vppinfra: add CLIB_SWAP()
[vpp.git] / src / plugins / dev_iavf / 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/bus/pci.h>
8 #include <vnet/dev/counters.h>
9 #include <dev_iavf/iavf.h>
10 #include <dev_iavf/iavf_regs.h>
11 #include <dev_iavf/virtchnl.h>
12 #include <dev_iavf/virtchnl_funcs.h>
13 #include <vnet/ethernet/ethernet.h>
14
15 VLIB_REGISTER_LOG_CLASS (iavf_log, static) = {
16   .class_name = "iavf",
17   .subclass_name = "port",
18 };
19
20 static const u8 default_rss_key[] = {
21   0x44, 0x39, 0x79, 0x6b, 0xb5, 0x4c, 0x50, 0x23, 0xb6, 0x75, 0xea, 0x5b, 0x12,
22   0x4f, 0x9f, 0x30, 0xb8, 0xa2, 0xc0, 0x3d, 0xdf, 0xdc, 0x4d, 0x02, 0xa0, 0x8c,
23   0x9b, 0x33, 0x4a, 0xf6, 0x4a, 0x4c, 0x05, 0xc6, 0xfa, 0x34, 0x39, 0x58, 0xd8,
24   0x55, 0x7d, 0x99, 0x58, 0x3a, 0xe1, 0x38, 0xc9, 0x2e, 0x81, 0x15, 0x03, 0x66,
25 };
26
27 const static iavf_dyn_ctl dyn_ctln_disabled = {};
28 const static iavf_dyn_ctl dyn_ctln_enabled = {
29   .intena = 1,
30   .clearpba = 1,
31   .interval = IAVF_ITR_INT / 2,
32 };
33 const static iavf_dyn_ctl dyn_ctln_wb_on_itr = {
34   .itr_indx = 1,
35   .interval = 2,
36   .wb_on_itr = 1,
37 };
38
39 vnet_dev_rv_t
40 iavf_port_vlan_strip_disable (vlib_main_t *vm, vnet_dev_port_t *port)
41 {
42   vnet_dev_t *dev = port->dev;
43   iavf_port_t *ap = vnet_dev_get_port_data (port);
44   virtchnl_vlan_caps_t vc;
45   vnet_dev_rv_t rv = VNET_DEV_ERR_NOT_SUPPORTED;
46   u32 outer, inner;
47   const u32 mask = VIRTCHNL_VLAN_ETHERTYPE_8100;
48
49   if (ap->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2)
50     {
51       if ((rv = iavf_vc_op_get_offload_vlan_v2_caps (vm, dev, &vc)))
52         return rv;
53
54       outer = vc.offloads.stripping_support.outer;
55       inner = vc.offloads.stripping_support.inner;
56
57       outer = outer & VIRTCHNL_VLAN_TOGGLE ? outer & mask : 0;
58       inner = inner & VIRTCHNL_VLAN_TOGGLE ? inner & mask : 0;
59
60       virtchnl_vlan_setting_t vs = {
61         .vport_id = ap->vsi_id,
62         .outer_ethertype_setting = outer,
63         .inner_ethertype_setting = inner,
64       };
65
66       if ((rv = iavf_vc_op_disable_vlan_stripping_v2 (vm, dev, &vs)))
67         return rv;
68     }
69
70   if (ap->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)
71     return iavf_vc_op_disable_vlan_stripping (vm, dev);
72
73   return rv;
74 }
75
76 vnet_dev_rv_t
77 iavf_port_init_rss (vlib_main_t *vm, vnet_dev_port_t *port)
78 {
79   vnet_dev_t *dev = port->dev;
80   iavf_port_t *ap = vnet_dev_get_port_data (port);
81   u16 keylen = clib_min (sizeof (default_rss_key), ap->rss_key_size);
82   u8 buffer[VIRTCHNL_MSG_SZ (virtchnl_rss_key_t, key, keylen)];
83   virtchnl_rss_key_t *key = (virtchnl_rss_key_t *) buffer;
84
85   if (!port->attr.caps.rss)
86     return VNET_DEV_OK;
87
88   /* config RSS key */
89   *key = (virtchnl_rss_key_t){
90     .vsi_id = ap->vsi_id,
91     .key_len = keylen,
92   };
93
94   clib_memcpy (key->key, default_rss_key, keylen);
95
96   return iavf_vc_op_config_rss_key (vm, dev, key);
97 }
98
99 vnet_dev_rv_t
100 iavf_port_update_rss_lut (vlib_main_t *vm, vnet_dev_port_t *port)
101 {
102   vnet_dev_t *dev = port->dev;
103   iavf_port_t *ap = vnet_dev_get_port_data (port);
104   u16 lut_size = clib_min (IAVF_MAX_RSS_LUT_SIZE, ap->rss_lut_size);
105   u8 buffer[VIRTCHNL_MSG_SZ (virtchnl_rss_lut_t, lut, lut_size)];
106   virtchnl_rss_lut_t *lut = (virtchnl_rss_lut_t *) buffer;
107   u32 enabled_rxq_bmp = 0;
108
109   if (!port->attr.caps.rss)
110     return VNET_DEV_OK;
111
112   *lut = (virtchnl_rss_lut_t){
113     .vsi_id = ap->vsi_id,
114     .lut_entries = lut_size,
115   };
116
117   foreach_vnet_dev_port_rx_queue (q, port)
118     if (q->enabled)
119       enabled_rxq_bmp |= 1ULL << q->queue_id;
120
121   /* config RSS LUT */
122   for (u32 i = 0, j; i < lut->lut_entries;)
123     foreach_set_bit_index (j, enabled_rxq_bmp)
124       {
125         lut->lut[i++] = j;
126         if (i >= lut->lut_entries)
127           break;
128       }
129
130   return iavf_vc_op_config_rss_lut (vm, dev, lut);
131 }
132
133 vnet_dev_rv_t
134 iavf_port_init_vsi_queues (vlib_main_t *vm, vnet_dev_port_t *port)
135 {
136   vnet_dev_t *dev = port->dev;
137   iavf_port_t *ap = vnet_dev_get_port_data (port);
138   virtchnl_queue_pair_info_t *qpi;
139   u16 vsi_id = ap->vsi_id;
140   u16 data_size = vlib_buffer_get_default_data_size (vm);
141   u16 max_frame_size = port->max_rx_frame_size;
142   u8 buffer[VIRTCHNL_MSG_SZ (virtchnl_vsi_queue_config_info_t, qpair,
143                              ap->num_qp)];
144   virtchnl_vsi_queue_config_info_t *ci =
145     (virtchnl_vsi_queue_config_info_t *) buffer;
146
147   *ci = (virtchnl_vsi_queue_config_info_t){
148     .num_queue_pairs = ap->num_qp,
149     .vsi_id = vsi_id,
150   };
151
152   for (u16 i = 0; i < ap->num_qp; i++)
153     ci->qpair[i] = (virtchnl_queue_pair_info_t){
154       .rxq = { .vsi_id = vsi_id,
155                .queue_id = i,
156                .max_pkt_size = ETHERNET_MIN_PACKET_BYTES },
157       .txq = { .vsi_id = vsi_id, .queue_id = i },
158     };
159
160   foreach_vnet_dev_port_rx_queue (q, port)
161     {
162       iavf_rxq_t *arq = vnet_dev_get_rx_queue_data (q);
163       qpi = ci->qpair + q->queue_id;
164       qpi->rxq.ring_len = q->size;
165       qpi->rxq.databuffer_size = data_size;
166       qpi->rxq.dma_ring_addr = vnet_dev_get_dma_addr (vm, dev, arq->descs);
167       qpi->rxq.max_pkt_size = max_frame_size;
168     }
169
170   foreach_vnet_dev_port_tx_queue (q, port)
171     {
172       iavf_txq_t *atq = vnet_dev_get_tx_queue_data (q);
173       qpi = ci->qpair + q->queue_id;
174       qpi->txq.ring_len = q->size;
175       qpi->txq.dma_ring_addr = vnet_dev_get_dma_addr (vm, dev, atq->descs);
176     }
177
178   return iavf_vc_op_config_vsi_queues (vm, dev, ci);
179 }
180
181 vnet_dev_rv_t
182 iavf_port_rx_irq_config (vlib_main_t *vm, vnet_dev_port_t *port, int enable)
183 {
184   vnet_dev_t *dev = port->dev;
185   iavf_device_t *ad = vnet_dev_get_data (dev);
186   iavf_port_t *ap = vnet_dev_get_port_data (port);
187   u16 n_rx_vectors = ap->n_rx_vectors;
188   u8 buffer[VIRTCHNL_MSG_SZ (virtchnl_irq_map_info_t, vecmap, n_rx_vectors)];
189   u8 n_intr_mode_queues_per_vector[n_rx_vectors];
190   u8 n_queues_per_vector[n_rx_vectors];
191   virtchnl_irq_map_info_t *im = (virtchnl_irq_map_info_t *) buffer;
192   vnet_dev_rv_t rv;
193
194   log_debug (dev, "intr mode per queue bitmap 0x%x",
195              ap->intr_mode_per_rxq_bitmap);
196
197   for (u32 i = 0; i < n_rx_vectors; i++)
198     n_intr_mode_queues_per_vector[i] = n_queues_per_vector[i] = 0;
199
200   *im = (virtchnl_irq_map_info_t){
201     .num_vectors = n_rx_vectors,
202   };
203
204   if (port->attr.caps.interrupt_mode)
205     {
206       for (u16 i = 0; i < im->num_vectors; i++)
207         im->vecmap[i] = (virtchnl_vector_map_t){
208           .vsi_id = ap->vsi_id,
209           .vector_id = i + 1,
210         };
211       if (enable)
212         foreach_vnet_dev_port_rx_queue (rxq, port)
213           if (rxq->enabled)
214             {
215               u32 i = rxq->rx_thread_index;
216               im->vecmap[i].rxq_map |= 1 << rxq->queue_id;
217               n_queues_per_vector[i]++;
218               n_intr_mode_queues_per_vector[i] +=
219                 u64_is_bit_set (ap->intr_mode_per_rxq_bitmap, rxq->queue_id);
220             }
221     }
222   else
223     {
224       im->vecmap[0] = (virtchnl_vector_map_t){
225         .vsi_id = ap->vsi_id,
226         .vector_id = 1,
227       };
228       if (enable)
229         foreach_vnet_dev_port_rx_queue (rxq, port)
230           if (rxq->enabled)
231             im->vecmap[0].rxq_map |= 1 << rxq->queue_id;
232     }
233
234   if ((rv = iavf_vc_op_config_irq_map (vm, dev, im)))
235     return rv;
236
237   for (int i = 0; i < n_rx_vectors; i++)
238     {
239       u32 val;
240
241       if (enable == 0 || n_queues_per_vector[i] == 0)
242         val = dyn_ctln_disabled.as_u32;
243       else if (ap->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_WB_ON_ITR &&
244                n_intr_mode_queues_per_vector[i] == 0)
245         val = dyn_ctln_wb_on_itr.as_u32;
246       else
247         val = dyn_ctln_enabled.as_u32;
248
249       iavf_reg_write (ad, IAVF_VFINT_DYN_CTLN (i), val);
250       log_debug (dev, "VFINT_DYN_CTLN(%u) set to 0x%x", i, val);
251     }
252
253   return rv;
254 }
255
256 static void
257 avf_msix_n_handler (vlib_main_t *vm, vnet_dev_t *dev, u16 line)
258 {
259   iavf_device_t *ad = vnet_dev_get_data (dev);
260   vnet_dev_port_t *port = vnet_dev_get_port_by_id (dev, 0);
261
262   line--;
263
264   iavf_reg_write (ad, IAVF_VFINT_DYN_CTLN (line), dyn_ctln_enabled.as_u32);
265   vlib_node_set_interrupt_pending (vlib_get_main_by_index (line),
266                                    port->intf.rx_node_index);
267 }
268
269 vnet_dev_rv_t
270 iavf_port_init (vlib_main_t *vm, vnet_dev_port_t *port)
271 {
272   vnet_dev_t *dev = port->dev;
273   iavf_port_t *ap = vnet_dev_get_port_data (port);
274   vnet_dev_rv_t rv;
275
276   log_debug (port->dev, "port %u", port->port_id);
277
278   ap->intr_mode_per_rxq_bitmap = 0;
279   foreach_vnet_dev_port_rx_queue (q, port)
280     if (q->interrupt_mode)
281       u64_bit_set (&ap->intr_mode_per_rxq_bitmap, q->queue_id, 1);
282
283   if ((rv = iavf_port_vlan_strip_disable (vm, port)))
284     {
285       if (rv == VNET_DEV_ERR_NOT_SUPPORTED)
286         log_warn (port->dev, "device doesn't support vlan stripping");
287       else
288         return rv;
289     }
290
291   if ((rv = iavf_port_init_rss (vm, port)))
292     return rv;
293
294   vnet_dev_pci_msix_add_handler (vm, dev, &avf_msix_n_handler, 1,
295                                  ap->n_rx_vectors);
296   vnet_dev_pci_msix_enable (vm, dev, 1, ap->n_rx_vectors);
297   for (u32 i = 1; i < ap->n_rx_vectors; i++)
298     vnet_dev_pci_msix_set_polling_thread (vm, dev, i + 1, i);
299
300   if (port->dev->poll_stats)
301     iavf_port_add_counters (vm, port);
302
303   return VNET_DEV_OK;
304 }
305
306 static vnet_dev_rv_t
307 iavf_enable_disable_queues (vlib_main_t *vm, vnet_dev_port_t *port, int enable)
308 {
309   iavf_port_t *ap = vnet_dev_get_port_data (port);
310
311   virtchnl_queue_select_t qs = {
312     .vsi_id = ap->vsi_id,
313   };
314
315   foreach_vnet_dev_port_rx_queue (q, port)
316     if ((enable && q->enabled) || (!enable && q->started))
317       qs.rx_queues |= 1ULL << q->queue_id;
318
319   foreach_vnet_dev_port_tx_queue (q, port)
320     if ((enable && q->enabled) || (!enable && q->started))
321       qs.tx_queues |= 1ULL << q->queue_id;
322
323   return enable ? iavf_vc_op_enable_queues (vm, port->dev, &qs) :
324                         iavf_vc_op_disable_queues (vm, port->dev, &qs);
325 }
326
327 vnet_dev_rv_t
328 iavf_port_start (vlib_main_t *vm, vnet_dev_port_t *port)
329 {
330   vnet_dev_rv_t rv;
331
332   log_debug (port->dev, "port %u", port->port_id);
333
334   foreach_vnet_dev_port_rx_queue (q, port)
335     if (q->enabled)
336       if ((rv = iavf_rx_queue_start (vm, q)))
337         goto done;
338
339   foreach_vnet_dev_port_tx_queue (q, port)
340     if ((rv = iavf_tx_queue_start (vm, q)))
341       goto done;
342
343   if ((rv = iavf_port_update_rss_lut (vm, port)))
344     goto done;
345
346   /* configure qpairs */
347   if ((rv = iavf_port_init_vsi_queues (vm, port)))
348     goto done;
349
350   if ((rv = iavf_port_rx_irq_config (vm, port, /* enable */ 1)))
351     goto done;
352
353   if ((rv = iavf_enable_disable_queues (vm, port, 1)))
354     goto done;
355
356   if (port->dev->poll_stats)
357     vnet_dev_poll_port_add (vm, port, 1, iavf_port_poll_stats);
358
359 done:
360   if (rv)
361     {
362       foreach_vnet_dev_port_rx_queue (q, port)
363         iavf_rx_queue_stop (vm, q);
364       foreach_vnet_dev_port_tx_queue (q, port)
365         iavf_tx_queue_stop (vm, q);
366     }
367   return rv;
368 }
369
370 void
371 iavf_port_stop (vlib_main_t *vm, vnet_dev_port_t *port)
372 {
373   log_debug (port->dev, "port %u", port->port_id);
374
375   iavf_enable_disable_queues (vm, port, /* enable */ 0);
376   iavf_port_rx_irq_config (vm, port, /* disable */ 0);
377
378   if (port->dev->poll_stats)
379     vnet_dev_poll_port_remove (vm, port, iavf_port_poll_stats);
380
381   foreach_vnet_dev_port_rx_queue (rxq, port)
382     iavf_rx_queue_stop (vm, rxq);
383
384   foreach_vnet_dev_port_tx_queue (txq, port)
385     iavf_tx_queue_stop (vm, txq);
386
387   vnet_dev_port_state_change (vm, port,
388                               (vnet_dev_port_state_changes_t){
389                                 .change.link_state = 1,
390                                 .change.link_speed = 1,
391                                 .link_speed = 0,
392                                 .link_state = 0,
393                               });
394 }
395
396 vnet_dev_rv_t
397 iavf_port_cfg_change_validate (vlib_main_t *vm, vnet_dev_port_t *port,
398                                vnet_dev_port_cfg_change_req_t *req)
399 {
400   vnet_dev_rv_t rv = VNET_DEV_OK;
401
402   switch (req->type)
403     {
404     case VNET_DEV_PORT_CFG_MAX_RX_FRAME_SIZE:
405       if (port->started)
406         rv = VNET_DEV_ERR_PORT_STARTED;
407       break;
408
409     case VNET_DEV_PORT_CFG_PROMISC_MODE:
410     case VNET_DEV_PORT_CFG_CHANGE_PRIMARY_HW_ADDR:
411     case VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR:
412     case VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR:
413       break;
414
415     default:
416       rv = VNET_DEV_ERR_NOT_SUPPORTED;
417     };
418
419   return rv;
420 }
421
422 static vnet_dev_rv_t
423 iavf_port_add_del_eth_addr (vlib_main_t *vm, vnet_dev_port_t *port,
424                             vnet_dev_hw_addr_t *addr, int is_add,
425                             int is_primary)
426 {
427   iavf_port_t *ap = vnet_dev_get_port_data (port);
428   u8 buffer[VIRTCHNL_MSG_SZ (virtchnl_ether_addr_list_t, list, 1)];
429   virtchnl_ether_addr_list_t *al = (virtchnl_ether_addr_list_t *) buffer;
430
431   *al = (virtchnl_ether_addr_list_t){
432     .vsi_id = ap->vsi_id,
433     .num_elements = 1,
434     .list[0].primary = is_primary ? 1 : 0,
435     .list[0].extra = is_primary ? 0 : 1,
436   };
437
438   clib_memcpy (al->list[0].addr, addr, sizeof (al->list[0].addr));
439
440   return is_add ? iavf_vc_op_add_eth_addr (vm, port->dev, al) :
441                   iavf_vc_op_del_eth_addr (vm, port->dev, al);
442 }
443
444 static vnet_dev_rv_t
445 iavf_port_cfg_rxq_int_mode_change (vlib_main_t *vm, vnet_dev_port_t *port,
446                                    u16 qid, u8 state, u8 all)
447 {
448   vnet_dev_rv_t rv = VNET_DEV_OK;
449   iavf_port_t *ap = vnet_dev_get_port_data (port);
450   vnet_dev_t *dev = port->dev;
451   char *ed = state ? "ena" : "disa";
452   char qstr[16];
453   u64 old, new = 0;
454
455   state = state != 0;
456   old = ap->intr_mode_per_rxq_bitmap;
457
458   if (all)
459     {
460       snprintf (qstr, sizeof (qstr), "all queues");
461       if (state)
462         foreach_vnet_dev_port_rx_queue (q, port)
463           u64_bit_set (&new, q->queue_id, 1);
464     }
465   else
466     {
467       snprintf (qstr, sizeof (qstr), "queue %u", qid);
468       new = old;
469       u64_bit_set (&new, qid, state);
470     }
471
472   if (new == old)
473     {
474       log_warn (dev, "interrupt mode already %sbled on %s", ed, qstr);
475       return rv;
476     }
477
478   ap->intr_mode_per_rxq_bitmap = new;
479
480   if (port->started)
481     {
482       if ((rv = iavf_port_rx_irq_config (vm, port, 1)))
483         {
484           ap->intr_mode_per_rxq_bitmap = old;
485           log_err (dev, "failed to %sble interrupt mode on %s", ed, qstr);
486           return rv;
487         }
488     }
489
490   log_debug (dev, "interrupt mode %sbled on %s, new bitmap is 0x%x", ed, qstr,
491              new);
492   return rv;
493 }
494
495 vnet_dev_rv_t
496 iavf_port_cfg_change (vlib_main_t *vm, vnet_dev_port_t *port,
497                       vnet_dev_port_cfg_change_req_t *req)
498 {
499   vnet_dev_t *dev = port->dev;
500   iavf_port_t *ap = vnet_dev_get_port_data (port);
501   vnet_dev_rv_t rv = VNET_DEV_OK;
502
503   switch (req->type)
504     {
505     case VNET_DEV_PORT_CFG_PROMISC_MODE:
506       {
507         virtchnl_promisc_info_t pi = {
508           .vsi_id = ap->vsi_id,
509           .unicast_promisc = req->promisc,
510           .multicast_promisc = req->promisc,
511         };
512
513         rv = iavf_vc_op_config_promisc_mode (vm, dev, &pi);
514       }
515       break;
516
517     case VNET_DEV_PORT_CFG_CHANGE_PRIMARY_HW_ADDR:
518       rv = iavf_port_add_del_eth_addr (vm, port, &port->primary_hw_addr,
519                                        /* is_add */ 0,
520                                        /* is_primary */ 1);
521       if (rv == VNET_DEV_OK)
522         rv = iavf_port_add_del_eth_addr (vm, port, &req->addr,
523                                          /* is_add */ 1,
524                                          /* is_primary */ 1);
525       break;
526
527     case VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR:
528       rv = iavf_port_add_del_eth_addr (vm, port, &req->addr,
529                                        /* is_add */ 1,
530                                        /* is_primary */ 0);
531       break;
532
533     case VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR:
534       rv = iavf_port_add_del_eth_addr (vm, port, &req->addr,
535                                        /* is_add */ 0,
536                                        /* is_primary */ 0);
537       break;
538
539     case VNET_DEV_PORT_CFG_MAX_RX_FRAME_SIZE:
540       break;
541
542     case VNET_DEV_PORT_CFG_RXQ_INTR_MODE_ENABLE:
543       rv = iavf_port_cfg_rxq_int_mode_change (vm, port, req->queue_id, 1,
544                                               req->all_queues);
545       break;
546
547     case VNET_DEV_PORT_CFG_RXQ_INTR_MODE_DISABLE:
548       rv = iavf_port_cfg_rxq_int_mode_change (vm, port, req->queue_id, 0,
549                                               req->all_queues);
550       break;
551
552     default:
553       return VNET_DEV_ERR_NOT_SUPPORTED;
554     };
555
556   return rv;
557 }