FD.io VPP  v21.01.1
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 
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;
207  u16 sz = vring->size;
208  u16 flags = 0, first_desc_flags = 0;
209 
210  used = vring->desc_in_use;
211  next = vring->desc_next;
212  vring_packed_desc_t *d = &vring->packed_desc[next];
213 
214  if (vlib_buffer_alloc (vm, &buffer_index, 1))
215  b = vlib_get_buffer (vm, buffer_index);
216  else
217  return VIRTIO_NET_ERR;
218  /*
219  * current_data may not be initialized with 0 and may contain
220  * previous offset.
221  */
222  b->current_data = 0;
224 
225  first_desc_flags = VRING_DESC_F_NEXT;
226  if (vring->avail_wrap_counter)
227  {
228  first_desc_flags |= VRING_DESC_F_AVAIL;
229  first_desc_flags &= ~VRING_DESC_F_USED;
230  }
231  else
232  {
233  first_desc_flags &= ~VRING_DESC_F_AVAIL;
234  first_desc_flags |= VRING_DESC_F_USED;
235  }
236  d->addr = vlib_buffer_get_current_pa (vm, b);
237  d->len = sizeof (virtio_net_ctrl_hdr_t);
238  d->id = next;
239 
240  next++;
241  if (next >= sz)
242  {
243  next = 0;
244  vring->avail_wrap_counter ^= 1;
245  }
246  used++;
247 
248  d = &vring->packed_desc[next];
249  flags = VRING_DESC_F_NEXT;
250  if (vring->avail_wrap_counter)
251  {
252  flags |= VRING_DESC_F_AVAIL;
253  flags &= ~VRING_DESC_F_USED;
254  }
255  else
256  {
257  flags &= ~VRING_DESC_F_AVAIL;
258  flags |= VRING_DESC_F_USED;
259  }
260  d->addr = vlib_buffer_get_current_pa (vm, b) +
262  d->len = len;
263  d->id = next;
264  d->flags = flags;
265 
266  next++;
267  if (next >= sz)
268  {
269  next = 0;
270  vring->avail_wrap_counter ^= 1;
271  }
272  used++;
273 
274  d = &vring->packed_desc[next];
275  flags = VRING_DESC_F_WRITE;
276  if (vring->avail_wrap_counter)
277  {
278  flags |= VRING_DESC_F_AVAIL;
279  flags &= ~VRING_DESC_F_USED;
280  }
281  else
282  {
283  flags &= ~VRING_DESC_F_AVAIL;
284  flags |= VRING_DESC_F_USED;
285  }
286  d->addr = vlib_buffer_get_current_pa (vm, b) +
288  d->len = sizeof (data->status);
289  d->id = next;
290  d->flags = flags;
291 
292  next++;
293  if (next >= sz)
294  {
295  next = 0;
296  vring->avail_wrap_counter ^= 1;
297  }
298  used++;
299 
301  vring->packed_desc[vring->desc_next].flags = first_desc_flags;
302  vring->desc_next = next;
303  vring->desc_in_use = used;
305  if (vring->device_event->flags != VRING_EVENT_F_DISABLE)
306  {
307  virtio_kick (vm, vring, vif);
308  }
309 
310  u16 last = vring->last_used_idx;
311  d = &vring->packed_desc[last];
312  do
313  {
314  flags = d->flags;
315  }
316  while ((flags & VRING_DESC_F_AVAIL) != (vring->used_wrap_counter << 7)
317  || (flags & VRING_DESC_F_USED) != (vring->used_wrap_counter << 15));
318 
319  last += 3;
320  if (last >= vring->size)
321  {
322  last = last - vring->size;
323  vring->used_wrap_counter ^= 1;
324  }
325  vring->desc_in_use -= 3;
326  vring->last_used_idx = last;
327 
329  clib_memcpy (&result, vlib_buffer_get_current (b),
330  sizeof (virtio_ctrl_msg_t));
331  virtio_log_debug (vif, "ctrl-queue: status %u", result.status);
332  status = result.status;
333  vlib_buffer_free (vm, &buffer_index, 1);
334  return status;
335 }
336 
337 static int
340 {
341  virtio_vring_t *vring = vif->cxq_vring;
343  virtio_ctrl_msg_t result;
344  u32 buffer_index;
345  vlib_buffer_t *b;
346  u16 used, next, avail;
347  u16 sz = vring->size;
348  u16 mask = sz - 1;
349 
350  used = vring->desc_in_use;
351  next = vring->desc_next;
352  avail = vring->avail->idx;
353  vring_desc_t *d = &vring->desc[next];
354 
355  if (vlib_buffer_alloc (vm, &buffer_index, 1))
356  b = vlib_get_buffer (vm, buffer_index);
357  else
358  return VIRTIO_NET_ERR;
359  /*
360  * current_data may not be initialized with 0 and may contain
361  * previous offset.
362  */
363  b->current_data = 0;
366  d->addr = vlib_buffer_get_current_pa (vm, b);
367  d->len = sizeof (virtio_net_ctrl_hdr_t);
368  vring->avail->ring[avail & mask] = next;
369  avail++;
370  next = (next + 1) & mask;
371  d->next = next;
372  used++;
373 
374  d = &vring->desc[next];
376  d->addr = vlib_buffer_get_current_pa (vm, b) +
378  d->len = len;
379  next = (next + 1) & mask;
380  d->next = next;
381  used++;
382 
383  d = &vring->desc[next];
385  d->addr = vlib_buffer_get_current_pa (vm, b) +
387  d->len = sizeof (data->status);
388  next = (next + 1) & mask;
389  used++;
390 
392  vring->avail->idx = avail;
393  vring->desc_next = next;
394  vring->desc_in_use = used;
395 
396  if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0)
397  {
398  virtio_kick (vm, vring, vif);
399  }
400 
401  u16 last = vring->last_used_idx, n_left = 0;
402  n_left = vring->used->idx - last;
403 
404  while (n_left)
405  {
406  vring_used_elem_t *e = &vring->used->ring[last & mask];
407  u16 slot = e->id;
408 
409  d = &vring->desc[slot];
410  while (d->flags & VRING_DESC_F_NEXT)
411  {
412  used--;
413  slot = d->next;
414  d = &vring->desc[slot];
415  }
416  used--;
417  last++;
418  n_left--;
419  }
420  vring->desc_in_use = used;
421  vring->last_used_idx = last;
422 
424  clib_memcpy (&result, vlib_buffer_get_current (b),
425  sizeof (virtio_ctrl_msg_t));
426  virtio_log_debug (vif, "ctrl-queue: status %u", result.status);
427  status = result.status;
428  vlib_buffer_free (vm, &buffer_index, 1);
429  return status;
430 }
431 
432 static int
435 {
436  if (vif->is_packed)
437  return virtio_pci_send_ctrl_msg_packed (vm, vif, data, len);
438  else
439  return virtio_pci_send_ctrl_msg_split (vm, vif, data, len);
440 }
441 
442 static int
444 {
445  virtio_ctrl_msg_t offload_hdr;
447 
448  offload_hdr.ctrl.class = VIRTIO_NET_CTRL_GUEST_OFFLOADS;
449  offload_hdr.ctrl.cmd = VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET;
450  offload_hdr.status = VIRTIO_NET_ERR;
451  u64 offloads = 0ULL;
452  clib_memcpy (offload_hdr.data, &offloads, sizeof (offloads));
453 
454  status =
455  virtio_pci_send_ctrl_msg (vm, vif, &offload_hdr, sizeof (offloads));
456  virtio_log_debug (vif, "disable offloads");
457  vif->remote_features = vif->virtio_pci_func->get_device_features (vm, vif);
458  vif->virtio_pci_func->get_driver_features (vm, vif);
459  return status;
460 }
461 
462 static int
464 {
465  virtio_ctrl_msg_t csum_offload_hdr;
467 
468  csum_offload_hdr.ctrl.class = VIRTIO_NET_CTRL_GUEST_OFFLOADS;
469  csum_offload_hdr.ctrl.cmd = VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET;
470  csum_offload_hdr.status = VIRTIO_NET_ERR;
471  u64 offloads = 0ULL;
472  offloads |= VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_CSUM);
473  clib_memcpy (csum_offload_hdr.data, &offloads, sizeof (offloads));
474 
475  status =
476  virtio_pci_send_ctrl_msg (vm, vif, &csum_offload_hdr, sizeof (offloads));
477  virtio_log_debug (vif, "enable checksum offload");
478  vif->remote_features = vif->virtio_pci_func->get_device_features (vm, vif);
479  vif->features = vif->virtio_pci_func->get_driver_features (vm, vif);
480  return status;
481 }
482 
483 static int
485 {
486  virtio_ctrl_msg_t gso_hdr;
488 
489  gso_hdr.ctrl.class = VIRTIO_NET_CTRL_GUEST_OFFLOADS;
491  gso_hdr.status = VIRTIO_NET_ERR;
492  u64 offloads = VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_CSUM)
493  | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO4)
494  | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO6);
495  clib_memcpy (gso_hdr.data, &offloads, sizeof (offloads));
496 
497  status = virtio_pci_send_ctrl_msg (vm, vif, &gso_hdr, sizeof (offloads));
498  virtio_log_debug (vif, "enable gso");
499  vif->remote_features = vif->virtio_pci_func->get_device_features (vm, vif);
500  vif->virtio_pci_func->get_driver_features (vm, vif);
501  return status;
502 }
503 
504 static int
505 virtio_pci_offloads (vlib_main_t * vm, virtio_if_t * vif, int gso_enabled,
506  int csum_offload_enabled)
507 {
508  vnet_main_t *vnm = vnet_get_main ();
510 
511  if ((vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ)) &&
512  (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)))
513  {
514  if (gso_enabled
515  && (vif->features & (VIRTIO_FEATURE (VIRTIO_NET_F_HOST_TSO4) |
516  VIRTIO_FEATURE (VIRTIO_NET_F_HOST_TSO6))))
517  {
518  if (virtio_pci_enable_gso (vm, vif))
519  {
520  virtio_log_warning (vif, "gso is not enabled");
521  }
522  else
523  {
524  vif->gso_enabled = 1;
525  vif->csum_offload_enabled = 0;
528  }
529  }
530  else if (csum_offload_enabled
531  && (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CSUM)))
532  {
534  {
535  virtio_log_warning (vif, "checksum offload is not enabled");
536  }
537  else
538  {
539  vif->csum_offload_enabled = 1;
540  vif->gso_enabled = 0;
542  hw->flags |=
544  }
545  }
546  else
547  {
548  if (virtio_pci_disable_offload (vm, vif))
549  {
550  virtio_log_warning (vif, "offloads are not disabled");
551  }
552  else
553  {
554  vif->csum_offload_enabled = 0;
555  vif->gso_enabled = 0;
558  }
559  }
560  }
561 
562  return 0;
563 }
564 
565 static int
567  u16 num_queues)
568 {
569  virtio_ctrl_msg_t mq_hdr;
571 
572  mq_hdr.ctrl.class = VIRTIO_NET_CTRL_MQ;
574  mq_hdr.status = VIRTIO_NET_ERR;
575  clib_memcpy (mq_hdr.data, &num_queues, sizeof (num_queues));
576 
577  status = virtio_pci_send_ctrl_msg (vm, vif, &mq_hdr, sizeof (num_queues));
578  virtio_log_debug (vif, "multi-queue enable %u queues", num_queues);
579  return status;
580 }
581 
582 static u8
584 {
585  if (qsz < 64 || qsz > 4096)
586  return 0;
587  if ((qsz % 64) != 0)
588  return 0;
589  return 1;
590 }
591 
592 clib_error_t *
594  u16 queue_num)
595 {
596  clib_error_t *error = 0;
597  u16 queue_size = 0;
598  virtio_vring_t *vring;
599  u32 i = 0;
600  void *ptr = NULL;
601 
602  queue_size = vif->virtio_pci_func->get_queue_size (vm, vif, queue_num);
603 
604  if (queue_size > 32768)
605  return clib_error_return (0, "ring size must be 32768 or lower");
606 
607  if (queue_size == 0)
608  queue_size = 256;
609 
611  vring = vec_elt_at_index (vif->cxq_vring, 0);
612 
613  i =
614  (((queue_size * sizeof (vring_packed_desc_t)) +
615  sizeof (vring_desc_event_t) + VIRTIO_PCI_VRING_ALIGN -
616  1) & ~(VIRTIO_PCI_VRING_ALIGN - 1)) + sizeof (vring_desc_event_t);
617 
618  ptr =
620  vif->numa_node);
621  if (!ptr)
622  return vlib_physmem_last_error (vm);
623  clib_memset (ptr, 0, i);
624 
625  vring->packed_desc = ptr;
626 
627  vring->driver_event = ptr + (queue_size * sizeof (vring_packed_desc_t));
628  vring->driver_event->off_wrap = 0;
629  vring->driver_event->flags = VRING_EVENT_F_DISABLE;
630 
631  vring->device_event =
632  ptr +
633  (((queue_size * sizeof (vring_packed_desc_t)) +
634  sizeof (vring_desc_event_t) + VIRTIO_PCI_VRING_ALIGN -
635  1) & ~(VIRTIO_PCI_VRING_ALIGN - 1));
636  vring->device_event->off_wrap = 0;
637  vring->device_event->flags = 0;
638 
639  vring->queue_id = queue_num;
640  vring->size = queue_size;
641  vring->avail_wrap_counter = 1;
642  vring->used_wrap_counter = 1;
643 
644  ASSERT (vring->buffers == 0);
645 
646  virtio_log_debug (vif, "control-queue: number %u, size %u", queue_num,
647  queue_size);
648  vif->virtio_pci_func->setup_queue (vm, vif, queue_num, (void *) vring);
649  vring->queue_notify_offset =
650  vif->notify_off_multiplier *
651  vif->virtio_pci_func->get_queue_notify_off (vm, vif, queue_num);
652  virtio_log_debug (vif, "queue-notify-offset: number %u, offset %u",
653  queue_num, vring->queue_notify_offset);
654  return error;
655 }
656 
657 clib_error_t *
659  u16 queue_num)
660 {
661  clib_error_t *error = 0;
662  u16 queue_size = 0;
663  virtio_vring_t *vring;
664  vring_t vr;
665  u32 i = 0;
666  void *ptr = NULL;
667 
668  queue_size = vif->virtio_pci_func->get_queue_size (vm, vif, queue_num);
669  if (!virtio_pci_queue_size_valid (queue_size))
670  clib_warning ("queue size is not valid");
671 
672  if (!is_pow2 (queue_size))
673  return clib_error_return (0, "ring size must be power of 2");
674 
675  if (queue_size > 32768)
676  return clib_error_return (0, "ring size must be 32768 or lower");
677 
678  if (queue_size == 0)
679  queue_size = 256;
680 
682  vring = vec_elt_at_index (vif->cxq_vring, 0);
683  i = vring_size (queue_size, VIRTIO_PCI_VRING_ALIGN);
685  ptr =
687  vif->numa_node);
688  if (!ptr)
689  return vlib_physmem_last_error (vm);
690  clib_memset (ptr, 0, i);
691  vring_init (&vr, queue_size, ptr, VIRTIO_PCI_VRING_ALIGN);
692  vring->desc = vr.desc;
693  vring->avail = vr.avail;
694  vring->used = vr.used;
695  vring->queue_id = queue_num;
697 
698  ASSERT (vring->buffers == 0);
699 
700  vring->size = queue_size;
701  virtio_log_debug (vif, "control-queue: number %u, size %u", queue_num,
702  queue_size);
703  vif->virtio_pci_func->setup_queue (vm, vif, queue_num, ptr);
704  vring->queue_notify_offset =
705  vif->notify_off_multiplier *
706  vif->virtio_pci_func->get_queue_notify_off (vm, vif, queue_num);
707  virtio_log_debug (vif, "queue-notify-offset: number %u, offset %u",
708  queue_num, vring->queue_notify_offset);
709 
710  return error;
711 }
712 
713 clib_error_t *
715  u16 queue_num)
716 {
717  if (vif->is_packed)
718  return virtio_pci_control_vring_packed_init (vm, vif, queue_num);
719  else
720  return virtio_pci_control_vring_split_init (vm, vif, queue_num);
721 }
722 
723 clib_error_t *
725  u16 queue_num)
726 {
728  clib_error_t *error = 0;
729  u16 queue_size = 0;
730  virtio_vring_t *vring;
731  vring_t vr;
732  u32 i = 0;
733  void *ptr = NULL;
734 
735  queue_size = vif->virtio_pci_func->get_queue_size (vm, vif, queue_num);
736  if (!virtio_pci_queue_size_valid (queue_size))
737  clib_warning ("queue size is not valid");
738 
739  if (!is_pow2 (queue_size))
740  return clib_error_return (0, "ring size must be power of 2");
741 
742  if (queue_size > 32768)
743  return clib_error_return (0, "ring size must be 32768 or lower");
744 
745  if (queue_size == 0)
746  queue_size = 256;
747 
748  if (queue_num % 2)
749  {
752  vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS (queue_num));
753  if (vif->max_queue_pairs < vtm->n_vlib_mains)
754  clib_spinlock_init (&vring->lockp);
755  }
756  else
757  {
760  vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS (queue_num));
761  }
762  i = vring_size (queue_size, VIRTIO_PCI_VRING_ALIGN);
764  ptr =
766  vif->numa_node);
767  if (!ptr)
768  return vlib_physmem_last_error (vm);
769  clib_memset (ptr, 0, i);
770  vring_init (&vr, queue_size, ptr, VIRTIO_PCI_VRING_ALIGN);
771  vring->desc = vr.desc;
772  vring->avail = vr.avail;
773  vring->used = vr.used;
774  vring->queue_id = queue_num;
776  vring->flow_table = 0;
777 
778  ASSERT (vring->buffers == 0);
779  vec_validate_aligned (vring->buffers, queue_size, CLIB_CACHE_LINE_BYTES);
780  if (queue_num % 2)
781  {
782  virtio_log_debug (vif, "tx-queue: number %u, size %u", queue_num,
783  queue_size);
784  clib_memset_u32 (vring->buffers, ~0, queue_size);
785  }
786  else
787  {
788  virtio_log_debug (vif, "rx-queue: number %u, size %u", queue_num,
789  queue_size);
790  }
791  vring->size = queue_size;
792  if (vif->virtio_pci_func->setup_queue (vm, vif, queue_num, ptr))
793  return clib_error_return (0, "error in queue address setup");
794 
795  vring->queue_notify_offset =
796  vif->notify_off_multiplier *
797  vif->virtio_pci_func->get_queue_notify_off (vm, vif, queue_num);
798  virtio_log_debug (vif, "queue-notify-offset: number %u, offset %u",
799  queue_num, vring->queue_notify_offset);
800  return error;
801 }
802 
803 clib_error_t *
805  u16 queue_num)
806 {
808  clib_error_t *error = 0;
809  u16 queue_size = 0;
810  virtio_vring_t *vring;
811  u32 i = 0;
812  void *ptr = NULL;
813 
814  queue_size = vif->virtio_pci_func->get_queue_size (vm, vif, queue_num);
815 
816  if (queue_size > 32768)
817  return clib_error_return (0, "ring size must be 32768 or lower");
818 
819  if (queue_size == 0)
820  queue_size = 256;
821 
822  if (queue_num % 2)
823  {
826  vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS (queue_num));
827  if (vif->max_queue_pairs < vtm->n_vlib_mains)
828  clib_spinlock_init (&vring->lockp);
829  }
830  else
831  {
834  vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS (queue_num));
835  }
836 
837  i =
838  (((queue_size * sizeof (vring_packed_desc_t)) +
839  sizeof (vring_desc_event_t) + VIRTIO_PCI_VRING_ALIGN -
840  1) & ~(VIRTIO_PCI_VRING_ALIGN - 1)) + sizeof (vring_desc_event_t);
841 
842  ptr =
844  vif->numa_node);
845  if (!ptr)
846  return vlib_physmem_last_error (vm);
847 
848  clib_memset (ptr, 0, i);
849  vring->packed_desc = ptr;
850 
851  vring->driver_event = ptr + (queue_size * sizeof (vring_packed_desc_t));
852  vring->driver_event->off_wrap = 0;
853  vring->driver_event->flags = VRING_EVENT_F_DISABLE;
854 
855  vring->device_event =
856  ptr +
857  (((queue_size * sizeof (vring_packed_desc_t)) +
858  sizeof (vring_desc_event_t) + VIRTIO_PCI_VRING_ALIGN -
859  1) & ~(VIRTIO_PCI_VRING_ALIGN - 1));
860  vring->device_event->off_wrap = 0;
861  vring->device_event->flags = 0;
862 
863  vring->queue_id = queue_num;
864 
865  vring->avail_wrap_counter = 1;
866  vring->used_wrap_counter = 1;
867 
868  ASSERT (vring->buffers == 0);
869  vec_validate_aligned (vring->buffers, queue_size, CLIB_CACHE_LINE_BYTES);
870  if (queue_num % 2)
871  {
872  virtio_log_debug (vif, "tx-queue: number %u, size %u", queue_num,
873  queue_size);
874  clib_memset_u32 (vring->buffers, ~0, queue_size);
875  }
876  else
877  {
878  virtio_log_debug (vif, "rx-queue: number %u, size %u", queue_num,
879  queue_size);
880  }
881  vring->size = queue_size;
882  if (vif->virtio_pci_func->setup_queue (vm, vif, queue_num, (void *) vring))
883  return clib_error_return (0, "error in queue address setup");
884 
885  vring->queue_notify_offset =
886  vif->notify_off_multiplier *
887  vif->virtio_pci_func->get_queue_notify_off (vm, vif, queue_num);
888  virtio_log_debug (vif, "queue-notify-offset: number %u, offset %u",
889  queue_num, vring->queue_notify_offset);
890 
891  return error;
892 }
893 
894 clib_error_t *
896 {
897  if (vif->is_packed)
898  return virtio_pci_vring_packed_init (vm, vif, queue_num);
899  else
900  return virtio_pci_vring_split_init (vm, vif, queue_num);
901 }
902 
903 static void
905  u64 req_features)
906 {
907  /*
908  * if features are not requested
909  * default: all supported features
910  */
911  u64 supported_features = VIRTIO_FEATURE (VIRTIO_NET_F_CSUM)
912  | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_CSUM)
913  | VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)
914  | VIRTIO_FEATURE (VIRTIO_NET_F_MTU)
915  | VIRTIO_FEATURE (VIRTIO_NET_F_MAC)
916  | VIRTIO_FEATURE (VIRTIO_NET_F_GSO)
917  | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO4)
918  | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO6)
919  | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_UFO)
920  | VIRTIO_FEATURE (VIRTIO_NET_F_HOST_TSO4)
921  | VIRTIO_FEATURE (VIRTIO_NET_F_HOST_TSO6)
922  | VIRTIO_FEATURE (VIRTIO_NET_F_HOST_UFO)
923  | VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF)
924  | VIRTIO_FEATURE (VIRTIO_NET_F_STATUS)
925  | VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ)
926  | VIRTIO_FEATURE (VIRTIO_NET_F_MQ)
927  | VIRTIO_FEATURE (VIRTIO_F_NOTIFY_ON_EMPTY)
928  | VIRTIO_FEATURE (VIRTIO_F_ANY_LAYOUT)
929  | VIRTIO_FEATURE (VIRTIO_RING_F_INDIRECT_DESC);
930 
931  if (vif->is_modern)
932  supported_features |= VIRTIO_FEATURE (VIRTIO_F_VERSION_1);
933 
934  if (vif->is_packed)
935  {
936  supported_features |=
937  (VIRTIO_FEATURE (VIRTIO_F_RING_PACKED) |
938  VIRTIO_FEATURE (VIRTIO_F_IN_ORDER));
939  }
940 
941  if (req_features == 0)
942  {
943  req_features = supported_features;
944  }
945 
946  vif->features = req_features & vif->remote_features & supported_features;
947 
948  if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MTU))
949  {
950  u16 mtu = 0;
951  mtu = vif->virtio_pci_func->get_mtu (vm, vif);
952 
953  if (mtu < 64)
954  vif->features &= ~VIRTIO_FEATURE (VIRTIO_NET_F_MTU);
955  }
956 
957  if ((vif->features & (VIRTIO_FEATURE (VIRTIO_F_RING_PACKED))) == 0)
958  vif->is_packed = 0;
959 
960  vif->virtio_pci_func->set_driver_features (vm, vif, vif->features);
961  vif->features = vif->virtio_pci_func->get_driver_features (vm, vif);
962 }
963 
964 void
966 {
967  vif->remote_features = vif->virtio_pci_func->get_device_features (vm, vif);
968 }
969 
970 int
972 {
973  u8 status = 0;
974 
975  /*
976  * Reset the device
977  */
978  status = vif->virtio_pci_func->device_reset (vm, vif);
979 
980  /*
981  * Set the Acknowledge status bit
982  */
983  vif->virtio_pci_func->set_status (vm, vif, VIRTIO_CONFIG_STATUS_ACK);
984 
985  /*
986  * Set the Driver status bit
987  */
988  vif->virtio_pci_func->set_status (vm, vif, VIRTIO_CONFIG_STATUS_DRIVER);
989 
990  /*
991  * Read the status and verify it
992  */
993  status = vif->virtio_pci_func->get_status (vm, vif);
994  if ((status & VIRTIO_CONFIG_STATUS_ACK)
995  && (status & VIRTIO_CONFIG_STATUS_DRIVER))
996  vif->status = status;
997  else
998  return -1;
999 
1000  return 0;
1001 }
1002 
1003 clib_error_t *
1005 {
1006  clib_error_t *error = 0;
1007  virtio_pci_cap_t cap;
1008  u8 pos, common_cfg = 0, notify = 0, dev_cfg = 0, isr = 0, pci_cfg = 0;
1010 
1011  if ((error = vlib_pci_read_config_u8 (vm, h, PCI_CAPABILITY_LIST, &pos)))
1012  {
1013  virtio_log_error (vif, "error in reading capabilty list position");
1014  return clib_error_return (error,
1015  "error in reading capabilty list position");
1016  }
1017  while (pos)
1018  {
1019  if ((error =
1020  vlib_pci_read_write_config (vm, h, VLIB_READ, pos, &cap,
1021  sizeof (cap))))
1022  {
1023  virtio_log_error (vif, "%s [%2x]",
1024  "error in reading the capability at", pos);
1025  return clib_error_return (error,
1026  "error in reading the capability at [%2x]",
1027  pos);
1028  }
1029 
1030  if (cap.cap_vndr == PCI_CAP_ID_MSIX)
1031  {
1032  u16 flags, table_size, table_size_mask = 0x07FF;
1033 
1034  if ((error =
1035  vlib_pci_read_write_config (vm, h, VLIB_READ, pos + 2, &flags,
1036  sizeof (flags))))
1037  return clib_error_return (error,
1038  "error in reading the capability at [%2x]",
1039  pos + 2);
1040 
1041  table_size = flags & table_size_mask;
1042  virtio_log_debug (vif, "flags:0x%x %s 0x%x", flags,
1043  "msix interrupt vector table-size", table_size);
1044 
1045  if (flags & PCI_MSIX_ENABLE)
1046  {
1047  virtio_log_debug (vif, "msix interrupt enabled");
1049  vif->msix_table_size = table_size;
1050  }
1051  else
1052  {
1053  virtio_log_debug (vif, "msix interrupt disabled");
1055  vif->msix_table_size = 0;
1056  }
1057  }
1058 
1059  if (cap.cap_vndr != PCI_CAP_ID_VNDR)
1060  {
1061  virtio_log_debug (vif, "[%2x] %s %2x ", pos,
1062  "skipping non VNDR cap id:", cap.cap_vndr);
1063  goto next;
1064  }
1065 
1066  virtio_log_debug (vif,
1067  "[%4x] cfg type: %u, bar: %u, offset: %04x, len: %u",
1068  pos, cap.cfg_type, cap.bar, cap.offset, cap.length);
1069 
1070  if (cap.bar >= 0 && cap.bar <= 5)
1071  {
1072  vif->bar = bar[cap.bar];
1073  vif->bar_id = cap.bar;
1074  }
1075  else
1076  return clib_error_return (error, "invalid bar %u", cap.bar);
1077 
1078  switch (cap.cfg_type)
1079  {
1081  vif->common_offset = cap.offset;
1082  common_cfg = 1;
1083  break;
1085  if ((error =
1087  pos + sizeof (cap),
1088  &vif->notify_off_multiplier,
1089  sizeof
1090  (vif->notify_off_multiplier))))
1091  {
1092  virtio_log_error (vif, "notify off multiplier is not given");
1093  }
1094  else
1095  {
1096  virtio_log_debug (vif, "notify off multiplier is %u",
1097  vif->notify_off_multiplier);
1098  vif->notify_offset = cap.offset;
1099  notify = 1;
1100  }
1101  break;
1103  vif->device_offset = cap.offset;
1104  dev_cfg = 1;
1105  break;
1107  vif->isr_offset = cap.offset;
1108  isr = 1;
1109  break;
1111  if (cap.bar == 0)
1112  pci_cfg = 1;
1113  break;
1114  }
1115  next:
1116  pos = cap.cap_next;
1117  }
1118 
1119  if (common_cfg == 0 || notify == 0 || dev_cfg == 0 || isr == 0)
1120  {
1122  vif->notify_off_multiplier = 0;
1123  virtio_log_debug (vif, "legacy virtio pci device found");
1124  return error;
1125  }
1126 
1127  vif->is_modern = 1;
1129 
1130  if (!pci_cfg)
1131  {
1132  virtio_log_debug (vif, "modern virtio pci device found");
1133  }
1134  else
1135  {
1136  virtio_log_debug (vif, "transitional virtio pci device found");
1137  }
1138 
1139  return error;
1140 }
1141 
1142 static clib_error_t *
1144  virtio_pci_create_if_args_t * args, void **bar)
1145 {
1146  clib_error_t *error = 0;
1148  u8 status = 0;
1149 
1150  if ((error = virtio_pci_read_caps (vm, vif, bar)))
1151  {
1152  args->rv = VNET_API_ERROR_UNSUPPORTED;
1153  virtio_log_error (vif, "Device is not supported");
1154  return clib_error_return (error, "Device is not supported");
1155  }
1156 
1157  if (virtio_pci_reset_device (vm, vif) < 0)
1158  {
1159  args->rv = VNET_API_ERROR_INIT_FAILED;
1160  virtio_log_error (vif, "Failed to reset the device");
1161  return clib_error_return (error, "Failed to reset the device");
1162  }
1163  /*
1164  * read device features and negotiate (user) requested features
1165  */
1167  if ((vif->remote_features & VIRTIO_FEATURE (VIRTIO_RING_F_INDIRECT_DESC)) ==
1168  0)
1169  {
1170  virtio_log_warning (vif, "error encountered: vhost-net backend doesn't "
1171  "support VIRTIO_RING_F_INDIRECT_DESC features");
1172  }
1173  if ((vif->remote_features & VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF)) == 0)
1174  {
1175  virtio_log_warning (vif, "error encountered: vhost-net backend doesn't "
1176  "support VIRTIO_NET_F_MRG_RXBUF features");
1177  }
1178  virtio_negotiate_features (vm, vif, args->features);
1179 
1180  /*
1181  * After FEATURE_OK, driver should not accept new feature bits
1182  */
1183  vif->virtio_pci_func->set_status (vm, vif,
1184  VIRTIO_CONFIG_STATUS_FEATURES_OK);
1185  status = vif->virtio_pci_func->get_status (vm, vif);
1186  if (!(status & VIRTIO_CONFIG_STATUS_FEATURES_OK))
1187  {
1188  args->rv = VNET_API_ERROR_UNSUPPORTED;
1189  virtio_log_error (vif,
1190  "error encountered: Device doesn't support requested features");
1191  return clib_error_return (error,
1192  "Device doesn't support requested features");
1193  }
1194  vif->status = status;
1195 
1196  /*
1197  * get or set the mac address
1198  */
1199  if (virtio_pci_get_mac (vm, vif))
1200  {
1201  f64 now = vlib_time_now (vm);
1202  u32 rnd;
1203  rnd = (u32) (now * 1e6);
1204  rnd = random_u32 (&rnd);
1205 
1206  memcpy (vif->mac_addr + 2, &rnd, sizeof (rnd));
1207  vif->mac_addr[0] = 2;
1208  vif->mac_addr[1] = 0xfe;
1209  virtio_pci_set_mac (vm, vif);
1210  }
1211 
1213 
1214  /*
1215  * Initialize the virtqueues
1216  */
1217  if ((error = virtio_pci_get_max_virtqueue_pairs (vm, vif)))
1218  {
1219  args->rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
1220  goto err;
1221  }
1222 
1223  if (vif->msix_enabled == VIRTIO_MSIX_ENABLED)
1224  {
1225  if (vif->msix_table_size <= vif->max_queue_pairs)
1226  {
1227  virtio_log_error (vif,
1228  "error MSIX lines (%u) <= Number of RXQs (%u)",
1229  vif->msix_table_size, vif->max_queue_pairs);
1230  return clib_error_return (error,
1231  "error MSIX lines (%u) <= Number of RXQs (%u)",
1232  vif->msix_table_size,
1233  vif->max_queue_pairs);
1234  }
1235  }
1236 
1237  for (int i = 0; i < vif->max_queue_pairs; i++)
1238  {
1239  if ((error = virtio_pci_vring_init (vm, vif, RX_QUEUE (i))))
1240  {
1241  args->rv = VNET_API_ERROR_INIT_FAILED;
1242  virtio_log_error (vif, "%s (%u) %s", "error in rxq-queue",
1243  RX_QUEUE (i), "initialization");
1244  error =
1245  clib_error_return (error, "%s (%u) %s", "error in rxq-queue",
1246  RX_QUEUE (i), "initialization");
1247  goto err;
1248  }
1249  else
1250  {
1251  vif->num_rxqs++;
1252  }
1253 
1254  if (i >= vtm->n_vlib_mains)
1255  {
1256  /*
1257  * There is 1:1 mapping between tx queue and vpp worker thread.
1258  * tx queue 0 is bind with thread index 0, tx queue 1 on thread
1259  * index 1 and so on.
1260  * Multiple worker threads can poll same tx queue when number of
1261  * workers are more than tx queues. In this case, 1:N mapping
1262  * between tx queue and vpp worker thread.
1263  */
1264  virtio_log_debug (vif, "%s %u, %s", "tx-queue: number",
1265  TX_QUEUE (i),
1266  "no VPP worker thread is available");
1267  continue;
1268  }
1269 
1270  if ((error = virtio_pci_vring_init (vm, vif, TX_QUEUE (i))))
1271  {
1272  args->rv = VNET_API_ERROR_INIT_FAILED;
1273  virtio_log_error (vif, "%s (%u) %s", "error in txq-queue",
1274  TX_QUEUE (i), "initialization");
1275  error =
1276  clib_error_return (error, "%s (%u) %s", "error in txq-queue",
1277  TX_QUEUE (i), "initialization");
1278  goto err;
1279  }
1280  else
1281  {
1282  vif->num_txqs++;
1283  }
1284  }
1285 
1286  if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
1287  {
1288  if ((error =
1289  virtio_pci_control_vring_init (vm, vif, vif->max_queue_pairs * 2)))
1290  {
1291  virtio_log_warning (vif, "%s (%u) %s", "error in control-queue",
1292  vif->max_queue_pairs * 2, "initialization");
1293  if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MQ))
1294  vif->features &= ~VIRTIO_FEATURE (VIRTIO_NET_F_MQ);
1295  }
1296  }
1297  else
1298  {
1299  virtio_log_debug (vif, "control queue is not available");
1300  vif->cxq_vring = NULL;
1301  }
1302 
1303  /*
1304  * set the msix interrupts
1305  */
1306  if (vif->msix_enabled == VIRTIO_MSIX_ENABLED)
1307  {
1308  int i, j;
1309  if (vif->virtio_pci_func->set_config_irq (vm, vif, 0) ==
1311  {
1312  virtio_log_warning (vif, "config vector 0 is not set");
1313  }
1314  else
1315  {
1316  virtio_log_debug (vif, "config msix vector is set at 0");
1317  }
1318  for (i = 0, j = 1; i < vif->max_queue_pairs; i++, j++)
1319  {
1320  if (vif->virtio_pci_func->set_queue_irq (vm, vif, j,
1321  RX_QUEUE (i)) ==
1323  {
1324  virtio_log_warning (vif, "queue (%u) vector is not set at %u",
1325  RX_QUEUE (i), j);
1326  }
1327  else
1328  {
1329  virtio_log_debug (vif, "%s (%u) %s %u", "queue",
1330  RX_QUEUE (i), "msix vector is set at", j);
1331  }
1332  }
1333  }
1334 
1335  /*
1336  * set the driver status OK
1337  */
1338  vif->virtio_pci_func->set_status (vm, vif, VIRTIO_CONFIG_STATUS_DRIVER_OK);
1339  vif->status = vif->virtio_pci_func->get_status (vm, vif);
1340 err:
1341  return error;
1342 }
1343 
1344 void
1346 {
1347  vnet_main_t *vnm = vnet_get_main ();
1348  virtio_main_t *vim = &virtio_main;
1349  virtio_if_t *vif;
1351  clib_error_t *error = 0;
1352  u32 interrupt_count = 0;
1353 
1354  /* *INDENT-OFF* */
1355  pool_foreach (vif, vim->interfaces) {
1356  if (vif->pci_addr.as_u32 == args->addr)
1357  {
1358  args->rv = VNET_API_ERROR_ADDRESS_IN_USE;
1359  args->error =
1360  clib_error_return (error, "PCI address in use");
1361  vlib_log (VLIB_LOG_LEVEL_ERR, vim->log_default, "%U: %s",
1362  format_vlib_pci_addr, &args->addr,
1363  " PCI address in use");
1364  return;
1365  }
1366  }
1367  /* *INDENT-ON* */
1368 
1369  pool_get (vim->interfaces, vif);
1370  vif->dev_instance = vif - vim->interfaces;
1371  vif->per_interface_next_index = ~0;
1372  vif->pci_addr.as_u32 = args->addr;
1373  if (args->virtio_flags & VIRTIO_FLAG_PACKED)
1374  vif->is_packed = 1;
1375 
1376  if ((error =
1377  vlib_pci_device_open (vm, (vlib_pci_addr_t *) & vif->pci_addr,
1378  virtio_pci_device_ids, &h)))
1379  {
1380  args->rv = VNET_API_ERROR_INVALID_INTERFACE;
1381  args->error =
1382  clib_error_return (error, "pci-addr %U", format_vlib_pci_addr,
1383  &vif->pci_addr);
1384  vlib_log (VLIB_LOG_LEVEL_ERR, vim->log_default, "%U: %s",
1386  "error encountered on pci device open");
1387  pool_put (vim->interfaces, vif);
1388  return;
1389  }
1390  vif->pci_dev_handle = h;
1392  vif->numa_node = vlib_pci_get_numa_node (vm, h);
1393  vif->type = VIRTIO_IF_TYPE_PCI;
1394 
1395  if ((error = vlib_pci_bus_master_enable (vm, h)))
1396  {
1397  virtio_log_error (vif, "error encountered on pci bus master enable");
1398  goto error;
1399  }
1400 
1401  void *bar[6];
1402  for (u32 i = 0; i <= 5; i++)
1403  {
1404 
1405  if ((error = vlib_pci_map_region (vm, h, i, &bar[i])))
1406  {
1407  virtio_log_debug (vif, "no pci map region for bar %u", i);
1408  }
1409  else
1410  {
1411  virtio_log_debug (vif, "pci map region for bar %u at %p", i,
1412  bar[i]);
1413  }
1414  }
1415 
1416  if ((error = vlib_pci_io_region (vm, h, 0)))
1417  {
1418  virtio_log_error (vif, "error encountered on pci io region");
1419  goto error;
1420  }
1421 
1422  interrupt_count = vlib_pci_get_num_msix_interrupts (vm, h);
1423  if (interrupt_count > 1)
1424  {
1425  if ((error = vlib_pci_register_msix_handler (vm, h, 0, 1,
1427  {
1428  args->rv = VNET_API_ERROR_INVALID_REGISTRATION;
1429  virtio_log_error (vif,
1430  "error encountered on pci register msix handler 0");
1431  goto error;
1432  }
1433 
1434  if ((error =
1435  vlib_pci_register_msix_handler (vm, h, 1, (interrupt_count - 1),
1437  {
1438  args->rv = VNET_API_ERROR_INVALID_REGISTRATION;
1439  virtio_log_error (vif,
1440  "error encountered on pci register msix handler 1");
1441  goto error;
1442  }
1443 
1444  if ((error = vlib_pci_enable_msix_irq (vm, h, 0, interrupt_count)))
1445  {
1446  virtio_log_error (vif, "error encountered on pci enable msix irq");
1447  goto error;
1448  }
1449  vif->support_int_mode = 1;
1450  virtio_log_debug (vif, "device supports msix interrupts");
1451  }
1452  else if (interrupt_count == 1)
1453  {
1454  /*
1455  * if msix table-size is 1, fall back to intX.
1456  */
1457  if ((error =
1459  {
1460  virtio_log_error (vif,
1461  "error encountered on pci register interrupt handler");
1462  goto error;
1463  }
1464  vif->support_int_mode = 1;
1465  virtio_log_debug (vif, "pci register interrupt handler");
1466  }
1467  else
1468  {
1469  /*
1470  * WARN: intX is showing some weird behaviour.
1471  * Please don't use interrupt mode with UIO driver.
1472  */
1473  vif->support_int_mode = 0;
1474  virtio_log_debug (vif, "driver is configured in poll mode only");
1475  }
1476 
1477  if ((error = vlib_pci_intr_enable (vm, h)))
1478  {
1479  virtio_log_error (vif, "error encountered on pci interrupt enable");
1480  goto error;
1481  }
1482 
1483  if ((error = virtio_pci_device_init (vm, vif, args, bar)))
1484  {
1485  virtio_log_error (vif, "error encountered on device init");
1486  goto error;
1487  }
1488 
1489  /* create interface */
1491  vif->dev_instance, vif->mac_addr,
1492  &vif->hw_if_index,
1494 
1495  if (error)
1496  {
1497  args->rv = VNET_API_ERROR_INVALID_REGISTRATION;
1498  virtio_log_error (vif,
1499  "error encountered on ethernet register interface");
1500  goto error;
1501  }
1502 
1504  vif->sw_if_index = sw->sw_if_index;
1505  args->sw_if_index = sw->sw_if_index;
1506 
1509 
1510  if (args->virtio_flags & VIRTIO_FLAG_BUFFERING)
1511  {
1512  error = virtio_set_packet_buffering (vif, args->buffering_size);
1513  if (error)
1514  {
1515  args->rv = VNET_API_ERROR_INIT_FAILED;
1516  virtio_log_error (vif,
1517  "error encountered during packet buffering init");
1518  goto error;
1519  }
1520  }
1521 
1523  virtio_input_node.index);
1524  u32 i = 0;
1525  vec_foreach_index (i, vif->rxq_vrings)
1526  {
1528  virtio_vring_set_numa_node (vm, vif, RX_QUEUE (i));
1529  /* Set default rx mode to POLLING */
1532  }
1534  {
1535  vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP;
1538  }
1539  else
1541 
1542  virtio_pci_offloads (vm, vif, args->gso_enabled,
1543  args->checksum_offload_enabled);
1544 
1545  if ((vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ)) &&
1546  (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MQ)))
1547  {
1548  if (virtio_pci_enable_multiqueue (vm, vif, vif->max_queue_pairs))
1549  virtio_log_warning (vif, "multiqueue is not set");
1550  }
1551  return;
1552 
1553 error:
1554  virtio_pci_delete_if (vm, vif);
1555  if (args->rv == 0)
1556  args->rv = VNET_API_ERROR_INVALID_INTERFACE;
1557  args->error = error;
1558 }
1559 
1560 int
1562 {
1563  vnet_main_t *vnm = vnet_get_main ();
1564  virtio_main_t *vim = &virtio_main;
1565  u32 i = 0;
1566 
1567  if (vif->type != VIRTIO_IF_TYPE_PCI)
1568  return VNET_API_ERROR_INVALID_INTERFACE;
1569 
1571 
1572  for (i = 0; i < vif->max_queue_pairs; i++)
1573  {
1574  vif->virtio_pci_func->del_queue (vm, vif, RX_QUEUE (i));
1575  vif->virtio_pci_func->del_queue (vm, vif, TX_QUEUE (i));
1576  }
1577 
1578  if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
1579  vif->virtio_pci_func->del_queue (vm, vif, vif->max_queue_pairs * 2);
1580 
1581  if (vif->virtio_pci_func)
1582  vif->virtio_pci_func->device_reset (vm, vif);
1583 
1584  if (vif->hw_if_index)
1585  {
1587  vec_foreach_index (i, vif->rxq_vrings)
1588  {
1590  }
1592  }
1593 
1595 
1596  vec_foreach_index (i, vif->rxq_vrings)
1597  {
1598  virtio_vring_t *vring = vec_elt_at_index (vif->rxq_vrings, i);
1599  if (vring->used)
1600  {
1601  virtio_free_buffers (vm, vring);
1602  }
1603  vec_free (vring->buffers);
1604  vlib_physmem_free (vm, vring->desc);
1605  }
1606 
1607  vec_foreach_index (i, vif->txq_vrings)
1608  {
1609  virtio_vring_t *vring = vec_elt_at_index (vif->txq_vrings, i);
1610  if (vring->used)
1611  {
1612  virtio_free_buffers (vm, vring);
1613  }
1614  vec_free (vring->buffers);
1617  clib_spinlock_free (&vring->lockp);
1618  vlib_physmem_free (vm, vring->desc);
1619  }
1620 
1621  if (vif->cxq_vring != NULL)
1622  {
1623  u16 last = vif->cxq_vring->last_used_idx;
1624  u16 n_left = vif->cxq_vring->used->idx - last;
1625  while (n_left)
1626  {
1627  last++;
1628  n_left--;
1629  }
1630 
1631  vif->cxq_vring->last_used_idx = last;
1632  vlib_physmem_free (vm, vif->cxq_vring->desc);
1633  }
1634 
1635  vec_free (vif->rxq_vrings);
1636  vec_free (vif->txq_vrings);
1637  vec_free (vif->cxq_vring);
1638 
1639  clib_error_free (vif->error);
1640  memset (vif, 0, sizeof (*vif));
1641  pool_put (vim->interfaces, vif);
1642 
1643  return 0;
1644 }
1645 
1646 int
1648  int gso_enabled,
1649  int checksum_offload_enabled,
1650  int offloads_disabled)
1651 {
1652  if (vif->type != VIRTIO_IF_TYPE_PCI)
1653  return VNET_API_ERROR_INVALID_INTERFACE;
1654 
1655  if (gso_enabled)
1656  virtio_pci_offloads (vm, vif, 1, 0);
1657  else if (checksum_offload_enabled)
1658  virtio_pci_offloads (vm, vif, 0, 1);
1659  else if (offloads_disabled)
1660  virtio_pci_offloads (vm, vif, 0, 0);
1661 
1662  return 0;
1663 }
1664 
1665 /*
1666  * fd.io coding-style-patch-verification: ON
1667  *
1668  * Local Variables:
1669  * eval: (c-set-style "gnu")
1670  * End:
1671  */
u32 per_interface_next_index
Definition: virtio.h:132
gro_flow_table_t * flow_table
Definition: virtio.h:109
#define VRING_EVENT_F_DISABLE
Definition: virtio_std.h:81
vlib_node_registration_t virtio_input_node
(constructor) VLIB_REGISTER_NODE (virtio_input_node)
Definition: node.c:670
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:443
vring_desc_event_t * device_event
Definition: virtio.h:79
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:252
virtio_if_t * interfaces
Definition: virtio.h:219
clib_error_t * virtio_pci_vring_init(vlib_main_t *vm, virtio_if_t *vif, u16 queue_num)
Definition: pci.c:895
u32 is_modern
Definition: virtio.h:198
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:105
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:393
u32 bar_id
Definition: virtio.h:196
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:527
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:137
void vlib_pci_device_close(vlib_main_t *vm, vlib_pci_dev_handle_t h)
Definition: pci.c:1311
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:136
u32 dev_instance
Definition: virtio.h:157
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:334
u16 device_offset
Definition: virtio.h:201
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:209
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:1143
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:236
#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:895
vlib_main_t * vm
Definition: in2out_ed.c:1580
#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
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:509
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:251
static int virtio_pci_enable_gso(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:484
#define VIRTIO_NET_CTRL_GUEST_OFFLOADS
Definition: pci.h:74
void * bar
Definition: virtio.h:193
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:1345
u8 data[128]
Definition: ipsec_types.api:90
#define VIRTIO_FEATURE(X)
Definition: virtio_std.h:69
vring_desc_t * desc
Definition: virtio.h:71
double f64
Definition: types.h:142
static void clib_spinlock_free(clib_spinlock_t *p)
Definition: lock.h:72
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:1034
u32 msix_enabled
Definition: virtio.h:145
u32 as_u32
Definition: virtio.h:121
u16 msix_table_size
Definition: virtio.h:204
#define VIRTIO_PCI_CAP_COMMON_CFG
Definition: pci.h:78
u64 features
Definition: virtio.h:130
int virtio_pci_reset_device(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:971
u32 hw_if_index
Definition: virtio.h:151
static u8 virtio_pci_queue_size_valid(u16 qsz)
Definition: pci.c:583
#define virtio_log_error(vif, f,...)
Definition: virtio.h:286
#define PCI_DEVICE_ID_VIRTIO_NIC
Definition: pci.c:29
#define TX_QUEUE_ACCESS(X)
Definition: virtio.h:39
u32 notify_off_multiplier
Definition: virtio.h:197
u8 support_int_mode
Definition: virtio.h:205
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:127
static void virtio_negotiate_features(vlib_main_t *vm, virtio_if_t *vif, u64 req_features)
Definition: pci.c:904
vnet_hw_interface_flags_t flags
Definition: interface.h:538
u16 isr_offset
Definition: virtio.h:202
#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:66
#define clib_error_return(e, args...)
Definition: error.h:99
const cJSON *const b
Definition: cJSON.h:255
#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:279
#define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET
Definition: pci.h:75
u16 queue_id
Definition: virtio.h:84
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:65
u16 num_txqs
Definition: virtio.h:134
Definition: cJSON.c:84
u32 pci_dev_handle
Definition: virtio.h:144
#define TX_QUEUE(X)
Definition: virtio.h:37
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
#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:73
vring_desc_event_t * driver_event
Definition: virtio.h:78
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
int vnet_hw_interface_set_rx_mode(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id, vnet_hw_if_rx_mode mode)
Definition: devices.c:253
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:233
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:301
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:838
pci_addr_t pci_addr
Definition: virtio.h:195
#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
clib_error_t * virtio_pci_vring_packed_init(vlib_main_t *vm, virtio_if_t *vif, u16 queue_num)
Definition: pci.c:804
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:965
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:1647
#define virtio_log_debug(vif, f,...)
Definition: virtio.h:272
u8 status
Definition: virtio.h:206
u8 len
Definition: ip_types.api:103
vring_used_t * used
Definition: virtio.h:72
u16 desc_next
Definition: virtio.h:86
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:133
virtio_vring_t * rxq_vrings
Definition: virtio.h:135
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:87
void virtio_free_buffers(vlib_main_t *vm, virtio_vring_t *vring)
Definition: virtio.c:137
#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:58
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
static_always_inline void gro_flow_table_free(gro_flow_table_t *flow_table)
Definition: gro.h:171
#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:131
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:170
u32 flags
Definition: virtio.h:131
clib_error_t * virtio_pci_control_vring_init(vlib_main_t *vm, virtio_if_t *vif, u16 queue_num)
Definition: pci.c:714
clib_error_t * error
Definition: virtio.h:162
vlib_log_class_t log_default
Definition: virtio.h:217
clib_error_t * virtio_pci_control_vring_packed_init(vlib_main_t *vm, virtio_if_t *vif, u16 queue_num)
Definition: pci.c:593
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:265
int virtio_pci_delete_if(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:1561
u32 numa_node
Definition: virtio.h:158
virtio_if_type_t type
Definition: virtio.h:149
#define PCI_DEVICE_ID_VIRTIO_NIC_MODERN
Definition: pci.c:31
clib_error_t * virtio_set_packet_buffering(virtio_if_t *vif, u16 buffering_size)
Definition: virtio.c:214
vring_packed_desc_t * packed_desc
Definition: virtio.h:77
#define ASSERT(truth)
u16 avail_wrap_counter
Definition: virtio.h:99
clib_error_t * virtio_pci_vring_split_init(vlib_main_t *vm, virtio_if_t *vif, u16 queue_num)
Definition: pci.c:724
static int virtio_pci_offloads(vlib_main_t *vm, virtio_if_t *vif, int gso_enabled, int csum_offload_enabled)
Definition: pci.c:505
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:159
clib_error_t * virtio_pci_read_caps(vlib_main_t *vm, virtio_if_t *vif, void **bar)
Definition: pci.c:1004
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:433
static int virtio_pci_enable_checksum_offload(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:463
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:787
#define VRING_DESC_F_NEXT
Definition: virtio_std.h:73
clib_error_t * error
Definition: pci.h:243
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:200
static uword is_pow2(uword x)
Definition: clib.h:253
u16 ring[0]
Definition: virtio_std.h:99
virtio_vring_buffering_t * buffering
Definition: virtio.h:108
Definition: defs.h:64
u16 used_wrap_counter
Definition: virtio.h:100
static int virtio_pci_send_ctrl_msg_packed(vlib_main_t *vm, virtio_if_t *vif, virtio_ctrl_msg_t *data, u32 len)
Definition: pci.c:198
#define RX_QUEUE_ACCESS(X)
Definition: virtio.h:40
int csum_offload_enabled
Definition: virtio.h:138
#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:348
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:1196
clib_error_t * vlib_pci_map_region(vlib_main_t *vm, vlib_pci_dev_handle_t h, u32 resource, void **result)
Definition: pci.c:1182
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
u32 sw_if_index
Definition: virtio.h:152
virtio_vring_t * cxq_vring
Definition: virtio.h:194
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 VRING_DESC_F_USED
Definition: virtio_std.h:78
int is_packed
Definition: virtio.h:210
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:133
#define VIRTIO_PCI_CAP_PCI_CFG
Definition: pci.h:86
clib_error_t * virtio_pci_control_vring_split_init(vlib_main_t *vm, virtio_if_t *vif, u16 queue_num)
Definition: pci.c:658
u16 max_queue_pairs
Definition: virtio.h:203
static int virtio_pci_send_ctrl_msg_split(vlib_main_t *vm, virtio_if_t *vif, virtio_ctrl_msg_t *data, u32 len)
Definition: pci.c:338
#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
#define VIRTIO_NET_S_LINK_UP
Definition: pci.h:54
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:1251
#define RX_QUEUE(X)
Definition: virtio.h:38
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:199
static int virtio_pci_enable_multiqueue(vlib_main_t *vm, virtio_if_t *vif, u16 num_queues)
Definition: pci.c:566
u16 desc_in_use
Definition: virtio.h:85
virtio_vring_t * txq_vrings
Definition: virtio.h:136
#define VRING_DESC_F_AVAIL
Definition: virtio_std.h:77
static_always_inline void virtio_kick(vlib_main_t *vm, virtio_vring_t *vring, virtio_if_t *vif)
Definition: virtio.h:251
static_always_inline void virtio_vring_buffering_free(vlib_main_t *vm, virtio_vring_buffering_t *buffering)
u16 queue_notify_offset
Definition: virtio.h:101
static_always_inline void clib_memset_u32(void *p, u32 val, uword count)
Definition: string.h:332