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