hs-test: more debug output in http3 test
[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   return VNET_DEV_OK;
128 }
129
130 void
131 oct_port_deinit (vlib_main_t *vm, vnet_dev_port_t *port)
132 {
133   vnet_dev_t *dev = port->dev;
134   oct_device_t *cd = vnet_dev_get_data (dev);
135   oct_port_t *cp = vnet_dev_get_port_data (port);
136   struct roc_nix *nix = cd->nix;
137   int rrv;
138
139   foreach_vnet_dev_port_rx_queue (q, port)
140     oct_rxq_deinit (vm, q);
141   foreach_vnet_dev_port_tx_queue (q, port)
142     oct_txq_deinit (vm, q);
143
144   if (cp->npc_initialized)
145     {
146       if ((rrv = roc_npc_fini (&cp->npc)))
147         oct_roc_err (dev, rrv, "roc_npc_fini() failed");
148       cp->npc_initialized = 0;
149     }
150
151   if (cp->tm_initialized)
152     {
153       roc_nix_tm_fini (nix);
154       cp->tm_initialized = 0;
155     }
156
157   if (cp->lf_allocated)
158     {
159       if ((rrv = roc_nix_lf_free (nix)))
160         oct_roc_err (dev, rrv, "roc_nix_lf_free() failed");
161       cp->lf_allocated = 0;
162     }
163 }
164
165 void
166 oct_port_poll (vlib_main_t *vm, vnet_dev_port_t *port)
167 {
168   vnet_dev_t *dev = port->dev;
169   oct_device_t *cd = vnet_dev_get_data (dev);
170   struct roc_nix *nix = cd->nix;
171   struct roc_nix_link_info link_info = {};
172   vnet_dev_port_state_changes_t changes = {};
173   int rrv;
174
175   if (roc_nix_is_lbk (nix))
176     {
177       link_info.status = 1;
178       link_info.full_duplex = 1;
179       link_info.autoneg = 0;
180       link_info.speed = OCT_ETH_LINK_SPEED_100G;
181     }
182   else
183     {
184       rrv = roc_nix_mac_link_info_get (nix, &link_info);
185       if (rrv)
186         return;
187     }
188
189   if (cd->status != link_info.status)
190     {
191       changes.change.link_state = 1;
192       changes.link_state = link_info.status;
193       cd->status = link_info.status;
194     }
195
196   if (cd->full_duplex != link_info.full_duplex)
197     {
198       changes.change.link_duplex = 1;
199       changes.full_duplex = link_info.full_duplex;
200       cd->full_duplex = link_info.full_duplex;
201     }
202
203   if (cd->speed != link_info.speed)
204     {
205       changes.change.link_speed = 1;
206       changes.link_speed = link_info.speed;
207       cd->speed = link_info.speed;
208     }
209
210   if (changes.change.any == 0)
211     return;
212
213   log_debug (dev,
214              "status %u full_duplex %u speed %u port %u lmac_type_id %u "
215              "fec %u aautoneg %u",
216              link_info.status, link_info.full_duplex, link_info.speed,
217              link_info.port, link_info.lmac_type_id, link_info.fec,
218              link_info.autoneg);
219   vnet_dev_port_state_change (vm, port, changes);
220 }
221
222 vnet_dev_rv_t
223 oct_rxq_start (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
224 {
225   vnet_dev_t *dev = rxq->port->dev;
226   oct_rxq_t *crq = vnet_dev_get_rx_queue_data (rxq);
227   u32 buffer_indices[rxq->size], n_alloc;
228   u8 bpi = vnet_dev_get_rx_queue_buffer_pool_index (rxq);
229   int rrv;
230
231   n_alloc = vlib_buffer_alloc_from_pool (vm, buffer_indices, rxq->size, bpi);
232
233   for (int i = 0; i < n_alloc; i++)
234     roc_npa_aura_op_free (
235       crq->aura_handle, 0,
236       pointer_to_uword (vlib_get_buffer (vm, buffer_indices[i])) -
237         crq->hdr_off);
238
239   crq->n_enq = n_alloc;
240
241   if (roc_npa_aura_op_available (crq->aura_handle) != rxq->size)
242     log_warn (rxq->port->dev, "rx queue %u aura not filled completelly",
243               rxq->queue_id);
244
245   if ((rrv = roc_nix_rq_ena_dis (&crq->rq, 1)))
246     return oct_roc_err (dev, rrv, "roc_nix_rq_ena_dis() failed");
247
248   return VNET_DEV_OK;
249 }
250 void
251 oct_rxq_stop (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
252 {
253   vnet_dev_t *dev = rxq->port->dev;
254   oct_rxq_t *crq = vnet_dev_get_rx_queue_data (rxq);
255   int rrv;
256   u32 n;
257
258   if ((rrv = roc_nix_rq_ena_dis (&crq->rq, 0)))
259     oct_roc_err (dev, rrv, "roc_nix_rq_ena_dis() failed");
260
261   n = oct_aura_free_all_buffers (vm, crq->aura_handle, crq->hdr_off);
262
263   if (crq->n_enq - n > 0)
264     log_err (dev, "%u buffers leaked on rx queue %u stop", crq->n_enq - n,
265              rxq->queue_id);
266   else
267     log_debug (dev, "%u buffers freed from rx queue %u", n, rxq->queue_id);
268
269   crq->n_enq = 0;
270 }
271
272 void
273 oct_txq_stop (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
274 {
275   vnet_dev_t *dev = txq->port->dev;
276   oct_txq_t *ctq = vnet_dev_get_tx_queue_data (txq);
277   oct_npa_batch_alloc_cl128_t *cl;
278   u32 n, off = ctq->hdr_off;
279
280   n = oct_aura_free_all_buffers (vm, ctq->aura_handle, off);
281   ctq->n_enq -= n;
282
283   if (ctq->n_enq > 0 && ctq->ba_num_cl > 0)
284     for (n = ctq->ba_num_cl, cl = ctq->ba_buffer + ctq->ba_first_cl; n;
285          cl++, n--)
286       {
287         oct_npa_batch_alloc_status_t st;
288
289         st.as_u64 = __atomic_load_n (cl->iova, __ATOMIC_ACQUIRE);
290         if (st.status.ccode != ALLOC_CCODE_INVAL)
291           for (u32 i = 0; i < st.status.count; i++)
292             {
293               vlib_buffer_t *b = (vlib_buffer_t *) (cl->iova[i] + off);
294               vlib_buffer_free_one (vm, vlib_get_buffer_index (vm, b));
295               ctq->n_enq--;
296             }
297       }
298
299   if (ctq->n_enq > 0)
300     log_err (dev, "%u buffers leaked on tx queue %u stop", ctq->n_enq,
301              txq->queue_id);
302   else
303     log_debug (dev, "%u buffers freed from tx queue %u", n, txq->queue_id);
304
305   ctq->n_enq = 0;
306 }
307
308 vnet_dev_rv_t
309 oct_port_start (vlib_main_t *vm, vnet_dev_port_t *port)
310 {
311   vnet_dev_t *dev = port->dev;
312   oct_device_t *cd = vnet_dev_get_data (dev);
313   struct roc_nix *nix = cd->nix;
314   struct roc_nix_eeprom_info eeprom_info = {};
315   vnet_dev_rv_t rv;
316   int rrv;
317
318   log_debug (port->dev, "port start: port %u", port->port_id);
319
320   foreach_vnet_dev_port_rx_queue (q, port)
321     if ((rv = oct_rxq_start (vm, q)) != VNET_DEV_OK)
322       goto done;
323
324   foreach_vnet_dev_port_tx_queue (q, port)
325     {
326       oct_txq_t *ctq = vnet_dev_get_tx_queue_data (q);
327       ctq->n_enq = 0;
328     }
329
330   if ((rrv = roc_nix_mac_mtu_set (nix, 9200)))
331     {
332       rv = oct_roc_err (dev, rrv, "roc_nix_mac_mtu_set() failed");
333       goto done;
334     }
335
336   if ((rrv = roc_nix_npc_rx_ena_dis (nix, true)))
337     {
338       rv = oct_roc_err (dev, rrv, "roc_nix_npc_rx_ena_dis() failed");
339       goto done;
340     }
341
342   vnet_dev_poll_port_add (vm, port, 0.5, oct_port_poll);
343
344   if (roc_nix_eeprom_info_get (nix, &eeprom_info) == 0)
345     {
346       log_debug (dev, "sff_id %u data %U", eeprom_info.sff_id, format_hexdump,
347                  eeprom_info.buf, sizeof (eeprom_info.buf));
348     }
349 done:
350   if (rv != VNET_DEV_OK)
351     oct_port_stop (vm, port);
352   return VNET_DEV_OK;
353 }
354
355 void
356 oct_port_stop (vlib_main_t *vm, vnet_dev_port_t *port)
357 {
358   vnet_dev_t *dev = port->dev;
359   oct_device_t *cd = vnet_dev_get_data (dev);
360   struct roc_nix *nix = cd->nix;
361   int rrv;
362
363   log_debug (port->dev, "port stop: port %u", port->port_id);
364
365   vnet_dev_poll_port_remove (vm, port, oct_port_poll);
366
367   rrv = roc_nix_npc_rx_ena_dis (nix, false);
368   if (rrv)
369     {
370       oct_roc_err (dev, rrv, "roc_nix_npc_rx_ena_dis() failed");
371       return;
372     }
373
374   foreach_vnet_dev_port_rx_queue (q, port)
375     oct_rxq_stop (vm, q);
376
377   foreach_vnet_dev_port_tx_queue (q, port)
378     oct_txq_stop (vm, q);
379 }
380
381 vnet_dev_rv_t
382 oct_validate_config_promisc_mode (vnet_dev_port_t *port, int enable)
383 {
384   vnet_dev_t *dev = port->dev;
385   oct_device_t *cd = vnet_dev_get_data (dev);
386   struct roc_nix *nix = cd->nix;
387
388   if (roc_nix_is_vf_or_sdp (nix))
389     return VNET_DEV_ERR_UNSUPPORTED_DEVICE;
390
391   return VNET_DEV_OK;
392 }
393
394 vnet_dev_rv_t
395 oct_op_config_promisc_mode (vlib_main_t *vm, vnet_dev_port_t *port, int enable)
396 {
397   vnet_dev_t *dev = port->dev;
398   oct_device_t *cd = vnet_dev_get_data (dev);
399   struct roc_nix *nix = cd->nix;
400   int rv;
401
402   rv = roc_nix_npc_promisc_ena_dis (nix, enable);
403   if (rv)
404     {
405       return oct_roc_err (dev, rv, "roc_nix_npc_promisc_ena_dis failed");
406     }
407
408   rv = roc_nix_mac_promisc_mode_enable (nix, enable);
409   if (rv)
410     {
411       return oct_roc_err (dev, rv,
412                           "roc_nix_mac_promisc_mode_enable(%s) failed",
413                           enable ? "true" : "false");
414     }
415
416   return VNET_DEV_OK;
417 }
418
419 vnet_dev_rv_t
420 oct_port_cfg_change_validate (vlib_main_t *vm, vnet_dev_port_t *port,
421                               vnet_dev_port_cfg_change_req_t *req)
422 {
423   vnet_dev_rv_t rv = VNET_DEV_OK;
424
425   switch (req->type)
426     {
427     case VNET_DEV_PORT_CFG_MAX_RX_FRAME_SIZE:
428       if (port->started)
429         rv = VNET_DEV_ERR_PORT_STARTED;
430       break;
431
432     case VNET_DEV_PORT_CFG_PROMISC_MODE:
433       rv = oct_validate_config_promisc_mode (port, req->promisc);
434       break;
435     case VNET_DEV_PORT_CFG_CHANGE_PRIMARY_HW_ADDR:
436     case VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR:
437     case VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR:
438       break;
439
440     case VNET_DEV_PORT_CFG_ADD_RX_FLOW:
441     case VNET_DEV_PORT_CFG_DEL_RX_FLOW:
442     case VNET_DEV_PORT_CFG_GET_RX_FLOW_COUNTER:
443     case VNET_DEV_PORT_CFG_RESET_RX_FLOW_COUNTER:
444       rv = oct_flow_validate_params (vm, port, req->type, req->flow_index,
445                                      req->private_data);
446       break;
447
448     default:
449       rv = VNET_DEV_ERR_NOT_SUPPORTED;
450     };
451
452   return rv;
453 }
454
455 vnet_dev_rv_t
456 oct_port_cfg_change (vlib_main_t *vm, vnet_dev_port_t *port,
457                      vnet_dev_port_cfg_change_req_t *req)
458 {
459   vnet_dev_rv_t rv = VNET_DEV_OK;
460
461   switch (req->type)
462     {
463     case VNET_DEV_PORT_CFG_PROMISC_MODE:
464       rv = oct_op_config_promisc_mode (vm, port, req->promisc);
465       break;
466
467     case VNET_DEV_PORT_CFG_CHANGE_PRIMARY_HW_ADDR:
468       break;
469
470     case VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR:
471       break;
472
473     case VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR:
474       break;
475
476     case VNET_DEV_PORT_CFG_MAX_RX_FRAME_SIZE:
477       break;
478
479     case VNET_DEV_PORT_CFG_ADD_RX_FLOW:
480     case VNET_DEV_PORT_CFG_DEL_RX_FLOW:
481     case VNET_DEV_PORT_CFG_GET_RX_FLOW_COUNTER:
482     case VNET_DEV_PORT_CFG_RESET_RX_FLOW_COUNTER:
483       rv = oct_flow_ops_fn (vm, port, req->type, req->flow_index,
484                             req->private_data);
485
486       break;
487
488     default:
489       return VNET_DEV_ERR_NOT_SUPPORTED;
490     };
491
492   return rv;
493 }