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