mlx5: support VLAN filtering
[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 rxq
97  *   Pointer to 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 rxq_del_mac_flow(struct rxq *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                 rxq->priv->mac[mac_index].addr_bytes;
111 #endif
112
113         assert(mac_index < RTE_DIM(rxq->mac_flow));
114         assert(vlan_index < RTE_DIM(rxq->mac_flow[mac_index]));
115         if (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 *)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(rxq->mac_flow[mac_index][vlan_index]));
124         rxq->mac_flow[mac_index][vlan_index] = NULL;
125 }
126
127 /**
128  * Unregister a MAC address from a RX queue.
129  *
130  * @param rxq
131  *   Pointer to RX queue structure.
132  * @param mac_index
133  *   MAC address index.
134  */
135 static void
136 rxq_mac_addr_del(struct rxq *rxq, unsigned int mac_index)
137 {
138         unsigned int i;
139
140         assert(mac_index < RTE_DIM(rxq->mac_flow));
141         for (i = 0; (i != RTE_DIM(rxq->mac_flow[mac_index])); ++i)
142                 rxq_del_mac_flow(rxq, mac_index, i);
143 }
144
145 /**
146  * Unregister all MAC addresses from a RX queue.
147  *
148  * @param rxq
149  *   Pointer to RX queue structure.
150  */
151 void
152 rxq_mac_addrs_del(struct rxq *rxq)
153 {
154         unsigned int i;
155
156         for (i = 0; (i != RTE_DIM(rxq->mac_flow)); ++i)
157                 rxq_mac_addr_del(rxq, i);
158 }
159
160 /**
161  * Unregister a MAC address.
162  *
163  * In RSS mode, the MAC address is unregistered from the parent queue,
164  * otherwise it is unregistered from each queue directly.
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         if (priv->rss) {
180                 rxq_mac_addr_del(&priv->rxq_parent, mac_index);
181                 goto end;
182         }
183         for (i = 0; (i != priv->dev->data->nb_rx_queues); ++i)
184                 rxq_mac_addr_del((*priv->rxqs)[i], mac_index);
185 end:
186         BITFIELD_RESET(priv->mac_configured, mac_index);
187 }
188
189 /**
190  * DPDK callback to remove a MAC address.
191  *
192  * @param dev
193  *   Pointer to Ethernet device structure.
194  * @param index
195  *   MAC address index.
196  */
197 void
198 mlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
199 {
200         struct priv *priv = dev->data->dev_private;
201
202         priv_lock(priv);
203         DEBUG("%p: removing MAC address from index %" PRIu32,
204               (void *)dev, index);
205         /* Last array entry is reserved for broadcast. */
206         if (index >= (RTE_DIM(priv->mac) - 1))
207                 goto end;
208         priv_mac_addr_del(priv, index);
209 end:
210         priv_unlock(priv);
211 }
212
213 /**
214  * Add MAC flow steering rule.
215  *
216  * @param rxq
217  *   Pointer to RX queue structure.
218  * @param mac_index
219  *   MAC address index to register.
220  * @param vlan_index
221  *   VLAN index to use.
222  *
223  * @return
224  *   0 on success, errno value on failure.
225  */
226 static int
227 rxq_add_mac_flow(struct rxq *rxq, unsigned int mac_index,
228                  unsigned int vlan_index)
229 {
230         struct ibv_flow *flow;
231         struct priv *priv = rxq->priv;
232         const uint8_t (*mac)[ETHER_ADDR_LEN] =
233                         (const uint8_t (*)[ETHER_ADDR_LEN])
234                         priv->mac[mac_index].addr_bytes;
235         struct __attribute__((packed)) {
236                 struct ibv_flow_attr attr;
237                 struct ibv_flow_spec_eth spec;
238         } data;
239         struct ibv_flow_attr *attr = &data.attr;
240         struct ibv_flow_spec_eth *spec = &data.spec;
241         unsigned int vlan_enabled = !!priv->vlan_filter_n;
242         unsigned int vlan_id = priv->vlan_filter[vlan_index];
243
244         assert(mac_index < RTE_DIM(rxq->mac_flow));
245         assert(vlan_index < RTE_DIM(rxq->mac_flow[mac_index]));
246         if (rxq->mac_flow[mac_index][vlan_index] != NULL)
247                 return 0;
248         /*
249          * No padding must be inserted by the compiler between attr and spec.
250          * This layout is expected by libibverbs.
251          */
252         assert(((uint8_t *)attr + sizeof(*attr)) == (uint8_t *)spec);
253         *attr = (struct ibv_flow_attr){
254                 .type = IBV_FLOW_ATTR_NORMAL,
255                 .num_of_specs = 1,
256                 .port = priv->port,
257                 .flags = 0
258         };
259         *spec = (struct ibv_flow_spec_eth){
260                 .type = IBV_FLOW_SPEC_ETH,
261                 .size = sizeof(*spec),
262                 .val = {
263                         .dst_mac = {
264                                 (*mac)[0], (*mac)[1], (*mac)[2],
265                                 (*mac)[3], (*mac)[4], (*mac)[5]
266                         },
267                         .vlan_tag = (vlan_enabled ? htons(vlan_id) : 0),
268                 },
269                 .mask = {
270                         .dst_mac = "\xff\xff\xff\xff\xff\xff",
271                         .vlan_tag = (vlan_enabled ? htons(0xfff) : 0),
272                 },
273         };
274         DEBUG("%p: adding MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u"
275               " VLAN index %u filtering %s, ID %u",
276               (void *)rxq,
277               (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5],
278               mac_index,
279               vlan_index,
280               (vlan_enabled ? "enabled" : "disabled"),
281               vlan_id);
282         /* Create related flow. */
283         errno = 0;
284         flow = ibv_create_flow(rxq->qp, attr);
285         if (flow == NULL) {
286                 /* It's not clear whether errno is always set in this case. */
287                 ERROR("%p: flow configuration failed, errno=%d: %s",
288                       (void *)rxq, errno,
289                       (errno ? strerror(errno) : "Unknown error"));
290                 if (errno)
291                         return errno;
292                 return EINVAL;
293         }
294         rxq->mac_flow[mac_index][vlan_index] = flow;
295         return 0;
296 }
297
298 /**
299  * Register a MAC address in a RX queue.
300  *
301  * @param rxq
302  *   Pointer to RX queue structure.
303  * @param mac_index
304  *   MAC address index to register.
305  *
306  * @return
307  *   0 on success, errno value on failure.
308  */
309 static int
310 rxq_mac_addr_add(struct rxq *rxq, unsigned int mac_index)
311 {
312         struct priv *priv = rxq->priv;
313         unsigned int i = 0;
314         int ret;
315
316         assert(mac_index < RTE_DIM(rxq->mac_flow));
317         assert(RTE_DIM(rxq->mac_flow[mac_index]) ==
318                RTE_DIM(priv->vlan_filter));
319         /* Add a MAC address for each VLAN filter, or at least once. */
320         do {
321                 ret = rxq_add_mac_flow(rxq, mac_index, i);
322                 if (ret) {
323                         /* Failure, rollback. */
324                         while (i != 0)
325                                 rxq_del_mac_flow(rxq, mac_index, --i);
326                         return ret;
327                 }
328         } while (++i < priv->vlan_filter_n);
329         return 0;
330 }
331
332 /**
333  * Register all MAC addresses in a RX queue.
334  *
335  * @param rxq
336  *   Pointer to RX queue structure.
337  *
338  * @return
339  *   0 on success, errno value on failure.
340  */
341 int
342 rxq_mac_addrs_add(struct rxq *rxq)
343 {
344         struct priv *priv = rxq->priv;
345         unsigned int i;
346         int ret;
347
348         assert(RTE_DIM(priv->mac) == RTE_DIM(rxq->mac_flow));
349         for (i = 0; (i != RTE_DIM(priv->mac)); ++i) {
350                 if (!BITFIELD_ISSET(priv->mac_configured, i))
351                         continue;
352                 ret = rxq_mac_addr_add(rxq, i);
353                 if (!ret)
354                         continue;
355                 /* Failure, rollback. */
356                 while (i != 0)
357                         rxq_mac_addr_del(rxq, --i);
358                 assert(ret > 0);
359                 return ret;
360         }
361         return 0;
362 }
363
364 /**
365  * Register a MAC address.
366  *
367  * In RSS mode, the MAC address is registered in the parent queue,
368  * otherwise it is registered in each queue directly.
369  *
370  * @param priv
371  *   Pointer to private structure.
372  * @param mac_index
373  *   MAC address index to use.
374  * @param mac
375  *   MAC address to register.
376  *
377  * @return
378  *   0 on success, errno value on failure.
379  */
380 int
381 priv_mac_addr_add(struct priv *priv, unsigned int mac_index,
382                   const uint8_t (*mac)[ETHER_ADDR_LEN])
383 {
384         unsigned int i;
385         int ret;
386
387         assert(mac_index < RTE_DIM(priv->mac));
388         /* First, make sure this address isn't already configured. */
389         for (i = 0; (i != RTE_DIM(priv->mac)); ++i) {
390                 /* Skip this index, it's going to be reconfigured. */
391                 if (i == mac_index)
392                         continue;
393                 if (!BITFIELD_ISSET(priv->mac_configured, i))
394                         continue;
395                 if (memcmp(priv->mac[i].addr_bytes, *mac, sizeof(*mac)))
396                         continue;
397                 /* Address already configured elsewhere, return with error. */
398                 return EADDRINUSE;
399         }
400         if (BITFIELD_ISSET(priv->mac_configured, mac_index))
401                 priv_mac_addr_del(priv, mac_index);
402         priv->mac[mac_index] = (struct ether_addr){
403                 {
404                         (*mac)[0], (*mac)[1], (*mac)[2],
405                         (*mac)[3], (*mac)[4], (*mac)[5]
406                 }
407         };
408         /* If device isn't started, this is all we need to do. */
409         if (!priv->started)
410                 goto end;
411         if (priv->rss) {
412                 ret = rxq_mac_addr_add(&priv->rxq_parent, mac_index);
413                 if (ret)
414                         return ret;
415                 goto end;
416         }
417         for (i = 0; (i != priv->rxqs_n); ++i) {
418                 if ((*priv->rxqs)[i] == NULL)
419                         continue;
420                 ret = rxq_mac_addr_add((*priv->rxqs)[i], mac_index);
421                 if (!ret)
422                         continue;
423                 /* Failure, rollback. */
424                 while (i != 0)
425                         if ((*priv->rxqs)[--i] != NULL)
426                                 rxq_mac_addr_del((*priv->rxqs)[i], mac_index);
427                 return ret;
428         }
429 end:
430         BITFIELD_SET(priv->mac_configured, mac_index);
431         return 0;
432 }
433
434 /**
435  * DPDK callback to add a MAC address.
436  *
437  * @param dev
438  *   Pointer to Ethernet device structure.
439  * @param mac_addr
440  *   MAC address to register.
441  * @param index
442  *   MAC address index.
443  * @param vmdq
444  *   VMDq pool index to associate address with (ignored).
445  */
446 void
447 mlx5_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
448                   uint32_t index, uint32_t vmdq)
449 {
450         struct priv *priv = dev->data->dev_private;
451
452         (void)vmdq;
453         priv_lock(priv);
454         DEBUG("%p: adding MAC address at index %" PRIu32,
455               (void *)dev, index);
456         /* Last array entry is reserved for broadcast. */
457         if (index >= (RTE_DIM(priv->mac) - 1))
458                 goto end;
459         priv_mac_addr_add(priv, index,
460                           (const uint8_t (*)[ETHER_ADDR_LEN])
461                           mac_addr->addr_bytes);
462 end:
463         priv_unlock(priv);
464 }