@@ -312,5 +312,7 @@ int mlx5_nl_mac_addr_remove(struct rte_eth_dev *dev, struct ether_addr *mac,
uint32_t index);
void mlx5_nl_mac_addr_sync(struct rte_eth_dev *dev);
void mlx5_nl_mac_addr_flush(struct rte_eth_dev *dev);
+int mlx5_nl_promisc(struct rte_eth_dev *dev, int enable);
+int mlx5_nl_allmulti(struct rte_eth_dev *dev, int enable);
#endif /* RTE_PMD_MLX5_H_ */
@@ -531,3 +531,97 @@ mlx5_nl_mac_addr_flush(struct rte_eth_dev *dev)
mlx5_nl_mac_addr_remove(dev, m, i);
}
}
+
+/**
+ * Enable promiscuous / all multicast mode through Netlink.
+ *
+ * @param dev
+ * Pointer to Ethernet device structure.
+ * @param flags
+ * IFF_PROMISC for promiscuous, IFF_ALLMULTI for allmulti.
+ * @param enable
+ * Nonzero to enable, disable otherwise.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+mlx5_nl_device_flags(struct rte_eth_dev *dev, uint32_t flags, int enable)
+{
+ struct priv *priv = dev->data->dev_private;
+ int iface_idx = mlx5_ifindex(dev);
+ struct {
+ struct nlmsghdr hdr;
+ struct ifinfomsg ifi;
+ } req = {
+ .hdr = {
+ .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+ .nlmsg_type = RTM_NEWLINK,
+ .nlmsg_flags = NLM_F_REQUEST,
+ },
+ .ifi = {
+ .ifi_flags = enable ? flags : 0,
+ .ifi_change = flags,
+ .ifi_index = iface_idx,
+ },
+ };
+ int fd;
+ int ret;
+
+ assert(!(flags & ~(IFF_PROMISC | IFF_ALLMULTI)));
+ if (priv->nl_socket < 0)
+ return 0;
+ fd = priv->nl_socket;
+ ret = mlx5_nl_send(fd, &req.hdr, priv->nl_sn++);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+/**
+ * Enable promiscuous mode through Netlink.
+ *
+ * @param dev
+ * Pointer to Ethernet device structure.
+ * @param enable
+ * Nonzero to enable, disable otherwise.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_nl_promisc(struct rte_eth_dev *dev, int enable)
+{
+ int ret = mlx5_nl_device_flags(dev, IFF_PROMISC, enable);
+
+ if (ret)
+ DRV_LOG(DEBUG,
+ "port %u cannot %s promisc mode: Netlink error %s",
+ dev->data->port_id, enable ? "enable" : "disable",
+ strerror(rte_errno));
+ return ret;
+}
+
+/**
+ * Enable all multicast mode through Netlink.
+ *
+ * @param dev
+ * Pointer to Ethernet device structure.
+ * @param enable
+ * Nonzero to enable, disable otherwise.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_nl_allmulti(struct rte_eth_dev *dev, int enable)
+{
+ int ret = mlx5_nl_device_flags(dev, IFF_ALLMULTI, enable);
+
+ if (ret)
+ DRV_LOG(DEBUG,
+ "port %u cannot %s allmulti mode: Netlink error %s",
+ dev->data->port_id, enable ? "enable" : "disable",
+ strerror(rte_errno));
+ return ret;
+}
@@ -35,6 +35,8 @@ mlx5_promiscuous_enable(struct rte_eth_dev *dev)
int ret;
dev->data->promiscuous = 1;
+ if (((struct priv *)dev->data->dev_private)->config.vf)
+ mlx5_nl_promisc(dev, 1);
ret = mlx5_traffic_restart(dev);
if (ret)
DRV_LOG(ERR, "port %u cannot enable promiscuous mode: %s",
@@ -53,6 +55,8 @@ mlx5_promiscuous_disable(struct rte_eth_dev *dev)
int ret;
dev->data->promiscuous = 0;
+ if (((struct priv *)dev->data->dev_private)->config.vf)
+ mlx5_nl_promisc(dev, 0);
ret = mlx5_traffic_restart(dev);
if (ret)
DRV_LOG(ERR, "port %u cannot disable promiscuous mode: %s",
@@ -71,6 +75,8 @@ mlx5_allmulticast_enable(struct rte_eth_dev *dev)
int ret;
dev->data->all_multicast = 1;
+ if (((struct priv *)dev->data->dev_private)->config.vf)
+ mlx5_nl_allmulti(dev, 1);
ret = mlx5_traffic_restart(dev);
if (ret)
DRV_LOG(ERR, "port %u cannot enable allmulicast mode: %s",
@@ -89,6 +95,8 @@ mlx5_allmulticast_disable(struct rte_eth_dev *dev)
int ret;
dev->data->all_multicast = 0;
+ if (((struct priv *)dev->data->dev_private)->config.vf)
+ mlx5_nl_allmulti(dev, 0);
ret = mlx5_traffic_restart(dev);
if (ret)
DRV_LOG(ERR, "port %u cannot disable allmulicast mode: %s",