FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
pci.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <fcntl.h>
17 #include <sys/ioctl.h>
18 
19 #include <vppinfra/types.h>
20 #include <vlib/vlib.h>
21 #include <vlib/pci/pci.h>
22 #include <vnet/ethernet/ethernet.h>
23 #include <vnet/ip/ip4_packet.h>
24 #include <vnet/ip/ip6_packet.h>
27 
28 #define PCI_VENDOR_ID_VIRTIO 0x1af4
29 #define PCI_DEVICE_ID_VIRTIO_NIC 0x1000
30 /* Doesn't support modern device */
31 #define PCI_DEVICE_ID_VIRTIO_NIC_MODERN 0x1041
32 
33 #define PCI_CAPABILITY_LIST 0x34
34 #define PCI_CAP_ID_VNDR 0x09
35 #define PCI_CAP_ID_MSIX 0x11
36 
37 #define PCI_MSIX_ENABLE 0x8000
38 
39 static pci_device_id_t virtio_pci_device_ids[] = {
40  {
42  .device_id = PCI_DEVICE_ID_VIRTIO_NIC},
43  {
44  .vendor_id = PCI_VENDOR_ID_VIRTIO,
45  .device_id = PCI_DEVICE_ID_VIRTIO_NIC_MODERN},
46  {0},
47 };
48 
49 static u32
51  u32 flags)
52 {
53  return 0;
54 }
55 
56 static clib_error_t *
58 {
59  clib_error_t *error = 0;
60  u16 max_queue_pairs = 1;
61 
62  if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MQ))
63  {
64  max_queue_pairs = vif->virtio_pci_func->get_max_queue_pairs (vm, vif);
65  }
66 
67  virtio_log_debug (vif, "max queue pair is %x", max_queue_pairs);
68  if (max_queue_pairs < 1 || max_queue_pairs > 0x8000)
69  return clib_error_return (error, "max queue pair is %x,"
70  " should be in range [1, 0x8000]",
71  max_queue_pairs);
72 
73  vif->max_queue_pairs = max_queue_pairs;
74  return error;
75 }
76 
77 static void
79 {
80  if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MAC))
81  vif->virtio_pci_func->set_mac (vm, vif);
82 }
83 
84 static u32
86 {
87  if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MAC))
88  {
89  vif->virtio_pci_func->get_mac (vm, vif);
90  return 0;
91  }
92  return 1;
93 }
94 
95 static u16
97 {
98  /*
99  * Minimal driver: assumes link is up
100  */
101  u16 status = 1;
102  if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_STATUS))
103  status = vif->virtio_pci_func->get_device_status (vm, vif);
104  return status;
105 }
106 
107 static void
109  u16 line)
110 {
111  vnet_main_t *vnm = vnet_get_main ();
112  virtio_main_t *vim = &virtio_main;
113  uword pd = vlib_pci_get_private_data (vm, h);
114  virtio_if_t *vif = pool_elt_at_index (vim->interfaces, pd);
115  line--;
116  u16 qid = line;
117 
119 }
120 
121 static void
123  u16 line)
124 {
125  vnet_main_t *vnm = vnet_get_main ();
126  virtio_main_t *vim = &virtio_main;
127  uword pd = vlib_pci_get_private_data (vm, h);
128  virtio_if_t *vif = pool_elt_at_index (vim->interfaces, pd);
129 
130  if (virtio_pci_is_link_up (vm, vif) & VIRTIO_NET_S_LINK_UP)
131  {
132  vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP;
135  }
136  else
137  {
138  vif->flags &= ~VIRTIO_IF_FLAG_ADMIN_UP;
140  }
141 }
142 
143 static void
145 {
146  virtio_main_t *vim = &virtio_main;
147  uword pd = vlib_pci_get_private_data (vm, h);
148  virtio_if_t *vif = pool_elt_at_index (vim->interfaces, pd);
149  u8 isr = 0;
150  u16 line = 0;
151 
152  isr = vif->virtio_pci_func->get_isr (vm, vif);
153 
154  /*
155  * If the lower bit is set: look through the used rings of
156  * all virtqueues for the device, to see if any progress has
157  * been made by the device which requires servicing.
158  */
159  if (isr & VIRTIO_PCI_ISR_INTR)
160  {
161  for (; line < vif->num_rxqs; line++)
162  virtio_pci_irq_queue_handler (vm, h, (line + 1));
163  }
164 
165  if (isr & VIRTIO_PCI_ISR_CONFIG)
166  virtio_pci_irq_config_handler (vm, h, line);
167 }
168 
169 inline void
171 {
172  struct status_struct
173  {
174  u8 bit;
175  char *str;
176  };
177  struct status_struct *status_entry;
178  static struct status_struct status_array[] = {
179 #define _(s,b) { .str = #s, .bit = b, },
181 #undef _
182  {.str = NULL}
183  };
184 
185  vlib_cli_output (vm, " status 0x%x", vif->status);
186 
187  status_entry = (struct status_struct *) &status_array;
188  while (status_entry->str)
189  {
190  if (vif->status & status_entry->bit)
191  vlib_cli_output (vm, " %s (%x)", status_entry->str,
192  status_entry->bit);
193  status_entry++;
194  }
195 }
196 
197 static int
200 {
201  virtio_vring_t *vring = vif->cxq_vring;
203  virtio_ctrl_msg_t result;
204  u32 buffer_index;
205  vlib_buffer_t *b;
206  u16 used, next, avail;
207  u16 sz = vring->size;
208  u16 mask = sz - 1;
209 
210  used = vring->desc_in_use;
211  next = vring->desc_next;
212  avail = vring->avail->idx;
213  vring_desc_t *d = &vring->desc[next];
214 
215  if (vlib_buffer_alloc (vm, &buffer_index, 1))
216  b = vlib_get_buffer (vm, buffer_index);
217  else
218  return VIRTIO_NET_ERR;
219  /*
220  * current_data may not be initialized with 0 and may contain
221  * previous offset.
222  */
223  b->current_data = 0;
226  d->addr = vlib_buffer_get_current_pa (vm, b);
227  d->len = sizeof (virtio_net_ctrl_hdr_t);
228  vring->avail->ring[avail & mask] = next;
229  avail++;
230  next = (next + 1) & mask;
231  d->next = next;
232  used++;
233 
234  d = &vring->desc[next];
236  d->addr = vlib_buffer_get_current_pa (vm, b) +
238  d->len = len;
239  next = (next + 1) & mask;
240  d->next = next;
241  used++;
242 
243  d = &vring->desc[next];
245  d->addr = vlib_buffer_get_current_pa (vm, b) +
247  d->len = sizeof (data->status);
248  next = (next + 1) & mask;
249  used++;
250 
252  vring->avail->idx = avail;
253  vring->desc_next = next;
254  vring->desc_in_use = used;
255 
256  if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0)
257  {
258  virtio_kick (vm, vring, vif);
259  }
260 
261  u16 last = vring->last_used_idx, n_left = 0;
262  n_left = vring->used->idx - last;
263 
264  while (n_left)
265  {
266  vring_used_elem_t *e = &vring->used->ring[last & mask];
267  u16 slot = e->id;
268 
269  d = &vring->desc[slot];
270  while (d->flags & VRING_DESC_F_NEXT)
271  {
272  used--;
273  slot = d->next;
274  d = &vring->desc[slot];
275  }
276  used--;
277  last++;
278  n_left--;
279  }
280  vring->desc_in_use = used;
281  vring->last_used_idx = last;
282 
284  clib_memcpy (&result, vlib_buffer_get_current (b),
285  sizeof (virtio_ctrl_msg_t));
286  virtio_log_debug (vif, "ctrl-queue: status %u", result.status);
287  status = result.status;
288  vlib_buffer_free (vm, &buffer_index, 1);
289  return status;
290 }
291 
292 static int
294 {
295  virtio_ctrl_msg_t offload_hdr;
297 
298  offload_hdr.ctrl.class = VIRTIO_NET_CTRL_GUEST_OFFLOADS;
299  offload_hdr.ctrl.cmd = VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET;
300  offload_hdr.status = VIRTIO_NET_ERR;
301  u64 offloads = 0ULL;
302  clib_memcpy (offload_hdr.data, &offloads, sizeof (offloads));
303 
304  status =
305  virtio_pci_send_ctrl_msg (vm, vif, &offload_hdr, sizeof (offloads));
306  virtio_log_debug (vif, "disable offloads");
307  vif->remote_features = vif->virtio_pci_func->get_device_features (vm, vif);
308  vif->virtio_pci_func->get_driver_features (vm, vif);
309  return status;
310 }
311 
312 static int
314 {
315  virtio_ctrl_msg_t csum_offload_hdr;
317 
318  csum_offload_hdr.ctrl.class = VIRTIO_NET_CTRL_GUEST_OFFLOADS;
319  csum_offload_hdr.ctrl.cmd = VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET;
320  csum_offload_hdr.status = VIRTIO_NET_ERR;
321  u64 offloads = 0ULL;
322  offloads |= VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_CSUM);
323  clib_memcpy (csum_offload_hdr.data, &offloads, sizeof (offloads));
324 
325  status =
326  virtio_pci_send_ctrl_msg (vm, vif, &csum_offload_hdr, sizeof (offloads));
327  virtio_log_debug (vif, "enable checksum offload");
328  vif->remote_features = vif->virtio_pci_func->get_device_features (vm, vif);
329  vif->features = vif->virtio_pci_func->get_driver_features (vm, vif);
330  return status;
331 }
332 
333 static int
335 {
336  virtio_ctrl_msg_t gso_hdr;
338 
339  gso_hdr.ctrl.class = VIRTIO_NET_CTRL_GUEST_OFFLOADS;
341  gso_hdr.status = VIRTIO_NET_ERR;
342  u64 offloads = VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_CSUM)
343  | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO4)
344  | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO6);
345  clib_memcpy (gso_hdr.data, &offloads, sizeof (offloads));
346 
347  status = virtio_pci_send_ctrl_msg (vm, vif, &gso_hdr, sizeof (offloads));
348  virtio_log_debug (vif, "enable gso");
349  vif->remote_features = vif->virtio_pci_func->get_device_features (vm, vif);
350  vif->virtio_pci_func->get_driver_features (vm, vif);
351  return status;
352 }
353 
354 static int
355 virtio_pci_offloads (vlib_main_t * vm, virtio_if_t * vif, int gso_enabled,
356  int csum_offload_enabled)
357 {
358  vnet_main_t *vnm = vnet_get_main ();
360 
361  if ((vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ)) &&
362  (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)))
363  {
364  if (gso_enabled
365  && (vif->features & (VIRTIO_FEATURE (VIRTIO_NET_F_HOST_TSO4) |
366  VIRTIO_FEATURE (VIRTIO_NET_F_HOST_TSO6))))
367  {
368  if (virtio_pci_enable_gso (vm, vif))
369  {
370  virtio_log_warning (vif, "gso is not enabled");
371  }
372  else
373  {
374  vif->gso_enabled = 1;
375  vif->csum_offload_enabled = 0;
378  }
379  }
380  else if (csum_offload_enabled
381  && (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CSUM)))
382  {
384  {
385  virtio_log_warning (vif, "checksum offload is not enabled");
386  }
387  else
388  {
389  vif->csum_offload_enabled = 1;
390  vif->gso_enabled = 0;
392  hw->flags |=
394  }
395  }
396  else
397  {
398  if (virtio_pci_disable_offload (vm, vif))
399  {
400  virtio_log_warning (vif, "offloads are not disabled");
401  }
402  else
403  {
404  vif->csum_offload_enabled = 0;
405  vif->gso_enabled = 0;
408  }
409  }
410  }
411 
412  return 0;
413 }
414 
415 static int
417  u16 num_queues)
418 {
419  virtio_ctrl_msg_t mq_hdr;
421 
422  mq_hdr.ctrl.class = VIRTIO_NET_CTRL_MQ;
424  mq_hdr.status = VIRTIO_NET_ERR;
425  clib_memcpy (mq_hdr.data, &num_queues, sizeof (num_queues));
426 
427  status = virtio_pci_send_ctrl_msg (vm, vif, &mq_hdr, sizeof (num_queues));
428  virtio_log_debug (vif, "multi-queue enable %u queues", num_queues);
429  return status;
430 }
431 
432 static u8
434 {
435  if (qsz < 64 || qsz > 4096)
436  return 0;
437  if ((qsz % 64) != 0)
438  return 0;
439  return 1;
440 }
441 
442 clib_error_t *
444  u16 queue_num)
445 {
446  clib_error_t *error = 0;
447  u16 queue_size = 0;
448  virtio_vring_t *vring;
449  vring_t vr;
450  u32 i = 0;
451  void *ptr = NULL;
452 
453  queue_size = vif->virtio_pci_func->get_queue_size (vm, vif, queue_num);
454  if (!virtio_pci_queue_size_valid (queue_size))
455  clib_warning ("queue size is not valid");
456 
457  if (!is_pow2 (queue_size))
458  return clib_error_return (0, "ring size must be power of 2");
459 
460  if (queue_size > 32768)
461  return clib_error_return (0, "ring size must be 32768 or lower");
462 
463  if (queue_size == 0)
464  queue_size = 256;
465 
467  vring = vec_elt_at_index (vif->cxq_vring, 0);
468  i = vring_size (queue_size, VIRTIO_PCI_VRING_ALIGN);
470  ptr =
472  vif->numa_node);
473  if (!ptr)
474  return vlib_physmem_last_error (vm);
475  clib_memset (ptr, 0, i);
476  vring_init (&vr, queue_size, ptr, VIRTIO_PCI_VRING_ALIGN);
477  vring->desc = vr.desc;
478  vring->avail = vr.avail;
479  vring->used = vr.used;
480  vring->queue_id = queue_num;
482 
483  ASSERT (vring->buffers == 0);
484 
485  vring->size = queue_size;
486  virtio_log_debug (vif, "control-queue: number %u, size %u", queue_num,
487  queue_size);
488  vif->virtio_pci_func->setup_queue (vm, vif, queue_num, ptr);
489  vring->queue_notify_offset =
490  vif->notify_off_multiplier *
491  vif->virtio_pci_func->get_queue_notify_off (vm, vif, queue_num);
492  virtio_log_debug (vif, "queue-notify-offset: number %u, offset %u",
493  queue_num, vring->queue_notify_offset);
494 
495  return error;
496 }
497 
498 clib_error_t *
500 {
502  clib_error_t *error = 0;
503  u16 queue_size = 0;
504  virtio_vring_t *vring;
505  vring_t vr;
506  u32 i = 0;
507  void *ptr = NULL;
508 
509  queue_size = vif->virtio_pci_func->get_queue_size (vm, vif, queue_num);
510  if (!virtio_pci_queue_size_valid (queue_size))
511  clib_warning ("queue size is not valid");
512 
513  if (!is_pow2 (queue_size))
514  return clib_error_return (0, "ring size must be power of 2");
515 
516  if (queue_size > 32768)
517  return clib_error_return (0, "ring size must be 32768 or lower");
518 
519  if (queue_size == 0)
520  queue_size = 256;
521 
522  if (queue_num % 2)
523  {
526  vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS (queue_num));
527  if (vif->max_queue_pairs < vtm->n_vlib_mains)
528  clib_spinlock_init (&vring->lockp);
529  }
530  else
531  {
534  vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS (queue_num));
535  }
536  i = vring_size (queue_size, VIRTIO_PCI_VRING_ALIGN);
538  ptr =
540  vif->numa_node);
541  if (!ptr)
542  return vlib_physmem_last_error (vm);
543  clib_memset (ptr, 0, i);
544  vring_init (&vr, queue_size, ptr, VIRTIO_PCI_VRING_ALIGN);
545  vring->desc = vr.desc;
546  vring->avail = vr.avail;
547  vring->used = vr.used;
548  vring->queue_id = queue_num;
550  vring->flow_table = 0;
551 
552  ASSERT (vring->buffers == 0);
553  vec_validate_aligned (vring->buffers, queue_size, CLIB_CACHE_LINE_BYTES);
554  if (queue_num % 2)
555  {
556  virtio_log_debug (vif, "tx-queue: number %u, size %u", queue_num,
557  queue_size);
558  clib_memset_u32 (vring->buffers, ~0, queue_size);
559  }
560  else
561  {
562  virtio_log_debug (vif, "rx-queue: number %u, size %u", queue_num,
563  queue_size);
564  }
565  vring->size = queue_size;
566  if (vif->virtio_pci_func->setup_queue (vm, vif, queue_num, ptr))
567  return clib_error_return (0, "error in queue address setup");
568 
569  vring->queue_notify_offset =
570  vif->notify_off_multiplier *
571  vif->virtio_pci_func->get_queue_notify_off (vm, vif, queue_num);
572  virtio_log_debug (vif, "queue-notify-offset: number %u, offset %u",
573  queue_num, vring->queue_notify_offset);
574  return error;
575 }
576 
577 static void
579  u64 req_features)
580 {
581  /*
582  * if features are not requested
583  * default: all supported features
584  */
585  u64 supported_features = VIRTIO_FEATURE (VIRTIO_NET_F_CSUM)
586  | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_CSUM)
587  | VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)
588  | VIRTIO_FEATURE (VIRTIO_NET_F_MTU)
589  | VIRTIO_FEATURE (VIRTIO_NET_F_MAC)
590  | VIRTIO_FEATURE (VIRTIO_NET_F_GSO)
591  | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO4)
592  | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO6)
593  | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_UFO)
594  | VIRTIO_FEATURE (VIRTIO_NET_F_HOST_TSO4)
595  | VIRTIO_FEATURE (VIRTIO_NET_F_HOST_TSO6)
596  | VIRTIO_FEATURE (VIRTIO_NET_F_HOST_UFO)
597  | VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF)
598  | VIRTIO_FEATURE (VIRTIO_NET_F_STATUS)
599  | VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ)
600  | VIRTIO_FEATURE (VIRTIO_NET_F_MQ)
601  | VIRTIO_FEATURE (VIRTIO_F_NOTIFY_ON_EMPTY)
602  | VIRTIO_FEATURE (VIRTIO_F_ANY_LAYOUT)
603  | VIRTIO_FEATURE (VIRTIO_RING_F_INDIRECT_DESC);
604 
605  if (vif->is_modern)
606  supported_features |= VIRTIO_FEATURE (VIRTIO_F_VERSION_1);
607 
608  if (req_features == 0)
609  {
610  req_features = supported_features;
611  }
612 
613  vif->features = req_features & vif->remote_features & supported_features;
614 
615  if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MTU))
616  {
617  u16 mtu = 0;
618  mtu = vif->virtio_pci_func->get_mtu (vm, vif);
619 
620  if (mtu < 64)
621  vif->features &= ~VIRTIO_FEATURE (VIRTIO_NET_F_MTU);
622  }
623 
624  vif->virtio_pci_func->set_driver_features (vm, vif, vif->features);
625  vif->features = vif->virtio_pci_func->get_driver_features (vm, vif);
626 }
627 
628 void
630 {
631  vif->remote_features = vif->virtio_pci_func->get_device_features (vm, vif);
632 }
633 
634 int
636 {
637  u8 status = 0;
638 
639  /*
640  * Reset the device
641  */
642  status = vif->virtio_pci_func->device_reset (vm, vif);
643 
644  /*
645  * Set the Acknowledge status bit
646  */
647  vif->virtio_pci_func->set_status (vm, vif, VIRTIO_CONFIG_STATUS_ACK);
648 
649  /*
650  * Set the Driver status bit
651  */
652  vif->virtio_pci_func->set_status (vm, vif, VIRTIO_CONFIG_STATUS_DRIVER);
653 
654  /*
655  * Read the status and verify it
656  */
657  status = vif->virtio_pci_func->get_status (vm, vif);
658  if ((status & VIRTIO_CONFIG_STATUS_ACK)
659  && (status & VIRTIO_CONFIG_STATUS_DRIVER))
660  vif->status = status;
661  else
662  return -1;
663 
664  return 0;
665 }
666 
667 clib_error_t *
669 {
670  clib_error_t *error = 0;
671  virtio_pci_cap_t cap;
672  u8 pos, common_cfg = 0, notify = 0, dev_cfg = 0, isr = 0, pci_cfg = 0;
674 
675  if ((error = vlib_pci_read_config_u8 (vm, h, PCI_CAPABILITY_LIST, &pos)))
676  {
677  virtio_log_error (vif, "error in reading capabilty list position");
678  return clib_error_return (error,
679  "error in reading capabilty list position");
680  }
681  while (pos)
682  {
683  if ((error =
684  vlib_pci_read_write_config (vm, h, VLIB_READ, pos, &cap,
685  sizeof (cap))))
686  {
687  virtio_log_error (vif, "%s [%2x]",
688  "error in reading the capability at", pos);
689  return clib_error_return (error,
690  "error in reading the capability at [%2x]",
691  pos);
692  }
693 
694  if (cap.cap_vndr == PCI_CAP_ID_MSIX)
695  {
696  u16 flags, table_size, table_size_mask = 0x07FF;
697 
698  if ((error =
699  vlib_pci_read_write_config (vm, h, VLIB_READ, pos + 2, &flags,
700  sizeof (flags))))
701  return clib_error_return (error,
702  "error in reading the capability at [%2x]",
703  pos + 2);
704 
705  table_size = flags & table_size_mask;
706  virtio_log_debug (vif, "flags:0x%x %s 0x%x", flags,
707  "msix interrupt vector table-size", table_size);
708 
709  if (flags & PCI_MSIX_ENABLE)
710  {
711  virtio_log_debug (vif, "msix interrupt enabled");
713  vif->msix_table_size = table_size;
714  }
715  else
716  {
717  virtio_log_debug (vif, "msix interrupt disabled");
719  vif->msix_table_size = 0;
720  }
721  }
722 
723  if (cap.cap_vndr != PCI_CAP_ID_VNDR)
724  {
725  virtio_log_debug (vif, "[%2x] %s %2x ", pos,
726  "skipping non VNDR cap id:", cap.cap_vndr);
727  goto next;
728  }
729 
730  virtio_log_debug (vif,
731  "[%4x] cfg type: %u, bar: %u, offset: %04x, len: %u",
732  pos, cap.cfg_type, cap.bar, cap.offset, cap.length);
733 
734  if (cap.bar >= 0 && cap.bar <= 5)
735  {
736  vif->bar = bar[cap.bar];
737  vif->bar_id = cap.bar;
738  }
739  else
740  return clib_error_return (error, "invalid bar %u", cap.bar);
741 
742  switch (cap.cfg_type)
743  {
745  vif->common_offset = cap.offset;
746  common_cfg = 1;
747  break;
749  if ((error =
751  pos + sizeof (cap),
752  &vif->notify_off_multiplier,
753  sizeof
754  (vif->notify_off_multiplier))))
755  {
756  virtio_log_error (vif, "notify off multiplier is not given");
757  }
758  else
759  {
760  virtio_log_debug (vif, "notify off multiplier is %u",
761  vif->notify_off_multiplier);
762  vif->notify_offset = cap.offset;
763  notify = 1;
764  }
765  break;
767  vif->device_offset = cap.offset;
768  dev_cfg = 1;
769  break;
771  vif->isr_offset = cap.offset;
772  isr = 1;
773  break;
775  if (cap.bar == 0)
776  pci_cfg = 1;
777  break;
778  }
779  next:
780  pos = cap.cap_next;
781  }
782 
783  if (common_cfg == 0 || notify == 0 || dev_cfg == 0 || isr == 0)
784  {
786  vif->notify_off_multiplier = 0;
787  virtio_log_debug (vif, "legacy virtio pci device found");
788  return error;
789  }
790 
791  vif->is_modern = 1;
793 
794  if (!pci_cfg)
795  {
796  virtio_log_debug (vif, "modern virtio pci device found");
797  }
798  else
799  {
800  virtio_log_debug (vif, "transitional virtio pci device found");
801  }
802 
803  return error;
804 }
805 
806 static clib_error_t *
808  virtio_pci_create_if_args_t * args, void **bar)
809 {
810  clib_error_t *error = 0;
812  u8 status = 0;
813 
814  if ((error = virtio_pci_read_caps (vm, vif, bar)))
815  {
816  args->rv = VNET_API_ERROR_UNSUPPORTED;
817  virtio_log_error (vif, "Device is not supported");
818  return clib_error_return (error, "Device is not supported");
819  }
820 
821  if (virtio_pci_reset_device (vm, vif) < 0)
822  {
823  args->rv = VNET_API_ERROR_INIT_FAILED;
824  virtio_log_error (vif, "Failed to reset the device");
825  return clib_error_return (error, "Failed to reset the device");
826  }
827  /*
828  * read device features and negotiate (user) requested features
829  */
831  if ((vif->remote_features & VIRTIO_FEATURE (VIRTIO_RING_F_INDIRECT_DESC)) ==
832  0)
833  {
834  virtio_log_warning (vif, "error encountered: vhost-net backend doesn't "
835  "support VIRTIO_RING_F_INDIRECT_DESC features");
836  }
837  if ((vif->remote_features & VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF)) == 0)
838  {
839  virtio_log_warning (vif, "error encountered: vhost-net backend doesn't "
840  "support VIRTIO_NET_F_MRG_RXBUF features");
841  }
842  virtio_negotiate_features (vm, vif, args->features);
843 
844  /*
845  * After FEATURE_OK, driver should not accept new feature bits
846  */
847  vif->virtio_pci_func->set_status (vm, vif,
848  VIRTIO_CONFIG_STATUS_FEATURES_OK);
849  status = vif->virtio_pci_func->get_status (vm, vif);
850  if (!(status & VIRTIO_CONFIG_STATUS_FEATURES_OK))
851  {
852  args->rv = VNET_API_ERROR_UNSUPPORTED;
853  virtio_log_error (vif,
854  "error encountered: Device doesn't support requested features");
855  return clib_error_return (error,
856  "Device doesn't support requested features");
857  }
858  vif->status = status;
859 
860  /*
861  * get or set the mac address
862  */
863  if (virtio_pci_get_mac (vm, vif))
864  {
865  f64 now = vlib_time_now (vm);
866  u32 rnd;
867  rnd = (u32) (now * 1e6);
868  rnd = random_u32 (&rnd);
869 
870  memcpy (vif->mac_addr + 2, &rnd, sizeof (rnd));
871  vif->mac_addr[0] = 2;
872  vif->mac_addr[1] = 0xfe;
873  virtio_pci_set_mac (vm, vif);
874  }
875 
877 
878  /*
879  * Initialize the virtqueues
880  */
881  if ((error = virtio_pci_get_max_virtqueue_pairs (vm, vif)))
882  {
883  args->rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
884  goto err;
885  }
886 
887  if (vif->msix_enabled == VIRTIO_MSIX_ENABLED)
888  {
889  if (vif->msix_table_size <= vif->max_queue_pairs)
890  {
891  virtio_log_error (vif,
892  "error MSIX lines (%u) <= Number of RXQs (%u)",
893  vif->msix_table_size, vif->max_queue_pairs);
894  return clib_error_return (error,
895  "error MSIX lines (%u) <= Number of RXQs (%u)",
896  vif->msix_table_size,
897  vif->max_queue_pairs);
898  }
899  }
900 
901  for (int i = 0; i < vif->max_queue_pairs; i++)
902  {
903  if ((error = virtio_pci_vring_init (vm, vif, RX_QUEUE (i))))
904  {
905  args->rv = VNET_API_ERROR_INIT_FAILED;
906  virtio_log_error (vif, "%s (%u) %s", "error in rxq-queue",
907  RX_QUEUE (i), "initialization");
908  error =
909  clib_error_return (error, "%s (%u) %s", "error in rxq-queue",
910  RX_QUEUE (i), "initialization");
911  goto err;
912  }
913  else
914  {
915  vif->num_rxqs++;
916  }
917 
918  if (i >= vtm->n_vlib_mains)
919  {
920  /*
921  * There is 1:1 mapping between tx queue and vpp worker thread.
922  * tx queue 0 is bind with thread index 0, tx queue 1 on thread
923  * index 1 and so on.
924  * Multiple worker threads can poll same tx queue when number of
925  * workers are more than tx queues. In this case, 1:N mapping
926  * between tx queue and vpp worker thread.
927  */
928  virtio_log_debug (vif, "%s %u, %s", "tx-queue: number",
929  TX_QUEUE (i),
930  "no VPP worker thread is available");
931  continue;
932  }
933 
934  if ((error = virtio_pci_vring_init (vm, vif, TX_QUEUE (i))))
935  {
936  args->rv = VNET_API_ERROR_INIT_FAILED;
937  virtio_log_error (vif, "%s (%u) %s", "error in txq-queue",
938  TX_QUEUE (i), "initialization");
939  error =
940  clib_error_return (error, "%s (%u) %s", "error in txq-queue",
941  TX_QUEUE (i), "initialization");
942  goto err;
943  }
944  else
945  {
946  vif->num_txqs++;
947  }
948  }
949 
950  if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
951  {
952  if ((error =
953  virtio_pci_control_vring_init (vm, vif, vif->max_queue_pairs * 2)))
954  {
955  virtio_log_warning (vif, "%s (%u) %s", "error in control-queue",
956  vif->max_queue_pairs * 2, "initialization");
957  if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MQ))
958  vif->features &= ~VIRTIO_FEATURE (VIRTIO_NET_F_MQ);
959  }
960  }
961  else
962  {
963  virtio_log_debug (vif, "control queue is not available");
964  vif->cxq_vring = NULL;
965  }
966 
967  /*
968  * set the msix interrupts
969  */
970  if (vif->msix_enabled == VIRTIO_MSIX_ENABLED)
971  {
972  int i, j;
973  if (vif->virtio_pci_func->set_config_irq (vm, vif, 0) ==
975  {
976  virtio_log_warning (vif, "config vector 0 is not set");
977  }
978  else
979  {
980  virtio_log_debug (vif, "config msix vector is set at 0");
981  }
982  for (i = 0, j = 1; i < vif->max_queue_pairs; i++, j++)
983  {
984  if (vif->virtio_pci_func->set_queue_irq (vm, vif, j,
985  RX_QUEUE (i)) ==
987  {
988  virtio_log_warning (vif, "queue (%u) vector is not set at %u",
989  RX_QUEUE (i), j);
990  }
991  else
992  {
993  virtio_log_debug (vif, "%s (%u) %s %u", "queue",
994  RX_QUEUE (i), "msix vector is set at", j);
995  }
996  }
997  }
998 
999  /*
1000  * set the driver status OK
1001  */
1002  vif->virtio_pci_func->set_status (vm, vif, VIRTIO_CONFIG_STATUS_DRIVER_OK);
1003  vif->status = vif->virtio_pci_func->get_status (vm, vif);
1004 err:
1005  return error;
1006 }
1007 
1008 void
1010 {
1011  vnet_main_t *vnm = vnet_get_main ();
1012  virtio_main_t *vim = &virtio_main;
1013  virtio_if_t *vif;
1015  clib_error_t *error = 0;
1016  u32 interrupt_count = 0;
1017 
1018  /* *INDENT-OFF* */
1019  pool_foreach (vif, vim->interfaces, ({
1020  if (vif->pci_addr.as_u32 == args->addr)
1021  {
1022  args->rv = VNET_API_ERROR_ADDRESS_IN_USE;
1023  args->error =
1024  clib_error_return (error, "PCI address in use");
1025  vlib_log (VLIB_LOG_LEVEL_ERR, vim->log_default, "%U: %s",
1026  format_vlib_pci_addr, &args->addr,
1027  " PCI address in use");
1028  return;
1029  }
1030  }));
1031  /* *INDENT-ON* */
1032 
1033  pool_get (vim->interfaces, vif);
1034  vif->dev_instance = vif - vim->interfaces;
1035  vif->per_interface_next_index = ~0;
1036  vif->pci_addr.as_u32 = args->addr;
1037 
1038  if ((error =
1039  vlib_pci_device_open (vm, (vlib_pci_addr_t *) & vif->pci_addr,
1040  virtio_pci_device_ids, &h)))
1041  {
1042  args->rv = VNET_API_ERROR_INVALID_INTERFACE;
1043  args->error =
1044  clib_error_return (error, "pci-addr %U", format_vlib_pci_addr,
1045  &vif->pci_addr);
1046  vlib_log (VLIB_LOG_LEVEL_ERR, vim->log_default, "%U: %s",
1047  format_vlib_pci_addr, &vif->pci_addr,
1048  "error encountered on pci device open");
1049  pool_put (vim->interfaces, vif);
1050  return;
1051  }
1052  vif->pci_dev_handle = h;
1053  vlib_pci_set_private_data (vm, h, vif->dev_instance);
1054  vif->numa_node = vlib_pci_get_numa_node (vm, h);
1055  vif->type = VIRTIO_IF_TYPE_PCI;
1056 
1057  if ((error = vlib_pci_bus_master_enable (vm, h)))
1058  {
1059  virtio_log_error (vif, "error encountered on pci bus master enable");
1060  goto error;
1061  }
1062 
1063  void *bar[6];
1064  for (u32 i = 0; i <= 5; i++)
1065  {
1066 
1067  if ((error = vlib_pci_map_region (vm, h, i, &bar[i])))
1068  {
1069  virtio_log_debug (vif, "no pci map region for bar %u", i);
1070  }
1071  else
1072  {
1073  virtio_log_debug (vif, "pci map region for bar %u at %p", i,
1074  bar[i]);
1075  }
1076  }
1077 
1078  if ((error = vlib_pci_io_region (vm, h, 0)))
1079  {
1080  virtio_log_error (vif, "error encountered on pci io region");
1081  goto error;
1082  }
1083 
1084  interrupt_count = vlib_pci_get_num_msix_interrupts (vm, h);
1085  if (interrupt_count > 1)
1086  {
1087  if ((error = vlib_pci_register_msix_handler (vm, h, 0, 1,
1089  {
1090  args->rv = VNET_API_ERROR_INVALID_REGISTRATION;
1091  virtio_log_error (vif,
1092  "error encountered on pci register msix handler 0");
1093  goto error;
1094  }
1095 
1096  if ((error =
1097  vlib_pci_register_msix_handler (vm, h, 1, (interrupt_count - 1),
1099  {
1100  args->rv = VNET_API_ERROR_INVALID_REGISTRATION;
1101  virtio_log_error (vif,
1102  "error encountered on pci register msix handler 1");
1103  goto error;
1104  }
1105 
1106  if ((error = vlib_pci_enable_msix_irq (vm, h, 0, interrupt_count)))
1107  {
1108  virtio_log_error (vif, "error encountered on pci enable msix irq");
1109  goto error;
1110  }
1111  vif->support_int_mode = 1;
1112  virtio_log_debug (vif, "device supports msix interrupts");
1113  }
1114  else if (interrupt_count == 1)
1115  {
1116  /*
1117  * if msix table-size is 1, fall back to intX.
1118  */
1119  if ((error =
1121  {
1122  virtio_log_error (vif,
1123  "error encountered on pci register interrupt handler");
1124  goto error;
1125  }
1126  vif->support_int_mode = 1;
1127  virtio_log_debug (vif, "pci register interrupt handler");
1128  }
1129  else
1130  {
1131  /*
1132  * WARN: intX is showing some weird behaviour.
1133  * Please don't use interrupt mode with UIO driver.
1134  */
1135  vif->support_int_mode = 0;
1136  virtio_log_debug (vif, "driver is configured in poll mode only");
1137  }
1138 
1139  if ((error = vlib_pci_intr_enable (vm, h)))
1140  {
1141  virtio_log_error (vif, "error encountered on pci interrupt enable");
1142  goto error;
1143  }
1144 
1145  if ((error = virtio_pci_device_init (vm, vif, args, bar)))
1146  {
1147  virtio_log_error (vif, "error encountered on device init");
1148  goto error;
1149  }
1150 
1151  /* create interface */
1153  vif->dev_instance, vif->mac_addr,
1154  &vif->hw_if_index,
1156 
1157  if (error)
1158  {
1159  args->rv = VNET_API_ERROR_INVALID_REGISTRATION;
1160  virtio_log_error (vif,
1161  "error encountered on ethernet register interface");
1162  goto error;
1163  }
1164 
1165  vnet_sw_interface_t *sw = vnet_get_hw_sw_interface (vnm, vif->hw_if_index);
1166  vif->sw_if_index = sw->sw_if_index;
1167  args->sw_if_index = sw->sw_if_index;
1168 
1169  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, vif->hw_if_index);
1171  vnet_hw_interface_set_input_node (vnm, vif->hw_if_index,
1172  virtio_input_node.index);
1173  u32 i = 0;
1174  vec_foreach_index (i, vif->rxq_vrings)
1175  {
1176  vnet_hw_interface_assign_rx_thread (vnm, vif->hw_if_index, i, ~0);
1178  /* Set default rx mode to POLLING */
1179  vnet_hw_interface_set_rx_mode (vnm, vif->hw_if_index, i,
1181  }
1182  if (virtio_pci_is_link_up (vm, vif) & VIRTIO_NET_S_LINK_UP)
1183  {
1184  vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP;
1185  vnet_hw_interface_set_flags (vnm, vif->hw_if_index,
1187  }
1188  else
1189  vnet_hw_interface_set_flags (vnm, vif->hw_if_index, 0);
1190 
1191  virtio_pci_offloads (vm, vif, args->gso_enabled,
1192  args->checksum_offload_enabled);
1193 
1194  if ((vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ)) &&
1195  (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MQ)))
1196  {
1197  if (virtio_pci_enable_multiqueue (vm, vif, vif->max_queue_pairs))
1198  virtio_log_warning (vif, "multiqueue is not set");
1199  }
1200  return;
1201 
1202 error:
1203  virtio_pci_delete_if (vm, vif);
1204  if (args->rv == 0)
1205  args->rv = VNET_API_ERROR_INVALID_INTERFACE;
1206  args->error = error;
1207 }
1208 
1209 int
1211 {
1212  vnet_main_t *vnm = vnet_get_main ();
1213  virtio_main_t *vim = &virtio_main;
1214  u32 i = 0;
1215 
1216  if (vif->type != VIRTIO_IF_TYPE_PCI)
1217  return VNET_API_ERROR_INVALID_INTERFACE;
1218 
1220 
1221  for (i = 0; i < vif->max_queue_pairs; i++)
1222  {
1223  vif->virtio_pci_func->del_queue (vm, vif, RX_QUEUE (i));
1224  vif->virtio_pci_func->del_queue (vm, vif, TX_QUEUE (i));
1225  }
1226 
1227  if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
1228  vif->virtio_pci_func->del_queue (vm, vif, vif->max_queue_pairs * 2);
1229 
1230  if (vif->virtio_pci_func)
1231  vif->virtio_pci_func->device_reset (vm, vif);
1232 
1233  if (vif->hw_if_index)
1234  {
1236  vec_foreach_index (i, vif->rxq_vrings)
1237  {
1239  }
1241  }
1242 
1244 
1245  vec_foreach_index (i, vif->rxq_vrings)
1246  {
1247  virtio_vring_t *vring = vec_elt_at_index (vif->rxq_vrings, i);
1248  if (vring->used)
1249  {
1250  virtio_free_rx_buffers (vm, vring);
1251  }
1252  vec_free (vring->buffers);
1253  vlib_physmem_free (vm, vring->desc);
1254  }
1255 
1256  vec_foreach_index (i, vif->txq_vrings)
1257  {
1258  virtio_vring_t *vring = vec_elt_at_index (vif->txq_vrings, i);
1259  if (vring->used)
1260  {
1261  virtio_free_used_desc (vm, vring);
1262  }
1263  vec_free (vring->buffers);
1264  clib_spinlock_free (&vring->lockp);
1265  vlib_physmem_free (vm, vring->desc);
1266  }
1267 
1268  if (vif->cxq_vring != NULL)
1269  {
1270  u16 last = vif->cxq_vring->last_used_idx;
1271  u16 n_left = vif->cxq_vring->used->idx - last;
1272  while (n_left)
1273  {
1274  last++;
1275  n_left--;
1276  }
1277 
1278  vif->cxq_vring->last_used_idx = last;
1279  vlib_physmem_free (vm, vif->cxq_vring->desc);
1280  }
1281 
1282  vec_free (vif->rxq_vrings);
1283  vec_free (vif->txq_vrings);
1284  vec_free (vif->cxq_vring);
1285 
1286  clib_error_free (vif->error);
1287  memset (vif, 0, sizeof (*vif));
1288  pool_put (vim->interfaces, vif);
1289 
1290  return 0;
1291 }
1292 
1293 int
1295  int gso_enabled,
1296  int checksum_offload_enabled,
1297  int offloads_disabled)
1298 {
1299  if (vif->type != VIRTIO_IF_TYPE_PCI)
1300  return VNET_API_ERROR_INVALID_INTERFACE;
1301 
1302  if (gso_enabled)
1303  virtio_pci_offloads (vm, vif, 1, 0);
1304  else if (checksum_offload_enabled)
1305  virtio_pci_offloads (vm, vif, 0, 1);
1306  else if (offloads_disabled)
1307  virtio_pci_offloads (vm, vif, 0, 0);
1308 
1309  return 0;
1310 }
1311 
1312 /*
1313  * fd.io coding-style-patch-verification: ON
1314  *
1315  * Local Variables:
1316  * eval: (c-set-style "gnu")
1317  * End:
1318  */
gro_flow_table_t * flow_table
Definition: virtio.h:86
vlib_node_registration_t virtio_input_node
(constructor) VLIB_REGISTER_NODE (virtio_input_node)
Definition: node.c:490
static uword vlib_buffer_get_current_pa(vlib_main_t *vm, vlib_buffer_t *b)
Definition: buffer_funcs.h:463
#define vec_foreach_index(var, v)
Iterate over vector indices.
static int virtio_pci_disable_offload(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:293
static clib_error_t * vlib_pci_intr_enable(vlib_main_t *vm, vlib_pci_dev_handle_t h)
Definition: pci.h:239
void virtio_set_net_hdr_size(virtio_if_t *vif)
Definition: virtio.c:255
virtio_if_t * interfaces
Definition: virtio.h:192
clib_error_t * virtio_pci_vring_init(vlib_main_t *vm, virtio_if_t *vif, u16 queue_num)
Definition: pci.c:499
u32 is_modern
Definition: virtio.h:173
static u32 virtio_pci_flag_change(vnet_main_t *vnm, vnet_hw_interface_t *hw, u32 flags)
Definition: pci.c:50
static clib_error_t * vlib_pci_bus_master_enable(vlib_main_t *vm, vlib_pci_dev_handle_t h)
Definition: pci.h:271
static void * vlib_physmem_alloc_aligned_on_numa(vlib_main_t *vm, uword n_bytes, uword alignment, u32 numa_node)
Definition: physmem_funcs.h:63
#define VIRTIO_PCI_CAP_ISR_CFG
Definition: pci.h:82
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:103
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:937
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:378
u32 bar_id
Definition: virtio.h:171
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vring_used_t * used
Definition: virtio_std.h:177
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
unsigned long u64
Definition: types.h:89
int gso_enabled
Definition: virtio.h:114
void vlib_pci_device_close(vlib_main_t *vm, vlib_pci_dev_handle_t h)
Definition: pci.c:1297
static void virtio_pci_irq_queue_handler(vlib_main_t *vm, vlib_pci_dev_handle_t h, u16 line)
Definition: pci.c:108
#define CLIB_MEMORY_STORE_BARRIER()
Definition: clib.h:135
vring_used_elem_t ring[0]
Definition: virtio_std.h:113
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:333
u16 device_offset
Definition: virtio.h:176
u32 vlib_pci_get_num_msix_interrupts(vlib_main_t *vm, vlib_pci_dev_handle_t h)
Definition: pci.c:177
static clib_error_t * vlib_physmem_last_error(struct vlib_main_t *vm)
const virtio_pci_func_t * virtio_pci_func
Definition: virtio.h:184
static clib_error_t * vlib_pci_intr_disable(vlib_main_t *vm, vlib_pci_dev_handle_t h)
Definition: pci.h:255
static clib_error_t * virtio_pci_device_init(vlib_main_t *vm, virtio_if_t *vif, virtio_pci_create_if_args_t *args, void **bar)
Definition: pci.c:807
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
vnet_device_class_t virtio_device_class
static heap_elt_t * last(heap_header_t *h)
Definition: heap.c:53
void virtio_vring_set_numa_node(vlib_main_t *vm, virtio_if_t *vif, u32 idx)
Definition: virtio.c:239
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:70
clib_error_t * vlib_pci_enable_msix_irq(vlib_main_t *vm, vlib_pci_dev_handle_t h, u16 start, u16 count)
Definition: pci.c:894
vlib_main_t * vm
Definition: in2out_ed.c:1582
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:520
u16 mask
Definition: flow_types.api:52
vring_avail_t * avail
Definition: virtio_std.h:176
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:252
static int virtio_pci_enable_gso(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:334
#define VIRTIO_NET_CTRL_GUEST_OFFLOADS
Definition: pci.h:74
void * bar
Definition: virtio.h:168
static void virtio_pci_set_mac(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:78
unsigned char u8
Definition: types.h:56
void virtio_pci_create_if(vlib_main_t *vm, virtio_pci_create_if_args_t *args)
Definition: pci.c:1009
u8 data[128]
Definition: ipsec_types.api:89
#define VIRTIO_FEATURE(X)
Definition: virtio_std.h:69
vring_desc_t * desc
Definition: virtio.h:63
double f64
Definition: types.h:142
static void clib_spinlock_free(clib_spinlock_t *p)
Definition: lock.h:70
u32 offset
Definition: pci.h:108
static vnet_sw_interface_t * vnet_get_hw_sw_interface(vnet_main_t *vnm, u32 hw_if_index)
#define clib_memcpy(d, s, n)
Definition: string.h:180
static void virtio_pci_irq_handler(vlib_main_t *vm, vlib_pci_dev_handle_t h)
Definition: pci.c:144
const virtio_pci_func_t virtio_pci_legacy_func
clib_error_t * vlib_pci_read_write_config(vlib_main_t *vm, vlib_pci_dev_handle_t h, vlib_read_or_write_t read_or_write, uword address, void *data, u32 n_bytes)
Definition: pci.c:1022
u32 msix_enabled
Definition: virtio.h:122
u16 msix_table_size
Definition: virtio.h:179
#define VIRTIO_PCI_CAP_COMMON_CFG
Definition: pci.h:78
u64 features
Definition: virtio.h:107
int virtio_pci_reset_device(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:635
u32 hw_if_index
Definition: virtio.h:128
static u8 virtio_pci_queue_size_valid(u16 qsz)
Definition: pci.c:433
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
#define virtio_log_error(vif, f,...)
Definition: virtio.h:258
#define PCI_DEVICE_ID_VIRTIO_NIC
Definition: pci.c:29
#define TX_QUEUE_ACCESS(X)
Definition: virtio.h:38
u32 notify_off_multiplier
Definition: virtio.h:172
void device_status(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:170
static_always_inline void vnet_device_input_set_interrupt_pending(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id)
Definition: devices.h:136
static void virtio_negotiate_features(vlib_main_t *vm, virtio_if_t *vif, u64 req_features)
Definition: pci.c:578
vnet_hw_interface_flags_t flags
Definition: interface.h:537
u16 isr_offset
Definition: virtio.h:177
void virtio_free_rx_buffers(vlib_main_t *vm, virtio_vring_t *vring)
Definition: virtio.c:137
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
clib_spinlock_t lockp
Definition: virtio.h:62
#define clib_error_return(e, args...)
Definition: error.h:99
#define VIRTIO_PCI_CAP_NOTIFY_CFG
Definition: pci.h:80
unsigned int u32
Definition: types.h:88
#define virtio_log_warning(vif, f,...)
Definition: virtio.h:251
#define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET
Definition: pci.h:75
u16 queue_id
Definition: virtio.h:79
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:63
u16 num_txqs
Definition: virtio.h:111
u32 pci_dev_handle
Definition: virtio.h:121
#define TX_QUEUE(X)
Definition: virtio.h:36
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
#define VIRTIO_MSI_NO_VECTOR
Definition: pci.h:29
void vlib_pci_set_private_data(vlib_main_t *vm, vlib_pci_dev_handle_t h, uword private_data)
Definition: pci.c:155
vring_avail_t * avail
Definition: virtio.h:65
static __clib_warn_unused_result u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:677
static_always_inline u16 vring_size(u32 num, u32 align)
Definition: virtio_std.h:194
unsigned short u16
Definition: types.h:57
#define VIRTIO_PCI_ISR_CONFIG
Definition: pci.h:34
vec_header_t h
Definition: buffer.c:322
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:302
clib_error_t * vlib_pci_register_msix_handler(vlib_main_t *vm, vlib_pci_dev_handle_t h, u32 start, u32 count, pci_msix_handler_function_t *msix_handler)
Definition: pci.c:837
#define PCI_MSIX_ENABLE
Definition: pci.c:37
uword vlib_pci_get_private_data(vlib_main_t *vm, vlib_pci_dev_handle_t h)
Definition: pci.c:148
u32 vlib_pci_dev_handle_t
Definition: pci.h:97
void virtio_pci_read_device_feature(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:629
virtio_net_ctrl_hdr_t ctrl
Definition: pci.h:169
static clib_error_t * virtio_pci_get_max_virtqueue_pairs(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:57
#define PCI_CAPABILITY_LIST
Definition: pci.c:33
vring_desc_t * desc
Definition: virtio_std.h:175
int virtio_pci_enable_disable_offloads(vlib_main_t *vm, virtio_if_t *vif, int gso_enabled, int checksum_offload_enabled, int offloads_disabled)
Definition: pci.c:1294
#define virtio_log_debug(vif, f,...)
Definition: virtio.h:244
u8 status
Definition: virtio.h:181
u8 len
Definition: ip_types.api:92
vring_used_t * used
Definition: virtio.h:64
u16 desc_next
Definition: virtio.h:67
u8 * format_vlib_pci_addr(u8 *s, va_list *va)
Definition: pci.c:141
u8 slot
Definition: pci_types.api:22
#define VIRTIO_PCI_VRING_ALIGN
Definition: pci.h:90
u32 length
Definition: pci.h:109
u16 num_rxqs
Definition: virtio.h:110
virtio_vring_t * rxq_vrings
Definition: virtio.h:112
u32 vlib_pci_get_numa_node(vlib_main_t *vm, vlib_pci_dev_handle_t h)
Definition: pci.c:170
u16 last_used_idx
Definition: virtio.h:83
#define VIRTIO_PCI_ISR_INTR
Definition: pci.h:32
static void vlib_physmem_free(vlib_main_t *vm, void *p)
Definition: physmem_funcs.h:89
#define VIRTIO_RING_FLAG_MASK_INT
Definition: virtio.h:57
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
#define VIRTIO_NET_CTRL_MQ
Definition: pci.h:61
#define clib_warning(format, args...)
Definition: error.h:59
#define VIRTIO_NET_ERR
Definition: pci.h:58
static u16 virtio_pci_is_link_up(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:96
void vlib_log(vlib_log_level_t level, vlib_log_class_t class, char *fmt,...)
Definition: log.c:87
static_always_inline void vring_init(vring_t *vr, u32 num, void *p, u32 align)
Definition: virtio_std.h:181
u8 mac_addr[6]
Definition: virtio.h:146
u32 flags
Definition: virtio.h:108
clib_error_t * virtio_pci_control_vring_init(vlib_main_t *vm, virtio_if_t *vif, u16 queue_num)
Definition: pci.c:443
clib_error_t * error
Definition: virtio.h:138
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:264
int virtio_pci_delete_if(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:1210
u32 numa_node
Definition: virtio.h:134
virtio_if_type_t type
Definition: virtio.h:126
void virtio_free_used_desc(vlib_main_t *vm, virtio_vring_t *vring)
Definition: virtio.c:174
#define PCI_DEVICE_ID_VIRTIO_NIC_MODERN
Definition: pci.c:31
#define ASSERT(truth)
static int virtio_pci_offloads(vlib_main_t *vm, virtio_if_t *vif, int gso_enabled, int csum_offload_enabled)
Definition: pci.c:355
void vnet_hw_interface_assign_rx_thread(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id, uword thread_index)
Definition: devices.c:139
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
u64 remote_features
Definition: virtio.h:135
clib_error_t * virtio_pci_read_caps(vlib_main_t *vm, virtio_if_t *vif, void **bar)
Definition: pci.c:668
static int virtio_pci_send_ctrl_msg(vlib_main_t *vm, virtio_if_t *vif, virtio_ctrl_msg_t *data, u32 len)
Definition: pci.c:198
static int virtio_pci_enable_checksum_offload(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:313
const virtio_pci_func_t virtio_pci_modern_func
u8 data[1024]
Definition: pci.h:171
clib_error_t * vlib_pci_register_intx_handler(vlib_main_t *vm, vlib_pci_dev_handle_t h, pci_intx_handler_function_t *intx_handler)
Definition: pci.c:786
#define VRING_DESC_F_NEXT
Definition: virtio_std.h:73
virtio_net_ctrl_ack_t status
Definition: pci.h:170
virtio_main_t virtio_main
Definition: virtio.c:35
u16 notify_offset
Definition: virtio.h:175
static uword is_pow2(uword x)
Definition: clib.h:252
u16 ring[0]
Definition: virtio_std.h:99
Definition: defs.h:64
#define RX_QUEUE_ACCESS(X)
Definition: virtio.h:39
int csum_offload_enabled
Definition: virtio.h:115
#define VIRTIO_PCI_CAP_DEVICE_CFG
Definition: pci.h:84
#define PCI_CAP_ID_VNDR
Definition: pci.c:34
clib_error_t * ethernet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, const u8 *address, u32 *hw_if_index_return, ethernet_flag_change_function_t flag_change)
Definition: interface.c:331
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags)
Definition: interface.c:498
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
static void virtio_pci_irq_config_handler(vlib_main_t *vm, vlib_pci_dev_handle_t h, u16 line)
Definition: pci.c:122
#define clib_error_free(e)
Definition: error.h:86
#define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET
Definition: pci.h:62
clib_error_t * vlib_pci_io_region(vlib_main_t *vm, vlib_pci_dev_handle_t h, u32 resource)
Definition: pci.c:1182
clib_error_t * vlib_pci_map_region(vlib_main_t *vm, vlib_pci_dev_handle_t h, u32 resource, void **result)
Definition: pci.c:1168
u32 * buffers
Definition: virtio.h:82
int vnet_hw_interface_unassign_rx_thread(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id)
Definition: devices.c:188
u8 virtio_net_ctrl_ack_t
Definition: pci.h:165
virtio_vring_t * cxq_vring
Definition: virtio.h:169
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:132
int vnet_hw_interface_set_rx_mode(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id, vnet_hw_interface_rx_mode mode)
Definition: devices.c:253
#define VIRTIO_PCI_CAP_PCI_CFG
Definition: pci.h:86
u16 max_queue_pairs
Definition: virtio.h:178
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
#define PCI_VENDOR_ID_VIRTIO
Definition: pci.c:28
#define PCI_CAP_ID_MSIX
Definition: pci.c:35
#define VRING_DESC_F_WRITE
Definition: virtio_std.h:74
clib_error_t * vlib_pci_device_open(vlib_main_t *vm, vlib_pci_addr_t *addr, pci_device_id_t ids[], vlib_pci_dev_handle_t *handle)
Definition: pci.c:1237
#define RX_QUEUE(X)
Definition: virtio.h:37
static u32 virtio_pci_get_mac(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:85
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
static void vnet_hw_interface_set_input_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: devices.h:79
u16 vendor_id
Definition: pci.h:127
u16 common_offset
Definition: virtio.h:174
static int virtio_pci_enable_multiqueue(vlib_main_t *vm, virtio_if_t *vif, u16 num_queues)
Definition: pci.c:416
u16 desc_in_use
Definition: virtio.h:66
virtio_vring_t * txq_vrings
Definition: virtio.h:113
static_always_inline void virtio_kick(vlib_main_t *vm, virtio_vring_t *vring, virtio_if_t *vif)
Definition: virtio.h:223
u16 queue_notify_offset
Definition: virtio.h:75
static_always_inline void clib_memset_u32(void *p, u32 val, uword count)
Definition: string.h:332