mlx5: refactor Rx code for the new verbs RSS API
[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_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_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         struct __attribute__((packed)) {
246                 struct ibv_flow_attr attr;
247                 struct ibv_flow_spec_eth spec;
248         } data;
249         struct ibv_flow_attr *attr = &data.attr;
250         struct ibv_flow_spec_eth *spec = &data.spec;
251         unsigned int vlan_enabled = !!priv->vlan_filter_n;
252         unsigned int vlan_id = priv->vlan_filter[vlan_index];
253
254         assert(mac_index < RTE_DIM(hash_rxq->mac_flow));
255         assert(vlan_index < RTE_DIM(hash_rxq->mac_flow[mac_index]));
256         if (hash_rxq->mac_flow[mac_index][vlan_index] != NULL)
257                 return 0;
258         /*
259          * No padding must be inserted by the compiler between attr and spec.
260          * This layout is expected by libibverbs.
261          */
262         assert(((uint8_t *)attr + sizeof(*attr)) == (uint8_t *)spec);
263         *attr = (struct ibv_flow_attr){
264                 .type = IBV_FLOW_ATTR_NORMAL,
265                 .num_of_specs = 1,
266                 .port = priv->port,
267                 .flags = 0
268         };
269         *spec = (struct ibv_flow_spec_eth){
270                 .type = IBV_FLOW_SPEC_ETH,
271                 .size = sizeof(*spec),
272                 .val = {
273                         .dst_mac = {
274                                 (*mac)[0], (*mac)[1], (*mac)[2],
275                                 (*mac)[3], (*mac)[4], (*mac)[5]
276                         },
277                         .vlan_tag = (vlan_enabled ? htons(vlan_id) : 0),
278                 },
279                 .mask = {
280                         .dst_mac = "\xff\xff\xff\xff\xff\xff",
281                         .vlan_tag = (vlan_enabled ? htons(0xfff) : 0),
282                 },
283         };
284         DEBUG("%p: adding MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u"
285               " VLAN index %u filtering %s, ID %u",
286               (void *)hash_rxq,
287               (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5],
288               mac_index,
289               vlan_index,
290               (vlan_enabled ? "enabled" : "disabled"),
291               vlan_id);
292         /* Create related flow. */
293         errno = 0;
294         flow = ibv_create_flow(hash_rxq->qp, attr);
295         if (flow == NULL) {
296                 /* It's not clear whether errno is always set in this case. */
297                 ERROR("%p: flow configuration failed, errno=%d: %s",
298                       (void *)hash_rxq, errno,
299                       (errno ? strerror(errno) : "Unknown error"));
300                 if (errno)
301                         return errno;
302                 return EINVAL;
303         }
304         hash_rxq->mac_flow[mac_index][vlan_index] = flow;
305         return 0;
306 }
307
308 /**
309  * Register a MAC address in a hash RX queue.
310  *
311  * @param hash_rxq
312  *   Pointer to hash RX queue structure.
313  * @param mac_index
314  *   MAC address index to register.
315  *
316  * @return
317  *   0 on success, errno value on failure.
318  */
319 static int
320 hash_rxq_mac_addr_add(struct hash_rxq *hash_rxq, unsigned int mac_index)
321 {
322         struct priv *priv = hash_rxq->priv;
323         unsigned int i = 0;
324         int ret;
325
326         assert(mac_index < RTE_DIM(hash_rxq->mac_flow));
327         assert(RTE_DIM(hash_rxq->mac_flow[mac_index]) ==
328                RTE_DIM(priv->vlan_filter));
329         /* Add a MAC address for each VLAN filter, or at least once. */
330         do {
331                 ret = hash_rxq_add_mac_flow(hash_rxq, mac_index, i);
332                 if (ret) {
333                         /* Failure, rollback. */
334                         while (i != 0)
335                                 hash_rxq_del_mac_flow(hash_rxq, mac_index,
336                                                       --i);
337                         return ret;
338                 }
339         } while (++i < priv->vlan_filter_n);
340         return 0;
341 }
342
343 /**
344  * Register all MAC addresses in a hash RX queue.
345  *
346  * @param hash_rxq
347  *   Pointer to hash RX queue structure.
348  *
349  * @return
350  *   0 on success, errno value on failure.
351  */
352 int
353 hash_rxq_mac_addrs_add(struct hash_rxq *hash_rxq)
354 {
355         struct priv *priv = hash_rxq->priv;
356         unsigned int i;
357         int ret;
358
359         assert(RTE_DIM(priv->mac) == RTE_DIM(hash_rxq->mac_flow));
360         for (i = 0; (i != RTE_DIM(priv->mac)); ++i) {
361                 if (!BITFIELD_ISSET(priv->mac_configured, i))
362                         continue;
363                 ret = hash_rxq_mac_addr_add(hash_rxq, i);
364                 if (!ret)
365                         continue;
366                 /* Failure, rollback. */
367                 while (i != 0)
368                         hash_rxq_mac_addr_del(hash_rxq, --i);
369                 assert(ret > 0);
370                 return ret;
371         }
372         return 0;
373 }
374
375 /**
376  * Register a MAC address.
377  *
378  * This is done for each hash RX queue.
379  *
380  * @param priv
381  *   Pointer to private structure.
382  * @param mac_index
383  *   MAC address index to use.
384  * @param mac
385  *   MAC address to register.
386  *
387  * @return
388  *   0 on success, errno value on failure.
389  */
390 int
391 priv_mac_addr_add(struct priv *priv, unsigned int mac_index,
392                   const uint8_t (*mac)[ETHER_ADDR_LEN])
393 {
394         unsigned int i;
395         int ret;
396
397         assert(mac_index < RTE_DIM(priv->mac));
398         /* First, make sure this address isn't already configured. */
399         for (i = 0; (i != RTE_DIM(priv->mac)); ++i) {
400                 /* Skip this index, it's going to be reconfigured. */
401                 if (i == mac_index)
402                         continue;
403                 if (!BITFIELD_ISSET(priv->mac_configured, i))
404                         continue;
405                 if (memcmp(priv->mac[i].addr_bytes, *mac, sizeof(*mac)))
406                         continue;
407                 /* Address already configured elsewhere, return with error. */
408                 return EADDRINUSE;
409         }
410         if (BITFIELD_ISSET(priv->mac_configured, mac_index))
411                 priv_mac_addr_del(priv, mac_index);
412         priv->mac[mac_index] = (struct ether_addr){
413                 {
414                         (*mac)[0], (*mac)[1], (*mac)[2],
415                         (*mac)[3], (*mac)[4], (*mac)[5]
416                 }
417         };
418         for (i = 0; (i != priv->hash_rxqs_n); ++i) {
419                 ret = hash_rxq_mac_addr_add(&(*priv->hash_rxqs)[i], mac_index);
420                 if (!ret)
421                         continue;
422                 /* Failure, rollback. */
423                 while (i != 0)
424                         hash_rxq_mac_addr_del(&(*priv->hash_rxqs)[--i],
425                                               mac_index);
426                 return ret;
427         }
428         BITFIELD_SET(priv->mac_configured, mac_index);
429         return 0;
430 }
431
432 /**
433  * Register all MAC addresses in all hash RX queues.
434  *
435  * @param priv
436  *   Pointer to private structure.
437  *
438  * @return
439  *   0 on success, errno value on failure.
440  */
441 int
442 priv_mac_addrs_enable(struct priv *priv)
443 {
444         unsigned int i;
445         int ret;
446
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 }