[PATCH mlx5-next 4/5] net/mlx5: fs, add NIC_RX_CLASS steering domain support

From: Edward Srouji

Date: Tue Nov 03 2026 - 13:15:58 EST


From: Michael Gur <michaelgur@xxxxxxxxxx>

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@xxxxxxxxxx>
Reviewed-by: Mark Bloch <mbloch@xxxxxxxxxx>
Reviewed-by: Patrisious Haddad <phaddad@xxxxxxxxxx>
Signed-off-by: Edward Srouji <edwards@xxxxxxxxxx>
---
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