[PATCH 1/2] net/mlx5: fix promiscuous inconsistency on port start
David Marchand
david.marchand at redhat.com
Fri Jul 31 11:23:31 CEST 2026
The kernel netdev promiscuous or all multicast mode could be enabled
before DPDK starts the port. This would cause an inconsistency between
the kernel state and DPDK's expected state
(dev->data->promiscuous / dev->data->all_multicast).
Add mlx5_os_get_promisc() and mlx5_os_get_allmulti() to query the
current kernel state via netlink. On port start, compare the kernel
state with DPDK's state and sync if they differ.
On Windows, these getters always return false as there seems to be no
API for getting the states.
Fixes: dd4bb90bc3cb ("net/mlx5: use Netlink to enable promisc/allmulti mode")
Cc: stable at dpdk.org
Signed-off-by: David Marchand <david.marchand at redhat.com>
---
drivers/common/mlx5/linux/mlx5_nl.c | 116 +++++++++++++++++++++++-----
drivers/common/mlx5/linux/mlx5_nl.h | 4 +
drivers/net/mlx5/linux/mlx5_os.c | 34 ++++++++
drivers/net/mlx5/mlx5.h | 2 +
drivers/net/mlx5/mlx5_trigger.c | 14 ++++
drivers/net/mlx5/windows/mlx5_os.c | 32 ++++++++
6 files changed, 182 insertions(+), 20 deletions(-)
diff --git a/drivers/common/mlx5/linux/mlx5_nl.c b/drivers/common/mlx5/linux/mlx5_nl.c
index 8b19838a7e..42ccb73e36 100644
--- a/drivers/common/mlx5/linux/mlx5_nl.c
+++ b/drivers/common/mlx5/linux/mlx5_nl.c
@@ -966,6 +966,101 @@ mlx5_nl_allmulti(int nlsk_fd, unsigned int iface_idx, int enable)
return ret;
}
+/**
+ * Query link information via Netlink.
+ *
+ * @param[in] nlsk_fd
+ * Netlink socket file descriptor.
+ * @param[in] iface_idx
+ * Net device interface index.
+ * @param[in] cb
+ * Callback to process the response.
+ * @param[out] arg
+ * Opaque argument for the callback.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise.
+ */
+static int
+mlx5_nl_link_info(int nlsk_fd, unsigned int iface_idx,
+ int (*cb)(struct nlmsghdr *, void *), void *arg)
+{
+ struct {
+ struct nlmsghdr hdr;
+ struct ifinfomsg ifi;
+ } req = {
+ .hdr = {
+ .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+ .nlmsg_type = RTM_GETLINK,
+ .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
+ },
+ .ifi = {
+ .ifi_family = AF_UNSPEC,
+ .ifi_index = iface_idx,
+ },
+ };
+ uint32_t sn = MLX5_NL_SN_GENERATE;
+ int ret;
+
+ ret = mlx5_nl_send(nlsk_fd, &req.hdr, sn);
+ if (ret >= 0)
+ ret = mlx5_nl_recv(nlsk_fd, sn, cb, arg);
+ return ret;
+}
+
+static int
+mlx5_nl_get_flags_cb(struct nlmsghdr *nh, void *arg)
+{
+ struct ifinfomsg *ifm = NLMSG_DATA(nh);
+
+ *(uint32_t *)arg = ifm->ifi_flags;
+ return 0;
+}
+
+/**
+ * Get promiscuous mode via Netlink.
+ *
+ * @param[in] nlsk_fd
+ * Netlink socket file descriptor.
+ * @param[in] iface_idx
+ * Net device interface index.
+ *
+ * @return
+ * True if promiscuous mode is enabled, false otherwise.
+ */
+RTE_EXPORT_INTERNAL_SYMBOL(mlx5_nl_get_promisc)
+bool
+mlx5_nl_get_promisc(int nlsk_fd, unsigned int iface_idx)
+{
+ uint32_t flags = 0;
+
+ if (mlx5_nl_link_info(nlsk_fd, iface_idx, mlx5_nl_get_flags_cb, &flags))
+ return false;
+ return !!(flags & IFF_PROMISC);
+}
+
+/**
+ * Get all multicast mode via Netlink.
+ *
+ * @param[in] nlsk_fd
+ * Netlink socket file descriptor.
+ * @param[in] iface_idx
+ * Net device interface index.
+ *
+ * @return
+ * True if all multicast mode is enabled, false otherwise.
+ */
+RTE_EXPORT_INTERNAL_SYMBOL(mlx5_nl_get_allmulti)
+bool
+mlx5_nl_get_allmulti(int nlsk_fd, unsigned int iface_idx)
+{
+ uint32_t flags = 0;
+
+ if (mlx5_nl_link_info(nlsk_fd, iface_idx, mlx5_nl_get_flags_cb, &flags))
+ return false;
+ return !!(flags & IFF_ALLMULTI);
+}
+
/**
* Process network interface information from Netlink message.
*
@@ -2313,21 +2408,6 @@ int
mlx5_nl_get_mtu_bounds(int nl, unsigned int ifindex, uint16_t *min_mtu, uint16_t *max_mtu)
{
struct mlx5_mtu out = { 0 };
- struct {
- struct nlmsghdr nh;
- struct ifinfomsg info;
- } req = {
- .nh = {
- .nlmsg_len = NLMSG_LENGTH(sizeof(req.info)),
- .nlmsg_type = RTM_GETLINK,
- .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
- },
- .info = {
- .ifi_family = AF_UNSPEC,
- .ifi_index = ifindex,
- },
- };
- uint32_t sn = MLX5_NL_SN_GENERATE;
int ret;
if (min_mtu == NULL || max_mtu == NULL) {
@@ -2335,11 +2415,7 @@ mlx5_nl_get_mtu_bounds(int nl, unsigned int ifindex, uint16_t *min_mtu, uint16_t
return -rte_errno;
}
- ret = mlx5_nl_send(nl, &req.nh, sn);
- if (ret < 0)
- return ret;
-
- ret = mlx5_nl_recv(nl, sn, mlx5_nl_get_mtu_bounds_cb, &out);
+ ret = mlx5_nl_link_info(nl, ifindex, mlx5_nl_get_mtu_bounds_cb, &out);
if (ret < 0)
return ret;
diff --git a/drivers/common/mlx5/linux/mlx5_nl.h b/drivers/common/mlx5/linux/mlx5_nl.h
index 3f79a73c85..8ccdd244b0 100644
--- a/drivers/common/mlx5/linux/mlx5_nl.h
+++ b/drivers/common/mlx5/linux/mlx5_nl.h
@@ -74,6 +74,10 @@ int mlx5_nl_promisc(int nlsk_fd, unsigned int iface_idx, int enable);
__rte_internal
int mlx5_nl_allmulti(int nlsk_fd, unsigned int iface_idx, int enable);
__rte_internal
+bool mlx5_nl_get_promisc(int nlsk_fd, unsigned int iface_idx);
+__rte_internal
+bool mlx5_nl_get_allmulti(int nlsk_fd, unsigned int iface_idx);
+__rte_internal
unsigned int mlx5_nl_portnum(int nl, const char *name, struct mlx5_dev_info *dev_info);
__rte_internal
unsigned int mlx5_nl_ifindex(int nl, const char *name, uint32_t pindex,
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index adc5878296..592e233844 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -3483,6 +3483,40 @@ mlx5_os_set_allmulti(struct rte_eth_dev *dev, int enable)
mlx5_ifindex(dev), !!enable);
}
+/**
+ * Get device promiscuous mode
+ *
+ * @param dev
+ * Pointer to Ethernet device structure.
+ *
+ * @return
+ * True if promiscuous mode is enabled, false otherwise.
+ */
+bool
+mlx5_os_get_promisc(struct rte_eth_dev *dev)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+
+ return mlx5_nl_get_promisc(priv->nl_socket_route, mlx5_ifindex(dev));
+}
+
+/**
+ * Get device all multicast mode
+ *
+ * @param dev
+ * Pointer to Ethernet device structure.
+ *
+ * @return
+ * True if all multicast mode is enabled, false otherwise.
+ */
+bool
+mlx5_os_get_allmulti(struct rte_eth_dev *dev)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+
+ return mlx5_nl_get_allmulti(priv->nl_socket_route, mlx5_ifindex(dev));
+}
+
/**
* Flush device MAC addresses
*
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 27e6f4e31a..190d203c49 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -2639,6 +2639,8 @@ int mlx5_os_vf_mac_addr_modify(struct mlx5_priv *priv, unsigned int iface_idx,
int vf_index);
int mlx5_os_set_promisc(struct rte_eth_dev *dev, int enable);
int mlx5_os_set_allmulti(struct rte_eth_dev *dev, int enable);
+bool mlx5_os_get_promisc(struct rte_eth_dev *dev);
+bool mlx5_os_get_allmulti(struct rte_eth_dev *dev);
int mlx5_os_set_nonblock_channel_fd(int fd);
void mlx5_os_mac_addr_flush(struct rte_eth_dev *dev);
void mlx5_os_net_cleanup(void);
diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c
index 25847c8ba2..2a91e02b45 100644
--- a/drivers/net/mlx5/mlx5_trigger.c
+++ b/drivers/net/mlx5/mlx5_trigger.c
@@ -1455,6 +1455,20 @@ mlx5_dev_start(struct rte_eth_dev *dev)
}
}
#endif
+ if (priv->sh->dev_cap.vf || priv->sh->dev_cap.sf) {
+ if (mlx5_os_get_promisc(dev) != dev->data->promiscuous) {
+ DRV_LOG(INFO, "port %u forcing promiscuous mode to %s",
+ dev->data->port_id,
+ dev->data->promiscuous ? "enabled" : "disabled");
+ mlx5_os_set_promisc(dev, dev->data->promiscuous);
+ }
+ if (mlx5_os_get_allmulti(dev) != dev->data->all_multicast) {
+ DRV_LOG(INFO, "port %u forcing all multicast mode to %s",
+ dev->data->port_id,
+ dev->data->all_multicast ? "enabled" : "disabled");
+ mlx5_os_set_allmulti(dev, dev->data->all_multicast);
+ }
+ }
ret = mlx5_traffic_enable(dev);
if (ret) {
DRV_LOG(ERR, "port %u failed to set defaults flows",
diff --git a/drivers/net/mlx5/windows/mlx5_os.c b/drivers/net/mlx5/windows/mlx5_os.c
index 9acfa8ec84..cf34e4e1d6 100644
--- a/drivers/net/mlx5/windows/mlx5_os.c
+++ b/drivers/net/mlx5/windows/mlx5_os.c
@@ -829,6 +829,38 @@ mlx5_os_set_allmulti(struct rte_eth_dev *dev, int enable)
return mlx5_glue->devx_set_promisc_vport(priv->sh->cdev->ctx, MC_PROMISC, enable);
}
+/**
+ * Get device promiscuous mode
+ *
+ * @param dev
+ * Pointer to Ethernet device structure.
+ *
+ * @return
+ * Always false on Windows.
+ */
+bool
+mlx5_os_get_promisc(struct rte_eth_dev *dev)
+{
+ RTE_SET_USED(dev);
+ return false;
+}
+
+/**
+ * Get device all multicast mode
+ *
+ * @param dev
+ * Pointer to Ethernet device structure.
+ *
+ * @return
+ * Always false on Windows.
+ */
+bool
+mlx5_os_get_allmulti(struct rte_eth_dev *dev)
+{
+ RTE_SET_USED(dev);
+ return false;
+}
+
/**
* DPDK callback to register a PCI device.
*
--
2.54.0
More information about the stable
mailing list