public inbox for dev@dpdk.org
 help / color / mirror / Atom feed
* [PATCH 26.07 0/5] net/mlx5: legacy vport match support with HWS
@ 2026-03-25  9:07 Dariusz Sosnowski
  2026-03-25  9:07 ` [PATCH 26.07 1/5] common/mlx5: query vport VHCA ID Dariusz Sosnowski
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Dariusz Sosnowski @ 2026-03-25  9:07 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Bing Zhao, Ori Kam, Suanming Mou,
	Matan Azrad; +Cc: dev

NVIDIA NICs and DPUs have an embedded switch (E-Switch)
to which all associated functions (PFs, VFs, SFs) and physical ports
are connected through virtual ports (vports).
mlx5 PMD supports devices with E-Switch enabled and
also exposes flow rule offloading to the E-Switch
through transfer flow rules.

Flow rules matching on vports (with flow item REPRESENTED_PORT)
can match on specific vport using one of the two internal mechanisms:

- vport metadata - E-Switch internally tags all packets with a metadata value
  associated with originating vport.
  mlx5 PMD can match on that metadata through a specialized HW register in each flow rule.
  vport metadata enables features such as VF-LAG, Multiport E-Switch and
  others mentioned in [1].
- legacy match - A static value known as "source vport" is assigned to each vport.
  These values are not globally unique, because they are statically assigned per E-Switch
  (e.g., VF0 on each of the PFs will have the same source_vport number).

Users can select the vport matching mode through devlink [1].
vport metadata matching mode is the default and is enough for most of the use cases.
However, internally tagging all the packets with metadata values,
increases the packet latency in the E-Switch. As described in the linked kernel docs,
disabling vport metadata matching can increase packet rate up to 20%.
If features provided by vport metadata matching are not required,
it can be disabled to increase E-Switch's throughput.

mlx5 PMD with HW Steering flow engine enabled, only supported
vport metadata mode when running on a device with enabled E-Switch.
Goal of this patchset is to enable support of devices with
disabled vport metadata matching. This is purely an internal change in mlx5 PMD.
No changes in DPDK applications should be required.

- Patches 1-2 - Extend information queried from the device by mlx5 PMD
  to include information necessary to implement legacy vport match.
  This data is always available, regardless of selected E-Switch matching mode.
- Patch 3 - Adjusts internal translation of DPDK port ID to flow rule matching data,
  so that returned data is always valid even if vport metadata matching is disabled.
  Also adds detection of vport matching mode to HWS layer.
- Patch 4 - Adds support for REPRESENTED_PORT item in HWS layer
  whenever vport metadata matching mode is disabled.
  This involves correctly translating DPDK port index to "source vport".
- Patch 5 - Removes all validation checks from mlx5 PMD which prevented probing
  on devices with disabled vport metadata matching mode.
  Adjusts internal PMD logic to work with "source vport" whenever needed.

[1]: https://docs.kernel.org/networking/devlink/mlx5.html

Dariusz Sosnowski (5):
  common/mlx5: query vport VHCA ID
  net/mlx5: store port VHCA ID
  net/mlx5: return port info regardless of register mask
  net/mlx5/hws: add source vport match in HWS
  net/mlx5: allow legacy source vport match

 drivers/common/mlx5/linux/mlx5_glue.c |  4 ++
 drivers/common/mlx5/linux/mlx5_glue.h |  2 +
 drivers/net/mlx5/hws/mlx5dr_cmd.c     | 13 +++-
 drivers/net/mlx5/hws/mlx5dr_cmd.h     |  1 +
 drivers/net/mlx5/hws/mlx5dr_definer.c | 99 ++++++++++++++++++++++-----
 drivers/net/mlx5/hws/mlx5dr_definer.h |  2 +
 drivers/net/mlx5/hws/mlx5dr_table.c   |  6 ++
 drivers/net/mlx5/linux/mlx5_os.c      | 38 +++-------
 drivers/net/mlx5/mlx5.h               |  4 ++
 drivers/net/mlx5/mlx5_flow.h          |  3 +-
 drivers/net/mlx5/mlx5_flow_dv.c       |  3 +
 drivers/net/mlx5/mlx5_flow_hw.c       | 34 ++++-----
 12 files changed, 140 insertions(+), 69 deletions(-)

--
2.47.3


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 26.07 1/5] common/mlx5: query vport VHCA ID
  2026-03-25  9:07 [PATCH 26.07 0/5] net/mlx5: legacy vport match support with HWS Dariusz Sosnowski
@ 2026-03-25  9:07 ` Dariusz Sosnowski
  2026-03-25  9:07 ` [PATCH 26.07 2/5] net/mlx5: store port " Dariusz Sosnowski
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Dariusz Sosnowski @ 2026-03-25  9:07 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Bing Zhao, Ori Kam, Suanming Mou,
	Matan Azrad; +Cc: dev

Extend port info returned by mlx5_glue_devx_port_query()
with VHCA ID of the device related to the IB port.
This ID will be later used to implement source vport matching
without E-Switch vport metadata enabled.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
 drivers/common/mlx5/linux/mlx5_glue.c | 4 ++++
 drivers/common/mlx5/linux/mlx5_glue.h | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/drivers/common/mlx5/linux/mlx5_glue.c b/drivers/common/mlx5/linux/mlx5_glue.c
index a91eaa429d..56eaedf0a2 100644
--- a/drivers/common/mlx5/linux/mlx5_glue.c
+++ b/drivers/common/mlx5/linux/mlx5_glue.c
@@ -1263,6 +1263,10 @@ mlx5_glue_devx_port_query(struct ibv_context *ctx,
 		info->vport_id = devx_port.vport;
 		info->query_flags |= MLX5_PORT_QUERY_VPORT;
 	}
+	if (devx_port.flags & MLX5DV_QUERY_PORT_VPORT_VHCA_ID) {
+		info->vport_vhca_id = devx_port.vport_vhca_id;
+		info->query_flags |= MLX5_PORT_QUERY_VPORT_VHCA_ID;
+	}
 	if (devx_port.flags & MLX5DV_QUERY_PORT_ESW_OWNER_VHCA_ID) {
 		info->esw_owner_vhca_id = devx_port.esw_owner_vhca_id;
 		info->query_flags |= MLX5_PORT_QUERY_ESW_OWNER_VHCA_ID;
diff --git a/drivers/common/mlx5/linux/mlx5_glue.h b/drivers/common/mlx5/linux/mlx5_glue.h
index 81d6b0aaf9..0610e7778e 100644
--- a/drivers/common/mlx5/linux/mlx5_glue.h
+++ b/drivers/common/mlx5/linux/mlx5_glue.h
@@ -92,11 +92,13 @@ struct mlx5dv_port;
 #define MLX5_PORT_QUERY_VPORT (1u << 0)
 #define MLX5_PORT_QUERY_REG_C0 (1u << 1)
 #define MLX5_PORT_QUERY_ESW_OWNER_VHCA_ID (1u << 2)
+#define MLX5_PORT_QUERY_VPORT_VHCA_ID (1u << 3)
 
 struct mlx5_port_info {
 	uint16_t query_flags;
 	uint16_t vport_id; /* Associated VF vport index (if any). */
 	uint16_t esw_owner_vhca_id; /* Associated the esw_owner that this VF belongs to. */
+	uint16_t vport_vhca_id; /* VHCA ID of the function associated with the vport. */
 	uint32_t vport_meta_tag; /* Used for vport index match ove VF LAG. */
 	uint32_t vport_meta_mask; /* Used for vport index field match mask. */
 };
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 26.07 2/5] net/mlx5: store port VHCA ID
  2026-03-25  9:07 [PATCH 26.07 0/5] net/mlx5: legacy vport match support with HWS Dariusz Sosnowski
  2026-03-25  9:07 ` [PATCH 26.07 1/5] common/mlx5: query vport VHCA ID Dariusz Sosnowski
@ 2026-03-25  9:07 ` Dariusz Sosnowski
  2026-03-25  9:07 ` [PATCH 26.07 3/5] net/mlx5: return port info regardless of register mask Dariusz Sosnowski
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Dariusz Sosnowski @ 2026-03-25  9:07 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Bing Zhao, Ori Kam, Suanming Mou,
	Matan Azrad; +Cc: dev

Save VHCA ID (if available) of each mlx5 port and
of E-Switch Manager, and update port info cache
(mlx5_flow_hw_port_infos array) used for translating
DPDK port ID into HW matching value and mask,
when matching on source vport.

This data will be later used to implement source vport matching
without E-Switch vport metadata enabled.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
 drivers/net/mlx5/linux/mlx5_os.c | 3 +++
 drivers/net/mlx5/mlx5.h          | 2 ++
 drivers/net/mlx5/mlx5_flow_hw.c  | 5 ++---
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index a717191002..3a9b019601 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -377,6 +377,7 @@ mlx5_os_capabilities_prepare(struct mlx5_dev_ctx_shared *sh)
 					hca_attr->scatter_fcs_w_decap_disable;
 	sh->dev_cap.rq_delay_drop_en = hca_attr->rq_delay_drop;
 	mlx5_rt_timestamp_config(sh, hca_attr);
+	sh->dev_cap.esw_info.vhca_id = hca_attr->vhca_id;
 #ifdef HAVE_IBV_DEVICE_ATTR_ESW_MGR_REG_C0
 	if (dv_attr.comp_mask & MLX5DV_CONTEXT_MASK_REG_C0) {
 		sh->dev_cap.esw_info.regc_value = dv_attr.reg_c0.value;
@@ -1524,6 +1525,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 			goto error;
 		}
 	}
+	if (vport_info.query_flags & MLX5_PORT_QUERY_VPORT_VHCA_ID)
+		priv->vport_vhca_id = vport_info.vport_vhca_id;
 	if (vport_info.query_flags & MLX5_PORT_QUERY_VPORT) {
 		priv->vport_id = vport_info.vport_id;
 	} else if (spawn->pf_bond >= 0 && sh->esw_mode) {
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 4da184eb47..7ae9129e46 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -152,6 +152,7 @@ struct mlx5_flow_cb_ctx {
 struct flow_hw_port_info {
 	uint32_t regc_mask;
 	uint32_t regc_value;
+	uint32_t vhca_id;
 	uint32_t is_wire:1;
 	uint32_t direction:2;
 };
@@ -2003,6 +2004,7 @@ struct mlx5_priv {
 	uint32_t jump_fdb_rx_en:1; /* Jump from FDB Tx to FDB Rx flag per port. */
 	uint16_t domain_id; /* Switch domain identifier. */
 	uint16_t vport_id; /* Associated VF vport index (if any). */
+	uint16_t vport_vhca_id; /* VHCA ID of the associated vport (if any). */
 	uint32_t vport_meta_tag; /* Used for vport index match ove VF LAG. */
 	uint32_t vport_meta_mask; /* Used for vport index field match mask. */
 	uint16_t representor_id; /* UINT16_MAX if not a representor. */
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index bca5b2769e..adbd4f33b0 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -12305,6 +12305,7 @@ mlx5_flow_hw_set_port_info(struct rte_eth_dev *dev)
 	info = &mlx5_flow_hw_port_infos[port_id];
 	info->regc_mask = priv->vport_meta_mask;
 	info->regc_value = priv->vport_meta_tag;
+	info->vhca_id = priv->vport_vhca_id;
 	info->is_wire = mlx5_is_port_on_mpesw_device(priv) ? priv->mpesw_uplink : priv->master;
 }
 
@@ -12317,9 +12318,7 @@ mlx5_flow_hw_clear_port_info(struct rte_eth_dev *dev)
 
 	MLX5_ASSERT(port_id < RTE_MAX_ETHPORTS);
 	info = &mlx5_flow_hw_port_infos[port_id];
-	info->regc_mask = 0;
-	info->regc_value = 0;
-	info->is_wire = 0;
+	memset(info, 0, sizeof(*info));
 }
 
 static int
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 26.07 3/5] net/mlx5: return port info regardless of register mask
  2026-03-25  9:07 [PATCH 26.07 0/5] net/mlx5: legacy vport match support with HWS Dariusz Sosnowski
  2026-03-25  9:07 ` [PATCH 26.07 1/5] common/mlx5: query vport VHCA ID Dariusz Sosnowski
  2026-03-25  9:07 ` [PATCH 26.07 2/5] net/mlx5: store port " Dariusz Sosnowski
@ 2026-03-25  9:07 ` Dariusz Sosnowski
  2026-03-25  9:07 ` [PATCH 26.07 4/5] net/mlx5/hws: add source vport match in HWS Dariusz Sosnowski
  2026-03-25  9:07 ` [PATCH 26.07 5/5] net/mlx5: allow legacy source vport match Dariusz Sosnowski
  4 siblings, 0 replies; 6+ messages in thread
From: Dariusz Sosnowski @ 2026-03-25  9:07 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Bing Zhao, Ori Kam, Suanming Mou,
	Matan Azrad; +Cc: dev

Previously if the port info did not have REG_C mask set,
flow_hw_conv_port_id() returned NULL.
In order to allow for support of legacy source vport match,
this patch changes that logic.

Now flow port info will be returned for all ports,
regardless of REG_C mask value.

HWS layer, depending on REG_C mask value (zero or non-zero)
will decide which matching mode should be used for
REPRESENTED_PORT items.
If REG_C mask is available, metadata matching will be used.
Otherwise, legacy source vport match will be used.
Definer handling for legacy source vport match
will be added in the follow up commit.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
 drivers/net/mlx5/hws/mlx5dr_cmd.c     | 13 +++++++--
 drivers/net/mlx5/hws/mlx5dr_cmd.h     |  1 +
 drivers/net/mlx5/hws/mlx5dr_definer.c | 38 ++++++++++++++++-----------
 drivers/net/mlx5/linux/mlx5_os.c      |  1 +
 drivers/net/mlx5/mlx5.h               |  1 +
 drivers/net/mlx5/mlx5_flow.h          |  3 ++-
 drivers/net/mlx5/mlx5_flow_hw.c       |  1 +
 7 files changed, 40 insertions(+), 18 deletions(-)

diff --git a/drivers/net/mlx5/hws/mlx5dr_cmd.c b/drivers/net/mlx5/hws/mlx5dr_cmd.c
index 47e6a1fd49..668e409988 100644
--- a/drivers/net/mlx5/hws/mlx5dr_cmd.c
+++ b/drivers/net/mlx5/hws/mlx5dr_cmd.c
@@ -1363,10 +1363,19 @@ int mlx5dr_cmd_query_caps(struct ibv_context *ctx,
 	strlcpy(caps->fw_ver, attr_ex.orig_attr.fw_ver, sizeof(caps->fw_ver));
 
 	port_info = flow_hw_get_wire_port(ctx);
-	if (port_info)
+	if (port_info) {
 		caps->wire_regc_mask = port_info->regc_mask;
-	else
+		/*
+		 * If REG_C_0 vport mask is available, then we can assume that vport metadata is
+		 * enabled on the switchdev.
+		 */
+		caps->vport_metadata_match = !!port_info->regc_mask;
+		DR_LOG(DEBUG, "ibdev %s vport metadata match is %sabled",
+		       ctx->device->name,
+		       caps->vport_metadata_match ? "en" : "dis");
+	} else {
 		DR_LOG(INFO, "Failed to query wire port regc value");
+	}
 
 	return ret;
 }
diff --git a/drivers/net/mlx5/hws/mlx5dr_cmd.h b/drivers/net/mlx5/hws/mlx5dr_cmd.h
index eb9643c555..3ed7c6ecb7 100644
--- a/drivers/net/mlx5/hws/mlx5dr_cmd.h
+++ b/drivers/net/mlx5/hws/mlx5dr_cmd.h
@@ -207,6 +207,7 @@ struct mlx5dr_cmd_generate_wqe_attr {
 
 struct mlx5dr_cmd_query_caps {
 	uint32_t wire_regc_mask;
+	bool vport_metadata_match;
 	uint32_t flex_protocols;
 	uint8_t wqe_based_update;
 	uint8_t rtc_reparse_mode;
diff --git a/drivers/net/mlx5/hws/mlx5dr_definer.c b/drivers/net/mlx5/hws/mlx5dr_definer.c
index 6a016de78e..3ba69c1001 100644
--- a/drivers/net/mlx5/hws/mlx5dr_definer.c
+++ b/drivers/net/mlx5/hws/mlx5dr_definer.c
@@ -777,12 +777,13 @@ mlx5dr_definer_vport_set(struct mlx5dr_definer_fc *fc,
 	const struct flow_hw_port_info *port_info = NULL;
 	uint32_t regc_value;
 
-	if (v)
+	if (v) {
 		port_info = flow_hw_conv_port_id(fc->dr_ctx, v->port_id);
-	if (unlikely(!port_info))
-		regc_value = BAD_PORT;
-	else
+		assert(port_info != NULL);
 		regc_value = port_info->regc_value >> fc->bit_off;
+	} else {
+		regc_value = BAD_PORT;
+	}
 
 	/* Bit offset is set to 0 to since regc value is 32bit */
 	DR_SET(tag, regc_value, fc->byte_off, fc->bit_off, fc->bit_mask);
@@ -1593,20 +1594,27 @@ mlx5dr_definer_conv_item_port(struct mlx5dr_definer_conv_data *cd,
 	struct mlx5dr_definer_fc *fc;
 
 	if (port_id) {
-		if (!caps->wire_regc_mask) {
-			DR_LOG(ERR, "Port ID item not supported, missing wire REGC mask");
+		if (caps->vport_metadata_match) {
+			if (!caps->wire_regc_mask) {
+				DR_LOG(ERR, "Port ID item not supported, missing wire REGC mask");
+				rte_errno = ENOTSUP;
+				return rte_errno;
+			}
+
+			fc = &cd->fc[MLX5DR_DEFINER_FNAME_VPORT_REG_C_0];
+			fc->item_idx = item_idx;
+			fc->tag_set = &mlx5dr_definer_vport_set;
+			fc->tag_mask_set = &mlx5dr_definer_ones_set;
+			DR_CALC_SET_HDR(fc, registers, register_c_0);
+			fc->bit_off = rte_ctz32(caps->wire_regc_mask);
+			fc->bit_mask = caps->wire_regc_mask >> fc->bit_off;
+			fc->dr_ctx = cd->ctx;
+		} else {
+			/* TODO */
+			DR_LOG(ERR, "Port ID item with legacy vport match is not implemented");
 			rte_errno = ENOTSUP;
 			return rte_errno;
 		}
-
-		fc = &cd->fc[MLX5DR_DEFINER_FNAME_VPORT_REG_C_0];
-		fc->item_idx = item_idx;
-		fc->tag_set = &mlx5dr_definer_vport_set;
-		fc->tag_mask_set = &mlx5dr_definer_ones_set;
-		DR_CALC_SET_HDR(fc, registers, register_c_0);
-		fc->bit_off = rte_ctz32(caps->wire_regc_mask);
-		fc->bit_mask = caps->wire_regc_mask >> fc->bit_off;
-		fc->dr_ctx = cd->ctx;
 	}
 
 	return 0;
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 3a9b019601..75a2936023 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -387,6 +387,7 @@ mlx5_os_capabilities_prepare(struct mlx5_dev_ctx_shared *sh)
 	sh->dev_cap.esw_info.regc_value = 0;
 	sh->dev_cap.esw_info.regc_mask = 0;
 #endif
+	sh->dev_cap.esw_info.is_set = 1;
 	return 0;
 }
 
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 7ae9129e46..8cd6562633 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -153,6 +153,7 @@ struct flow_hw_port_info {
 	uint32_t regc_mask;
 	uint32_t regc_value;
 	uint32_t vhca_id;
+	uint32_t is_set:1;
 	uint32_t is_wire:1;
 	uint32_t direction:2;
 };
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 4c56e638ab..c9e72a33d6 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -2156,8 +2156,9 @@ flow_hw_conv_port_id(void *ctx, const uint16_t port_id)
 
 	if (port_id >= RTE_MAX_ETHPORTS)
 		return NULL;
+
 	port_info = &mlx5_flow_hw_port_infos[port_id];
-	return !!port_info->regc_mask ? port_info : NULL;
+	return port_info->is_set ? port_info : NULL;
 }
 
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index adbd4f33b0..4871594c35 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -12307,6 +12307,7 @@ mlx5_flow_hw_set_port_info(struct rte_eth_dev *dev)
 	info->regc_value = priv->vport_meta_tag;
 	info->vhca_id = priv->vport_vhca_id;
 	info->is_wire = mlx5_is_port_on_mpesw_device(priv) ? priv->mpesw_uplink : priv->master;
+	info->is_set = 1;
 }
 
 /* Clears vport tag and mask used for HWS rules. */
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 26.07 4/5] net/mlx5/hws: add source vport match in HWS
  2026-03-25  9:07 [PATCH 26.07 0/5] net/mlx5: legacy vport match support with HWS Dariusz Sosnowski
                   ` (2 preceding siblings ...)
  2026-03-25  9:07 ` [PATCH 26.07 3/5] net/mlx5: return port info regardless of register mask Dariusz Sosnowski
@ 2026-03-25  9:07 ` Dariusz Sosnowski
  2026-03-25  9:07 ` [PATCH 26.07 5/5] net/mlx5: allow legacy source vport match Dariusz Sosnowski
  4 siblings, 0 replies; 6+ messages in thread
From: Dariusz Sosnowski @ 2026-03-25  9:07 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Bing Zhao, Ori Kam, Suanming Mou,
	Matan Azrad; +Cc: dev

Matching source vport without having vport metadata available
requires matching on 2 fields:

- source_gvmi - equal to VHCA ID property of the port,
- functional_lb

There are following cases:

- If packet comes from PF/VF/SF, then it originated on some Tx queue on
  the host. In this case, source_gvmi will be populated with
  the ID of the originating function.
- If packet comes from the wire, then source_gvmi will be set to 0.

There is one edge case - discriminating packets coming from PF0 and
from wire. In this case, both packets will have source_gvmi set to 0.
Distinguishing them requires additional match on functional_lb.
If packet comes from PF, functional_lb will be set to 1.
This only happens when packet was sent from PF to FDB, and
then moved to PF again.

Because of all of the above:

- Unified FDB must be disabled when vport metadata is disabled,
  because packet from PF0 and from wire will not have
  correct functional_lb set yet when flow rules in FDB are processed.
- Without unified FDB, when separate FDB_RX and FDB_TX tables are used
  internally, match on functional_lb is not needed.
  Table type already defines the direction.
- NIC_TX tables belong to a single GVMI and as a result
  vport matching is not needed there.

As a result, functional_lb match is only required on NIC_RX.

This patch adds support for source_gvmi and functional_lb matching
in HWS layer.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
 drivers/net/mlx5/hws/mlx5dr_definer.c | 65 +++++++++++++++++++++++++--
 drivers/net/mlx5/hws/mlx5dr_definer.h |  2 +
 drivers/net/mlx5/hws/mlx5dr_table.c   |  6 +++
 3 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/drivers/net/mlx5/hws/mlx5dr_definer.c b/drivers/net/mlx5/hws/mlx5dr_definer.c
index 3ba69c1001..7400b8f252 100644
--- a/drivers/net/mlx5/hws/mlx5dr_definer.c
+++ b/drivers/net/mlx5/hws/mlx5dr_definer.c
@@ -6,6 +6,8 @@
 
 #include "mlx5dr_internal.h"
 
+#define WIRE_GVMI	0
+#define BAD_GVMI	0xFFFF
 #define GTP_PDU_SC	0x85
 #define BAD_PORT	0xBAD
 #define BAD_SQN		0xBAD
@@ -789,6 +791,49 @@ mlx5dr_definer_vport_set(struct mlx5dr_definer_fc *fc,
 	DR_SET(tag, regc_value, fc->byte_off, fc->bit_off, fc->bit_mask);
 }
 
+static void
+mlx5dr_definer_source_gvmi_set(struct mlx5dr_definer_fc *fc,
+			       const void *item_spec,
+			       uint8_t *tag)
+{
+	const struct rte_flow_item_ethdev *v = item_spec;
+	const struct flow_hw_port_info *port_info;
+	uint32_t source_gvmi;
+
+	if (v) {
+		port_info = flow_hw_conv_port_id(fc->dr_ctx, v->port_id);
+		assert(port_info != NULL);
+		if (port_info->is_wire)
+			source_gvmi = WIRE_GVMI;
+		else
+			source_gvmi = port_info->vhca_id;
+	} else {
+		source_gvmi = BAD_GVMI;
+	}
+
+	DR_SET(tag, source_gvmi, fc->byte_off, fc->bit_off, fc->bit_mask);
+}
+
+static void
+mlx5dr_definer_functional_lb_set(struct mlx5dr_definer_fc *fc,
+				 const void *item_spec,
+				 uint8_t *tag)
+{
+	const struct rte_flow_item_ethdev *v = item_spec;
+	const struct flow_hw_port_info *port_info;
+	uint32_t functional_lb;
+
+	if (v) {
+		port_info = flow_hw_conv_port_id(fc->dr_ctx, v->port_id);
+		assert(port_info != NULL);
+		functional_lb = !port_info->is_wire;
+	} else {
+		functional_lb = 0;
+	}
+
+	DR_SET(tag, functional_lb, fc->byte_off, fc->bit_off, fc->bit_mask);
+}
+
 static struct mlx5dr_definer_fc *
 mlx5dr_definer_get_mpls_fc(struct mlx5dr_definer_conv_data *cd, bool inner)
 {
@@ -1610,10 +1655,22 @@ mlx5dr_definer_conv_item_port(struct mlx5dr_definer_conv_data *cd,
 			fc->bit_mask = caps->wire_regc_mask >> fc->bit_off;
 			fc->dr_ctx = cd->ctx;
 		} else {
-			/* TODO */
-			DR_LOG(ERR, "Port ID item with legacy vport match is not implemented");
-			rte_errno = ENOTSUP;
-			return rte_errno;
+			fc = &cd->fc[MLX5DR_DEFINER_FNAME_SOURCE_GVMI];
+			fc->item_idx = item_idx;
+			fc->tag_set = &mlx5dr_definer_source_gvmi_set;
+			fc->tag_mask_set = &mlx5dr_definer_ones_set;
+			DR_CALC_SET_HDR(fc, source_qp_gvmi, source_gvmi);
+			fc->dr_ctx = cd->ctx;
+
+			if (cd->table_type != MLX5DR_TABLE_TYPE_NIC_RX)
+				return 0;
+
+			fc = &cd->fc[MLX5DR_DEFINER_FNAME_FUNCTIONAL_LB];
+			fc->item_idx = item_idx;
+			fc->tag_set = &mlx5dr_definer_functional_lb_set;
+			fc->tag_mask_set = &mlx5dr_definer_ones_set;
+			DR_CALC_SET_HDR(fc, source_qp_gvmi, functional_lb);
+			fc->dr_ctx = cd->ctx;
 		}
 	}
 
diff --git a/drivers/net/mlx5/hws/mlx5dr_definer.h b/drivers/net/mlx5/hws/mlx5dr_definer.h
index d0c99399ae..f5d6cce887 100644
--- a/drivers/net/mlx5/hws/mlx5dr_definer.h
+++ b/drivers/net/mlx5/hws/mlx5dr_definer.h
@@ -214,6 +214,8 @@ enum mlx5dr_definer_fname {
 	MLX5DR_DEFINER_FNAME_PTYPE_FRAG_O,
 	MLX5DR_DEFINER_FNAME_PTYPE_FRAG_I,
 	MLX5DR_DEFINER_FNAME_RANDOM_NUM,
+	MLX5DR_DEFINER_FNAME_SOURCE_GVMI,
+	MLX5DR_DEFINER_FNAME_FUNCTIONAL_LB,
 	MLX5DR_DEFINER_FNAME_MAX,
 };
 
diff --git a/drivers/net/mlx5/hws/mlx5dr_table.c b/drivers/net/mlx5/hws/mlx5dr_table.c
index 41ffaa19e3..14e983a363 100644
--- a/drivers/net/mlx5/hws/mlx5dr_table.c
+++ b/drivers/net/mlx5/hws/mlx5dr_table.c
@@ -468,6 +468,12 @@ struct mlx5dr_table *mlx5dr_table_create(struct mlx5dr_context *ctx,
 		return NULL;
 	}
 
+	if (attr->type == MLX5DR_TABLE_TYPE_FDB_UNIFIED && !ctx->caps->vport_metadata_match) {
+		DR_LOG(ERR, "Table type %d requires vport metadata to be enabled", attr->type);
+		rte_errno = ENOTSUP;
+		return NULL;
+	}
+
 	if ((mlx5dr_table_is_fdb_any(attr->type) && attr->type != MLX5DR_TABLE_TYPE_FDB) &&
 	    !attr->level) {
 		DR_LOG(ERR, "Table type %d not supported by root table", attr->type);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 26.07 5/5] net/mlx5: allow legacy source vport match
  2026-03-25  9:07 [PATCH 26.07 0/5] net/mlx5: legacy vport match support with HWS Dariusz Sosnowski
                   ` (3 preceding siblings ...)
  2026-03-25  9:07 ` [PATCH 26.07 4/5] net/mlx5/hws: add source vport match in HWS Dariusz Sosnowski
@ 2026-03-25  9:07 ` Dariusz Sosnowski
  4 siblings, 0 replies; 6+ messages in thread
From: Dariusz Sosnowski @ 2026-03-25  9:07 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Bing Zhao, Ori Kam, Suanming Mou,
	Matan Azrad; +Cc: dev

Allow running mlx5 PMD on top of a device with switchdev enabled,
where vport metadata is disabled (esw_port_metadata devlink parameter
is set to false). This requires:

- Preceding patches introducing source vport match capabilities
  in HWS layer.
- Removing the check for vport metadata during port probing
  (it previously was one of the requirements).
- Modify Tx representor matching flow rules logic when vport metadata
  is not available - instead of metadata, match on vport ID.
    - vport ID is enough, because any shared FDB use case
      required vport metadata to be enabled.
- Disable internal usage of unified FDB, when vport metadata
  is not available.
- Force internal usage of source_vport match on root flow rules,
  when vport metadata is not available.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
 drivers/net/mlx5/linux/mlx5_os.c | 34 +++++++-------------------------
 drivers/net/mlx5/mlx5.h          |  1 +
 drivers/net/mlx5/mlx5_flow_dv.c  |  3 +++
 drivers/net/mlx5/mlx5_flow_hw.c  | 28 +++++++++-----------------
 4 files changed, 20 insertions(+), 46 deletions(-)

diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 75a2936023..a9dd0be055 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -1866,7 +1866,9 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		 *   3. with unsupported FW
 		 *   4. all representors in HWS
 		 */
-		priv->unified_fdb_en = !!priv->master && sh->cdev->config.hca_attr.fdb_unified_en;
+		priv->unified_fdb_en = sh->cdev->config.hca_attr.fdb_unified_en &&
+				       priv->master &&
+				       priv->vport_meta_mask != 0;
 		/* Jump FDB Rx works only with unified FDB enabled. */
 		if (priv->unified_fdb_en)
 			priv->jump_fdb_rx_en = sh->cdev->config.hca_attr.jump_fdb_rx_en;
@@ -1874,32 +1876,10 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 			eth_dev->data->port_id,
 			priv->unified_fdb_en ? "is" : "isn't",
 			priv->jump_fdb_rx_en ? "is" : "isn't");
-		if (priv->sh->config.dv_esw_en) {
-			uint32_t usable_bits;
-			uint32_t required_bits;
-
-			if (priv->sh->dv_regc0_mask == UINT32_MAX) {
-				DRV_LOG(ERR, "E-Switch port metadata is required when using HWS "
-					     "but it is disabled (configure it through devlink)");
-				err = ENOTSUP;
-				goto error;
-			}
-			if (priv->sh->dv_regc0_mask == 0) {
-				DRV_LOG(ERR, "E-Switch with HWS is not supported "
-					     "(no available bits in reg_c[0])");
-				err = ENOTSUP;
-				goto error;
-			}
-			usable_bits = rte_popcount32(priv->sh->dv_regc0_mask);
-			required_bits = rte_popcount32(priv->vport_meta_mask);
-			if (usable_bits < required_bits) {
-				DRV_LOG(ERR, "Not enough bits available in reg_c[0] to provide "
-					     "representor matching.");
-				err = ENOTSUP;
-				goto error;
-			}
-		}
-		if (priv->vport_meta_mask)
+		/* Without vport metadata, PMD must rely on source_vport match. */
+		if (priv->sh->config.dv_esw_en && priv->vport_meta_mask == 0)
+			priv->vport_match = 1;
+		if (priv->sh->config.dv_esw_en)
 			mlx5_flow_hw_set_port_info(eth_dev);
 		if (priv->sh->config.dv_esw_en &&
 		    priv->sh->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 8cd6562633..7e8ef1d467 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -2003,6 +2003,7 @@ struct mlx5_priv {
 	uint32_t tunnel_enabled:1; /* If tunnel offloading is enabled on rxqs. */
 	uint32_t unified_fdb_en:1; /* Unified FDB flag per port. */
 	uint32_t jump_fdb_rx_en:1; /* Jump from FDB Tx to FDB Rx flag per port. */
+	uint32_t vport_match:1; /* True if source_vport match is used instead of metadata */
 	uint16_t domain_id; /* Switch domain identifier. */
 	uint16_t vport_id; /* Associated VF vport index (if any). */
 	uint16_t vport_vhca_id; /* VHCA ID of the associated vport (if any). */
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 32e75b063f..c2a2874913 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -11050,6 +11050,9 @@ flow_dv_translate_item_represented_port(struct rte_eth_dev *dev, void *key,
 #ifndef HAVE_IBV_DEVICE_ATTR_ESW_MGR_REG_C0
 	if (priv->sh->config.dv_flow_en == 2)
 		vport_match = true;
+#else
+	if (priv->sh->config.dv_flow_en == 2)
+		vport_match = !!priv->vport_match;
 #endif
 	if (!pid_m && !pid_v)
 		return 0;
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 4871594c35..b6bb9f12a6 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -9939,33 +9939,23 @@ static __rte_always_inline uint32_t
 flow_hw_tx_tag_regc_mask(struct rte_eth_dev *dev)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
-	uint32_t mask = priv->sh->dv_regc0_mask;
 
-	/* Mask is verified during device initialization. Sanity checking here. */
-	MLX5_ASSERT(mask != 0);
-	/*
-	 * Availability of sufficient number of bits in REG_C_0 is verified on initialization.
-	 * Sanity checking here.
-	 */
-	MLX5_ASSERT(rte_popcount32(mask) >= rte_popcount32(priv->vport_meta_mask));
-	return mask;
+	if (priv->vport_meta_mask != 0)
+		return priv->sh->dv_regc0_mask;
+	else
+		return UINT32_MAX;
 }
 
 static __rte_always_inline uint32_t
 flow_hw_tx_tag_regc_value(struct rte_eth_dev *dev)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
-	uint32_t tag;
 
-	/* Mask is verified during device initialization. Sanity checking here. */
-	MLX5_ASSERT(priv->vport_meta_mask != 0);
-	tag = priv->vport_meta_tag >> (rte_bsf32(priv->vport_meta_mask));
-	/*
-	 * Availability of sufficient number of bits in REG_C_0 is verified on initialization.
-	 * Sanity checking here.
-	 */
-	MLX5_ASSERT((tag & priv->sh->dv_regc0_mask) == tag);
-	return tag;
+	if (priv->vport_meta_mask != 0)
+		return priv->vport_meta_tag >> (rte_bsf32(priv->vport_meta_mask));
+
+	/* Without REG_C match value available, resort to matching vport ID. */
+	return priv->vport_id | (priv->sh->cdev->config.hca_attr.vhca_id << 16);
 }
 
 static void
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-03-25  9:09 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-25  9:07 [PATCH 26.07 0/5] net/mlx5: legacy vport match support with HWS Dariusz Sosnowski
2026-03-25  9:07 ` [PATCH 26.07 1/5] common/mlx5: query vport VHCA ID Dariusz Sosnowski
2026-03-25  9:07 ` [PATCH 26.07 2/5] net/mlx5: store port " Dariusz Sosnowski
2026-03-25  9:07 ` [PATCH 26.07 3/5] net/mlx5: return port info regardless of register mask Dariusz Sosnowski
2026-03-25  9:07 ` [PATCH 26.07 4/5] net/mlx5/hws: add source vport match in HWS Dariusz Sosnowski
2026-03-25  9:07 ` [PATCH 26.07 5/5] net/mlx5: allow legacy source vport match Dariusz Sosnowski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox