1 /*- 2 * BSD LICENSE 3 * 4 * Copyright 2015 6WIND S.A. 5 * Copyright 2015 Mellanox. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of 6WIND S.A. nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <stddef.h> 35 #include <assert.h> 36 #include <stdint.h> 37 #include <string.h> 38 #include <inttypes.h> 39 #include <errno.h> 40 #include <netinet/in.h> 41 #include <sys/ioctl.h> 42 #include <arpa/inet.h> 43 44 /* Verbs header. */ 45 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ 46 #ifdef PEDANTIC 47 #pragma GCC diagnostic ignored "-Wpedantic" 48 #endif 49 #include <infiniband/verbs.h> 50 #ifdef PEDANTIC 51 #pragma GCC diagnostic error "-Wpedantic" 52 #endif 53 54 #include <rte_ether.h> 55 #include <rte_ethdev_driver.h> 56 #include <rte_common.h> 57 58 #include "mlx5.h" 59 #include "mlx5_utils.h" 60 #include "mlx5_rxtx.h" 61 #include "mlx5_defs.h" 62 63 /** 64 * Get MAC address by querying netdevice. 65 * 66 * @param[in] priv 67 * struct priv for the requested device. 68 * @param[out] mac 69 * MAC address output buffer. 70 * 71 * @return 72 * 0 on success, -1 on failure and errno is set. 73 */ 74 int 75 priv_get_mac(struct priv *priv, uint8_t (*mac)[ETHER_ADDR_LEN]) 76 { 77 struct ifreq request; 78 79 if (priv_ifreq(priv, SIOCGIFHWADDR, &request)) 80 return -1; 81 memcpy(mac, request.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); 82 return 0; 83 } 84 85 /** 86 * DPDK callback to remove a MAC address. 87 * 88 * @param dev 89 * Pointer to Ethernet device structure. 90 * @param index 91 * MAC address index. 92 */ 93 void 94 mlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) 95 { 96 assert(index < MLX5_MAX_MAC_ADDRESSES); 97 memset(&dev->data->mac_addrs[index], 0, sizeof(struct ether_addr)); 98 if (!dev->data->promiscuous) 99 mlx5_traffic_restart(dev); 100 } 101 102 /** 103 * DPDK callback to add a MAC address. 104 * 105 * @param dev 106 * Pointer to Ethernet device structure. 107 * @param mac_addr 108 * MAC address to register. 109 * @param index 110 * MAC address index. 111 * @param vmdq 112 * VMDq pool index to associate address with (ignored). 113 * 114 * @return 115 * 0 on success. 116 */ 117 int 118 mlx5_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac, 119 uint32_t index, uint32_t vmdq) 120 { 121 unsigned int i; 122 int ret = 0; 123 124 (void)vmdq; 125 assert(index < MLX5_MAX_MAC_ADDRESSES); 126 /* First, make sure this address isn't already configured. */ 127 for (i = 0; (i != MLX5_MAX_MAC_ADDRESSES); ++i) { 128 /* Skip this index, it's going to be reconfigured. */ 129 if (i == index) 130 continue; 131 if (memcmp(&dev->data->mac_addrs[i], mac, sizeof(*mac))) 132 continue; 133 /* Address already configured elsewhere, return with error. */ 134 return EADDRINUSE; 135 } 136 dev->data->mac_addrs[index] = *mac; 137 if (!dev->data->promiscuous) 138 mlx5_traffic_restart(dev); 139 return ret; 140 } 141 142 /** 143 * DPDK callback to set primary MAC address. 144 * 145 * @param dev 146 * Pointer to Ethernet device structure. 147 * @param mac_addr 148 * MAC address to register. 149 */ 150 void 151 mlx5_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr) 152 { 153 DEBUG("%p: setting primary MAC address", (void *)dev); 154 mlx5_mac_addr_add(dev, mac_addr, 0, 0); 155 } 156