1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2015 6WIND S.A. 3 * Copyright 2015 Mellanox Technologies, Ltd 4 */ 5 6 #include <stddef.h> 7 #include <stdint.h> 8 #include <string.h> 9 #include <inttypes.h> 10 #include <errno.h> 11 12 #include <rte_ether.h> 13 #include <ethdev_driver.h> 14 #include <rte_common.h> 15 16 #include "mlx5_defs.h" 17 #include "mlx5.h" 18 #include "mlx5_utils.h" 19 #include "mlx5_rxtx.h" 20 21 /** 22 * Remove a MAC address from the internal array. 23 * 24 * @param dev 25 * Pointer to Ethernet device structure. 26 * @param index 27 * MAC address index. 28 */ 29 static void 30 mlx5_internal_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) 31 { 32 MLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES); 33 if (rte_is_zero_ether_addr(&dev->data->mac_addrs[index])) 34 return; 35 mlx5_os_mac_addr_remove(dev, index); 36 memset(&dev->data->mac_addrs[index], 0, sizeof(struct rte_ether_addr)); 37 } 38 39 /** 40 * Adds a MAC address to the internal array. 41 * 42 * @param dev 43 * Pointer to Ethernet device structure. 44 * @param mac_addr 45 * MAC address to register. 46 * @param index 47 * MAC address index. 48 * 49 * @return 50 * 0 on success, a negative errno value otherwise and rte_errno is set. 51 */ 52 static int 53 mlx5_internal_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac, 54 uint32_t index) 55 { 56 unsigned int i; 57 int ret; 58 59 MLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES); 60 if (rte_is_zero_ether_addr(mac)) { 61 rte_errno = EINVAL; 62 return -rte_errno; 63 } 64 /* First, make sure this address isn't already configured. */ 65 for (i = 0; (i != MLX5_MAX_MAC_ADDRESSES); ++i) { 66 /* Skip this index, it's going to be reconfigured. */ 67 if (i == index) 68 continue; 69 if (memcmp(&dev->data->mac_addrs[i], mac, sizeof(*mac))) 70 continue; 71 /* Address already configured elsewhere, return with error. */ 72 rte_errno = EADDRINUSE; 73 return -rte_errno; 74 } 75 ret = mlx5_os_mac_addr_add(dev, mac, index); 76 if (ret) 77 return ret; 78 79 dev->data->mac_addrs[index] = *mac; 80 return 0; 81 } 82 83 /** 84 * DPDK callback to remove a MAC address. 85 * 86 * @param dev 87 * Pointer to Ethernet device structure. 88 * @param index 89 * MAC address index. 90 */ 91 void 92 mlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) 93 { 94 int ret; 95 96 if (index >= MLX5_MAX_UC_MAC_ADDRESSES) 97 return; 98 mlx5_internal_mac_addr_remove(dev, index); 99 if (!dev->data->promiscuous) { 100 ret = mlx5_traffic_restart(dev); 101 if (ret) 102 DRV_LOG(ERR, "port %u cannot restart traffic: %s", 103 dev->data->port_id, strerror(rte_errno)); 104 } 105 } 106 107 /** 108 * DPDK callback to add a MAC address. 109 * 110 * @param dev 111 * Pointer to Ethernet device structure. 112 * @param mac_addr 113 * MAC address to register. 114 * @param index 115 * MAC address index. 116 * @param vmdq 117 * VMDq pool index to associate address with (ignored). 118 * 119 * @return 120 * 0 on success, a negative errno value otherwise and rte_errno is set. 121 */ 122 int 123 mlx5_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac, 124 uint32_t index, uint32_t vmdq __rte_unused) 125 { 126 int ret; 127 128 if (index >= MLX5_MAX_UC_MAC_ADDRESSES) { 129 rte_errno = EINVAL; 130 return -rte_errno; 131 } 132 ret = mlx5_internal_mac_addr_add(dev, mac, index); 133 if (ret < 0) 134 return ret; 135 if (!dev->data->promiscuous) 136 return mlx5_traffic_restart(dev); 137 return 0; 138 } 139 140 /** 141 * DPDK callback to set primary MAC address. 142 * 143 * @param dev 144 * Pointer to Ethernet device structure. 145 * @param mac_addr 146 * MAC address to register. 147 * 148 * @return 149 * 0 on success, a negative errno value otherwise and rte_errno is set. 150 */ 151 int 152 mlx5_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr) 153 { 154 uint16_t port_id; 155 struct mlx5_priv *priv = dev->data->dev_private; 156 struct mlx5_priv *pf_priv; 157 158 /* 159 * Configuring the VF instead of its representor, 160 * need to skip the special case of HPF on Bluefield. 161 */ 162 if (priv->representor && !mlx5_is_hpf(dev) && !mlx5_is_sf_repr(dev)) { 163 DRV_LOG(DEBUG, "VF represented by port %u setting primary MAC address", 164 dev->data->port_id); 165 if (priv->pf_bond >= 0) { 166 /* Bonding, get owner PF ifindex from shared data. */ 167 return mlx5_os_vf_mac_addr_modify 168 (priv, 169 priv->sh->bond.ports[priv->pf_bond].ifindex, 170 mac_addr, 171 MLX5_REPRESENTOR_REPR(priv->representor_id)); 172 } 173 RTE_ETH_FOREACH_DEV_SIBLING(port_id, dev->data->port_id) { 174 pf_priv = rte_eth_devices[port_id].data->dev_private; 175 if (pf_priv->master == 1) 176 return mlx5_os_vf_mac_addr_modify 177 (priv, pf_priv->if_index, mac_addr, 178 MLX5_REPRESENTOR_REPR 179 (priv->representor_id)); 180 } 181 rte_errno = -ENOTSUP; 182 return rte_errno; 183 } 184 185 DRV_LOG(DEBUG, "port %u setting primary MAC address", 186 dev->data->port_id); 187 return mlx5_mac_addr_add(dev, mac_addr, 0, 0); 188 } 189 190 /** 191 * DPDK callback to set multicast addresses list. 192 * 193 * @see rte_eth_dev_set_mc_addr_list() 194 */ 195 int 196 mlx5_set_mc_addr_list(struct rte_eth_dev *dev, 197 struct rte_ether_addr *mc_addr_set, uint32_t nb_mc_addr) 198 { 199 uint32_t i; 200 int ret; 201 202 if (nb_mc_addr >= MLX5_MAX_MC_MAC_ADDRESSES) { 203 rte_errno = ENOSPC; 204 return -rte_errno; 205 } 206 for (i = MLX5_MAX_UC_MAC_ADDRESSES; i != MLX5_MAX_MAC_ADDRESSES; ++i) 207 mlx5_internal_mac_addr_remove(dev, i); 208 i = MLX5_MAX_UC_MAC_ADDRESSES; 209 while (nb_mc_addr--) { 210 ret = mlx5_internal_mac_addr_add(dev, mc_addr_set++, i++); 211 if (ret) 212 return ret; 213 } 214 if (!dev->data->promiscuous) 215 return mlx5_traffic_restart(dev); 216 return 0; 217 } 218