* [PATCH rdma-next 0/5] RDMA/mlx5: Add NIC_RX_CLASS steering domain for RDMA classification
@ 2026-11-03 18:12 Edward Srouji
2026-11-03 18:12 ` [PATCH mlx5-next 1/5] net/mlx5: Add NIC_RX_CLASS IFC bits Edward Srouji
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Edward Srouji @ 2026-11-03 18:12 UTC (permalink / raw)
To: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Jason Gunthorpe, Yishai Hadas
Cc: Edward Srouji, linux-rdma, netdev, linux-kernel, Mark Bloch,
Michael Gur, Patrisious Haddad
mlx5 devices recognise RDMA traffic on receive with a fixed classifier: UDP
destination port 4791. Packets that match are handed to the RDMA receive path
(NIC_RX_RDMA); everything else continues down the normal NIC RX path.
RDMA transports that identify their packet differently don't reach the
RDMA receive path as they use a different packet format entirely.
This series adds NIC_RX_CLASS, a new per-vport receive steering domain placed
ahead of NIC_RX/NIC_RX_RDMA. It gives a privileged RDMA transport manager a
programmable classification stage that supports matching on arbitrary header
fields and marking the packet as RDMA.
NIC_RX_CLASS reuses the model used by RDMA_TRANSPORT_RX/TX domains:
- one root namespace per vport, owned by the eswitch manager;
- targeted from userspace by `ib_port`, as with the existing per-vport
domains;
- gated by `rdma_transport_manager`, and by
`rdma_transport_manager_other_eswitch` for the cross-eswitch (LAG /
socket-direct) case;
- restricted to callers holding the same UCAP that per-port matchers already
require, so an unprivileged process cannot program another vport's
classification.
A rule in this domain takes no destination: it matches, attaches a
modify-header action to mark the packet as RDMA and explicitly allows it
onward. ALLOW is the only terminal action the domain accepts; a flow counter
may be attached alongside it.
Patch 1 adds the IFC bits, patch 2 fixes ALLOW handling in the FTE merge
logic, patch 3 unifies the per-vport root namespace init/cleanup helpers,
and patch 4 adds the NIC_RX_CLASS domain itself. Patch 5 exposes the new
domain and the ALLOW action to userspace.
Patches 1-4 are mlx5_core changes and are targeted at the shared mlx5-next
branch, prefixed accordingly; patch 5 depends on them and is targeted at
rdma-next.
Signed-off-by: Edward Srouji <edwards@nvidia.com>
---
Michael Gur (5):
net/mlx5: Add NIC_RX_CLASS IFC bits
net/mlx5: fs, treat ALLOW as a conflicting action upon merge
net/mlx5: fs, refactor RDMA transport manager root namespace init/cleanup
net/mlx5: fs, add NIC_RX_CLASS steering domain support
RDMA/mlx5: Expose NIC_RX_CLASS flow table type to userspace
drivers/infiniband/hw/mlx5/fs.c | 59 ++++++-
drivers/infiniband/hw/mlx5/fs.h | 2 +
drivers/infiniband/hw/mlx5/ib_rep.c | 25 ++-
drivers/infiniband/hw/mlx5/mlx5_ib.h | 1 +
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c | 5 +
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 178 +++++++++-------------
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h | 15 +-
include/linux/mlx5/device.h | 3 +
include/linux/mlx5/fs.h | 4 +-
include/linux/mlx5/mlx5_ifc.h | 9 +-
include/uapi/rdma/mlx5_user_ioctl_cmds.h | 1 +
include/uapi/rdma/mlx5_user_ioctl_verbs.h | 1 +
12 files changed, 173 insertions(+), 130 deletions(-)
---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20261103-rdma-rx-classifier-866946b90d6a
Best regards,
--
Edward Srouji <edwards@nvidia.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH mlx5-next 1/5] net/mlx5: Add NIC_RX_CLASS IFC bits
2026-11-03 18:12 [PATCH rdma-next 0/5] RDMA/mlx5: Add NIC_RX_CLASS steering domain for RDMA classification Edward Srouji
@ 2026-11-03 18:12 ` Edward Srouji
2026-11-03 18:12 ` [PATCH mlx5-next 2/5] net/mlx5: fs, treat ALLOW as a conflicting action upon merge Edward Srouji
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Edward Srouji @ 2026-11-03 18:12 UTC (permalink / raw)
To: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Jason Gunthorpe, Yishai Hadas
Cc: Edward Srouji, linux-rdma, netdev, linux-kernel, Mark Bloch,
Michael Gur, Patrisious Haddad
From: Michael Gur <michaelgur@nvidia.com>
Expose NIC_RX_CLASS capabilities in ADV_RDMA struct to allow exposing
the new steering domain to users in the following patches.
Signed-off-by: Michael Gur <michaelgur@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Reviewed-by: Patrisious Haddad <phaddad@nvidia.com>
Signed-off-by: Edward Srouji <edwards@nvidia.com>
---
include/linux/mlx5/mlx5_ifc.h | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index 697fc9387b73ae1dd2305d475f7fdc767a1a2cdd..a7cf67264a1799ad179938907f5c871c9190f9e5 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -13690,7 +13690,14 @@ struct mlx5_ifc_adv_rdma_cap_bits {
struct mlx5_ifc_flow_table_fields_supported_2_bits rdma_transport_tx_ft_field_bitmask_support_2;
- u8 reserved_at_800[0x3800];
+ u8 reserved_at_800[0x400];
+ u8 reserved_at_c00[0x400];
+
+ struct mlx5_ifc_flow_table_prop_layout_bits nic_rx_class_flow_table_properties;
+
+ u8 reserved_at_1200[0x500];
+
+ u8 reserved_at_1700[0x2900];
};
struct mlx5_ifc_adv_virtualization_cap_bits {
--
2.49.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH mlx5-next 2/5] net/mlx5: fs, treat ALLOW as a conflicting action upon merge
2026-11-03 18:12 [PATCH rdma-next 0/5] RDMA/mlx5: Add NIC_RX_CLASS steering domain for RDMA classification Edward Srouji
2026-11-03 18:12 ` [PATCH mlx5-next 1/5] net/mlx5: Add NIC_RX_CLASS IFC bits Edward Srouji
@ 2026-11-03 18:12 ` Edward Srouji
2026-11-03 18:12 ` [PATCH mlx5-next 3/5] net/mlx5: fs, refactor RDMA transport manager root namespace init/cleanup Edward Srouji
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Edward Srouji @ 2026-11-03 18:12 UTC (permalink / raw)
To: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Jason Gunthorpe, Yishai Hadas
Cc: Edward Srouji, linux-rdma, netdev, linux-kernel, Mark Bloch,
Michael Gur, Patrisious Haddad
From: Michael Gur <michaelgur@nvidia.com>
Two rules with identical match criteria are allowed to merge into one
firmware entry, combining their actions - this is how a single match
fans out to multiple actions. That merge logic rejects combining
conflicting actions, e.g a DROP rule with a forwarding rule, since one
entry can't carry both, but never learned to do the same for ALLOW.
Two same-match rules, one requesting ALLOW and the other forwarding,
merge into a single entry that ends up requesting both, violating
firmware's rule that exactly one of forward/drop/allow may be set per
entry.
Reject merging same-match rules that disagree on ALLOW, the same way
already done for other actions.
Fixes: a7ee18bdee83 ("RDMA/mlx5: Allow creating a matcher for a NIC TX flow table")
Signed-off-by: Michael Gur <michaelgur@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Reviewed-by: Patrisious Haddad <phaddad@nvidia.com>
Signed-off-by: Edward Srouji <edwards@nvidia.com>
---
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index c8f6adae6f51a03d058e48aba376fa4cfbe263b9..70545053f9c42d6f6ccf439852d14f9b9e16419f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -1929,6 +1929,7 @@ static bool check_conflicting_actions(const struct mlx5_flow_act *act1,
return false;
if (xored_actions & (MLX5_FLOW_CONTEXT_ACTION_DROP |
+ MLX5_FLOW_CONTEXT_ACTION_ALLOW |
MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT |
MLX5_FLOW_CONTEXT_ACTION_DECAP |
MLX5_FLOW_CONTEXT_ACTION_MOD_HDR |
--
2.49.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH mlx5-next 3/5] net/mlx5: fs, refactor RDMA transport manager root namespace init/cleanup
2026-11-03 18:12 [PATCH rdma-next 0/5] RDMA/mlx5: Add NIC_RX_CLASS steering domain for RDMA classification Edward Srouji
2026-11-03 18:12 ` [PATCH mlx5-next 1/5] net/mlx5: Add NIC_RX_CLASS IFC bits Edward Srouji
2026-11-03 18:12 ` [PATCH mlx5-next 2/5] net/mlx5: fs, treat ALLOW as a conflicting action upon merge Edward Srouji
@ 2026-11-03 18:12 ` Edward Srouji
2026-11-03 18:12 ` [PATCH mlx5-next 4/5] net/mlx5: fs, add NIC_RX_CLASS steering domain support Edward Srouji
2026-11-03 18:12 ` [PATCH rdma-next 5/5] RDMA/mlx5: Expose NIC_RX_CLASS flow table type to userspace Edward Srouji
4 siblings, 0 replies; 6+ messages in thread
From: Edward Srouji @ 2026-11-03 18:12 UTC (permalink / raw)
To: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Jason Gunthorpe, Yishai Hadas
Cc: Edward Srouji, linux-rdma, netdev, linux-kernel, Mark Bloch,
Michael Gur, Patrisious Haddad
From: Michael Gur <michaelgur@nvidia.com>
The rdma transport steering domains init, cleanup and helpers are
near-identical, merge them into single
init_transport_manager_root_ns()/_one() and
cleanup_transport_manager_root_ns() with parameters.
This is preparation for a new domain with the same per-vport root
namespace usage model, which will reuse these functions instead of
duplicating them a third time.
No functional change to RDMA_TRANSPORT_RX/TX.
Signed-off-by: Michael Gur <michaelgur@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Reviewed-by: Patrisious Haddad <phaddad@nvidia.com>
Signed-off-by: Edward Srouji <edwards@nvidia.com>
---
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 153 +++++++---------------
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h | 11 +-
2 files changed, 53 insertions(+), 111 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 70545053f9c42d6f6ccf439852d14f9b9e16419f..033ea5a198ee0d5a7e77ce0770f38bb8ffe97812 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -2817,20 +2817,20 @@ mlx5_get_flow_vport_namespace(struct mlx5_core_dev *dev,
else
return NULL;
case MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_RX:
- if (vport_idx >= steering->rdma_transport_rx_vports)
+ 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;
+ 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)
+ 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;
+ 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:
@@ -3244,7 +3244,9 @@ static int init_rdma_tx_root_ns(struct mlx5_flow_steering *steering)
}
static int
-init_rdma_transport_rx_root_ns_one(struct mlx5_flow_steering *steering,
+init_transport_manager_root_ns_one(struct mlx5_flow_steering *steering,
+ struct mlx5_flow_root_namespace **root_ns_arr,
+ enum fs_flow_table_type ft_type,
int vport_idx)
{
struct mlx5_flow_root_namespace *root_ns;
@@ -3252,43 +3254,11 @@ init_rdma_transport_rx_root_ns_one(struct mlx5_flow_steering *steering,
int ret;
int i;
- 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])
+ root_ns_arr[vport_idx] = create_root_ns(steering, ft_type);
+ if (!root_ns_arr[vport_idx])
return -ENOMEM;
- root_ns = steering->rdma_transport_rx_root_ns[vport_idx];
-
- for (i = 0; i < MLX5_RDMA_TRANSPORT_BYPASS_PRIO; i++) {
- prio = fs_create_prio(&root_ns->ns, i, 1);
- if (IS_ERR(prio)) {
- ret = PTR_ERR(prio);
- goto err;
- }
- }
- set_prio_attrs(root_ns);
- return 0;
-
-err:
- cleanup_root_ns(root_ns);
- return ret;
-}
-
-static int
-init_rdma_transport_tx_root_ns_one(struct mlx5_flow_steering *steering,
- int vport_idx)
-{
- struct mlx5_flow_root_namespace *root_ns;
- struct fs_prio *prio;
- int ret;
- int i;
-
- 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;
-
- root_ns = steering->rdma_transport_tx_root_ns[vport_idx];
+ root_ns = root_ns_arr[vport_idx];
for (i = 0; i < MLX5_RDMA_TRANSPORT_BYPASS_PRIO; i++) {
prio = fs_create_prio(&root_ns->ns, i, 1);
@@ -3327,12 +3297,12 @@ int mlx5_fs_set_root_dev(struct mlx5_core_dev *dev,
switch (table_type) {
case FS_FT_RDMA_TRANSPORT_TX:
- root = dev->priv.steering->rdma_transport_tx_root_ns;
- total_vports = dev->priv.steering->rdma_transport_tx_vports;
+ root = dev->priv.steering->rdma_transport_tx.root_ns;
+ total_vports = dev->priv.steering->rdma_transport_tx.vports;
break;
case FS_FT_RDMA_TRANSPORT_RX:
- root = dev->priv.steering->rdma_transport_rx_root_ns;
- total_vports = dev->priv.steering->rdma_transport_rx_vports;
+ root = dev->priv.steering->rdma_transport_rx.root_ns;
+ total_vports = dev->priv.steering->rdma_transport_rx.vports;
break;
default:
WARN_ON_ONCE(true);
@@ -3361,39 +3331,10 @@ int mlx5_fs_set_root_dev(struct mlx5_core_dev *dev,
}
EXPORT_SYMBOL(mlx5_fs_set_root_dev);
-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 =
- kzalloc_objs(*steering->rdma_transport_rx_root_ns,
- total_vports);
- 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)
+static int
+init_transport_manager_root_ns(struct mlx5_flow_steering *steering,
+ struct mlx5_transport_manager_ns *tm,
+ enum fs_flow_table_type ft_type)
{
struct mlx5_core_dev *dev = steering->dev;
int total_vports;
@@ -3403,47 +3344,40 @@ static int init_rdma_transport_tx_root_ns(struct mlx5_flow_steering *steering)
/* 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 =
- kzalloc_objs(*steering->rdma_transport_tx_root_ns,
- total_vports);
- if (!steering->rdma_transport_tx_root_ns)
+ tm->root_ns = kzalloc_objs(*tm->root_ns, total_vports);
+ if (!tm->root_ns)
return -ENOMEM;
for (i = 0; i < total_vports; i++) {
- err = init_rdma_transport_tx_root_ns_one(steering, i);
+ err = init_transport_manager_root_ns_one(steering, tm->root_ns,
+ ft_type, i);
if (err)
goto cleanup_root_ns;
}
- steering->rdma_transport_tx_vports = total_vports;
+ tm->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;
+ cleanup_root_ns(tm->root_ns[i]);
+ kfree(tm->root_ns);
+ tm->root_ns = NULL;
return err;
}
-static void cleanup_rdma_transport_roots_ns(struct mlx5_flow_steering *steering)
+static void
+cleanup_transport_manager_root_ns(struct mlx5_transport_manager_ns *tm)
{
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 (!tm->root_ns)
+ return;
- 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]);
+ for (i = 0; i < tm->vports; i++)
+ cleanup_root_ns(tm->root_ns[i]);
- kfree(steering->rdma_transport_tx_root_ns);
- steering->rdma_transport_tx_root_ns = NULL;
- }
+ kfree(tm->root_ns);
+ tm->root_ns = NULL;
}
/* FT and tc chains are stored in the same array so we can re-use the
@@ -3871,7 +3805,8 @@ 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);
+ cleanup_transport_manager_root_ns(&steering->rdma_transport_rx);
+ cleanup_transport_manager_root_ns(&steering->rdma_transport_tx);
devl_params_unregister(priv_to_devlink(dev), mlx5_fs_params,
ARRAY_SIZE(mlx5_fs_params));
@@ -3942,13 +3877,17 @@ int mlx5_fs_core_init(struct mlx5_core_dev *dev)
}
if (MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_RX(dev, ft_support)) {
- err = init_rdma_transport_rx_root_ns(steering);
+ err = init_transport_manager_root_ns(steering,
+ &steering->rdma_transport_rx,
+ FS_FT_RDMA_TRANSPORT_RX);
if (err)
goto err;
}
if (MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_TX(dev, ft_support)) {
- err = init_rdma_transport_tx_root_ns(steering);
+ err = init_transport_manager_root_ns(steering,
+ &steering->rdma_transport_tx,
+ FS_FT_RDMA_TRANSPORT_TX);
if (err)
goto err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
index 906584345a022d14aadd20d665ea41d2f287d719..e36735bea218c6909a6196305caa5c2aa5a83af6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
@@ -125,6 +125,11 @@ enum mlx5_flow_steering_capabilty {
MLX5_FLOW_STEERING_CAP_DUPLICATE_MATCH = 1UL << 3,
};
+struct mlx5_transport_manager_ns {
+ struct mlx5_flow_root_namespace **root_ns;
+ int vports;
+};
+
struct mlx5_flow_steering {
struct mlx5_core_dev *dev;
enum mlx5_flow_steering_mode mode;
@@ -141,10 +146,8 @@ struct mlx5_flow_steering {
struct mlx5_flow_root_namespace *rdma_tx_root_ns;
struct mlx5_flow_root_namespace *egress_root_ns;
struct mlx5_flow_root_namespace *port_sel_root_ns;
- 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 mlx5_transport_manager_ns rdma_transport_rx;
+ struct mlx5_transport_manager_ns rdma_transport_tx;
};
struct fs_node {
--
2.49.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH mlx5-next 4/5] net/mlx5: fs, add NIC_RX_CLASS steering domain support
2026-11-03 18:12 [PATCH rdma-next 0/5] RDMA/mlx5: Add NIC_RX_CLASS steering domain for RDMA classification Edward Srouji
` (2 preceding siblings ...)
2026-11-03 18:12 ` [PATCH mlx5-next 3/5] net/mlx5: fs, refactor RDMA transport manager root namespace init/cleanup Edward Srouji
@ 2026-11-03 18:12 ` Edward Srouji
2026-11-03 18:12 ` [PATCH rdma-next 5/5] RDMA/mlx5: Expose NIC_RX_CLASS flow table type to userspace Edward Srouji
4 siblings, 0 replies; 6+ messages in thread
From: Edward Srouji @ 2026-11-03 18:12 UTC (permalink / raw)
To: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Jason Gunthorpe, Yishai Hadas
Cc: Edward Srouji, linux-rdma, netdev, linux-kernel, Mark Bloch,
Michael Gur, Patrisious Haddad
From: Michael Gur <michaelgur@nvidia.com>
RDMA transports that don't natively map to hardware's fixed RoCE
recognition (UDP dst port 4791) need a way to tell the NIC that other
packets should be treated as RDMA traffic too. NIC_RX_CLASS gives the
RDMA transport manager a programmable classification stage ahead of
the regular NIC receive path: software installs match/modify-header
rules there to steer packets using other UDP ports, or other packet
formats entirely, into the RDMA receive path, instead of being limited
to hardware's native RoCE detection.
This domain supports Modify header actions in case steering the packet
into the RDMA path requires rewriting it into a format RDMA_RX expects.
Signed-off-by: Michael Gur <michaelgur@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Reviewed-by: Patrisious Haddad <phaddad@nvidia.com>
Signed-off-by: Edward Srouji <edwards@nvidia.com>
---
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c | 5 +++++
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 24 ++++++++++++++++++++++-
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h | 4 +++-
include/linux/mlx5/device.h | 3 +++
include/linux/mlx5/fs.h | 4 +++-
5 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
index 8af73393770c3c8eef2556efe591d5b712388aa6..fad0050c53a666da54c5d26e8d78bef917558b69 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
@@ -1016,6 +1016,10 @@ static int mlx5_cmd_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
max_actions = MLX5_CAP_FLOWTABLE_RDMA_TX(dev, max_modify_header_actions);
table_type = FS_FT_RDMA_TX;
break;
+ case MLX5_FLOW_NAMESPACE_NIC_RX_CLASS:
+ max_actions = MLX5_CAP_FLOWTABLE_NIC_RX_CLASS(dev, max_modify_header_actions);
+ table_type = FS_FT_NIC_RX_CLASS;
+ break;
default:
return -EOPNOTSUPP;
}
@@ -1177,6 +1181,7 @@ const struct mlx5_flow_cmds *mlx5_fs_cmd_get_default(enum fs_flow_table_type typ
case FS_FT_PORT_SEL:
case FS_FT_RDMA_TRANSPORT_RX:
case FS_FT_RDMA_TRANSPORT_TX:
+ case FS_FT_NIC_RX_CLASS:
return mlx5_fs_cmd_get_fw_cmds();
default:
return mlx5_fs_cmd_get_stub_cmds();
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 033ea5a198ee0d5a7e77ce0770f38bb8ffe97812..77985347e4f13831d7561094af2b2a998c345fcb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -2833,6 +2833,14 @@ mlx5_get_flow_vport_namespace(struct mlx5_core_dev *dev,
return &steering->rdma_transport_tx.root_ns[vport_idx]->ns;
else
return NULL;
+ case MLX5_FLOW_NAMESPACE_NIC_RX_CLASS:
+ if (vport_idx >= steering->nic_rx_class.vports)
+ return NULL;
+ if (steering->nic_rx_class.root_ns &&
+ steering->nic_rx_class.root_ns[vport_idx])
+ return &steering->nic_rx_class.root_ns[vport_idx]->ns;
+ else
+ return NULL;
default:
return NULL;
}
@@ -3304,6 +3312,10 @@ int mlx5_fs_set_root_dev(struct mlx5_core_dev *dev,
root = dev->priv.steering->rdma_transport_rx.root_ns;
total_vports = dev->priv.steering->rdma_transport_rx.vports;
break;
+ case FS_FT_NIC_RX_CLASS:
+ root = dev->priv.steering->nic_rx_class.root_ns;
+ total_vports = dev->priv.steering->nic_rx_class.vports;
+ break;
default:
WARN_ON_ONCE(true);
return -EINVAL;
@@ -3807,6 +3819,7 @@ void mlx5_fs_core_cleanup(struct mlx5_core_dev *dev)
cleanup_root_ns(steering->egress_root_ns);
cleanup_transport_manager_root_ns(&steering->rdma_transport_rx);
cleanup_transport_manager_root_ns(&steering->rdma_transport_tx);
+ cleanup_transport_manager_root_ns(&steering->nic_rx_class);
devl_params_unregister(priv_to_devlink(dev), mlx5_fs_params,
ARRAY_SIZE(mlx5_fs_params));
@@ -3892,6 +3905,14 @@ int mlx5_fs_core_init(struct mlx5_core_dev *dev)
goto err;
}
+ if (MLX5_CAP_FLOWTABLE_NIC_RX_CLASS(dev, ft_support)) {
+ err = init_transport_manager_root_ns(steering,
+ &steering->nic_rx_class,
+ FS_FT_NIC_RX_CLASS);
+ if (err)
+ goto err;
+ }
+
xa_init(&steering->esw_egress_root_ns);
xa_init(&steering->esw_ingress_root_ns);
return 0;
@@ -4048,7 +4069,8 @@ mlx5_get_root_namespace(struct mlx5_core_dev *dev, enum mlx5_flow_namespace_type
if (ns_type == MLX5_FLOW_NAMESPACE_ESW_EGRESS ||
ns_type == MLX5_FLOW_NAMESPACE_ESW_INGRESS ||
ns_type == MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_TX ||
- ns_type == MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_RX)
+ ns_type == MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_RX ||
+ ns_type == MLX5_FLOW_NAMESPACE_NIC_RX_CLASS)
ns = mlx5_get_flow_vport_namespace(dev, ns_type, 0);
else
ns = mlx5_get_flow_namespace(dev, ns_type);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
index e36735bea218c6909a6196305caa5c2aa5a83af6..1ef4201e0c5b2ee460bda1c3e79ee37b30291d4a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
@@ -148,6 +148,7 @@ struct mlx5_flow_steering {
struct mlx5_flow_root_namespace *port_sel_root_ns;
struct mlx5_transport_manager_ns rdma_transport_rx;
struct mlx5_transport_manager_ns rdma_transport_tx;
+ struct mlx5_transport_manager_ns nic_rx_class;
};
struct fs_node {
@@ -420,7 +421,8 @@ int mlx5_fs_get_packet_reformat_id(struct mlx5_pkt_reformat *pkt_reformat,
(type == FS_FT_FDB_TX) ? MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, cap) : \
(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))\
+ (type == FS_FT_NIC_RX_CLASS) ? MLX5_CAP_FLOWTABLE_NIC_RX_CLASS(mdev, cap) : \
+ (BUILD_BUG_ON_ZERO(FS_FT_NIC_RX_CLASS != FS_FT_MAX_TYPE))\
)
#endif
diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h
index 37727b5ab78f25df35b07536e106125e2167f20d..b82cf2d6330c612d4cacdda22ed6fdbf1163548c 100644
--- a/include/linux/mlx5/device.h
+++ b/include/linux/mlx5/device.h
@@ -1155,6 +1155,9 @@ enum mlx5_qcam_feature_groups {
#define MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_TX(mdev, cap) \
MLX5_CAP_ADV_RDMA(mdev, rdma_transport_tx_flow_table_properties.cap)
+#define MLX5_CAP_FLOWTABLE_NIC_RX_CLASS(mdev, cap) \
+ MLX5_CAP_ADV_RDMA(mdev, nic_rx_class_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)
diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h
index d8f3b7ef319e192cc9fa895be8d0735c2df4463a..4a868005a36e077655bdb26dfffe1441f5c4e208 100644
--- a/include/linux/mlx5/fs.h
+++ b/include/linux/mlx5/fs.h
@@ -115,6 +115,7 @@ enum mlx5_flow_namespace_type {
MLX5_FLOW_NAMESPACE_RDMA_TX_MACSEC,
MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_RX,
MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_TX,
+ MLX5_FLOW_NAMESPACE_NIC_RX_CLASS,
};
enum {
@@ -145,7 +146,8 @@ enum fs_flow_table_type {
FS_FT_FDB_TX = 0xb,
FS_FT_RDMA_TRANSPORT_RX = 0xd,
FS_FT_RDMA_TRANSPORT_TX = 0xe,
- FS_FT_MAX_TYPE = FS_FT_RDMA_TRANSPORT_TX,
+ FS_FT_NIC_RX_CLASS = 0xf,
+ FS_FT_MAX_TYPE = FS_FT_NIC_RX_CLASS,
};
struct mlx5_pkt_reformat;
--
2.49.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH rdma-next 5/5] RDMA/mlx5: Expose NIC_RX_CLASS flow table type to userspace
2026-11-03 18:12 [PATCH rdma-next 0/5] RDMA/mlx5: Add NIC_RX_CLASS steering domain for RDMA classification Edward Srouji
` (3 preceding siblings ...)
2026-11-03 18:12 ` [PATCH mlx5-next 4/5] net/mlx5: fs, add NIC_RX_CLASS steering domain support Edward Srouji
@ 2026-11-03 18:12 ` Edward Srouji
4 siblings, 0 replies; 6+ messages in thread
From: Edward Srouji @ 2026-11-03 18:12 UTC (permalink / raw)
To: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Jason Gunthorpe, Yishai Hadas
Cc: Edward Srouji, linux-rdma, netdev, linux-kernel, Mark Bloch,
Michael Gur, Patrisious Haddad
From: Michael Gur <michaelgur@nvidia.com>
Let userspace create matchers and rules against the new NIC_RX_CLASS
domain, the same way it already can for RDMA_TRANSPORT_RX/TX: the same
per-vport ib_port targeting and eswitch-manager ownership model.
Classification only tags a packet: a rule matches it, optionally
rewrites it with a MODIFY_HEADER action to mark it as RDMA, and lets it
continue down the RX pipe rather than steering it to a destination of
its own. ALLOW says exactly that. It is the rule's terminal action,
telling the device to proceed to the next steering domain, so a
NIC_RX_CLASS rule carries no destination. A flow counter may be
attached alongside it.
Expose ALLOW to userspace as a new flag, matching FW's ALLOW FTE action.
It is limited to NIC_RX_CLASS: no other namespace's rule creation
accepts it, since its driver-side handling and uapi flag are only
meaningful in terms of this domain's semantics today.
Signed-off-by: Michael Gur <michaelgur@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Reviewed-by: Patrisious Haddad <phaddad@nvidia.com>
Signed-off-by: Edward Srouji <edwards@nvidia.com>
---
drivers/infiniband/hw/mlx5/fs.c | 59 ++++++++++++++++++++++++++-----
drivers/infiniband/hw/mlx5/fs.h | 2 ++
drivers/infiniband/hw/mlx5/ib_rep.c | 25 +++++++++----
drivers/infiniband/hw/mlx5/mlx5_ib.h | 1 +
include/uapi/rdma/mlx5_user_ioctl_cmds.h | 1 +
include/uapi/rdma/mlx5_user_ioctl_verbs.h | 1 +
6 files changed, 74 insertions(+), 15 deletions(-)
diff --git a/drivers/infiniband/hw/mlx5/fs.c b/drivers/infiniband/hw/mlx5/fs.c
index bc2c15c7172baf3ee726e6b1a9bf794e4c982a35..07486885e046a9a527371160206d3cb2d911b6c4 100644
--- a/drivers/infiniband/hw/mlx5/fs.c
+++ b/drivers/infiniband/hw/mlx5/fs.c
@@ -1967,8 +1967,8 @@ _get_flow_table(struct mlx5_ib_dev *dev, u16 user_priority,
break;
case MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_RX:
case MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_TX:
- if (ib_port == 0 ||
- user_priority >= MLX5_RDMA_TRANSPORT_BYPASS_PRIO)
+ case MLX5_FLOW_NAMESPACE_NIC_RX_CLASS:
+ if (ib_port == 0 || user_priority >= MLX5_RDMA_TRANSPORT_BYPASS_PRIO)
return ERR_PTR(-EINVAL);
ret = mlx5_ib_fill_transport_ns_info(dev, ns_type, &flags,
&vport_idx, &vport,
@@ -1981,10 +1981,14 @@ _get_flow_table(struct mlx5_ib_dev *dev, u16 user_priority,
max_table_size =
BIT(MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_RX(
ft_mdev, log_max_ft_size));
- else
+ else if (ns_type == MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_TX)
max_table_size =
BIT(MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_TX(
ft_mdev, log_max_ft_size));
+ else
+ max_table_size =
+ BIT(MLX5_CAP_FLOWTABLE_NIC_RX_CLASS(
+ ft_mdev, log_max_ft_size));
priority = user_priority;
break;
default:
@@ -1994,7 +1998,8 @@ _get_flow_table(struct mlx5_ib_dev *dev, u16 user_priority,
max_table_size = min_t(int, max_table_size, MLX5_FS_MAX_ENTRIES);
if (ns_type == MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_RX ||
- ns_type == MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_TX)
+ ns_type == MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_TX ||
+ ns_type == MLX5_FLOW_NAMESPACE_NIC_RX_CLASS)
ns = mlx5_get_flow_vport_namespace(ft_mdev, ns_type, vport_idx);
else
ns = mlx5_get_flow_namespace(ft_mdev, ns_type);
@@ -2024,6 +2029,9 @@ _get_flow_table(struct mlx5_ib_dev *dev, u16 user_priority,
case MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_TX:
prio = &dev->flow_db->rdma_transport_tx[priority][ib_port - 1];
break;
+ case MLX5_FLOW_NAMESPACE_NIC_RX_CLASS:
+ prio = &dev->flow_db->nic_rx_class[priority][ib_port - 1];
+ break;
default: return ERR_PTR(-EINVAL);
}
@@ -2281,6 +2289,9 @@ mlx5_ib_ft_type_to_namespace(enum mlx5_ib_uapi_flow_table_type table_type,
case MLX5_IB_UAPI_FLOW_TABLE_TYPE_RDMA_TRANSPORT_TX:
*namespace = MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_TX;
break;
+ case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX_CLASS:
+ *namespace = MLX5_FLOW_NAMESPACE_NIC_RX_CLASS;
+ break;
default:
return -EINVAL;
}
@@ -2348,7 +2359,8 @@ static int get_dests(struct uverbs_attr_bundle *attrs,
*flags = 0;
err = uverbs_get_flags32(flags, attrs, MLX5_IB_ATTR_CREATE_FLOW_FLAGS,
MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DEFAULT_MISS |
- MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP);
+ MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP |
+ MLX5_IB_ATTR_CREATE_FLOW_FLAGS_ALLOW);
if (err)
return err;
@@ -2357,6 +2369,21 @@ static int get_dests(struct uverbs_attr_bundle *attrs,
*flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP)
return -EINVAL;
+ /* NIC_RX_CLASS only classifies packets into the RDMA path: it takes
+ * no destination, and ALLOW is its only terminal action.
+ */
+ if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_NIC_RX_CLASS) {
+ if (dest_qp || dest_devx ||
+ *flags != MLX5_IB_ATTR_CREATE_FLOW_FLAGS_ALLOW)
+ return -EINVAL;
+
+ *dest_type = MLX5_FLOW_DESTINATION_TYPE_NONE;
+ return 0;
+ } else if (*flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_ALLOW) {
+ /* ALLOW is only supported for NIC_RX_CLASS */
+ return -EINVAL;
+ }
+
if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_BYPASS) {
if (dest_devx && (dest_qp || *flags))
return -EINVAL;
@@ -2477,6 +2504,9 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
if (get_dests(attrs, fs_matcher, &dest_id, &dest_type, &qp, &flags))
return -EINVAL;
+ if (flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_ALLOW)
+ flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW;
+
if (flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DEFAULT_MISS)
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS;
@@ -2963,7 +2993,8 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)(
goto end;
}
if (obj->ns_type != MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_RX &&
- obj->ns_type != MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_TX) {
+ obj->ns_type != MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_TX &&
+ obj->ns_type != MLX5_FLOW_NAMESPACE_NIC_RX_CLASS) {
err = -EINVAL;
goto end;
}
@@ -3106,7 +3137,9 @@ static bool mlx5_ib_modify_header_supported(struct mlx5_ib_dev *dev)
MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev,
max_modify_header_actions) ||
MLX5_CAP_FLOWTABLE_RDMA_TX(dev->mdev,
- max_modify_header_actions);
+ max_modify_header_actions) ||
+ MLX5_CAP_FLOWTABLE_NIC_RX_CLASS(dev->mdev,
+ max_modify_header_actions);
}
static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER)(
@@ -3477,7 +3510,7 @@ static const struct ib_device_ops flow_ops = {
int mlx5_ib_fs_init(struct mlx5_ib_dev *dev)
{
- int i, j;
+ int i, j, k;
dev->flow_db = kzalloc_obj(*dev->flow_db);
@@ -3498,11 +3531,21 @@ int mlx5_ib_fs_init(struct mlx5_ib_dev *dev)
goto free_rdma_transport_tx;
}
+ for (k = 0; k < MLX5_RDMA_TRANSPORT_BYPASS_PRIO; k++) {
+ dev->flow_db->nic_rx_class[k] =
+ kzalloc_objs(struct mlx5_ib_flow_prio, dev->num_ports);
+ if (!dev->flow_db->nic_rx_class[k])
+ goto free_nic_rx_class;
+ }
+
mutex_init(&dev->flow_db->lock);
ib_set_device_ops(&dev->ib_dev, &flow_ops);
return 0;
+free_nic_rx_class:
+ while (k--)
+ kfree(dev->flow_db->nic_rx_class[k]);
free_rdma_transport_tx:
while (j--)
kfree(dev->flow_db->rdma_transport_tx[j]);
diff --git a/drivers/infiniband/hw/mlx5/fs.h b/drivers/infiniband/hw/mlx5/fs.h
index 7abba0e2837cf8a8d40053b7855faba8224fae8d..9d6f966fa4194053362429d2797fb137d674cb5b 100644
--- a/drivers/infiniband/hw/mlx5/fs.h
+++ b/drivers/infiniband/hw/mlx5/fs.h
@@ -31,6 +31,8 @@ static inline void mlx5_ib_fs_cleanup(struct mlx5_ib_dev *dev)
kfree(dev->flow_db->rdma_transport_tx[i]);
for (i = 0; i < MLX5_RDMA_TRANSPORT_BYPASS_PRIO; i++)
kfree(dev->flow_db->rdma_transport_rx[i]);
+ for (i = 0; i < MLX5_RDMA_TRANSPORT_BYPASS_PRIO; i++)
+ kfree(dev->flow_db->nic_rx_class[i]);
kfree(dev->flow_db);
}
#endif /* _MLX5_IB_FS_H */
diff --git a/drivers/infiniband/hw/mlx5/ib_rep.c b/drivers/infiniband/hw/mlx5/ib_rep.c
index 65d8767d1830c630f5aa2a2a693110e2c9bc9e48..249acc9b7cd55b88fdded606b0037fd88b0edc4c 100644
--- a/drivers/infiniband/hw/mlx5/ib_rep.c
+++ b/drivers/infiniband/hw/mlx5/ib_rep.c
@@ -62,8 +62,12 @@ static int mlx5_ib_set_owner_transport(struct mlx5_core_dev *cur_owner,
{
int ret;
- if (!MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_TX(cur_owner, ft_support) ||
- !MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_RX(cur_owner, ft_support))
+ /* Each of these three domains is independently capable; only bail
+ * out early if cur_owner supports none of them.
+ */
+ if (!MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_TX(cur_owner, ft_support) &&
+ !MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_RX(cur_owner, ft_support) &&
+ !MLX5_CAP_FLOWTABLE_NIC_RX_CLASS(cur_owner, ft_support))
return 0;
if (!MLX5_CAP_ADV_RDMA(new_owner, rdma_transport_manager) ||
@@ -77,13 +81,20 @@ static int mlx5_ib_set_owner_transport(struct mlx5_core_dev *cur_owner,
ret = mlx5_fs_set_root_dev(cur_owner, new_owner,
FS_FT_RDMA_TRANSPORT_RX);
- if (ret) {
- mlx5_fs_set_root_dev(cur_owner, cur_owner,
- FS_FT_RDMA_TRANSPORT_TX);
- return ret;
- }
+ if (ret)
+ goto err_rx;
+
+ ret = mlx5_fs_set_root_dev(cur_owner, new_owner, FS_FT_NIC_RX_CLASS);
+ if (ret)
+ goto err_nic_rx_class;
return 0;
+
+err_nic_rx_class:
+ mlx5_fs_set_root_dev(cur_owner, cur_owner, FS_FT_RDMA_TRANSPORT_RX);
+err_rx:
+ mlx5_fs_set_root_dev(cur_owner, cur_owner, FS_FT_RDMA_TRANSPORT_TX);
+ return ret;
}
static void mlx5_ib_release_transport(struct mlx5_core_dev *dev)
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 4a6ee14ffd7d1deaa82754cda088b2c67c7575d1..5f444044ada3aa5f1d3c75c5ccfb9c34f4a84e93 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -310,6 +310,7 @@ struct mlx5_ib_flow_db {
struct mlx5_ib_flow_prio opfcs[MLX5_IB_OPCOUNTER_MAX];
struct mlx5_ib_flow_prio *rdma_transport_rx[MLX5_RDMA_TRANSPORT_BYPASS_PRIO];
struct mlx5_ib_flow_prio *rdma_transport_tx[MLX5_RDMA_TRANSPORT_BYPASS_PRIO];
+ struct mlx5_ib_flow_prio *nic_rx_class[MLX5_RDMA_TRANSPORT_BYPASS_PRIO];
/* Protect flow steering bypass flow tables
* when add/del flow rules.
* only single add/removal of flow steering rule could be done
diff --git a/include/uapi/rdma/mlx5_user_ioctl_cmds.h b/include/uapi/rdma/mlx5_user_ioctl_cmds.h
index 3528743e385865aeb69fce16a491c32b9968ff17..ba0d3435c7d33b6afa202815a146bdefe6064bfa 100644
--- a/include/uapi/rdma/mlx5_user_ioctl_cmds.h
+++ b/include/uapi/rdma/mlx5_user_ioctl_cmds.h
@@ -305,6 +305,7 @@ enum mlx5_ib_flow_type {
enum mlx5_ib_create_flow_flags {
MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DEFAULT_MISS = 1 << 0,
MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP = 1 << 1,
+ MLX5_IB_ATTR_CREATE_FLOW_FLAGS_ALLOW = 1 << 2,
};
enum mlx5_ib_create_flow_attrs {
diff --git a/include/uapi/rdma/mlx5_user_ioctl_verbs.h b/include/uapi/rdma/mlx5_user_ioctl_verbs.h
index ef295b38a1cfb371922eb99ffb6c44886fb4f7be..ddf05cdae8ebdda544672f370981f582a6d90340 100644
--- a/include/uapi/rdma/mlx5_user_ioctl_verbs.h
+++ b/include/uapi/rdma/mlx5_user_ioctl_verbs.h
@@ -47,6 +47,7 @@ enum mlx5_ib_uapi_flow_table_type {
MLX5_IB_UAPI_FLOW_TABLE_TYPE_RDMA_TX = 0x4,
MLX5_IB_UAPI_FLOW_TABLE_TYPE_RDMA_TRANSPORT_RX = 0x5,
MLX5_IB_UAPI_FLOW_TABLE_TYPE_RDMA_TRANSPORT_TX = 0x6,
+ MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX_CLASS = 0x7,
};
enum mlx5_ib_uapi_flow_action_packet_reformat_type {
--
2.49.0
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-11-03 18:13 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-03 18:12 [PATCH rdma-next 0/5] RDMA/mlx5: Add NIC_RX_CLASS steering domain for RDMA classification Edward Srouji
2026-11-03 18:12 ` [PATCH mlx5-next 1/5] net/mlx5: Add NIC_RX_CLASS IFC bits Edward Srouji
2026-11-03 18:12 ` [PATCH mlx5-next 2/5] net/mlx5: fs, treat ALLOW as a conflicting action upon merge Edward Srouji
2026-11-03 18:12 ` [PATCH mlx5-next 3/5] net/mlx5: fs, refactor RDMA transport manager root namespace init/cleanup Edward Srouji
2026-11-03 18:12 ` [PATCH mlx5-next 4/5] net/mlx5: fs, add NIC_RX_CLASS steering domain support Edward Srouji
2026-11-03 18:12 ` [PATCH rdma-next 5/5] RDMA/mlx5: Expose NIC_RX_CLASS flow table type to userspace Edward Srouji
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®