net/mlx5: make FDB default rule optional
[dpdk.git] / drivers / net / mlx5 / mlx5_trigger.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2015 6WIND S.A.
3  * Copyright 2015 Mellanox Technologies, Ltd
4  */
5
6 #include <unistd.h>
7
8 #include <rte_ether.h>
9 #include <rte_ethdev_driver.h>
10 #include <rte_interrupts.h>
11 #include <rte_alarm.h>
12
13 #include "mlx5.h"
14 #include "mlx5_rxtx.h"
15 #include "mlx5_utils.h"
16
17 /**
18  * Stop traffic on Tx queues.
19  *
20  * @param dev
21  *   Pointer to Ethernet device structure.
22  */
23 static void
24 mlx5_txq_stop(struct rte_eth_dev *dev)
25 {
26         struct mlx5_priv *priv = dev->data->dev_private;
27         unsigned int i;
28
29         for (i = 0; i != priv->txqs_n; ++i)
30                 mlx5_txq_release(dev, i);
31 }
32
33 /**
34  * Start traffic on Tx queues.
35  *
36  * @param dev
37  *   Pointer to Ethernet device structure.
38  *
39  * @return
40  *   0 on success, a negative errno value otherwise and rte_errno is set.
41  */
42 static int
43 mlx5_txq_start(struct rte_eth_dev *dev)
44 {
45         struct mlx5_priv *priv = dev->data->dev_private;
46         unsigned int i;
47         int ret;
48
49         for (i = 0; i != priv->txqs_n; ++i) {
50                 struct mlx5_txq_ctrl *txq_ctrl = mlx5_txq_get(dev, i);
51
52                 if (!txq_ctrl)
53                         continue;
54                 if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN) {
55                         txq_ctrl->obj = mlx5_txq_obj_new
56                                 (dev, i, MLX5_TXQ_OBJ_TYPE_DEVX_HAIRPIN);
57                 } else {
58                         txq_alloc_elts(txq_ctrl);
59                         txq_ctrl->obj = mlx5_txq_obj_new
60                                 (dev, i, MLX5_TXQ_OBJ_TYPE_IBV);
61                 }
62                 if (!txq_ctrl->obj) {
63                         rte_errno = ENOMEM;
64                         goto error;
65                 }
66         }
67         return 0;
68 error:
69         ret = rte_errno; /* Save rte_errno before cleanup. */
70         do {
71                 mlx5_txq_release(dev, i);
72         } while (i-- != 0);
73         rte_errno = ret; /* Restore rte_errno. */
74         return -rte_errno;
75 }
76
77 /**
78  * Stop traffic on Rx queues.
79  *
80  * @param dev
81  *   Pointer to Ethernet device structure.
82  */
83 static void
84 mlx5_rxq_stop(struct rte_eth_dev *dev)
85 {
86         struct mlx5_priv *priv = dev->data->dev_private;
87         unsigned int i;
88
89         for (i = 0; i != priv->rxqs_n; ++i)
90                 mlx5_rxq_release(dev, i);
91 }
92
93 /**
94  * Start traffic on Rx queues.
95  *
96  * @param dev
97  *   Pointer to Ethernet device structure.
98  *
99  * @return
100  *   0 on success, a negative errno value otherwise and rte_errno is set.
101  */
102 static int
103 mlx5_rxq_start(struct rte_eth_dev *dev)
104 {
105         struct mlx5_priv *priv = dev->data->dev_private;
106         unsigned int i;
107         int ret = 0;
108         enum mlx5_rxq_obj_type obj_type = MLX5_RXQ_OBJ_TYPE_IBV;
109         struct mlx5_rxq_data *rxq = NULL;
110
111         for (i = 0; i < priv->rxqs_n; ++i) {
112                 rxq = (*priv->rxqs)[i];
113
114                 if (rxq && rxq->lro) {
115                         obj_type =  MLX5_RXQ_OBJ_TYPE_DEVX_RQ;
116                         break;
117                 }
118         }
119         /* Allocate/reuse/resize mempool for Multi-Packet RQ. */
120         if (mlx5_mprq_alloc_mp(dev)) {
121                 /* Should not release Rx queues but return immediately. */
122                 return -rte_errno;
123         }
124         for (i = 0; i != priv->rxqs_n; ++i) {
125                 struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_get(dev, i);
126                 struct rte_mempool *mp;
127
128                 if (!rxq_ctrl)
129                         continue;
130                 if (rxq_ctrl->type == MLX5_RXQ_TYPE_HAIRPIN) {
131                         rxq_ctrl->obj = mlx5_rxq_obj_new
132                                 (dev, i, MLX5_RXQ_OBJ_TYPE_DEVX_HAIRPIN);
133                         if (!rxq_ctrl->obj)
134                                 goto error;
135                         continue;
136                 }
137                 /* Pre-register Rx mempool. */
138                 mp = mlx5_rxq_mprq_enabled(&rxq_ctrl->rxq) ?
139                      rxq_ctrl->rxq.mprq_mp : rxq_ctrl->rxq.mp;
140                 DRV_LOG(DEBUG,
141                         "port %u Rx queue %u registering"
142                         " mp %s having %u chunks",
143                         dev->data->port_id, rxq_ctrl->rxq.idx,
144                         mp->name, mp->nb_mem_chunks);
145                 mlx5_mr_update_mp(dev, &rxq_ctrl->rxq.mr_ctrl, mp);
146                 ret = rxq_alloc_elts(rxq_ctrl);
147                 if (ret)
148                         goto error;
149                 rxq_ctrl->obj = mlx5_rxq_obj_new(dev, i, obj_type);
150                 if (!rxq_ctrl->obj)
151                         goto error;
152                 if (obj_type == MLX5_RXQ_OBJ_TYPE_IBV)
153                         rxq_ctrl->wqn = rxq_ctrl->obj->wq->wq_num;
154                 else if (obj_type == MLX5_RXQ_OBJ_TYPE_DEVX_RQ)
155                         rxq_ctrl->wqn = rxq_ctrl->obj->rq->id;
156         }
157         return 0;
158 error:
159         ret = rte_errno; /* Save rte_errno before cleanup. */
160         do {
161                 mlx5_rxq_release(dev, i);
162         } while (i-- != 0);
163         rte_errno = ret; /* Restore rte_errno. */
164         return -rte_errno;
165 }
166
167 /**
168  * Binds Tx queues to Rx queues for hairpin.
169  *
170  * Binds Tx queues to the target Rx queues.
171  *
172  * @param dev
173  *   Pointer to Ethernet device structure.
174  *
175  * @return
176  *   0 on success, a negative errno value otherwise and rte_errno is set.
177  */
178 static int
179 mlx5_hairpin_bind(struct rte_eth_dev *dev)
180 {
181         struct mlx5_priv *priv = dev->data->dev_private;
182         struct mlx5_devx_modify_sq_attr sq_attr = { 0 };
183         struct mlx5_devx_modify_rq_attr rq_attr = { 0 };
184         struct mlx5_txq_ctrl *txq_ctrl;
185         struct mlx5_rxq_ctrl *rxq_ctrl;
186         struct mlx5_devx_obj *sq;
187         struct mlx5_devx_obj *rq;
188         unsigned int i;
189         int ret = 0;
190
191         for (i = 0; i != priv->txqs_n; ++i) {
192                 txq_ctrl = mlx5_txq_get(dev, i);
193                 if (!txq_ctrl)
194                         continue;
195                 if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
196                         mlx5_txq_release(dev, i);
197                         continue;
198                 }
199                 if (!txq_ctrl->obj) {
200                         rte_errno = ENOMEM;
201                         DRV_LOG(ERR, "port %u no txq object found: %d",
202                                 dev->data->port_id, i);
203                         mlx5_txq_release(dev, i);
204                         return -rte_errno;
205                 }
206                 sq = txq_ctrl->obj->sq;
207                 rxq_ctrl = mlx5_rxq_get(dev,
208                                         txq_ctrl->hairpin_conf.peers[0].queue);
209                 if (!rxq_ctrl) {
210                         mlx5_txq_release(dev, i);
211                         rte_errno = EINVAL;
212                         DRV_LOG(ERR, "port %u no rxq object found: %d",
213                                 dev->data->port_id,
214                                 txq_ctrl->hairpin_conf.peers[0].queue);
215                         return -rte_errno;
216                 }
217                 if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN ||
218                     rxq_ctrl->hairpin_conf.peers[0].queue != i) {
219                         rte_errno = ENOMEM;
220                         DRV_LOG(ERR, "port %u Tx queue %d can't be binded to "
221                                 "Rx queue %d", dev->data->port_id,
222                                 i, txq_ctrl->hairpin_conf.peers[0].queue);
223                         goto error;
224                 }
225                 rq = rxq_ctrl->obj->rq;
226                 if (!rq) {
227                         rte_errno = ENOMEM;
228                         DRV_LOG(ERR, "port %u hairpin no matching rxq: %d",
229                                 dev->data->port_id,
230                                 txq_ctrl->hairpin_conf.peers[0].queue);
231                         goto error;
232                 }
233                 sq_attr.state = MLX5_SQC_STATE_RDY;
234                 sq_attr.sq_state = MLX5_SQC_STATE_RST;
235                 sq_attr.hairpin_peer_rq = rq->id;
236                 sq_attr.hairpin_peer_vhca = priv->config.hca_attr.vhca_id;
237                 ret = mlx5_devx_cmd_modify_sq(sq, &sq_attr);
238                 if (ret)
239                         goto error;
240                 rq_attr.state = MLX5_SQC_STATE_RDY;
241                 rq_attr.rq_state = MLX5_SQC_STATE_RST;
242                 rq_attr.hairpin_peer_sq = sq->id;
243                 rq_attr.hairpin_peer_vhca = priv->config.hca_attr.vhca_id;
244                 ret = mlx5_devx_cmd_modify_rq(rq, &rq_attr);
245                 if (ret)
246                         goto error;
247                 mlx5_txq_release(dev, i);
248                 mlx5_rxq_release(dev, txq_ctrl->hairpin_conf.peers[0].queue);
249         }
250         return 0;
251 error:
252         mlx5_txq_release(dev, i);
253         mlx5_rxq_release(dev, txq_ctrl->hairpin_conf.peers[0].queue);
254         return -rte_errno;
255 }
256
257 /**
258  * DPDK callback to start the device.
259  *
260  * Simulate device start by attaching all configured flows.
261  *
262  * @param dev
263  *   Pointer to Ethernet device structure.
264  *
265  * @return
266  *   0 on success, a negative errno value otherwise and rte_errno is set.
267  */
268 int
269 mlx5_dev_start(struct rte_eth_dev *dev)
270 {
271         struct mlx5_priv *priv = dev->data->dev_private;
272         int ret;
273
274         DRV_LOG(DEBUG, "port %u starting device", dev->data->port_id);
275         ret = mlx5_dev_configure_rss_reta(dev);
276         if (ret) {
277                 DRV_LOG(ERR, "port %u reta config failed: %s",
278                         dev->data->port_id, strerror(rte_errno));
279                 return -rte_errno;
280         }
281         ret = mlx5_txq_start(dev);
282         if (ret) {
283                 DRV_LOG(ERR, "port %u Tx queue allocation failed: %s",
284                         dev->data->port_id, strerror(rte_errno));
285                 return -rte_errno;
286         }
287         ret = mlx5_rxq_start(dev);
288         if (ret) {
289                 DRV_LOG(ERR, "port %u Rx queue allocation failed: %s",
290                         dev->data->port_id, strerror(rte_errno));
291                 mlx5_txq_stop(dev);
292                 return -rte_errno;
293         }
294         ret = mlx5_hairpin_bind(dev);
295         if (ret) {
296                 DRV_LOG(ERR, "port %u hairpin binding failed: %s",
297                         dev->data->port_id, strerror(rte_errno));
298                 mlx5_txq_stop(dev);
299                 return -rte_errno;
300         }
301         dev->data->dev_started = 1;
302         ret = mlx5_rx_intr_vec_enable(dev);
303         if (ret) {
304                 DRV_LOG(ERR, "port %u Rx interrupt vector creation failed",
305                         dev->data->port_id);
306                 goto error;
307         }
308         mlx5_stats_init(dev);
309         ret = mlx5_traffic_enable(dev);
310         if (ret) {
311                 DRV_LOG(DEBUG, "port %u failed to set defaults flows",
312                         dev->data->port_id);
313                 goto error;
314         }
315         ret = mlx5_flow_start(dev, &priv->flows);
316         if (ret) {
317                 DRV_LOG(DEBUG, "port %u failed to set flows",
318                         dev->data->port_id);
319                 goto error;
320         }
321         rte_wmb();
322         dev->tx_pkt_burst = mlx5_select_tx_function(dev);
323         dev->rx_pkt_burst = mlx5_select_rx_function(dev);
324         /* Enable datapath on secondary process. */
325         mlx5_mp_req_start_rxtx(dev);
326         mlx5_dev_interrupt_handler_install(dev);
327         return 0;
328 error:
329         ret = rte_errno; /* Save rte_errno before cleanup. */
330         /* Rollback. */
331         dev->data->dev_started = 0;
332         mlx5_flow_stop(dev, &priv->flows);
333         mlx5_traffic_disable(dev);
334         mlx5_txq_stop(dev);
335         mlx5_rxq_stop(dev);
336         rte_errno = ret; /* Restore rte_errno. */
337         return -rte_errno;
338 }
339
340 /**
341  * DPDK callback to stop the device.
342  *
343  * Simulate device stop by detaching all configured flows.
344  *
345  * @param dev
346  *   Pointer to Ethernet device structure.
347  */
348 void
349 mlx5_dev_stop(struct rte_eth_dev *dev)
350 {
351         struct mlx5_priv *priv = dev->data->dev_private;
352
353         dev->data->dev_started = 0;
354         /* Prevent crashes when queues are still in use. */
355         dev->rx_pkt_burst = removed_rx_burst;
356         dev->tx_pkt_burst = removed_tx_burst;
357         rte_wmb();
358         /* Disable datapath on secondary process. */
359         mlx5_mp_req_stop_rxtx(dev);
360         usleep(1000 * priv->rxqs_n);
361         DRV_LOG(DEBUG, "port %u stopping device", dev->data->port_id);
362         mlx5_flow_stop(dev, &priv->flows);
363         mlx5_traffic_disable(dev);
364         mlx5_rx_intr_vec_disable(dev);
365         mlx5_dev_interrupt_handler_uninstall(dev);
366         mlx5_txq_stop(dev);
367         mlx5_rxq_stop(dev);
368 }
369
370 /**
371  * Enable traffic flows configured by control plane
372  *
373  * @param dev
374  *   Pointer to Ethernet device private data.
375  * @param dev
376  *   Pointer to Ethernet device structure.
377  *
378  * @return
379  *   0 on success, a negative errno value otherwise and rte_errno is set.
380  */
381 int
382 mlx5_traffic_enable(struct rte_eth_dev *dev)
383 {
384         struct mlx5_priv *priv = dev->data->dev_private;
385         struct rte_flow_item_eth bcast = {
386                 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
387         };
388         struct rte_flow_item_eth ipv6_multi_spec = {
389                 .dst.addr_bytes = "\x33\x33\x00\x00\x00\x00",
390         };
391         struct rte_flow_item_eth ipv6_multi_mask = {
392                 .dst.addr_bytes = "\xff\xff\x00\x00\x00\x00",
393         };
394         struct rte_flow_item_eth unicast = {
395                 .src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
396         };
397         struct rte_flow_item_eth unicast_mask = {
398                 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
399         };
400         const unsigned int vlan_filter_n = priv->vlan_filter_n;
401         const struct rte_ether_addr cmp = {
402                 .addr_bytes = "\x00\x00\x00\x00\x00\x00",
403         };
404         unsigned int i;
405         unsigned int j;
406         int ret;
407
408         /*
409          * Hairpin txq default flow should be created no matter if it is
410          * isolation mode. Or else all the packets to be sent will be sent
411          * out directly without the TX flow actions, e.g. encapsulation.
412          */
413         for (i = 0; i != priv->txqs_n; ++i) {
414                 struct mlx5_txq_ctrl *txq_ctrl = mlx5_txq_get(dev, i);
415                 if (!txq_ctrl)
416                         continue;
417                 if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN) {
418                         ret = mlx5_ctrl_flow_source_queue(dev, i);
419                         if (ret) {
420                                 mlx5_txq_release(dev, i);
421                                 goto error;
422                         }
423                 }
424                 mlx5_txq_release(dev, i);
425         }
426         if (priv->config.dv_esw_en && !priv->config.vf) {
427                 if (mlx5_flow_create_esw_table_zero_flow(dev))
428                         priv->fdb_def_rule = 1;
429                 else
430                         DRV_LOG(INFO, "port %u FDB default rule cannot be"
431                                 " configured - only Eswitch group 0 flows are"
432                                 " supported.", dev->data->port_id);
433         }
434         if (priv->isolated)
435                 return 0;
436         if (dev->data->promiscuous) {
437                 struct rte_flow_item_eth promisc = {
438                         .dst.addr_bytes = "\x00\x00\x00\x00\x00\x00",
439                         .src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
440                         .type = 0,
441                 };
442
443                 ret = mlx5_ctrl_flow(dev, &promisc, &promisc);
444                 if (ret)
445                         goto error;
446         }
447         if (dev->data->all_multicast) {
448                 struct rte_flow_item_eth multicast = {
449                         .dst.addr_bytes = "\x01\x00\x00\x00\x00\x00",
450                         .src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
451                         .type = 0,
452                 };
453
454                 ret = mlx5_ctrl_flow(dev, &multicast, &multicast);
455                 if (ret)
456                         goto error;
457         } else {
458                 /* Add broadcast/multicast flows. */
459                 for (i = 0; i != vlan_filter_n; ++i) {
460                         uint16_t vlan = priv->vlan_filter[i];
461
462                         struct rte_flow_item_vlan vlan_spec = {
463                                 .tci = rte_cpu_to_be_16(vlan),
464                         };
465                         struct rte_flow_item_vlan vlan_mask =
466                                 rte_flow_item_vlan_mask;
467
468                         ret = mlx5_ctrl_flow_vlan(dev, &bcast, &bcast,
469                                                   &vlan_spec, &vlan_mask);
470                         if (ret)
471                                 goto error;
472                         ret = mlx5_ctrl_flow_vlan(dev, &ipv6_multi_spec,
473                                                   &ipv6_multi_mask,
474                                                   &vlan_spec, &vlan_mask);
475                         if (ret)
476                                 goto error;
477                 }
478                 if (!vlan_filter_n) {
479                         ret = mlx5_ctrl_flow(dev, &bcast, &bcast);
480                         if (ret)
481                                 goto error;
482                         ret = mlx5_ctrl_flow(dev, &ipv6_multi_spec,
483                                              &ipv6_multi_mask);
484                         if (ret)
485                                 goto error;
486                 }
487         }
488         /* Add MAC address flows. */
489         for (i = 0; i != MLX5_MAX_MAC_ADDRESSES; ++i) {
490                 struct rte_ether_addr *mac = &dev->data->mac_addrs[i];
491
492                 if (!memcmp(mac, &cmp, sizeof(*mac)))
493                         continue;
494                 memcpy(&unicast.dst.addr_bytes,
495                        mac->addr_bytes,
496                        RTE_ETHER_ADDR_LEN);
497                 for (j = 0; j != vlan_filter_n; ++j) {
498                         uint16_t vlan = priv->vlan_filter[j];
499
500                         struct rte_flow_item_vlan vlan_spec = {
501                                 .tci = rte_cpu_to_be_16(vlan),
502                         };
503                         struct rte_flow_item_vlan vlan_mask =
504                                 rte_flow_item_vlan_mask;
505
506                         ret = mlx5_ctrl_flow_vlan(dev, &unicast,
507                                                   &unicast_mask,
508                                                   &vlan_spec,
509                                                   &vlan_mask);
510                         if (ret)
511                                 goto error;
512                 }
513                 if (!vlan_filter_n) {
514                         ret = mlx5_ctrl_flow(dev, &unicast, &unicast_mask);
515                         if (ret)
516                                 goto error;
517                 }
518         }
519         return 0;
520 error:
521         ret = rte_errno; /* Save rte_errno before cleanup. */
522         mlx5_flow_list_flush(dev, &priv->ctrl_flows);
523         rte_errno = ret; /* Restore rte_errno. */
524         return -rte_errno;
525 }
526
527
528 /**
529  * Disable traffic flows configured by control plane
530  *
531  * @param dev
532  *   Pointer to Ethernet device private data.
533  */
534 void
535 mlx5_traffic_disable(struct rte_eth_dev *dev)
536 {
537         struct mlx5_priv *priv = dev->data->dev_private;
538
539         mlx5_flow_list_flush(dev, &priv->ctrl_flows);
540 }
541
542 /**
543  * Restart traffic flows configured by control plane
544  *
545  * @param dev
546  *   Pointer to Ethernet device private data.
547  *
548  * @return
549  *   0 on success, a negative errno value otherwise and rte_errno is set.
550  */
551 int
552 mlx5_traffic_restart(struct rte_eth_dev *dev)
553 {
554         if (dev->data->dev_started) {
555                 mlx5_traffic_disable(dev);
556                 return mlx5_traffic_enable(dev);
557         }
558         return 0;
559 }