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 * Remove a MAC address from the internal array. 36 * 37 * @param dev 38 * Pointer to Ethernet device structure. 39 * @param index 40 * MAC address index. 41 */ 42 static void 43 mlx5_internal_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) 44 { 45 MLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES); 46 if (rte_is_zero_ether_addr(&dev->data->mac_addrs[index])) 47 return; 48 mlx5_os_mac_addr_remove(dev, index); 49 memset(&dev->data->mac_addrs[index], 0, sizeof(struct rte_ether_addr)); 50 } 51 52 /** 53 * Adds a MAC address to the internal array. 54 * 55 * @param dev 56 * Pointer to Ethernet device structure. 57 * @param mac_addr 58 * MAC address to register. 59 * @param index 60 * MAC address index. 61 * 62 * @return 63 * 0 on success, a negative errno value otherwise and rte_errno is set. 64 */ 65 static int 66 mlx5_internal_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac, 67 uint32_t index) 68 { 69 unsigned int i; 70 int ret; 71 72 MLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES); 73 if (rte_is_zero_ether_addr(mac)) { 74 rte_errno = EINVAL; 75 return -rte_errno; 76 } 77 /* First, make sure this address isn't already configured. */ 78 for (i = 0; (i != MLX5_MAX_MAC_ADDRESSES); ++i) { 79 /* Skip this index, it's going to be reconfigured. */ 80 if (i == index) 81 continue; 82 if (memcmp(&dev->data->mac_addrs[i], mac, sizeof(*mac))) 83 continue; 84 /* Address already configured elsewhere, return with error. */ 85 rte_errno = EADDRINUSE; 86 return -rte_errno; 87 } 88 ret = mlx5_os_mac_addr_add(dev, mac, index); 89 if (ret) 90 return ret; 91 92 dev->data->mac_addrs[index] = *mac; 93 return 0; 94 } 95 96 /** 97 * DPDK callback to remove a MAC address. 98 * 99 * @param dev 100 * Pointer to Ethernet device structure. 101 * @param index 102 * MAC address index. 103 */ 104 void 105 mlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) 106 { 107 int ret; 108 109 if (index >= MLX5_MAX_UC_MAC_ADDRESSES) 110 return; 111 mlx5_internal_mac_addr_remove(dev, index); 112 if (!dev->data->promiscuous) { 113 ret = mlx5_traffic_restart(dev); 114 if (ret) 115 DRV_LOG(ERR, "port %u cannot restart traffic: %s", 116 dev->data->port_id, strerror(rte_errno)); 117 } 118 } 119 120 /** 121 * DPDK callback to add a MAC address. 122 * 123 * @param dev 124 * Pointer to Ethernet device structure. 125 * @param mac_addr 126 * MAC address to register. 127 * @param index 128 * MAC address index. 129 * @param vmdq 130 * VMDq pool index to associate address with (ignored). 131 * 132 * @return 133 * 0 on success, a negative errno value otherwise and rte_errno is set. 134 */ 135 int 136 mlx5_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac, 137 uint32_t index, uint32_t vmdq __rte_unused) 138 { 139 int ret; 140 141 if (index >= MLX5_MAX_UC_MAC_ADDRESSES) { 142 rte_errno = EINVAL; 143 return -rte_errno; 144 } 145 ret = mlx5_internal_mac_addr_add(dev, mac, index); 146 if (ret < 0) 147 return ret; 148 if (!dev->data->promiscuous) 149 return mlx5_traffic_restart(dev); 150 return 0; 151 } 152 153 /** 154 * DPDK callback to set primary MAC address. 155 * 156 * @param dev 157 * Pointer to Ethernet device structure. 158 * @param mac_addr 159 * MAC address to register. 160 * 161 * @return 162 * 0 on success, a negative errno value otherwise and rte_errno is set. 163 */ 164 int 165 mlx5_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr) 166 { 167 uint16_t port_id; 168 struct mlx5_priv *priv = dev->data->dev_private; 169 170 /* Configuring the VF instead of its representor. */ 171 if (priv->representor) { 172 DRV_LOG(DEBUG, "VF represented by port %u setting primary MAC address", 173 dev->data->port_id); 174 RTE_ETH_FOREACH_DEV_SIBLING(port_id, dev->data->port_id) { 175 priv = rte_eth_devices[port_id].data->dev_private; 176 if (priv->master == 1) { 177 priv = dev->data->dev_private; 178 return mlx5_os_vf_mac_addr_modify 179 (priv, 180 mlx5_ifindex(&rte_eth_devices[port_id]), 181 mac_addr, priv->representor_id); 182 } 183 } 184 rte_errno = -ENOTSUP; 185 return rte_errno; 186 } 187 188 DRV_LOG(DEBUG, "port %u setting primary MAC address", 189 dev->data->port_id); 190 return mlx5_mac_addr_add(dev, mac_addr, 0, 0); 191 } 192 193 /** 194 * DPDK callback to set multicast addresses list. 195 * 196 * @see rte_eth_dev_set_mc_addr_list() 197 */ 198 int 199 mlx5_set_mc_addr_list(struct rte_eth_dev *dev, 200 struct rte_ether_addr *mc_addr_set, uint32_t nb_mc_addr) 201 { 202 uint32_t i; 203 int ret; 204 205 if (nb_mc_addr >= MLX5_MAX_MC_MAC_ADDRESSES) { 206 rte_errno = ENOSPC; 207 return -rte_errno; 208 } 209 for (i = MLX5_MAX_UC_MAC_ADDRESSES; i != MLX5_MAX_MAC_ADDRESSES; ++i) 210 mlx5_internal_mac_addr_remove(dev, i); 211 i = MLX5_MAX_UC_MAC_ADDRESSES; 212 while (nb_mc_addr--) { 213 ret = mlx5_internal_mac_addr_add(dev, mc_addr_set++, i++); 214 if (ret) 215 return ret; 216 } 217 if (!dev->data->promiscuous) 218 return mlx5_traffic_restart(dev); 219 return 0; 220 } 221