From dd4bb90bc3cb4588299081b9ae5aad02792038f0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?N=C3=A9lio=20Laranjeiro?= Date: Thu, 5 Apr 2018 17:07:20 +0200 Subject: [PATCH] net/mlx5: use Netlink to enable promisc/allmulti mode VF devices are not able to receive promisc or allmulti traffic unless it fully requests it though Netlink. This will cause the request to be processed by the PF which will handle the request and enable it. This requires the VF to be trusted by the PF. Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5.h | 2 + drivers/net/mlx5/mlx5_nl.c | 94 ++++++++++++++++++++++++++++++++++ drivers/net/mlx5/mlx5_rxmode.c | 8 +++ 3 files changed, 104 insertions(+) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 8ca39be357..9943b1d714 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -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_ */ diff --git a/drivers/net/mlx5/mlx5_nl.c b/drivers/net/mlx5/mlx5_nl.c index 238e591d12..dca85835ab 100644 --- a/drivers/net/mlx5/mlx5_nl.c +++ b/drivers/net/mlx5/mlx5_nl.c @@ -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; +} diff --git a/drivers/net/mlx5/mlx5_rxmode.c b/drivers/net/mlx5/mlx5_rxmode.c index 14c0fc715a..80824bc43b 100644 --- a/drivers/net/mlx5/mlx5_rxmode.c +++ b/drivers/net/mlx5/mlx5_rxmode.c @@ -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", -- 2.20.1