net/mlx5: fs, add RDMA TRANSPORT steering domain support
authorPatrisious Haddad <phaddad@nvidia.com>
Wed, 26 Feb 2025 13:01:09 +0000 (15:01 +0200)
committerLeon Romanovsky <leon@kernel.org>
Sat, 8 Mar 2025 18:22:49 +0000 (13:22 -0500)
Add RX and TX RDMA_TRANSPORT flow table namespace, and the ability
to create flow tables in those namespaces.

The RDMA_TRANSPORT RX and TX are per vport.

Packets will traverse through RDMA_TRANSPORT_RX after RDMA_RX and through
RDMA_TRANSPORT_TX before RDMA_TX, ensuring proper control and management.

RDMA_TRANSPORT domains are managed by the vport group manager.

Signed-off-by: Patrisious Haddad <phaddad@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/a6b550d9859a197eafa804b9a8d76916ca481da9.1740574103.git.leon@kernel.org
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
include/linux/mlx5/device.h
include/linux/mlx5/fs.h

index d599e50af346bef72bd08cb385fe0aca44cdf2c7..3ce455c2535c400b50fda8fe27464ed360345020 100644 (file)
@@ -27,7 +27,7 @@ esw_acl_table_create(struct mlx5_eswitch *esw, struct mlx5_vport *vport, int ns,
        esw_debug(dev, "Create vport[%d] %s ACL table\n", vport_num,
                  ns == MLX5_FLOW_NAMESPACE_ESW_INGRESS ? "ingress" : "egress");
 
-       root_ns = mlx5_get_flow_vport_acl_namespace(dev, ns, vport->index);
+       root_ns = mlx5_get_flow_vport_namespace(dev, ns, vport->index);
        if (!root_ns) {
                esw_warn(dev, "Failed to get E-Switch root namespace for vport (%d)\n",
                         vport_num);
index 20cc01ceee8a94cc22e096da27c59e1ab94b99f0..1ee5791573d84168f9d9ae6bf07175b497680051 100644 (file)
@@ -2828,9 +2828,9 @@ static int esw_set_master_egress_rule(struct mlx5_core_dev *master,
        if (IS_ERR(vport))
                return PTR_ERR(vport);
 
-       egress_ns = mlx5_get_flow_vport_acl_namespace(master,
-                                                     MLX5_FLOW_NAMESPACE_ESW_EGRESS,
-                                                     vport->index);
+       egress_ns = mlx5_get_flow_vport_namespace(master,
+                                                 MLX5_FLOW_NAMESPACE_ESW_EGRESS,
+                                                 vport->index);
        if (!egress_ns)
                return -EINVAL;
 
index ae20c061e0fb2f9227d6a6514aaaf629ae4acefd..a47c29571f64739f00d662cf0e703154c962458c 100644 (file)
@@ -1142,6 +1142,8 @@ const struct mlx5_flow_cmds *mlx5_fs_cmd_get_default(enum fs_flow_table_type typ
        case FS_FT_RDMA_RX:
        case FS_FT_RDMA_TX:
        case FS_FT_PORT_SEL:
+       case FS_FT_RDMA_TRANSPORT_RX:
+       case FS_FT_RDMA_TRANSPORT_TX:
                return mlx5_fs_cmd_get_fw_cmds();
        default:
                return mlx5_fs_cmd_get_stub_cmds();
index 22dc23d991d2e157b7f241df33bb6daa84e0e9bc..6163bc98d94a941058dd7d80c735235b857a9118 100644 (file)
@@ -1456,7 +1456,7 @@ mlx5_create_auto_grouped_flow_table(struct mlx5_flow_namespace *ns,
        struct mlx5_flow_table *ft;
        int autogroups_max_fte;
 
-       ft = mlx5_create_flow_table(ns, ft_attr);
+       ft = mlx5_create_vport_flow_table(ns, ft_attr, ft_attr->vport);
        if (IS_ERR(ft))
                return ft;
 
@@ -2764,9 +2764,9 @@ struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
 }
 EXPORT_SYMBOL(mlx5_get_flow_namespace);
 
-struct mlx5_flow_namespace *mlx5_get_flow_vport_acl_namespace(struct mlx5_core_dev *dev,
-                                                             enum mlx5_flow_namespace_type type,
-                                                             int vport)
+struct mlx5_flow_namespace *
+mlx5_get_flow_vport_namespace(struct mlx5_core_dev *dev,
+                             enum mlx5_flow_namespace_type type, int vport_idx)
 {
        struct mlx5_flow_steering *steering = dev->priv.steering;
 
@@ -2775,25 +2775,43 @@ struct mlx5_flow_namespace *mlx5_get_flow_vport_acl_namespace(struct mlx5_core_d
 
        switch (type) {
        case MLX5_FLOW_NAMESPACE_ESW_EGRESS:
-               if (vport >= steering->esw_egress_acl_vports)
+               if (vport_idx >= steering->esw_egress_acl_vports)
                        return NULL;
                if (steering->esw_egress_root_ns &&
-                   steering->esw_egress_root_ns[vport])
-                       return &steering->esw_egress_root_ns[vport]->ns;
+                   steering->esw_egress_root_ns[vport_idx])
+                       return &steering->esw_egress_root_ns[vport_idx]->ns;
                else
                        return NULL;
        case MLX5_FLOW_NAMESPACE_ESW_INGRESS:
-               if (vport >= steering->esw_ingress_acl_vports)
+               if (vport_idx >= steering->esw_ingress_acl_vports)
                        return NULL;
                if (steering->esw_ingress_root_ns &&
-                   steering->esw_ingress_root_ns[vport])
-                       return &steering->esw_ingress_root_ns[vport]->ns;
+                   steering->esw_ingress_root_ns[vport_idx])
+                       return &steering->esw_ingress_root_ns[vport_idx]->ns;
+               else
+                       return NULL;
+       case MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_RX:
+               if (vport_idx >= steering->rdma_transport_rx_vports)
+                       return NULL;
+               if (steering->rdma_transport_rx_root_ns &&
+                   steering->rdma_transport_rx_root_ns[vport_idx])
+                       return &steering->rdma_transport_rx_root_ns[vport_idx]->ns;
+               else
+                       return NULL;
+       case MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_TX:
+               if (vport_idx >= steering->rdma_transport_tx_vports)
+                       return NULL;
+
+               if (steering->rdma_transport_tx_root_ns &&
+                   steering->rdma_transport_tx_root_ns[vport_idx])
+                       return &steering->rdma_transport_tx_root_ns[vport_idx]->ns;
                else
                        return NULL;
        default:
                return NULL;
        }
 }
+EXPORT_SYMBOL(mlx5_get_flow_vport_namespace);
 
 static struct fs_prio *_fs_create_prio(struct mlx5_flow_namespace *ns,
                                       unsigned int prio,
@@ -3199,6 +3217,127 @@ out_err:
        return err;
 }
 
+static int
+init_rdma_transport_rx_root_ns_one(struct mlx5_flow_steering *steering,
+                                  int vport_idx)
+{
+       struct fs_prio *prio;
+
+       steering->rdma_transport_rx_root_ns[vport_idx] =
+               create_root_ns(steering, FS_FT_RDMA_TRANSPORT_RX);
+       if (!steering->rdma_transport_rx_root_ns[vport_idx])
+               return -ENOMEM;
+
+       /* create 1 prio*/
+       prio = fs_create_prio(&steering->rdma_transport_rx_root_ns[vport_idx]->ns,
+                             MLX5_RDMA_TRANSPORT_BYPASS_PRIO, 1);
+       return PTR_ERR_OR_ZERO(prio);
+}
+
+static int
+init_rdma_transport_tx_root_ns_one(struct mlx5_flow_steering *steering,
+                                  int vport_idx)
+{
+       struct fs_prio *prio;
+
+       steering->rdma_transport_tx_root_ns[vport_idx] =
+               create_root_ns(steering, FS_FT_RDMA_TRANSPORT_TX);
+       if (!steering->rdma_transport_tx_root_ns[vport_idx])
+               return -ENOMEM;
+
+       /* create 1 prio*/
+       prio = fs_create_prio(&steering->rdma_transport_tx_root_ns[vport_idx]->ns,
+                             MLX5_RDMA_TRANSPORT_BYPASS_PRIO, 1);
+       return PTR_ERR_OR_ZERO(prio);
+}
+
+static int init_rdma_transport_rx_root_ns(struct mlx5_flow_steering *steering)
+{
+       struct mlx5_core_dev *dev = steering->dev;
+       int total_vports;
+       int err;
+       int i;
+
+       /* In case eswitch not supported and working in legacy mode */
+       total_vports = mlx5_eswitch_get_total_vports(dev) ?: 1;
+
+       steering->rdma_transport_rx_root_ns =
+                       kcalloc(total_vports,
+                               sizeof(*steering->rdma_transport_rx_root_ns),
+                               GFP_KERNEL);
+       if (!steering->rdma_transport_rx_root_ns)
+               return -ENOMEM;
+
+       for (i = 0; i < total_vports; i++) {
+               err = init_rdma_transport_rx_root_ns_one(steering, i);
+               if (err)
+                       goto cleanup_root_ns;
+       }
+       steering->rdma_transport_rx_vports = total_vports;
+       return 0;
+
+cleanup_root_ns:
+       while (i--)
+               cleanup_root_ns(steering->rdma_transport_rx_root_ns[i]);
+       kfree(steering->rdma_transport_rx_root_ns);
+       steering->rdma_transport_rx_root_ns = NULL;
+       return err;
+}
+
+static int init_rdma_transport_tx_root_ns(struct mlx5_flow_steering *steering)
+{
+       struct mlx5_core_dev *dev = steering->dev;
+       int total_vports;
+       int err;
+       int i;
+
+       /* In case eswitch not supported and working in legacy mode */
+       total_vports = mlx5_eswitch_get_total_vports(dev) ?: 1;
+
+       steering->rdma_transport_tx_root_ns =
+                       kcalloc(total_vports,
+                               sizeof(*steering->rdma_transport_tx_root_ns),
+                               GFP_KERNEL);
+       if (!steering->rdma_transport_tx_root_ns)
+               return -ENOMEM;
+
+       for (i = 0; i < total_vports; i++) {
+               err = init_rdma_transport_tx_root_ns_one(steering, i);
+               if (err)
+                       goto cleanup_root_ns;
+       }
+       steering->rdma_transport_tx_vports = total_vports;
+       return 0;
+
+cleanup_root_ns:
+       while (i--)
+               cleanup_root_ns(steering->rdma_transport_tx_root_ns[i]);
+       kfree(steering->rdma_transport_tx_root_ns);
+       steering->rdma_transport_tx_root_ns = NULL;
+       return err;
+}
+
+static void cleanup_rdma_transport_roots_ns(struct mlx5_flow_steering *steering)
+{
+       int i;
+
+       if (steering->rdma_transport_rx_root_ns) {
+               for (i = 0; i < steering->rdma_transport_rx_vports; i++)
+                       cleanup_root_ns(steering->rdma_transport_rx_root_ns[i]);
+
+               kfree(steering->rdma_transport_rx_root_ns);
+               steering->rdma_transport_rx_root_ns = NULL;
+       }
+
+       if (steering->rdma_transport_tx_root_ns) {
+               for (i = 0; i < steering->rdma_transport_tx_vports; i++)
+                       cleanup_root_ns(steering->rdma_transport_tx_root_ns[i]);
+
+               kfree(steering->rdma_transport_tx_root_ns);
+               steering->rdma_transport_tx_root_ns = NULL;
+       }
+}
+
 /* FT and tc chains are stored in the same array so we can re-use the
  * mlx5_get_fdb_sub_ns() and tc api for FT chains.
  * When creating a new ns for each chain store it in the first available slot.
@@ -3631,6 +3770,7 @@ void mlx5_fs_core_cleanup(struct mlx5_core_dev *dev)
        cleanup_root_ns(steering->rdma_rx_root_ns);
        cleanup_root_ns(steering->rdma_tx_root_ns);
        cleanup_root_ns(steering->egress_root_ns);
+       cleanup_rdma_transport_roots_ns(steering);
 
        devl_params_unregister(priv_to_devlink(dev), mlx5_fs_params,
                               ARRAY_SIZE(mlx5_fs_params));
@@ -3700,6 +3840,18 @@ int mlx5_fs_core_init(struct mlx5_core_dev *dev)
                        goto err;
        }
 
+       if (MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_RX(dev, ft_support)) {
+               err = init_rdma_transport_rx_root_ns(steering);
+               if (err)
+                       goto err;
+       }
+
+       if (MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_TX(dev, ft_support)) {
+               err = init_rdma_transport_tx_root_ns(steering);
+               if (err)
+                       goto err;
+       }
+
        return 0;
 
 err:
@@ -3850,8 +4002,10 @@ mlx5_get_root_namespace(struct mlx5_core_dev *dev, enum mlx5_flow_namespace_type
        struct mlx5_flow_namespace *ns;
 
        if (ns_type == MLX5_FLOW_NAMESPACE_ESW_EGRESS ||
-           ns_type == MLX5_FLOW_NAMESPACE_ESW_INGRESS)
-               ns = mlx5_get_flow_vport_acl_namespace(dev, ns_type, 0);
+           ns_type == MLX5_FLOW_NAMESPACE_ESW_INGRESS ||
+           ns_type == MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_TX ||
+           ns_type == MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_RX)
+               ns = mlx5_get_flow_vport_namespace(dev, ns_type, 0);
        else
                ns = mlx5_get_flow_namespace(dev, ns_type);
        if (!ns)
index 20837e526679d0f3b94db7377379300272540234..dbe747e938415de0504aa16169172e78192bfbc9 100644 (file)
@@ -115,7 +115,9 @@ enum fs_flow_table_type {
        FS_FT_PORT_SEL          = 0X9,
        FS_FT_FDB_RX            = 0xa,
        FS_FT_FDB_TX            = 0xb,
-       FS_FT_MAX_TYPE = FS_FT_FDB_TX,
+       FS_FT_RDMA_TRANSPORT_RX = 0xd,
+       FS_FT_RDMA_TRANSPORT_TX = 0xe,
+       FS_FT_MAX_TYPE = FS_FT_RDMA_TRANSPORT_TX,
 };
 
 enum fs_flow_table_op_mod {
@@ -158,6 +160,10 @@ struct mlx5_flow_steering {
        struct mlx5_flow_root_namespace *port_sel_root_ns;
        int esw_egress_acl_vports;
        int esw_ingress_acl_vports;
+       struct mlx5_flow_root_namespace **rdma_transport_rx_root_ns;
+       struct mlx5_flow_root_namespace **rdma_transport_tx_root_ns;
+       int rdma_transport_rx_vports;
+       int rdma_transport_tx_vports;
 };
 
 struct fs_node {
@@ -434,7 +440,9 @@ struct mlx5_flow_root_namespace *find_root(struct fs_node *node);
        (type == FS_FT_PORT_SEL) ? MLX5_CAP_FLOWTABLE_PORT_SELECTION(mdev, cap) :      \
        (type == FS_FT_FDB_RX) ? MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, cap) :      \
        (type == FS_FT_FDB_TX) ? MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, cap) :      \
-       (BUILD_BUG_ON_ZERO(FS_FT_FDB_TX != FS_FT_MAX_TYPE))\
+       (type == FS_FT_RDMA_TRANSPORT_RX) ? MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_RX(mdev, cap) :      \
+       (type == FS_FT_RDMA_TRANSPORT_TX) ? MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_TX(mdev, cap) :      \
+       (BUILD_BUG_ON_ZERO(FS_FT_RDMA_TRANSPORT_TX != FS_FT_MAX_TYPE))\
        )
 
 #endif
index 0ae6d69c5221d51634b0ac4b4dbf3e4356c06163..8fe56d0362c62665471357f0658084b84f356e0e 100644 (file)
@@ -1346,6 +1346,12 @@ enum mlx5_qcam_feature_groups {
 #define MLX5_CAP_FLOWTABLE_RDMA_TX(mdev, cap) \
        MLX5_CAP_FLOWTABLE(mdev, flow_table_properties_nic_transmit_rdma.cap)
 
+#define MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_RX(mdev, cap) \
+       MLX5_CAP_ADV_RDMA(mdev, rdma_transport_rx_flow_table_properties.cap)
+
+#define MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_TX(mdev, cap) \
+       MLX5_CAP_ADV_RDMA(mdev, rdma_transport_tx_flow_table_properties.cap)
+
 #define MLX5_CAP_ESW_FLOWTABLE(mdev, cap) \
        MLX5_GET(flow_table_eswitch_cap, \
                 mdev->caps.hca[MLX5_CAP_ESWITCH_FLOW_TABLE]->cur, cap)
index 01cb72d68c231f6543c838b578d2ff1b96b22c8c..fd62b2b1611d65f01e7fa11c0472129a7650246b 100644 (file)
@@ -40,6 +40,7 @@
 
 #define MLX5_SET_CFG(p, f, v) MLX5_SET(create_flow_group_in, p, f, v)
 
+#define MLX5_RDMA_TRANSPORT_BYPASS_PRIO 0
 #define MLX5_FS_MAX_POOL_SIZE BIT(30)
 
 enum mlx5_flow_destination_type {
@@ -110,6 +111,8 @@ enum mlx5_flow_namespace_type {
        MLX5_FLOW_NAMESPACE_RDMA_TX_IPSEC,
        MLX5_FLOW_NAMESPACE_RDMA_RX_MACSEC,
        MLX5_FLOW_NAMESPACE_RDMA_TX_MACSEC,
+       MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_RX,
+       MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_TX,
 };
 
 enum {
@@ -194,9 +197,9 @@ struct mlx5_flow_namespace *
 mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
                        enum mlx5_flow_namespace_type type);
 struct mlx5_flow_namespace *
-mlx5_get_flow_vport_acl_namespace(struct mlx5_core_dev *dev,
-                                 enum mlx5_flow_namespace_type type,
-                                 int vport);
+mlx5_get_flow_vport_namespace(struct mlx5_core_dev *dev,
+                             enum mlx5_flow_namespace_type type,
+                             int vport_idx);
 
 struct mlx5_flow_table_attr {
        int prio;
@@ -204,6 +207,7 @@ struct mlx5_flow_table_attr {
        u32 level;
        u32 flags;
        u16 uid;
+       u16 vport;
        struct mlx5_flow_table *next_ft;
 
        struct {