22/* Copyright (c) 2018 Mellanox Technologies. */
33
44#include <net/vxlan.h>
5+ #include <net/gre.h>
56#include "lib/vxlan.h"
67#include "en/tc_tun.h"
78
@@ -109,6 +110,30 @@ static int mlx5e_gen_vxlan_header(char buf[], struct ip_tunnel_key *tun_key)
109110 return 0 ;
110111}
111112
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+
112137static int mlx5e_gen_ip_tunnel_header (char buf [], __u8 * ip_proto ,
113138 struct mlx5e_encap_entry * e )
114139{
@@ -118,6 +143,9 @@ static int mlx5e_gen_ip_tunnel_header(char buf[], __u8 *ip_proto,
118143 if (e -> tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN ) {
119144 * ip_proto = IPPROTO_UDP ;
120145 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 );
121149 } else {
122150 pr_warn ("mlx5: Cannot generate tunnel header for tunnel type (%d)\n"
123151 , e -> tunnel_type );
@@ -358,6 +386,9 @@ int mlx5e_tc_tun_get_type(struct net_device *tunnel_dev)
358386{
359387 if (netif_is_vxlan (tunnel_dev ))
360388 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 ;
361392 else
362393 return MLX5E_TC_TUNNEL_TYPE_UNKNOWN ;
363394}
@@ -370,6 +401,9 @@ bool mlx5e_tc_tun_device_to_offload(struct mlx5e_priv *priv,
370401 if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN &&
371402 MLX5_CAP_ESW (priv -> mdev , vxlan_encap_decap ))
372403 return true;
404+ else if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_GRETAP &&
405+ MLX5_CAP_ESW (priv -> mdev , nvgre_encap_decap ))
406+ return true;
373407 else
374408 return false;
375409}
@@ -394,6 +428,9 @@ int mlx5e_tc_tun_init_encap_attr(struct net_device *tunnel_dev,
394428 }
395429 e -> reformat_type = MLX5_REFORMAT_TYPE_L2_TO_VXLAN ;
396430 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 );
397434 } else {
398435 e -> reformat_type = -1 ;
399436 e -> tunnel_hlen = -1 ;
@@ -472,6 +509,53 @@ static int mlx5e_tc_tun_parse_vxlan(struct mlx5e_priv *priv,
472509 return 0 ;
473510}
474511
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+
475559int mlx5e_tc_tun_parse (struct net_device * filter_dev ,
476560 struct mlx5e_priv * priv ,
477561 struct mlx5_flow_spec * spec ,
@@ -486,6 +570,9 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
486570 if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN ) {
487571 err = mlx5e_tc_tun_parse_vxlan (priv , spec , f ,
488572 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 );
489576 } else {
490577 netdev_warn (priv -> netdev ,
491578 "decapsulation offload is not supported for %s net device (%d)\n" ,
0 commit comments