mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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


      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®