dpdk: xstats vecor stuck at 0 elements
[vpp.git] / src / plugins / dev_octeon / port.c
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright (c) 2023 Cisco Systems, Inc.
3  */
4
5 #include <vnet/vnet.h>
6 #include <vnet/dev/dev.h>
7 #include <vnet/dev/pci.h>
8 #include <vnet/dev/counters.h>
9 #include <dev_octeon/octeon.h>
10 #include <dev_octeon/common.h>
11 #include <vnet/ethernet/ethernet.h>
12
13 #define OCT_FLOW_PREALLOC_SIZE  1
14 #define OCT_FLOW_MAX_PRIORITY   7
15 #define OCT_ETH_LINK_SPEED_100G 100000 /**< 100 Gbps */
16
17 VLIB_REGISTER_LOG_CLASS (oct_log, static) = {
18   .class_name = "octeon",
19   .subclass_name = "port",
20 };
21
22 static const u8 default_rss_key[] = {
23   0xfe, 0xed, 0x0b, 0xad, 0xfe, 0xed, 0x0b, 0xad, 0xad, 0x0b, 0xed, 0xfe,
24   0xad, 0x0b, 0xed, 0xfe, 0x13, 0x57, 0x9b, 0xef, 0x24, 0x68, 0xac, 0x0e,
25   0x91, 0x72, 0x53, 0x11, 0x82, 0x64, 0x20, 0x44, 0x12, 0xef, 0x34, 0xcd,
26   0x56, 0xbc, 0x78, 0x9a, 0x9a, 0x78, 0xbc, 0x56, 0xcd, 0x34, 0xef, 0x12
27 };
28
29 static const u32 default_rss_flowkey =
30   (FLOW_KEY_TYPE_IPV4 | FLOW_KEY_TYPE_IPV6 | FLOW_KEY_TYPE_TCP |
31    FLOW_KEY_TYPE_UDP | FLOW_KEY_TYPE_SCTP);
32
33 static const u64 rxq_cfg =
34   ROC_NIX_LF_RX_CFG_DIS_APAD | ROC_NIX_LF_RX_CFG_IP6_UDP_OPT |
35   ROC_NIX_LF_RX_CFG_L2_LEN_ERR | ROC_NIX_LF_RX_CFG_DROP_RE |
36   ROC_NIX_LF_RX_CFG_CSUM_OL4 | ROC_NIX_LF_RX_CFG_CSUM_IL4 |
37   ROC_NIX_LF_RX_CFG_LEN_OL3 | ROC_NIX_LF_RX_CFG_LEN_OL4 |
38   ROC_NIX_LF_RX_CFG_LEN_IL3 | ROC_NIX_LF_RX_CFG_LEN_IL4;
39
40 static vnet_dev_rv_t
41 oct_roc_err (vnet_dev_t *dev, int rv, char *fmt, ...)
42 {
43   u8 *s = 0;
44   va_list va;
45
46   va_start (va, fmt);
47   s = va_format (s, fmt, &va);
48   va_end (va);
49
50   log_err (dev, "%v - ROC error %s (%d)", s, roc_error_msg_get (rv), rv);
51
52   vec_free (s);
53   return VNET_DEV_ERR_INTERNAL;
54 }
55
56 vnet_dev_rv_t
57 oct_port_init (vlib_main_t *vm, vnet_dev_port_t *port)
58 {
59   vnet_dev_t *dev = port->dev;
60   oct_device_t *cd = vnet_dev_get_data (dev);
61   oct_port_t *cp = vnet_dev_get_port_data (port);
62   struct roc_nix *nix = cd->nix;
63   vnet_dev_rv_t rv;
64   int rrv;
65
66   log_debug (dev, "port init: port %u", port->port_id);
67
68   if ((rrv = roc_nix_lf_alloc (nix, port->intf.num_rx_queues,
69                                port->intf.num_tx_queues, rxq_cfg)))
70     {
71       oct_port_deinit (vm, port);
72       return oct_roc_err (
73         dev, rrv,
74         "roc_nix_lf_alloc(nb_rxq = %u, nb_txq = %d, rxq_cfg=0x%lx) failed",
75         port->intf.num_rx_queues, port->intf.num_tx_queues, rxq_cfg);
76     }
77   cp->lf_allocated = 1;
78
79   if ((rrv = roc_nix_tm_init (nix)))
80     {
81       oct_port_deinit (vm, port);
82       return oct_roc_err (dev, rrv, "roc_nix_tm_init() failed");
83     }
84   cp->tm_initialized = 1;
85
86   if ((rrv = roc_nix_tm_hierarchy_enable (nix, ROC_NIX_TM_DEFAULT,
87                                           /* xmit_enable */ 0)))
88     {
89       oct_port_deinit (vm, port);
90       return oct_roc_err (dev, rrv, "roc_nix_tm_hierarchy_enable() failed");
91     }
92
93   if ((rrv = roc_nix_rss_default_setup (nix, default_rss_flowkey)))
94     {
95       oct_port_deinit (vm, port);
96       return oct_roc_err (dev, rrv, "roc_nix_rss_default_setup() failed");
97     }
98
99   roc_nix_rss_key_set (nix, default_rss_key);
100
101   cp->npc.roc_nix = nix;
102   cp->npc.flow_prealloc_size = OCT_FLOW_PREALLOC_SIZE;
103   cp->npc.flow_max_priority = OCT_FLOW_MAX_PRIORITY;
104   if ((rrv = roc_npc_init (&cp->npc)))
105     {
106       oct_port_deinit (vm, port);
107       return oct_roc_err (dev, rrv, "roc_npc_init() failed");
108     }
109   cp->npc_initialized = 1;
110
111   foreach_vnet_dev_port_rx_queue (q, port)
112     if (q->enabled)
113       if ((rv = oct_rxq_init (vm, q)))
114         {
115           oct_port_deinit (vm, port);
116           return rv;
117         }
118
119   foreach_vnet_dev_port_tx_queue (q, port)
120     if (q->enabled)
121       if ((rv = oct_txq_init (vm, q)))
122         {
123           oct_port_deinit (vm, port);
124           return rv;
125         }
126
127   oct_port_add_counters (vm, port);
128
129   return VNET_DEV_OK;
130 }
131
132 void
133 oct_port_deinit (vlib_main_t *vm, vnet_dev_port_t *port)
134 {
135   vnet_dev_t *dev = port->dev;
136   oct_device_t *cd = vnet_dev_get_data (dev);
137   oct_port_t *cp = vnet_dev_get_port_data (port);
138   struct roc_nix *nix = cd->nix;
139   int rrv;
140
141   foreach_vnet_dev_port_rx_queue (q, port)
142     oct_rxq_deinit (vm, q);
143   foreach_vnet_dev_port_tx_queue (q, port)
144     oct_txq_deinit (vm, q);
145
146   if (cp->npc_initialized)
147     {
148       if ((rrv = roc_npc_fini (&cp->npc)))
149         oct_roc_err (dev, rrv, "roc_npc_fini() failed");
150       cp->npc_initialized = 0;
151     }
152
153   if (cp->tm_initialized)
154     {
155       roc_nix_tm_fini (nix);
156       cp->tm_initialized = 0;
157     }
158
159   if (cp->lf_allocated)
160     {
161       if ((rrv = roc_nix_lf_free (nix)))
162         oct_roc_err (dev, rrv, "roc_nix_lf_free() failed");
163       cp->lf_allocated = 0;
164     }
165 }
166
167 void
168 oct_port_poll (vlib_main_t *vm, vnet_dev_port_t *port)
169 {
170   vnet_dev_t *dev = port->dev;
171   oct_device_t *cd = vnet_dev_get_data (dev);
172   struct roc_nix *nix = cd->nix;
173   struct roc_nix_link_info link_info = {};
174   vnet_dev_port_state_changes_t changes = {};
175   int rrv;
176
177   if (oct_port_get_stats (vm, port))
178     return;
179
180   foreach_vnet_dev_port_rx_queue (q, port)
181     {
182       if (oct_rxq_get_stats (vm, port, q))
183         return;
184     }
185
186   foreach_vnet_dev_port_tx_queue (q, port)
187     {
188       if (oct_txq_get_stats (vm, port, q))
189         return;
190     }
191
192   if (roc_nix_is_lbk (nix))
193     {
194       link_info.status = 1;
195       link_info.full_duplex = 1;
196       link_info.autoneg = 0;
197       link_info.speed = OCT_ETH_LINK_SPEED_100G;
198     }
199   else
200     {
201       rrv = roc_nix_mac_link_info_get (nix, &link_info);
202       if (rrv)
203         return;
204     }
205
206   if (cd->status != link_info.status)
207     {
208       changes.change.link_state = 1;
209       changes.link_state = link_info.status;
210       cd->status = link_info.status;
211     }
212
213   if (cd->full_duplex != link_info.full_duplex)
214     {
215       changes.change.link_duplex = 1;
216       changes.full_duplex = link_info.full_duplex;
217       cd->full_duplex = link_info.full_duplex;
218     }
219
220   if (cd->speed != link_info.speed)
221     {
222       changes.change.link_speed = 1;
223       /* Convert to Kbps */
224       changes.link_speed = link_info.speed * 1000;
225       cd->speed = link_info.speed;
226     }
227
228   if (changes.change.any == 0)
229     return;
230
231   log_debug (dev,
232              "status %u full_duplex %u speed %u port %u lmac_type_id %u "
233              "fec %u aautoneg %u",
234              link_info.status, link_info.full_duplex, link_info.speed,
235              link_info.port, link_info.lmac_type_id, link_info.fec,
236              link_info.autoneg);
237   vnet_dev_port_state_change (vm, port, changes);
238 }
239
240 vnet_dev_rv_t
241 oct_rxq_start (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
242 {
243   vnet_dev_t *dev = rxq->port->dev;
244   oct_rxq_t *crq = vnet_dev_get_rx_queue_data (rxq);
245   u32 buffer_indices[rxq->size], n_alloc;
246   u8 bpi = vnet_dev_get_rx_queue_buffer_pool_index (rxq);
247   int rrv;
248
249   n_alloc = vlib_buffer_alloc_from_pool (vm, buffer_indices, rxq->size, bpi);
250
251   for (int i = 0; i < n_alloc; i++)
252     roc_npa_aura_op_free (
253       crq->aura_handle, 0,
254       pointer_to_uword (vlib_get_buffer (vm, buffer_indices[i])) -
255         crq->hdr_off);
256
257   crq->n_enq = n_alloc;
258
259   if (roc_npa_aura_op_available (crq->aura_handle) != rxq->size)
260     log_warn (rxq->port->dev, "rx queue %u aura not filled completelly",
261               rxq->queue_id);
262
263   if ((rrv = roc_nix_rq_ena_dis (&crq->rq, 1)))
264     return oct_roc_err (dev, rrv, "roc_nix_rq_ena_dis() failed");
265
266   return VNET_DEV_OK;
267 }
268 void
269 oct_rxq_stop (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
270 {
271   vnet_dev_t *dev = rxq->port->dev;
272   oct_rxq_t *crq = vnet_dev_get_rx_queue_data (rxq);
273   int rrv;
274   u32 n;
275
276   if ((rrv = roc_nix_rq_ena_dis (&crq->rq, 0)))
277     oct_roc_err (dev, rrv, "roc_nix_rq_ena_dis() failed");
278
279   n = oct_aura_free_all_buffers (vm, crq->aura_handle, crq->hdr_off);
280
281   if (crq->n_enq - n > 0)
282     log_err (dev, "%u buffers leaked on rx queue %u stop", crq->n_enq - n,
283              rxq->queue_id);
284   else
285     log_debug (dev, "%u buffers freed from rx queue %u", n, rxq->queue_id);
286
287   crq->n_enq = 0;
288 }
289
290 void
291 oct_txq_stop (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
292 {
293   vnet_dev_t *dev = txq->port->dev;
294   oct_txq_t *ctq = vnet_dev_get_tx_queue_data (txq);
295   oct_npa_batch_alloc_cl128_t *cl;
296   u32 n, off = ctq->hdr_off;
297
298   n = oct_aura_free_all_buffers (vm, ctq->aura_handle, off);
299   ctq->n_enq -= n;
300
301   if (ctq->n_enq > 0 && ctq->ba_num_cl > 0)
302     for (n = ctq->ba_num_cl, cl = ctq->ba_buffer + ctq->ba_first_cl; n;
303          cl++, n--)
304       {
305         oct_npa_batch_alloc_status_t st;
306
307         st.as_u64 = __atomic_load_n (cl->iova, __ATOMIC_ACQUIRE);
308         if (st.status.ccode != ALLOC_CCODE_INVAL)
309           for (u32 i = 0; i < st.status.count; i++)
310             {
311               vlib_buffer_t *b = (vlib_buffer_t *) (cl->iova[i] + off);
312               vlib_buffer_free_one (vm, vlib_get_buffer_index (vm, b));
313               ctq->n_enq--;
314             }
315       }
316
317   if (ctq->n_enq > 0)
318     log_err (dev, "%u buffers leaked on tx queue %u stop", ctq->n_enq,
319              txq->queue_id);
320   else
321     log_debug (dev, "%u buffers freed from tx queue %u", n, txq->queue_id);
322
323   ctq->n_enq = 0;
324 }
325
326 vnet_dev_rv_t
327 oct_port_start (vlib_main_t *vm, vnet_dev_port_t *port)
328 {
329   vnet_dev_t *dev = port->dev;
330   oct_device_t *cd = vnet_dev_get_data (dev);
331   struct roc_nix *nix = cd->nix;
332   struct roc_nix_eeprom_info eeprom_info = {};
333   vnet_dev_rv_t rv;
334   int rrv;
335
336   log_debug (port->dev, "port start: port %u", port->port_id);
337
338   foreach_vnet_dev_port_rx_queue (q, port)
339     if ((rv = oct_rxq_start (vm, q)) != VNET_DEV_OK)
340       goto done;
341
342   foreach_vnet_dev_port_tx_queue (q, port)
343     {
344       oct_txq_t *ctq = vnet_dev_get_tx_queue_data (q);
345       ctq->n_enq = 0;
346     }
347
348   if ((rrv = roc_nix_mac_mtu_set (nix, 9200)))
349     {
350       rv = oct_roc_err (dev, rrv, "roc_nix_mac_mtu_set() failed");
351       goto done;
352     }
353
354   if ((rrv = roc_nix_npc_rx_ena_dis (nix, true)))
355     {
356       rv = oct_roc_err (dev, rrv, "roc_nix_npc_rx_ena_dis() failed");
357       goto done;
358     }
359
360   vnet_dev_poll_port_add (vm, port, 0.5, oct_port_poll);
361
362   if (roc_nix_eeprom_info_get (nix, &eeprom_info) == 0)
363     {
364       log_debug (dev, "sff_id %u data %U", eeprom_info.sff_id, format_hexdump,
365                  eeprom_info.buf, sizeof (eeprom_info.buf));
366     }
367 done:
368   if (rv != VNET_DEV_OK)
369     oct_port_stop (vm, port);
370   return VNET_DEV_OK;
371 }
372
373 void
374 oct_port_stop (vlib_main_t *vm, vnet_dev_port_t *port)
375 {
376   vnet_dev_t *dev = port->dev;
377   oct_device_t *cd = vnet_dev_get_data (dev);
378   struct roc_nix *nix = cd->nix;
379   int rrv;
380
381   log_debug (port->dev, "port stop: port %u", port->port_id);
382
383   vnet_dev_poll_port_remove (vm, port, oct_port_poll);
384
385   rrv = roc_nix_npc_rx_ena_dis (nix, false);
386   if (rrv)
387     {
388       oct_roc_err (dev, rrv, "roc_nix_npc_rx_ena_dis() failed");
389       return;
390     }
391
392   foreach_vnet_dev_port_rx_queue (q, port)
393     oct_rxq_stop (vm, q);
394
395   foreach_vnet_dev_port_tx_queue (q, port)
396     oct_txq_stop (vm, q);
397 }
398
399 vnet_dev_rv_t
400 oct_validate_config_promisc_mode (vnet_dev_port_t *port, int enable)
401 {
402   vnet_dev_t *dev = port->dev;
403   oct_device_t *cd = vnet_dev_get_data (dev);
404   struct roc_nix *nix = cd->nix;
405
406   if (roc_nix_is_sdp (nix) || roc_nix_is_lbk (nix))
407     return VNET_DEV_ERR_UNSUPPORTED_DEVICE;
408
409   return VNET_DEV_OK;
410 }
411
412 vnet_dev_rv_t
413 oct_op_config_promisc_mode (vlib_main_t *vm, vnet_dev_port_t *port, int enable)
414 {
415   vnet_dev_t *dev = port->dev;
416   oct_device_t *cd = vnet_dev_get_data (dev);
417   struct roc_nix *nix = cd->nix;
418   int rv;
419
420   rv = roc_nix_npc_promisc_ena_dis (nix, enable);
421   if (rv)
422     {
423       return oct_roc_err (dev, rv, "roc_nix_npc_promisc_ena_dis failed");
424     }
425
426   if (!roc_nix_is_pf (nix))
427     return VNET_DEV_OK;
428
429   rv = roc_nix_mac_promisc_mode_enable (nix, enable);
430   if (rv)
431     {
432       return oct_roc_err (dev, rv,
433                           "roc_nix_mac_promisc_mode_enable(%s) failed",
434                           enable ? "true" : "false");
435     }
436
437   return VNET_DEV_OK;
438 }
439
440 static vnet_dev_rv_t
441 oct_port_add_del_eth_addr (vlib_main_t *vm, vnet_dev_port_t *port,
442                            vnet_dev_hw_addr_t *addr, int is_add,
443                            int is_primary)
444 {
445   vnet_dev_t *dev = port->dev;
446   oct_device_t *cd = vnet_dev_get_data (dev);
447   struct roc_nix *nix = cd->nix;
448   vnet_dev_rv_t rv = VNET_DEV_OK;
449
450   i32 rrv;
451
452   if (is_primary)
453     {
454       if (is_add)
455         {
456           /* Update mac address at NPC */
457           rrv = roc_nix_npc_mac_addr_set (nix, (u8 *) addr);
458           if (rrv)
459             rv = oct_roc_err (dev, rrv, "roc_nix_npc_mac_addr_set() failed");
460
461           /* Update mac address at CGX for PFs only */
462           if (!roc_nix_is_vf_or_sdp (nix))
463             {
464               rrv = roc_nix_mac_addr_set (nix, (u8 *) addr);
465               if (rrv)
466                 {
467                   /* Rollback to previous mac address */
468                   roc_nix_npc_mac_addr_set (nix,
469                                             (u8 *) &port->primary_hw_addr);
470                   rv = oct_roc_err (dev, rrv, "roc_nix_mac_addr_set() failed");
471                 }
472             }
473         }
474     }
475   return rv;
476 }
477
478 vnet_dev_rv_t
479 oct_port_cfg_change_validate (vlib_main_t *vm, vnet_dev_port_t *port,
480                               vnet_dev_port_cfg_change_req_t *req)
481 {
482   vnet_dev_rv_t rv = VNET_DEV_OK;
483
484   switch (req->type)
485     {
486     case VNET_DEV_PORT_CFG_MAX_RX_FRAME_SIZE:
487       if (port->started)
488         rv = VNET_DEV_ERR_PORT_STARTED;
489       break;
490
491     case VNET_DEV_PORT_CFG_PROMISC_MODE:
492       rv = oct_validate_config_promisc_mode (port, req->promisc);
493       break;
494     case VNET_DEV_PORT_CFG_CHANGE_PRIMARY_HW_ADDR:
495     case VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR:
496     case VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR:
497       break;
498
499     case VNET_DEV_PORT_CFG_ADD_RX_FLOW:
500     case VNET_DEV_PORT_CFG_DEL_RX_FLOW:
501     case VNET_DEV_PORT_CFG_GET_RX_FLOW_COUNTER:
502     case VNET_DEV_PORT_CFG_RESET_RX_FLOW_COUNTER:
503       rv = oct_flow_validate_params (vm, port, req->type, req->flow_index,
504                                      req->private_data);
505       break;
506
507     default:
508       rv = VNET_DEV_ERR_NOT_SUPPORTED;
509     };
510
511   return rv;
512 }
513
514 vnet_dev_rv_t
515 oct_port_cfg_change (vlib_main_t *vm, vnet_dev_port_t *port,
516                      vnet_dev_port_cfg_change_req_t *req)
517 {
518   vnet_dev_rv_t rv = VNET_DEV_OK;
519
520   switch (req->type)
521     {
522     case VNET_DEV_PORT_CFG_PROMISC_MODE:
523       rv = oct_op_config_promisc_mode (vm, port, req->promisc);
524       break;
525
526     case VNET_DEV_PORT_CFG_CHANGE_PRIMARY_HW_ADDR:
527       rv = oct_port_add_del_eth_addr (vm, port, &req->addr,
528                                       /* is_add */ 1,
529                                       /* is_primary */ 1);
530       break;
531
532     case VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR:
533       break;
534
535     case VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR:
536       break;
537
538     case VNET_DEV_PORT_CFG_MAX_RX_FRAME_SIZE:
539       break;
540
541     case VNET_DEV_PORT_CFG_ADD_RX_FLOW:
542     case VNET_DEV_PORT_CFG_DEL_RX_FLOW:
543     case VNET_DEV_PORT_CFG_GET_RX_FLOW_COUNTER:
544     case VNET_DEV_PORT_CFG_RESET_RX_FLOW_COUNTER:
545       rv = oct_flow_ops_fn (vm, port, req->type, req->flow_index,
546                             req->private_data);
547
548       break;
549
550     default:
551       return VNET_DEV_ERR_NOT_SUPPORTED;
552     };
553
554   return rv;
555 }