FD.io VPP  v19.08.3-2-gbabecb413
Vector Packet Processing
device.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2016 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 
22 #include <vlib/vlib.h>
23 #include <vlib/unix/unix.h>
24 #include <vnet/ethernet/ethernet.h>
25 #include <vnet/ip/ip4_packet.h>
26 #include <vnet/ip/ip6_packet.h>
28 
29 #define foreach_virtio_tx_func_error \
30 _(NO_FREE_SLOTS, "no free tx slots") \
31 _(TRUNC_PACKET, "packet > buffer size -- truncated in tx ring") \
32 _(PENDING_MSGS, "pending msgs in tx ring") \
33 _(NO_TX_QUEUES, "no tx queues") \
34 _(OUT_OF_ORDER, "out-of-order buffers in used ring")
35 
36 typedef enum
37 {
38 #define _(f,s) VIRTIO_TX_ERROR_##f,
40 #undef _
43 
44 static char *virtio_tx_func_error_strings[] = {
45 #define _(n,s) s,
47 #undef _
48 };
49 
50 #ifndef CLIB_MARCH_VARIANT
51 u8 *
52 format_virtio_device_name (u8 * s, va_list * args)
53 {
54  u32 dev_instance = va_arg (*args, u32);
56  virtio_if_t *vif = pool_elt_at_index (mm->interfaces, dev_instance);
57 
58  if (vif->type == VIRTIO_IF_TYPE_TAP)
59  s = format (s, "tap%u", vif->id);
60  else if (vif->type == VIRTIO_IF_TYPE_PCI)
61  s = format (s, "virtio-%x/%x/%x/%x", vif->pci_addr.domain,
62  vif->pci_addr.bus, vif->pci_addr.slot,
63  vif->pci_addr.function);
64  else
65  s = format (s, "virtio-%lu", vif->dev_instance);
66 
67  return s;
68 }
69 #endif /* CLIB_MARCH_VARIANT */
70 
71 static u8 *
72 format_virtio_device (u8 * s, va_list * args)
73 {
74  u32 dev_instance = va_arg (*args, u32);
75  int verbose = va_arg (*args, int);
76  u32 indent = format_get_indent (s);
77 
78  s = format (s, "VIRTIO interface");
79  if (verbose)
80  {
81  s = format (s, "\n%U instance %u", format_white_space, indent + 2,
82  dev_instance);
83  }
84  return s;
85 }
86 
87 static u8 *
88 format_virtio_tx_trace (u8 * s, va_list * args)
89 {
90  s = format (s, "Unimplemented...");
91  return s;
92 }
93 
95 virtio_memset_ring_u32 (u32 * ring, u32 start, u32 ring_size, u32 n_buffers)
96 {
97  ASSERT (n_buffers <= ring_size);
98 
99  if (PREDICT_TRUE (start + n_buffers <= ring_size))
100  {
101  clib_memset_u32 (ring + start, ~0, n_buffers);
102  }
103  else
104  {
105  clib_memset_u32 (ring + start, ~0, ring_size - start);
106  clib_memset_u32 (ring, ~0, n_buffers - (ring_size - start));
107  }
108 }
109 
112  uword node_index)
113 {
114  u16 used = vring->desc_in_use;
115  u16 sz = vring->size;
116  u16 mask = sz - 1;
117  u16 last = vring->last_used_idx;
118  u16 n_left = vring->used->idx - last;
119  u16 out_of_order_count = 0;
120 
121  if (n_left == 0)
122  return;
123 
124  while (n_left)
125  {
126  struct vring_used_elem *e = &vring->used->ring[last & mask];
127  u16 slot, n_buffers;
128  slot = n_buffers = e->id;
129 
130  while (e->id == (n_buffers & mask))
131  {
132  n_left--;
133  last++;
134  n_buffers++;
135  if (n_left == 0)
136  break;
137  e = &vring->used->ring[last & mask];
138  }
139  vlib_buffer_free_from_ring (vm, vring->buffers, slot,
140  sz, (n_buffers - slot));
141  virtio_memset_ring_u32 (vring->buffers, slot, sz, (n_buffers - slot));
142  used -= (n_buffers - slot);
143 
144  if (n_left > 0)
145  {
146  vlib_buffer_free (vm, &vring->buffers[e->id], 1);
147  vring->buffers[e->id] = ~0;
148  used--;
149  last++;
150  n_left--;
151  out_of_order_count++;
152  vring->flags |= VRING_TX_OUT_OF_ORDER;
153  }
154  }
155 
156  /*
157  * Some vhost-backends give buffers back in out-of-order fashion in used ring.
158  * It impacts the overall virtio-performance.
159  */
160  if (out_of_order_count)
161  vlib_error_count (vm, node_index, VIRTIO_TX_ERROR_OUT_OF_ORDER,
162  out_of_order_count);
163 
164  vring->desc_in_use = used;
165  vring->last_used_idx = last;
166 }
167 
170  virtio_vring_t * vring, u32 bi, u16 avail, u16 next,
171  u16 mask, int do_gso)
172 {
173  u16 n_added = 0;
174  int hdr_sz = vif->virtio_net_hdr_sz;
175  struct vring_desc *d;
176  d = &vring->desc[next];
177  vlib_buffer_t *b = vlib_get_buffer (vm, bi);
178  struct virtio_net_hdr_v1 *hdr = vlib_buffer_get_current (b) - hdr_sz;
179 
180  clib_memset (hdr, 0, hdr_sz);
181  if (do_gso && (b->flags & VNET_BUFFER_F_GSO))
182  {
183  if (b->flags & VNET_BUFFER_F_IS_IP4)
184  {
185  hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
186  hdr->gso_size = vnet_buffer2 (b)->gso_size;
187  hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
188  hdr->csum_start = vnet_buffer (b)->l4_hdr_offset; // 0x22;
189  hdr->csum_offset = 0x10;
190  }
191  else
192  {
193  hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
194  hdr->gso_size = vnet_buffer2 (b)->gso_size;
195  hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
196  hdr->csum_start = vnet_buffer (b)->l4_hdr_offset; // 0x36;
197  hdr->csum_offset = 0x10;
198  }
199  }
200 
201  if (PREDICT_TRUE ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0))
202  {
203  d->addr =
205  b) :
207  d->len = b->current_length + hdr_sz;
208  d->flags = 0;
209  }
210  else
211  {
212  /*
213  * We are using single vlib_buffer_t for indirect descriptor(s)
214  * chain. Single descriptor is 16 bytes and vlib_buffer_t
215  * has 2048 bytes space. So maximum long chain can have 128
216  * (=2048/16) indirect descriptors.
217  * It can easily support 65535 bytes of Jumbo frames with
218  * each data buffer size of 512 bytes minimum.
219  */
220  u32 indirect_buffer = 0;
221  if (PREDICT_FALSE (vlib_buffer_alloc (vm, &indirect_buffer, 1) == 0))
222  return n_added;
223 
224  vlib_buffer_t *indirect_desc = vlib_get_buffer (vm, indirect_buffer);
225  indirect_desc->current_data = 0;
226  indirect_desc->flags |= VLIB_BUFFER_NEXT_PRESENT;
227  indirect_desc->next_buffer = bi;
228  bi = indirect_buffer;
229 
230  struct vring_desc *id =
231  (struct vring_desc *) vlib_buffer_get_current (indirect_desc);
232  u32 count = 1;
233  if (vif->type == VIRTIO_IF_TYPE_PCI)
234  {
235  d->addr = vlib_physmem_get_pa (vm, id);
236  id->addr = vlib_buffer_get_current_pa (vm, b) - hdr_sz;
237 
238  /*
239  * If VIRTIO_F_ANY_LAYOUT is not negotiated, then virtio_net_hdr
240  * should be presented in separate descriptor and data will start
241  * from next descriptor.
242  */
243  if (PREDICT_TRUE
244  (vif->features & VIRTIO_FEATURE (VIRTIO_F_ANY_LAYOUT)))
245  id->len = b->current_length + hdr_sz;
246  else
247  {
248  id->len = hdr_sz;
249  id->flags = VRING_DESC_F_NEXT;
250  id->next = count;
251  count++;
252  id++;
253  id->addr = vlib_buffer_get_current_pa (vm, b);
254  id->len = b->current_length;
255  }
256  while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
257  {
258  id->flags = VRING_DESC_F_NEXT;
259  id->next = count;
260  count++;
261  id++;
262  b = vlib_get_buffer (vm, b->next_buffer);
263  id->addr = vlib_buffer_get_current_pa (vm, b);
264  id->len = b->current_length;
265  }
266  }
267  else /* VIRTIO_IF_TYPE_TAP */
268  {
269  d->addr = pointer_to_uword (id);
270  /* first buffer in chain */
271  id->addr = pointer_to_uword (vlib_buffer_get_current (b)) - hdr_sz;
272  id->len = b->current_length + hdr_sz;
273 
274  while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
275  {
276  id->flags = VRING_DESC_F_NEXT;
277  id->next = count;
278  count++;
279  id++;
280  b = vlib_get_buffer (vm, b->next_buffer);
281  id->addr = pointer_to_uword (vlib_buffer_get_current (b));
282  id->len = b->current_length;
283  }
284  }
285  id->flags = 0;
286  id->next = 0;
287  d->len = count * sizeof (struct vring_desc);
288  d->flags = VRING_DESC_F_INDIRECT;
289  }
290  vring->buffers[next] = bi;
291  vring->avail->ring[avail & mask] = next;
292  n_added++;
293  return n_added;
294 }
295 
298  u16 req, u16 next, u32 * first_free_desc_index,
299  u16 * free_desc_count)
300 {
301  u16 start = 0;
302  /* next is used as hint: from where to start looking */
303  for (u16 i = 0; i < size; i++, next++)
304  {
305  if (vring->buffers[next & mask] == ~0)
306  {
307  if (*first_free_desc_index == ~0)
308  {
309  *first_free_desc_index = (next & mask);
310  start = i;
311  (*free_desc_count)++;
312  req--;
313  if (req == 0)
314  break;
315  }
316  else
317  {
318  if (start + *free_desc_count == i)
319  {
320  (*free_desc_count)++;
321  req--;
322  if (req == 0)
323  break;
324  }
325  else
326  break;
327  }
328  }
329  }
330  return *first_free_desc_index;
331 }
332 
335  vlib_frame_t * frame, virtio_if_t * vif,
336  int do_gso)
337 {
338  u16 n_left = frame->n_vectors;
339  virtio_vring_t *vring;
340  u16 qid = vm->thread_index % vif->num_txqs;
341  vring = vec_elt_at_index (vif->txq_vrings, qid);
342  u16 used, next, avail;
343  u16 sz = vring->size;
344  u16 mask = sz - 1;
345  u16 retry_count = 2;
346  u32 *buffers = vlib_frame_vector_args (frame);
347 
349 
350  if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0 &&
351  (vring->last_kick_avail_idx != vring->avail->idx))
352  virtio_kick (vm, vring, vif);
353 
354 retry:
355  /* free consumed buffers */
356  virtio_free_used_device_desc (vm, vring, node->node_index);
357 
358  used = vring->desc_in_use;
359  next = vring->desc_next;
360  avail = vring->avail->idx;
361 
362  u16 free_desc_count = 0;
363 
365  {
366  u32 first_free_desc_index = ~0;
367 
368  virtio_find_free_desc (vring, sz, mask, n_left, next,
369  &first_free_desc_index, &free_desc_count);
370 
371  if (free_desc_count)
372  next = first_free_desc_index;
373  }
374  else
375  free_desc_count = sz - used;
376 
377  while (n_left && free_desc_count)
378  {
379  u16 n_added = 0;
380  n_added =
381  add_buffer_to_slot (vm, vif, vring, buffers[0], avail, next, mask,
382  do_gso);
383  if (!n_added)
384  break;
385  avail += n_added;
386  next = (next + n_added) & mask;
387  used += n_added;
388  buffers++;
389  n_left--;
390  free_desc_count--;
391  }
392 
393  if (n_left != frame->n_vectors)
394  {
396  vring->avail->idx = avail;
397  vring->desc_next = next;
398  vring->desc_in_use = used;
399  if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0)
400  virtio_kick (vm, vring, vif);
401  }
402 
403  if (n_left)
404  {
405  if (retry_count--)
406  goto retry;
407 
408  vlib_error_count (vm, node->node_index, VIRTIO_TX_ERROR_NO_FREE_SLOTS,
409  n_left);
410  vlib_buffer_free (vm, buffers, n_left);
411  }
412 
414 
415  return frame->n_vectors - n_left;
416 }
417 
419  vlib_node_runtime_t * node,
420  vlib_frame_t * frame)
421 {
422  virtio_main_t *nm = &virtio_main;
423  vnet_interface_output_runtime_t *rund = (void *) node->runtime_data;
425  vnet_main_t *vnm = vnet_get_main ();
426 
427  if (vnm->interface_main.gso_interface_count > 0)
428  return virtio_interface_tx_inline (vm, node, frame, vif, 1 /* do_gso */ );
429  else
430  return virtio_interface_tx_inline (vm, node, frame, vif,
431  0 /* no do_gso */ );
432 }
433 
434 static void
436  u32 node_index)
437 {
438  virtio_main_t *apm = &virtio_main;
439  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
441 
442  /* Shut off redirection */
443  if (node_index == ~0)
444  {
445  vif->per_interface_next_index = node_index;
446  return;
447  }
448 
451  node_index);
452 }
453 
454 static void
456 {
457  /* Nothing for now */
458 }
459 
460 static clib_error_t *
463 {
464  virtio_main_t *mm = &virtio_main;
465  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
467  virtio_vring_t *vring = vec_elt_at_index (vif->rxq_vrings, qid);
468 
469  if (vif->type == VIRTIO_IF_TYPE_PCI && !(vif->support_int_mode))
470  {
471  vring->avail->flags |= VIRTIO_RING_FLAG_MASK_INT;
472  return clib_error_return (0, "interrupt mode is not supported");
473  }
474 
476  vring->avail->flags |= VIRTIO_RING_FLAG_MASK_INT;
477  else
478  vring->avail->flags &= ~VIRTIO_RING_FLAG_MASK_INT;
479 
480  return 0;
481 }
482 
483 static clib_error_t *
485 {
486  virtio_main_t *mm = &virtio_main;
487  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
489 
491  {
492  vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP;
495  }
496  else
497  {
498  vif->flags &= ~VIRTIO_IF_FLAG_ADMIN_UP;
500  }
501  return 0;
502 }
503 
504 static clib_error_t *
506  u32 hw_if_index,
507  struct vnet_sw_interface_t *st, int is_add)
508 {
509  /* Nothing for now */
510  return 0;
511 }
512 
513 /* *INDENT-OFF* */
515  .name = "virtio",
516  .format_device_name = format_virtio_device_name,
517  .format_device = format_virtio_device,
518  .format_tx_trace = format_virtio_tx_trace,
519  .tx_function_n_errors = VIRTIO_TX_N_ERROR,
520  .tx_function_error_strings = virtio_tx_func_error_strings,
521  .rx_redirect_to_node = virtio_set_interface_next_node,
522  .clear_counters = virtio_clear_hw_interface_counters,
523  .admin_up_down_function = virtio_interface_admin_up_down,
524  .subif_add_del_function = virtio_subif_add_del_function,
525  .rx_mode_change_function = virtio_interface_rx_mode_change,
526 };
527 /* *INDENT-ON* */
528 
529 /*
530  * fd.io coding-style-patch-verification: ON
531  *
532  * Local Variables:
533  * eval: (c-set-style "gnu")
534  * End:
535  */
u32 per_interface_next_index
Definition: virtio.h:151
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
struct vring_used * used
Definition: virtio.h:105
static uword vlib_buffer_get_current_pa(vlib_main_t *vm, vlib_buffer_t *b)
Definition: buffer_funcs.h:427
vlib_node_registration_t virtio_input_node
(constructor) VLIB_REGISTER_NODE (virtio_input_node)
Definition: node.c:398
virtio_if_t * interfaces
Definition: virtio.h:193
u32 flags
Definition: vhost_user.h:141
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:865
#define foreach_virtio_tx_func_error
Definition: device.c:29
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define vnet_buffer2(b)
Definition: buffer.h:424
vnet_interface_main_t interface_main
Definition: vnet.h:56
#define PREDICT_TRUE(x)
Definition: clib.h:113
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
#define CLIB_MEMORY_STORE_BARRIER()
Definition: clib.h:119
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:57
u32 dev_instance
Definition: virtio.h:140
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static_always_inline void clib_spinlock_unlock_if_init(clib_spinlock_t *p)
Definition: lock.h:110
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u32 thread_index
Definition: main.h:218
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
static heap_elt_t * last(heap_header_t *h)
Definition: heap.c:53
int i
static u32 format_get_indent(u8 *s)
Definition: format.h:72
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
static_always_inline u32 virtio_find_free_desc(virtio_vring_t *vring, u16 size, u16 mask, u16 req, u16 next, u32 *first_free_desc_index, u16 *free_desc_count)
Definition: device.c:297
u16 domain
Definition: virtio.h:127
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1092
unsigned char u8
Definition: types.h:56
static char * virtio_tx_func_error_strings[]
Definition: device.c:44
virtio_tx_func_error_t
Definition: device.c:36
vnet_hw_interface_rx_mode
Definition: interface.h:53
struct vring_avail * avail
Definition: virtio.h:106
u64 features
Definition: virtio.h:164
#define static_always_inline
Definition: clib.h:100
u32 hw_if_index
Definition: virtio.h:141
static_always_inline uword virtio_interface_tx_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, virtio_if_t *vif, int do_gso)
Definition: device.c:334
VNET_DEVICE_CLASS_TX_FN() virtio_device_class(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: device.c:418
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
u8 bus
Definition: virtio.h:128
u8 support_int_mode
Definition: virtio.h:168
#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:107
static void virtio_clear_hw_interface_counters(u32 instance)
Definition: device.c:455
#define clib_error_return(e, args...)
Definition: error.h:99
#define VNET_DEVICE_CLASS_TX_FN(devclass)
Definition: interface.h:298
unsigned int u32
Definition: types.h:88
u32 id
Definition: virtio.h:148
static clib_error_t * virtio_interface_rx_mode_change(vnet_main_t *vnm, u32 hw_if_index, u32 qid, vnet_hw_interface_rx_mode mode)
Definition: device.c:461
u16 num_txqs
Definition: virtio.h:171
static void vlib_buffer_free_from_ring(vlib_main_t *vm, u32 *ring, u32 start, u32 ring_size, u32 n_buffers)
Free buffers from ring.
Definition: buffer_funcs.h:912
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
uword size
static_always_inline void virtio_memset_ring_u32(u32 *ring, u32 start, u32 ring_size, u32 n_buffers)
Definition: device.c:95
unsigned short u16
Definition: types.h:57
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
pci_addr_t pci_addr
Definition: virtio.h:149
#define PREDICT_FALSE(x)
Definition: clib.h:112
u32 node_index
Node index.
Definition: node.h:496
static u8 * format_virtio_device(u8 *s, va_list *args)
Definition: device.c:72
u16 desc_next
Definition: virtio.h:109
u16 virtio_net_hdr_sz
Definition: virtio.h:144
static void virtio_set_interface_next_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: device.c:435
virtio_vring_t * rxq_vrings
Definition: virtio.h:162
u16 last_used_idx
Definition: virtio.h:119
u16 n_vectors
Definition: node.h:397
static u8 * format_virtio_tx_trace(u8 *s, va_list *args)
Definition: device.c:88
vlib_main_t * vm
Definition: buffer.c:323
#define VIRTIO_RING_FLAG_MASK_INT
Definition: virtio.h:99
static clib_error_t * virtio_subif_add_del_function(vnet_main_t *vnm, u32 hw_if_index, struct vnet_sw_interface_t *st, int is_add)
Definition: device.c:505
static clib_error_t * virtio_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: device.c:484
u32 flags
Definition: virtio.h:138
u16 last_kick_avail_idx
Definition: virtio.h:120
vl_api_vxlan_gbp_api_tunnel_mode_t mode
Definition: vxlan_gbp.api:44
virtio_if_type_t type
Definition: virtio.h:145
#define ASSERT(truth)
#define VIRTIO_FEATURE(X)
Definition: virtio.h:76
VNET_DEVICE_CLASS(bond_dev_class)
size_t count
Definition: vapi.c:47
u8 function
Definition: virtio.h:130
static uword pointer_to_uword(const void *p)
Definition: types.h:131
virtio_main_t virtio_main
Definition: virtio.c:37
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
#define VRING_TX_OUT_OF_ORDER
Definition: virtio.h:115
static_always_inline u16 add_buffer_to_slot(vlib_main_t *vm, virtio_if_t *vif, virtio_vring_t *vring, u32 bi, u16 avail, u16 next, u16 mask, int do_gso)
Definition: device.c:169
static u64 vlib_physmem_get_pa(vlib_main_t *vm, void *mem)
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:140
u32 instance
Definition: gre.api:48
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags)
Definition: interface.c:492
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
static_always_inline void virtio_free_used_device_desc(vlib_main_t *vm, virtio_vring_t *vring, uword node_index)
Definition: device.c:111
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
u32 * buffers
Definition: virtio.h:118
#define vnet_buffer(b)
Definition: buffer.h:365
struct vring_desc * desc
Definition: virtio.h:104
u8 * format_virtio_device_name(u8 *s, va_list *args)
Definition: device.c:52
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:612
static_always_inline void clib_spinlock_lock_if_init(clib_spinlock_t *p)
Definition: lock.h:95
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
u16 desc_in_use
Definition: virtio.h:108
virtio_vring_t * txq_vrings
Definition: virtio.h:163
static_always_inline void virtio_kick(vlib_main_t *vm, virtio_vring_t *vring, virtio_if_t *vif)
Definition: virtio.h:218
u8 slot
Definition: virtio.h:129
static_always_inline void clib_memset_u32(void *p, u32 val, uword count)
Definition: string.h:332