From: Edward Srouji <edwards@nvidia.com>
To: Saeed Mahameed <saeedm@nvidia.com>,
Leon Romanovsky <leon@kernel.org>,
Tariq Toukan <tariqt@nvidia.com>, Mark Bloch <mbloch@nvidia.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
"Eric Dumazet" <edumazet@kernel.org>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Jason Gunthorpe <jgg@ziepe.ca>,
Yishai Hadas <yishaih@mellanox.com>
Cc: Edward Srouji <edwards@nvidia.com>, <linux-rdma@vger.kernel.org>,
<netdev@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
Mark Bloch <markb@mellanox.com>,
Michael Gur <michaelgur@nvidia.com>,
Patrisious Haddad <phaddad@nvidia.com>
Subject: [PATCH rdma-next 5/5] RDMA/mlx5: Expose NIC_RX_CLASS flow table type to userspace
Date: Tue, 3 Nov 2026 20:12:53 +0200 [thread overview]
Message-ID: <20261103-rdma-rx-classifier-v1-5-1ad6c8cfe936@nvidia.com> (raw)
In-Reply-To: <20261103-rdma-rx-classifier-v1-0-1ad6c8cfe936@nvidia.com>
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
prev parent reply other threads:[~2026-11-03 18:13 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
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 ` Edward Srouji [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261103-rdma-rx-classifier-v1-5-1ad6c8cfe936@nvidia.com \
--to=edwards@nvidia.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=jgg@ziepe.ca \
--cc=kuba@kernel.org \
--cc=leon@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=markb@mellanox.com \
--cc=mbloch@nvidia.com \
--cc=michaelgur@nvidia.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=phaddad@nvidia.com \
--cc=saeedm@nvidia.com \
--cc=tariqt@nvidia.com \
--cc=yishaih@mellanox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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®