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