mlx5: remove redundant debug message
[dpdk.git] / drivers / net / mlx5 / mlx5_rxmode.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 <errno.h>
36 #include <string.h>
37
38 /* Verbs header. */
39 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
40 #ifdef PEDANTIC
41 #pragma GCC diagnostic ignored "-pedantic"
42 #endif
43 #include <infiniband/verbs.h>
44 #ifdef PEDANTIC
45 #pragma GCC diagnostic error "-pedantic"
46 #endif
47
48 /* DPDK headers don't like -pedantic. */
49 #ifdef PEDANTIC
50 #pragma GCC diagnostic ignored "-pedantic"
51 #endif
52 #include <rte_ethdev.h>
53 #ifdef PEDANTIC
54 #pragma GCC diagnostic error "-pedantic"
55 #endif
56
57 #include "mlx5.h"
58 #include "mlx5_rxtx.h"
59 #include "mlx5_utils.h"
60
61 /* Initialization data for special flows. */
62 static const struct special_flow_init special_flow_init[] = {
63         [HASH_RXQ_FLOW_TYPE_PROMISC] = {
64                 .dst_mac_val = "\x00\x00\x00\x00\x00\x00",
65                 .dst_mac_mask = "\x00\x00\x00\x00\x00\x00",
66                 .hash_types =
67                         1 << HASH_RXQ_TCPV4 |
68                         1 << HASH_RXQ_UDPV4 |
69                         1 << HASH_RXQ_IPV4 |
70 #ifdef HAVE_FLOW_SPEC_IPV6
71                         1 << HASH_RXQ_TCPV6 |
72                         1 << HASH_RXQ_UDPV6 |
73                         1 << HASH_RXQ_IPV6 |
74 #endif /* HAVE_FLOW_SPEC_IPV6 */
75                         1 << HASH_RXQ_ETH |
76                         0,
77         },
78         [HASH_RXQ_FLOW_TYPE_ALLMULTI] = {
79                 .dst_mac_val = "\x01\x00\x00\x00\x00\x00",
80                 .dst_mac_mask = "\x01\x00\x00\x00\x00\x00",
81                 .hash_types =
82                         1 << HASH_RXQ_UDPV4 |
83                         1 << HASH_RXQ_IPV4 |
84 #ifdef HAVE_FLOW_SPEC_IPV6
85                         1 << HASH_RXQ_UDPV6 |
86                         1 << HASH_RXQ_IPV6 |
87 #endif /* HAVE_FLOW_SPEC_IPV6 */
88                         1 << HASH_RXQ_ETH |
89                         0,
90         },
91         [HASH_RXQ_FLOW_TYPE_BROADCAST] = {
92                 .dst_mac_val = "\xff\xff\xff\xff\xff\xff",
93                 .dst_mac_mask = "\xff\xff\xff\xff\xff\xff",
94                 .hash_types =
95                         1 << HASH_RXQ_UDPV4 |
96                         1 << HASH_RXQ_IPV4 |
97 #ifdef HAVE_FLOW_SPEC_IPV6
98                         1 << HASH_RXQ_UDPV6 |
99                         1 << HASH_RXQ_IPV6 |
100 #endif /* HAVE_FLOW_SPEC_IPV6 */
101                         1 << HASH_RXQ_ETH |
102                         0,
103         },
104 #ifdef HAVE_FLOW_SPEC_IPV6
105         [HASH_RXQ_FLOW_TYPE_IPV6MULTI] = {
106                 .dst_mac_val = "\x33\x33\x00\x00\x00\x00",
107                 .dst_mac_mask = "\xff\xff\x00\x00\x00\x00",
108                 .hash_types =
109                         1 << HASH_RXQ_UDPV6 |
110                         1 << HASH_RXQ_IPV6 |
111                         1 << HASH_RXQ_ETH |
112                         0,
113         },
114 #endif /* HAVE_FLOW_SPEC_IPV6 */
115 };
116
117 /**
118  * Enable a special flow in a hash RX queue.
119  *
120  * @param hash_rxq
121  *   Pointer to hash RX queue structure.
122  * @param flow_type
123  *   Special flow type.
124  *
125  * @return
126  *   0 on success, errno value on failure.
127  */
128 static int
129 hash_rxq_special_flow_enable(struct hash_rxq *hash_rxq,
130                              enum hash_rxq_flow_type flow_type)
131 {
132         struct priv *priv = hash_rxq->priv;
133         struct ibv_exp_flow *flow;
134         FLOW_ATTR_SPEC_ETH(data, priv_flow_attr(priv, NULL, 0, hash_rxq->type));
135         struct ibv_exp_flow_attr *attr = &data->attr;
136         struct ibv_exp_flow_spec_eth *spec = &data->spec;
137         const uint8_t *mac;
138         const uint8_t *mask;
139
140         /* Check if flow is relevant for this hash_rxq. */
141         if (!(special_flow_init[flow_type].hash_types & (1 << hash_rxq->type)))
142                 return 0;
143         /* Check if flow already exists. */
144         if (hash_rxq->special_flow[flow_type] != NULL)
145                 return 0;
146
147         /*
148          * No padding must be inserted by the compiler between attr and spec.
149          * This layout is expected by libibverbs.
150          */
151         assert(((uint8_t *)attr + sizeof(*attr)) == (uint8_t *)spec);
152         priv_flow_attr(priv, attr, sizeof(data), hash_rxq->type);
153         /* The first specification must be Ethernet. */
154         assert(spec->type == IBV_EXP_FLOW_SPEC_ETH);
155         assert(spec->size == sizeof(*spec));
156
157         mac = special_flow_init[flow_type].dst_mac_val;
158         mask = special_flow_init[flow_type].dst_mac_mask;
159         *spec = (struct ibv_exp_flow_spec_eth){
160                 .type = IBV_EXP_FLOW_SPEC_ETH,
161                 .size = sizeof(*spec),
162                 .val = {
163                         .dst_mac = {
164                                 mac[0], mac[1], mac[2],
165                                 mac[3], mac[4], mac[5],
166                         },
167                 },
168                 .mask = {
169                         .dst_mac = {
170                                 mask[0], mask[1], mask[2],
171                                 mask[3], mask[4], mask[5],
172                         },
173                 },
174         };
175
176         errno = 0;
177         flow = ibv_exp_create_flow(hash_rxq->qp, attr);
178         if (flow == NULL) {
179                 /* It's not clear whether errno is always set in this case. */
180                 ERROR("%p: flow configuration failed, errno=%d: %s",
181                       (void *)hash_rxq, errno,
182                       (errno ? strerror(errno) : "Unknown error"));
183                 if (errno)
184                         return errno;
185                 return EINVAL;
186         }
187         hash_rxq->special_flow[flow_type] = flow;
188         DEBUG("%p: enabling special flow %s (%d)",
189               (void *)hash_rxq, hash_rxq_flow_type_str(flow_type), flow_type);
190         return 0;
191 }
192
193 /**
194  * Disable a special flow in a hash RX queue.
195  *
196  * @param hash_rxq
197  *   Pointer to hash RX queue structure.
198  * @param flow_type
199  *   Special flow type.
200  */
201 static void
202 hash_rxq_special_flow_disable(struct hash_rxq *hash_rxq,
203                               enum hash_rxq_flow_type flow_type)
204 {
205         if (hash_rxq->special_flow[flow_type] == NULL)
206                 return;
207         claim_zero(ibv_exp_destroy_flow(hash_rxq->special_flow[flow_type]));
208         hash_rxq->special_flow[flow_type] = NULL;
209         DEBUG("%p: special flow %s (%d) disabled",
210               (void *)hash_rxq, hash_rxq_flow_type_str(flow_type), flow_type);
211 }
212
213 /**
214  * Enable a special flow in all hash RX queues.
215  *
216  * @param priv
217  *   Private structure.
218  * @param flow_type
219  *   Special flow type.
220  *
221  * @return
222  *   0 on success, errno value on failure.
223  */
224 int
225 priv_special_flow_enable(struct priv *priv, enum hash_rxq_flow_type flow_type)
226 {
227         unsigned int i;
228
229         if (!priv_allow_flow_type(priv, flow_type))
230                 return 0;
231         for (i = 0; (i != priv->hash_rxqs_n); ++i) {
232                 struct hash_rxq *hash_rxq = &(*priv->hash_rxqs)[i];
233                 int ret;
234
235                 ret = hash_rxq_special_flow_enable(hash_rxq, flow_type);
236                 if (!ret)
237                         continue;
238                 /* Failure, rollback. */
239                 while (i != 0) {
240                         hash_rxq = &(*priv->hash_rxqs)[--i];
241                         hash_rxq_special_flow_disable(hash_rxq, flow_type);
242                 }
243                 return ret;
244         }
245         return 0;
246 }
247
248 /**
249  * Disable a special flow in all hash RX queues.
250  *
251  * @param priv
252  *   Private structure.
253  * @param flow_type
254  *   Special flow type.
255  */
256 void
257 priv_special_flow_disable(struct priv *priv, enum hash_rxq_flow_type flow_type)
258 {
259         unsigned int i;
260
261         for (i = 0; (i != priv->hash_rxqs_n); ++i) {
262                 struct hash_rxq *hash_rxq = &(*priv->hash_rxqs)[i];
263
264                 hash_rxq_special_flow_disable(hash_rxq, flow_type);
265         }
266 }
267
268 /**
269  * Enable all special flows in all hash RX queues.
270  *
271  * @param priv
272  *   Private structure.
273  */
274 int
275 priv_special_flow_enable_all(struct priv *priv)
276 {
277         enum hash_rxq_flow_type flow_type;
278
279         for (flow_type = 0; flow_type != HASH_RXQ_FLOW_TYPE_MAC; ++flow_type) {
280                 int ret;
281
282                 ret = priv_special_flow_enable(priv, flow_type);
283                 if (!ret)
284                         continue;
285                 /* Failure, rollback. */
286                 while (flow_type)
287                         priv_special_flow_disable(priv, --flow_type);
288                 return ret;
289         }
290         return 0;
291 }
292
293 /**
294  * Disable all special flows in all hash RX queues.
295  *
296  * @param priv
297  *   Private structure.
298  */
299 void
300 priv_special_flow_disable_all(struct priv *priv)
301 {
302         enum hash_rxq_flow_type flow_type;
303
304         for (flow_type = 0; flow_type != HASH_RXQ_FLOW_TYPE_MAC; ++flow_type)
305                 priv_special_flow_disable(priv, flow_type);
306 }
307
308 /**
309  * DPDK callback to enable promiscuous mode.
310  *
311  * @param dev
312  *   Pointer to Ethernet device structure.
313  */
314 void
315 mlx5_promiscuous_enable(struct rte_eth_dev *dev)
316 {
317         struct priv *priv = dev->data->dev_private;
318         int ret;
319
320         priv_lock(priv);
321         priv->promisc_req = 1;
322         ret = priv_rehash_flows(priv);
323         if (ret)
324                 ERROR("error while enabling promiscuous mode: %s",
325                       strerror(ret));
326         priv_unlock(priv);
327 }
328
329 /**
330  * DPDK callback to disable promiscuous mode.
331  *
332  * @param dev
333  *   Pointer to Ethernet device structure.
334  */
335 void
336 mlx5_promiscuous_disable(struct rte_eth_dev *dev)
337 {
338         struct priv *priv = dev->data->dev_private;
339         int ret;
340
341         priv_lock(priv);
342         priv->promisc_req = 0;
343         ret = priv_rehash_flows(priv);
344         if (ret)
345                 ERROR("error while disabling promiscuous mode: %s",
346                       strerror(ret));
347         priv_unlock(priv);
348 }
349
350 /**
351  * DPDK callback to enable allmulti mode.
352  *
353  * @param dev
354  *   Pointer to Ethernet device structure.
355  */
356 void
357 mlx5_allmulticast_enable(struct rte_eth_dev *dev)
358 {
359         struct priv *priv = dev->data->dev_private;
360         int ret;
361
362         priv_lock(priv);
363         priv->allmulti_req = 1;
364         ret = priv_rehash_flows(priv);
365         if (ret)
366                 ERROR("error while enabling allmulticast mode: %s",
367                       strerror(ret));
368         priv_unlock(priv);
369 }
370
371 /**
372  * DPDK callback to disable allmulti mode.
373  *
374  * @param dev
375  *   Pointer to Ethernet device structure.
376  */
377 void
378 mlx5_allmulticast_disable(struct rte_eth_dev *dev)
379 {
380         struct priv *priv = dev->data->dev_private;
381         int ret;
382
383         priv_lock(priv);
384         priv->allmulti_req = 0;
385         ret = priv_rehash_flows(priv);
386         if (ret)
387                 ERROR("error while disabling allmulticast mode: %s",
388                       strerror(ret));
389         priv_unlock(priv);
390 }