vhost: migrate to use device infra for worker thread assignment, rx-mode.
[vpp.git] / src / vnet / devices / virtio / vhost-user.c
1 /*
2  *------------------------------------------------------------------
3  * vhost.c - vhost-user
4  *
5  * Copyright (c) 2014 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/ip/ip.h>
37
38 #include <vnet/ethernet/ethernet.h>
39 #include <vnet/devices/devices.h>
40 #include <vnet/feature/feature.h>
41
42 #include <vnet/devices/virtio/vhost-user.h>
43
44 /**
45  * @file
46  * @brief vHost User Device Driver.
47  *
48  * This file contains the source code for vHost User interface.
49  */
50
51
52 #define VHOST_USER_DEBUG_SOCKET 0
53 #define VHOST_DEBUG_VQ 0
54
55 #if VHOST_USER_DEBUG_SOCKET == 1
56 #define DBG_SOCK(args...) clib_warning(args);
57 #else
58 #define DBG_SOCK(args...)
59 #endif
60
61 #if VHOST_DEBUG_VQ == 1
62 #define DBG_VQ(args...) clib_warning(args);
63 #else
64 #define DBG_VQ(args...)
65 #endif
66
67 /*
68  * When an RX queue is down but active, received packets
69  * must be discarded. This value controls up to how many
70  * packets will be discarded during each round.
71  */
72 #define VHOST_USER_DOWN_DISCARD_COUNT 256
73
74 /*
75  * When the number of available buffers gets under this threshold,
76  * RX node will start discarding packets.
77  */
78 #define VHOST_USER_RX_BUFFER_STARVATION 32
79
80 /*
81  * On the receive side, the host should free descriptors as soon
82  * as possible in order to avoid TX drop in the VM.
83  * This value controls the number of copy operations that are stacked
84  * before copy is done for all and descriptors are given back to
85  * the guest.
86  * The value 64 was obtained by testing (48 and 128 were not as good).
87  */
88 #define VHOST_USER_RX_COPY_THRESHOLD 64
89
90 #define UNIX_GET_FD(unixfd_idx) \
91     (unixfd_idx != ~0) ? \
92         pool_elt_at_index (unix_main.file_pool, \
93                            unixfd_idx)->file_descriptor : -1;
94
95 #define foreach_virtio_trace_flags \
96   _ (SIMPLE_CHAINED, 0, "Simple descriptor chaining") \
97   _ (SINGLE_DESC,  1, "Single descriptor packet") \
98   _ (INDIRECT, 2, "Indirect descriptor") \
99   _ (MAP_ERROR, 4, "Memory mapping error")
100
101 typedef enum
102 {
103 #define _(n,i,s) VIRTIO_TRACE_F_##n,
104   foreach_virtio_trace_flags
105 #undef _
106 } virtio_trace_flag_t;
107
108 vlib_node_registration_t vhost_user_input_node;
109
110 #define foreach_vhost_user_tx_func_error      \
111   _(NONE, "no error")  \
112   _(NOT_READY, "vhost vring not ready")  \
113   _(DOWN, "vhost interface is down")  \
114   _(PKT_DROP_NOBUF, "tx packet drops (no available descriptors)")  \
115   _(PKT_DROP_NOMRG, "tx packet drops (cannot merge descriptors)")  \
116   _(MMAP_FAIL, "mmap failure") \
117   _(INDIRECT_OVERFLOW, "indirect descriptor table overflow")
118
119 typedef enum
120 {
121 #define _(f,s) VHOST_USER_TX_FUNC_ERROR_##f,
122   foreach_vhost_user_tx_func_error
123 #undef _
124     VHOST_USER_TX_FUNC_N_ERROR,
125 } vhost_user_tx_func_error_t;
126
127 static char *vhost_user_tx_func_error_strings[] = {
128 #define _(n,s) s,
129   foreach_vhost_user_tx_func_error
130 #undef _
131 };
132
133 #define foreach_vhost_user_input_func_error      \
134   _(NO_ERROR, "no error")  \
135   _(NO_BUFFER, "no available buffer")  \
136   _(MMAP_FAIL, "mmap failure")  \
137   _(INDIRECT_OVERFLOW, "indirect descriptor overflows table")  \
138   _(UNDERSIZED_FRAME, "undersized ethernet frame received (< 14 bytes)") \
139   _(FULL_RX_QUEUE, "full rx queue (possible driver tx drop)")
140
141 typedef enum
142 {
143 #define _(f,s) VHOST_USER_INPUT_FUNC_ERROR_##f,
144   foreach_vhost_user_input_func_error
145 #undef _
146     VHOST_USER_INPUT_FUNC_N_ERROR,
147 } vhost_user_input_func_error_t;
148
149 static char *vhost_user_input_func_error_strings[] = {
150 #define _(n,s) s,
151   foreach_vhost_user_input_func_error
152 #undef _
153 };
154
155 /* *INDENT-OFF* */
156 static vhost_user_main_t vhost_user_main = {
157   .mtu_bytes = 1518,
158 };
159
160 VNET_HW_INTERFACE_CLASS (vhost_interface_class, static) = {
161   .name = "vhost-user",
162 };
163 /* *INDENT-ON* */
164
165 static u8 *
166 format_vhost_user_interface_name (u8 * s, va_list * args)
167 {
168   u32 i = va_arg (*args, u32);
169   u32 show_dev_instance = ~0;
170   vhost_user_main_t *vum = &vhost_user_main;
171
172   if (i < vec_len (vum->show_dev_instance_by_real_dev_instance))
173     show_dev_instance = vum->show_dev_instance_by_real_dev_instance[i];
174
175   if (show_dev_instance != ~0)
176     i = show_dev_instance;
177
178   s = format (s, "VirtualEthernet0/0/%d", i);
179   return s;
180 }
181
182 static int
183 vhost_user_name_renumber (vnet_hw_interface_t * hi, u32 new_dev_instance)
184 {
185   // FIXME: check if the new dev instance is already used
186   vhost_user_main_t *vum = &vhost_user_main;
187   vec_validate_init_empty (vum->show_dev_instance_by_real_dev_instance,
188                            hi->dev_instance, ~0);
189
190   vum->show_dev_instance_by_real_dev_instance[hi->dev_instance] =
191     new_dev_instance;
192
193   DBG_SOCK ("renumbered vhost-user interface dev_instance %d to %d",
194             hi->dev_instance, new_dev_instance);
195
196   return 0;
197 }
198
199 static_always_inline void *
200 map_guest_mem (vhost_user_intf_t * vui, uword addr, u32 * hint)
201 {
202   int i = *hint;
203   if (PREDICT_TRUE ((vui->regions[i].guest_phys_addr <= addr) &&
204                     ((vui->regions[i].guest_phys_addr +
205                       vui->regions[i].memory_size) > addr)))
206     {
207       return (void *) (vui->region_mmap_addr[i] + addr -
208                        vui->regions[i].guest_phys_addr);
209     }
210 #if __SSE4_2__
211   __m128i rl, rh, al, ah, r;
212   al = _mm_set1_epi64x (addr + 1);
213   ah = _mm_set1_epi64x (addr);
214
215   rl = _mm_loadu_si128 ((__m128i *) & vui->region_guest_addr_lo[0]);
216   rl = _mm_cmpgt_epi64 (al, rl);
217   rh = _mm_loadu_si128 ((__m128i *) & vui->region_guest_addr_hi[0]);
218   rh = _mm_cmpgt_epi64 (rh, ah);
219   r = _mm_and_si128 (rl, rh);
220
221   rl = _mm_loadu_si128 ((__m128i *) & vui->region_guest_addr_lo[2]);
222   rl = _mm_cmpgt_epi64 (al, rl);
223   rh = _mm_loadu_si128 ((__m128i *) & vui->region_guest_addr_hi[2]);
224   rh = _mm_cmpgt_epi64 (rh, ah);
225   r = _mm_blend_epi16 (r, _mm_and_si128 (rl, rh), 0x22);
226
227   rl = _mm_loadu_si128 ((__m128i *) & vui->region_guest_addr_lo[4]);
228   rl = _mm_cmpgt_epi64 (al, rl);
229   rh = _mm_loadu_si128 ((__m128i *) & vui->region_guest_addr_hi[4]);
230   rh = _mm_cmpgt_epi64 (rh, ah);
231   r = _mm_blend_epi16 (r, _mm_and_si128 (rl, rh), 0x44);
232
233   rl = _mm_loadu_si128 ((__m128i *) & vui->region_guest_addr_lo[6]);
234   rl = _mm_cmpgt_epi64 (al, rl);
235   rh = _mm_loadu_si128 ((__m128i *) & vui->region_guest_addr_hi[6]);
236   rh = _mm_cmpgt_epi64 (rh, ah);
237   r = _mm_blend_epi16 (r, _mm_and_si128 (rl, rh), 0x88);
238
239   r = _mm_shuffle_epi8 (r, _mm_set_epi64x (0, 0x0e060c040a020800));
240   i = __builtin_ctzll (_mm_movemask_epi8 (r) |
241                        (1 << VHOST_MEMORY_MAX_NREGIONS));
242
243   if (i < vui->nregions)
244     {
245       *hint = i;
246       return (void *) (vui->region_mmap_addr[i] + addr -
247                        vui->regions[i].guest_phys_addr);
248     }
249
250 #else
251   for (i = 0; i < vui->nregions; i++)
252     {
253       if ((vui->regions[i].guest_phys_addr <= addr) &&
254           ((vui->regions[i].guest_phys_addr + vui->regions[i].memory_size) >
255            addr))
256         {
257           *hint = i;
258           return (void *) (vui->region_mmap_addr[i] + addr -
259                            vui->regions[i].guest_phys_addr);
260         }
261     }
262 #endif
263   DBG_VQ ("failed to map guest mem addr %llx", addr);
264   *hint = 0;
265   return 0;
266 }
267
268 static inline void *
269 map_user_mem (vhost_user_intf_t * vui, uword addr)
270 {
271   int i;
272   for (i = 0; i < vui->nregions; i++)
273     {
274       if ((vui->regions[i].userspace_addr <= addr) &&
275           ((vui->regions[i].userspace_addr + vui->regions[i].memory_size) >
276            addr))
277         {
278           return (void *) (vui->region_mmap_addr[i] + addr -
279                            vui->regions[i].userspace_addr);
280         }
281     }
282   return 0;
283 }
284
285 static long
286 get_huge_page_size (int fd)
287 {
288   struct statfs s;
289   fstatfs (fd, &s);
290   return s.f_bsize;
291 }
292
293 static void
294 unmap_all_mem_regions (vhost_user_intf_t * vui)
295 {
296   int i, r;
297   for (i = 0; i < vui->nregions; i++)
298     {
299       if (vui->region_mmap_addr[i] != (void *) -1)
300         {
301
302           long page_sz = get_huge_page_size (vui->region_mmap_fd[i]);
303
304           ssize_t map_sz = (vui->regions[i].memory_size +
305                             vui->regions[i].mmap_offset +
306                             page_sz - 1) & ~(page_sz - 1);
307
308           r =
309             munmap (vui->region_mmap_addr[i] - vui->regions[i].mmap_offset,
310                     map_sz);
311
312           DBG_SOCK
313             ("unmap memory region %d addr 0x%lx len 0x%lx page_sz 0x%x", i,
314              vui->region_mmap_addr[i], map_sz, page_sz);
315
316           vui->region_mmap_addr[i] = (void *) -1;
317
318           if (r == -1)
319             {
320               clib_warning ("failed to unmap memory region (errno %d)",
321                             errno);
322             }
323           close (vui->region_mmap_fd[i]);
324         }
325     }
326   vui->nregions = 0;
327 }
328
329 static void
330 vhost_user_tx_thread_placement (vhost_user_intf_t * vui)
331 {
332   //Let's try to assign one queue to each thread
333   u32 qid = 0;
334   u32 thread_index = 0;
335   vui->use_tx_spinlock = 0;
336   while (1)
337     {
338       for (qid = 0; qid < VHOST_VRING_MAX_N / 2; qid++)
339         {
340           vhost_user_vring_t *rxvq = &vui->vrings[VHOST_VRING_IDX_RX (qid)];
341           if (!rxvq->started || !rxvq->enabled)
342             continue;
343
344           vui->per_cpu_tx_qid[thread_index] = qid;
345           thread_index++;
346           if (thread_index == vlib_get_thread_main ()->n_vlib_mains)
347             return;
348         }
349       //We need to loop, meaning the spinlock has to be used
350       vui->use_tx_spinlock = 1;
351       if (thread_index == 0)
352         {
353           //Could not find a single valid one
354           for (thread_index = 0;
355                thread_index < vlib_get_thread_main ()->n_vlib_mains;
356                thread_index++)
357             {
358               vui->per_cpu_tx_qid[thread_index] = 0;
359             }
360           return;
361         }
362     }
363 }
364
365 /**
366  * @brief Unassign existing interface/queue to thread mappings and re-assign
367  * new interface/queue to thread mappings
368  */
369 static void
370 vhost_user_rx_thread_placement ()
371 {
372   vhost_user_main_t *vum = &vhost_user_main;
373   vhost_user_intf_t *vui;
374   vhost_user_vring_t *txvq;
375   vnet_main_t *vnm = vnet_get_main ();
376   u32 qid;
377   int rv;
378   u16 *queue;
379
380   // Scrap all existing mappings for all interfaces/queues
381   /* *INDENT-OFF* */
382   pool_foreach (vui, vum->vhost_user_interfaces, {
383       vec_foreach (queue, vui->rx_queues)
384         {
385           rv = vnet_hw_interface_unassign_rx_thread (vnm, vui->hw_if_index,
386                                                      *queue);
387           if (rv)
388             clib_warning ("Warning: unable to unassign interface %d, "
389                           "queue %d: rc=%d", vui->hw_if_index, *queue, rv);
390         }
391       vec_reset_length (vui->rx_queues);
392   });
393   /* *INDENT-ON* */
394
395   // Create the rx_queues for all interfaces
396   /* *INDENT-OFF* */
397   pool_foreach (vui, vum->vhost_user_interfaces, {
398       for (qid = 0; qid < VHOST_VRING_MAX_N / 2; qid++)
399         {
400           txvq = &vui->vrings[VHOST_VRING_IDX_TX (qid)];
401           if (txvq->started)
402             {
403               if (txvq->mode == VNET_HW_INTERFACE_RX_MODE_UNKNOWN)
404                 /* Set polling as the default */
405                 txvq->mode = VNET_HW_INTERFACE_RX_MODE_POLLING;
406               vec_add1 (vui->rx_queues, qid);
407             }
408         }
409   });
410   /* *INDENT-ON* */
411
412   // Assign new mappings for all interfaces/queues
413   /* *INDENT-OFF* */
414   pool_foreach (vui, vum->vhost_user_interfaces, {
415       vnet_hw_interface_set_input_node (vnm, vui->hw_if_index,
416                                         vhost_user_input_node.index);
417       vec_foreach (queue, vui->rx_queues)
418         {
419           vnet_hw_interface_assign_rx_thread (vnm, vui->hw_if_index, *queue,
420                                               ~0);
421           txvq = &vui->vrings[VHOST_VRING_IDX_TX (*queue)];
422           rv = vnet_hw_interface_set_rx_mode (vnm, vui->hw_if_index, *queue,
423                                               txvq->mode);
424           if (rv)
425             clib_warning ("Warning: unable to set rx mode for interface %d, "
426                           "queue %d: rc=%d", vui->hw_if_index, *queue, rv);
427         }
428   });
429   /* *INDENT-ON* */
430 }
431
432 /** @brief Returns whether at least one TX and one RX vring are enabled */
433 int
434 vhost_user_intf_ready (vhost_user_intf_t * vui)
435 {
436   int i, found[2] = { };        //RX + TX
437
438   for (i = 0; i < VHOST_VRING_MAX_N; i++)
439     if (vui->vrings[i].started && vui->vrings[i].enabled)
440       found[i & 1] = 1;
441
442   return found[0] && found[1];
443 }
444
445 static void
446 vhost_user_update_iface_state (vhost_user_intf_t * vui)
447 {
448   /* if we have pointers to descriptor table, go up */
449   int is_up = vhost_user_intf_ready (vui);
450   if (is_up != vui->is_up)
451     {
452       DBG_SOCK ("interface %d %s", vui->sw_if_index,
453                 is_up ? "ready" : "down");
454       vnet_hw_interface_set_flags (vnet_get_main (), vui->hw_if_index,
455                                    is_up ? VNET_HW_INTERFACE_FLAG_LINK_UP :
456                                    0);
457       vui->is_up = is_up;
458     }
459   vhost_user_rx_thread_placement ();
460   vhost_user_tx_thread_placement (vui);
461 }
462
463 static void
464 vhost_user_set_interrupt_pending (vhost_user_intf_t * vui, u32 ifq)
465 {
466   u32 qid;
467   vnet_main_t *vnm = vnet_get_main ();
468
469   qid = ifq & 0xff;
470   if ((qid & 1) == 0)
471     /* Only care about the odd number, or TX, virtqueue */
472     return;
473
474   if (vhost_user_intf_ready (vui))
475     // qid >> 1 is to convert virtqueue number to vring queue index
476     vnet_device_input_set_interrupt_pending (vnm, vui->hw_if_index, qid >> 1);
477 }
478
479 static clib_error_t *
480 vhost_user_callfd_read_ready (unix_file_t * uf)
481 {
482   __attribute__ ((unused)) int n;
483   u8 buff[8];
484
485   n = read (uf->file_descriptor, ((char *) &buff), 8);
486   DBG_SOCK ("if %d CALL queue %d", uf->private_data >> 8,
487             uf->private_data & 0xff);
488
489   return 0;
490 }
491
492 static clib_error_t *
493 vhost_user_kickfd_read_ready (unix_file_t * uf)
494 {
495   __attribute__ ((unused)) int n;
496   u8 buff[8];
497   vhost_user_intf_t *vui =
498     pool_elt_at_index (vhost_user_main.vhost_user_interfaces,
499                        uf->private_data >> 8);
500   u32 qid = uf->private_data & 0xff;
501
502   n = read (uf->file_descriptor, ((char *) &buff), 8);
503   DBG_SOCK ("if %d KICK queue %d", uf->private_data >> 8, qid);
504   if (!vui->vrings[qid].started ||
505       (vhost_user_intf_ready (vui) != vui->is_up))
506     {
507       vlib_worker_thread_barrier_sync (vlib_get_main ());
508       vui->vrings[qid].started = 1;
509       vhost_user_update_iface_state (vui);
510       vlib_worker_thread_barrier_release (vlib_get_main ());
511     }
512
513   vhost_user_set_interrupt_pending (vui, uf->private_data);
514   return 0;
515 }
516
517 /**
518  * @brief Try once to lock the vring
519  * @return 0 on success, non-zero on failure.
520  */
521 static inline int
522 vhost_user_vring_try_lock (vhost_user_intf_t * vui, u32 qid)
523 {
524   return __sync_lock_test_and_set (vui->vring_locks[qid], 1);
525 }
526
527 /**
528  * @brief Spin until the vring is successfully locked
529  */
530 static inline void
531 vhost_user_vring_lock (vhost_user_intf_t * vui, u32 qid)
532 {
533   while (vhost_user_vring_try_lock (vui, qid))
534     ;
535 }
536
537 /**
538  * @brief Unlock the vring lock
539  */
540 static inline void
541 vhost_user_vring_unlock (vhost_user_intf_t * vui, u32 qid)
542 {
543   *vui->vring_locks[qid] = 0;
544 }
545
546 static inline void
547 vhost_user_vring_init (vhost_user_intf_t * vui, u32 qid)
548 {
549   vhost_user_vring_t *vring = &vui->vrings[qid];
550   memset (vring, 0, sizeof (*vring));
551   vring->kickfd_idx = ~0;
552   vring->callfd_idx = ~0;
553   vring->errfd = -1;
554
555   /*
556    * We have a bug with some qemu 2.5, and this may be a fix.
557    * Feel like interpretation holy text, but this is from vhost-user.txt.
558    * "
559    * One queue pair is enabled initially. More queues are enabled
560    * dynamically, by sending message VHOST_USER_SET_VRING_ENABLE.
561    * "
562    * Don't know who's right, but this is what DPDK does.
563    */
564   if (qid == 0 || qid == 1)
565     vring->enabled = 1;
566 }
567
568 static inline void
569 vhost_user_vring_close (vhost_user_intf_t * vui, u32 qid)
570 {
571   vhost_user_vring_t *vring = &vui->vrings[qid];
572   if (vring->kickfd_idx != ~0)
573     {
574       unix_file_t *uf = pool_elt_at_index (unix_main.file_pool,
575                                            vring->kickfd_idx);
576       unix_file_del (&unix_main, uf);
577       vring->kickfd_idx = ~0;
578     }
579   if (vring->callfd_idx != ~0)
580     {
581       unix_file_t *uf = pool_elt_at_index (unix_main.file_pool,
582                                            vring->callfd_idx);
583       unix_file_del (&unix_main, uf);
584       vring->callfd_idx = ~0;
585     }
586   if (vring->errfd != -1)
587     {
588       close (vring->errfd);
589       vring->errfd = -1;
590     }
591   vhost_user_vring_init (vui, qid);
592 }
593
594 static inline void
595 vhost_user_if_disconnect (vhost_user_intf_t * vui)
596 {
597   vnet_main_t *vnm = vnet_get_main ();
598   int q;
599
600   vnet_hw_interface_set_flags (vnm, vui->hw_if_index, 0);
601
602   if (vui->unix_file_index != ~0)
603     {
604       unix_file_del (&unix_main, unix_main.file_pool + vui->unix_file_index);
605       vui->unix_file_index = ~0;
606     }
607
608   vui->is_up = 0;
609
610   for (q = 0; q < VHOST_VRING_MAX_N; q++)
611     vhost_user_vring_close (vui, q);
612
613   unmap_all_mem_regions (vui);
614   DBG_SOCK ("interface ifindex %d disconnected", vui->sw_if_index);
615 }
616
617 #define VHOST_LOG_PAGE 0x1000
618 static_always_inline void
619 vhost_user_log_dirty_pages_2 (vhost_user_intf_t * vui,
620                               u64 addr, u64 len, u8 is_host_address)
621 {
622   if (PREDICT_TRUE (vui->log_base_addr == 0
623                     || !(vui->features & (1 << FEAT_VHOST_F_LOG_ALL))))
624     {
625       return;
626     }
627   if (is_host_address)
628     {
629       addr = pointer_to_uword (map_user_mem (vui, (uword) addr));
630     }
631   if (PREDICT_FALSE ((addr + len - 1) / VHOST_LOG_PAGE / 8 >= vui->log_size))
632     {
633       DBG_SOCK ("vhost_user_log_dirty_pages(): out of range\n");
634       return;
635     }
636
637   CLIB_MEMORY_BARRIER ();
638   u64 page = addr / VHOST_LOG_PAGE;
639   while (page * VHOST_LOG_PAGE < addr + len)
640     {
641       ((u8 *) vui->log_base_addr)[page / 8] |= 1 << page % 8;
642       page++;
643     }
644 }
645
646 static_always_inline void
647 vhost_user_log_dirty_pages (vhost_user_intf_t * vui, u64 addr, u64 len)
648 {
649   vhost_user_log_dirty_pages_2 (vui, addr, len, 0);
650 }
651
652 #define vhost_user_log_dirty_ring(vui, vq, member) \
653   if (PREDICT_FALSE(vq->log_used)) { \
654     vhost_user_log_dirty_pages(vui, vq->log_guest_addr + STRUCT_OFFSET_OF(vring_used_t, member), \
655                              sizeof(vq->used->member)); \
656   }
657
658 static clib_error_t *
659 vhost_user_socket_read (unix_file_t * uf)
660 {
661   int n, i;
662   int fd, number_of_fds = 0;
663   int fds[VHOST_MEMORY_MAX_NREGIONS];
664   vhost_user_msg_t msg;
665   struct msghdr mh;
666   struct iovec iov[1];
667   vhost_user_main_t *vum = &vhost_user_main;
668   vhost_user_intf_t *vui;
669   struct cmsghdr *cmsg;
670   u8 q;
671   unix_file_t template = { 0 };
672   vnet_main_t *vnm = vnet_get_main ();
673
674   vui = pool_elt_at_index (vum->vhost_user_interfaces, uf->private_data);
675
676   char control[CMSG_SPACE (VHOST_MEMORY_MAX_NREGIONS * sizeof (int))];
677
678   memset (&mh, 0, sizeof (mh));
679   memset (control, 0, sizeof (control));
680
681   for (i = 0; i < VHOST_MEMORY_MAX_NREGIONS; i++)
682     fds[i] = -1;
683
684   /* set the payload */
685   iov[0].iov_base = (void *) &msg;
686   iov[0].iov_len = VHOST_USER_MSG_HDR_SZ;
687
688   mh.msg_iov = iov;
689   mh.msg_iovlen = 1;
690   mh.msg_control = control;
691   mh.msg_controllen = sizeof (control);
692
693   n = recvmsg (uf->file_descriptor, &mh, 0);
694
695   /* Stop workers to avoid end of the world */
696   vlib_worker_thread_barrier_sync (vlib_get_main ());
697
698   if (n != VHOST_USER_MSG_HDR_SZ)
699     {
700       if (n == -1)
701         {
702           DBG_SOCK ("recvmsg returned error %d %s", errno, strerror (errno));
703         }
704       else
705         {
706           DBG_SOCK ("n (%d) != VHOST_USER_MSG_HDR_SZ (%d)",
707                     n, VHOST_USER_MSG_HDR_SZ);
708         }
709       goto close_socket;
710     }
711
712   if (mh.msg_flags & MSG_CTRUNC)
713     {
714       DBG_SOCK ("MSG_CTRUNC is set");
715       goto close_socket;
716     }
717
718   cmsg = CMSG_FIRSTHDR (&mh);
719
720   if (cmsg && (cmsg->cmsg_len > 0) && (cmsg->cmsg_level == SOL_SOCKET) &&
721       (cmsg->cmsg_type == SCM_RIGHTS) &&
722       (cmsg->cmsg_len - CMSG_LEN (0) <=
723        VHOST_MEMORY_MAX_NREGIONS * sizeof (int)))
724     {
725       number_of_fds = (cmsg->cmsg_len - CMSG_LEN (0)) / sizeof (int);
726       clib_memcpy (fds, CMSG_DATA (cmsg), number_of_fds * sizeof (int));
727     }
728
729   /* version 1, no reply bit set */
730   if ((msg.flags & 7) != 1)
731     {
732       DBG_SOCK ("malformed message received. closing socket");
733       goto close_socket;
734     }
735
736   {
737     int rv;
738     rv =
739       read (uf->file_descriptor, ((char *) &msg) + VHOST_USER_MSG_HDR_SZ,
740             msg.size);
741     if (rv < 0)
742       {
743         DBG_SOCK ("read failed %s", strerror (errno));
744         goto close_socket;
745       }
746     else if (rv != msg.size)
747       {
748         DBG_SOCK ("message too short (read %dB should be %dB)", rv, msg.size);
749         goto close_socket;
750       }
751   }
752
753   switch (msg.request)
754     {
755     case VHOST_USER_GET_FEATURES:
756       msg.flags |= 4;
757       msg.u64 = (1ULL << FEAT_VIRTIO_NET_F_MRG_RXBUF) |
758         (1ULL << FEAT_VIRTIO_NET_F_CTRL_VQ) |
759         (1ULL << FEAT_VIRTIO_F_ANY_LAYOUT) |
760         (1ULL << FEAT_VIRTIO_F_INDIRECT_DESC) |
761         (1ULL << FEAT_VHOST_F_LOG_ALL) |
762         (1ULL << FEAT_VIRTIO_NET_F_GUEST_ANNOUNCE) |
763         (1ULL << FEAT_VIRTIO_NET_F_MQ) |
764         (1ULL << FEAT_VHOST_USER_F_PROTOCOL_FEATURES) |
765         (1ULL << FEAT_VIRTIO_F_VERSION_1);
766       msg.u64 &= vui->feature_mask;
767       msg.size = sizeof (msg.u64);
768       DBG_SOCK ("if %d msg VHOST_USER_GET_FEATURES - reply 0x%016llx",
769                 vui->hw_if_index, msg.u64);
770       break;
771
772     case VHOST_USER_SET_FEATURES:
773       DBG_SOCK ("if %d msg VHOST_USER_SET_FEATURES features 0x%016llx",
774                 vui->hw_if_index, msg.u64);
775
776       vui->features = msg.u64;
777
778       if (vui->features &
779           ((1 << FEAT_VIRTIO_NET_F_MRG_RXBUF) |
780            (1ULL << FEAT_VIRTIO_F_VERSION_1)))
781         vui->virtio_net_hdr_sz = 12;
782       else
783         vui->virtio_net_hdr_sz = 10;
784
785       vui->is_any_layout =
786         (vui->features & (1 << FEAT_VIRTIO_F_ANY_LAYOUT)) ? 1 : 0;
787
788       ASSERT (vui->virtio_net_hdr_sz < VLIB_BUFFER_PRE_DATA_SIZE);
789       vnet_hw_interface_set_flags (vnm, vui->hw_if_index, 0);
790       vui->is_up = 0;
791
792       /*for (q = 0; q < VHOST_VRING_MAX_N; q++)
793          vhost_user_vring_close(&vui->vrings[q]); */
794
795       break;
796
797     case VHOST_USER_SET_MEM_TABLE:
798       DBG_SOCK ("if %d msg VHOST_USER_SET_MEM_TABLE nregions %d",
799                 vui->hw_if_index, msg.memory.nregions);
800
801       if ((msg.memory.nregions < 1) ||
802           (msg.memory.nregions > VHOST_MEMORY_MAX_NREGIONS))
803         {
804
805           DBG_SOCK ("number of mem regions must be between 1 and %i",
806                     VHOST_MEMORY_MAX_NREGIONS);
807
808           goto close_socket;
809         }
810
811       if (msg.memory.nregions != number_of_fds)
812         {
813           DBG_SOCK ("each memory region must have FD");
814           goto close_socket;
815         }
816       unmap_all_mem_regions (vui);
817       for (i = 0; i < msg.memory.nregions; i++)
818         {
819           clib_memcpy (&(vui->regions[i]), &msg.memory.regions[i],
820                        sizeof (vhost_user_memory_region_t));
821
822           long page_sz = get_huge_page_size (fds[i]);
823
824           /* align size to 2M page */
825           ssize_t map_sz = (vui->regions[i].memory_size +
826                             vui->regions[i].mmap_offset +
827                             page_sz - 1) & ~(page_sz - 1);
828
829           vui->region_mmap_addr[i] = mmap (0, map_sz, PROT_READ | PROT_WRITE,
830                                            MAP_SHARED, fds[i], 0);
831           vui->region_guest_addr_lo[i] = vui->regions[i].guest_phys_addr;
832           vui->region_guest_addr_hi[i] = vui->regions[i].guest_phys_addr +
833             vui->regions[i].memory_size;
834
835           DBG_SOCK
836             ("map memory region %d addr 0 len 0x%lx fd %d mapped 0x%lx "
837              "page_sz 0x%x", i, map_sz, fds[i], vui->region_mmap_addr[i],
838              page_sz);
839
840           if (vui->region_mmap_addr[i] == MAP_FAILED)
841             {
842               clib_warning ("failed to map memory. errno is %d", errno);
843               goto close_socket;
844             }
845           vui->region_mmap_addr[i] += vui->regions[i].mmap_offset;
846           vui->region_mmap_fd[i] = fds[i];
847         }
848       vui->nregions = msg.memory.nregions;
849       break;
850
851     case VHOST_USER_SET_VRING_NUM:
852       DBG_SOCK ("if %d msg VHOST_USER_SET_VRING_NUM idx %d num %d",
853                 vui->hw_if_index, msg.state.index, msg.state.num);
854
855       if ((msg.state.num > 32768) ||    /* maximum ring size is 32768 */
856           (msg.state.num == 0) ||       /* it cannot be zero */
857           ((msg.state.num - 1) & msg.state.num))        /* must be power of 2 */
858         goto close_socket;
859       vui->vrings[msg.state.index].qsz = msg.state.num;
860       break;
861
862     case VHOST_USER_SET_VRING_ADDR:
863       DBG_SOCK ("if %d msg VHOST_USER_SET_VRING_ADDR idx %d",
864                 vui->hw_if_index, msg.state.index);
865
866       if (msg.state.index >= VHOST_VRING_MAX_N)
867         {
868           DBG_SOCK ("invalid vring index VHOST_USER_SET_VRING_ADDR:"
869                     " %d >= %d", msg.state.index, VHOST_VRING_MAX_N);
870           goto close_socket;
871         }
872
873       if (msg.size < sizeof (msg.addr))
874         {
875           DBG_SOCK ("vhost message is too short (%d < %d)",
876                     msg.size, sizeof (msg.addr));
877           goto close_socket;
878         }
879
880       vui->vrings[msg.state.index].desc = (vring_desc_t *)
881         map_user_mem (vui, msg.addr.desc_user_addr);
882       vui->vrings[msg.state.index].used = (vring_used_t *)
883         map_user_mem (vui, msg.addr.used_user_addr);
884       vui->vrings[msg.state.index].avail = (vring_avail_t *)
885         map_user_mem (vui, msg.addr.avail_user_addr);
886
887       if ((vui->vrings[msg.state.index].desc == NULL) ||
888           (vui->vrings[msg.state.index].used == NULL) ||
889           (vui->vrings[msg.state.index].avail == NULL))
890         {
891           DBG_SOCK ("failed to map user memory for hw_if_index %d",
892                     vui->hw_if_index);
893           goto close_socket;
894         }
895
896       vui->vrings[msg.state.index].log_guest_addr = msg.addr.log_guest_addr;
897       vui->vrings[msg.state.index].log_used =
898         (msg.addr.flags & (1 << VHOST_VRING_F_LOG)) ? 1 : 0;
899
900       /* Spec says: If VHOST_USER_F_PROTOCOL_FEATURES has not been negotiated,
901          the ring is initialized in an enabled state. */
902       if (!(vui->features & (1 << FEAT_VHOST_USER_F_PROTOCOL_FEATURES)))
903         {
904           vui->vrings[msg.state.index].enabled = 1;
905         }
906
907       vui->vrings[msg.state.index].last_used_idx =
908         vui->vrings[msg.state.index].last_avail_idx =
909         vui->vrings[msg.state.index].used->idx;
910
911       /* tell driver that we don't want interrupts */
912       vui->vrings[msg.state.index].used->flags = VRING_USED_F_NO_NOTIFY;
913       break;
914
915     case VHOST_USER_SET_OWNER:
916       DBG_SOCK ("if %d msg VHOST_USER_SET_OWNER", vui->hw_if_index);
917       break;
918
919     case VHOST_USER_RESET_OWNER:
920       DBG_SOCK ("if %d msg VHOST_USER_RESET_OWNER", vui->hw_if_index);
921       break;
922
923     case VHOST_USER_SET_VRING_CALL:
924       DBG_SOCK ("if %d msg VHOST_USER_SET_VRING_CALL u64 %d",
925                 vui->hw_if_index, msg.u64);
926
927       q = (u8) (msg.u64 & 0xFF);
928
929       /* if there is old fd, delete and close it */
930       if (vui->vrings[q].callfd_idx != ~0)
931         {
932           unix_file_t *uf = pool_elt_at_index (unix_main.file_pool,
933                                                vui->vrings[q].callfd_idx);
934           unix_file_del (&unix_main, uf);
935           vui->vrings[q].callfd_idx = ~0;
936         }
937
938       if (!(msg.u64 & 0x100))
939         {
940           if (number_of_fds != 1)
941             {
942               DBG_SOCK ("More than one fd received !");
943               goto close_socket;
944             }
945
946           template.read_function = vhost_user_callfd_read_ready;
947           template.file_descriptor = fds[0];
948           template.private_data =
949             ((vui - vhost_user_main.vhost_user_interfaces) << 8) + q;
950           vui->vrings[q].callfd_idx = unix_file_add (&unix_main, &template);
951         }
952       else
953         vui->vrings[q].callfd_idx = ~0;
954       break;
955
956     case VHOST_USER_SET_VRING_KICK:
957       DBG_SOCK ("if %d msg VHOST_USER_SET_VRING_KICK u64 %d",
958                 vui->hw_if_index, msg.u64);
959
960       q = (u8) (msg.u64 & 0xFF);
961
962       if (vui->vrings[q].kickfd_idx != ~0)
963         {
964           unix_file_t *uf = pool_elt_at_index (unix_main.file_pool,
965                                                vui->vrings[q].kickfd_idx);
966           unix_file_del (&unix_main, uf);
967           vui->vrings[q].kickfd_idx = ~0;
968         }
969
970       if (!(msg.u64 & 0x100))
971         {
972           if (number_of_fds != 1)
973             {
974               DBG_SOCK ("More than one fd received !");
975               goto close_socket;
976             }
977
978           template.read_function = vhost_user_kickfd_read_ready;
979           template.file_descriptor = fds[0];
980           template.private_data =
981             (((uword) (vui - vhost_user_main.vhost_user_interfaces)) << 8) +
982             q;
983           vui->vrings[q].kickfd_idx = unix_file_add (&unix_main, &template);
984         }
985       else
986         {
987           //When no kickfd is set, the queue is initialized as started
988           vui->vrings[q].kickfd_idx = ~0;
989           vui->vrings[q].started = 1;
990         }
991
992       break;
993
994     case VHOST_USER_SET_VRING_ERR:
995       DBG_SOCK ("if %d msg VHOST_USER_SET_VRING_ERR u64 %d",
996                 vui->hw_if_index, msg.u64);
997
998       q = (u8) (msg.u64 & 0xFF);
999
1000       if (vui->vrings[q].errfd != -1)
1001         close (vui->vrings[q].errfd);
1002
1003       if (!(msg.u64 & 0x100))
1004         {
1005           if (number_of_fds != 1)
1006             goto close_socket;
1007
1008           vui->vrings[q].errfd = fds[0];
1009         }
1010       else
1011         vui->vrings[q].errfd = -1;
1012
1013       break;
1014
1015     case VHOST_USER_SET_VRING_BASE:
1016       DBG_SOCK ("if %d msg VHOST_USER_SET_VRING_BASE idx %d num %d",
1017                 vui->hw_if_index, msg.state.index, msg.state.num);
1018
1019       vui->vrings[msg.state.index].last_avail_idx = msg.state.num;
1020       break;
1021
1022     case VHOST_USER_GET_VRING_BASE:
1023       DBG_SOCK ("if %d msg VHOST_USER_GET_VRING_BASE idx %d num %d",
1024                 vui->hw_if_index, msg.state.index, msg.state.num);
1025
1026       if (msg.state.index >= VHOST_VRING_MAX_N)
1027         {
1028           DBG_SOCK ("invalid vring index VHOST_USER_GET_VRING_BASE:"
1029                     " %d >= %d", msg.state.index, VHOST_VRING_MAX_N);
1030           goto close_socket;
1031         }
1032
1033       /*
1034        * Copy last_avail_idx from the vring before closing it because
1035        * closing the vring also initializes the vring last_avail_idx
1036        */
1037       msg.state.num = vui->vrings[msg.state.index].last_avail_idx;
1038       msg.flags |= 4;
1039       msg.size = sizeof (msg.state);
1040
1041       /* Spec says: Client must [...] stop ring upon receiving VHOST_USER_GET_VRING_BASE. */
1042       vhost_user_vring_close (vui, msg.state.index);
1043       break;
1044
1045     case VHOST_USER_NONE:
1046       DBG_SOCK ("if %d msg VHOST_USER_NONE", vui->hw_if_index);
1047
1048       break;
1049
1050     case VHOST_USER_SET_LOG_BASE:
1051       {
1052         DBG_SOCK ("if %d msg VHOST_USER_SET_LOG_BASE", vui->hw_if_index);
1053
1054         if (msg.size != sizeof (msg.log))
1055           {
1056             DBG_SOCK
1057               ("invalid msg size for VHOST_USER_SET_LOG_BASE: %d instead of %d",
1058                msg.size, sizeof (msg.log));
1059             goto close_socket;
1060           }
1061
1062         if (!
1063             (vui->protocol_features & (1 << VHOST_USER_PROTOCOL_F_LOG_SHMFD)))
1064           {
1065             DBG_SOCK
1066               ("VHOST_USER_PROTOCOL_F_LOG_SHMFD not set but VHOST_USER_SET_LOG_BASE received");
1067             goto close_socket;
1068           }
1069
1070         fd = fds[0];
1071         /* align size to 2M page */
1072         long page_sz = get_huge_page_size (fd);
1073         ssize_t map_sz =
1074           (msg.log.size + msg.log.offset + page_sz - 1) & ~(page_sz - 1);
1075
1076         vui->log_base_addr = mmap (0, map_sz, PROT_READ | PROT_WRITE,
1077                                    MAP_SHARED, fd, 0);
1078
1079         DBG_SOCK
1080           ("map log region addr 0 len 0x%lx off 0x%lx fd %d mapped 0x%lx",
1081            map_sz, msg.log.offset, fd, vui->log_base_addr);
1082
1083         if (vui->log_base_addr == MAP_FAILED)
1084           {
1085             clib_warning ("failed to map memory. errno is %d", errno);
1086             goto close_socket;
1087           }
1088
1089         vui->log_base_addr += msg.log.offset;
1090         vui->log_size = msg.log.size;
1091
1092         msg.flags |= 4;
1093         msg.size = sizeof (msg.u64);
1094
1095         break;
1096       }
1097
1098     case VHOST_USER_SET_LOG_FD:
1099       DBG_SOCK ("if %d msg VHOST_USER_SET_LOG_FD", vui->hw_if_index);
1100
1101       break;
1102
1103     case VHOST_USER_GET_PROTOCOL_FEATURES:
1104       DBG_SOCK ("if %d msg VHOST_USER_GET_PROTOCOL_FEATURES",
1105                 vui->hw_if_index);
1106
1107       msg.flags |= 4;
1108       msg.u64 = (1 << VHOST_USER_PROTOCOL_F_LOG_SHMFD) |
1109         (1 << VHOST_USER_PROTOCOL_F_MQ);
1110       msg.size = sizeof (msg.u64);
1111       break;
1112
1113     case VHOST_USER_SET_PROTOCOL_FEATURES:
1114       DBG_SOCK ("if %d msg VHOST_USER_SET_PROTOCOL_FEATURES features 0x%lx",
1115                 vui->hw_if_index, msg.u64);
1116
1117       vui->protocol_features = msg.u64;
1118
1119       break;
1120
1121     case VHOST_USER_GET_QUEUE_NUM:
1122       DBG_SOCK ("if %d msg VHOST_USER_GET_QUEUE_NUM", vui->hw_if_index);
1123       msg.flags |= 4;
1124       msg.u64 = VHOST_VRING_MAX_N;
1125       msg.size = sizeof (msg.u64);
1126       break;
1127
1128     case VHOST_USER_SET_VRING_ENABLE:
1129       DBG_SOCK ("if %d VHOST_USER_SET_VRING_ENABLE: %s queue %d",
1130                 vui->hw_if_index, msg.state.num ? "enable" : "disable",
1131                 msg.state.index);
1132       if (msg.state.index >= VHOST_VRING_MAX_N)
1133         {
1134           DBG_SOCK ("invalid vring index VHOST_USER_SET_VRING_ENABLE:"
1135                     " %d >= %d", msg.state.index, VHOST_VRING_MAX_N);
1136           goto close_socket;
1137         }
1138
1139       vui->vrings[msg.state.index].enabled = msg.state.num;
1140       break;
1141
1142     default:
1143       DBG_SOCK ("unknown vhost-user message %d received. closing socket",
1144                 msg.request);
1145       goto close_socket;
1146     }
1147
1148   /* if we need to reply */
1149   if (msg.flags & 4)
1150     {
1151       n =
1152         send (uf->file_descriptor, &msg, VHOST_USER_MSG_HDR_SZ + msg.size, 0);
1153       if (n != (msg.size + VHOST_USER_MSG_HDR_SZ))
1154         {
1155           DBG_SOCK ("could not send message response");
1156           goto close_socket;
1157         }
1158     }
1159
1160   vhost_user_update_iface_state (vui);
1161   vlib_worker_thread_barrier_release (vlib_get_main ());
1162   return 0;
1163
1164 close_socket:
1165   vhost_user_if_disconnect (vui);
1166   vhost_user_update_iface_state (vui);
1167   vlib_worker_thread_barrier_release (vlib_get_main ());
1168   return 0;
1169 }
1170
1171 static clib_error_t *
1172 vhost_user_socket_error (unix_file_t * uf)
1173 {
1174   vlib_main_t *vm = vlib_get_main ();
1175   vhost_user_main_t *vum = &vhost_user_main;
1176   vhost_user_intf_t *vui =
1177     pool_elt_at_index (vum->vhost_user_interfaces, uf->private_data);
1178
1179   DBG_SOCK ("socket error on if %d", vui->sw_if_index);
1180   vlib_worker_thread_barrier_sync (vm);
1181   vhost_user_if_disconnect (vui);
1182   vhost_user_rx_thread_placement ();
1183   vlib_worker_thread_barrier_release (vm);
1184   return 0;
1185 }
1186
1187 static clib_error_t *
1188 vhost_user_socksvr_accept_ready (unix_file_t * uf)
1189 {
1190   int client_fd, client_len;
1191   struct sockaddr_un client;
1192   unix_file_t template = { 0 };
1193   vhost_user_main_t *vum = &vhost_user_main;
1194   vhost_user_intf_t *vui;
1195
1196   vui = pool_elt_at_index (vum->vhost_user_interfaces, uf->private_data);
1197
1198   client_len = sizeof (client);
1199   client_fd = accept (uf->file_descriptor,
1200                       (struct sockaddr *) &client,
1201                       (socklen_t *) & client_len);
1202
1203   if (client_fd < 0)
1204     return clib_error_return_unix (0, "accept");
1205
1206   DBG_SOCK ("New client socket for vhost interface %d", vui->sw_if_index);
1207   template.read_function = vhost_user_socket_read;
1208   template.error_function = vhost_user_socket_error;
1209   template.file_descriptor = client_fd;
1210   template.private_data = vui - vhost_user_main.vhost_user_interfaces;
1211   vui->unix_file_index = unix_file_add (&unix_main, &template);
1212   return 0;
1213 }
1214
1215 static clib_error_t *
1216 vhost_user_init (vlib_main_t * vm)
1217 {
1218   clib_error_t *error;
1219   vhost_user_main_t *vum = &vhost_user_main;
1220   vlib_thread_main_t *tm = vlib_get_thread_main ();
1221
1222   error = vlib_call_init_function (vm, ip4_init);
1223   if (error)
1224     return error;
1225
1226   vum->coalesce_frames = 32;
1227   vum->coalesce_time = 1e-3;
1228
1229   vec_validate (vum->cpus, tm->n_vlib_mains - 1);
1230
1231   vhost_cpu_t *cpu;
1232   vec_foreach (cpu, vum->cpus)
1233   {
1234     /* This is actually not necessary as validate already zeroes it
1235      * Just keeping the loop here for later because I am lazy. */
1236     cpu->rx_buffers_len = 0;
1237   }
1238
1239   vum->random = random_default_seed ();
1240
1241   mhash_init_c_string (&vum->if_index_by_sock_name, sizeof (uword));
1242
1243   return 0;
1244 }
1245
1246 VLIB_INIT_FUNCTION (vhost_user_init);
1247
1248 static u8 *
1249 format_vhost_trace (u8 * s, va_list * va)
1250 {
1251   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
1252   CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
1253   CLIB_UNUSED (vnet_main_t * vnm) = vnet_get_main ();
1254   vhost_user_main_t *vum = &vhost_user_main;
1255   vhost_trace_t *t = va_arg (*va, vhost_trace_t *);
1256   vhost_user_intf_t *vui = pool_elt_at_index (vum->vhost_user_interfaces,
1257                                               t->device_index);
1258
1259   vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, vui->sw_if_index);
1260
1261   uword indent = format_get_indent (s);
1262
1263   s = format (s, "%U %U queue %d\n", format_white_space, indent,
1264               format_vnet_sw_interface_name, vnm, sw, t->qid);
1265
1266   s = format (s, "%U virtio flags:\n", format_white_space, indent);
1267 #define _(n,i,st) \
1268           if (t->virtio_ring_flags & (1 << VIRTIO_TRACE_F_##n)) \
1269             s = format (s, "%U  %s %s\n", format_white_space, indent, #n, st);
1270   foreach_virtio_trace_flags
1271 #undef _
1272     s = format (s, "%U virtio_net_hdr first_desc_len %u\n",
1273                 format_white_space, indent, t->first_desc_len);
1274
1275   s = format (s, "%U   flags 0x%02x gso_type %u\n",
1276               format_white_space, indent,
1277               t->hdr.hdr.flags, t->hdr.hdr.gso_type);
1278
1279   if (vui->virtio_net_hdr_sz == 12)
1280     s = format (s, "%U   num_buff %u",
1281                 format_white_space, indent, t->hdr.num_buffers);
1282
1283   return s;
1284 }
1285
1286 void
1287 vhost_user_rx_trace (vhost_trace_t * t,
1288                      vhost_user_intf_t * vui, u16 qid,
1289                      vlib_buffer_t * b, vhost_user_vring_t * txvq)
1290 {
1291   vhost_user_main_t *vum = &vhost_user_main;
1292   u32 qsz_mask = txvq->qsz - 1;
1293   u32 last_avail_idx = txvq->last_avail_idx;
1294   u32 desc_current = txvq->avail->ring[last_avail_idx & qsz_mask];
1295   vring_desc_t *hdr_desc = 0;
1296   virtio_net_hdr_mrg_rxbuf_t *hdr;
1297   u32 hint = 0;
1298
1299   memset (t, 0, sizeof (*t));
1300   t->device_index = vui - vum->vhost_user_interfaces;
1301   t->qid = qid;
1302
1303   hdr_desc = &txvq->desc[desc_current];
1304   if (txvq->desc[desc_current].flags & VIRTQ_DESC_F_INDIRECT)
1305     {
1306       t->virtio_ring_flags |= 1 << VIRTIO_TRACE_F_INDIRECT;
1307       /* Header is the first here */
1308       hdr_desc = map_guest_mem (vui, txvq->desc[desc_current].addr, &hint);
1309     }
1310   if (txvq->desc[desc_current].flags & VIRTQ_DESC_F_NEXT)
1311     {
1312       t->virtio_ring_flags |= 1 << VIRTIO_TRACE_F_SIMPLE_CHAINED;
1313     }
1314   if (!(txvq->desc[desc_current].flags & VIRTQ_DESC_F_NEXT) &&
1315       !(txvq->desc[desc_current].flags & VIRTQ_DESC_F_INDIRECT))
1316     {
1317       t->virtio_ring_flags |= 1 << VIRTIO_TRACE_F_SINGLE_DESC;
1318     }
1319
1320   t->first_desc_len = hdr_desc ? hdr_desc->len : 0;
1321
1322   if (!hdr_desc || !(hdr = map_guest_mem (vui, hdr_desc->addr, &hint)))
1323     {
1324       t->virtio_ring_flags |= 1 << VIRTIO_TRACE_F_MAP_ERROR;
1325     }
1326   else
1327     {
1328       u32 len = vui->virtio_net_hdr_sz;
1329       memcpy (&t->hdr, hdr, len > hdr_desc->len ? hdr_desc->len : len);
1330     }
1331 }
1332
1333 static inline void
1334 vhost_user_send_call (vlib_main_t * vm, vhost_user_vring_t * vq)
1335 {
1336   vhost_user_main_t *vum = &vhost_user_main;
1337   u64 x = 1;
1338   int fd = UNIX_GET_FD (vq->callfd_idx);
1339   int rv;
1340
1341   rv = write (fd, &x, sizeof (x));
1342   if (rv <= 0)
1343     {
1344       clib_unix_warning
1345         ("Error: Could not write to unix socket for callfd %d", fd);
1346       return;
1347     }
1348
1349   vq->n_since_last_int = 0;
1350   vq->int_deadline = vlib_time_now (vm) + vum->coalesce_time;
1351 }
1352
1353 static_always_inline u32
1354 vhost_user_input_copy (vhost_user_intf_t * vui, vhost_copy_t * cpy,
1355                        u16 copy_len, u32 * map_hint)
1356 {
1357   void *src0, *src1, *src2, *src3;
1358   if (PREDICT_TRUE (copy_len >= 4))
1359     {
1360       if (PREDICT_FALSE (!(src2 = map_guest_mem (vui, cpy[0].src, map_hint))))
1361         return 1;
1362       if (PREDICT_FALSE (!(src3 = map_guest_mem (vui, cpy[1].src, map_hint))))
1363         return 1;
1364
1365       while (PREDICT_TRUE (copy_len >= 4))
1366         {
1367           src0 = src2;
1368           src1 = src3;
1369
1370           if (PREDICT_FALSE
1371               (!(src2 = map_guest_mem (vui, cpy[2].src, map_hint))))
1372             return 1;
1373           if (PREDICT_FALSE
1374               (!(src3 = map_guest_mem (vui, cpy[3].src, map_hint))))
1375             return 1;
1376
1377           CLIB_PREFETCH (src2, 64, LOAD);
1378           CLIB_PREFETCH (src3, 64, LOAD);
1379
1380           clib_memcpy ((void *) cpy[0].dst, src0, cpy[0].len);
1381           clib_memcpy ((void *) cpy[1].dst, src1, cpy[1].len);
1382           copy_len -= 2;
1383           cpy += 2;
1384         }
1385     }
1386   while (copy_len)
1387     {
1388       if (PREDICT_FALSE (!(src0 = map_guest_mem (vui, cpy->src, map_hint))))
1389         return 1;
1390       clib_memcpy ((void *) cpy->dst, src0, cpy->len);
1391       copy_len -= 1;
1392       cpy += 1;
1393     }
1394   return 0;
1395 }
1396
1397 /**
1398  * Try to discard packets from the tx ring (VPP RX path).
1399  * Returns the number of discarded packets.
1400  */
1401 u32
1402 vhost_user_rx_discard_packet (vlib_main_t * vm,
1403                               vhost_user_intf_t * vui,
1404                               vhost_user_vring_t * txvq, u32 discard_max)
1405 {
1406   /*
1407    * On the RX side, each packet corresponds to one descriptor
1408    * (it is the same whether it is a shallow descriptor, chained, or indirect).
1409    * Therefore, discarding a packet is like discarding a descriptor.
1410    */
1411   u32 discarded_packets = 0;
1412   u32 avail_idx = txvq->avail->idx;
1413   u16 qsz_mask = txvq->qsz - 1;
1414   while (discarded_packets != discard_max)
1415     {
1416       if (avail_idx == txvq->last_avail_idx)
1417         goto out;
1418
1419       u16 desc_chain_head =
1420         txvq->avail->ring[txvq->last_avail_idx & qsz_mask];
1421       txvq->last_avail_idx++;
1422       txvq->used->ring[txvq->last_used_idx & qsz_mask].id = desc_chain_head;
1423       txvq->used->ring[txvq->last_used_idx & qsz_mask].len = 0;
1424       vhost_user_log_dirty_ring (vui, txvq,
1425                                  ring[txvq->last_used_idx & qsz_mask]);
1426       txvq->last_used_idx++;
1427       discarded_packets++;
1428     }
1429
1430 out:
1431   CLIB_MEMORY_BARRIER ();
1432   txvq->used->idx = txvq->last_used_idx;
1433   vhost_user_log_dirty_ring (vui, txvq, idx);
1434   return discarded_packets;
1435 }
1436
1437 /*
1438  * In case of overflow, we need to rewind the array of allocated buffers.
1439  */
1440 static void
1441 vhost_user_input_rewind_buffers (vlib_main_t * vm,
1442                                  vhost_cpu_t * cpu, vlib_buffer_t * b_head)
1443 {
1444   u32 bi_current = cpu->rx_buffers[cpu->rx_buffers_len];
1445   vlib_buffer_t *b_current = vlib_get_buffer (vm, bi_current);
1446   b_current->current_length = 0;
1447   b_current->flags = 0;
1448   while (b_current != b_head)
1449     {
1450       cpu->rx_buffers_len++;
1451       bi_current = cpu->rx_buffers[cpu->rx_buffers_len];
1452       b_current = vlib_get_buffer (vm, bi_current);
1453       b_current->current_length = 0;
1454       b_current->flags = 0;
1455     }
1456   cpu->rx_buffers_len++;
1457 }
1458
1459 static u32
1460 vhost_user_if_input (vlib_main_t * vm,
1461                      vhost_user_main_t * vum,
1462                      vhost_user_intf_t * vui,
1463                      u16 qid, vlib_node_runtime_t * node,
1464                      vnet_hw_interface_rx_mode mode)
1465 {
1466   vhost_user_vring_t *txvq = &vui->vrings[VHOST_VRING_IDX_TX (qid)];
1467   u16 n_rx_packets = 0;
1468   u32 n_rx_bytes = 0;
1469   u16 n_left;
1470   u32 n_left_to_next, *to_next;
1471   u32 next_index = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT;
1472   u32 n_trace = vlib_get_trace_count (vm, node);
1473   u16 qsz_mask;
1474   u32 map_hint = 0;
1475   u16 thread_index = vlib_get_thread_index ();
1476   u16 copy_len = 0;
1477
1478   {
1479     /* do we have pending interrupts ? */
1480     vhost_user_vring_t *rxvq = &vui->vrings[VHOST_VRING_IDX_RX (qid)];
1481     f64 now = vlib_time_now (vm);
1482
1483     if ((txvq->n_since_last_int) && (txvq->int_deadline < now))
1484       vhost_user_send_call (vm, txvq);
1485
1486     if ((rxvq->n_since_last_int) && (rxvq->int_deadline < now))
1487       vhost_user_send_call (vm, rxvq);
1488   }
1489
1490   /*
1491    * For adaptive mode, it is optimized to reduce interrupts.
1492    * If the scheduler switches the input node to polling due
1493    * to burst of traffic, we tell the driver no interrupt.
1494    * When the traffic subsides, the scheduler switches the node back to
1495    * interrupt mode. We must tell the driver we want interrupt.
1496    */
1497   if (PREDICT_FALSE (mode == VNET_HW_INTERFACE_RX_MODE_ADAPTIVE))
1498     {
1499       if ((node->flags &
1500            VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE) ||
1501           !(node->flags &
1502             VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE))
1503         /* Tell driver we want notification */
1504         txvq->used->flags = 0;
1505       else
1506         /* Tell driver we don't want notification */
1507         txvq->used->flags = VRING_USED_F_NO_NOTIFY;
1508     }
1509
1510   if (PREDICT_FALSE (txvq->avail->flags & 0xFFFE))
1511     return 0;
1512
1513   n_left = (u16) (txvq->avail->idx - txvq->last_avail_idx);
1514
1515   /* nothing to do */
1516   if (PREDICT_FALSE (n_left == 0))
1517     return 0;
1518
1519   if (PREDICT_FALSE (!vui->admin_up || !(txvq->enabled)))
1520     {
1521       /*
1522        * Discard input packet if interface is admin down or vring is not
1523        * enabled.
1524        * "For example, for a networking device, in the disabled state
1525        * client must not supply any new RX packets, but must process
1526        * and discard any TX packets."
1527        */
1528       vhost_user_rx_discard_packet (vm, vui, txvq,
1529                                     VHOST_USER_DOWN_DISCARD_COUNT);
1530       return 0;
1531     }
1532
1533   if (PREDICT_FALSE (n_left == txvq->qsz))
1534     {
1535       /*
1536        * Informational error logging when VPP is not
1537        * receiving packets fast enough.
1538        */
1539       vlib_error_count (vm, node->node_index,
1540                         VHOST_USER_INPUT_FUNC_ERROR_FULL_RX_QUEUE, 1);
1541     }
1542
1543   qsz_mask = txvq->qsz - 1;
1544
1545   if (n_left > VLIB_FRAME_SIZE)
1546     n_left = VLIB_FRAME_SIZE;
1547
1548   /*
1549    * For small packets (<2kB), we will not need more than one vlib buffer
1550    * per packet. In case packets are bigger, we will just yeld at some point
1551    * in the loop and come back later. This is not an issue as for big packet,
1552    * processing cost really comes from the memory copy.
1553    */
1554   if (PREDICT_FALSE (vum->cpus[thread_index].rx_buffers_len < n_left + 1))
1555     {
1556       u32 curr_len = vum->cpus[thread_index].rx_buffers_len;
1557       vum->cpus[thread_index].rx_buffers_len +=
1558         vlib_buffer_alloc_from_free_list (vm,
1559                                           vum->cpus[thread_index].rx_buffers +
1560                                           curr_len,
1561                                           VHOST_USER_RX_BUFFERS_N - curr_len,
1562                                           VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
1563
1564       if (PREDICT_FALSE
1565           (vum->cpus[thread_index].rx_buffers_len <
1566            VHOST_USER_RX_BUFFER_STARVATION))
1567         {
1568           /* In case of buffer starvation, discard some packets from the queue
1569            * and log the event.
1570            * We keep doing best effort for the remaining packets. */
1571           u32 flush = (n_left + 1 > vum->cpus[thread_index].rx_buffers_len) ?
1572             n_left + 1 - vum->cpus[thread_index].rx_buffers_len : 1;
1573           flush = vhost_user_rx_discard_packet (vm, vui, txvq, flush);
1574
1575           n_left -= flush;
1576           vlib_increment_simple_counter (vnet_main.
1577                                          interface_main.sw_if_counters +
1578                                          VNET_INTERFACE_COUNTER_DROP,
1579                                          vlib_get_thread_index (),
1580                                          vui->sw_if_index, flush);
1581
1582           vlib_error_count (vm, vhost_user_input_node.index,
1583                             VHOST_USER_INPUT_FUNC_ERROR_NO_BUFFER, flush);
1584         }
1585     }
1586
1587   while (n_left > 0)
1588     {
1589       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1590
1591       while (n_left > 0 && n_left_to_next > 0)
1592         {
1593           vlib_buffer_t *b_head, *b_current;
1594           u32 bi_current;
1595           u16 desc_current;
1596           u32 desc_data_offset;
1597           vring_desc_t *desc_table = txvq->desc;
1598
1599           if (PREDICT_FALSE (vum->cpus[thread_index].rx_buffers_len <= 1))
1600             {
1601               /* Not enough rx_buffers
1602                * Note: We yeld on 1 so we don't need to do an additional
1603                * check for the next buffer prefetch.
1604                */
1605               n_left = 0;
1606               break;
1607             }
1608
1609           desc_current = txvq->avail->ring[txvq->last_avail_idx & qsz_mask];
1610           vum->cpus[thread_index].rx_buffers_len--;
1611           bi_current = (vum->cpus[thread_index].rx_buffers)
1612             [vum->cpus[thread_index].rx_buffers_len];
1613           b_head = b_current = vlib_get_buffer (vm, bi_current);
1614           to_next[0] = bi_current;      //We do that now so we can forget about bi_current
1615           to_next++;
1616           n_left_to_next--;
1617
1618           vlib_prefetch_buffer_with_index (vm,
1619                                            (vum->
1620                                             cpus[thread_index].rx_buffers)
1621                                            [vum->cpus[thread_index].
1622                                             rx_buffers_len - 1], LOAD);
1623
1624           /* Just preset the used descriptor id and length for later */
1625           txvq->used->ring[txvq->last_used_idx & qsz_mask].id = desc_current;
1626           txvq->used->ring[txvq->last_used_idx & qsz_mask].len = 0;
1627           vhost_user_log_dirty_ring (vui, txvq,
1628                                      ring[txvq->last_used_idx & qsz_mask]);
1629
1630           /* The buffer should already be initialized */
1631           b_head->total_length_not_including_first_buffer = 0;
1632           b_head->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
1633
1634           if (PREDICT_FALSE (n_trace))
1635             {
1636               //TODO: next_index is not exactly known at that point
1637               vlib_trace_buffer (vm, node, next_index, b_head,
1638                                  /* follow_chain */ 0);
1639               vhost_trace_t *t0 =
1640                 vlib_add_trace (vm, node, b_head, sizeof (t0[0]));
1641               vhost_user_rx_trace (t0, vui, qid, b_head, txvq);
1642               n_trace--;
1643               vlib_set_trace_count (vm, node, n_trace);
1644             }
1645
1646           /* This depends on the setup but is very consistent
1647            * So I think the CPU branch predictor will make a pretty good job
1648            * at optimizing the decision. */
1649           if (txvq->desc[desc_current].flags & VIRTQ_DESC_F_INDIRECT)
1650             {
1651               desc_table = map_guest_mem (vui, txvq->desc[desc_current].addr,
1652                                           &map_hint);
1653               desc_current = 0;
1654               if (PREDICT_FALSE (desc_table == 0))
1655                 {
1656                   vlib_error_count (vm, node->node_index,
1657                                     VHOST_USER_INPUT_FUNC_ERROR_MMAP_FAIL, 1);
1658                   goto out;
1659                 }
1660             }
1661
1662           if (PREDICT_TRUE (vui->is_any_layout) ||
1663               (!(desc_table[desc_current].flags & VIRTQ_DESC_F_NEXT)))
1664             {
1665               /* ANYLAYOUT or single buffer */
1666               desc_data_offset = vui->virtio_net_hdr_sz;
1667             }
1668           else
1669             {
1670               /* CSR case without ANYLAYOUT, skip 1st buffer */
1671               desc_data_offset = desc_table[desc_current].len;
1672             }
1673
1674           while (1)
1675             {
1676               /* Get more input if necessary. Or end of packet. */
1677               if (desc_data_offset == desc_table[desc_current].len)
1678                 {
1679                   if (PREDICT_FALSE (desc_table[desc_current].flags &
1680                                      VIRTQ_DESC_F_NEXT))
1681                     {
1682                       desc_current = desc_table[desc_current].next;
1683                       desc_data_offset = 0;
1684                     }
1685                   else
1686                     {
1687                       goto out;
1688                     }
1689                 }
1690
1691               /* Get more output if necessary. Or end of packet. */
1692               if (PREDICT_FALSE
1693                   (b_current->current_length == VLIB_BUFFER_DATA_SIZE))
1694                 {
1695                   if (PREDICT_FALSE
1696                       (vum->cpus[thread_index].rx_buffers_len == 0))
1697                     {
1698                       /* Cancel speculation */
1699                       to_next--;
1700                       n_left_to_next++;
1701
1702                       /*
1703                        * Checking if there are some left buffers.
1704                        * If not, just rewind the used buffers and stop.
1705                        * Note: Scheduled copies are not cancelled. This is
1706                        * not an issue as they would still be valid. Useless,
1707                        * but valid.
1708                        */
1709                       vhost_user_input_rewind_buffers (vm,
1710                                                        &vum->cpus
1711                                                        [thread_index],
1712                                                        b_head);
1713                       n_left = 0;
1714                       goto stop;
1715                     }
1716
1717                   /* Get next output */
1718                   vum->cpus[thread_index].rx_buffers_len--;
1719                   u32 bi_next =
1720                     (vum->cpus[thread_index].rx_buffers)[vum->cpus
1721                                                          [thread_index].rx_buffers_len];
1722                   b_current->next_buffer = bi_next;
1723                   b_current->flags |= VLIB_BUFFER_NEXT_PRESENT;
1724                   bi_current = bi_next;
1725                   b_current = vlib_get_buffer (vm, bi_current);
1726                 }
1727
1728               /* Prepare a copy order executed later for the data */
1729               vhost_copy_t *cpy = &vum->cpus[thread_index].copy[copy_len];
1730               copy_len++;
1731               u32 desc_data_l =
1732                 desc_table[desc_current].len - desc_data_offset;
1733               cpy->len = VLIB_BUFFER_DATA_SIZE - b_current->current_length;
1734               cpy->len = (cpy->len > desc_data_l) ? desc_data_l : cpy->len;
1735               cpy->dst = (uword) (vlib_buffer_get_current (b_current) +
1736                                   b_current->current_length);
1737               cpy->src = desc_table[desc_current].addr + desc_data_offset;
1738
1739               desc_data_offset += cpy->len;
1740
1741               b_current->current_length += cpy->len;
1742               b_head->total_length_not_including_first_buffer += cpy->len;
1743             }
1744
1745         out:
1746           CLIB_PREFETCH (&n_left, sizeof (n_left), LOAD);
1747
1748           n_rx_bytes += b_head->total_length_not_including_first_buffer;
1749           n_rx_packets++;
1750
1751           b_head->total_length_not_including_first_buffer -=
1752             b_head->current_length;
1753
1754           /* consume the descriptor and return it as used */
1755           txvq->last_avail_idx++;
1756           txvq->last_used_idx++;
1757
1758           VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b_head);
1759
1760           vnet_buffer (b_head)->sw_if_index[VLIB_RX] = vui->sw_if_index;
1761           vnet_buffer (b_head)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1762           b_head->error = 0;
1763
1764           {
1765             u32 next0 = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT;
1766
1767             /* redirect if feature path enabled */
1768             vnet_feature_start_device_input_x1 (vui->sw_if_index, &next0,
1769                                                 b_head);
1770
1771             u32 bi = to_next[-1];       //Cannot use to_next[-1] in the macro
1772             vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1773                                              to_next, n_left_to_next,
1774                                              bi, next0);
1775           }
1776
1777           n_left--;
1778
1779           /*
1780            * Although separating memory copies from virtio ring parsing
1781            * is beneficial, we can offer to perform the copies from time
1782            * to time in order to free some space in the ring.
1783            */
1784           if (PREDICT_FALSE (copy_len >= VHOST_USER_RX_COPY_THRESHOLD))
1785             {
1786               if (PREDICT_FALSE
1787                   (vhost_user_input_copy (vui, vum->cpus[thread_index].copy,
1788                                           copy_len, &map_hint)))
1789                 {
1790                   vlib_error_count (vm, node->node_index,
1791                                     VHOST_USER_INPUT_FUNC_ERROR_MMAP_FAIL, 1);
1792                 }
1793               copy_len = 0;
1794
1795               /* give buffers back to driver */
1796               CLIB_MEMORY_BARRIER ();
1797               txvq->used->idx = txvq->last_used_idx;
1798               vhost_user_log_dirty_ring (vui, txvq, idx);
1799             }
1800         }
1801     stop:
1802       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1803     }
1804
1805   /* Do the memory copies */
1806   if (PREDICT_FALSE
1807       (vhost_user_input_copy (vui, vum->cpus[thread_index].copy,
1808                               copy_len, &map_hint)))
1809     {
1810       vlib_error_count (vm, node->node_index,
1811                         VHOST_USER_INPUT_FUNC_ERROR_MMAP_FAIL, 1);
1812     }
1813
1814   /* give buffers back to driver */
1815   CLIB_MEMORY_BARRIER ();
1816   txvq->used->idx = txvq->last_used_idx;
1817   vhost_user_log_dirty_ring (vui, txvq, idx);
1818
1819   /* interrupt (call) handling */
1820   if ((txvq->callfd_idx != ~0) &&
1821       !(txvq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT))
1822     {
1823       txvq->n_since_last_int += n_rx_packets;
1824
1825       if (txvq->n_since_last_int > vum->coalesce_frames)
1826         vhost_user_send_call (vm, txvq);
1827     }
1828
1829   /* increase rx counters */
1830   vlib_increment_combined_counter
1831     (vnet_main.interface_main.combined_sw_if_counters
1832      + VNET_INTERFACE_COUNTER_RX,
1833      vlib_get_thread_index (), vui->sw_if_index, n_rx_packets, n_rx_bytes);
1834
1835   vnet_device_increment_rx_packets (thread_index, n_rx_packets);
1836
1837   return n_rx_packets;
1838 }
1839
1840 static uword
1841 vhost_user_input (vlib_main_t * vm,
1842                   vlib_node_runtime_t * node, vlib_frame_t * f)
1843 {
1844   vhost_user_main_t *vum = &vhost_user_main;
1845   uword n_rx_packets = 0;
1846   vhost_user_intf_t *vui;
1847   vnet_device_input_runtime_t *rt =
1848     (vnet_device_input_runtime_t *) node->runtime_data;
1849   vnet_device_and_queue_t *dq;
1850
1851   vec_foreach (dq, rt->devices_and_queues)
1852   {
1853     if (clib_smp_swap (&dq->interrupt_pending, 0) ||
1854         (node->state == VLIB_NODE_STATE_POLLING))
1855       {
1856         vui =
1857           pool_elt_at_index (vum->vhost_user_interfaces, dq->dev_instance);
1858         n_rx_packets = vhost_user_if_input (vm, vum, vui, dq->queue_id, node,
1859                                             dq->mode);
1860       }
1861   }
1862
1863   return n_rx_packets;
1864 }
1865
1866 /* *INDENT-OFF* */
1867 VLIB_REGISTER_NODE (vhost_user_input_node) = {
1868   .function = vhost_user_input,
1869   .type = VLIB_NODE_TYPE_INPUT,
1870   .name = "vhost-user-input",
1871   .sibling_of = "device-input",
1872
1873   /* Will be enabled if/when hardware is detected. */
1874   .state = VLIB_NODE_STATE_DISABLED,
1875
1876   .format_buffer = format_ethernet_header_with_length,
1877   .format_trace = format_vhost_trace,
1878
1879   .n_errors = VHOST_USER_INPUT_FUNC_N_ERROR,
1880   .error_strings = vhost_user_input_func_error_strings,
1881 };
1882
1883 VLIB_NODE_FUNCTION_MULTIARCH (vhost_user_input_node, vhost_user_input)
1884 /* *INDENT-ON* */
1885
1886
1887 void
1888 vhost_user_tx_trace (vhost_trace_t * t,
1889                      vhost_user_intf_t * vui, u16 qid,
1890                      vlib_buffer_t * b, vhost_user_vring_t * rxvq)
1891 {
1892   vhost_user_main_t *vum = &vhost_user_main;
1893   u32 qsz_mask = rxvq->qsz - 1;
1894   u32 last_avail_idx = rxvq->last_avail_idx;
1895   u32 desc_current = rxvq->avail->ring[last_avail_idx & qsz_mask];
1896   vring_desc_t *hdr_desc = 0;
1897   u32 hint = 0;
1898
1899   memset (t, 0, sizeof (*t));
1900   t->device_index = vui - vum->vhost_user_interfaces;
1901   t->qid = qid;
1902
1903   hdr_desc = &rxvq->desc[desc_current];
1904   if (rxvq->desc[desc_current].flags & VIRTQ_DESC_F_INDIRECT)
1905     {
1906       t->virtio_ring_flags |= 1 << VIRTIO_TRACE_F_INDIRECT;
1907       /* Header is the first here */
1908       hdr_desc = map_guest_mem (vui, rxvq->desc[desc_current].addr, &hint);
1909     }
1910   if (rxvq->desc[desc_current].flags & VIRTQ_DESC_F_NEXT)
1911     {
1912       t->virtio_ring_flags |= 1 << VIRTIO_TRACE_F_SIMPLE_CHAINED;
1913     }
1914   if (!(rxvq->desc[desc_current].flags & VIRTQ_DESC_F_NEXT) &&
1915       !(rxvq->desc[desc_current].flags & VIRTQ_DESC_F_INDIRECT))
1916     {
1917       t->virtio_ring_flags |= 1 << VIRTIO_TRACE_F_SINGLE_DESC;
1918     }
1919
1920   t->first_desc_len = hdr_desc ? hdr_desc->len : 0;
1921 }
1922
1923 static_always_inline u32
1924 vhost_user_tx_copy (vhost_user_intf_t * vui, vhost_copy_t * cpy,
1925                     u16 copy_len, u32 * map_hint)
1926 {
1927   void *dst0, *dst1, *dst2, *dst3;
1928   if (PREDICT_TRUE (copy_len >= 4))
1929     {
1930       if (PREDICT_FALSE (!(dst2 = map_guest_mem (vui, cpy[0].dst, map_hint))))
1931         return 1;
1932       if (PREDICT_FALSE (!(dst3 = map_guest_mem (vui, cpy[1].dst, map_hint))))
1933         return 1;
1934       while (PREDICT_TRUE (copy_len >= 4))
1935         {
1936           dst0 = dst2;
1937           dst1 = dst3;
1938
1939           if (PREDICT_FALSE
1940               (!(dst2 = map_guest_mem (vui, cpy[2].dst, map_hint))))
1941             return 1;
1942           if (PREDICT_FALSE
1943               (!(dst3 = map_guest_mem (vui, cpy[3].dst, map_hint))))
1944             return 1;
1945
1946           CLIB_PREFETCH ((void *) cpy[2].src, 64, LOAD);
1947           CLIB_PREFETCH ((void *) cpy[3].src, 64, LOAD);
1948
1949           clib_memcpy (dst0, (void *) cpy[0].src, cpy[0].len);
1950           clib_memcpy (dst1, (void *) cpy[1].src, cpy[1].len);
1951
1952           vhost_user_log_dirty_pages_2 (vui, cpy[0].dst, cpy[0].len, 1);
1953           vhost_user_log_dirty_pages_2 (vui, cpy[1].dst, cpy[1].len, 1);
1954           copy_len -= 2;
1955           cpy += 2;
1956         }
1957     }
1958   while (copy_len)
1959     {
1960       if (PREDICT_FALSE (!(dst0 = map_guest_mem (vui, cpy->dst, map_hint))))
1961         return 1;
1962       clib_memcpy (dst0, (void *) cpy->src, cpy->len);
1963       vhost_user_log_dirty_pages_2 (vui, cpy->dst, cpy->len, 1);
1964       copy_len -= 1;
1965       cpy += 1;
1966     }
1967   return 0;
1968 }
1969
1970
1971 static uword
1972 vhost_user_tx (vlib_main_t * vm,
1973                vlib_node_runtime_t * node, vlib_frame_t * frame)
1974 {
1975   u32 *buffers = vlib_frame_args (frame);
1976   u32 n_left = frame->n_vectors;
1977   vhost_user_main_t *vum = &vhost_user_main;
1978   vnet_interface_output_runtime_t *rd = (void *) node->runtime_data;
1979   vhost_user_intf_t *vui =
1980     pool_elt_at_index (vum->vhost_user_interfaces, rd->dev_instance);
1981   u32 qid = ~0;
1982   vhost_user_vring_t *rxvq;
1983   u16 qsz_mask;
1984   u8 error;
1985   u32 thread_index = vlib_get_thread_index ();
1986   u32 map_hint = 0;
1987   u8 retry = 8;
1988   u16 copy_len;
1989   u16 tx_headers_len;
1990
1991   if (PREDICT_FALSE (!vui->admin_up))
1992     {
1993       error = VHOST_USER_TX_FUNC_ERROR_DOWN;
1994       goto done3;
1995     }
1996
1997   if (PREDICT_FALSE (!vui->is_up))
1998     {
1999       error = VHOST_USER_TX_FUNC_ERROR_NOT_READY;
2000       goto done3;
2001     }
2002
2003   qid =
2004     VHOST_VRING_IDX_RX (*vec_elt_at_index
2005                         (vui->per_cpu_tx_qid, vlib_get_thread_index ()));
2006   rxvq = &vui->vrings[qid];
2007   if (PREDICT_FALSE (vui->use_tx_spinlock))
2008     vhost_user_vring_lock (vui, qid);
2009
2010   qsz_mask = rxvq->qsz - 1;     /* qsz is always power of 2 */
2011
2012 retry:
2013   error = VHOST_USER_TX_FUNC_ERROR_NONE;
2014   tx_headers_len = 0;
2015   copy_len = 0;
2016   while (n_left > 0)
2017     {
2018       vlib_buffer_t *b0, *current_b0;
2019       u16 desc_head, desc_index, desc_len;
2020       vring_desc_t *desc_table;
2021       uword buffer_map_addr;
2022       u32 buffer_len;
2023       u16 bytes_left;
2024
2025       if (PREDICT_TRUE (n_left > 1))
2026         vlib_prefetch_buffer_with_index (vm, buffers[1], LOAD);
2027
2028       b0 = vlib_get_buffer (vm, buffers[0]);
2029
2030       if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2031         {
2032           vum->cpus[thread_index].current_trace =
2033             vlib_add_trace (vm, node, b0,
2034                             sizeof (*vum->cpus[thread_index].current_trace));
2035           vhost_user_tx_trace (vum->cpus[thread_index].current_trace,
2036                                vui, qid / 2, b0, rxvq);
2037         }
2038
2039       if (PREDICT_FALSE (rxvq->last_avail_idx == rxvq->avail->idx))
2040         {
2041           error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
2042           goto done;
2043         }
2044
2045       desc_table = rxvq->desc;
2046       desc_head = desc_index =
2047         rxvq->avail->ring[rxvq->last_avail_idx & qsz_mask];
2048
2049       /* Go deeper in case of indirect descriptor
2050        * I don't know of any driver providing indirect for RX. */
2051       if (PREDICT_FALSE (rxvq->desc[desc_head].flags & VIRTQ_DESC_F_INDIRECT))
2052         {
2053           if (PREDICT_FALSE
2054               (rxvq->desc[desc_head].len < sizeof (vring_desc_t)))
2055             {
2056               error = VHOST_USER_TX_FUNC_ERROR_INDIRECT_OVERFLOW;
2057               goto done;
2058             }
2059           if (PREDICT_FALSE
2060               (!(desc_table =
2061                  map_guest_mem (vui, rxvq->desc[desc_index].addr,
2062                                 &map_hint))))
2063             {
2064               error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
2065               goto done;
2066             }
2067           desc_index = 0;
2068         }
2069
2070       desc_len = vui->virtio_net_hdr_sz;
2071       buffer_map_addr = desc_table[desc_index].addr;
2072       buffer_len = desc_table[desc_index].len;
2073
2074       {
2075         // Get a header from the header array
2076         virtio_net_hdr_mrg_rxbuf_t *hdr =
2077           &vum->cpus[thread_index].tx_headers[tx_headers_len];
2078         tx_headers_len++;
2079         hdr->hdr.flags = 0;
2080         hdr->hdr.gso_type = 0;
2081         hdr->num_buffers = 1;   //This is local, no need to check
2082
2083         // Prepare a copy order executed later for the header
2084         vhost_copy_t *cpy = &vum->cpus[thread_index].copy[copy_len];
2085         copy_len++;
2086         cpy->len = vui->virtio_net_hdr_sz;
2087         cpy->dst = buffer_map_addr;
2088         cpy->src = (uword) hdr;
2089       }
2090
2091       buffer_map_addr += vui->virtio_net_hdr_sz;
2092       buffer_len -= vui->virtio_net_hdr_sz;
2093       bytes_left = b0->current_length;
2094       current_b0 = b0;
2095       while (1)
2096         {
2097           if (buffer_len == 0)
2098             {                   //Get new output
2099               if (desc_table[desc_index].flags & VIRTQ_DESC_F_NEXT)
2100                 {
2101                   //Next one is chained
2102                   desc_index = desc_table[desc_index].next;
2103                   buffer_map_addr = desc_table[desc_index].addr;
2104                   buffer_len = desc_table[desc_index].len;
2105                 }
2106               else if (vui->virtio_net_hdr_sz == 12)    //MRG is available
2107                 {
2108                   virtio_net_hdr_mrg_rxbuf_t *hdr =
2109                     &vum->cpus[thread_index].tx_headers[tx_headers_len - 1];
2110
2111                   //Move from available to used buffer
2112                   rxvq->used->ring[rxvq->last_used_idx & qsz_mask].id =
2113                     desc_head;
2114                   rxvq->used->ring[rxvq->last_used_idx & qsz_mask].len =
2115                     desc_len;
2116                   vhost_user_log_dirty_ring (vui, rxvq,
2117                                              ring[rxvq->last_used_idx &
2118                                                   qsz_mask]);
2119
2120                   rxvq->last_avail_idx++;
2121                   rxvq->last_used_idx++;
2122                   hdr->num_buffers++;
2123                   desc_len = 0;
2124
2125                   if (PREDICT_FALSE
2126                       (rxvq->last_avail_idx == rxvq->avail->idx))
2127                     {
2128                       //Dequeue queued descriptors for this packet
2129                       rxvq->last_used_idx -= hdr->num_buffers - 1;
2130                       rxvq->last_avail_idx -= hdr->num_buffers - 1;
2131                       error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
2132                       goto done;
2133                     }
2134
2135                   desc_table = rxvq->desc;
2136                   desc_head = desc_index =
2137                     rxvq->avail->ring[rxvq->last_avail_idx & qsz_mask];
2138                   if (PREDICT_FALSE
2139                       (rxvq->desc[desc_head].flags & VIRTQ_DESC_F_INDIRECT))
2140                     {
2141                       //It is seriously unlikely that a driver will put indirect descriptor
2142                       //after non-indirect descriptor.
2143                       if (PREDICT_FALSE
2144                           (rxvq->desc[desc_head].len < sizeof (vring_desc_t)))
2145                         {
2146                           error = VHOST_USER_TX_FUNC_ERROR_INDIRECT_OVERFLOW;
2147                           goto done;
2148                         }
2149                       if (PREDICT_FALSE
2150                           (!(desc_table =
2151                              map_guest_mem (vui,
2152                                             rxvq->desc[desc_index].addr,
2153                                             &map_hint))))
2154                         {
2155                           error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
2156                           goto done;
2157                         }
2158                       desc_index = 0;
2159                     }
2160                   buffer_map_addr = desc_table[desc_index].addr;
2161                   buffer_len = desc_table[desc_index].len;
2162                 }
2163               else
2164                 {
2165                   error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOMRG;
2166                   goto done;
2167                 }
2168             }
2169
2170           {
2171             vhost_copy_t *cpy = &vum->cpus[thread_index].copy[copy_len];
2172             copy_len++;
2173             cpy->len = bytes_left;
2174             cpy->len = (cpy->len > buffer_len) ? buffer_len : cpy->len;
2175             cpy->dst = buffer_map_addr;
2176             cpy->src = (uword) vlib_buffer_get_current (current_b0) +
2177               current_b0->current_length - bytes_left;
2178
2179             bytes_left -= cpy->len;
2180             buffer_len -= cpy->len;
2181             buffer_map_addr += cpy->len;
2182             desc_len += cpy->len;
2183
2184             CLIB_PREFETCH (&rxvq->desc, CLIB_CACHE_LINE_BYTES, LOAD);
2185           }
2186
2187           // Check if vlib buffer has more data. If not, get more or break.
2188           if (PREDICT_TRUE (!bytes_left))
2189             {
2190               if (PREDICT_FALSE
2191                   (current_b0->flags & VLIB_BUFFER_NEXT_PRESENT))
2192                 {
2193                   current_b0 = vlib_get_buffer (vm, current_b0->next_buffer);
2194                   bytes_left = current_b0->current_length;
2195                 }
2196               else
2197                 {
2198                   //End of packet
2199                   break;
2200                 }
2201             }
2202         }
2203
2204       //Move from available to used ring
2205       rxvq->used->ring[rxvq->last_used_idx & qsz_mask].id = desc_head;
2206       rxvq->used->ring[rxvq->last_used_idx & qsz_mask].len = desc_len;
2207       vhost_user_log_dirty_ring (vui, rxvq,
2208                                  ring[rxvq->last_used_idx & qsz_mask]);
2209       rxvq->last_avail_idx++;
2210       rxvq->last_used_idx++;
2211
2212       if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2213         {
2214           vum->cpus[thread_index].current_trace->hdr =
2215             vum->cpus[thread_index].tx_headers[tx_headers_len - 1];
2216         }
2217
2218       n_left--;                 //At the end for error counting when 'goto done' is invoked
2219       buffers++;
2220     }
2221
2222 done:
2223   //Do the memory copies
2224   if (PREDICT_FALSE
2225       (vhost_user_tx_copy (vui, vum->cpus[thread_index].copy,
2226                            copy_len, &map_hint)))
2227     {
2228       vlib_error_count (vm, node->node_index,
2229                         VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL, 1);
2230     }
2231
2232   CLIB_MEMORY_BARRIER ();
2233   rxvq->used->idx = rxvq->last_used_idx;
2234   vhost_user_log_dirty_ring (vui, rxvq, idx);
2235
2236   /*
2237    * When n_left is set, error is always set to something too.
2238    * In case error is due to lack of remaining buffers, we go back up and
2239    * retry.
2240    * The idea is that it is better to waste some time on packets
2241    * that have been processed already than dropping them and get
2242    * more fresh packets with a good likelyhood that they will be dropped too.
2243    * This technique also gives more time to VM driver to pick-up packets.
2244    * In case the traffic flows from physical to virtual interfaces, this
2245    * technique will end-up leveraging the physical NIC buffer in order to
2246    * absorb the VM's CPU jitter.
2247    */
2248   if (n_left && (error == VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF) && retry)
2249     {
2250       retry--;
2251       goto retry;
2252     }
2253
2254   /* interrupt (call) handling */
2255   if ((rxvq->callfd_idx != ~0) &&
2256       !(rxvq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT))
2257     {
2258       rxvq->n_since_last_int += frame->n_vectors - n_left;
2259
2260       if (rxvq->n_since_last_int > vum->coalesce_frames)
2261         vhost_user_send_call (vm, rxvq);
2262     }
2263
2264   vhost_user_vring_unlock (vui, qid);
2265
2266 done3:
2267   if (PREDICT_FALSE (n_left && error != VHOST_USER_TX_FUNC_ERROR_NONE))
2268     {
2269       vlib_error_count (vm, node->node_index, error, n_left);
2270       vlib_increment_simple_counter
2271         (vnet_main.interface_main.sw_if_counters
2272          + VNET_INTERFACE_COUNTER_DROP,
2273          vlib_get_thread_index (), vui->sw_if_index, n_left);
2274     }
2275
2276   vlib_buffer_free (vm, vlib_frame_args (frame), frame->n_vectors);
2277   return frame->n_vectors;
2278 }
2279
2280 static uword
2281 vhost_user_send_interrupt_process (vlib_main_t * vm,
2282                                    vlib_node_runtime_t * rt, vlib_frame_t * f)
2283 {
2284   vhost_user_intf_t *vui;
2285   f64 timeout = 3153600000.0 /* 100 years */ ;
2286   uword event_type, *event_data = 0;
2287   vhost_user_main_t *vum = &vhost_user_main;
2288   u16 *queue;
2289   f64 now, poll_time_remaining;
2290   f64 next_timeout;
2291   u8 stop_timer = 0;
2292
2293   while (1)
2294     {
2295       poll_time_remaining =
2296         vlib_process_wait_for_event_or_clock (vm, timeout);
2297       event_type = vlib_process_get_events (vm, &event_data);
2298       vec_reset_length (event_data);
2299
2300       /*
2301        * Use the remaining timeout if it is less than coalesce time to avoid
2302        * resetting the existing timer in the middle of expiration
2303        */
2304       timeout = poll_time_remaining;
2305       if (vlib_process_suspend_time_is_zero (timeout) ||
2306           (timeout > vum->coalesce_time))
2307         timeout = vum->coalesce_time;
2308
2309       now = vlib_time_now (vm);
2310       switch (event_type)
2311         {
2312         case VHOST_USER_EVENT_STOP_TIMER:
2313           stop_timer = 1;
2314           break;
2315
2316         case VHOST_USER_EVENT_START_TIMER:
2317           stop_timer = 0;
2318           if (!vlib_process_suspend_time_is_zero (poll_time_remaining))
2319             break;
2320           /* fall through */
2321
2322         case ~0:
2323           /* *INDENT-OFF* */
2324           pool_foreach (vui, vum->vhost_user_interfaces, {
2325               next_timeout = timeout;
2326               vec_foreach (queue, vui->rx_queues)
2327                 {
2328                   vhost_user_vring_t *rxvq =
2329                     &vui->vrings[VHOST_VRING_IDX_RX (*queue)];
2330                   vhost_user_vring_t *txvq =
2331                     &vui->vrings[VHOST_VRING_IDX_TX (*queue)];
2332
2333                   if (txvq->n_since_last_int)
2334                     {
2335                       if (now >= txvq->int_deadline)
2336                         vhost_user_send_call (vm, txvq);
2337                       else
2338                         next_timeout = txvq->int_deadline - now;
2339                     }
2340
2341                   if (rxvq->n_since_last_int)
2342                     {
2343                       if (now >= rxvq->int_deadline)
2344                         vhost_user_send_call (vm, rxvq);
2345                       else
2346                         next_timeout = rxvq->int_deadline - now;
2347                     }
2348
2349                   if ((next_timeout < timeout) && (next_timeout > 0.0))
2350                     timeout = next_timeout;
2351                 }
2352           });
2353           /* *INDENT-ON* */
2354           break;
2355
2356         default:
2357           clib_warning ("BUG: unhandled event type %d", event_type);
2358           break;
2359         }
2360       /* No less than 1 millisecond */
2361       if (timeout < 1e-3)
2362         timeout = 1e-3;
2363       if (stop_timer)
2364         timeout = 3153600000.0;
2365     }
2366   return 0;
2367 }
2368
2369 /* *INDENT-OFF* */
2370 VLIB_REGISTER_NODE (vhost_user_send_interrupt_node,static) = {
2371     .function = vhost_user_send_interrupt_process,
2372     .type = VLIB_NODE_TYPE_PROCESS,
2373     .name = "vhost-user-send-interrupt-process",
2374 };
2375 /* *INDENT-ON* */
2376
2377 static clib_error_t *
2378 vhost_user_interface_rx_mode_change (vnet_main_t * vnm, u32 hw_if_index,
2379                                      u32 qid, vnet_hw_interface_rx_mode mode)
2380 {
2381   vlib_main_t *vm = vnm->vlib_main;
2382   vnet_hw_interface_t *hif = vnet_get_hw_interface (vnm, hw_if_index);
2383   vhost_user_main_t *vum = &vhost_user_main;
2384   vhost_user_intf_t *vui =
2385     pool_elt_at_index (vum->vhost_user_interfaces, hif->dev_instance);
2386   vhost_user_vring_t *txvq = &vui->vrings[VHOST_VRING_IDX_TX (qid)];
2387
2388   if ((mode == VNET_HW_INTERFACE_RX_MODE_INTERRUPT) ||
2389       (mode == VNET_HW_INTERFACE_RX_MODE_ADAPTIVE))
2390     {
2391       if (txvq->mode == VNET_HW_INTERFACE_RX_MODE_POLLING)
2392         {
2393           vum->ifq_count++;
2394           // Start the timer if this is the first encounter on interrupt
2395           // interface/queue
2396           if ((vum->ifq_count == 1) &&
2397               (vum->coalesce_time > 0.0) && (vum->coalesce_frames > 0))
2398             vlib_process_signal_event (vm,
2399                                        vhost_user_send_interrupt_node.index,
2400                                        VHOST_USER_EVENT_START_TIMER, 0);
2401         }
2402     }
2403   else if (mode == VNET_HW_INTERFACE_RX_MODE_POLLING)
2404     {
2405       if (((txvq->mode == VNET_HW_INTERFACE_RX_MODE_INTERRUPT) ||
2406            (txvq->mode == VNET_HW_INTERFACE_RX_MODE_ADAPTIVE)) &&
2407           vum->ifq_count)
2408         {
2409           vum->ifq_count--;
2410           // Stop the timer if there is no more interrupt interface/queue
2411           if ((vum->ifq_count == 0) &&
2412               (vum->coalesce_time > 0.0) && (vum->coalesce_frames > 0))
2413             vlib_process_signal_event (vm,
2414                                        vhost_user_send_interrupt_node.index,
2415                                        VHOST_USER_EVENT_STOP_TIMER, 0);
2416         }
2417     }
2418
2419   txvq->mode = mode;
2420   if (mode == VNET_HW_INTERFACE_RX_MODE_POLLING)
2421     txvq->used->flags = VRING_USED_F_NO_NOTIFY;
2422   else if ((mode == VNET_HW_INTERFACE_RX_MODE_ADAPTIVE) ||
2423            (mode == VNET_HW_INTERFACE_RX_MODE_INTERRUPT))
2424     txvq->used->flags = 0;
2425   else
2426     {
2427       clib_warning ("BUG: unhandled mode %d changed for if %d queue %d", mode,
2428                     hw_if_index, qid);
2429       return clib_error_return (0, "unsupported");
2430     }
2431
2432   return 0;
2433 }
2434
2435 static clib_error_t *
2436 vhost_user_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index,
2437                                     u32 flags)
2438 {
2439   vnet_hw_interface_t *hif = vnet_get_hw_interface (vnm, hw_if_index);
2440   uword is_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
2441   vhost_user_main_t *vum = &vhost_user_main;
2442   vhost_user_intf_t *vui =
2443     pool_elt_at_index (vum->vhost_user_interfaces, hif->dev_instance);
2444
2445   vui->admin_up = is_up;
2446
2447   if (is_up)
2448     vnet_hw_interface_set_flags (vnm, vui->hw_if_index,
2449                                  VNET_HW_INTERFACE_FLAG_LINK_UP);
2450
2451   return /* no error */ 0;
2452 }
2453
2454 /* *INDENT-OFF* */
2455 VNET_DEVICE_CLASS (vhost_user_dev_class,static) = {
2456   .name = "vhost-user",
2457   .tx_function = vhost_user_tx,
2458   .tx_function_n_errors = VHOST_USER_TX_FUNC_N_ERROR,
2459   .tx_function_error_strings = vhost_user_tx_func_error_strings,
2460   .format_device_name = format_vhost_user_interface_name,
2461   .name_renumber = vhost_user_name_renumber,
2462   .admin_up_down_function = vhost_user_interface_admin_up_down,
2463   .rx_mode_change_function = vhost_user_interface_rx_mode_change,
2464   .format_tx_trace = format_vhost_trace,
2465 };
2466
2467 VLIB_DEVICE_TX_FUNCTION_MULTIARCH (vhost_user_dev_class,
2468                                    vhost_user_tx)
2469 /* *INDENT-ON* */
2470
2471 static uword
2472 vhost_user_process (vlib_main_t * vm,
2473                     vlib_node_runtime_t * rt, vlib_frame_t * f)
2474 {
2475   vhost_user_main_t *vum = &vhost_user_main;
2476   vhost_user_intf_t *vui;
2477   struct sockaddr_un sun;
2478   int sockfd;
2479   unix_file_t template = { 0 };
2480   f64 timeout = 3153600000.0 /* 100 years */ ;
2481   uword *event_data = 0;
2482
2483   sockfd = -1;
2484   sun.sun_family = AF_UNIX;
2485   template.read_function = vhost_user_socket_read;
2486   template.error_function = vhost_user_socket_error;
2487
2488   while (1)
2489     {
2490       vlib_process_wait_for_event_or_clock (vm, timeout);
2491       vlib_process_get_events (vm, &event_data);
2492       vec_reset_length (event_data);
2493
2494       timeout = 3.0;
2495
2496       /* *INDENT-OFF* */
2497       pool_foreach (vui, vum->vhost_user_interfaces, {
2498
2499           if (vui->unix_server_index == ~0) { //Nothing to do for server sockets
2500               if (vui->unix_file_index == ~0)
2501                 {
2502                   if ((sockfd < 0) &&
2503                       ((sockfd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0))
2504                     {
2505                       /*
2506                        * 1st time error or new error for this interface,
2507                        * spit out the message and record the error
2508                        */
2509                       if (!vui->sock_errno || (vui->sock_errno != errno))
2510                         {
2511                           clib_unix_warning
2512                             ("Error: Could not open unix socket for %s",
2513                              vui->sock_filename);
2514                           vui->sock_errno = errno;
2515                         }
2516                       continue;
2517                     }
2518
2519                   /* try to connect */
2520                   strncpy (sun.sun_path, (char *) vui->sock_filename,
2521                            sizeof (sun.sun_path) - 1);
2522
2523                   /* Avoid hanging VPP if the other end does not accept */
2524                   if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0)
2525                       clib_unix_warning ("fcntl");
2526
2527                   if (connect (sockfd, (struct sockaddr *) &sun,
2528                                sizeof (struct sockaddr_un)) == 0)
2529                     {
2530                       /* Set the socket to blocking as it was before */
2531                       if (fcntl(sockfd, F_SETFL, 0) < 0)
2532                         clib_unix_warning ("fcntl2");
2533
2534                       vui->sock_errno = 0;
2535                       template.file_descriptor = sockfd;
2536                       template.private_data =
2537                           vui - vhost_user_main.vhost_user_interfaces;
2538                       vui->unix_file_index = unix_file_add (&unix_main, &template);
2539
2540                       /* This sockfd is considered consumed */
2541                       sockfd = -1;
2542                     }
2543                   else
2544                     {
2545                       vui->sock_errno = errno;
2546                     }
2547                 }
2548               else
2549                 {
2550                   /* check if socket is alive */
2551                   int error = 0;
2552                   socklen_t len = sizeof (error);
2553                   int fd = UNIX_GET_FD(vui->unix_file_index);
2554                   int retval =
2555                       getsockopt (fd, SOL_SOCKET, SO_ERROR, &error, &len);
2556
2557                   if (retval)
2558                     {
2559                       DBG_SOCK ("getsockopt returned %d", retval);
2560                       vhost_user_if_disconnect (vui);
2561                     }
2562                 }
2563           }
2564       });
2565       /* *INDENT-ON* */
2566     }
2567   return 0;
2568 }
2569
2570 /* *INDENT-OFF* */
2571 VLIB_REGISTER_NODE (vhost_user_process_node,static) = {
2572     .function = vhost_user_process,
2573     .type = VLIB_NODE_TYPE_PROCESS,
2574     .name = "vhost-user-process",
2575 };
2576 /* *INDENT-ON* */
2577
2578 /**
2579  * Disables and reset interface structure.
2580  * It can then be either init again, or removed from used interfaces.
2581  */
2582 static void
2583 vhost_user_term_if (vhost_user_intf_t * vui)
2584 {
2585   int q;
2586   vhost_user_main_t *vum = &vhost_user_main;
2587
2588   // disconnect interface sockets
2589   vhost_user_if_disconnect (vui);
2590   vhost_user_update_iface_state (vui);
2591
2592   for (q = 0; q < VHOST_VRING_MAX_N; q++)
2593     {
2594       clib_mem_free ((void *) vui->vring_locks[q]);
2595     }
2596
2597   if (vui->unix_server_index != ~0)
2598     {
2599       //Close server socket
2600       unix_file_t *uf = pool_elt_at_index (unix_main.file_pool,
2601                                            vui->unix_server_index);
2602       unix_file_del (&unix_main, uf);
2603       vui->unix_server_index = ~0;
2604       unlink (vui->sock_filename);
2605     }
2606
2607   mhash_unset (&vum->if_index_by_sock_name, vui->sock_filename,
2608                &vui->if_index);
2609 }
2610
2611 int
2612 vhost_user_delete_if (vnet_main_t * vnm, vlib_main_t * vm, u32 sw_if_index)
2613 {
2614   vhost_user_main_t *vum = &vhost_user_main;
2615   vhost_user_intf_t *vui;
2616   int rv = 0;
2617   vnet_hw_interface_t *hwif;
2618   u16 *queue;
2619
2620   if (!(hwif = vnet_get_sup_hw_interface (vnm, sw_if_index)) ||
2621       hwif->dev_class_index != vhost_user_dev_class.index)
2622     return VNET_API_ERROR_INVALID_SW_IF_INDEX;
2623
2624   DBG_SOCK ("Deleting vhost-user interface %s (instance %d)",
2625             hwif->name, hwif->dev_instance);
2626
2627   vui = pool_elt_at_index (vum->vhost_user_interfaces, hwif->dev_instance);
2628
2629   vec_foreach (queue, vui->rx_queues)
2630   {
2631     vhost_user_vring_t *txvq;
2632
2633     txvq = &vui->vrings[VHOST_VRING_IDX_TX (*queue)];
2634     if ((vum->ifq_count > 0) &&
2635         ((txvq->mode == VNET_HW_INTERFACE_RX_MODE_INTERRUPT) ||
2636          (txvq->mode == VNET_HW_INTERFACE_RX_MODE_ADAPTIVE)))
2637       {
2638         vum->ifq_count--;
2639         // Stop the timer if there is no more interrupt interface/queue
2640         if ((vum->ifq_count == 0) &&
2641             (vum->coalesce_time > 0.0) && (vum->coalesce_frames > 0))
2642           {
2643             vlib_process_signal_event (vm,
2644                                        vhost_user_send_interrupt_node.index,
2645                                        VHOST_USER_EVENT_STOP_TIMER, 0);
2646             break;
2647           }
2648       }
2649   }
2650
2651   // Disable and reset interface
2652   vhost_user_term_if (vui);
2653
2654   // Reset renumbered iface
2655   if (hwif->dev_instance <
2656       vec_len (vum->show_dev_instance_by_real_dev_instance))
2657     vum->show_dev_instance_by_real_dev_instance[hwif->dev_instance] = ~0;
2658
2659   // Delete ethernet interface
2660   ethernet_delete_interface (vnm, vui->hw_if_index);
2661
2662   // Back to pool
2663   pool_put (vum->vhost_user_interfaces, vui);
2664
2665   return rv;
2666 }
2667
2668 static clib_error_t *
2669 vhost_user_exit (vlib_main_t * vm)
2670 {
2671   vnet_main_t *vnm = vnet_get_main ();
2672   vhost_user_main_t *vum = &vhost_user_main;
2673   vhost_user_intf_t *vui;
2674
2675   vlib_worker_thread_barrier_sync (vlib_get_main ());
2676   /* *INDENT-OFF* */
2677   pool_foreach (vui, vum->vhost_user_interfaces, {
2678       vhost_user_delete_if (vnm, vm, vui->sw_if_index);
2679   });
2680   /* *INDENT-ON* */
2681   vlib_worker_thread_barrier_release (vlib_get_main ());
2682   return 0;
2683 }
2684
2685 VLIB_MAIN_LOOP_EXIT_FUNCTION (vhost_user_exit);
2686
2687 /**
2688  * Open server unix socket on specified sock_filename.
2689  */
2690 static int
2691 vhost_user_init_server_sock (const char *sock_filename, int *sock_fd)
2692 {
2693   int rv = 0;
2694   struct sockaddr_un un = { };
2695   int fd;
2696   /* create listening socket */
2697   if ((fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
2698     return VNET_API_ERROR_SYSCALL_ERROR_1;
2699
2700   un.sun_family = AF_UNIX;
2701   strncpy ((char *) un.sun_path, (char *) sock_filename,
2702            sizeof (un.sun_path) - 1);
2703
2704   /* remove if exists */
2705   unlink ((char *) sock_filename);
2706
2707   if (bind (fd, (struct sockaddr *) &un, sizeof (un)) == -1)
2708     {
2709       rv = VNET_API_ERROR_SYSCALL_ERROR_2;
2710       goto error;
2711     }
2712
2713   if (listen (fd, 1) == -1)
2714     {
2715       rv = VNET_API_ERROR_SYSCALL_ERROR_3;
2716       goto error;
2717     }
2718
2719   *sock_fd = fd;
2720   return 0;
2721
2722 error:
2723   close (fd);
2724   return rv;
2725 }
2726
2727 /**
2728  * Create ethernet interface for vhost user interface.
2729  */
2730 static void
2731 vhost_user_create_ethernet (vnet_main_t * vnm, vlib_main_t * vm,
2732                             vhost_user_intf_t * vui, u8 * hwaddress)
2733 {
2734   vhost_user_main_t *vum = &vhost_user_main;
2735   u8 hwaddr[6];
2736   clib_error_t *error;
2737
2738   /* create hw and sw interface */
2739   if (hwaddress)
2740     {
2741       clib_memcpy (hwaddr, hwaddress, 6);
2742     }
2743   else
2744     {
2745       random_u32 (&vum->random);
2746       clib_memcpy (hwaddr + 2, &vum->random, sizeof (vum->random));
2747       hwaddr[0] = 2;
2748       hwaddr[1] = 0xfe;
2749     }
2750
2751   error = ethernet_register_interface
2752     (vnm,
2753      vhost_user_dev_class.index,
2754      vui - vum->vhost_user_interfaces /* device instance */ ,
2755      hwaddr /* ethernet address */ ,
2756      &vui->hw_if_index, 0 /* flag change */ );
2757
2758   if (error)
2759     clib_error_report (error);
2760
2761   vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, vui->hw_if_index);
2762   hi->max_l3_packet_bytes[VLIB_RX] = hi->max_l3_packet_bytes[VLIB_TX] = 9000;
2763 }
2764
2765 /*
2766  *  Initialize vui with specified attributes
2767  */
2768 static void
2769 vhost_user_vui_init (vnet_main_t * vnm,
2770                      vhost_user_intf_t * vui,
2771                      int server_sock_fd,
2772                      const char *sock_filename,
2773                      u64 feature_mask, u32 * sw_if_index)
2774 {
2775   vnet_sw_interface_t *sw;
2776   int q;
2777   vhost_user_main_t *vum = &vhost_user_main;
2778   vnet_hw_interface_t *hw;
2779
2780   hw = vnet_get_hw_interface (vnm, vui->hw_if_index);
2781   sw = vnet_get_hw_sw_interface (vnm, vui->hw_if_index);
2782   if (server_sock_fd != -1)
2783     {
2784       unix_file_t template = { 0 };
2785       template.read_function = vhost_user_socksvr_accept_ready;
2786       template.file_descriptor = server_sock_fd;
2787       template.private_data = vui - vum->vhost_user_interfaces; //hw index
2788       vui->unix_server_index = unix_file_add (&unix_main, &template);
2789     }
2790   else
2791     {
2792       vui->unix_server_index = ~0;
2793     }
2794
2795   vui->sw_if_index = sw->sw_if_index;
2796   strncpy (vui->sock_filename, sock_filename,
2797            ARRAY_LEN (vui->sock_filename) - 1);
2798   vui->sock_errno = 0;
2799   vui->is_up = 0;
2800   vui->feature_mask = feature_mask;
2801   vui->unix_file_index = ~0;
2802   vui->log_base_addr = 0;
2803   vui->if_index = vui - vum->vhost_user_interfaces;
2804   mhash_set_mem (&vum->if_index_by_sock_name, vui->sock_filename,
2805                  &vui->if_index, 0);
2806
2807   for (q = 0; q < VHOST_VRING_MAX_N; q++)
2808     vhost_user_vring_init (vui, q);
2809
2810   hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE;
2811   vnet_hw_interface_set_flags (vnm, vui->hw_if_index, 0);
2812
2813   if (sw_if_index)
2814     *sw_if_index = vui->sw_if_index;
2815
2816   for (q = 0; q < VHOST_VRING_MAX_N; q++)
2817     {
2818       vui->vring_locks[q] = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES,
2819                                                     CLIB_CACHE_LINE_BYTES);
2820       memset ((void *) vui->vring_locks[q], 0, CLIB_CACHE_LINE_BYTES);
2821     }
2822
2823   vec_validate (vui->per_cpu_tx_qid,
2824                 vlib_get_thread_main ()->n_vlib_mains - 1);
2825   vhost_user_tx_thread_placement (vui);
2826 }
2827
2828 int
2829 vhost_user_create_if (vnet_main_t * vnm, vlib_main_t * vm,
2830                       const char *sock_filename,
2831                       u8 is_server,
2832                       u32 * sw_if_index,
2833                       u64 feature_mask,
2834                       u8 renumber, u32 custom_dev_instance, u8 * hwaddr)
2835 {
2836   vhost_user_intf_t *vui = NULL;
2837   u32 sw_if_idx = ~0;
2838   int rv = 0;
2839   int server_sock_fd = -1;
2840   vhost_user_main_t *vum = &vhost_user_main;
2841   uword *if_index;
2842
2843   if (sock_filename == NULL || !(strlen (sock_filename) > 0))
2844     {
2845       return VNET_API_ERROR_INVALID_ARGUMENT;
2846     }
2847
2848   if_index = mhash_get (&vum->if_index_by_sock_name, (void *) sock_filename);
2849   if (if_index)
2850     {
2851       if (sw_if_index)
2852         {
2853           vui = &vum->vhost_user_interfaces[*if_index];
2854           *sw_if_index = vui->sw_if_index;
2855         }
2856       return VNET_API_ERROR_IF_ALREADY_EXISTS;
2857     }
2858
2859   if (is_server)
2860     {
2861       if ((rv =
2862            vhost_user_init_server_sock (sock_filename, &server_sock_fd)) != 0)
2863         {
2864           return rv;
2865         }
2866     }
2867
2868   pool_get (vhost_user_main.vhost_user_interfaces, vui);
2869
2870   vhost_user_create_ethernet (vnm, vm, vui, hwaddr);
2871   vhost_user_vui_init (vnm, vui, server_sock_fd, sock_filename,
2872                        feature_mask, &sw_if_idx);
2873
2874   if (renumber)
2875     vnet_interface_name_renumber (sw_if_idx, custom_dev_instance);
2876
2877   if (sw_if_index)
2878     *sw_if_index = sw_if_idx;
2879
2880   // Process node must connect
2881   vlib_process_signal_event (vm, vhost_user_process_node.index, 0, 0);
2882
2883   return rv;
2884 }
2885
2886 int
2887 vhost_user_modify_if (vnet_main_t * vnm, vlib_main_t * vm,
2888                       const char *sock_filename,
2889                       u8 is_server,
2890                       u32 sw_if_index,
2891                       u64 feature_mask, u8 renumber, u32 custom_dev_instance)
2892 {
2893   vhost_user_main_t *vum = &vhost_user_main;
2894   vhost_user_intf_t *vui = NULL;
2895   u32 sw_if_idx = ~0;
2896   int server_sock_fd = -1;
2897   int rv = 0;
2898   vnet_hw_interface_t *hwif;
2899   uword *if_index;
2900
2901   if (!(hwif = vnet_get_sup_hw_interface (vnm, sw_if_index)) ||
2902       hwif->dev_class_index != vhost_user_dev_class.index)
2903     return VNET_API_ERROR_INVALID_SW_IF_INDEX;
2904
2905   if (sock_filename == NULL || !(strlen (sock_filename) > 0))
2906     return VNET_API_ERROR_INVALID_ARGUMENT;
2907
2908   vui = vec_elt_at_index (vum->vhost_user_interfaces, hwif->dev_instance);
2909
2910   /*
2911    * Disallow changing the interface to have the same path name
2912    * as other interface
2913    */
2914   if_index = mhash_get (&vum->if_index_by_sock_name, (void *) sock_filename);
2915   if (if_index && (*if_index != vui->if_index))
2916     return VNET_API_ERROR_IF_ALREADY_EXISTS;
2917
2918   // First try to open server socket
2919   if (is_server)
2920     if ((rv = vhost_user_init_server_sock (sock_filename,
2921                                            &server_sock_fd)) != 0)
2922       return rv;
2923
2924   vhost_user_term_if (vui);
2925   vhost_user_vui_init (vnm, vui, server_sock_fd,
2926                        sock_filename, feature_mask, &sw_if_idx);
2927
2928   if (renumber)
2929     vnet_interface_name_renumber (sw_if_idx, custom_dev_instance);
2930
2931   // Process node must connect
2932   vlib_process_signal_event (vm, vhost_user_process_node.index, 0, 0);
2933
2934   return rv;
2935 }
2936
2937 clib_error_t *
2938 vhost_user_connect_command_fn (vlib_main_t * vm,
2939                                unformat_input_t * input,
2940                                vlib_cli_command_t * cmd)
2941 {
2942   unformat_input_t _line_input, *line_input = &_line_input;
2943   u8 *sock_filename = NULL;
2944   u32 sw_if_index;
2945   u8 is_server = 0;
2946   u64 feature_mask = (u64) ~ (0ULL);
2947   u8 renumber = 0;
2948   u32 custom_dev_instance = ~0;
2949   u8 hwaddr[6];
2950   u8 *hw = NULL;
2951   clib_error_t *error = NULL;
2952
2953   /* Get a line of input. */
2954   if (!unformat_user (input, unformat_line_input, line_input))
2955     return 0;
2956
2957   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2958     {
2959       if (unformat (line_input, "socket %s", &sock_filename))
2960         ;
2961       else if (unformat (line_input, "server"))
2962         is_server = 1;
2963       else if (unformat (line_input, "feature-mask 0x%llx", &feature_mask))
2964         ;
2965       else
2966         if (unformat
2967             (line_input, "hwaddr %U", unformat_ethernet_address, hwaddr))
2968         hw = hwaddr;
2969       else if (unformat (line_input, "renumber %d", &custom_dev_instance))
2970         {
2971           renumber = 1;
2972         }
2973       else
2974         {
2975           error = clib_error_return (0, "unknown input `%U'",
2976                                      format_unformat_error, line_input);
2977           goto done;
2978         }
2979     }
2980
2981   vnet_main_t *vnm = vnet_get_main ();
2982
2983   int rv;
2984   if ((rv = vhost_user_create_if (vnm, vm, (char *) sock_filename,
2985                                   is_server, &sw_if_index, feature_mask,
2986                                   renumber, custom_dev_instance, hw)))
2987     {
2988       error = clib_error_return (0, "vhost_user_create_if returned %d", rv);
2989       goto done;
2990     }
2991
2992   vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (),
2993                    sw_if_index);
2994
2995 done:
2996   vec_free (sock_filename);
2997   unformat_free (line_input);
2998
2999   return error;
3000 }
3001
3002 clib_error_t *
3003 vhost_user_delete_command_fn (vlib_main_t * vm,
3004                               unformat_input_t * input,
3005                               vlib_cli_command_t * cmd)
3006 {
3007   unformat_input_t _line_input, *line_input = &_line_input;
3008   u32 sw_if_index = ~0;
3009   vnet_main_t *vnm = vnet_get_main ();
3010   clib_error_t *error = NULL;
3011
3012   /* Get a line of input. */
3013   if (!unformat_user (input, unformat_line_input, line_input))
3014     return 0;
3015
3016   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
3017     {
3018       if (unformat (line_input, "sw_if_index %d", &sw_if_index))
3019         ;
3020       else if (unformat
3021                (line_input, "%U", unformat_vnet_sw_interface, vnm,
3022                 &sw_if_index))
3023         {
3024           vnet_hw_interface_t *hwif =
3025             vnet_get_sup_hw_interface (vnm, sw_if_index);
3026           if (hwif == NULL ||
3027               vhost_user_dev_class.index != hwif->dev_class_index)
3028             {
3029               error = clib_error_return (0, "Not a vhost interface");
3030               goto done;
3031             }
3032         }
3033       else
3034         {
3035           error = clib_error_return (0, "unknown input `%U'",
3036                                      format_unformat_error, line_input);
3037           goto done;
3038         }
3039     }
3040
3041   vhost_user_delete_if (vnm, vm, sw_if_index);
3042
3043 done:
3044   unformat_free (line_input);
3045
3046   return error;
3047 }
3048
3049 int
3050 vhost_user_dump_ifs (vnet_main_t * vnm, vlib_main_t * vm,
3051                      vhost_user_intf_details_t ** out_vuids)
3052 {
3053   int rv = 0;
3054   vhost_user_main_t *vum = &vhost_user_main;
3055   vhost_user_intf_t *vui;
3056   vhost_user_intf_details_t *r_vuids = NULL;
3057   vhost_user_intf_details_t *vuid = NULL;
3058   u32 *hw_if_indices = 0;
3059   vnet_hw_interface_t *hi;
3060   u8 *s = NULL;
3061   int i;
3062
3063   if (!out_vuids)
3064     return -1;
3065
3066   pool_foreach (vui, vum->vhost_user_interfaces,
3067                 vec_add1 (hw_if_indices, vui->hw_if_index);
3068     );
3069
3070   for (i = 0; i < vec_len (hw_if_indices); i++)
3071     {
3072       hi = vnet_get_hw_interface (vnm, hw_if_indices[i]);
3073       vui = pool_elt_at_index (vum->vhost_user_interfaces, hi->dev_instance);
3074
3075       vec_add2 (r_vuids, vuid, 1);
3076       vuid->sw_if_index = vui->sw_if_index;
3077       vuid->virtio_net_hdr_sz = vui->virtio_net_hdr_sz;
3078       vuid->features = vui->features;
3079       vuid->num_regions = vui->nregions;
3080       vuid->is_server = vui->unix_server_index != ~0;
3081       vuid->sock_errno = vui->sock_errno;
3082       strncpy ((char *) vuid->sock_filename, (char *) vui->sock_filename,
3083                ARRAY_LEN (vuid->sock_filename) - 1);
3084
3085       s = format (s, "%v%c", hi->name, 0);
3086
3087       strncpy ((char *) vuid->if_name, (char *) s,
3088                ARRAY_LEN (vuid->if_name) - 1);
3089       _vec_len (s) = 0;
3090     }
3091
3092   vec_free (s);
3093   vec_free (hw_if_indices);
3094
3095   *out_vuids = r_vuids;
3096
3097   return rv;
3098 }
3099
3100 clib_error_t *
3101 show_vhost_user_command_fn (vlib_main_t * vm,
3102                             unformat_input_t * input,
3103                             vlib_cli_command_t * cmd)
3104 {
3105   clib_error_t *error = 0;
3106   vnet_main_t *vnm = vnet_get_main ();
3107   vhost_user_main_t *vum = &vhost_user_main;
3108   vhost_user_intf_t *vui;
3109   u32 hw_if_index, *hw_if_indices = 0;
3110   vnet_hw_interface_t *hi;
3111   u16 *queue;
3112   u32 ci;
3113   int i, j, q;
3114   int show_descr = 0;
3115   struct feat_struct
3116   {
3117     u8 bit;
3118     char *str;
3119   };
3120   struct feat_struct *feat_entry;
3121
3122   static struct feat_struct feat_array[] = {
3123 #define _(s,b) { .str = #s, .bit = b, },
3124     foreach_virtio_net_feature
3125 #undef _
3126     {.str = NULL}
3127   };
3128
3129 #define foreach_protocol_feature \
3130   _(VHOST_USER_PROTOCOL_F_MQ) \
3131   _(VHOST_USER_PROTOCOL_F_LOG_SHMFD)
3132
3133   static struct feat_struct proto_feat_array[] = {
3134 #define _(s) { .str = #s, .bit = s},
3135     foreach_protocol_feature
3136 #undef _
3137     {.str = NULL}
3138   };
3139
3140   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3141     {
3142       if (unformat
3143           (input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
3144         {
3145           vec_add1 (hw_if_indices, hw_if_index);
3146         }
3147       else if (unformat (input, "descriptors") || unformat (input, "desc"))
3148         show_descr = 1;
3149       else
3150         {
3151           error = clib_error_return (0, "unknown input `%U'",
3152                                      format_unformat_error, input);
3153           goto done;
3154         }
3155     }
3156   if (vec_len (hw_if_indices) == 0)
3157     {
3158       pool_foreach (vui, vum->vhost_user_interfaces,
3159                     vec_add1 (hw_if_indices, vui->hw_if_index);
3160         );
3161     }
3162   vlib_cli_output (vm, "Virtio vhost-user interfaces");
3163   vlib_cli_output (vm, "Global:\n  coalesce frames %d time %e",
3164                    vum->coalesce_frames, vum->coalesce_time);
3165   vlib_cli_output (vm, "  number of rx virtqueues in interrupt mode: %d",
3166                    vum->ifq_count);
3167
3168   for (i = 0; i < vec_len (hw_if_indices); i++)
3169     {
3170       hi = vnet_get_hw_interface (vnm, hw_if_indices[i]);
3171       vui = pool_elt_at_index (vum->vhost_user_interfaces, hi->dev_instance);
3172       vlib_cli_output (vm, "Interface: %s (ifindex %d)",
3173                        hi->name, hw_if_indices[i]);
3174
3175       vlib_cli_output (vm, "virtio_net_hdr_sz %d\n"
3176                        " features mask (0x%llx): \n"
3177                        " features (0x%llx): \n",
3178                        vui->virtio_net_hdr_sz, vui->feature_mask,
3179                        vui->features);
3180
3181       feat_entry = (struct feat_struct *) &feat_array;
3182       while (feat_entry->str)
3183         {
3184           if (vui->features & (1ULL << feat_entry->bit))
3185             vlib_cli_output (vm, "   %s (%d)", feat_entry->str,
3186                              feat_entry->bit);
3187           feat_entry++;
3188         }
3189
3190       vlib_cli_output (vm, "  protocol features (0x%llx)",
3191                        vui->protocol_features);
3192       feat_entry = (struct feat_struct *) &proto_feat_array;
3193       while (feat_entry->str)
3194         {
3195           if (vui->protocol_features & (1ULL << feat_entry->bit))
3196             vlib_cli_output (vm, "   %s (%d)", feat_entry->str,
3197                              feat_entry->bit);
3198           feat_entry++;
3199         }
3200
3201       vlib_cli_output (vm, "\n");
3202
3203       vlib_cli_output (vm, " socket filename %s type %s errno \"%s\"\n\n",
3204                        vui->sock_filename,
3205                        (vui->unix_server_index != ~0) ? "server" : "client",
3206                        strerror (vui->sock_errno));
3207
3208       vlib_cli_output (vm, " rx placement: ");
3209
3210       vec_foreach (queue, vui->rx_queues)
3211       {
3212         vnet_main_t *vnm = vnet_get_main ();
3213         uword thread_index;
3214         vnet_hw_interface_rx_mode mode;
3215
3216         thread_index = vnet_get_device_input_thread_index (vnm,
3217                                                            vui->hw_if_index,
3218                                                            *queue);
3219         vnet_hw_interface_get_rx_mode (vnm, vui->hw_if_index, *queue, &mode);
3220         vlib_cli_output (vm, "   thread %d on vring %d, %U\n",
3221                          thread_index, VHOST_VRING_IDX_TX (*queue),
3222                          format_vnet_hw_interface_rx_mode, mode);
3223       }
3224
3225       vlib_cli_output (vm, " tx placement: %s\n",
3226                        vui->use_tx_spinlock ? "spin-lock" : "lock-free");
3227
3228       vec_foreach_index (ci, vui->per_cpu_tx_qid)
3229       {
3230         vlib_cli_output (vm, "   thread %d on vring %d\n", ci,
3231                          VHOST_VRING_IDX_RX (vui->per_cpu_tx_qid[ci]));
3232       }
3233
3234       vlib_cli_output (vm, "\n");
3235
3236       vlib_cli_output (vm, " Memory regions (total %d)\n", vui->nregions);
3237
3238       if (vui->nregions)
3239         {
3240           vlib_cli_output (vm,
3241                            " region fd    guest_phys_addr    memory_size        userspace_addr     mmap_offset        mmap_addr\n");
3242           vlib_cli_output (vm,
3243                            " ====== ===== ================== ================== ================== ================== ==================\n");
3244         }
3245       for (j = 0; j < vui->nregions; j++)
3246         {
3247           vlib_cli_output (vm,
3248                            "  %d     %-5d 0x%016lx 0x%016lx 0x%016lx 0x%016lx 0x%016lx\n",
3249                            j, vui->region_mmap_fd[j],
3250                            vui->regions[j].guest_phys_addr,
3251                            vui->regions[j].memory_size,
3252                            vui->regions[j].userspace_addr,
3253                            vui->regions[j].mmap_offset,
3254                            pointer_to_uword (vui->region_mmap_addr[j]));
3255         }
3256       for (q = 0; q < VHOST_VRING_MAX_N; q++)
3257         {
3258           if (!vui->vrings[q].started)
3259             continue;
3260
3261           vlib_cli_output (vm, "\n Virtqueue %d (%s%s)\n", q,
3262                            (q & 1) ? "RX" : "TX",
3263                            vui->vrings[q].enabled ? "" : " disabled");
3264
3265           vlib_cli_output (vm,
3266                            "  qsz %d last_avail_idx %d last_used_idx %d\n",
3267                            vui->vrings[q].qsz, vui->vrings[q].last_avail_idx,
3268                            vui->vrings[q].last_used_idx);
3269
3270           if (vui->vrings[q].avail && vui->vrings[q].used)
3271             vlib_cli_output (vm,
3272                              "  avail.flags %x avail.idx %d used.flags %x used.idx %d\n",
3273                              vui->vrings[q].avail->flags,
3274                              vui->vrings[q].avail->idx,
3275                              vui->vrings[q].used->flags,
3276                              vui->vrings[q].used->idx);
3277
3278           int kickfd = UNIX_GET_FD (vui->vrings[q].kickfd_idx);
3279           int callfd = UNIX_GET_FD (vui->vrings[q].callfd_idx);
3280           vlib_cli_output (vm, "  kickfd %d callfd %d errfd %d\n",
3281                            kickfd, callfd, vui->vrings[q].errfd);
3282
3283           if (show_descr)
3284             {
3285               vlib_cli_output (vm, "\n  descriptor table:\n");
3286               vlib_cli_output (vm,
3287                                "   id          addr         len  flags  next      user_addr\n");
3288               vlib_cli_output (vm,
3289                                "  ===== ================== ===== ====== ===== ==================\n");
3290               for (j = 0; j < vui->vrings[q].qsz; j++)
3291                 {
3292                   u32 mem_hint = 0;
3293                   vlib_cli_output (vm,
3294                                    "  %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
3295                                    j, vui->vrings[q].desc[j].addr,
3296                                    vui->vrings[q].desc[j].len,
3297                                    vui->vrings[q].desc[j].flags,
3298                                    vui->vrings[q].desc[j].next,
3299                                    pointer_to_uword (map_guest_mem
3300                                                      (vui,
3301                                                       vui->vrings[q].desc[j].
3302                                                       addr, &mem_hint)));
3303                 }
3304             }
3305         }
3306       vlib_cli_output (vm, "\n");
3307     }
3308 done:
3309   vec_free (hw_if_indices);
3310   return error;
3311 }
3312
3313 /*
3314  * CLI functions
3315  */
3316
3317 /*?
3318  * Create a vHost User interface. Once created, a new virtual interface
3319  * will exist with the name '<em>VirtualEthernet0/0/x</em>', where '<em>x</em>'
3320  * is the next free index.
3321  *
3322  * There are several parameters associated with a vHost interface:
3323  *
3324  * - <b>socket <socket-filename></b> - Name of the linux socket used by QEMU/VM and
3325  * VPP to manage the vHost interface. If socket does not already exist, VPP will
3326  * create the socket.
3327  *
3328  * - <b>server</b> - Optional flag to indicate that VPP should be the server for the
3329  * linux socket. If not provided, VPP will be the client.
3330  *
3331  * - <b>feature-mask <hex></b> - Optional virtio/vhost feature set negotiated at
3332  * startup. By default, all supported features will be advertised. Otherwise,
3333  * provide the set of features desired.
3334  *   - 0x000008000 (15) - VIRTIO_NET_F_MRG_RXBUF
3335  *   - 0x000020000 (17) - VIRTIO_NET_F_CTRL_VQ
3336  *   - 0x000200000 (21) - VIRTIO_NET_F_GUEST_ANNOUNCE
3337  *   - 0x000400000 (22) - VIRTIO_NET_F_MQ
3338  *   - 0x004000000 (26) - VHOST_F_LOG_ALL
3339  *   - 0x008000000 (27) - VIRTIO_F_ANY_LAYOUT
3340  *   - 0x010000000 (28) - VIRTIO_F_INDIRECT_DESC
3341  *   - 0x040000000 (30) - VHOST_USER_F_PROTOCOL_FEATURES
3342  *   - 0x100000000 (32) - VIRTIO_F_VERSION_1
3343  *
3344  * - <b>hwaddr <mac-addr></b> - Optional ethernet address, can be in either
3345  * X:X:X:X:X:X unix or X.X.X cisco format.
3346  *
3347  * - <b>renumber <dev_instance></b> - Optional parameter which allows the instance
3348  * in the name to be specified. If instance already exists, name will be used
3349  * anyway and multiple instances will have the same name. Use with caution.
3350  *
3351  * - <b>mode [interrupt | polling]</b> - Optional parameter specifying
3352  * the input thread polling policy.
3353  *
3354  * @cliexpar
3355  * Example of how to create a vhost interface with VPP as the client and all features enabled:
3356  * @cliexstart{create vhost-user socket /tmp/vhost1.sock}
3357  * VirtualEthernet0/0/0
3358  * @cliexend
3359  * Example of how to create a vhost interface with VPP as the server and with just
3360  * multiple queues enabled:
3361  * @cliexstart{create vhost-user socket /tmp/vhost2.sock server feature-mask 0x40400000}
3362  * VirtualEthernet0/0/1
3363  * @cliexend
3364  * Once the vHost interface is created, enable the interface using:
3365  * @cliexcmd{set interface state VirtualEthernet0/0/0 up}
3366 ?*/
3367 /* *INDENT-OFF* */
3368 VLIB_CLI_COMMAND (vhost_user_connect_command, static) = {
3369     .path = "create vhost-user",
3370     .short_help = "create vhost-user socket <socket-filename> [server] "
3371     "[feature-mask <hex>] [hwaddr <mac-addr>] [renumber <dev_instance>] ",
3372     .function = vhost_user_connect_command_fn,
3373 };
3374 /* *INDENT-ON* */
3375
3376 /*?
3377  * Delete a vHost User interface using the interface name or the
3378  * software interface index. Use the '<em>show interface</em>'
3379  * command to determine the software interface index. On deletion,
3380  * the linux socket will not be deleted.
3381  *
3382  * @cliexpar
3383  * Example of how to delete a vhost interface by name:
3384  * @cliexcmd{delete vhost-user VirtualEthernet0/0/1}
3385  * Example of how to delete a vhost interface by software interface index:
3386  * @cliexcmd{delete vhost-user sw_if_index 1}
3387 ?*/
3388 /* *INDENT-OFF* */
3389 VLIB_CLI_COMMAND (vhost_user_delete_command, static) = {
3390     .path = "delete vhost-user",
3391     .short_help = "delete vhost-user {<interface> | sw_if_index <sw_idx>}",
3392     .function = vhost_user_delete_command_fn,
3393 };
3394
3395 /*?
3396  * Display the attributes of a single vHost User interface (provide interface
3397  * name), multiple vHost User interfaces (provide a list of interface names seperated
3398  * by spaces) or all Vhost User interfaces (omit an interface name to display all
3399  * vHost interfaces).
3400  *
3401  * @cliexpar
3402  * @parblock
3403  * Example of how to display a vhost interface:
3404  * @cliexstart{show vhost-user VirtualEthernet0/0/0}
3405  * Virtio vhost-user interfaces
3406  * Global:
3407  *   coalesce frames 32 time 1e-3
3408  * Interface: VirtualEthernet0/0/0 (ifindex 1)
3409  * virtio_net_hdr_sz 12
3410  *  features mask (0xffffffffffffffff):
3411  *  features (0x50408000):
3412  *    VIRTIO_NET_F_MRG_RXBUF (15)
3413  *    VIRTIO_NET_F_MQ (22)
3414  *    VIRTIO_F_INDIRECT_DESC (28)
3415  *    VHOST_USER_F_PROTOCOL_FEATURES (30)
3416  *   protocol features (0x3)
3417  *    VHOST_USER_PROTOCOL_F_MQ (0)
3418  *    VHOST_USER_PROTOCOL_F_LOG_SHMFD (1)
3419  *
3420  *  socket filename /tmp/vhost1.sock type client errno "Success"
3421  *
3422  * rx placement:
3423  *    thread 1 on vring 1
3424  *    thread 1 on vring 5
3425  *    thread 2 on vring 3
3426  *    thread 2 on vring 7
3427  *  tx placement: spin-lock
3428  *    thread 0 on vring 0
3429  *    thread 1 on vring 2
3430  *    thread 2 on vring 0
3431  *
3432  * Memory regions (total 2)
3433  * region fd    guest_phys_addr    memory_size        userspace_addr     mmap_offset        mmap_addr
3434  * ====== ===== ================== ================== ================== ================== ==================
3435  *   0     60    0x0000000000000000 0x00000000000a0000 0x00002aaaaac00000 0x0000000000000000 0x00002aab2b400000
3436  *   1     61    0x00000000000c0000 0x000000003ff40000 0x00002aaaaacc0000 0x00000000000c0000 0x00002aababcc0000
3437  *
3438  *  Virtqueue 0 (TX)
3439  *   qsz 256 last_avail_idx 0 last_used_idx 0
3440  *   avail.flags 1 avail.idx 128 used.flags 1 used.idx 0
3441  *   kickfd 62 callfd 64 errfd -1
3442  *
3443  *  Virtqueue 1 (RX)
3444  *   qsz 256 last_avail_idx 0 last_used_idx 0
3445  *   avail.flags 1 avail.idx 0 used.flags 1 used.idx 0
3446  *   kickfd 65 callfd 66 errfd -1
3447  *
3448  *  Virtqueue 2 (TX)
3449  *   qsz 256 last_avail_idx 0 last_used_idx 0
3450  *   avail.flags 1 avail.idx 128 used.flags 1 used.idx 0
3451  *   kickfd 63 callfd 70 errfd -1
3452  *
3453  *  Virtqueue 3 (RX)
3454  *   qsz 256 last_avail_idx 0 last_used_idx 0
3455  *   avail.flags 1 avail.idx 0 used.flags 1 used.idx 0
3456  *   kickfd 72 callfd 74 errfd -1
3457  *
3458  *  Virtqueue 4 (TX disabled)
3459  *   qsz 256 last_avail_idx 0 last_used_idx 0
3460  *   avail.flags 1 avail.idx 0 used.flags 1 used.idx 0
3461  *   kickfd 76 callfd 78 errfd -1
3462  *
3463  *  Virtqueue 5 (RX disabled)
3464  *   qsz 256 last_avail_idx 0 last_used_idx 0
3465  *   avail.flags 1 avail.idx 0 used.flags 1 used.idx 0
3466  *   kickfd 80 callfd 82 errfd -1
3467  *
3468  *  Virtqueue 6 (TX disabled)
3469  *   qsz 256 last_avail_idx 0 last_used_idx 0
3470  *  avail.flags 1 avail.idx 0 used.flags 1 used.idx 0
3471  *   kickfd 84 callfd 86 errfd -1
3472  *
3473  *  Virtqueue 7 (RX disabled)
3474  *   qsz 256 last_avail_idx 0 last_used_idx 0
3475  *   avail.flags 1 avail.idx 0 used.flags 1 used.idx 0
3476  *   kickfd 88 callfd 90 errfd -1
3477  *
3478  * @cliexend
3479  *
3480  * The optional '<em>descriptors</em>' parameter will display the same output as
3481  * the previous example but will include the descriptor table for each queue.
3482  * The output is truncated below:
3483  * @cliexstart{show vhost-user VirtualEthernet0/0/0 descriptors}
3484  * Virtio vhost-user interfaces
3485  * Global:
3486  *   coalesce frames 32 time 1e-3
3487  * Interface: VirtualEthernet0/0/0 (ifindex 1)
3488  * virtio_net_hdr_sz 12
3489  *  features mask (0xffffffffffffffff):
3490  *  features (0x50408000):
3491  *    VIRTIO_NET_F_MRG_RXBUF (15)
3492  *    VIRTIO_NET_F_MQ (22)
3493  * :
3494  *  Virtqueue 0 (TX)
3495  *   qsz 256 last_avail_idx 0 last_used_idx 0
3496  *   avail.flags 1 avail.idx 128 used.flags 1 used.idx 0
3497  *   kickfd 62 callfd 64 errfd -1
3498  *
3499  *   descriptor table:
3500  *    id          addr         len  flags  next      user_addr
3501  *   ===== ================== ===== ====== ===== ==================
3502  *   0     0x0000000010b6e974 2060  0x0002 1     0x00002aabbc76e974
3503  *   1     0x0000000010b6e034 2060  0x0002 2     0x00002aabbc76e034
3504  *   2     0x0000000010b6d6f4 2060  0x0002 3     0x00002aabbc76d6f4
3505  *   3     0x0000000010b6cdb4 2060  0x0002 4     0x00002aabbc76cdb4
3506  *   4     0x0000000010b6c474 2060  0x0002 5     0x00002aabbc76c474
3507  *   5     0x0000000010b6bb34 2060  0x0002 6     0x00002aabbc76bb34
3508  *   6     0x0000000010b6b1f4 2060  0x0002 7     0x00002aabbc76b1f4
3509  *   7     0x0000000010b6a8b4 2060  0x0002 8     0x00002aabbc76a8b4
3510  *   8     0x0000000010b69f74 2060  0x0002 9     0x00002aabbc769f74
3511  *   9     0x0000000010b69634 2060  0x0002 10    0x00002aabbc769634
3512  *   10    0x0000000010b68cf4 2060  0x0002 11    0x00002aabbc768cf4
3513  * :
3514  *   249   0x0000000000000000 0     0x0000 250   0x00002aab2b400000
3515  *   250   0x0000000000000000 0     0x0000 251   0x00002aab2b400000
3516  *   251   0x0000000000000000 0     0x0000 252   0x00002aab2b400000
3517  *   252   0x0000000000000000 0     0x0000 253   0x00002aab2b400000
3518  *   253   0x0000000000000000 0     0x0000 254   0x00002aab2b400000
3519  *   254   0x0000000000000000 0     0x0000 255   0x00002aab2b400000
3520  *   255   0x0000000000000000 0     0x0000 32768 0x00002aab2b400000
3521  *
3522  *  Virtqueue 1 (RX)
3523  *   qsz 256 last_avail_idx 0 last_used_idx 0
3524  * :
3525  * @cliexend
3526  * @endparblock
3527 ?*/
3528 /* *INDENT-OFF* */
3529 VLIB_CLI_COMMAND (show_vhost_user_command, static) = {
3530     .path = "show vhost-user",
3531     .short_help = "show vhost-user [<interface> [<interface> [..]]] [descriptors]",
3532     .function = show_vhost_user_command_fn,
3533 };
3534 /* *INDENT-ON* */
3535
3536 static clib_error_t *
3537 vhost_user_config (vlib_main_t * vm, unformat_input_t * input)
3538 {
3539   vhost_user_main_t *vum = &vhost_user_main;
3540
3541   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3542     {
3543       if (unformat (input, "coalesce-frames %d", &vum->coalesce_frames))
3544         ;
3545       else if (unformat (input, "coalesce-time %f", &vum->coalesce_time))
3546         ;
3547       else if (unformat (input, "dont-dump-memory"))
3548         vum->dont_dump_vhost_user_memory = 1;
3549       else
3550         return clib_error_return (0, "unknown input `%U'",
3551                                   format_unformat_error, input);
3552     }
3553
3554   return 0;
3555 }
3556
3557 /* vhost-user { ... } configuration. */
3558 VLIB_CONFIG_FUNCTION (vhost_user_config, "vhost-user");
3559
3560 void
3561 vhost_user_unmap_all (void)
3562 {
3563   vhost_user_main_t *vum = &vhost_user_main;
3564   vhost_user_intf_t *vui;
3565
3566   if (vum->dont_dump_vhost_user_memory)
3567     {
3568       pool_foreach (vui, vum->vhost_user_interfaces,
3569                     unmap_all_mem_regions (vui);
3570         );
3571     }
3572 }
3573
3574 /*
3575  * fd.io coding-style-patch-verification: ON
3576  *
3577  * Local Variables:
3578  * eval: (c-set-style "gnu")
3579  * End:
3580  */