1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* Copyright (c) 2018 Mellanox Technologies. */ 3 4 #include <net/gre.h> 5 #include "en/tc_tun.h" 6 7 static bool mlx5e_tc_tun_can_offload_gretap(struct mlx5e_priv *priv) 8 { 9 return !!MLX5_CAP_ESW(priv->mdev, nvgre_encap_decap); 10 } 11 12 static int mlx5e_tc_tun_calc_hlen_gretap(struct mlx5e_encap_entry *e) 13 { 14 return gre_calc_hlen(e->tun_info->key.tun_flags); 15 } 16 17 static int mlx5e_tc_tun_init_encap_attr_gretap(struct net_device *tunnel_dev, 18 struct mlx5e_priv *priv, 19 struct mlx5e_encap_entry *e, 20 struct netlink_ext_ack *extack) 21 { 22 e->tunnel = &gre_tunnel; 23 e->reformat_type = MLX5_REFORMAT_TYPE_L2_TO_NVGRE; 24 return 0; 25 } 26 27 static int mlx5e_gen_ip_tunnel_header_gretap(char buf[], 28 __u8 *ip_proto, 29 struct mlx5e_encap_entry *e) 30 { 31 const struct ip_tunnel_key *tun_key = &e->tun_info->key; 32 struct gre_base_hdr *greh = (struct gre_base_hdr *)(buf); 33 __be32 tun_id = tunnel_id_to_key32(tun_key->tun_id); 34 int hdr_len; 35 36 *ip_proto = IPPROTO_GRE; 37 38 /* the HW does not calculate GRE csum or sequences */ 39 if (tun_key->tun_flags & (TUNNEL_CSUM | TUNNEL_SEQ)) 40 return -EOPNOTSUPP; 41 42 greh->protocol = htons(ETH_P_TEB); 43 44 /* GRE key */ 45 hdr_len = mlx5e_tc_tun_calc_hlen_gretap(e); 46 greh->flags = gre_tnl_flags_to_gre_flags(tun_key->tun_flags); 47 if (tun_key->tun_flags & TUNNEL_KEY) { 48 __be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4); 49 *ptr = tun_id; 50 } 51 52 return 0; 53 } 54 55 static int mlx5e_tc_tun_parse_gretap(struct mlx5e_priv *priv, 56 struct mlx5_flow_spec *spec, 57 struct flow_cls_offload *f, 58 void *headers_c, 59 void *headers_v) 60 { 61 void *misc_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters); 62 void *misc_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); 63 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 64 65 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ip_protocol); 66 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_GRE); 67 68 /* gre protocol */ 69 MLX5_SET_TO_ONES(fte_match_set_misc, misc_c, gre_protocol); 70 MLX5_SET(fte_match_set_misc, misc_v, gre_protocol, ETH_P_TEB); 71 72 /* gre key */ 73 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) { 74 struct flow_match_enc_keyid enc_keyid; 75 76 flow_rule_match_enc_keyid(rule, &enc_keyid); 77 MLX5_SET(fte_match_set_misc, misc_c, 78 gre_key.key, be32_to_cpu(enc_keyid.mask->keyid)); 79 MLX5_SET(fte_match_set_misc, misc_v, 80 gre_key.key, be32_to_cpu(enc_keyid.key->keyid)); 81 } 82 83 spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS; 84 85 return 0; 86 } 87 88 struct mlx5e_tc_tunnel gre_tunnel = { 89 .tunnel_type = MLX5E_TC_TUNNEL_TYPE_GRETAP, 90 .match_level = MLX5_MATCH_L3, 91 .can_offload = mlx5e_tc_tun_can_offload_gretap, 92 .calc_hlen = mlx5e_tc_tun_calc_hlen_gretap, 93 .init_encap_attr = mlx5e_tc_tun_init_encap_attr_gretap, 94 .generate_ip_tun_hdr = mlx5e_gen_ip_tunnel_header_gretap, 95 .parse_udp_ports = NULL, 96 .parse_tunnel = mlx5e_tc_tun_parse_gretap, 97 .encap_info_equal = mlx5e_tc_tun_encap_info_equal_generic, 98 }; 99