Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'net-mlx5e-add-gbp-vxlan-hw-offload-support'

Gavin Li says:

====================
net/mlx5e: Add GBP VxLAN HW offload support

Patch-1: Remove unused argument from functions.
Patch-2: Expose helper function vxlan_build_gbp_hdr.
Patch-3: Add helper function for encap_info_equal for tunnels with options.
Patch-4: Preserving the const-ness of the pointer in ip_tunnel_info_opts.
Patch-5: Add HW offloading support for TC flows with VxLAN GBP encap/decap
in mlx ethernet driver.
====================

Link: https://lore.kernel.org/r/20230316070758.83512-1-gavinl@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+151 -56
+3
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h
··· 115 115 bool mlx5e_tc_tun_encap_info_equal_generic(struct mlx5e_encap_key *a, 116 116 struct mlx5e_encap_key *b); 117 117 118 + bool mlx5e_tc_tun_encap_info_equal_options(struct mlx5e_encap_key *a, 119 + struct mlx5e_encap_key *b, 120 + __be16 tun_flags); 118 121 #endif /* CONFIG_MLX5_ESWITCH */ 119 122 120 123 #endif //__MLX5_EN_TC_TUNNEL_H__
+32
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
··· 3 3 4 4 #include <net/fib_notifier.h> 5 5 #include <net/nexthop.h> 6 + #include <net/ip_tunnels.h> 6 7 #include "tc_tun_encap.h" 7 8 #include "en_tc.h" 8 9 #include "tc_tun.h" ··· 570 569 { 571 570 return memcmp(a->ip_tun_key, b->ip_tun_key, sizeof(*a->ip_tun_key)) == 0 && 572 571 a->tc_tunnel->tunnel_type == b->tc_tunnel->tunnel_type; 572 + } 573 + 574 + bool mlx5e_tc_tun_encap_info_equal_options(struct mlx5e_encap_key *a, 575 + struct mlx5e_encap_key *b, 576 + __be16 tun_flags) 577 + { 578 + struct ip_tunnel_info *a_info; 579 + struct ip_tunnel_info *b_info; 580 + bool a_has_opts, b_has_opts; 581 + 582 + if (!mlx5e_tc_tun_encap_info_equal_generic(a, b)) 583 + return false; 584 + 585 + a_has_opts = !!(a->ip_tun_key->tun_flags & tun_flags); 586 + b_has_opts = !!(b->ip_tun_key->tun_flags & tun_flags); 587 + 588 + /* keys are equal when both don't have any options attached */ 589 + if (!a_has_opts && !b_has_opts) 590 + return true; 591 + 592 + if (a_has_opts != b_has_opts) 593 + return false; 594 + 595 + /* options stored in memory next to ip_tunnel_info struct */ 596 + a_info = container_of(a->ip_tun_key, struct ip_tunnel_info, key); 597 + b_info = container_of(b->ip_tun_key, struct ip_tunnel_info, key); 598 + 599 + return a_info->options_len == b_info->options_len && 600 + !memcmp(ip_tunnel_info_opts(a_info), 601 + ip_tunnel_info_opts(b_info), 602 + a_info->options_len); 573 603 } 574 604 575 605 static int cmp_decap_info(struct mlx5e_decap_key *a,
+1 -23
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c
··· 337 337 static bool mlx5e_tc_tun_encap_info_equal_geneve(struct mlx5e_encap_key *a, 338 338 struct mlx5e_encap_key *b) 339 339 { 340 - struct ip_tunnel_info *a_info; 341 - struct ip_tunnel_info *b_info; 342 - bool a_has_opts, b_has_opts; 343 - 344 - if (!mlx5e_tc_tun_encap_info_equal_generic(a, b)) 345 - return false; 346 - 347 - a_has_opts = !!(a->ip_tun_key->tun_flags & TUNNEL_GENEVE_OPT); 348 - b_has_opts = !!(b->ip_tun_key->tun_flags & TUNNEL_GENEVE_OPT); 349 - 350 - /* keys are equal when both don't have any options attached */ 351 - if (!a_has_opts && !b_has_opts) 352 - return true; 353 - 354 - if (a_has_opts != b_has_opts) 355 - return false; 356 - 357 - /* geneve options stored in memory next to ip_tunnel_info struct */ 358 - a_info = container_of(a->ip_tun_key, struct ip_tunnel_info, key); 359 - b_info = container_of(b->ip_tun_key, struct ip_tunnel_info, key); 360 - 361 - return a_info->options_len == b_info->options_len && 362 - memcmp(a_info + 1, b_info + 1, a_info->options_len) == 0; 340 + return mlx5e_tc_tun_encap_info_equal_options(a, b, TUNNEL_GENEVE_OPT); 363 341 } 364 342 365 343 struct mlx5e_tc_tunnel geneve_tunnel = {
+70 -2
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 2 /* Copyright (c) 2018 Mellanox Technologies. */ 3 3 4 + #include <net/ip_tunnels.h> 4 5 #include <net/vxlan.h> 5 6 #include "lib/vxlan.h" 6 7 #include "en/tc_tun.h" ··· 87 86 const struct ip_tunnel_key *tun_key = &e->tun_info->key; 88 87 __be32 tun_id = tunnel_id_to_key32(tun_key->tun_id); 89 88 struct udphdr *udp = (struct udphdr *)(buf); 89 + const struct vxlan_metadata *md; 90 90 struct vxlanhdr *vxh; 91 91 92 - if (tun_key->tun_flags & TUNNEL_VXLAN_OPT) 92 + if ((tun_key->tun_flags & TUNNEL_VXLAN_OPT) && 93 + e->tun_info->options_len != sizeof(*md)) 93 94 return -EOPNOTSUPP; 94 95 vxh = (struct vxlanhdr *)((char *)udp + sizeof(struct udphdr)); 95 96 *ip_proto = IPPROTO_UDP; ··· 99 96 udp->dest = tun_key->tp_dst; 100 97 vxh->vx_flags = VXLAN_HF_VNI; 101 98 vxh->vx_vni = vxlan_vni_field(tun_id); 99 + if (tun_key->tun_flags & TUNNEL_VXLAN_OPT) { 100 + md = ip_tunnel_info_opts(e->tun_info); 101 + vxlan_build_gbp_hdr(vxh, md); 102 + } 103 + 104 + return 0; 105 + } 106 + 107 + static int mlx5e_tc_tun_parse_vxlan_gbp_option(struct mlx5e_priv *priv, 108 + struct mlx5_flow_spec *spec, 109 + struct flow_cls_offload *f) 110 + { 111 + struct flow_rule *rule = flow_cls_offload_flow_rule(f); 112 + struct netlink_ext_ack *extack = f->common.extack; 113 + struct flow_match_enc_opts enc_opts; 114 + void *misc5_c, *misc5_v; 115 + u32 *gbp, *gbp_mask; 116 + 117 + flow_rule_match_enc_opts(rule, &enc_opts); 118 + 119 + if (memchr_inv(&enc_opts.mask->data, 0, sizeof(enc_opts.mask->data)) && 120 + !MLX5_CAP_ESW_FT_FIELD_SUPPORT_2(priv->mdev, tunnel_header_0_1)) { 121 + NL_SET_ERR_MSG_MOD(extack, "Matching on VxLAN GBP is not supported"); 122 + return -EOPNOTSUPP; 123 + } 124 + 125 + if (enc_opts.key->dst_opt_type != TUNNEL_VXLAN_OPT) { 126 + NL_SET_ERR_MSG_MOD(extack, "Wrong VxLAN option type: not GBP"); 127 + return -EOPNOTSUPP; 128 + } 129 + 130 + if (enc_opts.key->len != sizeof(*gbp) || 131 + enc_opts.mask->len != sizeof(*gbp_mask)) { 132 + NL_SET_ERR_MSG_MOD(extack, "VxLAN GBP option/mask len is not 32 bits"); 133 + return -EINVAL; 134 + } 135 + 136 + gbp = (u32 *)&enc_opts.key->data[0]; 137 + gbp_mask = (u32 *)&enc_opts.mask->data[0]; 138 + 139 + if (*gbp_mask & ~VXLAN_GBP_MASK) { 140 + NL_SET_ERR_MSG_FMT_MOD(extack, "Wrong VxLAN GBP mask(0x%08X)\n", *gbp_mask); 141 + return -EINVAL; 142 + } 143 + 144 + misc5_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_5); 145 + misc5_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_5); 146 + MLX5_SET(fte_match_set_misc5, misc5_c, tunnel_header_0, *gbp_mask); 147 + MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_0, *gbp); 148 + 149 + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_5; 102 150 103 151 return 0; 104 152 } ··· 176 122 if (!enc_keyid.mask->keyid) 177 123 return 0; 178 124 125 + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_OPTS)) { 126 + int err; 127 + 128 + err = mlx5e_tc_tun_parse_vxlan_gbp_option(priv, spec, f); 129 + if (err) 130 + return err; 131 + } 132 + 179 133 /* match on VNI is required */ 180 134 181 135 if (!MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev, ··· 205 143 return 0; 206 144 } 207 145 146 + static bool mlx5e_tc_tun_encap_info_equal_vxlan(struct mlx5e_encap_key *a, 147 + struct mlx5e_encap_key *b) 148 + { 149 + return mlx5e_tc_tun_encap_info_equal_options(a, b, TUNNEL_VXLAN_OPT); 150 + } 151 + 208 152 static int mlx5e_tc_tun_get_remote_ifindex(struct net_device *mirred_dev) 209 153 { 210 154 const struct vxlan_dev *vxlan = netdev_priv(mirred_dev); ··· 228 160 .generate_ip_tun_hdr = mlx5e_gen_ip_tunnel_header_vxlan, 229 161 .parse_udp_ports = mlx5e_tc_tun_parse_udp_ports_vxlan, 230 162 .parse_tunnel = mlx5e_tc_tun_parse_vxlan, 231 - .encap_info_equal = mlx5e_tc_tun_encap_info_equal_generic, 163 + .encap_info_equal = mlx5e_tc_tun_encap_info_equal_vxlan, 232 164 .get_remote_ifindex = mlx5e_tc_tun_get_remote_ifindex, 233 165 };
+3 -24
drivers/net/vxlan/vxlan_core.c
··· 2093 2093 return false; 2094 2094 } 2095 2095 2096 - static void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, u32 vxflags, 2097 - struct vxlan_metadata *md) 2098 - { 2099 - struct vxlanhdr_gbp *gbp; 2100 - 2101 - if (!md->gbp) 2102 - return; 2103 - 2104 - gbp = (struct vxlanhdr_gbp *)vxh; 2105 - vxh->vx_flags |= VXLAN_HF_GBP; 2106 - 2107 - if (md->gbp & VXLAN_GBP_DONT_LEARN) 2108 - gbp->dont_learn = 1; 2109 - 2110 - if (md->gbp & VXLAN_GBP_POLICY_APPLIED) 2111 - gbp->policy_applied = 1; 2112 - 2113 - gbp->policy_id = htons(md->gbp & VXLAN_GBP_ID_MASK); 2114 - } 2115 - 2116 - static int vxlan_build_gpe_hdr(struct vxlanhdr *vxh, u32 vxflags, 2117 - __be16 protocol) 2096 + static int vxlan_build_gpe_hdr(struct vxlanhdr *vxh, __be16 protocol) 2118 2097 { 2119 2098 struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)vxh; 2120 2099 ··· 2156 2177 } 2157 2178 2158 2179 if (vxflags & VXLAN_F_GBP) 2159 - vxlan_build_gbp_hdr(vxh, vxflags, md); 2180 + vxlan_build_gbp_hdr(vxh, md); 2160 2181 if (vxflags & VXLAN_F_GPE) { 2161 - err = vxlan_build_gpe_hdr(vxh, vxflags, skb->protocol); 2182 + err = vxlan_build_gpe_hdr(vxh, skb->protocol); 2162 2183 if (err < 0) 2163 2184 return err; 2164 2185 inner_protocol = skb->protocol;
+6
include/linux/mlx5/device.h
··· 1357 1357 #define MLX5_CAP_ESW_INGRESS_ACL_MAX(mdev, cap) \ 1358 1358 MLX5_CAP_ESW_FLOWTABLE_MAX(mdev, flow_table_properties_esw_acl_ingress.cap) 1359 1359 1360 + #define MLX5_CAP_ESW_FT_FIELD_SUPPORT_2(mdev, cap) \ 1361 + MLX5_CAP_ESW_FLOWTABLE(mdev, ft_field_support_2_esw_fdb.cap) 1362 + 1363 + #define MLX5_CAP_ESW_FT_FIELD_SUPPORT_2_MAX(mdev, cap) \ 1364 + MLX5_CAP_ESW_FLOWTABLE_MAX(mdev, ft_field_support_2_esw_fdb.cap) 1365 + 1360 1366 #define MLX5_CAP_ESW(mdev, cap) \ 1361 1367 MLX5_GET(e_switch_cap, \ 1362 1368 mdev->caps.hca[MLX5_CAP_ESWITCH]->cur, cap)
+11 -2
include/linux/mlx5/mlx5_ifc.h
··· 404 404 u8 metadata_reg_c_0[0x1]; 405 405 }; 406 406 407 + /* Table 2170 - Flow Table Fields Supported 2 Format */ 407 408 struct mlx5_ifc_flow_table_fields_supported_2_bits { 408 409 u8 reserved_at_0[0xe]; 409 410 u8 bth_opcode[0x1]; 410 - u8 reserved_at_f[0x11]; 411 + u8 reserved_at_f[0x1]; 412 + u8 tunnel_header_0_1[0x1]; 413 + u8 reserved_at_11[0xf]; 411 414 412 415 u8 reserved_at_20[0x60]; 413 416 }; ··· 898 895 899 896 struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_esw_acl_egress; 900 897 901 - u8 reserved_at_800[0x1000]; 898 + u8 reserved_at_800[0xC00]; 899 + 900 + struct mlx5_ifc_flow_table_fields_supported_2_bits ft_field_support_2_esw_fdb; 901 + 902 + struct mlx5_ifc_flow_table_fields_supported_2_bits ft_field_bitmask_support_2_esw_fdb; 903 + 904 + u8 reserved_at_1500[0x300]; 902 905 903 906 u8 sw_steering_fdb_action_drop_icm_address_rx[0x40]; 904 907
+6 -5
include/net/ip_tunnels.h
··· 67 67 GENMASK((sizeof_field(struct ip_tunnel_info, \ 68 68 options_len) * BITS_PER_BYTE) - 1, 0) 69 69 70 + #define ip_tunnel_info_opts(info) \ 71 + _Generic(info, \ 72 + const struct ip_tunnel_info * : ((const void *)((info) + 1)),\ 73 + struct ip_tunnel_info * : ((void *)((info) + 1))\ 74 + ) 75 + 70 76 struct ip_tunnel_info { 71 77 struct ip_tunnel_key key; 72 78 #ifdef CONFIG_DST_CACHE ··· 489 483 err_stats->tx_dropped++; 490 484 } 491 485 } 492 - } 493 - 494 - static inline void *ip_tunnel_info_opts(struct ip_tunnel_info *info) 495 - { 496 - return info + 1; 497 486 } 498 487 499 488 static inline void ip_tunnel_info_opts_get(void *to,
+19
include/net/vxlan.h
··· 572 572 return true; 573 573 } 574 574 575 + static inline void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, const struct vxlan_metadata *md) 576 + { 577 + struct vxlanhdr_gbp *gbp; 578 + 579 + if (!md->gbp) 580 + return; 581 + 582 + gbp = (struct vxlanhdr_gbp *)vxh; 583 + vxh->vx_flags |= VXLAN_HF_GBP; 584 + 585 + if (md->gbp & VXLAN_GBP_DONT_LEARN) 586 + gbp->dont_learn = 1; 587 + 588 + if (md->gbp & VXLAN_GBP_POLICY_APPLIED) 589 + gbp->policy_applied = 1; 590 + 591 + gbp->policy_id = htons(md->gbp & VXLAN_GBP_ID_MASK); 592 + } 593 + 575 594 #endif