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