FD.io VPP  v20.05-21-gb1500e9ff
Vector Packet Processing
virtio.c
Go to the documentation of this file.
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 <linux/virtio_net.h>
25 #include <linux/vhost.h>
26 #include <sys/eventfd.h>
27 
28 #include <vlib/vlib.h>
29 #include <vlib/pci/pci.h>
30 #include <vlib/unix/unix.h>
31 #include <vnet/ethernet/ethernet.h>
32 #include <vnet/ip/ip4_packet.h>
33 #include <vnet/ip/ip6_packet.h>
36 
38 
39 #define _IOCTL(fd,a,...) \
40  if (ioctl (fd, a, __VA_ARGS__) < 0) \
41  { \
42  err = clib_error_return_unix (0, "ioctl(" #a ")"); \
43  goto error; \
44  }
45 
46 static clib_error_t *
48 {
50  vnet_main_t *vnm = vnet_get_main ();
51  u16 qid = uf->private_data & 0xFFFF;
52  virtio_if_t *vif =
53  vec_elt_at_index (nm->interfaces, uf->private_data >> 16);
54  u64 b;
55 
56  CLIB_UNUSED (ssize_t size) = read (uf->file_descriptor, &b, sizeof (b));
57  if ((qid & 1) == 0)
59 
60  return 0;
61 }
62 
63 
66 {
67  virtio_vring_t *vring;
68  clib_file_t t = { 0 };
69  int i;
70 
71  if (!is_pow2 (sz))
72  return clib_error_return (0, "ring size must be power of 2");
73 
74  if (sz > 32768)
75  return clib_error_return (0, "ring size must be 32768 or lower");
76 
77  if (sz == 0)
78  sz = 256;
79 
80  if (idx % 2)
81  {
85  vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS (idx));
86  if (thm->n_vlib_mains > vif->num_txqs)
87  clib_spinlock_init (&vring->lockp);
88  }
89  else
90  {
93  vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS (idx));
94  }
95  i = sizeof (struct vring_desc) * sz;
98  clib_memset (vring->desc, 0, i);
99 
100  i = sizeof (struct vring_avail) + sz * sizeof (vring->avail->ring[0]);
103  clib_memset (vring->avail, 0, i);
104  // tell kernel that we don't need interrupt
105  vring->avail->flags = VIRTIO_RING_FLAG_MASK_INT;
106 
107  i = sizeof (struct vring_used) + sz * sizeof (struct vring_used_elem);
110  clib_memset (vring->used, 0, i);
111 
112  vring->queue_id = idx;
113  ASSERT (vring->buffers == 0);
115 
116  if (idx & 1)
117  {
118  clib_memset_u32 (vring->buffers, ~0, sz);
119  }
120 
121  vring->size = sz;
122  vring->call_fd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
123  vring->kick_fd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
124  virtio_log_debug (vif, "vring %u size %u call_fd %d kick_fd %d", idx,
125  vring->size, vring->call_fd, vring->kick_fd);
126 
128  t.file_descriptor = vring->call_fd;
129  t.private_data = vif->dev_instance << 16 | idx;
130  t.description = format (0, "%U vring %u", format_virtio_device_name,
131  vif->dev_instance, idx);
132  vring->call_file_index = clib_file_add (&file_main, &t);
133 
134  return 0;
135 }
136 
137 inline void
139 {
140  u16 used = vring->desc_in_use;
141  u16 last = vring->last_used_idx;
142  u16 mask = vring->size - 1;
143 
144  while (used)
145  {
146  vlib_buffer_free (vm, &vring->buffers[last & mask], 1);
147  last++;
148  used--;
149  }
150 }
151 
152 clib_error_t *
154 {
155  virtio_vring_t *vring =
157 
159  close (vring->kick_fd);
160  close (vring->call_fd);
161  if (vring->used)
162  {
163  virtio_free_rx_buffers (vm, vring);
164  clib_mem_free (vring->used);
165  }
166  if (vring->desc)
167  clib_mem_free (vring->desc);
168  if (vring->avail)
169  clib_mem_free (vring->avail);
170  vec_free (vring->buffers);
171  return 0;
172 }
173 
174 inline void
176 {
177  u16 used = vring->desc_in_use;
178  u16 sz = vring->size;
179  u16 mask = sz - 1;
180  u16 last = vring->last_used_idx;
181  u16 n_left = vring->used->idx - last;
182 
183  if (n_left == 0)
184  return;
185 
186  while (n_left)
187  {
188  struct vring_used_elem *e = &vring->used->ring[last & mask];
189  u16 slot = e->id;
190 
191  vlib_buffer_free (vm, &vring->buffers[slot], 1);
192  used--;
193  last++;
194  n_left--;
195  }
196  vring->desc_in_use = used;
197  vring->last_used_idx = last;
198 }
199 
200 clib_error_t *
202 {
203  virtio_vring_t *vring =
205 
207  close (vring->kick_fd);
208  close (vring->call_fd);
209  if (vring->used)
210  {
211  virtio_free_used_desc (vm, vring);
212  clib_mem_free (vring->used);
213  }
214  if (vring->desc)
215  clib_mem_free (vring->desc);
216  if (vring->avail)
217  clib_mem_free (vring->avail);
218  vec_free (vring->buffers);
219  clib_spinlock_free (&vring->lockp);
220  return 0;
221 }
222 
223 void
225 {
226  vnet_main_t *vnm = vnet_get_main ();
227  u32 thread_index;
228  virtio_vring_t *vring =
230  thread_index =
232  RX_QUEUE_ACCESS (idx));
233  vring->buffer_pool_index =
235  vlib_mains
236  [thread_index]->numa_node);
237 }
238 
239 inline void
241 {
242  if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF) ||
243  vif->features & VIRTIO_FEATURE (VIRTIO_F_VERSION_1))
244  vif->virtio_net_hdr_sz = sizeof (struct virtio_net_hdr_v1);
245  else
246  vif->virtio_net_hdr_sz = sizeof (struct virtio_net_hdr);
247 }
248 
249 inline void
250 virtio_show (vlib_main_t * vm, u32 * hw_if_indices, u8 show_descr, u32 type)
251 {
252  u32 i, j, hw_if_index;
253  virtio_if_t *vif;
254  vnet_main_t *vnm = &vnet_main;
255  virtio_main_t *mm = &virtio_main;
256  virtio_vring_t *vring;
257  struct feat_struct
258  {
259  u8 bit;
260  char *str;
261  };
262  struct feat_struct *feat_entry;
263 
264  static struct feat_struct feat_array[] = {
265 #define _(s,b) { .str = #s, .bit = b, },
267 #undef _
268  {.str = NULL}
269  };
270 
271  struct feat_struct *flag_entry;
272  static struct feat_struct flags_array[] = {
273 #define _(b,e,s) { .bit = b, .str = s, },
275 #undef _
276  {.str = NULL}
277  };
278 
279  if (!hw_if_indices)
280  return;
281 
282  for (hw_if_index = 0; hw_if_index < vec_len (hw_if_indices); hw_if_index++)
283  {
285  vnet_get_hw_interface (vnm, hw_if_indices[hw_if_index]);
286  vif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
287  if (vif->type != type)
288  continue;
289  vlib_cli_output (vm, "Interface: %U (ifindex %d)",
291  hw_if_indices[hw_if_index], vif->hw_if_index);
292  if (type == VIRTIO_IF_TYPE_PCI)
293  {
294  vlib_cli_output (vm, " PCI Address: %U", format_vlib_pci_addr,
295  &vif->pci_addr);
296  }
297  if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
298  {
299  u8 *str = 0;
300  if (vif->host_if_name)
301  vlib_cli_output (vm, " name \"%s\"", vif->host_if_name);
302  if (vif->net_ns)
303  vlib_cli_output (vm, " host-ns \"%s\"", vif->net_ns);
304  if (vif->host_mtu_size)
305  vlib_cli_output (vm, " host-mtu-size \"%d\"",
306  vif->host_mtu_size);
307  if (type == VIRTIO_IF_TYPE_TAP)
308  vlib_cli_output (vm, " host-mac-addr: %U",
310 
311  vec_foreach_index (i, vif->vhost_fds)
312  str = format (str, " %d", vif->vhost_fds[i]);
313  vlib_cli_output (vm, " vhost-fds%v", str);
314  vec_free (str);
315  vec_foreach_index (i, vif->tap_fds)
316  str = format (str, " %d", vif->tap_fds[i]);
317  vlib_cli_output (vm, " tap-fds%v", str);
318  vec_free (str);
319  }
320  vlib_cli_output (vm, " gso-enabled %d", vif->gso_enabled);
321  vlib_cli_output (vm, " csum-enabled %d", vif->csum_offload_enabled);
322  if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_PCI))
323  vlib_cli_output (vm, " Mac Address: %U", format_ethernet_address,
324  vif->mac_addr);
325  vlib_cli_output (vm, " Device instance: %u", vif->dev_instance);
326  vlib_cli_output (vm, " flags 0x%x", vif->flags);
327  flag_entry = (struct feat_struct *) &flags_array;
328  while (flag_entry->str)
329  {
330  if (vif->flags & (1ULL << flag_entry->bit))
331  vlib_cli_output (vm, " %s (%d)", flag_entry->str,
332  flag_entry->bit);
333  flag_entry++;
334  }
335  if (type == VIRTIO_IF_TYPE_PCI)
336  {
337  device_status (vm, vif);
338  }
339  vlib_cli_output (vm, " features 0x%lx", vif->features);
340  feat_entry = (struct feat_struct *) &feat_array;
341  while (feat_entry->str)
342  {
343  if (vif->features & (1ULL << feat_entry->bit))
344  vlib_cli_output (vm, " %s (%d)", feat_entry->str,
345  feat_entry->bit);
346  feat_entry++;
347  }
348  vlib_cli_output (vm, " remote-features 0x%lx", vif->remote_features);
349  feat_entry = (struct feat_struct *) &feat_array;
350  while (feat_entry->str)
351  {
352  if (vif->remote_features & (1ULL << feat_entry->bit))
353  vlib_cli_output (vm, " %s (%d)", feat_entry->str,
354  feat_entry->bit);
355  feat_entry++;
356  }
357  vlib_cli_output (vm, " Number of RX Virtqueue %u", vif->num_rxqs);
358  vlib_cli_output (vm, " Number of TX Virtqueue %u", vif->num_txqs);
359  if (vif->cxq_vring != NULL
360  && vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
361  vlib_cli_output (vm, " Number of CTRL Virtqueue 1");
362  vec_foreach_index (i, vif->rxq_vrings)
363  {
364  vring = vec_elt_at_index (vif->rxq_vrings, i);
365  vlib_cli_output (vm, " Virtqueue (RX) %d", vring->queue_id);
366  vlib_cli_output (vm,
367  " qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
368  vring->size, vring->last_used_idx, vring->desc_next,
369  vring->desc_in_use);
370  vlib_cli_output (vm,
371  " avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
372  vring->avail->flags, vring->avail->idx,
373  vring->used->flags, vring->used->idx);
374  if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
375  {
376  vlib_cli_output (vm, " kickfd %d, callfd %d", vring->kick_fd,
377  vring->call_fd);
378  }
379  if (show_descr)
380  {
381  vlib_cli_output (vm, "\n descriptor table:\n");
382  vlib_cli_output (vm,
383  " id addr len flags next user_addr\n");
384  vlib_cli_output (vm,
385  " ===== ================== ===== ====== ===== ==================\n");
386  for (j = 0; j < vring->size; j++)
387  {
388  struct vring_desc *desc = &vring->desc[j];
389  vlib_cli_output (vm,
390  " %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
391  j, desc->addr,
392  desc->len,
393  desc->flags, desc->next, desc->addr);
394  }
395  }
396  }
397  vec_foreach_index (i, vif->txq_vrings)
398  {
399  vring = vec_elt_at_index (vif->txq_vrings, i);
400  vlib_cli_output (vm, " Virtqueue (TX) %d", vring->queue_id);
401  vlib_cli_output (vm,
402  " qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
403  vring->size, vring->last_used_idx, vring->desc_next,
404  vring->desc_in_use);
405  vlib_cli_output (vm,
406  " avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
407  vring->avail->flags, vring->avail->idx,
408  vring->used->flags, vring->used->idx);
409  if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
410  {
411  vlib_cli_output (vm, " kickfd %d, callfd %d", vring->kick_fd,
412  vring->call_fd);
413  }
414  if (show_descr)
415  {
416  vlib_cli_output (vm, "\n descriptor table:\n");
417  vlib_cli_output (vm,
418  " id addr len flags next user_addr\n");
419  vlib_cli_output (vm,
420  " ===== ================== ===== ====== ===== ==================\n");
421  for (j = 0; j < vring->size; j++)
422  {
423  struct vring_desc *desc = &vring->desc[j];
424  vlib_cli_output (vm,
425  " %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
426  j, desc->addr,
427  desc->len,
428  desc->flags, desc->next, desc->addr);
429  }
430  }
431  }
432  if (vif->cxq_vring != NULL
433  && vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
434  {
435  vring = vif->cxq_vring;
436  vlib_cli_output (vm, " Virtqueue (CTRL) %d", vring->queue_id);
437  vlib_cli_output (vm,
438  " qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
439  vring->size, vring->last_used_idx,
440  vring->desc_next, vring->desc_in_use);
441  vlib_cli_output (vm,
442  " avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
443  vring->avail->flags, vring->avail->idx,
444  vring->used->flags, vring->used->idx);
445  if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
446  {
447  vlib_cli_output (vm, " kickfd %d, callfd %d", vring->kick_fd,
448  vring->call_fd);
449  }
450  if (show_descr)
451  {
452  vlib_cli_output (vm, "\n descriptor table:\n");
453  vlib_cli_output (vm,
454  " id addr len flags next user_addr\n");
455  vlib_cli_output (vm,
456  " ===== ================== ===== ====== ===== ==================\n");
457  for (j = 0; j < vring->size; j++)
458  {
459  struct vring_desc *desc = &vring->desc[j];
460  vlib_cli_output (vm,
461  " %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
462  j, desc->addr,
463  desc->len,
464  desc->flags, desc->next, desc->addr);
465  }
466  }
467  }
468 
469  }
470 
471 }
472 
473 static clib_error_t *
475 {
476  virtio_main_t *vim = &virtio_main;
477  clib_error_t *error = 0;
478 
479  vim->log_default = vlib_log_register_class ("virtio", 0);
480  vlib_log_debug (vim->log_default, "initialized");
481 
482  return error;
483 }
484 
486 
487 /*
488  * fd.io coding-style-patch-verification: ON
489  *
490  * Local Variables:
491  * eval: (c-set-style "gnu")
492  * End:
493  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:209
struct vring_used * used
Definition: virtio.h:110
#define vec_foreach_index(var, v)
Iterate over vector indices.
format_function_t format_vnet_hw_if_index_name
void virtio_set_net_hdr_size(virtio_if_t *vif)
Definition: virtio.c:240
virtio_if_t * interfaces
Definition: virtio.h:195
#define CLIB_UNUSED(x)
Definition: clib.h:86
void virtio_show(vlib_main_t *vm, u32 *hw_if_indices, u8 show_descr, u32 type)
Definition: virtio.c:250
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:937
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
unsigned long u64
Definition: types.h:89
int gso_enabled
Definition: virtio.h:183
u32 host_mtu_size
Definition: virtio.h:182
u32 dev_instance
Definition: virtio.h:145
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
#define foreach_virtio_net_features
Definition: virtio.h:26
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u32 file_descriptor
Definition: file.h:54
static heap_elt_t * last(heap_header_t *h)
Definition: heap.c:53
void virtio_vring_set_numa_node(vlib_main_t *vm, virtio_if_t *vif, u32 idx)
Definition: virtio.c:224
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:518
vlib_main_t ** vlib_mains
Definition: buffer.c:332
unsigned char u8
Definition: types.h:56
clib_error_t * virtio_vring_free_tx(vlib_main_t *vm, virtio_if_t *vif, u32 idx)
Definition: virtio.c:201
clib_file_function_t * read_function
Definition: file.h:67
static void clib_spinlock_free(clib_spinlock_t *p)
Definition: lock.h:70
struct vring_avail * avail
Definition: virtio.h:111
u64 features
Definition: virtio.h:163
u32 hw_if_index
Definition: virtio.h:146
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
static clib_error_t * virtio_init(vlib_main_t *vm)
Definition: virtio.c:474
#define TX_QUEUE_ACCESS(X)
Definition: virtio.h:79
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
void device_status(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:379
static_always_inline void vnet_device_input_set_interrupt_pending(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id)
Definition: devices.h:136
void virtio_free_rx_buffers(vlib_main_t *vm, virtio_vring_t *vring)
Definition: virtio.c:138
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
clib_spinlock_t lockp
Definition: virtio.h:112
#define clib_error_return(e, args...)
Definition: error.h:99
clib_file_main_t file_main
Definition: main.c:63
unsigned int u32
Definition: types.h:88
#define vlib_log_debug(...)
Definition: log.h:109
u16 queue_id
Definition: virtio.h:119
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:63
u16 num_txqs
Definition: virtio.h:170
vl_api_fib_path_type_t type
Definition: fib_types.api:123
u8 * description
Definition: file.h:70
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
int * vhost_fds
Definition: virtio.h:157
static_always_inline uword vnet_get_device_input_thread_index(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id)
Definition: devices.h:127
unsigned short u16
Definition: types.h:57
u64 size
Definition: vhost_user.h:150
pci_addr_t pci_addr
Definition: virtio.h:154
vnet_main_t vnet_main
Definition: misc.c:43
u8 buffer_pool_index
Definition: virtio.h:117
vlib_main_t * vm
Definition: in2out_ed.c:1599
#define virtio_log_debug(vif, f,...)
Definition: virtio.h:236
u16 desc_next
Definition: virtio.h:114
u16 virtio_net_hdr_sz
Definition: virtio.h:149
u8 slot
Definition: pci_types.api:22
u16 num_rxqs
Definition: virtio.h:169
virtio_vring_t * rxq_vrings
Definition: virtio.h:161
format_function_t format_virtio_device_name
Definition: virtio.h:217
u16 last_used_idx
Definition: virtio.h:124
#define VIRTIO_RING_FLAG_MASK_INT
Definition: virtio.h:104
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
u32 call_file_index
Definition: virtio.h:122
u8 * net_ns
Definition: virtio.h:175
u8 mac_addr[6]
Definition: virtio.h:173
u32 flags
Definition: virtio.h:143
vlib_log_class_t log_default
Definition: virtio.h:193
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:256
virtio_if_type_t type
Definition: virtio.h:150
void virtio_free_used_desc(vlib_main_t *vm, virtio_vring_t *vring)
Definition: virtio.c:175
#define ASSERT(truth)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
u64 remote_features
Definition: virtio.h:163
static uword clib_file_add(clib_file_main_t *um, clib_file_t *template)
Definition: file.h:96
static void clib_file_del_by_index(clib_file_main_t *um, uword index)
Definition: file.h:119
#define VIRTIO_FEATURE(X)
Definition: virtio.h:75
clib_error_t * virtio_vring_init(vlib_main_t *vm, virtio_if_t *vif, u16 idx, u16 sz)
Definition: virtio.c:65
u8 host_mac_addr[6]
Definition: virtio.h:177
static void clib_mem_free(void *p)
Definition: mem.h:215
virtio_main_t virtio_main
Definition: virtio.c:37
vl_api_ip4_address_t hi
Definition: arp.api:37
static uword is_pow2(uword x)
Definition: clib.h:250
#define RX_QUEUE_ACCESS(X)
Definition: virtio.h:80
int csum_offload_enabled
Definition: virtio.h:184
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u32 * buffers
Definition: virtio.h:123
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:165
virtio_vring_t * cxq_vring
Definition: virtio.h:187
clib_error_t * virtio_vring_free_rx(vlib_main_t *vm, virtio_if_t *vif, u32 idx)
Definition: virtio.c:153
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
uword private_data
Definition: file.h:64
struct vring_desc * desc
Definition: virtio.h:109
Definition: file.h:51
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
static u8 vlib_buffer_pool_get_default_for_numa(vlib_main_t *vm, u32 numa_node)
Definition: buffer_funcs.h:199
int * tap_fds
Definition: virtio.h:158
format_function_t format_vlib_pci_addr
Definition: pci.h:324
u16 desc_in_use
Definition: virtio.h:113
virtio_vring_t * txq_vrings
Definition: virtio.h:162
static clib_error_t * call_read_ready(clib_file_t *uf)
Definition: virtio.c:47
u8 * host_if_name
Definition: virtio.h:174
static_always_inline void clib_memset_u32(void *p, u32 val, uword count)
Definition: string.h:332