2
2
/* Copyright (c) 2018 Mellanox Technologies. */
3
3
4
4
#include <net/vxlan.h>
5
+ #include <net/gre.h>
5
6
#include "lib/vxlan.h"
6
7
#include "en/tc_tun.h"
7
8
@@ -109,6 +110,30 @@ static int mlx5e_gen_vxlan_header(char buf[], struct ip_tunnel_key *tun_key)
109
110
return 0 ;
110
111
}
111
112
113
+ static int mlx5e_gen_gre_header (char buf [], struct ip_tunnel_key * tun_key )
114
+ {
115
+ __be32 tun_id = tunnel_id_to_key32 (tun_key -> tun_id );
116
+ int hdr_len ;
117
+ struct gre_base_hdr * greh = (struct gre_base_hdr * )(buf );
118
+
119
+ /* the HW does not calculate GRE csum or sequences */
120
+ if (tun_key -> tun_flags & (TUNNEL_CSUM | TUNNEL_SEQ ))
121
+ return - EOPNOTSUPP ;
122
+
123
+ greh -> protocol = htons (ETH_P_TEB );
124
+
125
+ /* GRE key */
126
+ hdr_len = gre_calc_hlen (tun_key -> tun_flags );
127
+ greh -> flags = gre_tnl_flags_to_gre_flags (tun_key -> tun_flags );
128
+ if (tun_key -> tun_flags & TUNNEL_KEY ) {
129
+ __be32 * ptr = (__be32 * )(((u8 * )greh ) + hdr_len - 4 );
130
+
131
+ * ptr = tun_id ;
132
+ }
133
+
134
+ return 0 ;
135
+ }
136
+
112
137
static int mlx5e_gen_ip_tunnel_header (char buf [], __u8 * ip_proto ,
113
138
struct mlx5e_encap_entry * e )
114
139
{
@@ -118,6 +143,9 @@ static int mlx5e_gen_ip_tunnel_header(char buf[], __u8 *ip_proto,
118
143
if (e -> tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN ) {
119
144
* ip_proto = IPPROTO_UDP ;
120
145
err = mlx5e_gen_vxlan_header (buf , key );
146
+ } else if (e -> tunnel_type == MLX5E_TC_TUNNEL_TYPE_GRETAP ) {
147
+ * ip_proto = IPPROTO_GRE ;
148
+ err = mlx5e_gen_gre_header (buf , key );
121
149
} else {
122
150
pr_warn ("mlx5: Cannot generate tunnel header for tunnel type (%d)\n"
123
151
, e -> tunnel_type );
@@ -358,6 +386,9 @@ int mlx5e_tc_tun_get_type(struct net_device *tunnel_dev)
358
386
{
359
387
if (netif_is_vxlan (tunnel_dev ))
360
388
return MLX5E_TC_TUNNEL_TYPE_VXLAN ;
389
+ else if (netif_is_gretap (tunnel_dev ) ||
390
+ netif_is_ip6gretap (tunnel_dev ))
391
+ return MLX5E_TC_TUNNEL_TYPE_GRETAP ;
361
392
else
362
393
return MLX5E_TC_TUNNEL_TYPE_UNKNOWN ;
363
394
}
@@ -370,6 +401,9 @@ bool mlx5e_tc_tun_device_to_offload(struct mlx5e_priv *priv,
370
401
if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN &&
371
402
MLX5_CAP_ESW (priv -> mdev , vxlan_encap_decap ))
372
403
return true;
404
+ else if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_GRETAP &&
405
+ MLX5_CAP_ESW (priv -> mdev , nvgre_encap_decap ))
406
+ return true;
373
407
else
374
408
return false;
375
409
}
@@ -394,6 +428,9 @@ int mlx5e_tc_tun_init_encap_attr(struct net_device *tunnel_dev,
394
428
}
395
429
e -> reformat_type = MLX5_REFORMAT_TYPE_L2_TO_VXLAN ;
396
430
e -> tunnel_hlen = VXLAN_HLEN ;
431
+ } else if (e -> tunnel_type == MLX5E_TC_TUNNEL_TYPE_GRETAP ) {
432
+ e -> reformat_type = MLX5_REFORMAT_TYPE_L2_TO_NVGRE ;
433
+ e -> tunnel_hlen = gre_calc_hlen (e -> tun_info .key .tun_flags );
397
434
} else {
398
435
e -> reformat_type = -1 ;
399
436
e -> tunnel_hlen = -1 ;
@@ -472,6 +509,53 @@ static int mlx5e_tc_tun_parse_vxlan(struct mlx5e_priv *priv,
472
509
return 0 ;
473
510
}
474
511
512
+ static int mlx5e_tc_tun_parse_gretap (struct mlx5e_priv * priv ,
513
+ struct mlx5_flow_spec * spec ,
514
+ struct tc_cls_flower_offload * f ,
515
+ void * outer_headers_c ,
516
+ void * outer_headers_v )
517
+ {
518
+ void * misc_c = MLX5_ADDR_OF (fte_match_param , spec -> match_criteria ,
519
+ misc_parameters );
520
+ void * misc_v = MLX5_ADDR_OF (fte_match_param , spec -> match_value ,
521
+ misc_parameters );
522
+
523
+ if (!MLX5_CAP_ESW (priv -> mdev , nvgre_encap_decap )) {
524
+ NL_SET_ERR_MSG_MOD (f -> common .extack ,
525
+ "GRE HW offloading is not supported" );
526
+ netdev_warn (priv -> netdev , "GRE HW offloading is not supported\n" );
527
+ return - EOPNOTSUPP ;
528
+ }
529
+
530
+ MLX5_SET_TO_ONES (fte_match_set_lyr_2_4 , outer_headers_c , ip_protocol );
531
+ MLX5_SET (fte_match_set_lyr_2_4 , outer_headers_v ,
532
+ ip_protocol , IPPROTO_GRE );
533
+
534
+ /* gre protocol*/
535
+ MLX5_SET_TO_ONES (fte_match_set_misc , misc_c , gre_protocol );
536
+ MLX5_SET (fte_match_set_misc , misc_v , gre_protocol , ETH_P_TEB );
537
+
538
+ /* gre key */
539
+ if (dissector_uses_key (f -> dissector , FLOW_DISSECTOR_KEY_ENC_KEYID )) {
540
+ struct flow_dissector_key_keyid * mask = NULL ;
541
+ struct flow_dissector_key_keyid * key = NULL ;
542
+
543
+ mask = skb_flow_dissector_target (f -> dissector ,
544
+ FLOW_DISSECTOR_KEY_ENC_KEYID ,
545
+ f -> mask );
546
+ MLX5_SET (fte_match_set_misc , misc_c ,
547
+ gre_key .key , be32_to_cpu (mask -> keyid ));
548
+
549
+ key = skb_flow_dissector_target (f -> dissector ,
550
+ FLOW_DISSECTOR_KEY_ENC_KEYID ,
551
+ f -> key );
552
+ MLX5_SET (fte_match_set_misc , misc_v ,
553
+ gre_key .key , be32_to_cpu (key -> keyid ));
554
+ }
555
+
556
+ return 0 ;
557
+ }
558
+
475
559
int mlx5e_tc_tun_parse (struct net_device * filter_dev ,
476
560
struct mlx5e_priv * priv ,
477
561
struct mlx5_flow_spec * spec ,
@@ -486,6 +570,9 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
486
570
if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN ) {
487
571
err = mlx5e_tc_tun_parse_vxlan (priv , spec , f ,
488
572
headers_c , headers_v );
573
+ } else if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_GRETAP ) {
574
+ err = mlx5e_tc_tun_parse_gretap (priv , spec , f ,
575
+ headers_c , headers_v );
489
576
} else {
490
577
netdev_warn (priv -> netdev ,
491
578
"decapsulation offload is not supported for %s net device (%d)\n" ,
0 commit comments