From: Dariusz Sosnowski <dsosnowski@nvidia.com>
To: Viacheslav Ovsiienko <viacheslavo@nvidia.com>,
Bing Zhao <bingz@nvidia.com>, Ori Kam <orika@nvidia.com>,
Suanming Mou <suanmingm@nvidia.com>,
Matan Azrad <matan@nvidia.com>
Cc: <dev@dpdk.org>
Subject: [PATCH 11/13] net/mlx5: add sibling device iteration macro
Date: Mon, 26 Oct 2026 17:27:07 +0100 [thread overview]
Message-ID: <20261026162709.1292958-12-dsosnowski@nvidia.com> (raw)
In-Reply-To: <20261026162709.1292958-1-dsosnowski@nvidia.com>
In some embedded switch topologies, not all DPDK representor ports
will be based on the same rte_device.
One such example is ConnectX socket direct configurations
or nested switches based on VFs/SFs.
mlx5 networking driver in many cases requires to iterate
over all DPDK ethdev ports belonging to the same switch.
In the past it relied on "one rte_device" assumption.
This patch introduces a new macro - MLX5_ETH_FOREACH_SIBLING -
which iterates over all ethdev ports managed by mlx5 driver,
which share the same mlx5 common device.
All relevant usages of previous iteration macros are replaced with
MLX5_ETH_FOREACH_SIBLING, in preparation for allowing usage of multiple
rte_device's in mlx5 networking driver.
Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
---
drivers/net/mlx5/linux/mlx5_ethdev_os.c | 13 ++---
drivers/net/mlx5/linux/mlx5_os.c | 22 +++-----
drivers/net/mlx5/mlx5.c | 70 ++++++++++++++++++++-----
drivers/net/mlx5/mlx5.h | 6 +++
drivers/net/mlx5/mlx5_ethdev.c | 27 +++-------
drivers/net/mlx5/mlx5_flow.c | 24 ++++-----
drivers/net/mlx5/mlx5_mac.c | 2 +-
drivers/net/mlx5/mlx5_trigger.c | 10 ++--
drivers/net/mlx5/windows/mlx5_os.c | 24 ++++-----
9 files changed, 105 insertions(+), 93 deletions(-)
diff --git a/drivers/net/mlx5/linux/mlx5_ethdev_os.c b/drivers/net/mlx5/linux/mlx5_ethdev_os.c
index f6394ebd19..55cae148f0 100644
--- a/drivers/net/mlx5/linux/mlx5_ethdev_os.c
+++ b/drivers/net/mlx5/linux/mlx5_ethdev_os.c
@@ -300,18 +300,13 @@ mlx5_find_master_dev(struct rte_eth_dev *dev)
{
struct mlx5_priv *priv;
uint16_t port_id;
- uint16_t domain_id;
priv = dev->data->dev_private;
- domain_id = priv->domain_id;
MLX5_ASSERT(priv->representor);
- MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
- struct mlx5_priv *opriv =
- rte_eth_devices[port_id].data->dev_private;
- if (opriv &&
- opriv->master &&
- opriv->domain_id == domain_id &&
- opriv->sh == priv->sh)
+ MLX5_ETH_FOREACH_SIBLING(port_id, priv->sh->cdev) {
+ struct mlx5_priv *opriv = rte_eth_devices[port_id].data->dev_private;
+
+ if (opriv->master)
return &rte_eth_devices[port_id];
}
return NULL;
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 42b23e7f58..1b1b1bb013 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -1585,14 +1585,10 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
* Look for sibling devices in order to reuse their switch domain
* if any, otherwise allocate one.
*/
- MLX5_ETH_FOREACH_DEV(port_id, dpdk_dev) {
- const struct mlx5_priv *opriv =
- rte_eth_devices[port_id].data->dev_private;
-
- if (!opriv ||
- opriv->sh != priv->sh ||
- opriv->domain_id ==
- RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID)
+ MLX5_ETH_FOREACH_SIBLING(port_id, priv->sh->cdev) {
+ const struct mlx5_priv *opriv = rte_eth_devices[port_id].data->dev_private;
+
+ if (opriv->domain_id == RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID)
continue;
priv->domain_id = opriv->domain_id;
DRV_LOG(DEBUG, "dev_port-%u inherit domain_id=%u\n",
@@ -1711,13 +1707,9 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
if (priv->representor) {
eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
eth_dev->data->representor_id = eth_dev->data->port_id;
- MLX5_ETH_FOREACH_DEV(port_id, dpdk_dev) {
- struct mlx5_priv *opriv =
- rte_eth_devices[port_id].data->dev_private;
- if (opriv &&
- opriv->master &&
- opriv->domain_id == priv->domain_id &&
- opriv->sh == priv->sh) {
+ MLX5_ETH_FOREACH_SIBLING(port_id, priv->sh->cdev) {
+ struct mlx5_priv *opriv = rte_eth_devices[port_id].data->dev_private;
+ if (opriv->master) {
eth_dev->data->backer_port_id = port_id;
break;
}
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 7093eefa15..615b2ff943 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -2565,23 +2565,14 @@ mlx5_dev_close(struct rte_eth_dev *dev)
* since 'mlx5_dev_interrupt_nl_cb' uses priv.
*/
rte_io_wmb();
- /*
- * Free the shared context in last turn, because the cleanup
- * routines above may use some shared fields, like
- * mlx5_os_mac_addr_flush() uses ibdev_path for retrieving
- * ifindex if Netlink fails.
- */
- mlx5_free_shared_dev_ctx(sh);
if (priv->domain_id != RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) {
unsigned int c = 0;
uint16_t port_id;
- MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
- struct mlx5_priv *opriv =
- rte_eth_devices[port_id].data->dev_private;
+ MLX5_ETH_FOREACH_SIBLING(port_id, priv->sh->cdev) {
+ struct mlx5_priv *opriv = rte_eth_devices[port_id].data->dev_private;
- if (!opriv ||
- opriv->domain_id != priv->domain_id ||
+ if (opriv->domain_id != priv->domain_id ||
&rte_eth_devices[port_id] == dev)
continue;
++c;
@@ -2590,6 +2581,13 @@ mlx5_dev_close(struct rte_eth_dev *dev)
if (!c)
claim_zero(rte_eth_switch_domain_free(priv->domain_id));
}
+ /*
+ * Free the shared context in last turn, because the cleanup
+ * routines above may use some shared fields, like
+ * mlx5_os_mac_addr_flush() uses ibdev_path for retrieving
+ * ifindex if Netlink fails.
+ */
+ mlx5_free_shared_dev_ctx(sh);
mlx5_flow_pools_destroy(priv);
memset(priv, 0, sizeof(*priv));
priv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;
@@ -3508,6 +3506,54 @@ mlx5_eth_find_next(uint16_t port_id, struct rte_device *odev)
return port_id;
}
+/**
+ * Look for the ethernet device belonging to mlx5 driver, which share the device context.
+ *
+ * If port index is found, then caller can assume that:
+ *
+ * - Port is a valid ethdev port, managed by mlx5 driver.
+ * - Port has private device data set (mlx5_priv).
+ * - Port has shared mlx5 device context set (priv->sh).
+ * - Port is based on the @p cdev common device.
+ *
+ * @param[in] start_port_id
+ * Port index to start looking for device.
+ * @param[in] cdev
+ * Pointer to common device.
+ *
+ * @return
+ * Port index of found device, RTE_MAX_ETHPORTS if not found.
+ */
+uint16_t
+mlx5_eth_find_next_sibling(uint16_t start_port_id, struct mlx5_common_device *cdev)
+{
+ struct mlx5_priv *priv;
+ uint16_t port_id;
+
+ if (cdev == NULL)
+ return RTE_MAX_ETHPORTS;
+
+ for (port_id = start_port_id; port_id < RTE_MAX_ETHPORTS; port_id++) {
+ if (rte_eth_dev_is_valid_port(port_id) == 0)
+ continue;
+
+ if (!mlx5_dev_is_managed(rte_eth_devices[port_id].device))
+ continue;
+
+ priv = rte_eth_devices[port_id].data->dev_private;
+ if (priv == NULL || priv->sh == NULL)
+ continue;
+
+ if (priv->sh->cdev == cdev)
+ break;
+ }
+
+ if (port_id >= RTE_MAX_ETHPORTS)
+ return RTE_MAX_ETHPORTS;
+
+ return port_id;
+}
+
static int
mlx5_hairpin_queue_counter_supported(struct mlx5_priv *priv)
{
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index b1493745ee..e4ebdd4c2f 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -2295,6 +2295,7 @@ void mlx5_proc_priv_uninit(struct rte_eth_dev *dev);
int mlx5_udp_tunnel_port_add(struct rte_eth_dev *dev,
struct rte_eth_udp_tunnel *udp_tunnel);
uint16_t mlx5_eth_find_next(uint16_t port_id, struct rte_device *odev);
+uint16_t mlx5_eth_find_next_sibling(uint16_t port_id, struct mlx5_common_device *cdev);
int mlx5_dev_close(struct rte_eth_dev *dev);
int mlx5_net_remove(struct mlx5_common_device *cdev);
bool mlx5_is_hpf(struct rte_eth_dev *dev);
@@ -2312,6 +2313,11 @@ int mlx5_disable_per_queue_hairpin_counter(struct rte_eth_dev *dev, uint64_t id)
for (port_id = mlx5_eth_find_next(0, dev); \
port_id < RTE_MAX_ETHPORTS; \
port_id = mlx5_eth_find_next(port_id + 1, dev))
+/* Macro to iterate over all valid ports for mlx5 driver spawned on given common device. */
+#define MLX5_ETH_FOREACH_SIBLING(port_id, cdev) \
+ for (port_id = mlx5_eth_find_next_sibling(0, cdev); \
+ port_id < RTE_MAX_ETHPORTS; \
+ port_id = mlx5_eth_find_next_sibling(port_id + 1, cdev))
void mlx5_rt_timestamp_config(struct mlx5_dev_ctx_shared *sh,
struct mlx5_hca_attr *hca_attr);
struct mlx5_dev_ctx_shared *
diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c
index 306c1cd734..f41724725c 100644
--- a/drivers/net/mlx5/mlx5_ethdev.c
+++ b/drivers/net/mlx5/mlx5_ethdev.c
@@ -424,15 +424,12 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
if (priv->representor) {
uint16_t port_id;
- MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
- struct mlx5_priv *opriv =
- rte_eth_devices[port_id].data->dev_private;
-
- if (!opriv ||
- opriv->representor ||
- opriv->sh != priv->sh ||
- opriv->domain_id != priv->domain_id)
+ MLX5_ETH_FOREACH_SIBLING(port_id, priv->sh->cdev) {
+ struct mlx5_priv *opriv = rte_eth_devices[port_id].data->dev_private;
+
+ if (opriv->representor)
continue;
+
/*
* Override switch name with that of the master
* device.
@@ -523,14 +520,9 @@ mlx5_representor_info_count(struct rte_eth_dev *dev)
uint16_t port_id;
unsigned int count = 0;
- MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
+ MLX5_ETH_FOREACH_SIBLING(port_id, priv->sh->cdev) {
struct mlx5_priv *opriv = rte_eth_devices[port_id].data->dev_private;
- if (!opriv ||
- opriv->sh != priv->sh ||
- opriv->domain_id != priv->domain_id)
- continue;
-
count += mlx5_representor_info_count_one(opriv);
}
@@ -629,14 +621,9 @@ mlx5_representor_info_fill(struct rte_eth_dev *dev,
info->controller = priv->port_info.ctrl_num;
info->pf = RTE_BUS_DEVICE(dev->device, struct rte_pci_device)->addr.function;
- MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
+ MLX5_ETH_FOREACH_SIBLING(port_id, priv->sh->cdev) {
struct mlx5_priv *opriv = rte_eth_devices[port_id].data->dev_private;
- if (!opriv ||
- opriv->sh != priv->sh ||
- opriv->domain_id != priv->domain_id)
- continue;
-
mlx5_representor_info_fill_one(opriv, info);
}
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index b0eac185b5..cceb6668f9 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -1665,15 +1665,12 @@ mlx5_flow_rxq_mark_flag_set(struct rte_eth_dev *dev)
if (priv->sh->shared_mark_enabled)
return;
if (priv->master || priv->representor) {
- MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
- struct mlx5_priv *opriv =
- rte_eth_devices[port_id].data->dev_private;
-
- if (!opriv ||
- opriv->sh != priv->sh ||
- opriv->domain_id != priv->domain_id ||
- opriv->mark_enabled)
+ MLX5_ETH_FOREACH_SIBLING(port_id, priv->sh->cdev) {
+ struct mlx5_priv *opriv = rte_eth_devices[port_id].data->dev_private;
+
+ if (opriv->mark_enabled)
continue;
+
LIST_FOREACH(rxq_ctrl, &opriv->rxqsctrl, next) {
rxq_ctrl->rxq.mark = 1;
}
@@ -12290,12 +12287,9 @@ mlx5_flow_pick_transfer_proxy(struct rte_eth_dev *dev,
*proxy_port_id = dev->data->port_id;
return 0;
}
- MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
- const struct rte_eth_dev *port_dev = &rte_eth_devices[port_id];
- const struct mlx5_priv *port_priv = port_dev->data->dev_private;
-
- if (port_priv->master &&
- port_priv->domain_id == priv->domain_id) {
+ MLX5_ETH_FOREACH_SIBLING(port_id, priv->sh->cdev) {
+ const struct mlx5_priv *port_priv = rte_eth_devices[port_id].data->dev_private;
+ if (port_priv->master) {
*proxy_port_id = port_id;
return 0;
}
@@ -12511,7 +12505,7 @@ flow_disable_steering_run_on_related(struct rte_eth_dev *dev,
}
/* Run callback on representors. */
- MLX5_ETH_FOREACH_DEV(other_port_id, dev->device) {
+ MLX5_ETH_FOREACH_SIBLING(other_port_id, priv->sh->cdev) {
struct rte_eth_dev *other_dev = &rte_eth_devices[other_port_id];
if (other_port_id != proxy_port_id)
diff --git a/drivers/net/mlx5/mlx5_mac.c b/drivers/net/mlx5/mlx5_mac.c
index 9e7bf7f2ec..8cbaaf67dd 100644
--- a/drivers/net/mlx5/mlx5_mac.c
+++ b/drivers/net/mlx5/mlx5_mac.c
@@ -191,7 +191,7 @@ mlx5_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
mac_addr,
MLX5_REPRESENTOR_REPR(priv->representor_id));
}
- RTE_ETH_FOREACH_DEV_SIBLING(port_id, dev->data->port_id) {
+ MLX5_ETH_FOREACH_SIBLING(port_id, priv->sh->cdev) {
pf_priv = rte_eth_devices[port_id].data->dev_private;
if (pf_priv->master == 1)
return mlx5_os_vf_mac_addr_modify
diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c
index c5f493117b..ae0584f1b4 100644
--- a/drivers/net/mlx5/mlx5_trigger.c
+++ b/drivers/net/mlx5/mlx5_trigger.c
@@ -1578,13 +1578,11 @@ mlx5_hw_proxy_port_allowed_stop(struct rte_eth_dev *dev)
/* If transfer proxy port was not configured for HWS, then stopping it is allowed. */
if (!priv->dr_ctx)
return 0;
- MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
- const struct rte_eth_dev *port_dev = &rte_eth_devices[port_id];
- const struct mlx5_priv *port_priv = port_dev->data->dev_private;
+ MLX5_ETH_FOREACH_SIBLING(port_id, priv->sh->cdev) {
+ struct rte_eth_dev *odev = &rte_eth_devices[port_id];
+ struct mlx5_priv *opriv = odev->data->dev_private;
- if (port_id != dev->data->port_id &&
- port_priv->domain_id == priv->domain_id &&
- port_dev->data->dev_started)
+ if (opriv->representor && odev->data->dev_started)
representor_started = true;
}
if (representor_started) {
diff --git a/drivers/net/mlx5/windows/mlx5_os.c b/drivers/net/mlx5/windows/mlx5_os.c
index 8e3baa95b4..2dbcbb1acb 100644
--- a/drivers/net/mlx5/windows/mlx5_os.c
+++ b/drivers/net/mlx5/windows/mlx5_os.c
@@ -437,16 +437,14 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
* Look for sibling devices in order to reuse their switch domain
* if any, otherwise allocate one.
*/
- MLX5_ETH_FOREACH_DEV(port_id, dpdk_dev) {
- const struct mlx5_priv *opriv =
- rte_eth_devices[port_id].data->dev_private;
-
- if (!opriv ||
- opriv->sh != priv->sh ||
- opriv->domain_id ==
- RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID)
+ MLX5_ETH_FOREACH_SIBLING(port_id, priv->sh->cdev) {
+ const struct mlx5_priv *opriv = rte_eth_devices[port_id].data->dev_private;
+
+ if (opriv->domain_id == RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID)
continue;
priv->domain_id = opriv->domain_id;
+ DRV_LOG(DEBUG, "dev_port-%u inherit domain_id=%u",
+ priv->dev_port, priv->domain_id);
break;
}
if (priv->domain_id == RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) {
@@ -476,13 +474,9 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
if (priv->representor) {
eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
eth_dev->data->representor_id = priv->representor_id;
- MLX5_ETH_FOREACH_DEV(port_id, dpdk_dev) {
- struct mlx5_priv *opriv =
- rte_eth_devices[port_id].data->dev_private;
- if (opriv &&
- opriv->master &&
- opriv->domain_id == priv->domain_id &&
- opriv->sh == priv->sh) {
+ MLX5_ETH_FOREACH_SIBLING(port_id, priv->sh->cdev) {
+ struct mlx5_priv *opriv = rte_eth_devices[port_id].data->dev_private;
+ if (opriv->master) {
eth_dev->data->backer_port_id = port_id;
break;
}
--
2.43.0
next prev parent reply other threads:[~2026-10-26 16:29 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-26 16:26 [PATCH 00/13] net/mlx5: support nested E-Switch Dariusz Sosnowski
2026-10-26 16:26 ` [PATCH 01/13] common/mlx5: rework IB port number query Dariusz Sosnowski
2026-10-26 16:26 ` [PATCH 02/13] common/mlx5: allow ifindex query without cache Dariusz Sosnowski
2026-10-26 16:26 ` [PATCH 03/13] common/mlx5: separate netdev info from switch info Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 04/13] common/mlx5: query parent device over Netlink Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 05/13] common/mlx5: add check for auxiliary device Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 06/13] common/mlx5: gather associated devices Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 07/13] common/mlx5: always use EAL device for probing Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 08/13] common/mlx5: query devlink port for netdevs Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 09/13] common/mlx5: get devlink port by port index Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 10/13] common/mlx5: add check for managed device Dariusz Sosnowski
2026-10-26 16:27 ` Dariusz Sosnowski [this message]
2026-10-26 16:27 ` [PATCH 12/13] net/mlx5: allow associated devices Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 13/13] net/mlx5: allow multiport auxiliary device probe Dariusz Sosnowski
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=20261026162709.1292958-12-dsosnowski@nvidia.com \
--to=dsosnowski@nvidia.com \
--cc=bingz@nvidia.com \
--cc=dev@dpdk.org \
--cc=matan@nvidia.com \
--cc=orika@nvidia.com \
--cc=suanmingm@nvidia.com \
--cc=viacheslavo@nvidia.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