git: 2b729c222d48 - stable/14 - mlx5: Add modify header support

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Wed, 22 Nov 2023 01:51:49 UTC
The branch stable/14 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=2b729c222d4821069c817c853f56826d065f7ac7

commit 2b729c222d4821069c817c853f56826d065f7ac7
Author:     Mark Bloch <mbloch@nvidia.com>
AuthorDate: 2023-02-19 08:41:24 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2023-11-22 01:40:27 +0000

    mlx5: Add modify header support
    
    (cherry picked from commit e4f84168b3c8bf99297dda712b147906d463b20e)
---
 sys/dev/mlx5/fs.h                     |   6 ++
 sys/dev/mlx5/mlx5_core/fs_core.h      |  15 ++++
 sys/dev/mlx5/mlx5_core/mlx5_fs_cmd.c  |  73 ++++++++++++++++
 sys/dev/mlx5/mlx5_core/mlx5_fs_tree.c |  32 +++++++
 sys/dev/mlx5/mlx5_ifc.h               | 160 +++++++++++++++++++++++++++++++++-
 5 files changed, 283 insertions(+), 3 deletions(-)

diff --git a/sys/dev/mlx5/fs.h b/sys/dev/mlx5/fs.h
index b630ab22d465..db5ba1964845 100644
--- a/sys/dev/mlx5/fs.h
+++ b/sys/dev/mlx5/fs.h
@@ -228,4 +228,10 @@ bool fs_match_exact_mask(
 		void *mask2);
 /**********end API for sniffer**********/
 
+struct mlx5_modify_hdr *mlx5_modify_header_alloc(struct mlx5_core_dev *dev,
+						 enum mlx5_flow_namespace_type ns_type,
+						 u8 num_actions,
+						 void *modify_actions);
+void mlx5_modify_header_dealloc(struct mlx5_core_dev *dev,
+				struct mlx5_modify_hdr *modify_hdr);
 #endif
diff --git a/sys/dev/mlx5/mlx5_core/fs_core.h b/sys/dev/mlx5/mlx5_core/fs_core.h
index c1033e24a20e..11b042863454 100644
--- a/sys/dev/mlx5/mlx5_core/fs_core.h
+++ b/sys/dev/mlx5/mlx5_core/fs_core.h
@@ -168,6 +168,11 @@ struct fs_client_priv_data {
 	void   *client_dst_data;
 };
 
+struct mlx5_modify_hdr {
+	enum mlx5_flow_namespace_type ns_type;
+	u32 id;
+};
+
 void _fs_remove_node(struct kref *kref);
 #define fs_get_obj(v, _base)  {v = container_of((_base), typeof(*v), base); }
 #define fs_get_parent(v, child)  {v = (child)->base.parent ?		     \
@@ -295,4 +300,14 @@ int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
 
 int mlx5_init_fs(struct mlx5_core_dev *dev);
 void mlx5_cleanup_fs(struct mlx5_core_dev *dev);
+void mlx5_fc_update_sampling_interval(struct mlx5_core_dev *dev,
+				      unsigned long interval);
+
+int mlx5_cmd_modify_header_alloc(struct mlx5_core_dev *dev,
+				 enum mlx5_flow_namespace_type namespace,
+				 u8 num_actions,
+				 void *modify_actions,
+				 struct mlx5_modify_hdr *modify_hdr);
+void mlx5_cmd_modify_header_dealloc(struct mlx5_core_dev *dev,
+				    struct mlx5_modify_hdr *modify_hdr);
 #endif
diff --git a/sys/dev/mlx5/mlx5_core/mlx5_fs_cmd.c b/sys/dev/mlx5/mlx5_core/mlx5_fs_cmd.c
index 75e48909aae6..214b4141a973 100644
--- a/sys/dev/mlx5/mlx5_core/mlx5_fs_cmd.c
+++ b/sys/dev/mlx5/mlx5_core/mlx5_fs_cmd.c
@@ -283,3 +283,76 @@ int mlx5_cmd_fs_delete_fte(struct mlx5_core_dev *dev,
 
 	return err;
 }
+
+int mlx5_cmd_modify_header_alloc(struct mlx5_core_dev *dev,
+				 enum mlx5_flow_namespace_type namespace,
+				 u8 num_actions,
+				 void *modify_actions,
+				 struct mlx5_modify_hdr *modify_hdr)
+{
+        u32 out[MLX5_ST_SZ_DW(alloc_modify_header_context_out)] = {};
+        int max_actions, actions_size, inlen, err;
+        void *actions_in;
+        u8 table_type;
+        u32 *in;
+
+        switch (namespace) {
+        case MLX5_FLOW_NAMESPACE_FDB:
+                max_actions = MLX5_CAP_ESW_FLOWTABLE_FDB(dev, max_modify_header_actions);
+                table_type = FS_FT_FDB;
+                break;
+        case MLX5_FLOW_NAMESPACE_KERNEL:
+        case MLX5_FLOW_NAMESPACE_BYPASS:
+                max_actions = MLX5_CAP_FLOWTABLE_NIC_RX(dev, max_modify_header_actions);
+                table_type = FS_FT_NIC_RX;
+                break;
+        case MLX5_FLOW_NAMESPACE_ESW_INGRESS:
+                max_actions = MLX5_CAP_ESW_INGRESS_ACL(dev, max_modify_header_actions);
+                table_type = FS_FT_ESW_INGRESS_ACL;
+                break;
+        default:
+                return -EOPNOTSUPP;
+        }
+
+        if (num_actions > max_actions) {
+                mlx5_core_warn(dev, "too many modify header actions %d, max supported %d\n",
+                               num_actions, max_actions);
+                return -EOPNOTSUPP;
+        }
+
+        actions_size = MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto) * num_actions;
+        inlen = MLX5_ST_SZ_BYTES(alloc_modify_header_context_in) + actions_size;
+
+        in = kzalloc(inlen, GFP_KERNEL);
+        if (!in)
+                return -ENOMEM;
+
+        MLX5_SET(alloc_modify_header_context_in, in, opcode,
+                 MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT);
+        MLX5_SET(alloc_modify_header_context_in, in, table_type, table_type);
+        MLX5_SET(alloc_modify_header_context_in, in, num_of_actions, num_actions);
+
+        actions_in = MLX5_ADDR_OF(alloc_modify_header_context_in, in, actions);
+        memcpy(actions_in, modify_actions, actions_size);
+
+        err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
+
+        modify_hdr->id = MLX5_GET(alloc_modify_header_context_out, out, modify_header_id);
+        kfree(in);
+
+        return err;
+}
+
+void mlx5_cmd_modify_header_dealloc(struct mlx5_core_dev *dev,
+				    struct mlx5_modify_hdr *modify_hdr)
+{
+	u32 out[MLX5_ST_SZ_DW(dealloc_modify_header_context_out)] = {};
+        u32 in[MLX5_ST_SZ_DW(dealloc_modify_header_context_in)] = {};
+
+        MLX5_SET(dealloc_modify_header_context_in, in, opcode,
+                 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
+        MLX5_SET(dealloc_modify_header_context_in, in, modify_header_id,
+                 modify_hdr->id);
+
+        mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
diff --git a/sys/dev/mlx5/mlx5_core/mlx5_fs_tree.c b/sys/dev/mlx5/mlx5_core/mlx5_fs_tree.c
index 734992be9de1..9e9febfe902e 100644
--- a/sys/dev/mlx5/mlx5_core/mlx5_fs_tree.c
+++ b/sys/dev/mlx5/mlx5_core/mlx5_fs_tree.c
@@ -2739,3 +2739,35 @@ free_list:
 	mlx5_del_flow_rules_list(rules_list);
 	return NULL;
 }
+
+struct mlx5_modify_hdr *mlx5_modify_header_alloc(struct mlx5_core_dev *dev,
+						 enum mlx5_flow_namespace_type ns_type,
+						 u8 num_actions,
+						 void *modify_actions)
+{
+	struct mlx5_modify_hdr *modify_hdr;
+	int err;
+
+	modify_hdr = kzalloc(sizeof(*modify_hdr), GFP_KERNEL);
+	if (!modify_hdr)
+		return ERR_PTR(-ENOMEM);
+
+	modify_hdr->ns_type = ns_type;
+	err = mlx5_cmd_modify_header_alloc(dev, ns_type, num_actions,
+					   modify_actions, modify_hdr);
+	if (err) {
+		kfree(modify_hdr);
+		return ERR_PTR(err);
+	}
+
+	return modify_hdr;
+}
+EXPORT_SYMBOL(mlx5_modify_header_alloc);
+
+void mlx5_modify_header_dealloc(struct mlx5_core_dev *dev,
+                                struct mlx5_modify_hdr *modify_hdr)
+{
+        mlx5_cmd_modify_header_dealloc(dev, modify_hdr);
+        kfree(modify_hdr);
+}
+EXPORT_SYMBOL(mlx5_modify_header_dealloc);
diff --git a/sys/dev/mlx5/mlx5_ifc.h b/sys/dev/mlx5/mlx5_ifc.h
index 5293a83f56d9..fcea7342532b 100644
--- a/sys/dev/mlx5/mlx5_ifc.h
+++ b/sys/dev/mlx5/mlx5_ifc.h
@@ -473,7 +473,8 @@ struct mlx5_ifc_flow_table_prop_layout_bits {
 
 	u8         reserved_at_20[0x2];
 	u8         log_max_ft_size[0x6];
-	u8         reserved_at_28[0x10];
+	u8         log_max_modify_header_context[0x8];
+        u8         max_modify_header_actions[0x8];
 	u8         max_ft_level[0x8];
 
 	u8         reserved_at_40[0x20];
@@ -2251,11 +2252,15 @@ struct mlx5_ifc_flow_context_bits {
 	u8         reserved_4[0x8];
 	u8         flow_counter_list_size[0x18];
 
-	u8         reserved_5[0x140];
+	u8         reserved_5[0x20];
+
+	u8	   modify_header_id[0x20];
+
+	u8	   reserved_6[0x100];
 
 	struct mlx5_ifc_fte_match_param_bits match_value;
 
-	u8         reserved_6[0x600];
+	u8         reserved_7[0x600];
 
 	union mlx5_ifc_dest_format_struct_flow_counter_list_auto_bits destination[0];
 };
@@ -5199,6 +5204,155 @@ struct mlx5_ifc_query_eq_in_bits {
 	u8         reserved_3[0x20];
 };
 
+struct mlx5_ifc_set_action_in_bits {
+        u8         action_type[0x4];
+        u8         field[0xc];
+        u8         reserved_at_10[0x3];
+        u8         offset[0x5];
+        u8         reserved_at_18[0x3];
+        u8         length[0x5];
+
+        u8         data[0x20];
+};
+
+struct mlx5_ifc_add_action_in_bits {
+        u8         action_type[0x4];
+        u8         field[0xc];
+        u8         reserved_at_10[0x10];
+
+        u8         data[0x20];
+};
+
+struct mlx5_ifc_copy_action_in_bits {
+        u8         action_type[0x4];
+        u8         src_field[0xc];
+        u8         reserved_at_10[0x3];
+        u8         src_offset[0x5];
+        u8         reserved_at_18[0x3];
+        u8         length[0x5];
+
+        u8         reserved_at_20[0x4];
+        u8         dst_field[0xc];
+        u8         reserved_at_30[0x3];
+        u8         dst_offset[0x5];
+        u8         reserved_at_38[0x8];
+};
+
+union mlx5_ifc_set_add_copy_action_in_auto_bits {
+        struct mlx5_ifc_set_action_in_bits  set_action_in;
+        struct mlx5_ifc_add_action_in_bits  add_action_in;
+        struct mlx5_ifc_copy_action_in_bits copy_action_in;
+        u8         reserved_at_0[0x40];
+};
+
+enum {
+        MLX5_ACTION_TYPE_SET   = 0x1,
+        MLX5_ACTION_TYPE_ADD   = 0x2,
+        MLX5_ACTION_TYPE_COPY  = 0x3,
+};
+
+enum {
+        MLX5_ACTION_IN_FIELD_OUT_SMAC_47_16    = 0x1,
+        MLX5_ACTION_IN_FIELD_OUT_SMAC_15_0     = 0x2,
+        MLX5_ACTION_IN_FIELD_OUT_ETHERTYPE     = 0x3,
+        MLX5_ACTION_IN_FIELD_OUT_DMAC_47_16    = 0x4,
+        MLX5_ACTION_IN_FIELD_OUT_DMAC_15_0     = 0x5,
+        MLX5_ACTION_IN_FIELD_OUT_IP_DSCP       = 0x6,
+        MLX5_ACTION_IN_FIELD_OUT_TCP_FLAGS     = 0x7,
+        MLX5_ACTION_IN_FIELD_OUT_TCP_SPORT     = 0x8,
+        MLX5_ACTION_IN_FIELD_OUT_TCP_DPORT     = 0x9,
+        MLX5_ACTION_IN_FIELD_OUT_IP_TTL        = 0xa,
+        MLX5_ACTION_IN_FIELD_OUT_UDP_SPORT     = 0xb,
+        MLX5_ACTION_IN_FIELD_OUT_UDP_DPORT     = 0xc,
+        MLX5_ACTION_IN_FIELD_OUT_SIPV6_127_96  = 0xd,
+        MLX5_ACTION_IN_FIELD_OUT_SIPV6_95_64   = 0xe,
+        MLX5_ACTION_IN_FIELD_OUT_SIPV6_63_32   = 0xf,
+        MLX5_ACTION_IN_FIELD_OUT_SIPV6_31_0    = 0x10,
+        MLX5_ACTION_IN_FIELD_OUT_DIPV6_127_96  = 0x11,
+        MLX5_ACTION_IN_FIELD_OUT_DIPV6_95_64   = 0x12,
+        MLX5_ACTION_IN_FIELD_OUT_DIPV6_63_32   = 0x13,
+        MLX5_ACTION_IN_FIELD_OUT_DIPV6_31_0    = 0x14,
+        MLX5_ACTION_IN_FIELD_OUT_SIPV4         = 0x15,
+        MLX5_ACTION_IN_FIELD_OUT_DIPV4         = 0x16,
+        MLX5_ACTION_IN_FIELD_OUT_FIRST_VID     = 0x17,
+        MLX5_ACTION_IN_FIELD_OUT_IPV6_HOPLIMIT = 0x47,
+        MLX5_ACTION_IN_FIELD_METADATA_REG_A    = 0x49,
+        MLX5_ACTION_IN_FIELD_METADATA_REG_B    = 0x50,
+        MLX5_ACTION_IN_FIELD_METADATA_REG_C_0  = 0x51,
+        MLX5_ACTION_IN_FIELD_METADATA_REG_C_1  = 0x52,
+        MLX5_ACTION_IN_FIELD_METADATA_REG_C_2  = 0x53,
+        MLX5_ACTION_IN_FIELD_METADATA_REG_C_3  = 0x54,
+        MLX5_ACTION_IN_FIELD_METADATA_REG_C_4  = 0x55,
+        MLX5_ACTION_IN_FIELD_METADATA_REG_C_5  = 0x56,
+        MLX5_ACTION_IN_FIELD_METADATA_REG_C_6  = 0x57,
+        MLX5_ACTION_IN_FIELD_METADATA_REG_C_7  = 0x58,
+        MLX5_ACTION_IN_FIELD_OUT_TCP_SEQ_NUM   = 0x59,
+        MLX5_ACTION_IN_FIELD_OUT_TCP_ACK_NUM   = 0x5B,
+        MLX5_ACTION_IN_FIELD_IPSEC_SYNDROME    = 0x5D,
+        MLX5_ACTION_IN_FIELD_OUT_EMD_47_32     = 0x6F,
+        MLX5_ACTION_IN_FIELD_OUT_EMD_31_0      = 0x70,
+};
+
+struct mlx5_ifc_alloc_modify_header_context_out_bits {
+        u8         status[0x8];
+        u8         reserved_at_8[0x18];
+
+        u8         syndrome[0x20];
+
+        u8         modify_header_id[0x20];
+
+        u8         reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_alloc_modify_header_context_in_bits {
+        u8         opcode[0x10];
+        u8         reserved_at_10[0x10];
+
+        u8         reserved_at_20[0x10];
+        u8         op_mod[0x10];
+
+        u8         reserved_at_40[0x20];
+
+        u8         table_type[0x8];
+        u8         reserved_at_68[0x10];
+        u8         num_of_actions[0x8];
+
+        union mlx5_ifc_set_add_copy_action_in_auto_bits actions[];
+};
+
+struct mlx5_ifc_dealloc_modify_header_context_out_bits {
+        u8         status[0x8];
+        u8         reserved_at_8[0x18];
+
+        u8         syndrome[0x20];
+
+        u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_dealloc_modify_header_context_in_bits {
+        u8         opcode[0x10];
+        u8         reserved_at_10[0x10];
+
+        u8         reserved_at_20[0x10];
+        u8         op_mod[0x10];
+
+        u8         modify_header_id[0x20];
+
+        u8         reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_query_modify_header_context_in_bits {
+        u8         opcode[0x10];
+        u8         uid[0x10];
+
+        u8         reserved_at_20[0x10];
+        u8         op_mod[0x10];
+
+        u8         modify_header_id[0x20];
+
+        u8         reserved_at_60[0xa0];
+};
+
 struct mlx5_ifc_query_dct_out_bits {
 	u8         status[0x8];
 	u8         reserved_0[0x18];