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 #include <netinet/in.h> 12 #include <sys/ioctl.h> 13 #include <arpa/inet.h> 14 15 /* Verbs header. */ 16 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ 17 #ifdef PEDANTIC 18 #pragma GCC diagnostic ignored "-Wpedantic" 19 #endif 20 #include <infiniband/verbs.h> 21 #ifdef PEDANTIC 22 #pragma GCC diagnostic error "-Wpedantic" 23 #endif 24 25 #include <rte_ether.h> 26 #include <rte_ethdev_driver.h> 27 #include <rte_common.h> 28 29 #include "mlx5_defs.h" 30 #include "mlx5.h" 31 #include "mlx5_utils.h" 32 #include "mlx5_rxtx.h" 33 34 /** 35 * Get MAC address by querying netdevice. 36 * 37 * @param[in] dev 38 * Pointer to Ethernet device. 39 * @param[out] mac 40 * MAC address output buffer. 41 * 42 * @return 43 * 0 on success, a negative errno value otherwise and rte_errno is set. 44 */ 45 int 46 mlx5_get_mac(struct rte_eth_dev *dev, uint8_t (*mac)[RTE_ETHER_ADDR_LEN]) 47 { 48 struct ifreq request; 49 int ret; 50 51 ret = mlx5_ifreq(dev, SIOCGIFHWADDR, &request); 52 if (ret) 53 return ret; 54 memcpy(mac, request.ifr_hwaddr.sa_data, RTE_ETHER_ADDR_LEN); 55 return 0; 56 } 57 58 /** 59 * Remove a MAC address from the internal array. 60 * 61 * @param dev 62 * Pointer to Ethernet device structure. 63 * @param index 64 * MAC address index. 65 */ 66 static void 67 mlx5_internal_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) 68 { 69 struct mlx5_priv *priv = dev->data->dev_private; 70 const int vf = priv->config.vf; 71 72 MLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES); 73 if (rte_is_zero_ether_addr(&dev->data->mac_addrs[index])) 74 return; 75 if (vf) 76 mlx5_nl_mac_addr_remove(priv->nl_socket_route, 77 mlx5_ifindex(dev), priv->mac_own, 78 &dev->data->mac_addrs[index], index); 79 memset(&dev->data->mac_addrs[index], 0, sizeof(struct rte_ether_addr)); 80 } 81 82 /** 83 * Adds a MAC address to the internal array. 84 * 85 * @param dev 86 * Pointer to Ethernet device structure. 87 * @param mac_addr 88 * MAC address to register. 89 * @param index 90 * MAC address index. 91 * 92 * @return 93 * 0 on success, a negative errno value otherwise and rte_errno is set. 94 */ 95 static int 96 mlx5_internal_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac, 97 uint32_t index) 98 { 99 struct mlx5_priv *priv = dev->data->dev_private; 100 const int vf = priv->config.vf; 101 unsigned int i; 102 103 MLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES); 104 if (rte_is_zero_ether_addr(mac)) { 105 rte_errno = EINVAL; 106 return -rte_errno; 107 } 108 /* First, make sure this address isn't already configured. */ 109 for (i = 0; (i != MLX5_MAX_MAC_ADDRESSES); ++i) { 110 /* Skip this index, it's going to be reconfigured. */ 111 if (i == index) 112 continue; 113 if (memcmp(&dev->data->mac_addrs[i], mac, sizeof(*mac))) 114 continue; 115 /* Address already configured elsewhere, return with error. */ 116 rte_errno = EADDRINUSE; 117 return -rte_errno; 118 } 119 if (vf) { 120 int ret = mlx5_nl_mac_addr_add(priv->nl_socket_route, 121 mlx5_ifindex(dev), priv->mac_own, 122 mac, index); 123 124 if (ret) 125 return ret; 126 } 127 dev->data->mac_addrs[index] = *mac; 128 return 0; 129 } 130 131 /** 132 * DPDK callback to remove a MAC address. 133 * 134 * @param dev 135 * Pointer to Ethernet device structure. 136 * @param index 137 * MAC address index. 138 */ 139 void 140 mlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) 141 { 142 int ret; 143 144 if (index >= MLX5_MAX_UC_MAC_ADDRESSES) 145 return; 146 mlx5_internal_mac_addr_remove(dev, index); 147 if (!dev->data->promiscuous) { 148 ret = mlx5_traffic_restart(dev); 149 if (ret) 150 DRV_LOG(ERR, "port %u cannot restart traffic: %s", 151 dev->data->port_id, strerror(rte_errno)); 152 } 153 } 154 155 /** 156 * DPDK callback to add a MAC address. 157 * 158 * @param dev 159 * Pointer to Ethernet device structure. 160 * @param mac_addr 161 * MAC address to register. 162 * @param index 163 * MAC address index. 164 * @param vmdq 165 * VMDq pool index to associate address with (ignored). 166 * 167 * @return 168 * 0 on success, a negative errno value otherwise and rte_errno is set. 169 */ 170 int 171 mlx5_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac, 172 uint32_t index, uint32_t vmdq __rte_unused) 173 { 174 int ret; 175 176 if (index >= MLX5_MAX_UC_MAC_ADDRESSES) { 177 rte_errno = EINVAL; 178 return -rte_errno; 179 } 180 ret = mlx5_internal_mac_addr_add(dev, mac, index); 181 if (ret < 0) 182 return ret; 183 if (!dev->data->promiscuous) 184 return mlx5_traffic_restart(dev); 185 return 0; 186 } 187 188 /** 189 * DPDK callback to set primary MAC address. 190 * 191 * @param dev 192 * Pointer to Ethernet device structure. 193 * @param mac_addr 194 * MAC address to register. 195 * 196 * @return 197 * 0 on success, a negative errno value otherwise and rte_errno is set. 198 */ 199 int 200 mlx5_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr) 201 { 202 uint16_t port_id; 203 struct mlx5_priv *priv = dev->data->dev_private; 204 205 /* Configuring the VF instead of its representor. */ 206 if (priv->representor) { 207 DRV_LOG(DEBUG, "VF represented by port %u setting primary MAC address", 208 dev->data->port_id); 209 RTE_ETH_FOREACH_DEV_SIBLING(port_id, dev->data->port_id) { 210 priv = rte_eth_devices[port_id].data->dev_private; 211 if (priv->master == 1) { 212 priv = dev->data->dev_private; 213 return mlx5_nl_vf_mac_addr_modify 214 (priv->nl_socket_route, 215 mlx5_ifindex(&rte_eth_devices[port_id]), 216 mac_addr, priv->representor_id); 217 } 218 } 219 rte_errno = -ENOTSUP; 220 return rte_errno; 221 } 222 223 DRV_LOG(DEBUG, "port %u setting primary MAC address", 224 dev->data->port_id); 225 return mlx5_mac_addr_add(dev, mac_addr, 0, 0); 226 } 227 228 /** 229 * DPDK callback to set multicast addresses list. 230 * 231 * @see rte_eth_dev_set_mc_addr_list() 232 */ 233 int 234 mlx5_set_mc_addr_list(struct rte_eth_dev *dev, 235 struct rte_ether_addr *mc_addr_set, uint32_t nb_mc_addr) 236 { 237 uint32_t i; 238 int ret; 239 240 if (nb_mc_addr >= MLX5_MAX_MC_MAC_ADDRESSES) { 241 rte_errno = ENOSPC; 242 return -rte_errno; 243 } 244 for (i = MLX5_MAX_UC_MAC_ADDRESSES; i != MLX5_MAX_MAC_ADDRESSES; ++i) 245 mlx5_internal_mac_addr_remove(dev, i); 246 i = MLX5_MAX_UC_MAC_ADDRESSES; 247 while (nb_mc_addr--) { 248 ret = mlx5_internal_mac_addr_add(dev, mc_addr_set++, i++); 249 if (ret) 250 return ret; 251 } 252 if (!dev->data->promiscuous) 253 return mlx5_traffic_restart(dev); 254 return 0; 255 } 256