net/bnx2x: replace macro with static function
[dpdk.git] / drivers / net / mlx5 / mlx5_mac.c
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 /* DPDK headers don't like -pedantic. */
55 #ifdef PEDANTIC
56 #pragma GCC diagnostic ignored "-Wpedantic"
57 #endif
58 #include <rte_ether.h>
59 #include <rte_ethdev.h>
60 #include <rte_common.h>
61 #ifdef PEDANTIC
62 #pragma GCC diagnostic error "-Wpedantic"
63 #endif
64
65 #include "mlx5.h"
66 #include "mlx5_utils.h"
67 #include "mlx5_rxtx.h"
68 #include "mlx5_defs.h"
69
70 /**
71  * Get MAC address by querying netdevice.
72  *
73  * @param[in] priv
74  *   struct priv for the requested device.
75  * @param[out] mac
76  *   MAC address output buffer.
77  *
78  * @return
79  *   0 on success, -1 on failure and errno is set.
80  */
81 int
82 priv_get_mac(struct priv *priv, uint8_t (*mac)[ETHER_ADDR_LEN])
83 {
84         struct ifreq request;
85
86         if (priv_ifreq(priv, SIOCGIFHWADDR, &request))
87                 return -1;
88         memcpy(mac, request.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
89         return 0;
90 }
91
92 /**
93  * Delete MAC flow steering rule.
94  *
95  * @param hash_rxq
96  *   Pointer to hash RX queue structure.
97  * @param mac_index
98  *   MAC address index.
99  * @param vlan_index
100  *   VLAN index to use.
101  */
102 static void
103 hash_rxq_del_mac_flow(struct hash_rxq *hash_rxq, unsigned int mac_index,
104                       unsigned int vlan_index)
105 {
106 #ifndef NDEBUG
107         const uint8_t (*mac)[ETHER_ADDR_LEN] =
108                 (const uint8_t (*)[ETHER_ADDR_LEN])
109                 hash_rxq->priv->mac[mac_index].addr_bytes;
110 #endif
111
112         assert(mac_index < RTE_DIM(hash_rxq->mac_flow));
113         assert(vlan_index < RTE_DIM(hash_rxq->mac_flow[mac_index]));
114         if (hash_rxq->mac_flow[mac_index][vlan_index] == NULL)
115                 return;
116         DEBUG("%p: removing MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u"
117               " VLAN index %u",
118               (void *)hash_rxq,
119               (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5],
120               mac_index,
121               vlan_index);
122         claim_zero(ibv_exp_destroy_flow(hash_rxq->mac_flow
123                                         [mac_index][vlan_index]));
124         hash_rxq->mac_flow[mac_index][vlan_index] = NULL;
125 }
126
127 /**
128  * Unregister a MAC address from a hash RX queue.
129  *
130  * @param hash_rxq
131  *   Pointer to hash RX queue structure.
132  * @param mac_index
133  *   MAC address index.
134  */
135 static void
136 hash_rxq_mac_addr_del(struct hash_rxq *hash_rxq, unsigned int mac_index)
137 {
138         unsigned int i;
139
140         assert(mac_index < RTE_DIM(hash_rxq->mac_flow));
141         for (i = 0; (i != RTE_DIM(hash_rxq->mac_flow[mac_index])); ++i)
142                 hash_rxq_del_mac_flow(hash_rxq, mac_index, i);
143 }
144
145 /**
146  * Unregister all MAC addresses from a hash RX queue.
147  *
148  * @param hash_rxq
149  *   Pointer to hash RX queue structure.
150  */
151 void
152 hash_rxq_mac_addrs_del(struct hash_rxq *hash_rxq)
153 {
154         unsigned int i;
155
156         for (i = 0; (i != RTE_DIM(hash_rxq->mac_flow)); ++i)
157                 hash_rxq_mac_addr_del(hash_rxq, i);
158 }
159
160 /**
161  * Unregister a MAC address.
162  *
163  * This is done for each hash RX queue.
164  *
165  * @param priv
166  *   Pointer to private structure.
167  * @param mac_index
168  *   MAC address index.
169  */
170 static void
171 priv_mac_addr_del(struct priv *priv, unsigned int mac_index)
172 {
173         unsigned int i;
174
175         assert(mac_index < RTE_DIM(priv->mac));
176         if (!BITFIELD_ISSET(priv->mac_configured, mac_index))
177                 return;
178         for (i = 0; (i != priv->hash_rxqs_n); ++i)
179                 hash_rxq_mac_addr_del(&(*priv->hash_rxqs)[i], mac_index);
180         BITFIELD_RESET(priv->mac_configured, mac_index);
181 }
182
183 /**
184  * Unregister all MAC addresses from all hash RX queues.
185  *
186  * @param priv
187  *   Pointer to private structure.
188  */
189 void
190 priv_mac_addrs_disable(struct priv *priv)
191 {
192         unsigned int i;
193
194         for (i = 0; (i != priv->hash_rxqs_n); ++i)
195                 hash_rxq_mac_addrs_del(&(*priv->hash_rxqs)[i]);
196 }
197
198 /**
199  * DPDK callback to remove a MAC address.
200  *
201  * @param dev
202  *   Pointer to Ethernet device structure.
203  * @param index
204  *   MAC address index.
205  */
206 void
207 mlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
208 {
209         struct priv *priv = dev->data->dev_private;
210
211         if (mlx5_is_secondary())
212                 return;
213
214         priv_lock(priv);
215         DEBUG("%p: removing MAC address from index %" PRIu32,
216               (void *)dev, index);
217         if (index >= RTE_DIM(priv->mac))
218                 goto end;
219         priv_mac_addr_del(priv, index);
220 end:
221         priv_unlock(priv);
222 }
223
224 /**
225  * Add MAC flow steering rule.
226  *
227  * @param hash_rxq
228  *   Pointer to hash RX queue structure.
229  * @param mac_index
230  *   MAC address index to register.
231  * @param vlan_index
232  *   VLAN index to use.
233  *
234  * @return
235  *   0 on success, errno value on failure.
236  */
237 static int
238 hash_rxq_add_mac_flow(struct hash_rxq *hash_rxq, unsigned int mac_index,
239                       unsigned int vlan_index)
240 {
241         struct ibv_exp_flow *flow;
242         struct priv *priv = hash_rxq->priv;
243         const uint8_t (*mac)[ETHER_ADDR_LEN] =
244                         (const uint8_t (*)[ETHER_ADDR_LEN])
245                         priv->mac[mac_index].addr_bytes;
246         FLOW_ATTR_SPEC_ETH(data, priv_flow_attr(priv, NULL, 0, hash_rxq->type));
247         struct ibv_exp_flow_attr *attr = &data->attr;
248         struct ibv_exp_flow_spec_eth *spec = &data->spec;
249         unsigned int vlan_enabled = !!priv->vlan_filter_n;
250         unsigned int vlan_id = priv->vlan_filter[vlan_index];
251
252         assert(mac_index < RTE_DIM(hash_rxq->mac_flow));
253         assert(vlan_index < RTE_DIM(hash_rxq->mac_flow[mac_index]));
254         if (hash_rxq->mac_flow[mac_index][vlan_index] != NULL)
255                 return 0;
256         /*
257          * No padding must be inserted by the compiler between attr and spec.
258          * This layout is expected by libibverbs.
259          */
260         assert(((uint8_t *)attr + sizeof(*attr)) == (uint8_t *)spec);
261         priv_flow_attr(priv, attr, sizeof(data), hash_rxq->type);
262         /* The first specification must be Ethernet. */
263         assert(spec->type == IBV_EXP_FLOW_SPEC_ETH);
264         assert(spec->size == sizeof(*spec));
265         *spec = (struct ibv_exp_flow_spec_eth){
266                 .type = IBV_EXP_FLOW_SPEC_ETH,
267                 .size = sizeof(*spec),
268                 .val = {
269                         .dst_mac = {
270                                 (*mac)[0], (*mac)[1], (*mac)[2],
271                                 (*mac)[3], (*mac)[4], (*mac)[5]
272                         },
273                         .vlan_tag = (vlan_enabled ? htons(vlan_id) : 0),
274                 },
275                 .mask = {
276                         .dst_mac = "\xff\xff\xff\xff\xff\xff",
277                         .vlan_tag = (vlan_enabled ? htons(0xfff) : 0),
278                 },
279         };
280         DEBUG("%p: adding MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u"
281               " VLAN index %u filtering %s, ID %u",
282               (void *)hash_rxq,
283               (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5],
284               mac_index,
285               vlan_index,
286               (vlan_enabled ? "enabled" : "disabled"),
287               vlan_id);
288         /* Create related flow. */
289         errno = 0;
290         flow = ibv_exp_create_flow(hash_rxq->qp, attr);
291         if (flow == NULL) {
292                 /* It's not clear whether errno is always set in this case. */
293                 ERROR("%p: flow configuration failed, errno=%d: %s",
294                       (void *)hash_rxq, errno,
295                       (errno ? strerror(errno) : "Unknown error"));
296                 if (errno)
297                         return errno;
298                 return EINVAL;
299         }
300         hash_rxq->mac_flow[mac_index][vlan_index] = flow;
301         return 0;
302 }
303
304 /**
305  * Register a MAC address in a hash RX queue.
306  *
307  * @param hash_rxq
308  *   Pointer to hash RX queue structure.
309  * @param mac_index
310  *   MAC address index to register.
311  *
312  * @return
313  *   0 on success, errno value on failure.
314  */
315 static int
316 hash_rxq_mac_addr_add(struct hash_rxq *hash_rxq, unsigned int mac_index)
317 {
318         struct priv *priv = hash_rxq->priv;
319         unsigned int i = 0;
320         int ret;
321
322         assert(mac_index < RTE_DIM(hash_rxq->mac_flow));
323         assert(RTE_DIM(hash_rxq->mac_flow[mac_index]) ==
324                RTE_DIM(priv->vlan_filter));
325         /* Add a MAC address for each VLAN filter, or at least once. */
326         do {
327                 ret = hash_rxq_add_mac_flow(hash_rxq, mac_index, i);
328                 if (ret) {
329                         /* Failure, rollback. */
330                         while (i != 0)
331                                 hash_rxq_del_mac_flow(hash_rxq, mac_index,
332                                                       --i);
333                         return ret;
334                 }
335         } while (++i < priv->vlan_filter_n);
336         return 0;
337 }
338
339 /**
340  * Register all MAC addresses in a hash RX queue.
341  *
342  * @param hash_rxq
343  *   Pointer to hash RX queue structure.
344  *
345  * @return
346  *   0 on success, errno value on failure.
347  */
348 int
349 hash_rxq_mac_addrs_add(struct hash_rxq *hash_rxq)
350 {
351         struct priv *priv = hash_rxq->priv;
352         unsigned int i;
353         int ret;
354
355         assert(RTE_DIM(priv->mac) == RTE_DIM(hash_rxq->mac_flow));
356         for (i = 0; (i != RTE_DIM(priv->mac)); ++i) {
357                 if (!BITFIELD_ISSET(priv->mac_configured, i))
358                         continue;
359                 ret = hash_rxq_mac_addr_add(hash_rxq, i);
360                 if (!ret)
361                         continue;
362                 /* Failure, rollback. */
363                 while (i != 0)
364                         hash_rxq_mac_addr_del(hash_rxq, --i);
365                 assert(ret > 0);
366                 return ret;
367         }
368         return 0;
369 }
370
371 /**
372  * Register a MAC address.
373  *
374  * This is done for each hash RX queue.
375  *
376  * @param priv
377  *   Pointer to private structure.
378  * @param mac_index
379  *   MAC address index to use.
380  * @param mac
381  *   MAC address to register.
382  *
383  * @return
384  *   0 on success, errno value on failure.
385  */
386 int
387 priv_mac_addr_add(struct priv *priv, unsigned int mac_index,
388                   const uint8_t (*mac)[ETHER_ADDR_LEN])
389 {
390         unsigned int i;
391         int ret;
392
393         assert(mac_index < RTE_DIM(priv->mac));
394         /* First, make sure this address isn't already configured. */
395         for (i = 0; (i != RTE_DIM(priv->mac)); ++i) {
396                 /* Skip this index, it's going to be reconfigured. */
397                 if (i == mac_index)
398                         continue;
399                 if (!BITFIELD_ISSET(priv->mac_configured, i))
400                         continue;
401                 if (memcmp(priv->mac[i].addr_bytes, *mac, sizeof(*mac)))
402                         continue;
403                 /* Address already configured elsewhere, return with error. */
404                 return EADDRINUSE;
405         }
406         if (BITFIELD_ISSET(priv->mac_configured, mac_index))
407                 priv_mac_addr_del(priv, mac_index);
408         priv->mac[mac_index] = (struct ether_addr){
409                 {
410                         (*mac)[0], (*mac)[1], (*mac)[2],
411                         (*mac)[3], (*mac)[4], (*mac)[5]
412                 }
413         };
414         if (!priv_allow_flow_type(priv, HASH_RXQ_FLOW_TYPE_MAC))
415                 goto end;
416         for (i = 0; (i != priv->hash_rxqs_n); ++i) {
417                 ret = hash_rxq_mac_addr_add(&(*priv->hash_rxqs)[i], mac_index);
418                 if (!ret)
419                         continue;
420                 /* Failure, rollback. */
421                 while (i != 0)
422                         hash_rxq_mac_addr_del(&(*priv->hash_rxqs)[--i],
423                                               mac_index);
424                 return ret;
425         }
426 end:
427         BITFIELD_SET(priv->mac_configured, mac_index);
428         return 0;
429 }
430
431 /**
432  * Register all MAC addresses in all hash RX queues.
433  *
434  * @param priv
435  *   Pointer to private structure.
436  *
437  * @return
438  *   0 on success, errno value on failure.
439  */
440 int
441 priv_mac_addrs_enable(struct priv *priv)
442 {
443         unsigned int i;
444         int ret;
445
446         if (!priv_allow_flow_type(priv, HASH_RXQ_FLOW_TYPE_MAC))
447                 return 0;
448         for (i = 0; (i != priv->hash_rxqs_n); ++i) {
449                 ret = hash_rxq_mac_addrs_add(&(*priv->hash_rxqs)[i]);
450                 if (!ret)
451                         continue;
452                 /* Failure, rollback. */
453                 while (i != 0)
454                         hash_rxq_mac_addrs_del(&(*priv->hash_rxqs)[--i]);
455                 assert(ret > 0);
456                 return ret;
457         }
458         return 0;
459 }
460
461 /**
462  * DPDK callback to add a MAC address.
463  *
464  * @param dev
465  *   Pointer to Ethernet device structure.
466  * @param mac_addr
467  *   MAC address to register.
468  * @param index
469  *   MAC address index.
470  * @param vmdq
471  *   VMDq pool index to associate address with (ignored).
472  */
473 void
474 mlx5_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
475                   uint32_t index, uint32_t vmdq)
476 {
477         struct priv *priv = dev->data->dev_private;
478
479         if (mlx5_is_secondary())
480                 return;
481
482         (void)vmdq;
483         priv_lock(priv);
484         DEBUG("%p: adding MAC address at index %" PRIu32,
485               (void *)dev, index);
486         if (index >= RTE_DIM(priv->mac))
487                 goto end;
488         priv_mac_addr_add(priv, index,
489                           (const uint8_t (*)[ETHER_ADDR_LEN])
490                           mac_addr->addr_bytes);
491 end:
492         priv_unlock(priv);
493 }
494
495 /**
496  * DPDK callback to set primary MAC address.
497  *
498  * @param dev
499  *   Pointer to Ethernet device structure.
500  * @param mac_addr
501  *   MAC address to register.
502  */
503 void
504 mlx5_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
505 {
506         DEBUG("%p: setting primary MAC address", (void *)dev);
507         mlx5_mac_addr_remove(dev, 0);
508         mlx5_mac_addr_add(dev, mac_addr, 0, 0);
509 }