FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
vhost_user.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * vhost.c - vhost-user
4  *
5  * Copyright (c) 2014-2018 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19 
20 #include <fcntl.h> /* for open */
21 #include <sys/ioctl.h>
22 #include <sys/socket.h>
23 #include <sys/un.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <sys/uio.h> /* for iovec */
27 #include <netinet/in.h>
28 #include <sys/vfs.h>
29 
30 #include <linux/if_arp.h>
31 #include <linux/if_tun.h>
32 
33 #include <vlib/vlib.h>
34 #include <vlib/unix/unix.h>
35 
36 #include <vnet/ethernet/ethernet.h>
37 #include <vnet/devices/devices.h>
38 #include <vnet/feature/feature.h>
41 
44 
45 /**
46  * @file
47  * @brief vHost User Device Driver.
48  *
49  * This file contains the source code for vHost User interface.
50  */
51 
52 
54 
55 /* *INDENT-OFF* */
57  .mtu_bytes = 1518,
58 };
59 
60 VNET_HW_INTERFACE_CLASS (vhost_interface_class, static) = {
61  .name = "vhost-user",
62 };
63 /* *INDENT-ON* */
64 
65 static long
67 {
68  struct statfs s;
69  fstatfs (fd, &s);
70  return s.f_bsize;
71 }
72 
73 static void
75 {
76  int i, r, q;
78 
79  for (i = 0; i < vui->nregions; i++)
80  {
81  if (vui->region_mmap_addr[i] != MAP_FAILED)
82  {
83 
84  long page_sz = get_huge_page_size (vui->region_mmap_fd[i]);
85 
86  ssize_t map_sz = (vui->regions[i].memory_size +
87  vui->regions[i].mmap_offset +
88  page_sz - 1) & ~(page_sz - 1);
89 
90  r =
91  munmap (vui->region_mmap_addr[i] - vui->regions[i].mmap_offset,
92  map_sz);
93 
94  vu_log_debug (vui, "unmap memory region %d addr 0x%lx len 0x%lx "
95  "page_sz 0x%x", i, vui->region_mmap_addr[i], map_sz,
96  page_sz);
97 
98  vui->region_mmap_addr[i] = MAP_FAILED;
99 
100  if (r == -1)
101  {
102  vu_log_err (vui, "failed to unmap memory region (errno %d)",
103  errno);
104  }
105  close (vui->region_mmap_fd[i]);
106  }
107  }
108  vui->nregions = 0;
109 
110  FOR_ALL_VHOST_RX_TXQ (q, vui)
111  {
112  vq = &vui->vrings[q];
113  vq->avail = 0;
114  vq->used = 0;
115  vq->desc = 0;
116  }
117 }
118 
121 {
122  vnet_main_t *vnm = vnet_get_main ();
123  vhost_user_vring_t *rxvq = &vui->vrings[qid];
124  u32 q = qid >> 1, rxvq_count;
125 
126  ASSERT ((qid & 1) == 0);
127  if (!rxvq->started || !rxvq->enabled)
128  return;
129 
130  rxvq_count = (qid >> 1) + 1;
131  if (rxvq->queue_index == ~0)
132  {
133  rxvq->queue_index =
135  rxvq->qid = q;
136  }
137 
138  FOR_ALL_VHOST_RXQ (q, vui)
139  {
140  vhost_user_vring_t *rxvq = &vui->vrings[q];
141  u32 qi = rxvq->queue_index;
142 
143  if (rxvq->queue_index == ~0)
144  break;
145  for (u32 i = 0; i < vlib_get_n_threads (); i++)
147  }
148 
149  for (u32 i = 0; i < vlib_get_n_threads (); i++)
150  {
151  vhost_user_vring_t *rxvq =
152  &vui->vrings[VHOST_VRING_IDX_RX (i % rxvq_count)];
153  u32 qi = rxvq->queue_index;
154 
156  }
157 
159 }
160 
161 /**
162  * @brief Unassign existing interface/queue to thread mappings and re-assign
163  * new interface/queue to thread mappings
164  */
167 {
168  vhost_user_vring_t *txvq = &vui->vrings[qid];
169  vnet_main_t *vnm = vnet_get_main ();
170  int rv;
171  u32 q = qid >> 1;
173 
174  ASSERT ((qid & 1) == 1); // should be odd
175  // Assign new queue mappings for the interface
176  if (txvq->queue_index != ~0)
177  return;
179  vhost_user_input_node.index);
182  txvq->thread_index =
184 
185  if (txvq->mode == VNET_HW_IF_RX_MODE_UNKNOWN)
186  /* Set polling as the default */
188  if (txvq->mode == VNET_HW_IF_RX_MODE_POLLING)
189  {
190  vhost_cpu_t *cpu = vec_elt_at_index (vum->cpus, txvq->thread_index);
191  /* Keep a polling queue count for each thread */
192  cpu->polling_q_count++;
193  }
194  txvq->qid = q;
195  rv = vnet_hw_if_set_rx_queue_mode (vnm, txvq->queue_index, txvq->mode);
196  if (rv)
197  vu_log_warn (vui, "unable to set rx mode for interface %d, "
198  "queue %d: rc=%d", vui->hw_if_index, q, rv);
200 }
201 
202 /** @brief Returns whether at least one TX and one RX vring are enabled */
205 {
206  int i, found[2] = { }; //RX + TX
207 
208  for (i = 0; i < vui->num_qid; i++)
209  if (vui->vrings[i].started && vui->vrings[i].enabled)
210  found[i & 1] = 1;
211 
212  return found[0] && found[1];
213 }
214 
217 {
218  /* if we have pointers to descriptor table, go up */
219  int is_ready = vhost_user_intf_ready (vui);
220  if (is_ready != vui->is_ready)
221  {
222  vu_log_debug (vui, "interface %d %s", vui->sw_if_index,
223  is_ready ? "ready" : "down");
224  if (vui->admin_up)
227  : 0);
228  vui->is_ready = is_ready;
229  }
230 }
231 
232 static clib_error_t *
234 {
235  __attribute__ ((unused)) int n;
236  u8 buff[8];
237 
238  n = read (uf->file_descriptor, ((char *) &buff), 8);
239 
240  return 0;
241 }
242 
245 {
246  if (qid & 1) // RX is odd, TX is even
247  {
248  if (vui->vrings[qid].queue_index == ~0)
250  }
251  else
253 }
254 
255 static clib_error_t *
257 {
258  __attribute__ ((unused)) ssize_t n;
259  u8 buff[8];
261  vhost_user_intf_t *vui =
263  u32 qid = uf->private_data & 0xff;
264  u32 is_txq = qid & 1;
265  vhost_user_vring_t *vq = &vui->vrings[qid];
266  vnet_main_t *vnm = vnet_get_main ();
267 
268  n = read (uf->file_descriptor, buff, 8);
269  if (vq->started == 0)
270  {
271  vq->started = 1;
272  vhost_user_thread_placement (vui, qid);
274  if (is_txq)
276  vq->kickfd_idx);
277  }
278 
279  if (is_txq && (vq->mode != VNET_HW_IF_RX_MODE_POLLING) &&
280  vhost_user_intf_ready (vui))
281  {
282  vhost_cpu_t *cpu = vec_elt_at_index (vum->cpus, vq->thread_index);
283  /*
284  * If the thread has more than 1 queue and the other queue is in polling
285  * mode, there is no need to trigger an interrupt
286  */
287  if (cpu->polling_q_count == 0)
289  }
290 
291  return 0;
292 }
293 
296 {
297  vhost_user_vring_t *vring = &vui->vrings[qid];
298 
299  clib_memset (vring, 0, sizeof (*vring));
300  vring->kickfd_idx = ~0;
301  vring->callfd_idx = ~0;
302  vring->errfd = -1;
303  vring->qid = -1;
304  vring->queue_index = ~0;
305  vring->thread_index = ~0;
307 
308  clib_spinlock_init (&vring->vring_lock);
309 
310  /*
311  * We have a bug with some qemu 2.5, and this may be a fix.
312  * Feel like interpretation holy text, but this is from vhost-user.txt.
313  * "
314  * One queue pair is enabled initially. More queues are enabled
315  * dynamically, by sending message VHOST_USER_SET_VRING_ENABLE.
316  * "
317  * Don't know who's right, but this is what DPDK does.
318  */
319  if (qid == 0 || qid == 1)
320  vring->enabled = 1;
321 }
322 
325 {
326  vhost_user_vring_t *vring = &vui->vrings[qid];
327 
328  if (vring->kickfd_idx != ~0)
329  {
331  vring->kickfd_idx);
332  clib_file_del (&file_main, uf);
333  vring->kickfd_idx = ~0;
334  }
335  if (vring->callfd_idx != ~0)
336  {
338  vring->callfd_idx);
339  clib_file_del (&file_main, uf);
340  vring->callfd_idx = ~0;
341  }
342  if (vring->errfd != -1)
343  {
344  close (vring->errfd);
345  vring->errfd = -1;
346  }
347 
348  clib_spinlock_free (&vring->vring_lock);
349 
350  // save the needed information in vrings prior to being wiped out
351  u16 q = vui->vrings[qid].qid;
352  u32 queue_index = vui->vrings[qid].queue_index;
353  u32 mode = vui->vrings[qid].mode;
354  u32 thread_index = vui->vrings[qid].thread_index;
355  vhost_user_vring_init (vui, qid);
356  vui->vrings[qid].qid = q;
357  vui->vrings[qid].queue_index = queue_index;
358  vui->vrings[qid].mode = mode;
359  vui->vrings[qid].thread_index = thread_index;
360 }
361 
364 {
365  vnet_main_t *vnm = vnet_get_main ();
366  int q;
367 
369 
370  if (vui->clib_file_index != ~0)
371  {
373  vui->clib_file_index = ~0;
374  }
375 
376  vui->is_ready = 0;
377 
378  FOR_ALL_VHOST_RX_TXQ (q, vui) { vhost_user_vring_close (vui, q); }
379 
380  unmap_all_mem_regions (vui);
381  vu_log_debug (vui, "interface ifindex %d disconnected", vui->sw_if_index);
382 }
383 
384 void
386  vhost_user_vring_t *txvq)
387 {
389  {
390  if (txvq->used_event)
391  {
392  if (txvq->mode == VNET_HW_IF_RX_MODE_POLLING)
393  txvq->used_event->flags = VRING_EVENT_F_DISABLE;
394  else
395  txvq->used_event->flags = 0;
396  }
397  }
398  else
399  {
400  if (txvq->used)
401  {
402  if (txvq->mode == VNET_HW_IF_RX_MODE_POLLING)
404  else
405  txvq->used->flags = 0;
406  }
407  }
408 }
409 
410 static clib_error_t *
412 {
413  int n, i, j;
414  int fd, number_of_fds = 0;
415  int fds[VHOST_MEMORY_MAX_NREGIONS];
416  vhost_user_msg_t msg;
417  struct msghdr mh;
418  struct iovec iov[1];
420  vhost_user_intf_t *vui;
421  struct cmsghdr *cmsg;
422  u8 q;
423  clib_file_t template = { 0 };
424  vnet_main_t *vnm = vnet_get_main ();
426 
427  vui = pool_elt_at_index (vum->vhost_user_interfaces, uf->private_data);
428 
429  char control[CMSG_SPACE (VHOST_MEMORY_MAX_NREGIONS * sizeof (int))];
430 
431  clib_memset (&mh, 0, sizeof (mh));
432  clib_memset (control, 0, sizeof (control));
433 
434  for (i = 0; i < VHOST_MEMORY_MAX_NREGIONS; i++)
435  fds[i] = -1;
436 
437  /* set the payload */
438  iov[0].iov_base = (void *) &msg;
439  iov[0].iov_len = VHOST_USER_MSG_HDR_SZ;
440 
441  mh.msg_iov = iov;
442  mh.msg_iovlen = 1;
443  mh.msg_control = control;
444  mh.msg_controllen = sizeof (control);
445 
446  n = recvmsg (uf->file_descriptor, &mh, 0);
447 
448  if (n != VHOST_USER_MSG_HDR_SZ)
449  {
450  if (n == -1)
451  {
452  vu_log_debug (vui, "recvmsg returned error %d %s", errno,
453  strerror (errno));
454  }
455  else
456  {
457  vu_log_debug (vui, "n (%d) != VHOST_USER_MSG_HDR_SZ (%d)",
459  }
460  goto close_socket;
461  }
462 
463  if (mh.msg_flags & MSG_CTRUNC)
464  {
465  vu_log_debug (vui, "MSG_CTRUNC is set");
466  goto close_socket;
467  }
468 
469  cmsg = CMSG_FIRSTHDR (&mh);
470 
471  if (cmsg && (cmsg->cmsg_len > 0) && (cmsg->cmsg_level == SOL_SOCKET) &&
472  (cmsg->cmsg_type == SCM_RIGHTS) &&
473  (cmsg->cmsg_len - CMSG_LEN (0) <=
474  VHOST_MEMORY_MAX_NREGIONS * sizeof (int)))
475  {
476  number_of_fds = (cmsg->cmsg_len - CMSG_LEN (0)) / sizeof (int);
477  clib_memcpy_fast (fds, CMSG_DATA (cmsg), number_of_fds * sizeof (int));
478  }
479 
480  /* version 1, no reply bit set */
481  if ((msg.flags & 7) != 1)
482  {
483  vu_log_debug (vui, "malformed message received. closing socket");
484  goto close_socket;
485  }
486 
487  {
488  int rv;
489  rv =
490  read (uf->file_descriptor, ((char *) &msg) + VHOST_USER_MSG_HDR_SZ,
491  msg.size);
492  if (rv < 0)
493  {
494  vu_log_debug (vui, "read failed %s", strerror (errno));
495  goto close_socket;
496  }
497  else if (rv != msg.size)
498  {
499  vu_log_debug (vui, "message too short (read %dB should be %dB)", rv,
500  msg.size);
501  goto close_socket;
502  }
503  }
504 
505  switch (msg.request)
506  {
508  msg.flags |= 4;
509  msg.u64 = VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF) |
510  VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ) |
511  VIRTIO_FEATURE (VIRTIO_F_ANY_LAYOUT) |
512  VIRTIO_FEATURE (VIRTIO_RING_F_INDIRECT_DESC) |
513  VIRTIO_FEATURE (VHOST_F_LOG_ALL) |
514  VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_ANNOUNCE) |
515  VIRTIO_FEATURE (VIRTIO_NET_F_MQ) |
516  VIRTIO_FEATURE (VHOST_USER_F_PROTOCOL_FEATURES) |
517  VIRTIO_FEATURE (VIRTIO_F_VERSION_1);
518  msg.u64 &= vui->feature_mask;
519 
520  if (vui->enable_event_idx)
521  msg.u64 |= VIRTIO_FEATURE (VIRTIO_RING_F_EVENT_IDX);
522  if (vui->enable_gso)
524  if (vui->enable_packed)
525  msg.u64 |= VIRTIO_FEATURE (VIRTIO_F_RING_PACKED);
526 
527  msg.size = sizeof (msg.u64);
528  vu_log_debug (vui, "if %d msg VHOST_USER_GET_FEATURES - reply "
529  "0x%016llx", vui->hw_if_index, msg.u64);
530  n =
531  send (uf->file_descriptor, &msg, VHOST_USER_MSG_HDR_SZ + msg.size, 0);
532  if (n != (msg.size + VHOST_USER_MSG_HDR_SZ))
533  {
534  vu_log_debug (vui, "could not send message response");
535  goto close_socket;
536  }
537  break;
538 
540  vu_log_debug (vui, "if %d msg VHOST_USER_SET_FEATURES features "
541  "0x%016llx", vui->hw_if_index, msg.u64);
542 
543  vui->features = msg.u64;
544 
545  if (vui->features &
546  (VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF) |
547  VIRTIO_FEATURE (VIRTIO_F_VERSION_1)))
548  vui->virtio_net_hdr_sz = 12;
549  else
550  vui->virtio_net_hdr_sz = 10;
551 
552  vui->is_any_layout =
553  (vui->features & VIRTIO_FEATURE (VIRTIO_F_ANY_LAYOUT)) ? 1 : 0;
554 
557  if (vui->enable_gso &&
560  {
564  }
565  else
566  {
569  }
571  vui->is_ready = 0;
573  break;
574 
576  vu_log_debug (vui, "if %d msg VHOST_USER_SET_MEM_TABLE nregions %d",
577  vui->hw_if_index, msg.memory.nregions);
578 
579  if ((msg.memory.nregions < 1) ||
580  (msg.memory.nregions > VHOST_MEMORY_MAX_NREGIONS))
581  {
582  vu_log_debug (vui, "number of mem regions must be between 1 and %i",
584  goto close_socket;
585  }
586 
587  if (msg.memory.nregions != number_of_fds)
588  {
589  vu_log_debug (vui, "each memory region must have FD");
590  goto close_socket;
591  }
592 
593  /* Do the mmap without barrier sync */
594  void *region_mmap_addr[VHOST_MEMORY_MAX_NREGIONS];
595  for (i = 0; i < msg.memory.nregions; i++)
596  {
597  long page_sz = get_huge_page_size (fds[i]);
598 
599  /* align size to page */
600  ssize_t map_sz = (msg.memory.regions[i].memory_size +
601  msg.memory.regions[i].mmap_offset +
602  page_sz - 1) & ~(page_sz - 1);
603 
604  region_mmap_addr[i] = mmap (0, map_sz, PROT_READ | PROT_WRITE,
605  MAP_SHARED, fds[i], 0);
606  if (region_mmap_addr[i] == MAP_FAILED)
607  {
608  vu_log_err (vui, "failed to map memory. errno is %d", errno);
609  for (j = 0; j < i; j++)
610  munmap (region_mmap_addr[j], map_sz);
611  goto close_socket;
612  }
613  vu_log_debug (vui, "map memory region %d addr 0 len 0x%lx fd %d "
614  "mapped 0x%lx page_sz 0x%x", i, map_sz, fds[i],
615  region_mmap_addr[i], page_sz);
616  }
617 
619  unmap_all_mem_regions (vui);
620  for (i = 0; i < msg.memory.nregions; i++)
621  {
622  clib_memcpy_fast (&(vui->regions[i]), &msg.memory.regions[i],
623  sizeof (vhost_user_memory_region_t));
624 
625  vui->region_mmap_addr[i] = region_mmap_addr[i];
626  vui->region_guest_addr_lo[i] = vui->regions[i].guest_phys_addr;
627  vui->region_guest_addr_hi[i] = vui->regions[i].guest_phys_addr +
628  vui->regions[i].memory_size;
629 
630  vui->region_mmap_addr[i] += vui->regions[i].mmap_offset;
631  vui->region_mmap_fd[i] = fds[i];
632 
633  vui->nregions++;
634  }
635 
636  /*
637  * Re-compute desc, used, and avail descriptor table if vring address
638  * is set.
639  */
640  FOR_ALL_VHOST_RX_TXQ (q, vui)
641  {
642  if (vui->vrings[q].desc_user_addr && vui->vrings[q].used_user_addr &&
643  vui->vrings[q].avail_user_addr)
644  {
645  vui->vrings[q].desc =
646  map_user_mem (vui, vui->vrings[q].desc_user_addr);
647  vui->vrings[q].used =
648  map_user_mem (vui, vui->vrings[q].used_user_addr);
649  vui->vrings[q].avail =
650  map_user_mem (vui, vui->vrings[q].avail_user_addr);
651  }
652  }
654  break;
655 
657  vu_log_debug (vui, "if %d msg VHOST_USER_SET_VRING_NUM idx %d num %d",
658  vui->hw_if_index, msg.state.index, msg.state.num);
659 
660  if ((msg.state.num > 32768) || /* maximum ring size is 32768 */
661  (msg.state.num == 0) || /* it cannot be zero */
662  ((msg.state.num - 1) & msg.state.num) || /* must be power of 2 */
663  (msg.state.index >= vui->num_qid))
664  {
665  vu_log_debug (vui, "invalid VHOST_USER_SET_VRING_NUM: msg.state.num"
666  " %d, msg.state.index %d, curruent max q %d",
667  msg.state.num, msg.state.index, vui->num_qid);
668  goto close_socket;
669  }
670  vui->vrings[msg.state.index].qsz_mask = msg.state.num - 1;
671  break;
672 
674  vu_log_debug (vui, "if %d msg VHOST_USER_SET_VRING_ADDR idx %d",
675  vui->hw_if_index, msg.state.index);
676 
677  if (msg.state.index >= vui->num_qid)
678  {
679  vu_log_debug (vui, "invalid vring index VHOST_USER_SET_VRING_ADDR:"
680  " %u >= %u", msg.state.index, vui->num_qid);
681  goto close_socket;
682  }
683 
684  if (msg.size < sizeof (msg.addr))
685  {
686  vu_log_debug (vui, "vhost message is too short (%d < %d)",
687  msg.size, sizeof (msg.addr));
688  goto close_socket;
689  }
690 
691  vring_desc_t *desc = map_user_mem (vui, msg.addr.desc_user_addr);
692  vring_used_t *used = map_user_mem (vui, msg.addr.used_user_addr);
693  vring_avail_t *avail = map_user_mem (vui, msg.addr.avail_user_addr);
694 
695  if ((desc == NULL) || (used == NULL) || (avail == NULL))
696  {
697  vu_log_debug (vui, "failed to map user memory for hw_if_index %d",
698  vui->hw_if_index);
699  goto close_socket;
700  }
701 
702  vui->vrings[msg.state.index].desc_user_addr = msg.addr.desc_user_addr;
703  vui->vrings[msg.state.index].used_user_addr = msg.addr.used_user_addr;
704  vui->vrings[msg.state.index].avail_user_addr = msg.addr.avail_user_addr;
705 
707  vui->vrings[msg.state.index].desc = desc;
708  vui->vrings[msg.state.index].used = used;
709  vui->vrings[msg.state.index].avail = avail;
710 
711  vui->vrings[msg.state.index].log_guest_addr = msg.addr.log_guest_addr;
712  vui->vrings[msg.state.index].log_used =
713  (msg.addr.flags & (1 << VHOST_VRING_F_LOG)) ? 1 : 0;
714 
715  /* Spec says: If VHOST_USER_F_PROTOCOL_FEATURES has not been negotiated,
716  the ring is initialized in an enabled state. */
717  if (!(vui->features & VIRTIO_FEATURE (VHOST_USER_F_PROTOCOL_FEATURES)))
718  vui->vrings[msg.state.index].enabled = 1;
719 
720  vui->vrings[msg.state.index].last_used_idx =
721  vui->vrings[msg.state.index].last_avail_idx =
722  vui->vrings[msg.state.index].used->idx;
723  vui->vrings[msg.state.index].last_kick =
724  vui->vrings[msg.state.index].last_used_idx;
725 
726  /* tell driver that we want interrupts or not */
727  vhost_user_set_operation_mode (vui, &vui->vrings[msg.state.index]);
730  break;
731 
733  vu_log_debug (vui, "if %d msg VHOST_USER_SET_OWNER", vui->hw_if_index);
734  break;
735 
737  vu_log_debug (vui, "if %d msg VHOST_USER_RESET_OWNER",
738  vui->hw_if_index);
739  break;
740 
742  vu_log_debug (vui, "if %d msg VHOST_USER_SET_VRING_CALL %d",
743  vui->hw_if_index, msg.u64);
744 
745  q = (u8) (msg.u64 & 0xFF);
746  if (vui->num_qid > q)
747  {
748  /* if there is old fd, delete and close it */
749  if (vui->vrings[q].callfd_idx != ~0)
750  {
752  vui->vrings[q].callfd_idx);
753  clib_file_del (&file_main, uf);
754  vui->vrings[q].callfd_idx = ~0;
755  }
756  }
757  else if (vec_len (vui->vrings) > q)
758  {
759  /* grow vrings by pair (RX + TX) */
760  vui->num_qid = (q & 1) ? (q + 1) : (q + 2);
761  }
762  else
763  {
764  u32 i, new_max_q, old_max_q = vec_len (vui->vrings);
765 
766  /*
767  * Double the array size if it is less than 64 entries.
768  * Slow down thereafter.
769  */
770  if (vec_len (vui->vrings) < (VHOST_VRING_INIT_MQ_PAIR_SZ << 3))
771  new_max_q = vec_len (vui->vrings) << 1;
772  else
773  new_max_q = vec_len (vui->vrings) +
775  if (new_max_q > (VHOST_VRING_MAX_MQ_PAIR_SZ << 1))
776  new_max_q = (VHOST_VRING_MAX_MQ_PAIR_SZ << 1);
777 
778  /* sync with the worker threads, vrings may move due to realloc */
780  vec_validate_aligned (vui->vrings, new_max_q - 1,
783 
784  for (i = old_max_q; i < vec_len (vui->vrings); i++)
785  vhost_user_vring_init (vui, i);
786 
787  /* grow vrings by pair (RX + TX) */
788  vui->num_qid = (q & 1) ? (q + 1) : (q + 2);
789  }
790 
791  if (!(msg.u64 & VHOST_USER_VRING_NOFD_MASK))
792  {
793  if (number_of_fds != 1)
794  {
795  vu_log_debug (vui, "More than one fd received !");
796  goto close_socket;
797  }
798 
799  template.read_function = vhost_user_callfd_read_ready;
800  template.file_descriptor = fds[0];
801  template.private_data =
802  ((vui - vhost_user_main.vhost_user_interfaces) << 8) + q;
803  template.description = format (0, "vhost user");
804  vui->vrings[q].callfd_idx = clib_file_add (&file_main, &template);
805  }
806  else
807  vui->vrings[q].callfd_idx = ~0;
808  break;
809 
811  vu_log_debug (vui, "if %d msg VHOST_USER_SET_VRING_KICK %d",
812  vui->hw_if_index, msg.u64);
813 
814  q = (u8) (msg.u64 & 0xFF);
815  if (q >= vui->num_qid)
816  {
817  vu_log_debug (vui, "invalid vring index VHOST_USER_SET_VRING_KICK:"
818  " %u >= %u", q, vui->num_qid);
819  goto close_socket;
820  }
821 
822  if (vui->vrings[q].kickfd_idx != ~0)
823  {
825  vui->vrings[q].kickfd_idx);
826  clib_file_del (&file_main, uf);
827  vui->vrings[q].kickfd_idx = ~0;
828  }
829 
830  if (!(msg.u64 & VHOST_USER_VRING_NOFD_MASK))
831  {
832  if (number_of_fds != 1)
833  {
834  vu_log_debug (vui, "More than one fd received !");
835  goto close_socket;
836  }
837 
838  template.read_function = vhost_user_kickfd_read_ready;
839  template.file_descriptor = fds[0];
840  template.private_data =
841  (((uword) (vui - vhost_user_main.vhost_user_interfaces)) << 8) +
842  q;
843  vui->vrings[q].kickfd_idx = clib_file_add (&file_main, &template);
844  }
845  else
846  {
847  //When no kickfd is set, the queue is initialized as started
848  vui->vrings[q].kickfd_idx = ~0;
849  vui->vrings[q].started = 1;
851  }
853  break;
854 
856  vu_log_debug (vui, "if %d msg VHOST_USER_SET_VRING_ERR %d",
857  vui->hw_if_index, msg.u64);
858 
859  q = (u8) (msg.u64 & 0xFF);
860  if (q >= vui->num_qid)
861  {
862  vu_log_debug (vui, "invalid vring index VHOST_USER_SET_VRING_ERR:"
863  " %u >= %u", q, vui->num_qid);
864  goto close_socket;
865  }
866 
867  if (vui->vrings[q].errfd != -1)
868  close (vui->vrings[q].errfd);
869 
870  if (!(msg.u64 & VHOST_USER_VRING_NOFD_MASK))
871  {
872  if (number_of_fds != 1)
873  goto close_socket;
874 
875  vui->vrings[q].errfd = fds[0];
876  }
877  else
878  vui->vrings[q].errfd = -1;
879  break;
880 
882  vu_log_debug (vui,
883  "if %d msg VHOST_USER_SET_VRING_BASE idx %d num 0x%x",
884  vui->hw_if_index, msg.state.index, msg.state.num);
885  if (msg.state.index >= vui->num_qid)
886  {
887  vu_log_debug (vui, "invalid vring index VHOST_USER_SET_VRING_ADDR:"
888  " %u >= %u", msg.state.index, vui->num_qid);
889  goto close_socket;
890  }
892  vui->vrings[msg.state.index].last_avail_idx = msg.state.num;
894  {
895  /*
896  * 0 1 2 3
897  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
898  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
899  * | last avail idx | | last used idx | |
900  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
901  * ^ ^
902  * | |
903  * avail wrap counter used wrap counter
904  */
905  /* last avail idx at bit 0-14. */
906  vui->vrings[msg.state.index].last_avail_idx =
907  msg.state.num & 0x7fff;
908  /* avail wrap counter at bit 15 */
909  vui->vrings[msg.state.index].avail_wrap_counter =
910  ! !(msg.state.num & (1 << 15));
911 
912  /*
913  * Although last_used_idx is passed in the upper 16 bits in qemu
914  * implementation, in practice, last_avail_idx and last_used_idx are
915  * usually the same. As a result, DPDK does not bother to pass us
916  * last_used_idx. The spec is not clear on thex coding. I figured it
917  * out by reading the qemu code. So let's just read last_avail_idx
918  * and set last_used_idx equals to last_avail_idx.
919  */
920  vui->vrings[msg.state.index].last_used_idx =
921  vui->vrings[msg.state.index].last_avail_idx;
922  vui->vrings[msg.state.index].last_kick =
923  vui->vrings[msg.state.index].last_used_idx;
924  vui->vrings[msg.state.index].used_wrap_counter =
925  vui->vrings[msg.state.index].avail_wrap_counter;
926 
927  if (vui->vrings[msg.state.index].avail_wrap_counter == 1)
928  vui->vrings[msg.state.index].avail_wrap_counter =
930  }
932  break;
933 
935  if (msg.state.index >= vui->num_qid)
936  {
937  vu_log_debug (vui, "invalid vring index VHOST_USER_GET_VRING_BASE:"
938  " %u >= %u", msg.state.index, vui->num_qid);
939  goto close_socket;
940  }
941 
942  /* protection is needed to prevent rx/tx from changing last_avail_idx */
944  /*
945  * Copy last_avail_idx from the vring before closing it because
946  * closing the vring also initializes the vring last_avail_idx
947  */
948  msg.state.num = vui->vrings[msg.state.index].last_avail_idx;
950  {
951  msg.state.num =
952  (vui->vrings[msg.state.index].last_avail_idx & 0x7fff) |
953  (! !vui->vrings[msg.state.index].avail_wrap_counter << 15);
954  msg.state.num |=
955  ((vui->vrings[msg.state.index].last_used_idx & 0x7fff) |
956  (! !vui->vrings[msg.state.index].used_wrap_counter << 15)) << 16;
957  }
958  msg.flags |= 4;
959  msg.size = sizeof (msg.state);
960 
961  /*
962  * Spec says: Client must [...] stop ring upon receiving
963  * VHOST_USER_GET_VRING_BASE
964  */
965  vhost_user_vring_close (vui, msg.state.index);
967  vu_log_debug (vui,
968  "if %d msg VHOST_USER_GET_VRING_BASE idx %d num 0x%x",
969  vui->hw_if_index, msg.state.index, msg.state.num);
970  n =
971  send (uf->file_descriptor, &msg, VHOST_USER_MSG_HDR_SZ + msg.size, 0);
972  if (n != (msg.size + VHOST_USER_MSG_HDR_SZ))
973  {
974  vu_log_debug (vui, "could not send message response");
975  goto close_socket;
976  }
978  break;
979 
980  case VHOST_USER_NONE:
981  vu_log_debug (vui, "if %d msg VHOST_USER_NONE", vui->hw_if_index);
982  break;
983 
985  vu_log_debug (vui, "if %d msg VHOST_USER_SET_LOG_BASE",
986  vui->hw_if_index);
987 
988  if (msg.size != sizeof (msg.log))
989  {
990  vu_log_debug (vui, "invalid msg size for VHOST_USER_SET_LOG_BASE:"
991  " %d instead of %d", msg.size, sizeof (msg.log));
992  goto close_socket;
993  }
994 
996  {
997  vu_log_debug (vui, "VHOST_USER_PROTOCOL_F_LOG_SHMFD not set but "
998  "VHOST_USER_SET_LOG_BASE received");
999  goto close_socket;
1000  }
1001 
1002  fd = fds[0];
1003  /* align size to page */
1004  long page_sz = get_huge_page_size (fd);
1005  ssize_t map_sz =
1006  (msg.log.size + msg.log.offset + page_sz - 1) & ~(page_sz - 1);
1007 
1008  void *log_base_addr = mmap (0, map_sz, PROT_READ | PROT_WRITE,
1009  MAP_SHARED, fd, 0);
1010 
1011  vu_log_debug (vui, "map log region addr 0 len 0x%lx off 0x%lx fd %d "
1012  "mapped 0x%lx", map_sz, msg.log.offset, fd,
1013  log_base_addr);
1014 
1015  if (log_base_addr == MAP_FAILED)
1016  {
1017  vu_log_err (vui, "failed to map memory. errno is %d", errno);
1018  goto close_socket;
1019  }
1020 
1022  vui->log_base_addr = log_base_addr;
1023  vui->log_base_addr += msg.log.offset;
1024  vui->log_size = msg.log.size;
1026 
1027  msg.flags |= 4;
1028  msg.size = sizeof (msg.u64);
1029  n =
1030  send (uf->file_descriptor, &msg, VHOST_USER_MSG_HDR_SZ + msg.size, 0);
1031  if (n != (msg.size + VHOST_USER_MSG_HDR_SZ))
1032  {
1033  vu_log_debug (vui, "could not send message response");
1034  goto close_socket;
1035  }
1036  break;
1037 
1038  case VHOST_USER_SET_LOG_FD:
1039  vu_log_debug (vui, "if %d msg VHOST_USER_SET_LOG_FD", vui->hw_if_index);
1040  break;
1041 
1043  msg.flags |= 4;
1044  msg.u64 = (1 << VHOST_USER_PROTOCOL_F_LOG_SHMFD) |
1045  (1 << VHOST_USER_PROTOCOL_F_MQ);
1046  msg.size = sizeof (msg.u64);
1047  vu_log_debug (vui, "if %d msg VHOST_USER_GET_PROTOCOL_FEATURES - "
1048  "reply 0x%016llx", vui->hw_if_index, msg.u64);
1049  n =
1050  send (uf->file_descriptor, &msg, VHOST_USER_MSG_HDR_SZ + msg.size, 0);
1051  if (n != (msg.size + VHOST_USER_MSG_HDR_SZ))
1052  {
1053  vu_log_debug (vui, "could not send message response");
1054  goto close_socket;
1055  }
1056  break;
1057 
1059  vu_log_debug (vui, "if %d msg VHOST_USER_SET_PROTOCOL_FEATURES "
1060  "features 0x%016llx", vui->hw_if_index, msg.u64);
1061  vui->protocol_features = msg.u64;
1062  break;
1063 
1065  msg.flags |= 4;
1066  msg.u64 = VHOST_VRING_MAX_MQ_PAIR_SZ;
1067  msg.size = sizeof (msg.u64);
1068  vu_log_debug (vui, "if %d msg VHOST_USER_GET_QUEUE_NUM - reply %d",
1069  vui->hw_if_index, msg.u64);
1070  n =
1071  send (uf->file_descriptor, &msg, VHOST_USER_MSG_HDR_SZ + msg.size, 0);
1072  if (n != (msg.size + VHOST_USER_MSG_HDR_SZ))
1073  {
1074  vu_log_debug (vui, "could not send message response");
1075  goto close_socket;
1076  }
1077  break;
1078 
1080  vu_log_debug (vui, "if %d VHOST_USER_SET_VRING_ENABLE: %s queue %d",
1081  vui->hw_if_index, msg.state.num ? "enable" : "disable",
1082  msg.state.index);
1083  if (msg.state.index >= vui->num_qid)
1084  {
1085  vu_log_debug (vui, "invalid vring idx VHOST_USER_SET_VRING_ENABLE:"
1086  " %u >= %u", msg.state.index, vui->num_qid);
1087  goto close_socket;
1088  }
1089 
1090  vui->vrings[msg.state.index].enabled = msg.state.num;
1091  vhost_user_thread_placement (vui, msg.state.index);
1093  break;
1094 
1095  default:
1096  vu_log_debug (vui, "unknown vhost-user message %d received. "
1097  "closing socket", msg.request);
1098  goto close_socket;
1099  }
1100 
1101  return 0;
1102 
1103 close_socket:
1108  return 0;
1109 }
1110 
1111 static clib_error_t *
1113 {
1116  vhost_user_intf_t *vui =
1118 
1119  vu_log_debug (vui, "socket error on if %d", vui->sw_if_index);
1123  return 0;
1124 }
1125 
1126 static clib_error_t *
1128 {
1129  int client_fd, client_len;
1130  struct sockaddr_un client;
1131  clib_file_t template = { 0 };
1133  vhost_user_intf_t *vui;
1134 
1136 
1137  client_len = sizeof (client);
1138  client_fd = accept (uf->file_descriptor,
1139  (struct sockaddr *) &client,
1140  (socklen_t *) & client_len);
1141 
1142  if (client_fd < 0)
1143  return clib_error_return_unix (0, "accept");
1144 
1145  if (vui->clib_file_index != ~0)
1146  {
1147  vu_log_debug (vui, "Close client socket for vhost interface %d, fd %d",
1148  vui->sw_if_index, UNIX_GET_FD (vui->clib_file_index));
1150  }
1151 
1152  vu_log_debug (vui, "New client socket for vhost interface %d, fd %d",
1153  vui->sw_if_index, client_fd);
1154  template.read_function = vhost_user_socket_read;
1155  template.error_function = vhost_user_socket_error;
1156  template.file_descriptor = client_fd;
1157  template.private_data = vui - vhost_user_main.vhost_user_interfaces;
1158  template.description = format (0, "vhost interface %d", vui->sw_if_index);
1159  vui->clib_file_index = clib_file_add (&file_main, &template);
1160  vui->num_qid = 2;
1161  return 0;
1162 }
1163 
1164 static clib_error_t *
1166 {
1169 
1170  vum->log_default = vlib_log_register_class ("vhost-user", 0);
1171 
1172  vum->coalesce_frames = 32;
1173  vum->coalesce_time = 1e-3;
1174 
1175  vec_validate (vum->cpus, tm->n_vlib_mains - 1);
1176 
1177  vhost_cpu_t *cpu;
1178  vec_foreach (cpu, vum->cpus)
1179  {
1180  /* This is actually not necessary as validate already zeroes it
1181  * Just keeping the loop here for later because I am lazy. */
1182  cpu->rx_buffers_len = 0;
1183  }
1184 
1185  vum->random = random_default_seed ();
1186 
1188 
1189  return 0;
1190 }
1191 
1192 /* *INDENT-OFF* */
1194 {
1195  .runs_after = VLIB_INITS("ip4_init"),
1196 };
1197 /* *INDENT-ON* */
1198 
1199 static uword
1202 {
1203  vhost_user_intf_t *vui;
1204  f64 timeout = 3153600000.0 /* 100 years */ ;
1205  uword event_type, *event_data = 0;
1207  u16 qid;
1208  f64 now, poll_time_remaining;
1209  f64 next_timeout;
1210  u8 stop_timer = 0;
1211 
1212  while (1)
1213  {
1214  poll_time_remaining =
1216  event_type = vlib_process_get_events (vm, &event_data);
1217  vec_reset_length (event_data);
1218 
1219  /*
1220  * Use the remaining timeout if it is less than coalesce time to avoid
1221  * resetting the existing timer in the middle of expiration
1222  */
1223  timeout = poll_time_remaining;
1224  if (vlib_process_suspend_time_is_zero (timeout) ||
1225  (timeout > vum->coalesce_time))
1226  timeout = vum->coalesce_time;
1227 
1228  now = vlib_time_now (vm);
1229  switch (event_type)
1230  {
1232  stop_timer = 1;
1233  break;
1234 
1236  stop_timer = 0;
1237  timeout = 1e-3;
1238  if (!vlib_process_suspend_time_is_zero (poll_time_remaining))
1239  break;
1240  /* fall through */
1241 
1242  case ~0:
1243  /* *INDENT-OFF* */
1244  pool_foreach (vui, vum->vhost_user_interfaces) {
1245  next_timeout = timeout;
1246  FOR_ALL_VHOST_RX_TXQ (qid, vui)
1247  {
1248  vhost_user_vring_t *vq = &vui->vrings[qid];
1249 
1250  if (vq->started == 0)
1251  continue;
1252  if (vq->n_since_last_int)
1253  {
1254  if (now >= vq->int_deadline)
1255  vhost_user_send_call (vm, vui, vq);
1256  else
1257  next_timeout = vq->int_deadline - now;
1258  }
1259 
1260  if ((next_timeout < timeout) && (next_timeout > 0.0))
1261  timeout = next_timeout;
1262  }
1263  }
1264  /* *INDENT-ON* */
1265  break;
1266 
1267  default:
1268  clib_warning ("BUG: unhandled event type %d", event_type);
1269  break;
1270  }
1271  /* No less than 1 millisecond */
1272  if (timeout < 1e-3)
1273  timeout = 1e-3;
1274  if (stop_timer)
1275  timeout = 3153600000.0;
1276  }
1277  return 0;
1278 }
1279 
1280 /* *INDENT-OFF* */
1283  .type = VLIB_NODE_TYPE_PROCESS,
1284  .name = "vhost-user-send-interrupt-process",
1285 };
1286 /* *INDENT-ON* */
1287 
1288 static uword
1291 {
1293  vhost_user_intf_t *vui;
1294  struct sockaddr_un sun;
1295  int sockfd;
1296  clib_file_t template = { 0 };
1297  f64 timeout = 3153600000.0 /* 100 years */ ;
1298  uword *event_data = 0;
1299 
1300  sockfd = -1;
1301  sun.sun_family = AF_UNIX;
1303  template.error_function = vhost_user_socket_error;
1304 
1305  while (1)
1306  {
1308  vlib_process_get_events (vm, &event_data);
1309  vec_reset_length (event_data);
1310 
1311  timeout = 3.0;
1312 
1313  /* *INDENT-OFF* */
1314  pool_foreach (vui, vum->vhost_user_interfaces) {
1315 
1316  if (vui->unix_server_index == ~0) { //Nothing to do for server sockets
1317  if (vui->clib_file_index == ~0)
1318  {
1319  if ((sockfd < 0) &&
1320  ((sockfd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0))
1321  {
1322  /*
1323  * 1st time error or new error for this interface,
1324  * spit out the message and record the error
1325  */
1326  if (!vui->sock_errno || (vui->sock_errno != errno))
1327  {
1329  ("Error: Could not open unix socket for %s",
1330  vui->sock_filename);
1331  vui->sock_errno = errno;
1332  }
1333  continue;
1334  }
1335 
1336  /* try to connect */
1337  strncpy (sun.sun_path, (char *) vui->sock_filename,
1338  sizeof (sun.sun_path) - 1);
1339  sun.sun_path[sizeof (sun.sun_path) - 1] = 0;
1340 
1341  /* Avoid hanging VPP if the other end does not accept */
1342  if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0)
1343  clib_unix_warning ("fcntl");
1344 
1345  if (connect (sockfd, (struct sockaddr *) &sun,
1346  sizeof (struct sockaddr_un)) == 0)
1347  {
1348  /* Set the socket to blocking as it was before */
1349  if (fcntl(sockfd, F_SETFL, 0) < 0)
1350  clib_unix_warning ("fcntl2");
1351 
1352  vui->sock_errno = 0;
1353  template.file_descriptor = sockfd;
1354  template.private_data =
1356  template.description = format (0, "vhost user process");
1357  vui->clib_file_index = clib_file_add (&file_main, &template);
1358  vui->num_qid = 2;
1359 
1360  /* This sockfd is considered consumed */
1361  sockfd = -1;
1362  }
1363  else
1364  {
1365  vui->sock_errno = errno;
1366  }
1367  }
1368  else
1369  {
1370  /* check if socket is alive */
1371  int error = 0;
1372  socklen_t len = sizeof (error);
1373  int fd = UNIX_GET_FD(vui->clib_file_index);
1374  int retval =
1375  getsockopt (fd, SOL_SOCKET, SO_ERROR, &error, &len);
1376 
1377  if (retval)
1378  {
1379  vu_log_debug (vui, "getsockopt returned %d", retval);
1381  }
1382  }
1383  }
1384  }
1385  /* *INDENT-ON* */
1386  }
1387  return 0;
1388 }
1389 
1390 /* *INDENT-OFF* */
1392  .function = vhost_user_process,
1393  .type = VLIB_NODE_TYPE_PROCESS,
1394  .name = "vhost-user-process",
1395 };
1396 /* *INDENT-ON* */
1397 
1398 /**
1399  * Disables and reset interface structure.
1400  * It can then be either init again, or removed from used interfaces.
1401  */
1402 static void
1404 {
1405  int q;
1407 
1408  // disconnect interface sockets
1410  vhost_user_update_gso_interface_count (vui, 0 /* delete */ );
1412 
1413  FOR_ALL_VHOST_RX_TXQ (q, vui)
1414  {
1416  }
1417 
1418  if (vui->unix_server_index != ~0)
1419  {
1420  //Close server socket
1422  vui->unix_server_index);
1423  clib_file_del (&file_main, uf);
1424  vui->unix_server_index = ~0;
1425  unlink (vui->sock_filename);
1426  }
1427 
1429  &vui->if_index);
1430 }
1431 
1432 int
1434 {
1436  vhost_user_intf_t *vui;
1437  int rv = 0;
1438  vnet_hw_interface_t *hwif;
1439  u16 qid;
1440 
1441  if (!
1442  (hwif =
1444  || hwif->dev_class_index != vhost_user_device_class.index)
1445  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1446 
1448 
1449  vu_log_debug (vui, "Deleting vhost-user interface %s (instance %d)",
1450  hwif->name, hwif->dev_instance);
1451 
1452  FOR_ALL_VHOST_TXQ (qid, vui)
1453  {
1454  vhost_user_vring_t *txvq = &vui->vrings[qid];
1455 
1456  if ((txvq->mode == VNET_HW_IF_RX_MODE_POLLING) &&
1457  (txvq->thread_index != ~0))
1458  {
1459  vhost_cpu_t *cpu = vec_elt_at_index (vum->cpus, txvq->thread_index);
1460  ASSERT (cpu->polling_q_count != 0);
1461  cpu->polling_q_count--;
1462  }
1463 
1464  if ((vum->ifq_count > 0) &&
1465  ((txvq->mode == VNET_HW_IF_RX_MODE_INTERRUPT) ||
1466  (txvq->mode == VNET_HW_IF_RX_MODE_ADAPTIVE)))
1467  {
1468  vum->ifq_count--;
1469  // Stop the timer if there is no more interrupt interface/queue
1470  if (vum->ifq_count == 0)
1471  {
1475  break;
1476  }
1477  }
1478  }
1479 
1480  // Disable and reset interface
1481  vhost_user_term_if (vui);
1482 
1483  // Reset renumbered iface
1484  if (hwif->dev_instance <
1487 
1488  // Delete ethernet interface
1490 
1491  // free vrings
1492  vec_free (vui->vrings);
1493 
1494  // Back to pool
1495  pool_put (vum->vhost_user_interfaces, vui);
1496 
1497  return rv;
1498 }
1499 
1500 static clib_error_t *
1502 {
1503  vnet_main_t *vnm = vnet_get_main ();
1505  vhost_user_intf_t *vui;
1506 
1508  /* *INDENT-OFF* */
1509  pool_foreach (vui, vum->vhost_user_interfaces) {
1510  vhost_user_delete_if (vnm, vm, vui->sw_if_index);
1511  }
1512  /* *INDENT-ON* */
1514  return 0;
1515 }
1516 
1518 
1519 /**
1520  * Open server unix socket on specified sock_filename.
1521  */
1522 static int
1523 vhost_user_init_server_sock (const char *sock_filename, int *sock_fd)
1524 {
1525  int rv = 0;
1526  struct sockaddr_un un = { };
1527  int fd;
1528  /* create listening socket */
1529  if ((fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
1530  return VNET_API_ERROR_SYSCALL_ERROR_1;
1531 
1532  un.sun_family = AF_UNIX;
1533  strncpy ((char *) un.sun_path, (char *) sock_filename,
1534  sizeof (un.sun_path) - 1);
1535 
1536  /* remove if exists */
1537  unlink ((char *) sock_filename);
1538 
1539  if (bind (fd, (struct sockaddr *) &un, sizeof (un)) == -1)
1540  {
1541  rv = VNET_API_ERROR_SYSCALL_ERROR_2;
1542  goto error;
1543  }
1544 
1545  if (listen (fd, 1) == -1)
1546  {
1547  rv = VNET_API_ERROR_SYSCALL_ERROR_3;
1548  goto error;
1549  }
1550 
1551  *sock_fd = fd;
1552  return 0;
1553 
1554 error:
1555  close (fd);
1556  return rv;
1557 }
1558 
1559 /**
1560  * Create ethernet interface for vhost user interface.
1561  */
1562 static void
1564  vhost_user_intf_t *vui,
1566 {
1568  u8 hwaddr[6];
1570 
1571  /* create hw and sw interface */
1572  if (args->use_custom_mac)
1573  {
1574  clib_memcpy (hwaddr, args->hwaddr, 6);
1575  }
1576  else
1577  {
1578  random_u32 (&vum->random);
1579  clib_memcpy (hwaddr + 2, &vum->random, sizeof (vum->random));
1580  hwaddr[0] = 2;
1581  hwaddr[1] = 0xfe;
1582  }
1583 
1585  (vnm,
1587  vui - vum->vhost_user_interfaces /* device instance */ ,
1588  hwaddr /* ethernet address */ ,
1589  &vui->hw_if_index, 0 /* flag change */ );
1590 
1591  if (error)
1593 }
1594 
1595 /*
1596  * Initialize vui with specified attributes
1597  */
1598 static void
1600  int server_sock_fd, vhost_user_create_if_args_t * args,
1601  u32 * sw_if_index)
1602 {
1603  vnet_sw_interface_t *sw;
1604  int q;
1606  vnet_hw_interface_t *hw;
1607 
1608  hw = vnet_get_hw_interface (vnm, vui->hw_if_index);
1609  sw = vnet_get_hw_sw_interface (vnm, vui->hw_if_index);
1610  if (server_sock_fd != -1)
1611  {
1612  clib_file_t template = { 0 };
1614  template.file_descriptor = server_sock_fd;
1615  template.private_data = vui - vum->vhost_user_interfaces; //hw index
1616  template.description = format (0, "vhost user %d", sw);
1617  vui->unix_server_index = clib_file_add (&file_main, &template);
1618  }
1619  else
1620  {
1621  vui->unix_server_index = ~0;
1622  }
1623 
1624  vui->sw_if_index = sw->sw_if_index;
1625  strncpy (vui->sock_filename, args->sock_filename,
1626  ARRAY_LEN (vui->sock_filename) - 1);
1627  vui->sock_errno = 0;
1628  vui->is_ready = 0;
1629  vui->feature_mask = args->feature_mask;
1630  vui->clib_file_index = ~0;
1631  vui->log_base_addr = 0;
1632  vui->if_index = vui - vum->vhost_user_interfaces;
1633  vui->enable_gso = args->enable_gso;
1634  vui->enable_event_idx = args->enable_event_idx;
1635  vui->enable_packed = args->enable_packed;
1636  /*
1637  * enable_gso takes precedence over configurable feature mask if there
1638  * is a clash.
1639  * if feature mask disables gso, but enable_gso is configured,
1640  * then gso is enable
1641  * if feature mask enables gso, but enable_gso is not configured,
1642  * then gso is enable
1643  *
1644  * if gso is enable via feature mask, it must enable both host and guest
1645  * gso feature mask, we don't support one sided GSO or partial GSO.
1646  */
1647  if ((vui->enable_gso == 0) &&
1650  vui->enable_gso = 1;
1651  vhost_user_update_gso_interface_count (vui, 1 /* add */ );
1653  &vui->if_index, 0);
1654 
1657  vui->num_qid = 2;
1658  for (q = 0; q < vec_len (vui->vrings); q++)
1659  vhost_user_vring_init (vui, q);
1660 
1663 
1664  if (sw_if_index)
1665  *sw_if_index = vui->sw_if_index;
1666 }
1667 
1668 int
1671 {
1672  vhost_user_intf_t *vui = NULL;
1673  u32 sw_if_idx = ~0;
1674  int rv = 0;
1675  int server_sock_fd = -1;
1677  uword *if_index;
1678 
1679  if (args->sock_filename == NULL || !(strlen (args->sock_filename) > 0))
1680  {
1681  return VNET_API_ERROR_INVALID_ARGUMENT;
1682  }
1683 
1684  if_index = mhash_get (&vum->if_index_by_sock_name,
1685  (void *) args->sock_filename);
1686  if (if_index)
1687  {
1688  vui = &vum->vhost_user_interfaces[*if_index];
1689  args->sw_if_index = vui->sw_if_index;
1690  return VNET_API_ERROR_IF_ALREADY_EXISTS;
1691  }
1692 
1693  if (args->is_server)
1694  {
1695  if ((rv =
1697  &server_sock_fd)) != 0)
1698  {
1699  return rv;
1700  }
1701  }
1702 
1703  /* Protect the uninitialized vui from being dispatched by rx/tx */
1706  vhost_user_create_ethernet (vnm, vm, vui, args);
1708 
1709  vhost_user_vui_init (vnm, vui, server_sock_fd, args, &sw_if_idx);
1710  vnet_sw_interface_set_mtu (vnm, vui->sw_if_index, 9000);
1712 
1713  if (args->renumber)
1715 
1716  args->sw_if_index = sw_if_idx;
1717 
1718  // Process node must connect
1720 
1721  return rv;
1722 }
1723 
1724 int
1727 {
1729  vhost_user_intf_t *vui = NULL;
1730  u32 sw_if_idx = ~0;
1731  int server_sock_fd = -1;
1732  int rv = 0;
1733  vnet_hw_interface_t *hwif;
1734  uword *if_index;
1735 
1737  args->sw_if_index))
1738  || hwif->dev_class_index != vhost_user_device_class.index)
1739  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1740 
1741  if (args->sock_filename == NULL || !(strlen (args->sock_filename) > 0))
1742  return VNET_API_ERROR_INVALID_ARGUMENT;
1743 
1745 
1746  /*
1747  * Disallow changing the interface to have the same path name
1748  * as other interface
1749  */
1750  if_index = mhash_get (&vum->if_index_by_sock_name,
1751  (void *) args->sock_filename);
1752  if (if_index && (*if_index != vui->if_index))
1753  return VNET_API_ERROR_IF_ALREADY_EXISTS;
1754 
1755  // First try to open server socket
1756  if (args->is_server)
1758  &server_sock_fd)) != 0)
1759  return rv;
1760 
1761  vhost_user_term_if (vui);
1762  vhost_user_vui_init (vnm, vui, server_sock_fd, args, &sw_if_idx);
1763 
1764  if (args->renumber)
1766 
1767  // Process node must connect
1769 
1770  return rv;
1771 }
1772 
1773 clib_error_t *
1775  unformat_input_t * input,
1776  vlib_cli_command_t * cmd)
1777 {
1778  vnet_main_t *vnm = vnet_get_main ();
1779  unformat_input_t _line_input, *line_input = &_line_input;
1780  clib_error_t *error = NULL;
1781  vhost_user_create_if_args_t args = { 0 };
1782  int rv;
1783 
1784  /* Get a line of input. */
1785  if (!unformat_user (input, unformat_line_input, line_input))
1786  return 0;
1787 
1788  args.feature_mask = (u64) ~ (0ULL);
1789  args.custom_dev_instance = ~0;
1790  /* GSO feature is disable by default */
1792  /* packed-ring feature is disable by default */
1793  args.feature_mask &= ~VIRTIO_FEATURE (VIRTIO_F_RING_PACKED);
1794  /* event_idx feature is disable by default */
1795  args.feature_mask &= ~VIRTIO_FEATURE (VIRTIO_RING_F_EVENT_IDX);
1796 
1797  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1798  {
1799  if (unformat (line_input, "socket %s", &args.sock_filename))
1800  ;
1801  else if (unformat (line_input, "server"))
1802  args.is_server = 1;
1803  else if (unformat (line_input, "gso"))
1804  args.enable_gso = 1;
1805  else if (unformat (line_input, "packed"))
1806  args.enable_packed = 1;
1807  else if (unformat (line_input, "event-idx"))
1808  args.enable_event_idx = 1;
1809  else if (unformat (line_input, "feature-mask 0x%llx",
1810  &args.feature_mask))
1811  ;
1812  else if (unformat (line_input, "hwaddr %U", unformat_ethernet_address,
1813  args.hwaddr))
1814  args.use_custom_mac = 1;
1815  else if (unformat (line_input, "renumber %d",
1816  &args.custom_dev_instance))
1817  args.renumber = 1;
1818  else
1819  {
1820  error = clib_error_return (0, "unknown input `%U'",
1821  format_unformat_error, line_input);
1822  goto done;
1823  }
1824  }
1825 
1826  if ((rv = vhost_user_create_if (vnm, vm, &args)))
1827  {
1828  error = clib_error_return (0, "vhost_user_create_if returned %d", rv);
1829  goto done;
1830  }
1831 
1833  args.sw_if_index);
1834 
1835 done:
1836  vec_free (args.sock_filename);
1837  unformat_free (line_input);
1838 
1839  return error;
1840 }
1841 
1842 clib_error_t *
1844  unformat_input_t * input,
1845  vlib_cli_command_t * cmd)
1846 {
1847  unformat_input_t _line_input, *line_input = &_line_input;
1848  u32 sw_if_index = ~0;
1849  vnet_main_t *vnm = vnet_get_main ();
1850  clib_error_t *error = NULL;
1851 
1852  /* Get a line of input. */
1853  if (!unformat_user (input, unformat_line_input, line_input))
1854  return 0;
1855 
1856  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1857  {
1858  if (unformat (line_input, "sw_if_index %d", &sw_if_index))
1859  ;
1860  else if (unformat
1861  (line_input, "%U", unformat_vnet_sw_interface, vnm,
1862  &sw_if_index))
1863  {
1864  vnet_hw_interface_t *hwif =
1866  if (hwif == NULL ||
1868  {
1869  error = clib_error_return (0, "Not a vhost interface");
1870  goto done;
1871  }
1872  }
1873  else
1874  {
1875  error = clib_error_return (0, "unknown input `%U'",
1876  format_unformat_error, line_input);
1877  goto done;
1878  }
1879  }
1880 
1882 
1883 done:
1884  unformat_free (line_input);
1885 
1886  return error;
1887 }
1888 
1889 int
1891  vhost_user_intf_details_t ** out_vuids)
1892 {
1893  int rv = 0;
1895  vhost_user_intf_t *vui;
1896  vhost_user_intf_details_t *r_vuids = NULL;
1897  vhost_user_intf_details_t *vuid = NULL;
1898  u32 *hw_if_indices = 0;
1900  int i;
1901 
1902  if (!out_vuids)
1903  return -1;
1904 
1906  vec_add1 (hw_if_indices, vui->hw_if_index);
1907 
1908  for (i = 0; i < vec_len (hw_if_indices); i++)
1909  {
1910  hi = vnet_get_hw_interface (vnm, hw_if_indices[i]);
1911  vui = pool_elt_at_index (vum->vhost_user_interfaces, hi->dev_instance);
1912 
1913  vec_add2 (r_vuids, vuid, 1);
1914  vuid->sw_if_index = vui->sw_if_index;
1915  vuid->virtio_net_hdr_sz = vui->virtio_net_hdr_sz;
1916  vuid->features = vui->features;
1917  vuid->num_regions = vui->nregions;
1918  vuid->is_server = vui->unix_server_index != ~0;
1919  vuid->sock_errno = vui->sock_errno;
1920  snprintf ((char *) vuid->sock_filename, sizeof (vuid->sock_filename),
1921  "%s", vui->sock_filename);
1922  memcpy_s (vuid->if_name, sizeof (vuid->if_name), hi->name,
1923  clib_min (vec_len (hi->name), sizeof (vuid->if_name) - 1));
1924  vuid->if_name[sizeof (vuid->if_name) - 1] = 0;
1925  }
1926 
1927  vec_free (hw_if_indices);
1928 
1929  *out_vuids = r_vuids;
1930 
1931  return rv;
1932 }
1933 
1934 static u8 *
1935 format_vhost_user_desc (u8 * s, va_list * args)
1936 {
1937  char *fmt = va_arg (*args, char *);
1938  vhost_user_intf_t *vui = va_arg (*args, vhost_user_intf_t *);
1939  vring_desc_t *desc_table = va_arg (*args, vring_desc_t *);
1940  int idx = va_arg (*args, int);
1941  u32 *mem_hint = va_arg (*args, u32 *);
1942 
1943  s = format (s, fmt, idx, desc_table[idx].addr, desc_table[idx].len,
1944  desc_table[idx].flags, desc_table[idx].next,
1945  pointer_to_uword (map_guest_mem (vui, desc_table[idx].addr,
1946  mem_hint)));
1947  return s;
1948 }
1949 
1950 static void
1952 {
1953  int kickfd = UNIX_GET_FD (vq->kickfd_idx);
1954  int callfd = UNIX_GET_FD (vq->callfd_idx);
1955 
1956  vlib_cli_output (vm, " kickfd %d callfd %d errfd %d\n", kickfd, callfd,
1957  vq->errfd);
1958 }
1959 
1960 static void
1962  int show_descr, int show_verbose)
1963 {
1964  int j;
1965  u32 mem_hint = 0;
1966  u32 idx;
1967  u32 n_entries;
1968  vring_desc_t *desc_table;
1969  vhost_user_vring_t *vq = &vui->vrings[q];
1970 
1971  if (vq->avail && vq->used)
1973  " avail.flags %x avail event idx %u avail.idx %d "
1974  "used.flags %x used event idx %u used.idx %d\n",
1976  vq->avail->idx, vq->used->flags,
1977  vhost_user_used_event_idx (vq), vq->used->idx);
1978 
1979  vhost_user_show_fds (vm, vq);
1980 
1981  if (show_descr)
1982  {
1983  vlib_cli_output (vm, "\n descriptor table:\n");
1985  " slot addr len flags next "
1986  "user_addr\n");
1988  " ===== ================== ===== ====== ===== "
1989  "==================\n");
1990  for (j = 0; j < vq->qsz_mask + 1; j++)
1991  {
1992  desc_table = vq->desc;
1994  " %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n", vui,
1995  desc_table, j, &mem_hint);
1996  if (show_verbose && (desc_table[j].flags & VRING_DESC_F_INDIRECT))
1997  {
1998  n_entries = desc_table[j].len / sizeof (vring_desc_t);
1999  desc_table = map_guest_mem (vui, desc_table[j].addr, &mem_hint);
2000  if (desc_table)
2001  {
2002  for (idx = 0; idx < clib_min (20, n_entries); idx++)
2003  {
2005  (vm, "%U", format_vhost_user_desc,
2006  "> %-4u 0x%016lx %-5u 0x%04x %-5u 0x%016lx\n", vui,
2007  desc_table, idx, &mem_hint);
2008  }
2009  if (n_entries >= 20)
2010  vlib_cli_output (vm, "Skip displaying entries 20...%u\n",
2011  n_entries);
2012  }
2013  }
2014  }
2015  }
2016 }
2017 
2018 static u8 *
2019 format_vhost_user_packed_desc (u8 * s, va_list * args)
2020 {
2021  char *fmt = va_arg (*args, char *);
2022  vhost_user_intf_t *vui = va_arg (*args, vhost_user_intf_t *);
2023  vring_packed_desc_t *desc_table = va_arg (*args, vring_packed_desc_t *);
2024  int idx = va_arg (*args, int);
2025  u32 *mem_hint = va_arg (*args, u32 *);
2026 
2027  s = format (s, fmt, idx, desc_table[idx].addr, desc_table[idx].len,
2028  desc_table[idx].flags, desc_table[idx].id,
2029  pointer_to_uword (map_guest_mem (vui, desc_table[idx].addr,
2030  mem_hint)));
2031  return s;
2032 }
2033 
2034 static u8 *
2036 {
2037  u32 flags = va_arg (*args, u32);
2038  typedef struct
2039  {
2040  u8 value;
2041  char *str;
2042  } event_idx_flags;
2043  static event_idx_flags event_idx_array[] = {
2044 #define _(s,v) { .str = #s, .value = v, },
2046 #undef _
2047  };
2048  u32 num_entries = sizeof (event_idx_array) / sizeof (event_idx_flags);
2049 
2050  if (flags < num_entries)
2051  s = format (s, "%s", event_idx_array[flags].str);
2052  else
2053  s = format (s, "%u", flags);
2054  return s;
2055 }
2056 
2057 static void
2059  int show_descr, int show_verbose)
2060 {
2061  int j;
2062  u32 mem_hint = 0;
2063  u32 idx;
2064  u32 n_entries;
2065  vring_packed_desc_t *desc_table;
2066  vhost_user_vring_t *vq = &vui->vrings[q];
2067  u16 off_wrap, event_idx;
2068 
2069  off_wrap = vq->avail_event->off_wrap;
2070  event_idx = off_wrap & 0x7fff;
2071  vlib_cli_output (vm, " avail_event.flags %U avail_event.off_wrap %u "
2072  "avail event idx %u\n", format_vhost_user_event_idx_flags,
2073  (u32) vq->avail_event->flags, off_wrap, event_idx);
2074 
2075  off_wrap = vq->used_event->off_wrap;
2076  event_idx = off_wrap & 0x7fff;
2077  vlib_cli_output (vm, " used_event.flags %U used_event.off_wrap %u "
2078  "used event idx %u\n", format_vhost_user_event_idx_flags,
2079  (u32) vq->used_event->flags, off_wrap, event_idx);
2080 
2081  vlib_cli_output (vm, " avail wrap counter %u, used wrap counter %u\n",
2083 
2084  vhost_user_show_fds (vm, vq);
2085 
2086  if (show_descr)
2087  {
2088  vlib_cli_output (vm, "\n descriptor table:\n");
2090  " slot addr len flags id "
2091  "user_addr\n");
2093  " ===== ================== ===== ====== ===== "
2094  "==================\n");
2095  for (j = 0; j < vq->qsz_mask + 1; j++)
2096  {
2097  desc_table = vq->packed_desc;
2099  " %-5u 0x%016lx %-5u 0x%04x %-5u 0x%016lx\n", vui,
2100  desc_table, j, &mem_hint);
2101  if (show_verbose && (desc_table[j].flags & VRING_DESC_F_INDIRECT))
2102  {
2103  n_entries = desc_table[j].len >> 4;
2104  desc_table = map_guest_mem (vui, desc_table[j].addr, &mem_hint);
2105  if (desc_table)
2106  {
2107  for (idx = 0; idx < clib_min (20, n_entries); idx++)
2108  {
2111  "> %-4u 0x%016lx %-5u 0x%04x %-5u 0x%016lx\n", vui,
2112  desc_table, idx, &mem_hint);
2113  }
2114  if (n_entries >= 20)
2115  vlib_cli_output (vm, "Skip displaying entries 20...%u\n",
2116  n_entries);
2117  }
2118  }
2119  }
2120  }
2121 }
2122 
2123 clib_error_t *
2125  unformat_input_t * input,
2126  vlib_cli_command_t * cmd)
2127 {
2128  clib_error_t *error = 0;
2129  vnet_main_t *vnm = vnet_get_main ();
2131  vhost_user_intf_t *vui;
2132  u32 hw_if_index, *hw_if_indices = 0;
2134  u16 qid;
2135  int i, j, q;
2136  int show_descr = 0;
2137  int show_verbose = 0;
2138  struct feat_struct
2139  {
2140  u8 bit;
2141  char *str;
2142  };
2143  struct feat_struct *feat_entry;
2144 
2145  static struct feat_struct feat_array[] = {
2146 #define _(s,b) { .str = #s, .bit = b, },
2148 #undef _
2149  {.str = NULL}
2150  };
2151 
2152 #define foreach_protocol_feature \
2153  _(VHOST_USER_PROTOCOL_F_MQ) \
2154  _(VHOST_USER_PROTOCOL_F_LOG_SHMFD)
2155 
2156  static struct feat_struct proto_feat_array[] = {
2157 #define _(s) { .str = #s, .bit = s},
2159 #undef _
2160  {.str = NULL}
2161  };
2162 
2163  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2164  {
2165  if (unformat
2166  (input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
2167  {
2168  hi = vnet_get_hw_interface (vnm, hw_if_index);
2169  if (vhost_user_device_class.index != hi->dev_class_index)
2170  {
2171  error = clib_error_return (0, "unknown input `%U'",
2172  format_unformat_error, input);
2173  goto done;
2174  }
2175  vec_add1 (hw_if_indices, hw_if_index);
2176  }
2177  else if (unformat (input, "descriptors") || unformat (input, "desc"))
2178  show_descr = 1;
2179  else if (unformat (input, "verbose"))
2180  show_verbose = 1;
2181  else
2182  {
2183  error = clib_error_return (0, "unknown input `%U'",
2184  format_unformat_error, input);
2185  goto done;
2186  }
2187  }
2188  if (vec_len (hw_if_indices) == 0)
2189  {
2191  vec_add1 (hw_if_indices, vui->hw_if_index);
2192  }
2193  vlib_cli_output (vm, "Virtio vhost-user interfaces");
2194  vlib_cli_output (vm, "Global:\n coalesce frames %d time %e",
2195  vum->coalesce_frames, vum->coalesce_time);
2196  vlib_cli_output (vm, " Number of rx virtqueues in interrupt mode: %d",
2197  vum->ifq_count);
2198  vlib_cli_output (vm, " Number of GSO interfaces: %d", vum->gso_count);
2199  for (u32 tid = 0; tid <= vlib_num_workers (); tid++)
2200  {
2201  vhost_cpu_t *cpu = vec_elt_at_index (vum->cpus, tid);
2202  vlib_cli_output (vm, " Thread %u: Polling queue count %u", tid,
2203  cpu->polling_q_count);
2204  }
2205 
2206  for (i = 0; i < vec_len (hw_if_indices); i++)
2207  {
2208  hi = vnet_get_hw_interface (vnm, hw_if_indices[i]);
2209  vui = pool_elt_at_index (vum->vhost_user_interfaces, hi->dev_instance);
2210  vlib_cli_output (vm, "Interface: %U (ifindex %d)",
2211  format_vnet_hw_if_index_name, vnm, hw_if_indices[i],
2212  hw_if_indices[i]);
2213  vlib_cli_output (vm, " Number of qids %u", vui->num_qid);
2214  if (vui->enable_gso)
2215  vlib_cli_output (vm, " GSO enable");
2216  if (vui->enable_packed)
2217  vlib_cli_output (vm, " Packed ring enable");
2218  if (vui->enable_event_idx)
2219  vlib_cli_output (vm, " Event index enable");
2220 
2221  vlib_cli_output (vm, "virtio_net_hdr_sz %d\n"
2222  " features mask (0x%llx): \n"
2223  " features (0x%llx): \n",
2224  vui->virtio_net_hdr_sz, vui->feature_mask,
2225  vui->features);
2226 
2227  feat_entry = (struct feat_struct *) &feat_array;
2228  while (feat_entry->str)
2229  {
2230  if (vui->features & (1ULL << feat_entry->bit))
2231  vlib_cli_output (vm, " %s (%d)", feat_entry->str,
2232  feat_entry->bit);
2233  feat_entry++;
2234  }
2235 
2236  vlib_cli_output (vm, " protocol features (0x%llx)",
2237  vui->protocol_features);
2238  feat_entry = (struct feat_struct *) &proto_feat_array;
2239  while (feat_entry->str)
2240  {
2241  if (vui->protocol_features & (1ULL << feat_entry->bit))
2242  vlib_cli_output (vm, " %s (%d)", feat_entry->str,
2243  feat_entry->bit);
2244  feat_entry++;
2245  }
2246 
2247  vlib_cli_output (vm, "\n");
2248 
2249  vlib_cli_output (vm, " socket filename %s type %s errno \"%s\"\n\n",
2250  vui->sock_filename,
2251  (vui->unix_server_index != ~0) ? "server" : "client",
2252  strerror (vui->sock_errno));
2253 
2254  vlib_cli_output (vm, " rx placement: ");
2255 
2256  FOR_ALL_VHOST_TXQ (qid, vui)
2257  {
2258  vhost_user_vring_t *txvq = &vui->vrings[qid];
2259 
2260  if (txvq->qid == -1)
2261  continue;
2262  vlib_cli_output (vm, " thread %d on vring %d, %U\n",
2264  txvq->mode);
2265  }
2266 
2267  vlib_cli_output (vm, " tx placement\n");
2268 
2269  FOR_ALL_VHOST_RXQ (qid, vui)
2270  {
2271  vhost_user_vring_t *rxvq = &vui->vrings[qid];
2272  vnet_hw_if_tx_queue_t *txq;
2273 
2274  if (rxvq->queue_index == ~0)
2275  continue;
2276  txq = vnet_hw_if_get_tx_queue (vnm, rxvq->queue_index);
2277  if (txq->threads)
2278  vlib_cli_output (vm, " threads %U on vring %u: %s\n",
2279  format_bitmap_list, txq->threads, qid,
2280  txq->shared_queue ? "spin-lock" : "lock-free");
2281  }
2282 
2283  vlib_cli_output (vm, "\n");
2284 
2285  vlib_cli_output (vm, " Memory regions (total %d)\n", vui->nregions);
2286 
2287  if (vui->nregions)
2288  {
2290  " region fd guest_phys_addr memory_size userspace_addr mmap_offset mmap_addr\n");
2292  " ====== ===== ================== ================== ================== ================== ==================\n");
2293  }
2294  for (j = 0; j < vui->nregions; j++)
2295  {
2297  " %d %-5d 0x%016lx 0x%016lx 0x%016lx 0x%016lx 0x%016lx\n",
2298  j, vui->region_mmap_fd[j],
2299  vui->regions[j].guest_phys_addr,
2300  vui->regions[j].memory_size,
2301  vui->regions[j].userspace_addr,
2302  vui->regions[j].mmap_offset,
2304  }
2305  FOR_ALL_VHOST_RX_TXQ (q, vui)
2306  {
2307  if (!vui->vrings[q].started)
2308  continue;
2309 
2310  vlib_cli_output (vm, "\n Virtqueue %d (%s%s)\n", q,
2311  (q & 1) ? "RX" : "TX",
2312  vui->vrings[q].enabled ? "" : " disabled");
2313  vlib_cli_output (vm, " global %s queue index %u\n",
2314  (q & 1) ? "RX" : "TX", vui->vrings[q].queue_index);
2315 
2316  vlib_cli_output (
2317  vm,
2318  " qsz %d last_avail_idx %d last_used_idx %d"
2319  " last_kick %u\n",
2320  vui->vrings[q].qsz_mask + 1, vui->vrings[q].last_avail_idx,
2321  vui->vrings[q].last_used_idx, vui->vrings[q].last_kick);
2322 
2324  vhost_user_show_desc_packed (vm, vui, q, show_descr, show_verbose);
2325  else
2326  vhost_user_show_desc (vm, vui, q, show_descr, show_verbose);
2327  }
2328  vlib_cli_output (vm, "\n");
2329  }
2330 done:
2331  vec_free (hw_if_indices);
2332  return error;
2333 }
2334 
2335 /*
2336  * CLI functions
2337  */
2338 
2339 /*?
2340  * Create a vHost User interface. Once created, a new virtual interface
2341  * will exist with the name '<em>VirtualEthernet0/0/x</em>', where '<em>x</em>'
2342  * is the next free index.
2343  *
2344  * There are several parameters associated with a vHost interface:
2345  *
2346  * - <b>socket <socket-filename></b> - Name of the linux socket used by hypervisor
2347  * and VPP to manage the vHost interface. If in '<em>server</em>' mode, VPP will
2348  * create the socket if it does not already exist. If in '<em>client</em>' mode,
2349  * hypervisor will create the socket if it does not already exist. The VPP code
2350  * is indifferent to the file location. However, if SELinux is enabled, then the
2351  * socket needs to be created in '<em>/var/run/vpp/</em>'.
2352  *
2353  * - <b>server</b> - Optional flag to indicate that VPP should be the server for
2354  * the linux socket. If not provided, VPP will be the client. In '<em>server</em>'
2355  * mode, the VM can be reset without tearing down the vHost Interface. In
2356  * '<em>client</em>' mode, VPP can be reset without bringing down the VM and
2357  * tearing down the vHost Interface.
2358  *
2359  * - <b>feature-mask <hex></b> - Optional virtio/vhost feature set negotiated at
2360  * startup. <b>This is intended for degugging only.</b> It is recommended that this
2361  * parameter not be used except by experienced users. By default, all supported
2362  * features will be advertised. Otherwise, provide the set of features desired.
2363  * - 0x000008000 (15) - VIRTIO_NET_F_MRG_RXBUF
2364  * - 0x000020000 (17) - VIRTIO_NET_F_CTRL_VQ
2365  * - 0x000200000 (21) - VIRTIO_NET_F_GUEST_ANNOUNCE
2366  * - 0x000400000 (22) - VIRTIO_NET_F_MQ
2367  * - 0x004000000 (26) - VHOST_F_LOG_ALL
2368  * - 0x008000000 (27) - VIRTIO_F_ANY_LAYOUT
2369  * - 0x010000000 (28) - VIRTIO_F_INDIRECT_DESC
2370  * - 0x040000000 (30) - VHOST_USER_F_PROTOCOL_FEATURES
2371  * - 0x100000000 (32) - VIRTIO_F_VERSION_1
2372  *
2373  * - <b>hwaddr <mac-addr></b> - Optional ethernet address, can be in either
2374  * X:X:X:X:X:X unix or X.X.X cisco format.
2375  *
2376  * - <b>renumber <dev_instance></b> - Optional parameter which allows the instance
2377  * in the name to be specified. If instance already exists, name will be used
2378  * anyway and multiple instances will have the same name. Use with caution.
2379  *
2380  * @cliexpar
2381  * Example of how to create a vhost interface with VPP as the client and all features enabled:
2382  * @cliexstart{create vhost-user socket /var/run/vpp/vhost1.sock}
2383  * VirtualEthernet0/0/0
2384  * @cliexend
2385  * Example of how to create a vhost interface with VPP as the server and with just
2386  * multiple queues enabled:
2387  * @cliexstart{create vhost-user socket /var/run/vpp/vhost2.sock server feature-mask 0x40400000}
2388  * VirtualEthernet0/0/1
2389  * @cliexend
2390  * Once the vHost interface is created, enable the interface using:
2391  * @cliexcmd{set interface state VirtualEthernet0/0/0 up}
2392 ?*/
2393 /* *INDENT-OFF* */
2395  .path = "create vhost-user",
2396  .short_help = "create vhost-user socket <socket-filename> [server] "
2397  "[feature-mask <hex>] [hwaddr <mac-addr>] [renumber <dev_instance>] [gso] "
2398  "[packed] [event-idx]",
2399  .function = vhost_user_connect_command_fn,
2400  .is_mp_safe = 1,
2401 };
2402 /* *INDENT-ON* */
2403 
2404 /*?
2405  * Delete a vHost User interface using the interface name or the
2406  * software interface index. Use the '<em>show interface</em>'
2407  * command to determine the software interface index. On deletion,
2408  * the linux socket will not be deleted.
2409  *
2410  * @cliexpar
2411  * Example of how to delete a vhost interface by name:
2412  * @cliexcmd{delete vhost-user VirtualEthernet0/0/1}
2413  * Example of how to delete a vhost interface by software interface index:
2414  * @cliexcmd{delete vhost-user sw_if_index 1}
2415 ?*/
2416 /* *INDENT-OFF* */
2418  .path = "delete vhost-user",
2419  .short_help = "delete vhost-user {<interface> | sw_if_index <sw_idx>}",
2420  .function = vhost_user_delete_command_fn,
2421 };
2422 
2423 /*?
2424  * Display the attributes of a single vHost User interface (provide interface
2425  * name), multiple vHost User interfaces (provide a list of interface names seperated
2426  * by spaces) or all Vhost User interfaces (omit an interface name to display all
2427  * vHost interfaces).
2428  *
2429  * @cliexpar
2430  * @parblock
2431  * Example of how to display a vhost interface:
2432  * @cliexstart{show vhost-user VirtualEthernet0/0/0}
2433  * Virtio vhost-user interfaces
2434  * Global:
2435  * coalesce frames 32 time 1e-3
2436  * Interface: VirtualEthernet0/0/0 (ifindex 1)
2437  * virtio_net_hdr_sz 12
2438  * features mask (0xffffffffffffffff):
2439  * features (0x50408000):
2440  * VIRTIO_NET_F_MRG_RXBUF (15)
2441  * VIRTIO_NET_F_MQ (22)
2442  * VIRTIO_F_INDIRECT_DESC (28)
2443  * VHOST_USER_F_PROTOCOL_FEATURES (30)
2444  * protocol features (0x3)
2445  * VHOST_USER_PROTOCOL_F_MQ (0)
2446  * VHOST_USER_PROTOCOL_F_LOG_SHMFD (1)
2447  *
2448  * socket filename /var/run/vpp/vhost1.sock type client errno "Success"
2449  *
2450  * rx placement:
2451  * thread 1 on vring 1
2452  * thread 1 on vring 5
2453  * thread 2 on vring 3
2454  * thread 2 on vring 7
2455  * tx placement: spin-lock
2456  * thread 0 on vring 0
2457  * thread 1 on vring 2
2458  * thread 2 on vring 0
2459  *
2460  * Memory regions (total 2)
2461  * region fd guest_phys_addr memory_size userspace_addr mmap_offset mmap_addr
2462  * ====== ===== ================== ================== ================== ================== ==================
2463  * 0 60 0x0000000000000000 0x00000000000a0000 0x00002aaaaac00000 0x0000000000000000 0x00002aab2b400000
2464  * 1 61 0x00000000000c0000 0x000000003ff40000 0x00002aaaaacc0000 0x00000000000c0000 0x00002aababcc0000
2465  *
2466  * Virtqueue 0 (TX)
2467  * qsz 256 last_avail_idx 0 last_used_idx 0
2468  * avail.flags 1 avail.idx 128 used.flags 1 used.idx 0
2469  * kickfd 62 callfd 64 errfd -1
2470  *
2471  * Virtqueue 1 (RX)
2472  * qsz 256 last_avail_idx 0 last_used_idx 0
2473  * avail.flags 1 avail.idx 0 used.flags 1 used.idx 0
2474  * kickfd 65 callfd 66 errfd -1
2475  *
2476  * Virtqueue 2 (TX)
2477  * qsz 256 last_avail_idx 0 last_used_idx 0
2478  * avail.flags 1 avail.idx 128 used.flags 1 used.idx 0
2479  * kickfd 63 callfd 70 errfd -1
2480  *
2481  * Virtqueue 3 (RX)
2482  * qsz 256 last_avail_idx 0 last_used_idx 0
2483  * avail.flags 1 avail.idx 0 used.flags 1 used.idx 0
2484  * kickfd 72 callfd 74 errfd -1
2485  *
2486  * Virtqueue 4 (TX disabled)
2487  * qsz 256 last_avail_idx 0 last_used_idx 0
2488  * avail.flags 1 avail.idx 0 used.flags 1 used.idx 0
2489  * kickfd 76 callfd 78 errfd -1
2490  *
2491  * Virtqueue 5 (RX disabled)
2492  * qsz 256 last_avail_idx 0 last_used_idx 0
2493  * avail.flags 1 avail.idx 0 used.flags 1 used.idx 0
2494  * kickfd 80 callfd 82 errfd -1
2495  *
2496  * Virtqueue 6 (TX disabled)
2497  * qsz 256 last_avail_idx 0 last_used_idx 0
2498  * avail.flags 1 avail.idx 0 used.flags 1 used.idx 0
2499  * kickfd 84 callfd 86 errfd -1
2500  *
2501  * Virtqueue 7 (RX disabled)
2502  * qsz 256 last_avail_idx 0 last_used_idx 0
2503  * avail.flags 1 avail.idx 0 used.flags 1 used.idx 0
2504  * kickfd 88 callfd 90 errfd -1
2505  *
2506  * @cliexend
2507  *
2508  * The optional '<em>descriptors</em>' parameter will display the same output as
2509  * the previous example but will include the descriptor table for each queue.
2510  * The output is truncated below:
2511  * @cliexstart{show vhost-user VirtualEthernet0/0/0 descriptors}
2512  * Virtio vhost-user interfaces
2513  * Global:
2514  * coalesce frames 32 time 1e-3
2515  * Interface: VirtualEthernet0/0/0 (ifindex 1)
2516  * virtio_net_hdr_sz 12
2517  * features mask (0xffffffffffffffff):
2518  * features (0x50408000):
2519  * VIRTIO_NET_F_MRG_RXBUF (15)
2520  * VIRTIO_NET_F_MQ (22)
2521  * :
2522  * Virtqueue 0 (TX)
2523  * qsz 256 last_avail_idx 0 last_used_idx 0
2524  * avail.flags 1 avail.idx 128 used.flags 1 used.idx 0
2525  * kickfd 62 callfd 64 errfd -1
2526  *
2527  * descriptor table:
2528  * id addr len flags next user_addr
2529  * ===== ================== ===== ====== ===== ==================
2530  * 0 0x0000000010b6e974 2060 0x0002 1 0x00002aabbc76e974
2531  * 1 0x0000000010b6e034 2060 0x0002 2 0x00002aabbc76e034
2532  * 2 0x0000000010b6d6f4 2060 0x0002 3 0x00002aabbc76d6f4
2533  * 3 0x0000000010b6cdb4 2060 0x0002 4 0x00002aabbc76cdb4
2534  * 4 0x0000000010b6c474 2060 0x0002 5 0x00002aabbc76c474
2535  * 5 0x0000000010b6bb34 2060 0x0002 6 0x00002aabbc76bb34
2536  * 6 0x0000000010b6b1f4 2060 0x0002 7 0x00002aabbc76b1f4
2537  * 7 0x0000000010b6a8b4 2060 0x0002 8 0x00002aabbc76a8b4
2538  * 8 0x0000000010b69f74 2060 0x0002 9 0x00002aabbc769f74
2539  * 9 0x0000000010b69634 2060 0x0002 10 0x00002aabbc769634
2540  * 10 0x0000000010b68cf4 2060 0x0002 11 0x00002aabbc768cf4
2541  * :
2542  * 249 0x0000000000000000 0 0x0000 250 0x00002aab2b400000
2543  * 250 0x0000000000000000 0 0x0000 251 0x00002aab2b400000
2544  * 251 0x0000000000000000 0 0x0000 252 0x00002aab2b400000
2545  * 252 0x0000000000000000 0 0x0000 253 0x00002aab2b400000
2546  * 253 0x0000000000000000 0 0x0000 254 0x00002aab2b400000
2547  * 254 0x0000000000000000 0 0x0000 255 0x00002aab2b400000
2548  * 255 0x0000000000000000 0 0x0000 32768 0x00002aab2b400000
2549  *
2550  * Virtqueue 1 (RX)
2551  * qsz 256 last_avail_idx 0 last_used_idx 0
2552  * :
2553  * @cliexend
2554  * @endparblock
2555 ?*/
2556 /* *INDENT-OFF* */
2558  .path = "show vhost-user",
2559  .short_help = "show vhost-user [<interface> [<interface> [..]]] "
2560  "[[descriptors] [verbose]]",
2561  .function = show_vhost_user_command_fn,
2562 };
2563 /* *INDENT-ON* */
2564 
2565 
2566 static clib_error_t *
2568 {
2570 
2571  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2572  {
2573  if (unformat (input, "coalesce-frames %d", &vum->coalesce_frames))
2574  ;
2575  else if (unformat (input, "coalesce-time %f", &vum->coalesce_time))
2576  ;
2577  else if (unformat (input, "dont-dump-memory"))
2578  vum->dont_dump_vhost_user_memory = 1;
2579  else
2580  return clib_error_return (0, "unknown input `%U'",
2581  format_unformat_error, input);
2582  }
2583 
2584  return 0;
2585 }
2586 
2587 /* vhost-user { ... } configuration. */
2588 VLIB_CONFIG_FUNCTION (vhost_user_config, "vhost-user");
2589 
2590 void
2592 {
2594  vhost_user_intf_t *vui;
2595 
2596  if (vum->dont_dump_vhost_user_memory)
2597  {
2599  unmap_all_mem_regions (vui);
2600  }
2601 }
2602 
2603 /*
2604  * fd.io coding-style-patch-verification: ON
2605  *
2606  * Local Variables:
2607  * eval: (c-set-style "gnu")
2608  * End:
2609  */
vec_reset_length
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
Definition: vec_bootstrap.h:194
vlib.h
clib_spinlock_init
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:65
clib_file::file_descriptor
u32 file_descriptor
Definition: file.h:54
vhost_user_update_gso_interface_count
static_always_inline void vhost_user_update_gso_interface_count(vhost_user_intf_t *vui, u8 add)
Definition: vhost_user_inline.h:385
VNET_HW_IF_RXQ_THREAD_ANY
#define VNET_HW_IF_RXQ_THREAD_ANY
Definition: interface.h:598
vhost_user_term_if
static void vhost_user_term_if(vhost_user_intf_t *vui)
Disables and reset interface structure.
Definition: vhost_user.c:1403
vhost_user_create_if_args_t::is_server
u8 is_server
Definition: vhost_user.h:108
vhost_user_create_if_args_t::custom_dev_instance
u32 custom_dev_instance
Definition: vhost_user.h:105
VHOST_USER_MSG_HDR_SZ
#define VHOST_USER_MSG_HDR_SZ
Definition: vhost_user.h:24
vhost_user_send_call
static_always_inline void vhost_user_send_call(vlib_main_t *vm, vhost_user_intf_t *vui, vhost_user_vring_t *vq)
Definition: vhost_user_inline.h:364
vhost_user_vring_t
Definition: vhost_user.h:180
vhost_user_vring_t::mode
u32 mode
Definition: vhost_user.h:219
vlib_num_workers
static u32 vlib_num_workers()
Definition: threads.h:333
unformat_ethernet_address
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
Definition: format.c:233
vhost_user_intf_t::nregions
u32 nregions
Definition: vhost_user.h:258
file_main
clib_file_main_t file_main
Definition: main.c:63
vlib_worker_thread_barrier_release
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1375
vhost_user_intf_t::region_guest_addr_lo
u64 region_guest_addr_lo[VHOST_MEMORY_MAX_NREGIONS]
Definition: vhost_user.h:261
format_vhost_user_packed_desc
static u8 * format_vhost_user_packed_desc(u8 *s, va_list *args)
Definition: vhost_user.c:2019
unformat_user
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
thread_index
u32 thread_index
Definition: nat44_ei_hairpinning.c:495
vhost_user_inline.h
VNET_HW_IF_RX_MODE_ADAPTIVE
@ VNET_HW_IF_RX_MODE_ADAPTIVE
Definition: interface.h:58
vnet_sw_interface_set_mtu
void vnet_sw_interface_set_mtu(vnet_main_t *vnm, u32 sw_if_index, u32 mtu)
Definition: interface.c:706
vnet_sw_interface_t
Definition: interface.h:869
vhost_user_vui_init
static void vhost_user_vui_init(vnet_main_t *vnm, vhost_user_intf_t *vui, int server_sock_fd, vhost_user_create_if_args_t *args, u32 *sw_if_index)
Definition: vhost_user.c:1599
VHOST_USER_SET_VRING_KICK
@ VHOST_USER_SET_VRING_KICK
Definition: vhost_user.h:155
VHOST_VRING_F_LOG
#define VHOST_VRING_F_LOG
Definition: vhost_user.h:40
vhost_user_intf_t::enable_event_idx
u8 enable_event_idx
Definition: vhost_user.h:287
VNET_HW_INTERFACE_CAP_SUPPORTS_L4_TX_CKSUM
#define VNET_HW_INTERFACE_CAP_SUPPORTS_L4_TX_CKSUM
Definition: interface.h:555
vnet_hw_interface_t::caps
vnet_hw_interface_capabilities_t caps
Definition: interface.h:645
vhost_user_intf_details_t::if_name
u8 if_name[64]
Definition: vhost_user.h:360
clib_memcpy
#define clib_memcpy(d, s, n)
Definition: string.h:197
vhost_user_intf_t::features
u64 features
Definition: vhost_user.h:253
foreach_virtio_net_features
@ foreach_virtio_net_features
Definition: virtio_std.h:63
vnet_interface_name_renumber
int vnet_interface_name_renumber(u32 sw_if_index, u32 new_show_dev_instance)
Definition: interface.c:1474
vring_used_t::flags
u16 flags
Definition: virtio_std.h:117
vhost_user_vring_t::avail_wrap_counter
u16 avail_wrap_counter
Definition: vhost_user.h:230
vhost_user_thread_placement
static_always_inline void vhost_user_thread_placement(vhost_user_intf_t *vui, u32 qid)
Definition: vhost_user.c:244
vhost_user_intf_t::hw_if_index
u32 hw_if_index
Definition: vhost_user.h:250
vhost_user_dump_ifs
int vhost_user_dump_ifs(vnet_main_t *vnm, vlib_main_t *vm, vhost_user_intf_details_t **out_vuids)
Definition: vhost_user.c:1890
vhost_user_main_t::ifq_count
u32 ifq_count
Definition: vhost_user.h:349
VHOST_MEMORY_MAX_NREGIONS
#define VHOST_MEMORY_MAX_NREGIONS
Definition: vhost_user.h:23
vnet_hw_if_set_rx_queue_mode
int vnet_hw_if_set_rx_queue_mode(vnet_main_t *vnm, u32 queue_index, vnet_hw_if_rx_mode mode)
Definition: rx_queue.c:167
f
vlib_frame_t * f
Definition: interface_output.c:1098
pointer_to_uword
static uword pointer_to_uword(const void *p)
Definition: types.h:131
unformat_line_input
unformat_function_t unformat_line_input
Definition: format.h:275
vhost_user_show_fds
static void vhost_user_show_fds(vlib_main_t *vm, vhost_user_vring_t *vq)
Definition: vhost_user.c:1951
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:549
vhost_user_show_desc_packed
static void vhost_user_show_desc_packed(vlib_main_t *vm, vhost_user_intf_t *vui, int q, int show_descr, int show_verbose)
Definition: vhost_user.c:2058
vhost_user_avail_event_idx
static_always_inline u16 vhost_user_avail_event_idx(vhost_user_vring_t *vq)
Definition: vhost_user_inline.h:284
vhost_user_create_if_args_t::enable_gso
u8 enable_gso
Definition: vhost_user.h:109
vhost_user_main_t
Definition: vhost_user.h:332
vhost_user_device_class
vnet_device_class_t vhost_user_device_class
vhost_user_tx_thread_placement
static_always_inline void vhost_user_tx_thread_placement(vhost_user_intf_t *vui, u32 qid)
Definition: vhost_user.c:120
vhost_user_socket_error
static clib_error_t * vhost_user_socket_error(clib_file_t *uf)
Definition: vhost_user.c:1112
next
u16 * next
Definition: nat44_ei_out2in.c:718
memcpy_s
__clib_export errno_t memcpy_s(void *__restrict__ dest, rsize_t dmax, const void *__restrict__ src, rsize_t n)
copy src to dest, at most n bytes, up to dmax
Definition: string.c:120
vlib_log_register_class
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:339
vhost_user_intf_t::log_base_addr
void * log_base_addr
Definition: vhost_user.h:279
stop_timer
static void stop_timer(wg_peer_t *peer, u32 timer_id)
Definition: wireguard_timer.c:30
vhost_user_process_node
static vlib_node_registration_t vhost_user_process_node
(constructor) VLIB_REGISTER_NODE (vhost_user_process_node)
Definition: vhost_user.c:1391
clib_error_return
#define clib_error_return(e, args...)
Definition: error.h:99
vhost_user_vring_t::thread_index
u32 thread_index
Definition: vhost_user.h:234
u8
#define u8
Padding.
Definition: clib.h:121
vlib_cli_command_t::path
char * path
Definition: cli.h:96
clib_file::read_function
clib_file_function_t * read_function
Definition: file.h:67
VHOST_USER_SET_LOG_FD
@ VHOST_USER_SET_LOG_FD
Definition: vhost_user.h:150
vnet_hw_if_tx_queue_assign_thread
void vnet_hw_if_tx_queue_assign_thread(vnet_main_t *vnm, u32 queue_index, u32 thread_index)
Definition: tx_queue.c:109
vhost_user_create_if_args_t
Definition: vhost_user.h:101
u16
unsigned short u16
Definition: types.h:57
mode
vl_api_tunnel_mode_t mode
Definition: gre.api:48
vhost_user_callfd_read_ready
static clib_error_t * vhost_user_callfd_read_ready(clib_file_t *uf)
Definition: vhost_user.c:233
clib_file::private_data
u64 private_data
Definition: file.h:64
vhost_user_intf_t::sock_errno
int sock_errno
Definition: vhost_user.h:248
pool_put
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
mhash_get
static uword * mhash_get(mhash_t *h, const void *key)
Definition: mhash.h:110
VNET_HW_IF_RX_MODE_POLLING
@ VNET_HW_IF_RX_MODE_POLLING
Definition: interface.h:56
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
vhost_user_config
static clib_error_t * vhost_user_config(vlib_main_t *vm, unformat_input_t *input)
Definition: vhost_user.c:2567
vhost_user_vring_t::started
u8 started
Definition: vhost_user.h:206
VIRTIO_FEATURE
#define VIRTIO_FEATURE(X)
Definition: virtio_std.h:67
VNET_HW_INTERFACE_FLAG_LINK_UP
@ VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:509
vhost_user_main_t::coalesce_time
f64 coalesce_time
Definition: vhost_user.h:339
VNET_HW_INTERFACE_CLASS
VNET_HW_INTERFACE_CLASS(vhost_interface_class, static)
vhost_user_create_if_args_t::enable_packed
u8 enable_packed
Definition: vhost_user.h:110
hi
vl_api_ip4_address_t hi
Definition: arp.api:37
vhost_user_intf_details_t::is_server
u8 is_server
Definition: vhost_user.h:364
clib_error_report
#define clib_error_report(e)
Definition: error.h:113
unformat_input_t
struct _unformat_input_t unformat_input_t
vhost_user_create_if_args_t::use_custom_mac
u8 use_custom_mac
Definition: vhost_user.h:112
vnet_hw_interface_t::dev_instance
u32 dev_instance
Definition: interface.h:660
addr
vhost_vring_addr_t addr
Definition: vhost_user.h:130
r
vnet_hw_if_output_node_runtime_t * r
Definition: interface_output.c:1089
vhost_user_intf_t::log_size
u64 log_size
Definition: vhost_user.h:280
vhost_user_vring_t::avail_event
vring_desc_event_t * avail_event
Definition: vhost_user.h:195
vlib_frame_t
Definition: node.h:372
vnet_hw_if_tx_queue_unassign_thread
void vnet_hw_if_tx_queue_unassign_thread(vnet_main_t *vnm, u32 queue_index, u32 thread_index)
Definition: tx_queue.c:124
vlib_process_signal_event
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:1019
VHOST_USER_NONE
@ VHOST_USER_NONE
Definition: vhost_user.h:143
clib_memcpy_fast
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
mhash_init_c_string
static void mhash_init_c_string(mhash_t *h, uword n_value_bytes)
Definition: mhash.h:78
vhost_cpu_t
Definition: vhost_user.h:315
vhost_user_socksvr_accept_ready
static clib_error_t * vhost_user_socksvr_accept_ready(clib_file_t *uf)
Definition: vhost_user.c:1127
vhost_user_intf_details_t::virtio_net_hdr_sz
u32 virtio_net_hdr_sz
Definition: vhost_user.h:362
vhost_user_input_node
vlib_node_registration_t vhost_user_input_node
(constructor) VLIB_REGISTER_NODE (vhost_user_input_node)
Definition: vhost_user_input.c:1450
ethernet.h
clib_unix_warning
#define clib_unix_warning(format, args...)
Definition: error.h:68
VHOST_USER_SET_VRING_NUM
@ VHOST_USER_SET_VRING_NUM
Definition: vhost_user.h:151
error
Definition: cJSON.c:88
format_bitmap_list
__clib_export u8 * format_bitmap_list(u8 *s, va_list *args)
Format a bitmap as a list.
Definition: bitmap.c:143
vhost_user_intf_details_t::sock_filename
u8 sock_filename[256]
Definition: vhost_user.h:365
VHOST_USER_GET_PROTOCOL_FEATURES
@ VHOST_USER_GET_PROTOCOL_FEATURES
Definition: vhost_user.h:158
VHOST_USER_SET_LOG_BASE
@ VHOST_USER_SET_LOG_BASE
Definition: vhost_user.h:149
FOR_ALL_VHOST_TXQ
#define FOR_ALL_VHOST_TXQ(qid, vui)
Definition: vhost_user.h:290
random_u32
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
VHOST_VRING_IDX_RX
#define VHOST_VRING_IDX_RX(qid)
Definition: vhost_user.h:33
vhost_user_intf_t::sw_if_index
u32 sw_if_index
Definition: vhost_user.h:250
VHOST_USER_VRING_NOFD_MASK
#define VHOST_USER_VRING_NOFD_MASK
Definition: vhost_user.h:36
VNET_HW_INTERFACE_CAP_SUPPORTS_TX_TCP_CKSUM
@ VNET_HW_INTERFACE_CAP_SUPPORTS_TX_TCP_CKSUM
Definition: interface.h:524
VLIB_CONFIG_FUNCTION
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:181
unformat
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
FOR_ALL_VHOST_RX_TXQ
#define FOR_ALL_VHOST_RX_TXQ(qid, vui)
Definition: vhost_user.h:294
vhost_user_show_desc
static void vhost_user_show_desc(vlib_main_t *vm, vhost_user_intf_t *vui, int q, int show_descr, int show_verbose)
Definition: vhost_user.c:1961
vhost_user_intf_t::regions
vhost_user_memory_region_t regions[VHOST_MEMORY_MAX_NREGIONS]
Definition: vhost_user.h:259
vnet_sw_interface_t::sw_if_index
u32 sw_if_index
Definition: interface.h:876
VHOST_USER_SET_PROTOCOL_FEATURES
@ VHOST_USER_SET_PROTOCOL_FEATURES
Definition: vhost_user.h:159
vlib_process_get_events
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type,...
Definition: node_funcs.h:583
vlib_thread_main_t::n_vlib_mains
u32 n_vlib_mains
Definition: threads.h:262
vhost_user_is_packed_ring_supported
static_always_inline u64 vhost_user_is_packed_ring_supported(vhost_user_intf_t *vui)
Definition: vhost_user_inline.h:252
vhost_user_unmap_all
void vhost_user_unmap_all(void)
Definition: vhost_user.c:2591
pool_foreach
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
vhost_user_intf_details_t::sock_errno
int sock_errno
Definition: vhost_user.h:367
vhost_user_vring_t::qid
i16 qid
Definition: vhost_user.h:227
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
unformat_free
static void unformat_free(unformat_input_t *i)
Definition: format.h:155
format_vnet_hw_if_rx_mode
format_function_t format_vnet_hw_if_rx_mode
Definition: interface_funcs.h:453
len
u8 len
Definition: ip_types.api:103
feature.h
vec_add2
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:644
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
vring_desc_t
Definition: virtio_std.h:93
VHOST_USER_EVENT_STOP_TIMER
#define VHOST_USER_EVENT_STOP_TIMER
Definition: vhost_user.h:238
vring_avail_t::flags
u16 flags
Definition: virtio_std.h:103
VRING_DESC_F_AVAIL
#define VRING_DESC_F_AVAIL
Definition: virtio_std.h:75
vec_elt_at_index
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Definition: vec_bootstrap.h:203
vnet_get_hw_interface
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface_funcs.h:44
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
clib_file
Definition: file.h:51
FEATURE_VIRTIO_NET_F_HOST_GUEST_TSO_FEATURE_BITS
#define FEATURE_VIRTIO_NET_F_HOST_GUEST_TSO_FEATURE_BITS
Definition: vhost_user.h:96
FOR_ALL_VHOST_RXQ
#define FOR_ALL_VHOST_RXQ(qid, vui)
Definition: vhost_user.h:292
vlib_worker_thread_barrier_sync
#define vlib_worker_thread_barrier_sync(X)
Definition: threads.h:173
VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO
@ VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO
Definition: interface.h:537
ARRAY_LEN
#define ARRAY_LEN(x)
Definition: clib.h:70
unformat_check_input
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:163
vlib_config_function_runtime_t
Definition: init.h:68
rx_queue_funcs.h
vec_validate_aligned
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:534
vnet_get_sup_hw_interface_api_visible_or_null
static vnet_hw_interface_t * vnet_get_sup_hw_interface_api_visible_or_null(vnet_main_t *vnm, u32 sw_if_index)
Definition: interface_funcs.h:101
foreach_protocol_feature
#define foreach_protocol_feature
static_always_inline
#define static_always_inline
Definition: clib.h:112
vhost_user_connect_command_fn
clib_error_t * vhost_user_connect_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vhost_user.c:1774
show_vhost_user_command_fn
clib_error_t * show_vhost_user_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vhost_user.c:2124
VRING_DESC_F_INDIRECT
#define VRING_DESC_F_INDIRECT
Definition: virtio_std.h:73
vhost_user_vring_t::log_guest_addr
u64 log_guest_addr
Definition: vhost_user.h:216
VHOST_USER_PROTOCOL_F_LOG_SHMFD
#define VHOST_USER_PROTOCOL_F_LOG_SHMFD
Definition: vhost_user.h:39
vhost_user_connect_command
static vlib_cli_command_t vhost_user_connect_command
(constructor) VLIB_CLI_COMMAND (vhost_user_connect_command)
Definition: vhost_user.c:2394
vu_log_err
#define vu_log_err(dev, f,...)
Definition: vhost_user.h:58
vu_log_warn
#define vu_log_warn(dev, f,...)
Definition: vhost_user.h:52
uword
u64 uword
Definition: types.h:112
format_vnet_hw_if_index_name
format_function_t format_vnet_hw_if_index_name
Definition: interface_funcs.h:454
map_user_mem
static_always_inline void * map_user_mem(vhost_user_intf_t *vui, uword addr)
Definition: vhost_user_inline.h:156
vnet_hw_interface_t::dev_class_index
u32 dev_class_index
Definition: interface.h:659
vnet_hw_if_update_runtime_data
void vnet_hw_if_update_runtime_data(vnet_main_t *vnm, u32 hw_if_index)
Definition: runtime.c:58
show_vhost_user_command
static vlib_cli_command_t show_vhost_user_command
(constructor) VLIB_CLI_COMMAND (show_vhost_user_command)
Definition: vhost_user.c:2557
vhost_user_used_event_idx
static_always_inline u16 vhost_user_used_event_idx(vhost_user_vring_t *vq)
Definition: vhost_user_inline.h:292
vhost_user_update_iface_state
static_always_inline void vhost_user_update_iface_state(vhost_user_intf_t *vui)
Definition: vhost_user.c:216
VNET_HW_IF_RX_MODE_INTERRUPT
@ VNET_HW_IF_RX_MODE_INTERRUPT
Definition: interface.h:57
vhost_user_vring_t::last_used_idx
u16 last_used_idx
Definition: vhost_user.h:185
vhost_user_main_t::coalesce_frames
u32 coalesce_frames
Definition: vhost_user.h:338
vhost_user_vring_t::packed_desc
vring_packed_desc_t * packed_desc
Definition: vhost_user.h:190
f64
double f64
Definition: types.h:142
vnet_hw_if_get_tx_queue
static_always_inline vnet_hw_if_tx_queue_t * vnet_hw_if_get_tx_queue(vnet_main_t *vnm, u32 queue_index)
Definition: tx_queue_funcs.h:23
vhost_user_intf_details_t::features
u64 features
Definition: vhost_user.h:363
clib_spinlock_free
static void clib_spinlock_free(clib_spinlock_t *p)
Definition: lock.h:72
vring_desc_t::len
u32 len
Definition: virtio_std.h:96
format_unformat_error
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
pool_get
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:255
vhost_user_intf_t::clib_file_index
u32 clib_file_index
Definition: vhost_user.h:246
vhost_user_vring_t::int_deadline
f64 int_deadline
Definition: vhost_user.h:205
vec_validate
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment)
Definition: vec.h:523
vhost_user_intf_t::vrings
vhost_user_vring_t * vrings
Definition: vhost_user.h:266
vhost_user_vring_t::last_avail_idx
u16 last_avail_idx
Definition: vhost_user.h:184
VLIB_CLI_COMMAND
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:163
vnet_hw_if_rx_queue_set_int_pending
static_always_inline void vnet_hw_if_rx_queue_set_int_pending(vnet_main_t *vnm, u32 queue_index)
Definition: rx_queue_funcs.h:52
VHOST_USER_SET_VRING_BASE
@ VHOST_USER_SET_VRING_BASE
Definition: vhost_user.h:153
vhost_user_intf_t::is_ready
u32 is_ready
Definition: vhost_user.h:243
VHOST_USER_SET_FEATURES
@ VHOST_USER_SET_FEATURES
Definition: vhost_user.h:145
clib_file_main_t::file_pool
clib_file_t * file_pool
Definition: file.h:88
unformat_vnet_hw_interface
unformat_function_t unformat_vnet_hw_interface
Definition: interface_funcs.h:463
vhost_cpu_t::polling_q_count
u32 polling_q_count
Definition: vhost_user.h:329
vhost_user_create_if_args_t::enable_event_idx
u8 enable_event_idx
Definition: vhost_user.h:111
VRING_USED_F_NO_NOTIFY
#define VRING_USED_F_NO_NOTIFY
Definition: virtio_std.h:90
clib_min
#define clib_min(x, y)
Definition: clib.h:342
VHOST_USER_SET_OWNER
@ VHOST_USER_SET_OWNER
Definition: vhost_user.h:146
CLIB_CACHE_LINE_BYTES
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:58
vhost_user_vring_t::callfd_idx
u32 callfd_idx
Definition: vhost_user.h:214
fmt
int cJSON_bool fmt
Definition: cJSON.h:160
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
vlib_cli_output
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:716
vhost_user_main_t::cpus
vhost_cpu_t * cpus
Per-CPU data for vhost-user.
Definition: vhost_user.h:343
VHOST_USER_PROTOCOL_F_MQ
#define VHOST_USER_PROTOCOL_F_MQ
Definition: vhost_user.h:38
vnet_hw_if_set_rx_queue_file_index
void vnet_hw_if_set_rx_queue_file_index(vnet_main_t *vnm, u32 queue_index, u32 file_index)
Definition: rx_queue.c:144
vhost_user_vring_t::desc_user_addr
uword desc_user_addr
Definition: vhost_user.h:202
vhost_user_intf_ready
static_always_inline int vhost_user_intf_ready(vhost_user_intf_t *vui)
Returns whether at least one TX and one RX vring are enabled.
Definition: vhost_user.c:204
vhost_user_intf_t::region_mmap_addr
void * region_mmap_addr[VHOST_MEMORY_MAX_NREGIONS]
Definition: vhost_user.h:260
vhost_user_vring_t::desc
vring_desc_t * desc
Definition: vhost_user.h:189
vhost_user_vring_t::avail
vring_avail_t * avail
Definition: vhost_user.h:194
vhost_user_vring_t::used_user_addr
uword used_user_addr
Definition: vhost_user.h:203
VHOST_USER_GET_VRING_BASE
@ VHOST_USER_GET_VRING_BASE
Definition: vhost_user.h:154
vhost_user_main_t::gso_count
u32 gso_count
Definition: vhost_user.h:355
vhost_user_intf_t::enable_gso
u8 enable_gso
Definition: vhost_user.h:282
vhost_user_vring_t::used_event
vring_desc_event_t * used_event
Definition: vhost_user.h:200
VHOST_VRING_INIT_MQ_PAIR_SZ
#define VHOST_VRING_INIT_MQ_PAIR_SZ
Definition: vhost_user.h:25
vnet_hw_interface_t
Definition: interface.h:638
vnet_main_t
Definition: vnet.h:76
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
vhost_user_process
static uword vhost_user_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: vhost_user.c:1289
vhost_user_intf_t::if_index
uword if_index
Definition: vhost_user.h:249
vring_avail_t
Definition: virtio_std.h:101
vhost_user_vring_t::log_used
u8 log_used
Definition: vhost_user.h:208
vhost_user_intf_t::admin_up
u32 admin_up
Definition: vhost_user.h:244
VHOST_USER_EVENT_START_TIMER
#define VHOST_USER_EVENT_START_TIMER
Definition: vhost_user.h:237
get_huge_page_size
static long get_huge_page_size(int fd)
Definition: vhost_user.c:66
event_idx
#define event_idx
Definition: tls_async.c:41
vhost_user_intf_t::virtio_net_hdr_sz
int virtio_net_hdr_sz
Definition: vhost_user.h:276
vhost_user_vring_t::enabled
u8 enabled
Definition: vhost_user.h:207
u64
unsigned long u64
Definition: types.h:89
format_vnet_sw_if_index_name
format_function_t format_vnet_sw_if_index_name
Definition: interface_funcs.h:458
unformat_vnet_sw_interface
unformat_function_t unformat_vnet_sw_interface
Definition: interface_funcs.h:462
vlib_process_wait_for_event_or_clock
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
Definition: node_funcs.h:755
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
vhost_user_main_t::show_dev_instance_by_real_dev_instance
u32 * show_dev_instance_by_real_dev_instance
Definition: vhost_user.h:337
clib_file_del
static void clib_file_del(clib_file_main_t *um, clib_file_t *f)
Definition: file.h:109
vhost_user_main
vhost_user_main_t vhost_user_main
Definition: vhost_user.c:56
vnet_get_hw_sw_interface
static vnet_sw_interface_t * vnet_get_hw_sw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface_funcs.h:72
VLIB_BUFFER_PRE_DATA_SIZE
#define VLIB_BUFFER_PRE_DATA_SIZE
Definition: buffer.h:51
VHOST_USER_RESET_OWNER
@ VHOST_USER_RESET_OWNER
Definition: vhost_user.h:147
u32
unsigned int u32
Definition: types.h:88
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
ethernet_delete_interface
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:393
vlib_thread_main_t
Definition: threads.h:243
vhost_user_create_if_args_t::feature_mask
u64 feature_mask
Definition: vhost_user.h:104
vhost_user_delete_command
static vlib_cli_command_t vhost_user_delete_command
(constructor) VLIB_CLI_COMMAND (vhost_user_delete_command)
Definition: vhost_user.c:2417
vhost_user_kickfd_read_ready
static clib_error_t * vhost_user_kickfd_read_ready(clib_file_t *uf)
Definition: vhost_user.c:256
vhost_user_vring_init
static_always_inline void vhost_user_vring_init(vhost_user_intf_t *vui, u32 qid)
Definition: vhost_user.c:295
vhost_user_vring_t::used_wrap_counter
u16 used_wrap_counter
Definition: vhost_user.h:229
vhost_user_intf_t::sock_filename
char sock_filename[256]
Definition: vhost_user.h:247
vec_foreach
#define vec_foreach(var, vec)
Vector iterator.
Definition: vec_bootstrap.h:213
vhost_user_main_t::mtu_bytes
u32 mtu_bytes
Definition: vhost_user.h:335
vhost_user_intf_t::region_guest_addr_hi
u64 region_guest_addr_hi[VHOST_MEMORY_MAX_NREGIONS]
Definition: vhost_user.h:262
VLIB_NODE_TYPE_PROCESS
@ VLIB_NODE_TYPE_PROCESS
Definition: node.h:84
clib_error_return_unix
#define clib_error_return_unix(e, args...)
Definition: error.h:102
vring_used_t::idx
u16 idx
Definition: virtio_std.h:118
vhost_user_intf_t::protocol_features
u64 protocol_features
Definition: vhost_user.h:255
vnet_hw_if_tx_queue_t
Definition: interface.h:602
clib_file_add
static uword clib_file_add(clib_file_main_t *um, clib_file_t *template)
Definition: file.h:96
vhost_user_init
static clib_error_t * vhost_user_init(vlib_main_t *vm)
Definition: vhost_user.c:1165
value
u8 value
Definition: qos.api:54
vhost_user_send_interrupt_process
static uword vhost_user_send_interrupt_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: vhost_user.c:1200
vhost_user_modify_if
int vhost_user_modify_if(vnet_main_t *vnm, vlib_main_t *vm, vhost_user_create_if_args_t *args)
Definition: vhost_user.c:1725
vhost_user_vring_close
static_always_inline void vhost_user_vring_close(vhost_user_intf_t *vui, u32 qid)
Definition: vhost_user.c:324
foreach_virtio_event_idx_flags
@ foreach_virtio_event_idx_flags
Definition: virtio_std.h:86
now
f64 now
Definition: nat44_ei_out2in.c:710
vhost_user_intf_t::enable_packed
u8 enable_packed
Definition: vhost_user.h:285
vnet_hw_if_tx_queue_t::shared_queue
u8 shared_queue
Definition: interface.h:604
vhost_user_intf_t::unix_server_index
u32 unix_server_index
Definition: vhost_user.h:245
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vlib_main_t
Definition: main.h:102
vlib_get_n_threads
static u32 vlib_get_n_threads()
Definition: global_funcs.h:23
vnet_hw_if_register_rx_queue
u32 vnet_hw_if_register_rx_queue(vnet_main_t *vnm, u32 hw_if_index, u32 queue_id, u32 thread_index)
Definition: rx_queue.c:64
VHOST_VRING_MAX_MQ_PAIR_SZ
#define VHOST_VRING_MAX_MQ_PAIR_SZ
Definition: vhost_user.h:32
VLIB_INITS
#define VLIB_INITS(...)
Definition: init.h:352
vhost_user_intf_t
Definition: vhost_user.h:240
vlib_get_main
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
vhost_user_intf_details_t::num_regions
u32 num_regions
Definition: vhost_user.h:366
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
vnet_hw_interface_set_flags
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:513
unix.h
rt
vnet_interface_output_runtime_t * rt
Definition: interface_output.c:419
vhost_user.h
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
format_vhost_user_desc
static u8 * format_vhost_user_desc(u8 *s, va_list *args)
Definition: vhost_user.c:1935
unmap_all_mem_regions
static void unmap_all_mem_regions(vhost_user_intf_t *vui)
Definition: vhost_user.c:74
vnet_hw_if_tx_queue_t::threads
clib_bitmap_t * threads
Definition: interface.h:612
map_guest_mem
static_always_inline void * map_guest_mem(vhost_user_intf_t *vui, uword addr, u32 *hint)
Definition: vhost_user_inline.h:21
vhost_user_init_server_sock
static int vhost_user_init_server_sock(const char *sock_filename, int *sock_fd)
Open server unix socket on specified sock_filename.
Definition: vhost_user.c:1523
VHOST_USER_SET_VRING_ENABLE
@ VHOST_USER_SET_VRING_ENABLE
Definition: vhost_user.h:161
vhost_user_intf_t::feature_mask
u64 feature_mask
Definition: vhost_user.h:254
vhost_user_vring_t::vring_lock
clib_spinlock_t vring_lock
Definition: vhost_user.h:209
i
int i
Definition: flowhash_template.h:376
VNET_HW_INTERFACE_CAP_SUPPORTS_TX_UDP_CKSUM
@ VNET_HW_INTERFACE_CAP_SUPPORTS_TX_UDP_CKSUM
Definition: interface.h:525
format_vhost_user_event_idx_flags
static u8 * format_vhost_user_event_idx_flags(u8 *s, va_list *args)
Definition: vhost_user.c:2035
UNIX_GET_FD
#define UNIX_GET_FD(unixfd_idx)
Definition: vhost_user.h:65
vhost_user_vring_t::kickfd_idx
u32 kickfd_idx
Definition: vhost_user.h:215
vhost_user_create_if_args_t::sock_filename
char * sock_filename
Definition: vhost_user.h:103
vhost_user_rx_thread_placement
static_always_inline void vhost_user_rx_thread_placement(vhost_user_intf_t *vui, u32 qid)
Unassign existing interface/queue to thread mappings and re-assign new interface/queue to thread mapp...
Definition: vhost_user.c:166
clib_warning
#define clib_warning(format, args...)
Definition: error.h:59
vlib_process_suspend_time_is_zero
static uword vlib_process_suspend_time_is_zero(f64 dt)
Returns TRUE if a process suspend time is less than 10us.
Definition: node_funcs.h:474
devices.h
vu_log_debug
#define vu_log_debug(dev, f,...)
Definition: vhost_user.h:45
vhost_user_create_if_args_t::sw_if_index
u32 sw_if_index
Definition: vhost_user.h:115
VHOST_USER_GET_FEATURES
@ VHOST_USER_GET_FEATURES
Definition: vhost_user.h:144
VNET_HW_INTERFACE_CAP_SUPPORTS_INT_MODE
@ VNET_HW_INTERFACE_CAP_SUPPORTS_INT_MODE
Definition: interface.h:550
vhost_user_create_ethernet
static void vhost_user_create_ethernet(vnet_main_t *vnm, vlib_main_t *vm, vhost_user_intf_t *vui, vhost_user_create_if_args_t *args)
Create ethernet interface for vhost user interface.
Definition: vhost_user.c:1563
vhost_user_main_t::vhost_user_interfaces
vhost_user_intf_t * vhost_user_interfaces
Definition: vhost_user.h:336
vhost_user_delete_if
int vhost_user_delete_if(vnet_main_t *vnm, vlib_main_t *vm, u32 sw_if_index)
Definition: vhost_user.c:1433
vnet_hw_interface_t::name
u8 * name
Definition: interface.h:678
rv
int __clib_unused rv
Definition: application.c:491
vhost_user_intf_t::region_mmap_fd
u32 region_mmap_fd[VHOST_MEMORY_MAX_NREGIONS]
Definition: vhost_user.h:263
tx_queue_funcs.h
vhost_user_if_disconnect
static_always_inline void vhost_user_if_disconnect(vhost_user_intf_t *vui)
Definition: vhost_user.c:363
vhost_user_vring_t::used
vring_used_t * used
Definition: vhost_user.h:199
vhost_user_main_t::log_default
vlib_log_class_t log_default
Definition: vhost_user.h:352
vlib_time_now
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:327
vhost_user_intf_details_t::sw_if_index
u32 sw_if_index
Definition: vhost_user.h:361
VLIB_MAIN_LOOP_EXIT_FUNCTION
#define VLIB_MAIN_LOOP_EXIT_FUNCTION(x)
Definition: init.h:177
vlib_node_runtime_t
Definition: node.h:454
VHOST_USER_GET_QUEUE_NUM
@ VHOST_USER_GET_QUEUE_NUM
Definition: vhost_user.h:160
VHOST_USER_SET_VRING_ERR
@ VHOST_USER_SET_VRING_ERR
Definition: vhost_user.h:157
vnet_hw_if_get_rx_queue_thread_index
static_always_inline u32 vnet_hw_if_get_rx_queue_thread_index(vnet_main_t *vnm, u32 queue_index)
Definition: rx_queue_funcs.h:92
vlib_cli_command_t
Definition: cli.h:92
vnet_hw_if_register_tx_queue
u32 vnet_hw_if_register_tx_queue(vnet_main_t *vnm, u32 hw_if_index, u32 queue_id)
Definition: tx_queue.c:35
vlib_get_thread_main
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:56
VHOST_USER_SET_VRING_CALL
@ VHOST_USER_SET_VRING_CALL
Definition: vhost_user.h:156
vhost_user_intf_t::is_any_layout
int is_any_layout
Definition: vhost_user.h:277
vhost_user_main_t::dont_dump_vhost_user_memory
int dont_dump_vhost_user_memory
Definition: vhost_user.h:340
sw_if_index
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
vhost_user_intf_t::num_qid
u32 num_qid
Definition: vhost_user.h:274
vhost_user_vring_t::qsz_mask
u16 qsz_mask
Definition: vhost_user.h:183
vhost_user_set_operation_mode
void vhost_user_set_operation_mode(vhost_user_intf_t *vui, vhost_user_vring_t *txvq)
Definition: vhost_user.c:385
vhost_user_main_t::random
u32 random
Pseudo random iterator.
Definition: vhost_user.h:346
vhost_user_vring_t::errfd
int errfd
Definition: vhost_user.h:213
vhost_user_intf_details_t
Definition: vhost_user.h:358
vring_avail_t::idx
u16 idx
Definition: virtio_std.h:104
vhost_user_socket_read
static clib_error_t * vhost_user_socket_read(clib_file_t *uf)
Definition: vhost_user.c:411
mhash_set_mem
__clib_export uword mhash_set_mem(mhash_t *h, void *key, uword *new_value, uword *old_value)
Definition: mhash.c:264
mhash_unset
__clib_export uword mhash_unset(mhash_t *h, void *key, uword *old_value)
Definition: mhash.c:346
vhost_user_send_interrupt_node
vlib_node_registration_t vhost_user_send_interrupt_node
(constructor) VLIB_REGISTER_NODE (vhost_user_send_interrupt_node)
Definition: vhost_user.c:53
vhost_user_exit
static clib_error_t * vhost_user_exit(vlib_main_t *vm)
Definition: vhost_user.c:1501
vhost_user_vring_t::last_kick
u16 last_kick
Definition: vhost_user.h:231
VHOST_USER_SET_MEM_TABLE
@ VHOST_USER_SET_MEM_TABLE
Definition: vhost_user.h:148
ethernet_register_interface
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
vhost_user_create_if_args_t::renumber
u8 renumber
Definition: vhost_user.h:107
vhost_user_vring_t::avail_user_addr
uword avail_user_addr
Definition: vhost_user.h:204
vnet_hw_if_set_input_node
void vnet_hw_if_set_input_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: rx_queue.c:157
UNFORMAT_END_OF_INPUT
#define UNFORMAT_END_OF_INPUT
Definition: format.h:137
vhost_user_vring_t::queue_index
u32 queue_index
Definition: vhost_user.h:233
vhost_user_create_if_args_t::hwaddr
u8 hwaddr[6]
Definition: vhost_user.h:106
VNET_HW_IF_RX_MODE_UNKNOWN
@ VNET_HW_IF_RX_MODE_UNKNOWN
Definition: interface.h:55
vhost_user_create_if
int vhost_user_create_if(vnet_main_t *vnm, vlib_main_t *vm, vhost_user_create_if_args_t *args)
Definition: vhost_user.c:1669
vhost_user_main_t::if_index_by_sock_name
mhash_t if_index_by_sock_name
Definition: vhost_user.h:334
VHOST_USER_SET_VRING_ADDR
@ VHOST_USER_SET_VRING_ADDR
Definition: vhost_user.h:152
vhost_cpu_t::rx_buffers_len
u32 rx_buffers_len
Definition: vhost_user.h:317
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
random_default_seed
static uword random_default_seed(void)
Default random seed (unix/linux user-mode)
Definition: random.h:91
vring_used_t
Definition: virtio_std.h:115
vhost_user_vring_t::n_since_last_int
u16 n_since_last_int
Definition: vhost_user.h:186
un
vl_api_address_union_t un
Definition: ip_types.api:98
flags
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
vhost_user_delete_command_fn
clib_error_t * vhost_user_delete_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vhost_user.c:1843