From: Adrien Mazarguil Date: Thu, 18 Apr 2019 13:10:34 +0000 (+0200) Subject: net/mlx4: support multicast address list interface X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=138a740c45bf3ade795906447f3a44575651f723;p=dpdk.git net/mlx4: support multicast address list interface Since this driver does not distinguish unicast/multicast addresses, applications could always rely on the standard MAC add/remove/set interface to configure both types. As a result, the multicast address list interface never got implemented (rte_eth_dev_set_mc_addr_list()) however PMD-agnostic applications still rely on it for compatibility reasons; a wrapper is therefore required. Signed-off-by: Adrien Mazarguil Acked-by: Shahaf Shuler --- diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c index 17dfcd5a3b..fe559c0407 100644 --- a/drivers/net/mlx4/mlx4.c +++ b/drivers/net/mlx4/mlx4.c @@ -410,6 +410,7 @@ static const struct eth_dev_ops mlx4_dev_ops = { .mac_addr_remove = mlx4_mac_addr_remove, .mac_addr_add = mlx4_mac_addr_add, .mac_addr_set = mlx4_mac_addr_set, + .set_mc_addr_list = mlx4_set_mc_addr_list, .stats_get = mlx4_stats_get, .stats_reset = mlx4_stats_reset, .fw_version_get = mlx4_fw_version_get, diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index 6224b3be1a..e2d184f848 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h @@ -188,6 +188,7 @@ struct mlx4_priv { LIST_HEAD(, rte_flow) flows; /**< Configured flow rule handles. */ struct ether_addr mac[MLX4_MAX_MAC_ADDRESSES]; /**< Configured MAC addresses. Unused entries are zeroed. */ + uint32_t mac_mc; /**< Number of trailing multicast entries in mac[]. */ struct mlx4_verbs_alloc_ctx verbs_alloc_ctx; /**< Context for Verbs allocator. */ }; @@ -211,6 +212,8 @@ void mlx4_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index); int mlx4_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t vmdq); int mlx4_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr); +int mlx4_set_mc_addr_list(struct rte_eth_dev *dev, struct ether_addr *list, + uint32_t num); int mlx4_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); int mlx4_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); void mlx4_stats_reset(struct rte_eth_dev *dev); diff --git a/drivers/net/mlx4/mlx4_ethdev.c b/drivers/net/mlx4/mlx4_ethdev.c index 4dae67a1bd..765affc34c 100644 --- a/drivers/net/mlx4/mlx4_ethdev.c +++ b/drivers/net/mlx4/mlx4_ethdev.c @@ -433,7 +433,7 @@ mlx4_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) struct mlx4_priv *priv = dev->data->dev_private; struct rte_flow_error error; - if (index >= RTE_DIM(priv->mac)) { + if (index >= RTE_DIM(priv->mac) - priv->mac_mc) { rte_errno = EINVAL; return; } @@ -471,7 +471,7 @@ mlx4_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, int ret; (void)vmdq; - if (index >= RTE_DIM(priv->mac)) { + if (index >= RTE_DIM(priv->mac) - priv->mac_mc) { rte_errno = EINVAL; return -rte_errno; } @@ -487,6 +487,63 @@ mlx4_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, return ret; } +/** + * DPDK callback to configure multicast addresses. + * + * @param dev + * Pointer to Ethernet device structure. + * @param list + * List of MAC addresses to register. + * @param num + * Number of entries in list. + * + * @return + * 0 on success, negative errno value otherwise and rte_errno is set. + */ +int +mlx4_set_mc_addr_list(struct rte_eth_dev *dev, struct ether_addr *list, + uint32_t num) +{ + struct mlx4_priv *priv = dev->data->dev_private; + struct rte_flow_error error; + int ret; + + if (num > RTE_DIM(priv->mac)) { + rte_errno = EINVAL; + return -rte_errno; + } + /* + * Make sure there is enough room to increase the number of + * multicast entries without overwriting standard entries. + */ + if (num > priv->mac_mc) { + unsigned int i; + + for (i = RTE_DIM(priv->mac) - num; + i != RTE_DIM(priv->mac) - priv->mac_mc; + ++i) + if (!is_zero_ether_addr(&priv->mac[i])) { + rte_errno = EBUSY; + return -rte_errno; + } + } else if (num < priv->mac_mc) { + /* Clear unused entries. */ + memset(priv->mac + RTE_DIM(priv->mac) - priv->mac_mc, + 0, + sizeof(priv->mac[0]) * (priv->mac_mc - num)); + } + memcpy(priv->mac + RTE_DIM(priv->mac) - num, list, sizeof(*list) * num); + priv->mac_mc = num; + ret = mlx4_flow_sync(priv, &error); + if (!ret) + return 0; + ERROR("failed to synchronize flow rules after modifying MC list," + " (code %d, \"%s\"), flow error type %d, cause %p, message: %s", + rte_errno, strerror(rte_errno), error.type, error.cause, + error.message ? error.message : "(unspecified)"); + return ret; +} + /** * DPDK callback to configure a VLAN filter. *