net/mlx5: DR, add support for ConnectX-8 steering
authorItamar Gozlan <igozlan@nvidia.com>
Thu, 19 Dec 2024 17:58:39 +0000 (19:58 +0200)
committerJakub Kicinski <kuba@kernel.org>
Mon, 23 Dec 2024 18:34:46 +0000 (10:34 -0800)
Add support for a new steering format version that is implemented by
ConnectX-8.
Except for several differences, the STEv3 is identical to STEv2, so
for most callbacks STEv3 context struct will call STEv2 functions.

Signed-off-by: Itamar Gozlan <igozlan@nvidia.com>
Signed-off-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20241219175841.1094544-10-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/mellanox/mlx5/core/Makefile
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_domain.c
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.c
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.h
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v3.c [new file with mode: 0644]
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5_ifc_dr.h
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5dr.h

index 79fe09de0a9fd1928fa274004554b7885c7700a2..10a763e668ed67139ce98a2a69a498943a3b6286 100644 (file)
@@ -123,6 +123,7 @@ mlx5_core-$(CONFIG_MLX5_SW_STEERING) += steering/sws/dr_domain.o \
                                        steering/sws/dr_ste_v0.o \
                                        steering/sws/dr_ste_v1.o \
                                        steering/sws/dr_ste_v2.o \
+                                       steering/sws/dr_ste_v3.o \
                                        steering/sws/dr_cmd.o \
                                        steering/sws/dr_fw.o \
                                        steering/sws/dr_action.o \
index 49f22cad92bfd0fcd05f2d55654ad5cd64bafbc8..60cb4527588a5340a5b4dbbd88fd7de69653802e 100644 (file)
@@ -8,7 +8,7 @@
 #define DR_DOMAIN_SW_STEERING_SUPPORTED(dmn, dmn_type) \
        ((dmn)->info.caps.dmn_type##_sw_owner ||        \
         ((dmn)->info.caps.dmn_type##_sw_owner_v2 &&    \
-         (dmn)->info.caps.sw_format_ver <= MLX5_STEERING_FORMAT_CONNECTX_7))
+         (dmn)->info.caps.sw_format_ver <= MLX5_STEERING_FORMAT_CONNECTX_8))
 
 bool mlx5dr_domain_is_support_ptrn_arg(struct mlx5dr_domain *dmn)
 {
index 01ba8eae2983d5d6693cf85244bdb74e055b0c4b..c8b8ff80c7c70fc9ab8c86a1d8c768b54b1e2e73 100644 (file)
@@ -1458,6 +1458,8 @@ struct mlx5dr_ste_ctx *mlx5dr_ste_get_ctx(u8 version)
                return mlx5dr_ste_get_ctx_v1();
        else if (version == MLX5_STEERING_FORMAT_CONNECTX_7)
                return mlx5dr_ste_get_ctx_v2();
+       else if (version == MLX5_STEERING_FORMAT_CONNECTX_8)
+               return mlx5dr_ste_get_ctx_v3();
 
        return NULL;
 }
index b6ec8d30d9903ad9ea57005db39650311555583c..5f409dc30aca82be26fdd20603fc86077ed6158b 100644 (file)
@@ -217,5 +217,6 @@ struct mlx5dr_ste_ctx {
 struct mlx5dr_ste_ctx *mlx5dr_ste_get_ctx_v0(void);
 struct mlx5dr_ste_ctx *mlx5dr_ste_get_ctx_v1(void);
 struct mlx5dr_ste_ctx *mlx5dr_ste_get_ctx_v2(void);
+struct mlx5dr_ste_ctx *mlx5dr_ste_get_ctx_v3(void);
 
 #endif  /* _DR_STE_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v3.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v3.c
new file mode 100644 (file)
index 0000000..cc60ce1
--- /dev/null
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/* Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#include "dr_ste_v1.h"
+#include "dr_ste_v2.h"
+
+static void dr_ste_v3_set_encap(u8 *hw_ste_p, u8 *d_action,
+                               u32 reformat_id, int size)
+{
+       MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action, action_id,
+                DR_STE_V1_ACTION_ID_INSERT_POINTER);
+       /* The hardware expects here size in words (2 byte) */
+       MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action, size, size / 2);
+       MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action, pointer, reformat_id);
+       MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action, attributes,
+                DR_STE_V1_ACTION_INSERT_PTR_ATTR_ENCAP);
+       dr_ste_v1_set_reparse(hw_ste_p);
+}
+
+static void dr_ste_v3_set_push_vlan(u8 *ste, u8 *d_action,
+                                   u32 vlan_hdr)
+{
+       MLX5_SET(ste_double_action_insert_with_inline_v3, d_action, action_id,
+                DR_STE_V1_ACTION_ID_INSERT_INLINE);
+       /* The hardware expects here offset to vlan header in words (2 byte) */
+       MLX5_SET(ste_double_action_insert_with_inline_v3, d_action, start_offset,
+                HDR_LEN_L2_MACS >> 1);
+       MLX5_SET(ste_double_action_insert_with_inline_v3, d_action, inline_data, vlan_hdr);
+       dr_ste_v1_set_reparse(ste);
+}
+
+static void dr_ste_v3_set_pop_vlan(u8 *hw_ste_p, u8 *s_action,
+                                  u8 vlans_num)
+{
+       MLX5_SET(ste_single_action_remove_header_size_v3, s_action,
+                action_id, DR_STE_V1_ACTION_ID_REMOVE_BY_SIZE);
+       MLX5_SET(ste_single_action_remove_header_size_v3, s_action,
+                start_anchor, DR_STE_HEADER_ANCHOR_1ST_VLAN);
+       /* The hardware expects here size in words (2 byte) */
+       MLX5_SET(ste_single_action_remove_header_size_v3, s_action,
+                remove_size, (HDR_LEN_L2_VLAN >> 1) * vlans_num);
+
+       dr_ste_v1_set_reparse(hw_ste_p);
+}
+
+static void dr_ste_v3_set_encap_l3(u8 *hw_ste_p,
+                                  u8 *frst_s_action,
+                                  u8 *scnd_d_action,
+                                  u32 reformat_id,
+                                  int size)
+{
+       /* Remove L2 headers */
+       MLX5_SET(ste_single_action_remove_header_v3, frst_s_action, action_id,
+                DR_STE_V1_ACTION_ID_REMOVE_HEADER_TO_HEADER);
+       MLX5_SET(ste_single_action_remove_header_v3, frst_s_action, end_anchor,
+                DR_STE_HEADER_ANCHOR_IPV6_IPV4);
+
+       /* Encapsulate with given reformat ID */
+       MLX5_SET(ste_double_action_insert_with_ptr_v3, scnd_d_action, action_id,
+                DR_STE_V1_ACTION_ID_INSERT_POINTER);
+       /* The hardware expects here size in words (2 byte) */
+       MLX5_SET(ste_double_action_insert_with_ptr_v3, scnd_d_action, size, size / 2);
+       MLX5_SET(ste_double_action_insert_with_ptr_v3, scnd_d_action, pointer, reformat_id);
+       MLX5_SET(ste_double_action_insert_with_ptr_v3, scnd_d_action, attributes,
+                DR_STE_V1_ACTION_INSERT_PTR_ATTR_ENCAP);
+
+       dr_ste_v1_set_reparse(hw_ste_p);
+}
+
+static void dr_ste_v3_set_rx_decap(u8 *hw_ste_p, u8 *s_action)
+{
+       MLX5_SET(ste_single_action_remove_header_v3, s_action, action_id,
+                DR_STE_V1_ACTION_ID_REMOVE_HEADER_TO_HEADER);
+       MLX5_SET(ste_single_action_remove_header_v3, s_action, decap, 1);
+       MLX5_SET(ste_single_action_remove_header_v3, s_action, vni_to_cqe, 1);
+       MLX5_SET(ste_single_action_remove_header_v3, s_action, end_anchor,
+                DR_STE_HEADER_ANCHOR_INNER_MAC);
+
+       dr_ste_v1_set_reparse(hw_ste_p);
+}
+
+static int
+dr_ste_v3_set_action_decap_l3_list(void *data, u32 data_sz,
+                                  u8 *hw_action, u32 hw_action_sz,
+                                  uint16_t *used_hw_action_num)
+{
+       u8 padded_data[DR_STE_L2_HDR_MAX_SZ] = {};
+       void *data_ptr = padded_data;
+       u16 used_actions = 0;
+       u32 inline_data_sz;
+       u32 i;
+
+       if (hw_action_sz / DR_STE_ACTION_DOUBLE_SZ < DR_STE_DECAP_L3_ACTION_NUM)
+               return -EINVAL;
+
+       inline_data_sz =
+               MLX5_FLD_SZ_BYTES(ste_double_action_insert_with_inline_v3, inline_data);
+
+       /* Add an alignment padding  */
+       memcpy(padded_data + data_sz % inline_data_sz, data, data_sz);
+
+       /* Remove L2L3 outer headers */
+       MLX5_SET(ste_single_action_remove_header_v3, hw_action, action_id,
+                DR_STE_V1_ACTION_ID_REMOVE_HEADER_TO_HEADER);
+       MLX5_SET(ste_single_action_remove_header_v3, hw_action, decap, 1);
+       MLX5_SET(ste_single_action_remove_header_v3, hw_action, vni_to_cqe, 1);
+       MLX5_SET(ste_single_action_remove_header_v3, hw_action, end_anchor,
+                DR_STE_HEADER_ANCHOR_INNER_IPV6_IPV4);
+       hw_action += DR_STE_ACTION_DOUBLE_SZ;
+       used_actions++; /* Remove and NOP are a single double action */
+
+       /* Point to the last dword of the header */
+       data_ptr += (data_sz / inline_data_sz) * inline_data_sz;
+
+       /* Add the new header using inline action 4Byte at a time, the header
+        * is added in reversed order to the beginning of the packet to avoid
+        * incorrect parsing by the HW. Since header is 14B or 18B an extra
+        * two bytes are padded and later removed.
+        */
+       for (i = 0; i < data_sz / inline_data_sz + 1; i++) {
+               void *addr_inline;
+
+               MLX5_SET(ste_double_action_insert_with_inline_v3, hw_action, action_id,
+                        DR_STE_V1_ACTION_ID_INSERT_INLINE);
+               /* The hardware expects here offset to words (2 bytes) */
+               MLX5_SET(ste_double_action_insert_with_inline_v3, hw_action, start_offset, 0);
+
+               /* Copy bytes one by one to avoid endianness problem */
+               addr_inline = MLX5_ADDR_OF(ste_double_action_insert_with_inline_v3,
+                                          hw_action, inline_data);
+               memcpy(addr_inline, data_ptr - i * inline_data_sz, inline_data_sz);
+               hw_action += DR_STE_ACTION_DOUBLE_SZ;
+               used_actions++;
+       }
+
+       /* Remove first 2 extra bytes */
+       MLX5_SET(ste_single_action_remove_header_size_v3, hw_action, action_id,
+                DR_STE_V1_ACTION_ID_REMOVE_BY_SIZE);
+       MLX5_SET(ste_single_action_remove_header_size_v3, hw_action, start_offset, 0);
+       /* The hardware expects here size in words (2 bytes) */
+       MLX5_SET(ste_single_action_remove_header_size_v3, hw_action, remove_size, 1);
+       used_actions++;
+
+       *used_hw_action_num = used_actions;
+
+       return 0;
+}
+
+static struct mlx5dr_ste_ctx ste_ctx_v3 = {
+       /* Builders */
+       .build_eth_l2_src_dst_init      = &dr_ste_v1_build_eth_l2_src_dst_init,
+       .build_eth_l3_ipv6_src_init     = &dr_ste_v1_build_eth_l3_ipv6_src_init,
+       .build_eth_l3_ipv6_dst_init     = &dr_ste_v1_build_eth_l3_ipv6_dst_init,
+       .build_eth_l3_ipv4_5_tuple_init = &dr_ste_v1_build_eth_l3_ipv4_5_tuple_init,
+       .build_eth_l2_src_init          = &dr_ste_v1_build_eth_l2_src_init,
+       .build_eth_l2_dst_init          = &dr_ste_v1_build_eth_l2_dst_init,
+       .build_eth_l2_tnl_init          = &dr_ste_v1_build_eth_l2_tnl_init,
+       .build_eth_l3_ipv4_misc_init    = &dr_ste_v1_build_eth_l3_ipv4_misc_init,
+       .build_eth_ipv6_l3_l4_init      = &dr_ste_v1_build_eth_ipv6_l3_l4_init,
+       .build_mpls_init                = &dr_ste_v1_build_mpls_init,
+       .build_tnl_gre_init             = &dr_ste_v1_build_tnl_gre_init,
+       .build_tnl_mpls_init            = &dr_ste_v1_build_tnl_mpls_init,
+       .build_tnl_mpls_over_udp_init   = &dr_ste_v1_build_tnl_mpls_over_udp_init,
+       .build_tnl_mpls_over_gre_init   = &dr_ste_v1_build_tnl_mpls_over_gre_init,
+       .build_icmp_init                = &dr_ste_v1_build_icmp_init,
+       .build_general_purpose_init     = &dr_ste_v1_build_general_purpose_init,
+       .build_eth_l4_misc_init         = &dr_ste_v1_build_eth_l4_misc_init,
+       .build_tnl_vxlan_gpe_init       = &dr_ste_v1_build_flex_parser_tnl_vxlan_gpe_init,
+       .build_tnl_geneve_init          = &dr_ste_v1_build_flex_parser_tnl_geneve_init,
+       .build_tnl_geneve_tlv_opt_init  = &dr_ste_v1_build_flex_parser_tnl_geneve_tlv_opt_init,
+       .build_tnl_geneve_tlv_opt_exist_init =
+                                 &dr_ste_v1_build_flex_parser_tnl_geneve_tlv_opt_exist_init,
+       .build_register_0_init          = &dr_ste_v1_build_register_0_init,
+       .build_register_1_init          = &dr_ste_v1_build_register_1_init,
+       .build_src_gvmi_qpn_init        = &dr_ste_v1_build_src_gvmi_qpn_init,
+       .build_flex_parser_0_init       = &dr_ste_v1_build_flex_parser_0_init,
+       .build_flex_parser_1_init       = &dr_ste_v1_build_flex_parser_1_init,
+       .build_tnl_gtpu_init            = &dr_ste_v1_build_flex_parser_tnl_gtpu_init,
+       .build_tnl_header_0_1_init      = &dr_ste_v1_build_tnl_header_0_1_init,
+       .build_tnl_gtpu_flex_parser_0_init = &dr_ste_v1_build_tnl_gtpu_flex_parser_0_init,
+       .build_tnl_gtpu_flex_parser_1_init = &dr_ste_v1_build_tnl_gtpu_flex_parser_1_init,
+
+       /* Getters and Setters */
+       .ste_init                       = &dr_ste_v1_init,
+       .set_next_lu_type               = &dr_ste_v1_set_next_lu_type,
+       .get_next_lu_type               = &dr_ste_v1_get_next_lu_type,
+       .is_miss_addr_set               = &dr_ste_v1_is_miss_addr_set,
+       .set_miss_addr                  = &dr_ste_v1_set_miss_addr,
+       .get_miss_addr                  = &dr_ste_v1_get_miss_addr,
+       .set_hit_addr                   = &dr_ste_v1_set_hit_addr,
+       .set_byte_mask                  = &dr_ste_v1_set_byte_mask,
+       .get_byte_mask                  = &dr_ste_v1_get_byte_mask,
+
+       /* Actions */
+       .actions_caps                   = DR_STE_CTX_ACTION_CAP_TX_POP |
+                                         DR_STE_CTX_ACTION_CAP_RX_PUSH |
+                                         DR_STE_CTX_ACTION_CAP_RX_ENCAP,
+       .set_actions_rx                 = &dr_ste_v1_set_actions_rx,
+       .set_actions_tx                 = &dr_ste_v1_set_actions_tx,
+       .modify_field_arr_sz            = ARRAY_SIZE(dr_ste_v2_action_modify_field_arr),
+       .modify_field_arr               = dr_ste_v2_action_modify_field_arr,
+       .set_action_set                 = &dr_ste_v1_set_action_set,
+       .set_action_add                 = &dr_ste_v1_set_action_add,
+       .set_action_copy                = &dr_ste_v1_set_action_copy,
+       .set_action_decap_l3_list       = &dr_ste_v3_set_action_decap_l3_list,
+       .alloc_modify_hdr_chunk         = &dr_ste_v1_alloc_modify_hdr_ptrn_arg,
+       .dealloc_modify_hdr_chunk       = &dr_ste_v1_free_modify_hdr_ptrn_arg,
+       /* Actions bit set */
+       .set_encap                      = &dr_ste_v3_set_encap,
+       .set_push_vlan                  = &dr_ste_v3_set_push_vlan,
+       .set_pop_vlan                   = &dr_ste_v3_set_pop_vlan,
+       .set_rx_decap                   = &dr_ste_v3_set_rx_decap,
+       .set_encap_l3                   = &dr_ste_v3_set_encap_l3,
+       /* Send */
+       .prepare_for_postsend           = &dr_ste_v1_prepare_for_postsend,
+};
+
+struct mlx5dr_ste_ctx *mlx5dr_ste_get_ctx_v3(void)
+{
+       return &ste_ctx_v3;
+}
index fb078fa0f0cc8363eee7a113f2db2ef8ce7ce659..898c3618ff263993d82bc480a8b20d70ed6368cd 100644 (file)
@@ -600,4 +600,44 @@ struct mlx5_ifc_ste_double_action_aso_v1_bits {
        };
 };
 
+struct mlx5_ifc_ste_single_action_remove_header_v3_bits {
+       u8         action_id[0x8];
+       u8         start_anchor[0x7];
+       u8         end_anchor[0x7];
+       u8         reserved_at_16[0x1];
+       u8         outer_l4_remove[0x1];
+       u8         reserved_at_18[0x4];
+       u8         decap[0x1];
+       u8         vni_to_cqe[0x1];
+       u8         qos_profile[0x2];
+};
+
+struct mlx5_ifc_ste_single_action_remove_header_size_v3_bits {
+       u8         action_id[0x8];
+       u8         start_anchor[0x7];
+       u8         start_offset[0x8];
+       u8         outer_l4_remove[0x1];
+       u8         reserved_at_18[0x2];
+       u8         remove_size[0x6];
+};
+
+struct mlx5_ifc_ste_double_action_insert_with_inline_v3_bits {
+       u8         action_id[0x8];
+       u8         start_anchor[0x7];
+       u8         start_offset[0x8];
+       u8         reserved_at_17[0x9];
+
+       u8         inline_data[0x20];
+};
+
+struct mlx5_ifc_ste_double_action_insert_with_ptr_v3_bits {
+       u8         action_id[0x8];
+       u8         start_anchor[0x7];
+       u8         start_offset[0x8];
+       u8         size[0x6];
+       u8         attributes[0x3];
+
+       u8         pointer[0x20];
+};
+
 #endif /* MLX5_IFC_DR_H */
index 3ac7dc67509fca96cf9f5e56aeb73d80eb839923..0bb3724c10c26ca08534da12c72e5fba0f6acbfc 100644 (file)
@@ -160,7 +160,7 @@ mlx5dr_is_supported(struct mlx5_core_dev *dev)
               (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, sw_owner) ||
                (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, sw_owner_v2) &&
                 (MLX5_CAP_GEN(dev, steering_format_version) <=
-                 MLX5_STEERING_FORMAT_CONNECTX_7)));
+                 MLX5_STEERING_FORMAT_CONNECTX_8)));
 }
 
 /* buddy functions & structure */