18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause 2771fa900SAdrien Mazarguil * Copyright 2015 6WIND S.A. 35feecc57SShahaf Shuler * Copyright 2015 Mellanox Technologies, Ltd 4771fa900SAdrien Mazarguil */ 5771fa900SAdrien Mazarguil 6771fa900SAdrien Mazarguil #include <stddef.h> 7771fa900SAdrien Mazarguil #include <stdint.h> 8771fa900SAdrien Mazarguil #include <string.h> 9771fa900SAdrien Mazarguil #include <inttypes.h> 10771fa900SAdrien Mazarguil #include <errno.h> 11771fa900SAdrien Mazarguil 12771fa900SAdrien Mazarguil #include <rte_ether.h> 13df96fd0dSBruce Richardson #include <ethdev_driver.h> 14771fa900SAdrien Mazarguil #include <rte_common.h> 15771fa900SAdrien Mazarguil 167b4f1e6bSMatan Azrad #include "mlx5_defs.h" 17771fa900SAdrien Mazarguil #include "mlx5.h" 18771fa900SAdrien Mazarguil #include "mlx5_utils.h" 193318aef7SAdrien Mazarguil #include "mlx5_rxtx.h" 20771fa900SAdrien Mazarguil 21771fa900SAdrien Mazarguil /** 2218c01b98SNélio Laranjeiro * Remove a MAC address from the internal array. 2318c01b98SNélio Laranjeiro * 2418c01b98SNélio Laranjeiro * @param dev 2518c01b98SNélio Laranjeiro * Pointer to Ethernet device structure. 2618c01b98SNélio Laranjeiro * @param index 2718c01b98SNélio Laranjeiro * MAC address index. 28*46532860SDariusz Sosnowski * @param addr 29*46532860SDariusz Sosnowski * If MAC address is actually removed, it will be stored here if pointer is not a NULL. 30*46532860SDariusz Sosnowski * 31*46532860SDariusz Sosnowski * @return 32*46532860SDariusz Sosnowski * True if there was a MAC address under given index. 3318c01b98SNélio Laranjeiro */ 34*46532860SDariusz Sosnowski static bool 35*46532860SDariusz Sosnowski mlx5_internal_mac_addr_remove(struct rte_eth_dev *dev, 36*46532860SDariusz Sosnowski uint32_t index, 37*46532860SDariusz Sosnowski struct rte_ether_addr *addr) 3818c01b98SNélio Laranjeiro { 398e46d4e1SAlexander Kozyrev MLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES); 40538da7a1SOlivier Matz if (rte_is_zero_ether_addr(&dev->data->mac_addrs[index])) 41*46532860SDariusz Sosnowski return false; 42ab27cdd9SOphir Munk mlx5_os_mac_addr_remove(dev, index); 43*46532860SDariusz Sosnowski if (addr != NULL) 44*46532860SDariusz Sosnowski *addr = dev->data->mac_addrs[index]; 456d13ea8eSOlivier Matz memset(&dev->data->mac_addrs[index], 0, sizeof(struct rte_ether_addr)); 46*46532860SDariusz Sosnowski return true; 4718c01b98SNélio Laranjeiro } 4818c01b98SNélio Laranjeiro 4918c01b98SNélio Laranjeiro /** 5018c01b98SNélio Laranjeiro * Adds a MAC address to the internal array. 5118c01b98SNélio Laranjeiro * 5218c01b98SNélio Laranjeiro * @param dev 5318c01b98SNélio Laranjeiro * Pointer to Ethernet device structure. 5418c01b98SNélio Laranjeiro * @param mac_addr 5518c01b98SNélio Laranjeiro * MAC address to register. 5618c01b98SNélio Laranjeiro * @param index 5718c01b98SNélio Laranjeiro * MAC address index. 5818c01b98SNélio Laranjeiro * 5918c01b98SNélio Laranjeiro * @return 6018c01b98SNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 6118c01b98SNélio Laranjeiro */ 6218c01b98SNélio Laranjeiro static int 636d13ea8eSOlivier Matz mlx5_internal_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac, 6418c01b98SNélio Laranjeiro uint32_t index) 6518c01b98SNélio Laranjeiro { 6618c01b98SNélio Laranjeiro unsigned int i; 67ab27cdd9SOphir Munk int ret; 6818c01b98SNélio Laranjeiro 698e46d4e1SAlexander Kozyrev MLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES); 70538da7a1SOlivier Matz if (rte_is_zero_ether_addr(mac)) { 7118c01b98SNélio Laranjeiro rte_errno = EINVAL; 7218c01b98SNélio Laranjeiro return -rte_errno; 7318c01b98SNélio Laranjeiro } 7418c01b98SNélio Laranjeiro /* First, make sure this address isn't already configured. */ 7518c01b98SNélio Laranjeiro for (i = 0; (i != MLX5_MAX_MAC_ADDRESSES); ++i) { 7618c01b98SNélio Laranjeiro /* Skip this index, it's going to be reconfigured. */ 7718c01b98SNélio Laranjeiro if (i == index) 7818c01b98SNélio Laranjeiro continue; 7918c01b98SNélio Laranjeiro if (memcmp(&dev->data->mac_addrs[i], mac, sizeof(*mac))) 8018c01b98SNélio Laranjeiro continue; 8118c01b98SNélio Laranjeiro /* Address already configured elsewhere, return with error. */ 8218c01b98SNélio Laranjeiro rte_errno = EADDRINUSE; 8318c01b98SNélio Laranjeiro return -rte_errno; 8418c01b98SNélio Laranjeiro } 85ab27cdd9SOphir Munk ret = mlx5_os_mac_addr_add(dev, mac, index); 8618c01b98SNélio Laranjeiro if (ret) 8718c01b98SNélio Laranjeiro return ret; 88ab27cdd9SOphir Munk 8918c01b98SNélio Laranjeiro dev->data->mac_addrs[index] = *mac; 9018c01b98SNélio Laranjeiro return 0; 9118c01b98SNélio Laranjeiro } 9218c01b98SNélio Laranjeiro 9318c01b98SNélio Laranjeiro /** 943318aef7SAdrien Mazarguil * DPDK callback to remove a MAC address. 953318aef7SAdrien Mazarguil * 963318aef7SAdrien Mazarguil * @param dev 973318aef7SAdrien Mazarguil * Pointer to Ethernet device structure. 983318aef7SAdrien Mazarguil * @param index 993318aef7SAdrien Mazarguil * MAC address index. 1003318aef7SAdrien Mazarguil */ 1013318aef7SAdrien Mazarguil void 1023318aef7SAdrien Mazarguil mlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) 1033318aef7SAdrien Mazarguil { 104*46532860SDariusz Sosnowski struct rte_ether_addr addr = { 0 }; 105ccdcba53SNélio Laranjeiro int ret; 106ccdcba53SNélio Laranjeiro 10718c01b98SNélio Laranjeiro if (index >= MLX5_MAX_UC_MAC_ADDRESSES) 108fa80b3c9SNélio Laranjeiro return; 109*46532860SDariusz Sosnowski if (mlx5_internal_mac_addr_remove(dev, index, &addr)) { 110*46532860SDariusz Sosnowski ret = mlx5_traffic_mac_remove(dev, &addr); 111a6d83b6aSNélio Laranjeiro if (ret) 112*46532860SDariusz Sosnowski DRV_LOG(ERR, "port %u cannot update control flow rules: %s", 1130f99970bSNélio Laranjeiro dev->data->port_id, strerror(rte_errno)); 114a6d83b6aSNélio Laranjeiro } 115ecc1c29dSAdrien Mazarguil } 116ecc1c29dSAdrien Mazarguil 117ecc1c29dSAdrien Mazarguil /** 1183318aef7SAdrien Mazarguil * DPDK callback to add a MAC address. 1193318aef7SAdrien Mazarguil * 1203318aef7SAdrien Mazarguil * @param dev 1213318aef7SAdrien Mazarguil * Pointer to Ethernet device structure. 1223318aef7SAdrien Mazarguil * @param mac_addr 1233318aef7SAdrien Mazarguil * MAC address to register. 1243318aef7SAdrien Mazarguil * @param index 1253318aef7SAdrien Mazarguil * MAC address index. 1263318aef7SAdrien Mazarguil * @param vmdq 1273318aef7SAdrien Mazarguil * VMDq pool index to associate address with (ignored). 128272733b5SNélio Laranjeiro * 129272733b5SNélio Laranjeiro * @return 130a6d83b6aSNélio Laranjeiro * 0 on success, a negative errno value otherwise and rte_errno is set. 1313318aef7SAdrien Mazarguil */ 1326d01e580SWei Dai int 1336d13ea8eSOlivier Matz mlx5_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac, 13456f08e16SNélio Laranjeiro uint32_t index, uint32_t vmdq __rte_unused) 1353318aef7SAdrien Mazarguil { 13618c01b98SNélio Laranjeiro int ret; 137a48deadaSOr Ami 13818c01b98SNélio Laranjeiro if (index >= MLX5_MAX_UC_MAC_ADDRESSES) { 139fa80b3c9SNélio Laranjeiro rte_errno = EINVAL; 140fa80b3c9SNélio Laranjeiro return -rte_errno; 141fa80b3c9SNélio Laranjeiro } 14218c01b98SNélio Laranjeiro ret = mlx5_internal_mac_addr_add(dev, mac, index); 14318c01b98SNélio Laranjeiro if (ret < 0) 144ccdcba53SNélio Laranjeiro return ret; 145*46532860SDariusz Sosnowski return mlx5_traffic_mac_add(dev, mac); 1463318aef7SAdrien Mazarguil } 14786977fccSDavid Marchand 14886977fccSDavid Marchand /** 14986977fccSDavid Marchand * DPDK callback to set primary MAC address. 15086977fccSDavid Marchand * 15186977fccSDavid Marchand * @param dev 15286977fccSDavid Marchand * Pointer to Ethernet device structure. 15386977fccSDavid Marchand * @param mac_addr 15486977fccSDavid Marchand * MAC address to register. 155caccf8b3SOlivier Matz * 156caccf8b3SOlivier Matz * @return 157caccf8b3SOlivier Matz * 0 on success, a negative errno value otherwise and rte_errno is set. 15886977fccSDavid Marchand */ 159caccf8b3SOlivier Matz int 1606d13ea8eSOlivier Matz mlx5_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr) 16186977fccSDavid Marchand { 1620d1d7317SRaslan Darawsheh uint16_t port_id; 1630d1d7317SRaslan Darawsheh struct mlx5_priv *priv = dev->data->dev_private; 1641ce7d26dSXueming Li struct mlx5_priv *pf_priv; 165*46532860SDariusz Sosnowski struct rte_ether_addr old_mac_addr = dev->data->mac_addrs[0]; 166*46532860SDariusz Sosnowski int ret; 167*46532860SDariusz Sosnowski 168*46532860SDariusz Sosnowski /* ethdev does not check if new default address is the same as the old one. */ 169*46532860SDariusz Sosnowski if (rte_is_same_ether_addr(mac_addr, &old_mac_addr)) 170*46532860SDariusz Sosnowski return 0; 1710d1d7317SRaslan Darawsheh 172753dd702SRaslan Darawsheh /* 173753dd702SRaslan Darawsheh * Configuring the VF instead of its representor, 17411c73de9SDariusz Sosnowski * need to skip the special cases: 17511c73de9SDariusz Sosnowski * - HPF on BlueField, 17611c73de9SDariusz Sosnowski * - SF representors, 17711c73de9SDariusz Sosnowski * - uplink ports when running in MPESW mode. 178753dd702SRaslan Darawsheh */ 17911c73de9SDariusz Sosnowski if (priv->representor && !mlx5_is_hpf(dev) && !mlx5_is_sf_repr(dev) && 18011c73de9SDariusz Sosnowski !priv->mpesw_uplink) { 1810d1d7317SRaslan Darawsheh DRV_LOG(DEBUG, "VF represented by port %u setting primary MAC address", 1820d1d7317SRaslan Darawsheh dev->data->port_id); 1831ce7d26dSXueming Li if (priv->pf_bond >= 0) { 1841ce7d26dSXueming Li /* Bonding, get owner PF ifindex from shared data. */ 185ab27cdd9SOphir Munk return mlx5_os_vf_mac_addr_modify 186ab27cdd9SOphir Munk (priv, 1871ce7d26dSXueming Li priv->sh->bond.ports[priv->pf_bond].ifindex, 188f926cce3SXueming Li mac_addr, 1891ce7d26dSXueming Li MLX5_REPRESENTOR_REPR(priv->representor_id)); 1901ce7d26dSXueming Li } 1911ce7d26dSXueming Li RTE_ETH_FOREACH_DEV_SIBLING(port_id, dev->data->port_id) { 1921ce7d26dSXueming Li pf_priv = rte_eth_devices[port_id].data->dev_private; 1931ce7d26dSXueming Li if (pf_priv->master == 1) 1941ce7d26dSXueming Li return mlx5_os_vf_mac_addr_modify 1951ce7d26dSXueming Li (priv, pf_priv->if_index, mac_addr, 196f926cce3SXueming Li MLX5_REPRESENTOR_REPR 197f926cce3SXueming Li (priv->representor_id)); 1980d1d7317SRaslan Darawsheh } 1990d1d7317SRaslan Darawsheh rte_errno = -ENOTSUP; 2000d1d7317SRaslan Darawsheh return rte_errno; 2010d1d7317SRaslan Darawsheh } 2020d1d7317SRaslan Darawsheh 203a170a30dSNélio Laranjeiro DRV_LOG(DEBUG, "port %u setting primary MAC address", 204a170a30dSNélio Laranjeiro dev->data->port_id); 205*46532860SDariusz Sosnowski ret = mlx5_mac_addr_add(dev, mac_addr, 0, 0); 206*46532860SDariusz Sosnowski if (ret) 207*46532860SDariusz Sosnowski return ret; 208*46532860SDariusz Sosnowski return mlx5_traffic_mac_remove(dev, &old_mac_addr); 20986977fccSDavid Marchand } 210e0586a8dSNélio Laranjeiro 211e0586a8dSNélio Laranjeiro /** 212e0586a8dSNélio Laranjeiro * DPDK callback to set multicast addresses list. 213e0586a8dSNélio Laranjeiro * 214e0586a8dSNélio Laranjeiro * @see rte_eth_dev_set_mc_addr_list() 215e0586a8dSNélio Laranjeiro */ 216e0586a8dSNélio Laranjeiro int 217e0586a8dSNélio Laranjeiro mlx5_set_mc_addr_list(struct rte_eth_dev *dev, 2186d13ea8eSOlivier Matz struct rte_ether_addr *mc_addr_set, uint32_t nb_mc_addr) 219e0586a8dSNélio Laranjeiro { 220e0586a8dSNélio Laranjeiro uint32_t i; 221e0586a8dSNélio Laranjeiro int ret; 222e0586a8dSNélio Laranjeiro 223e0586a8dSNélio Laranjeiro if (nb_mc_addr >= MLX5_MAX_MC_MAC_ADDRESSES) { 224e0586a8dSNélio Laranjeiro rte_errno = ENOSPC; 225e0586a8dSNélio Laranjeiro return -rte_errno; 226e0586a8dSNélio Laranjeiro } 227e0586a8dSNélio Laranjeiro for (i = MLX5_MAX_UC_MAC_ADDRESSES; i != MLX5_MAX_MAC_ADDRESSES; ++i) 228*46532860SDariusz Sosnowski mlx5_internal_mac_addr_remove(dev, i, NULL); 229e0586a8dSNélio Laranjeiro i = MLX5_MAX_UC_MAC_ADDRESSES; 230e0586a8dSNélio Laranjeiro while (nb_mc_addr--) { 231e0586a8dSNélio Laranjeiro ret = mlx5_internal_mac_addr_add(dev, mc_addr_set++, i++); 232e0586a8dSNélio Laranjeiro if (ret) 233e0586a8dSNélio Laranjeiro return ret; 234e0586a8dSNélio Laranjeiro } 235e0586a8dSNélio Laranjeiro if (!dev->data->promiscuous) 236e0586a8dSNélio Laranjeiro return mlx5_traffic_restart(dev); 237e0586a8dSNélio Laranjeiro return 0; 238e0586a8dSNélio Laranjeiro } 239