]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
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 <assert.h> | |
8 | #include <stdint.h> | |
9 | #include <string.h> | |
10 | #include <inttypes.h> | |
11 | #include <errno.h> | |
12 | #include <netinet/in.h> | |
13 | #include <sys/ioctl.h> | |
14 | #include <arpa/inet.h> | |
15 | ||
16 | /* Verbs header. */ | |
17 | /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ | |
18 | #ifdef PEDANTIC | |
19 | #pragma GCC diagnostic ignored "-Wpedantic" | |
20 | #endif | |
21 | #include <infiniband/verbs.h> | |
22 | #ifdef PEDANTIC | |
23 | #pragma GCC diagnostic error "-Wpedantic" | |
24 | #endif | |
25 | ||
26 | #include <rte_ether.h> | |
27 | #include <rte_ethdev_driver.h> | |
28 | #include <rte_common.h> | |
29 | ||
30 | #include "mlx5.h" | |
31 | #include "mlx5_utils.h" | |
32 | #include "mlx5_rxtx.h" | |
33 | #include "mlx5_defs.h" | |
34 | ||
35 | /** | |
36 | * Get MAC address by querying netdevice. | |
37 | * | |
38 | * @param[in] dev | |
39 | * Pointer to Ethernet device. | |
40 | * @param[out] mac | |
41 | * MAC address output buffer. | |
42 | * | |
43 | * @return | |
44 | * 0 on success, a negative errno value otherwise and rte_errno is set. | |
45 | */ | |
46 | int | |
47 | mlx5_get_mac(struct rte_eth_dev *dev, uint8_t (*mac)[ETHER_ADDR_LEN]) | |
48 | { | |
49 | struct ifreq request; | |
50 | int ret; | |
51 | ||
9f95a23c | 52 | ret = mlx5_ifreq(dev, SIOCGIFHWADDR, &request); |
11fdf7f2 TL |
53 | if (ret) |
54 | return ret; | |
55 | memcpy(mac, request.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); | |
56 | return 0; | |
57 | } | |
58 | ||
59 | /** | |
60 | * Remove a MAC address from the internal array. | |
61 | * | |
62 | * @param dev | |
63 | * Pointer to Ethernet device structure. | |
64 | * @param index | |
65 | * MAC address index. | |
66 | */ | |
67 | static void | |
68 | mlx5_internal_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) | |
69 | { | |
9f95a23c | 70 | struct mlx5_priv *priv = dev->data->dev_private; |
11fdf7f2 TL |
71 | const int vf = priv->config.vf; |
72 | ||
73 | assert(index < MLX5_MAX_MAC_ADDRESSES); | |
74 | if (is_zero_ether_addr(&dev->data->mac_addrs[index])) | |
75 | return; | |
76 | if (vf) | |
77 | mlx5_nl_mac_addr_remove(dev, &dev->data->mac_addrs[index], | |
78 | index); | |
79 | memset(&dev->data->mac_addrs[index], 0, sizeof(struct 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 ether_addr *mac, | |
97 | uint32_t index) | |
98 | { | |
9f95a23c | 99 | struct mlx5_priv *priv = dev->data->dev_private; |
11fdf7f2 TL |
100 | const int vf = priv->config.vf; |
101 | unsigned int i; | |
102 | ||
103 | assert(index < MLX5_MAX_MAC_ADDRESSES); | |
104 | if (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(dev, mac, index); | |
121 | ||
122 | if (ret) | |
123 | return ret; | |
124 | } | |
125 | dev->data->mac_addrs[index] = *mac; | |
126 | return 0; | |
127 | } | |
128 | ||
129 | /** | |
130 | * DPDK callback to remove a MAC address. | |
131 | * | |
132 | * @param dev | |
133 | * Pointer to Ethernet device structure. | |
134 | * @param index | |
135 | * MAC address index. | |
136 | */ | |
137 | void | |
138 | mlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) | |
139 | { | |
140 | int ret; | |
141 | ||
142 | if (index >= MLX5_MAX_UC_MAC_ADDRESSES) | |
143 | return; | |
144 | mlx5_internal_mac_addr_remove(dev, index); | |
145 | if (!dev->data->promiscuous) { | |
146 | ret = mlx5_traffic_restart(dev); | |
147 | if (ret) | |
148 | DRV_LOG(ERR, "port %u cannot restart traffic: %s", | |
149 | dev->data->port_id, strerror(rte_errno)); | |
150 | } | |
151 | } | |
152 | ||
153 | /** | |
154 | * DPDK callback to add a MAC address. | |
155 | * | |
156 | * @param dev | |
157 | * Pointer to Ethernet device structure. | |
158 | * @param mac_addr | |
159 | * MAC address to register. | |
160 | * @param index | |
161 | * MAC address index. | |
162 | * @param vmdq | |
163 | * VMDq pool index to associate address with (ignored). | |
164 | * | |
165 | * @return | |
166 | * 0 on success, a negative errno value otherwise and rte_errno is set. | |
167 | */ | |
168 | int | |
169 | mlx5_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac, | |
170 | uint32_t index, uint32_t vmdq __rte_unused) | |
171 | { | |
172 | int ret; | |
173 | ||
174 | if (index >= MLX5_MAX_UC_MAC_ADDRESSES) { | |
175 | rte_errno = EINVAL; | |
176 | return -rte_errno; | |
177 | } | |
178 | ret = mlx5_internal_mac_addr_add(dev, mac, index); | |
179 | if (ret < 0) | |
180 | return ret; | |
181 | if (!dev->data->promiscuous) | |
182 | return mlx5_traffic_restart(dev); | |
183 | return 0; | |
184 | } | |
185 | ||
186 | /** | |
187 | * DPDK callback to set primary MAC address. | |
188 | * | |
189 | * @param dev | |
190 | * Pointer to Ethernet device structure. | |
191 | * @param mac_addr | |
192 | * MAC address to register. | |
193 | * | |
194 | * @return | |
195 | * 0 on success, a negative errno value otherwise and rte_errno is set. | |
196 | */ | |
197 | int | |
198 | mlx5_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr) | |
199 | { | |
200 | DRV_LOG(DEBUG, "port %u setting primary MAC address", | |
201 | dev->data->port_id); | |
202 | return mlx5_mac_addr_add(dev, mac_addr, 0, 0); | |
203 | } | |
204 | ||
205 | /** | |
206 | * DPDK callback to set multicast addresses list. | |
207 | * | |
208 | * @see rte_eth_dev_set_mc_addr_list() | |
209 | */ | |
210 | int | |
211 | mlx5_set_mc_addr_list(struct rte_eth_dev *dev, | |
212 | struct ether_addr *mc_addr_set, uint32_t nb_mc_addr) | |
213 | { | |
214 | uint32_t i; | |
215 | int ret; | |
216 | ||
217 | if (nb_mc_addr >= MLX5_MAX_MC_MAC_ADDRESSES) { | |
218 | rte_errno = ENOSPC; | |
219 | return -rte_errno; | |
220 | } | |
221 | for (i = MLX5_MAX_UC_MAC_ADDRESSES; i != MLX5_MAX_MAC_ADDRESSES; ++i) | |
222 | mlx5_internal_mac_addr_remove(dev, i); | |
223 | i = MLX5_MAX_UC_MAC_ADDRESSES; | |
224 | while (nb_mc_addr--) { | |
225 | ret = mlx5_internal_mac_addr_add(dev, mc_addr_set++, i++); | |
226 | if (ret) | |
227 | return ret; | |
228 | } | |
229 | if (!dev->data->promiscuous) | |
230 | return mlx5_traffic_restart(dev); | |
231 | return 0; | |
232 | } |