session: remove ipv6 lookup threading assert
[vpp.git] / src / vnet / devices / virtio / virtio.c
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2017 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <net/if.h>
22 #ifdef __linux__
23 #include <linux/if_tun.h>
24 #elif __FreeBSD__
25 #include <net/if_tun.h>
26 #endif /* __linux__ */
27 #include <sys/ioctl.h>
28 #include <sys/eventfd.h>
29
30 #include <vlib/vlib.h>
31 #include <vlib/pci/pci.h>
32 #include <vlib/unix/unix.h>
33 #include <vnet/ethernet/ethernet.h>
34 #include <vnet/ip/ip4_packet.h>
35 #include <vnet/ip/ip6_packet.h>
36 #include <vnet/devices/virtio/virtio.h>
37 #include <vnet/devices/virtio/virtio_inline.h>
38 #include <vnet/devices/virtio/pci.h>
39 #include <vnet/interface/rx_queue_funcs.h>
40 #include <vnet/interface/tx_queue_funcs.h>
41
42 virtio_main_t virtio_main;
43
44 #define _IOCTL(fd,a,...) \
45   if (ioctl (fd, a, __VA_ARGS__) < 0) \
46     { \
47       err = clib_error_return_unix (0, "ioctl(" #a ")"); \
48       goto error; \
49     }
50
51 static clib_error_t *
52 call_read_ready (clib_file_t * uf)
53 {
54   vnet_main_t *vnm = vnet_get_main ();
55   u64 b;
56
57   CLIB_UNUSED (ssize_t size) = read (uf->file_descriptor, &b, sizeof (b));
58   vnet_hw_if_rx_queue_set_int_pending (vnm, uf->private_data);
59
60   return 0;
61 }
62
63
64 clib_error_t *
65 virtio_vring_init (vlib_main_t * vm, virtio_if_t * vif, u16 idx, u16 sz)
66 {
67   vnet_virtio_vring_t *vring;
68   int i;
69
70   if (!is_pow2 (sz))
71     return clib_error_return (0, "ring size must be power of 2");
72
73   if (sz > 32768)
74     return clib_error_return (0, "ring size must be 32768 or lower");
75
76   if (sz == 0)
77     sz = 256;
78
79   if (idx % 2)
80     {
81       vec_validate_aligned (vif->txq_vrings, TX_QUEUE_ACCESS (idx),
82                             CLIB_CACHE_LINE_BYTES);
83       vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS (idx));
84       clib_spinlock_init (&vring->lockp);
85     }
86   else
87     {
88       vec_validate_aligned (vif->rxq_vrings, RX_QUEUE_ACCESS (idx),
89                             CLIB_CACHE_LINE_BYTES);
90       vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS (idx));
91     }
92   i = sizeof (vnet_virtio_vring_desc_t) * sz;
93   i = round_pow2 (i, CLIB_CACHE_LINE_BYTES);
94   vring->desc = clib_mem_alloc_aligned (i, CLIB_CACHE_LINE_BYTES);
95   clib_memset (vring->desc, 0, i);
96
97   i = sizeof (vnet_virtio_vring_avail_t) + sz * sizeof (vring->avail->ring[0]);
98   i = round_pow2 (i, CLIB_CACHE_LINE_BYTES);
99   vring->avail = clib_mem_alloc_aligned (i, CLIB_CACHE_LINE_BYTES);
100   clib_memset (vring->avail, 0, i);
101   // tell kernel that we don't need interrupt
102   vring->avail->flags = VRING_AVAIL_F_NO_INTERRUPT;
103
104   i = sizeof (vnet_virtio_vring_used_t) +
105       sz * sizeof (vnet_virtio_vring_used_elem_t);
106   i = round_pow2 (i, CLIB_CACHE_LINE_BYTES);
107   vring->used = clib_mem_alloc_aligned (i, CLIB_CACHE_LINE_BYTES);
108   clib_memset (vring->used, 0, i);
109
110   vring->queue_id = idx;
111   ASSERT (vring->buffers == 0);
112   vec_validate_aligned (vring->buffers, sz, CLIB_CACHE_LINE_BYTES);
113
114   if (idx & 1)
115     {
116       clib_memset_u32 (vring->buffers, ~0, sz);
117       // tx path: suppress the interrupts from kernel
118       vring->call_fd = -1;
119     }
120   else
121     vring->call_fd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
122
123   vring->total_packets = 0;
124   vring->queue_size = sz;
125   vring->kick_fd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
126   virtio_log_debug (vif, "vring %u size %u call_fd %d kick_fd %d", idx,
127                     vring->queue_size, vring->call_fd, vring->kick_fd);
128
129   return 0;
130 }
131
132 inline void
133 virtio_free_buffers (vlib_main_t *vm, vnet_virtio_vring_t *vring)
134 {
135   u16 used = vring->desc_in_use;
136   u16 last = vring->last_used_idx;
137   u16 mask = vring->queue_size - 1;
138
139   while (used)
140     {
141       vlib_buffer_free (vm, &vring->buffers[last & mask], 1);
142       last++;
143       used--;
144     }
145 }
146
147 clib_error_t *
148 virtio_vring_free_rx (vlib_main_t * vm, virtio_if_t * vif, u32 idx)
149 {
150   vnet_virtio_vring_t *vring =
151     vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS (idx));
152
153   clib_file_del_by_index (&file_main, vring->call_file_index);
154   close (vring->kick_fd);
155   close (vring->call_fd);
156   if (vring->used)
157     {
158       virtio_free_buffers (vm, vring);
159       clib_mem_free (vring->used);
160     }
161   if (vring->desc)
162     clib_mem_free (vring->desc);
163   if (vring->avail)
164     clib_mem_free (vring->avail);
165   vec_free (vring->buffers);
166   return 0;
167 }
168
169 clib_error_t *
170 virtio_vring_free_tx (vlib_main_t * vm, virtio_if_t * vif, u32 idx)
171 {
172   vnet_virtio_vring_t *vring =
173     vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS (idx));
174
175   close (vring->kick_fd);
176   if (vring->used)
177     {
178       virtio_free_buffers (vm, vring);
179       clib_mem_free (vring->used);
180     }
181   if (vring->desc)
182     clib_mem_free (vring->desc);
183   if (vring->avail)
184     clib_mem_free (vring->avail);
185   vec_free (vring->buffers);
186   gro_flow_table_free (vring->flow_table);
187   virtio_vring_buffering_free (vm, vring->buffering);
188   clib_spinlock_free (&vring->lockp);
189   return 0;
190 }
191
192 void
193 virtio_set_packet_coalesce (virtio_if_t * vif)
194 {
195   vnet_main_t *vnm = vnet_get_main ();
196   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, vif->hw_if_index);
197   vnet_virtio_vring_t *vring;
198   vif->packet_coalesce = 1;
199   vec_foreach (vring, vif->txq_vrings)
200   {
201     gro_flow_table_init (&vring->flow_table,
202                          vif->type & (VIRTIO_IF_TYPE_TAP |
203                                       VIRTIO_IF_TYPE_PCI), hw->tx_node_index);
204   }
205 }
206
207 clib_error_t *
208 virtio_set_packet_buffering (virtio_if_t * vif, u16 buffering_size)
209 {
210   vnet_main_t *vnm = vnet_get_main ();
211   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, vif->hw_if_index);
212   vnet_virtio_vring_t *vring;
213   clib_error_t *error = 0;
214
215   vec_foreach (vring, vif->txq_vrings)
216   {
217     if ((error =
218          virtio_vring_buffering_init (&vring->buffering, hw->tx_node_index,
219                                       buffering_size)))
220       {
221         break;
222       }
223   }
224
225   return error;
226 }
227
228 static void
229 virtio_vring_fill (vlib_main_t *vm, virtio_if_t *vif,
230                    vnet_virtio_vring_t *vring)
231 {
232   if (vif->is_packed)
233     virtio_refill_vring_packed (vm, vif, vif->type, vring,
234                                 vif->virtio_net_hdr_sz,
235                                 virtio_input_node.index);
236   else
237     virtio_refill_vring_split (vm, vif, vif->type, vring,
238                                vif->virtio_net_hdr_sz,
239                                virtio_input_node.index);
240 }
241
242 void
243 virtio_vring_set_rx_queues (vlib_main_t *vm, virtio_if_t *vif)
244 {
245   vnet_main_t *vnm = vnet_get_main ();
246   vnet_virtio_vring_t *vring;
247   u32 i = 0;
248
249   vnet_hw_if_set_input_node (vnm, vif->hw_if_index, virtio_input_node.index);
250
251   vec_foreach (vring, vif->rxq_vrings)
252     {
253       vring->queue_index = vnet_hw_if_register_rx_queue (
254         vnm, vif->hw_if_index, RX_QUEUE_ACCESS (vring->queue_id),
255         VNET_HW_IF_RXQ_THREAD_ANY);
256       vring->buffer_pool_index = vlib_buffer_pool_get_default_for_numa (
257         vm, vnet_hw_if_get_rx_queue_numa_node (vnm, vring->queue_index));
258       if (vif->type == VIRTIO_IF_TYPE_TAP || vif->type == VIRTIO_IF_TYPE_TUN)
259         {
260
261           clib_file_t f = {
262             .read_function = call_read_ready,
263             .flags = UNIX_FILE_EVENT_EDGE_TRIGGERED,
264             .file_descriptor = vring->call_fd,
265             .private_data = vring->queue_index,
266             .description = format (0, "%U vring %u", format_virtio_device_name,
267                                    vif->dev_instance, vring->queue_id),
268           };
269
270           vring->call_file_index = clib_file_add (&file_main, &f);
271           vnet_hw_if_set_rx_queue_file_index (vnm, vring->queue_index,
272                                               vring->call_file_index);
273         }
274       else if ((vif->type == VIRTIO_IF_TYPE_PCI) && (vif->support_int_mode) &&
275                (vif->msix_enabled == VIRTIO_MSIX_ENABLED))
276         {
277           u32 file_index;
278           file_index =
279             vlib_pci_get_msix_file_index (vm, vif->pci_dev_handle, i + 1);
280           vnet_hw_if_set_rx_queue_file_index (vnm, vring->queue_index,
281                                               file_index);
282           i++;
283         }
284       vnet_hw_if_set_rx_queue_mode (vnm, vring->queue_index,
285                                     VNET_HW_IF_RX_MODE_POLLING);
286       vring->mode = VNET_HW_IF_RX_MODE_POLLING;
287       virtio_vring_fill (vm, vif, vring);
288     }
289   vnet_hw_if_update_runtime_data (vnm, vif->hw_if_index);
290 }
291
292 void
293 virtio_vring_set_tx_queues (vlib_main_t *vm, virtio_if_t *vif)
294 {
295   vnet_main_t *vnm = vnet_get_main ();
296   vnet_virtio_vring_t *vring;
297
298   vec_foreach (vring, vif->txq_vrings)
299     {
300       vring->queue_index = vnet_hw_if_register_tx_queue (
301         vnm, vif->hw_if_index, TX_QUEUE_ACCESS (vring->queue_id));
302     }
303
304   if (vif->num_txqs == 0)
305     {
306       virtio_log_error (vif, "Interface %U has 0 txq",
307                         format_vnet_hw_if_index_name, vnm, vif->hw_if_index);
308       return;
309     }
310
311   for (u32 j = 0; j < vlib_get_n_threads (); j++)
312     {
313       u32 qi = vif->txq_vrings[j % vif->num_txqs].queue_index;
314       vnet_hw_if_tx_queue_assign_thread (vnm, qi, j);
315     }
316
317   vnet_hw_if_update_runtime_data (vnm, vif->hw_if_index);
318 }
319
320 inline void
321 virtio_set_net_hdr_size (virtio_if_t * vif)
322 {
323   if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF) ||
324       vif->features & VIRTIO_FEATURE (VIRTIO_F_VERSION_1))
325     vif->virtio_net_hdr_sz = sizeof (vnet_virtio_net_hdr_v1_t);
326   else
327     vif->virtio_net_hdr_sz = sizeof (vnet_virtio_net_hdr_t);
328 }
329
330 inline void
331 virtio_show (vlib_main_t *vm, u32 *hw_if_indices, u8 show_descr,
332              virtio_if_type_t type)
333 {
334   u32 i, j, hw_if_index;
335   virtio_if_t *vif;
336   vnet_main_t *vnm = &vnet_main;
337   virtio_main_t *mm = &virtio_main;
338   vnet_virtio_vring_t *vring;
339   struct feat_struct
340   {
341     u8 bit;
342     char *str;
343   };
344   struct feat_struct *feat_entry;
345
346   static struct feat_struct feat_array[] = {
347 #define _(s,b) { .str = #s, .bit = b, },
348     foreach_virtio_net_features
349 #undef _
350     {.str = NULL}
351   };
352
353   struct feat_struct *flag_entry;
354   static struct feat_struct flags_array[] = {
355 #define _(b,e,s) { .bit = b, .str = s, },
356     foreach_virtio_if_flag
357 #undef _
358     {.str = NULL}
359   };
360
361   if (!hw_if_indices)
362     return;
363
364   for (hw_if_index = 0; hw_if_index < vec_len (hw_if_indices); hw_if_index++)
365     {
366       vnet_hw_interface_t *hi =
367         vnet_get_hw_interface (vnm, hw_if_indices[hw_if_index]);
368       vif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
369       if (vif->type != type)
370         continue;
371       vlib_cli_output (vm, "Interface: %U (ifindex %d)",
372                        format_vnet_hw_if_index_name, vnm,
373                        hw_if_indices[hw_if_index], vif->hw_if_index);
374       if (type == VIRTIO_IF_TYPE_PCI)
375         {
376           vlib_cli_output (vm, "  PCI Address: %U", format_vlib_pci_addr,
377                            &vif->pci_addr);
378         }
379       if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
380         {
381           u8 *str = 0;
382           if (vif->host_if_name)
383             vlib_cli_output (vm, "  name \"%s\"", vif->host_if_name);
384           if (vif->net_ns)
385             vlib_cli_output (vm, "  host-ns \"%s\"", vif->net_ns);
386           if (vif->host_mtu_size)
387             vlib_cli_output (vm, "  host-mtu-size \"%d\"",
388                              vif->host_mtu_size);
389           if (type == VIRTIO_IF_TYPE_TAP)
390             vlib_cli_output (vm, "  host-mac-addr: %U",
391                              format_ethernet_address, vif->host_mac_addr);
392           vlib_cli_output (vm, "  host-carrier-up: %u", vif->host_carrier_up);
393
394           vec_foreach_index (i, vif->vhost_fds)
395             str = format (str, " %d", vif->vhost_fds[i]);
396           vlib_cli_output (vm, "  vhost-fds%v", str);
397           vec_free (str);
398           vec_foreach_index (i, vif->tap_fds)
399             str = format (str, " %d", vif->tap_fds[i]);
400           vlib_cli_output (vm, "  tap-fds%v", str);
401           vec_free (str);
402         }
403       vlib_cli_output (vm, "  gso-enabled %d", vif->gso_enabled);
404       vlib_cli_output (vm, "  csum-enabled %d", vif->csum_offload_enabled);
405       vlib_cli_output (vm, "  packet-coalesce %d", vif->packet_coalesce);
406       vlib_cli_output (vm, "  packet-buffering %d", vif->packet_buffering);
407       if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_PCI))
408         vlib_cli_output (vm, "  Mac Address: %U", format_ethernet_address,
409                          vif->mac_addr);
410       vlib_cli_output (vm, "  Device instance: %u", vif->dev_instance);
411       vlib_cli_output (vm, "  flags 0x%x", vif->flags);
412       flag_entry = (struct feat_struct *) &flags_array;
413       while (flag_entry->str)
414         {
415           if (vif->flags & (1ULL << flag_entry->bit))
416             vlib_cli_output (vm, "    %s (%d)", flag_entry->str,
417                              flag_entry->bit);
418           flag_entry++;
419         }
420       if (type == VIRTIO_IF_TYPE_PCI)
421         {
422           device_status (vm, vif);
423         }
424       vlib_cli_output (vm, "  features 0x%lx", vif->features);
425       feat_entry = (struct feat_struct *) &feat_array;
426       while (feat_entry->str)
427         {
428           if (vif->features & (1ULL << feat_entry->bit))
429             vlib_cli_output (vm, "    %s (%d)", feat_entry->str,
430                              feat_entry->bit);
431           feat_entry++;
432         }
433       vlib_cli_output (vm, "  remote-features 0x%lx", vif->remote_features);
434       feat_entry = (struct feat_struct *) &feat_array;
435       while (feat_entry->str)
436         {
437           if (vif->remote_features & (1ULL << feat_entry->bit))
438             vlib_cli_output (vm, "    %s (%d)", feat_entry->str,
439                              feat_entry->bit);
440           feat_entry++;
441         }
442       vlib_cli_output (vm, "  Number of RX Virtqueue  %u", vif->num_rxqs);
443       vlib_cli_output (vm, "  Number of TX Virtqueue  %u", vif->num_txqs);
444       if (type == VIRTIO_IF_TYPE_PCI && vif->cxq_vring != NULL &&
445           vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
446         vlib_cli_output (vm, "  Number of CTRL Virtqueue 1");
447       vec_foreach_index (i, vif->rxq_vrings)
448       {
449         vring = vec_elt_at_index (vif->rxq_vrings, i);
450         vlib_cli_output (vm, "  Virtqueue (RX) %d", vring->queue_id);
451         vlib_cli_output (
452           vm, "    qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
453           vring->queue_size, vring->last_used_idx, vring->desc_next,
454           vring->desc_in_use);
455         if (vif->is_packed)
456           {
457             vlib_cli_output (vm,
458                              "    driver_event.flags 0x%x driver_event.off_wrap %d device_event.flags 0x%x device_event.off_wrap %d",
459                              vring->driver_event->flags,
460                              vring->driver_event->off_wrap,
461                              vring->device_event->flags,
462                              vring->device_event->off_wrap);
463             vlib_cli_output (vm,
464                              "    avail wrap counter %d, used wrap counter %d",
465                              vring->avail_wrap_counter,
466                              vring->used_wrap_counter);
467           }
468         else
469           vlib_cli_output (vm,
470                            "    avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
471                            vring->avail->flags, vring->avail->idx,
472                            vring->used->flags, vring->used->idx);
473         if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
474           {
475             vlib_cli_output (vm, "    kickfd %d, callfd %d", vring->kick_fd,
476                              vring->call_fd);
477           }
478         if (show_descr)
479           {
480             vlib_cli_output (vm, "\n  descriptor table:\n");
481             vlib_cli_output (vm,
482                              "   id          addr         len  flags  next/id      user_addr\n");
483             vlib_cli_output (vm,
484                              "  ===== ================== ===== ====== ======= ==================\n");
485             for (j = 0; j < vring->queue_size; j++)
486               {
487                 if (vif->is_packed)
488                   {
489                     vnet_virtio_vring_packed_desc_t *desc =
490                       &vring->packed_desc[j];
491                     vlib_cli_output (vm,
492                                      "  %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
493                                      j, desc->addr,
494                                      desc->len,
495                                      desc->flags, desc->id, desc->addr);
496                   }
497                 else
498                   {
499                     vnet_virtio_vring_desc_t *desc = &vring->desc[j];
500                     vlib_cli_output (vm,
501                                      "  %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
502                                      j, desc->addr,
503                                      desc->len,
504                                      desc->flags, desc->next, desc->addr);
505                   }
506               }
507           }
508       }
509       vec_foreach_index (i, vif->txq_vrings)
510       {
511         vring = vec_elt_at_index (vif->txq_vrings, i);
512         vlib_cli_output (vm, "  Virtqueue (TX) %d", vring->queue_id);
513         vlib_cli_output (
514           vm, "    qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
515           vring->queue_size, vring->last_used_idx, vring->desc_next,
516           vring->desc_in_use);
517         if (vif->is_packed)
518           {
519             vlib_cli_output (vm,
520                              "    driver_event.flags 0x%x driver_event.off_wrap %d device_event.flags 0x%x device_event.off_wrap %d",
521                              vring->driver_event->flags,
522                              vring->driver_event->off_wrap,
523                              vring->device_event->flags,
524                              vring->device_event->off_wrap);
525             vlib_cli_output (vm,
526                              "    avail wrap counter %d, used wrap counter %d",
527                              vring->avail_wrap_counter,
528                              vring->used_wrap_counter);
529           }
530         else
531           vlib_cli_output (vm,
532                            "    avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
533                            vring->avail->flags, vring->avail->idx,
534                            vring->used->flags, vring->used->idx);
535         if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
536           {
537             vlib_cli_output (vm, "    kickfd %d, callfd %d", vring->kick_fd,
538                              vring->call_fd);
539           }
540         if (vring->flow_table)
541           {
542             vlib_cli_output (vm, "    %U", gro_flow_table_format,
543                              vring->flow_table);
544           }
545         if (vif->packet_buffering)
546           {
547             vlib_cli_output (vm, "    %U", virtio_vring_buffering_format,
548                              vring->buffering);
549           }
550         if (show_descr)
551           {
552             vlib_cli_output (vm, "\n  descriptor table:\n");
553             vlib_cli_output (vm,
554                              "   id          addr         len  flags  next/id      user_addr\n");
555             vlib_cli_output (vm,
556                              "  ===== ================== ===== ====== ======== ==================\n");
557             for (j = 0; j < vring->queue_size; j++)
558               {
559                 if (vif->is_packed)
560                   {
561                     vnet_virtio_vring_packed_desc_t *desc =
562                       &vring->packed_desc[j];
563                     vlib_cli_output (vm,
564                                      "  %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
565                                      j, desc->addr,
566                                      desc->len,
567                                      desc->flags, desc->id, desc->addr);
568                   }
569                 else
570                   {
571                     vnet_virtio_vring_desc_t *desc = &vring->desc[j];
572                     vlib_cli_output (vm,
573                                      "  %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
574                                      j, desc->addr,
575                                      desc->len,
576                                      desc->flags, desc->next, desc->addr);
577                   }
578               }
579           }
580       }
581       if (type == VIRTIO_IF_TYPE_PCI && vif->cxq_vring != NULL &&
582           vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
583         {
584           vring = vif->cxq_vring;
585           vlib_cli_output (vm, "  Virtqueue (CTRL) %d", vring->queue_id);
586           vlib_cli_output (
587             vm, "    qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
588             vring->queue_size, vring->last_used_idx, vring->desc_next,
589             vring->desc_in_use);
590           if (vif->is_packed)
591             {
592               vlib_cli_output (vm,
593                                "    driver_event.flags 0x%x driver_event.off_wrap %d device_event.flags 0x%x device_event.off_wrap %d",
594                                vring->driver_event->flags,
595                                vring->driver_event->off_wrap,
596                                vring->device_event->flags,
597                                vring->device_event->off_wrap);
598               vlib_cli_output (vm,
599                                "    avail wrap counter %d, used wrap counter %d",
600                                vring->avail_wrap_counter,
601                                vring->used_wrap_counter);
602             }
603           else
604             {
605               vlib_cli_output (vm,
606                                "    avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
607                                vring->avail->flags, vring->avail->idx,
608                                vring->used->flags, vring->used->idx);
609             }
610           if (show_descr)
611             {
612               vlib_cli_output (vm, "\n  descriptor table:\n");
613               vlib_cli_output (vm,
614                                "   id          addr         len  flags  next/id      user_addr\n");
615               vlib_cli_output (vm,
616                                "  ===== ================== ===== ====== ======== ==================\n");
617               for (j = 0; j < vring->queue_size; j++)
618                 {
619                   if (vif->is_packed)
620                     {
621                       vnet_virtio_vring_packed_desc_t *desc =
622                         &vring->packed_desc[j];
623                       vlib_cli_output (vm,
624                                        "  %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
625                                        j, desc->addr,
626                                        desc->len,
627                                        desc->flags, desc->id, desc->addr);
628                     }
629                   else
630                     {
631                       vnet_virtio_vring_desc_t *desc = &vring->desc[j];
632                       vlib_cli_output (vm,
633                                        "  %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
634                                        j, desc->addr,
635                                        desc->len,
636                                        desc->flags, desc->next, desc->addr);
637                     }
638                 }
639             }
640         }
641     }
642
643 }
644
645 static clib_error_t *
646 virtio_init (vlib_main_t * vm)
647 {
648   virtio_main_t *vim = &virtio_main;
649   clib_error_t *error = 0;
650
651   vim->log_default = vlib_log_register_class ("virtio", 0);
652   vlib_log_debug (vim->log_default, "initialized");
653
654   return error;
655 }
656
657 VLIB_INIT_FUNCTION (virtio_init);
658
659 /*
660  * fd.io coding-style-patch-verification: ON
661  *
662  * Local Variables:
663  * eval: (c-set-style "gnu")
664  * End:
665  */