FD.io VPP  v21.10.1-2-g0a485f517
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/vnet.h>
25 #include <vnet/ethernet/ethernet.h>
26 #include <vnet/gso/gro_func.h>
28 #include <vnet/ip/ip4_packet.h>
29 #include <vnet/ip/ip6_packet.h>
30 #include <vnet/tcp/tcp_packet.h>
31 #include <vnet/udp/udp_packet.h>
33 
34 #define VIRTIO_TX_MAX_CHAIN_LEN 127
35 
36 #define foreach_virtio_tx_func_error \
37 _(NO_FREE_SLOTS, "no free tx slots") \
38 _(TRUNC_PACKET, "packet > buffer size -- truncated in tx ring") \
39 _(PENDING_MSGS, "pending msgs in tx ring") \
40 _(INDIRECT_DESC_ALLOC_FAILED, "indirect descriptor allocation failed - packet drop") \
41 _(OUT_OF_ORDER, "out-of-order buffers in used ring") \
42 _(GSO_PACKET_DROP, "gso disabled on itf -- gso packet drop") \
43 _(CSUM_OFFLOAD_PACKET_DROP, "checksum offload disabled on itf -- csum offload packet drop")
44 
45 typedef enum
46 {
47 #define _(f,s) VIRTIO_TX_ERROR_##f,
49 #undef _
52 
53 static char *virtio_tx_func_error_strings[] = {
54 #define _(n,s) s,
56 #undef _
57 };
58 
59 static u8 *
60 format_virtio_device (u8 * s, va_list * args)
61 {
62  u32 dev_instance = va_arg (*args, u32);
63  int verbose = va_arg (*args, int);
64  u32 indent = format_get_indent (s);
65 
66  s = format (s, "VIRTIO interface");
67  if (verbose)
68  {
69  s = format (s, "\n%U instance %u", format_white_space, indent + 2,
70  dev_instance);
71  }
72  return s;
73 }
74 
75 typedef struct
76 {
82 
83 static u8 *
84 format_virtio_tx_trace (u8 * s, va_list * va)
85 {
86  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
87  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
88  virtio_tx_trace_t *t = va_arg (*va, virtio_tx_trace_t *);
89  u32 indent = format_get_indent (s);
90 
91  s = format (s, "%Ubuffer 0x%x: %U\n", format_white_space, indent,
93  s =
94  format (s, "%U%U\n", format_white_space, indent,
96  s =
97  format (s, "%U%U", format_white_space, indent,
99  sizeof (t->buffer.pre_data));
100  return s;
101 }
102 
103 static void
105  u32 bi, int is_tun)
106 {
108  t = vlib_add_trace (vm, node, b0, sizeof (t[0]));
109  t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
110  t->buffer_index = bi;
111  if (is_tun)
112  {
113  int is_ip4 = 0, is_ip6 = 0;
114 
115  switch (((u8 *) vlib_buffer_get_current (b0))[0] & 0xf0)
116  {
117  case 0x40:
118  is_ip4 = 1;
119  break;
120  case 0x60:
121  is_ip6 = 1;
122  break;
123  default:
124  break;
125  }
126  vnet_generic_header_offset_parser (b0, &t->gho, 0, is_ip4, is_ip6);
127  }
128  else
130  b0->flags &
131  VNET_BUFFER_F_IS_IP4,
132  b0->flags & VNET_BUFFER_F_IS_IP6);
133 
134  clib_memcpy_fast (&t->buffer, b0, sizeof (*b0) - sizeof (b0->pre_data));
136  sizeof (t->buffer.pre_data));
137 }
138 
139 static void
141  uword node_index, u32 *buffers, u16 n,
143 {
147  vm->thread_index, vif->sw_if_index, n);
148  vlib_buffer_free (vm, buffers, n);
149 }
150 
151 static void
152 virtio_memset_ring_u32 (u32 *ring, u32 start, u32 ring_size, u32 n_buffers)
153 {
154  ASSERT (n_buffers <= ring_size);
155 
156  if (PREDICT_TRUE (start + n_buffers <= ring_size))
157  {
158  clib_memset_u32 (ring + start, ~0, n_buffers);
159  }
160  else
161  {
162  clib_memset_u32 (ring + start, ~0, ring_size - start);
163  clib_memset_u32 (ring, ~0, n_buffers - (ring_size - start));
164  }
165 }
166 
167 static void
170 {
171  u16 used = vring->desc_in_use;
172  u16 sz = vring->size;
173  u16 mask = sz - 1;
174  u16 last = vring->last_used_idx;
175  u16 n_left = vring->used->idx - last;
176  u16 out_of_order_count = 0;
177 
178  if (n_left == 0)
179  return;
180 
181  while (n_left)
182  {
183  vring_used_elem_t *e = &vring->used->ring[last & mask];
184  u16 slot, n_buffers;
185  slot = n_buffers = e->id;
186 
187  while (e->id == (n_buffers & mask))
188  {
189  n_left--;
190  last++;
191  n_buffers++;
192  vring_desc_t *d = &vring->desc[e->id];
193  u16 next;
194  while (d->flags & VRING_DESC_F_NEXT)
195  {
196  n_buffers++;
197  next = d->next;
198  d = &vring->desc[next];
199  }
200  if (n_left == 0)
201  break;
202  e = &vring->used->ring[last & mask];
203  }
205  sz, (n_buffers - slot));
206  virtio_memset_ring_u32 (vring->buffers, slot, sz, (n_buffers - slot));
207  used -= (n_buffers - slot);
208 
209  if (n_left > 0)
210  {
211  vlib_buffer_free (vm, &vring->buffers[e->id], 1);
212  vring->buffers[e->id] = ~0;
213  used--;
214  last++;
215  n_left--;
216  out_of_order_count++;
217  vring->flags |= VRING_TX_OUT_OF_ORDER;
218  }
219  }
220 
221  /*
222  * Some vhost-backends give buffers back in out-of-order fashion in used ring.
223  * It impacts the overall virtio-performance.
224  */
225  if (out_of_order_count)
226  vlib_error_count (vm, node_index, VIRTIO_TX_ERROR_OUT_OF_ORDER,
227  out_of_order_count);
228 
229  vring->desc_in_use = used;
230  vring->last_used_idx = last;
231 }
232 
233 static void
236 {
237  vring_packed_desc_t *d;
238  u16 sz = vring->size;
239  u16 last = vring->last_used_idx;
240  u16 n_buffers = 0, start;
241  u16 flags;
242 
243  if (vring->desc_in_use == 0)
244  return;
245 
246  d = &vring->packed_desc[last];
247  flags = d->flags;
248  start = d->id;
249 
250  while ((flags & VRING_DESC_F_AVAIL) == (vring->used_wrap_counter << 7) &&
251  (flags & VRING_DESC_F_USED) == (vring->used_wrap_counter << 15))
252  {
253  last++;
254  n_buffers++;
255 
256  if (last >= sz)
257  {
258  last = 0;
259  vring->used_wrap_counter ^= 1;
260  }
261  d = &vring->packed_desc[last];
262  flags = d->flags;
263  }
264 
265  if (n_buffers)
266  {
267  vlib_buffer_free_from_ring (vm, vring->buffers, start, sz, n_buffers);
268  virtio_memset_ring_u32 (vring->buffers, start, sz, n_buffers);
269  vring->desc_in_use -= n_buffers;
270  vring->last_used_idx = last;
271  }
272 }
273 
274 static void
276  uword node_index, int packed)
277 {
278  if (packed)
280  else
282 
283 }
284 
285 static void
286 set_checksum_offsets (vlib_buffer_t *b, virtio_net_hdr_v1_t *hdr,
287  const int is_l2)
288 {
289  vnet_buffer_oflags_t oflags = vnet_buffer (b)->oflags;
290 
291  if (b->flags & VNET_BUFFER_F_IS_IP4)
292  {
293  ip4_header_t *ip4;
294  generic_header_offset_t gho = { 0 };
295  vnet_generic_header_offset_parser (b, &gho, is_l2, 1 /* ip4 */ ,
296  0 /* ip6 */ );
297  hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
298  hdr->csum_start = gho.l4_hdr_offset; // 0x22;
299  if (oflags & VNET_BUFFER_OFFLOAD_F_TCP_CKSUM)
300  {
301  hdr->csum_offset = STRUCT_OFFSET_OF (tcp_header_t, checksum);
302  }
303  else if (oflags & VNET_BUFFER_OFFLOAD_F_UDP_CKSUM)
304  {
305  hdr->csum_offset = STRUCT_OFFSET_OF (udp_header_t, checksum);
306  }
307 
308  /*
309  * virtio devices do not support IP4 checksum offload. So driver takes care
310  * of it while doing tx.
311  */
312  ip4 =
314  if (oflags & VNET_BUFFER_OFFLOAD_F_IP_CKSUM)
315  ip4->checksum = ip4_header_checksum (ip4);
316  }
317  else if (b->flags & VNET_BUFFER_F_IS_IP6)
318  {
319  generic_header_offset_t gho = { 0 };
320  vnet_generic_header_offset_parser (b, &gho, is_l2, 0 /* ip4 */ ,
321  1 /* ip6 */ );
322  hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
323  hdr->csum_start = gho.l4_hdr_offset; // 0x36;
324  if (oflags & VNET_BUFFER_OFFLOAD_F_TCP_CKSUM)
325  {
326  hdr->csum_offset = STRUCT_OFFSET_OF (tcp_header_t, checksum);
327  }
328  else if (oflags & VNET_BUFFER_OFFLOAD_F_UDP_CKSUM)
329  {
330  hdr->csum_offset = STRUCT_OFFSET_OF (udp_header_t, checksum);
331  }
332  }
333 }
334 
335 static void
336 set_gso_offsets (vlib_buffer_t *b, virtio_net_hdr_v1_t *hdr, const int is_l2)
337 {
338  vnet_buffer_oflags_t oflags = vnet_buffer (b)->oflags;
339 
340  if (b->flags & VNET_BUFFER_F_IS_IP4)
341  {
342  ip4_header_t *ip4;
343  generic_header_offset_t gho = { 0 };
344  vnet_generic_header_offset_parser (b, &gho, is_l2, 1 /* ip4 */ ,
345  0 /* ip6 */ );
346  hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
347  hdr->gso_size = vnet_buffer2 (b)->gso_size;
348  hdr->hdr_len = gho.hdr_sz;
349  hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
350  hdr->csum_start = gho.l4_hdr_offset; // 0x22;
351  hdr->csum_offset = STRUCT_OFFSET_OF (tcp_header_t, checksum);
352  ip4 =
354  /*
355  * virtio devices do not support IP4 checksum offload. So driver takes care
356  * of it while doing tx.
357  */
358  if (oflags & VNET_BUFFER_OFFLOAD_F_IP_CKSUM)
359  ip4->checksum = ip4_header_checksum (ip4);
360  }
361  else if (b->flags & VNET_BUFFER_F_IS_IP6)
362  {
363  generic_header_offset_t gho = { 0 };
364  vnet_generic_header_offset_parser (b, &gho, is_l2, 0 /* ip4 */ ,
365  1 /* ip6 */ );
366  hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
367  hdr->gso_size = vnet_buffer2 (b)->gso_size;
368  hdr->hdr_len = gho.hdr_sz;
369  hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
370  hdr->csum_start = gho.l4_hdr_offset; // 0x36;
371  hdr->csum_offset = STRUCT_OFFSET_OF (tcp_header_t, checksum);
372  }
373 }
374 
375 static u16
377  virtio_if_t *vif, virtio_vring_t *vring, u32 bi,
378  u16 free_desc_count, u16 avail, u16 next, u16 mask,
379  int hdr_sz, int do_gso, int csum_offload, int is_pci,
380  int is_tun, int is_indirect, int is_any_layout)
381 {
382  u16 n_added = 0;
383  vring_desc_t *d;
384  int is_l2 = !is_tun;
385  d = &vring->desc[next];
387  virtio_net_hdr_v1_t *hdr = vlib_buffer_get_current (b) - hdr_sz;
388  u32 drop_inline = ~0;
389 
390  clib_memset_u8 (hdr, 0, hdr_sz);
391 
392  if (b->flags & VNET_BUFFER_F_GSO)
393  {
394  if (do_gso)
395  set_gso_offsets (b, hdr, is_l2);
396  else
397  {
398  drop_inline = VIRTIO_TX_ERROR_GSO_PACKET_DROP;
399  goto done;
400  }
401  }
402  else if (b->flags & VNET_BUFFER_F_OFFLOAD)
403  {
404  if (csum_offload)
405  set_checksum_offsets (b, hdr, is_l2);
406  else
407  {
408  drop_inline = VIRTIO_TX_ERROR_CSUM_OFFLOAD_PACKET_DROP;
409  goto done;
410  }
411  }
412 
413  if (PREDICT_FALSE (b->flags & VLIB_BUFFER_IS_TRACED))
414  {
415  virtio_tx_trace (vm, node, b, bi, is_tun);
416  }
417 
418  if (PREDICT_TRUE ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0))
419  {
420  d->addr = ((is_pci) ? vlib_buffer_get_current_pa (vm, b) :
422  d->len = b->current_length + hdr_sz;
423  d->flags = 0;
424  }
425  else if (is_indirect)
426  {
427  /*
428  * We are using single vlib_buffer_t for indirect descriptor(s)
429  * chain. Single descriptor is 16 bytes and vlib_buffer_t
430  * has 2048 bytes space. So maximum long chain can have 128
431  * (=2048/16) indirect descriptors.
432  * It can easily support 65535 bytes of Jumbo frames with
433  * each data buffer size of 512 bytes minimum.
434  */
435  u32 indirect_buffer = 0;
436  if (PREDICT_FALSE (vlib_buffer_alloc (vm, &indirect_buffer, 1) == 0))
437  {
438  drop_inline = VIRTIO_TX_ERROR_INDIRECT_DESC_ALLOC_FAILED;
439  goto done;
440  }
441 
442  vlib_buffer_t *indirect_desc = vlib_get_buffer (vm, indirect_buffer);
443  indirect_desc->current_data = 0;
444  indirect_desc->flags |= VLIB_BUFFER_NEXT_PRESENT;
445  indirect_desc->next_buffer = bi;
446  bi = indirect_buffer;
447 
448  vring_desc_t *id =
449  (vring_desc_t *) vlib_buffer_get_current (indirect_desc);
450  u32 count = 1;
451  if (is_pci)
452  {
453  d->addr = vlib_physmem_get_pa (vm, id);
454  id->addr = vlib_buffer_get_current_pa (vm, b) - hdr_sz;
455 
456  /*
457  * If VIRTIO_F_ANY_LAYOUT is not negotiated, then virtio_net_hdr
458  * should be presented in separate descriptor and data will start
459  * from next descriptor.
460  */
461  if (is_any_layout)
462  id->len = b->current_length + hdr_sz;
463  else
464  {
465  id->len = hdr_sz;
466  id->flags = VRING_DESC_F_NEXT;
467  id->next = count;
468  count++;
469  id++;
470  id->addr = vlib_buffer_get_current_pa (vm, b);
471  id->len = b->current_length;
472  }
473  while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
474  {
475  id->flags = VRING_DESC_F_NEXT;
476  id->next = count;
477  count++;
478  id++;
480  id->addr = vlib_buffer_get_current_pa (vm, b);
481  id->len = b->current_length;
483  {
484  if (b->flags & VLIB_BUFFER_NEXT_PRESENT)
485  vlib_error_count (vm, node->node_index,
486  VIRTIO_TX_ERROR_TRUNC_PACKET, 1);
487  break;
488  }
489  }
490  }
491  else /* VIRTIO_IF_TYPE_[TAP | TUN] */
492  {
493  d->addr = pointer_to_uword (id);
494  /* first buffer in chain */
495  id->addr = pointer_to_uword (vlib_buffer_get_current (b)) - hdr_sz;
496  id->len = b->current_length + hdr_sz;
497 
498  while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
499  {
500  id->flags = VRING_DESC_F_NEXT;
501  id->next = count;
502  count++;
503  id++;
506  id->len = b->current_length;
508  {
509  if (b->flags & VLIB_BUFFER_NEXT_PRESENT)
510  vlib_error_count (vm, node->node_index,
511  VIRTIO_TX_ERROR_TRUNC_PACKET, 1);
512  break;
513  }
514  }
515  }
516  id->flags = 0;
517  id->next = 0;
518  d->len = count * sizeof (vring_desc_t);
520  }
521  else if (is_pci)
522  {
523  u16 count = next;
524  vlib_buffer_t *b_temp = b;
525  u16 n_buffers_in_chain = 1;
526 
527  /*
528  * Check the length of the chain for the required number of
529  * descriptors. Return from here, retry to get more descriptors,
530  * if chain length is greater than available descriptors.
531  */
532  while (b_temp->flags & VLIB_BUFFER_NEXT_PRESENT)
533  {
534  n_buffers_in_chain++;
535  b_temp = vlib_get_buffer (vm, b_temp->next_buffer);
536  }
537 
538  if (n_buffers_in_chain > free_desc_count)
539  return n_buffers_in_chain;
540 
541  d->addr = vlib_buffer_get_current_pa (vm, b) - hdr_sz;
542  d->len = b->current_length + hdr_sz;
543 
544  while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
545  {
547  vring->buffers[count] = bi;
548  b->flags &=
549  ~(VLIB_BUFFER_NEXT_PRESENT | VLIB_BUFFER_TOTAL_LENGTH_VALID);
550  bi = b->next_buffer;
551  b->next_buffer = 0;
552  n_added++;
553  count = (count + 1) & mask;
554  d->next = count;
555  d = &vring->desc[count];
556  b = vlib_get_buffer (vm, bi);
558  d->len = b->current_length;
559  }
560  d->flags = 0;
561  vring->buffers[count] = bi;
562  vring->avail->ring[avail & mask] = next;
563  n_added++;
564  return n_added;
565  }
566  else
567  {
568  ASSERT (0);
569  }
570  vring->buffers[next] = bi;
571  vring->avail->ring[avail & mask] = next;
572  n_added++;
573 
574 done:
575  if (drop_inline != ~0)
576  virtio_interface_drop_inline (vm, vif, node->node_index, &bi, 1,
577  drop_inline);
578 
579  return n_added;
580 }
581 
582 static u16
584  virtio_if_t *vif, virtio_vring_t *vring, u32 bi,
585  u16 next, int hdr_sz, int do_gso, int csum_offload,
586  int is_pci, int is_tun, int is_indirect,
587  int is_any_layout)
588 {
589  u16 n_added = 0, flags = 0;
590  int is_l2 = !is_tun;
591  vring_packed_desc_t *d = &vring->packed_desc[next];
593  virtio_net_hdr_v1_t *hdr = vlib_buffer_get_current (b) - hdr_sz;
594  u32 drop_inline = ~0;
595 
596  clib_memset (hdr, 0, hdr_sz);
597 
598  if (b->flags & VNET_BUFFER_F_GSO)
599  {
600  if (do_gso)
601  set_gso_offsets (b, hdr, is_l2);
602  else
603  {
604  drop_inline = VIRTIO_TX_ERROR_GSO_PACKET_DROP;
605  goto done;
606  }
607  }
608  else if (b->flags & VNET_BUFFER_F_OFFLOAD)
609  {
610  if (csum_offload)
611  set_checksum_offsets (b, hdr, is_l2);
612  else
613  {
614  drop_inline = VIRTIO_TX_ERROR_CSUM_OFFLOAD_PACKET_DROP;
615  goto done;
616  }
617  }
618  if (PREDICT_FALSE (b->flags & VLIB_BUFFER_IS_TRACED))
619  {
620  virtio_tx_trace (vm, node, b, bi, is_tun);
621  }
622 
623  if (PREDICT_TRUE ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0))
624  {
625  d->addr =
626  ((is_pci) ? vlib_buffer_get_current_pa (vm,
627  b) :
629  d->len = b->current_length + hdr_sz;
630  }
631  else if (is_indirect)
632  {
633  /*
634  * We are using single vlib_buffer_t for indirect descriptor(s)
635  * chain. Single descriptor is 16 bytes and vlib_buffer_t
636  * has 2048 bytes space. So maximum long chain can have 128
637  * (=2048/16) indirect descriptors.
638  * It can easily support 65535 bytes of Jumbo frames with
639  * each data buffer size of 512 bytes minimum.
640  */
641  u32 indirect_buffer = 0;
642  if (PREDICT_FALSE (vlib_buffer_alloc (vm, &indirect_buffer, 1) == 0))
643  {
644  drop_inline = VIRTIO_TX_ERROR_INDIRECT_DESC_ALLOC_FAILED;
645  goto done;
646  }
647 
648  vlib_buffer_t *indirect_desc = vlib_get_buffer (vm, indirect_buffer);
649  indirect_desc->current_data = 0;
650  indirect_desc->flags |= VLIB_BUFFER_NEXT_PRESENT;
651  indirect_desc->next_buffer = bi;
652  bi = indirect_buffer;
653 
654  vring_packed_desc_t *id =
655  (vring_packed_desc_t *) vlib_buffer_get_current (indirect_desc);
656  u32 count = 1;
657  if (is_pci)
658  {
659  d->addr = vlib_physmem_get_pa (vm, id);
660  id->addr = vlib_buffer_get_current_pa (vm, b) - hdr_sz;
661 
662  /*
663  * If VIRTIO_F_ANY_LAYOUT is not negotiated, then virtio_net_hdr
664  * should be presented in separate descriptor and data will start
665  * from next descriptor.
666  */
667  if (is_any_layout)
668  id->len = b->current_length + hdr_sz;
669  else
670  {
671  id->len = hdr_sz;
672  id->flags = 0;
673  id->id = 0;
674  count++;
675  id++;
676  id->addr = vlib_buffer_get_current_pa (vm, b);
677  id->len = b->current_length;
678  }
679  while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
680  {
681  id->flags = 0;
682  id->id = 0;
683  count++;
684  id++;
686  id->addr = vlib_buffer_get_current_pa (vm, b);
687  id->len = b->current_length;
689  {
690  if (b->flags & VLIB_BUFFER_NEXT_PRESENT)
691  vlib_error_count (vm, node->node_index,
692  VIRTIO_TX_ERROR_TRUNC_PACKET, 1);
693  break;
694  }
695  }
696  }
697  id->flags = 0;
698  id->id = 0;
699  d->len = count * sizeof (vring_packed_desc_t);
701  }
702  else
703  {
704  ASSERT (0);
705  }
706  if (vring->avail_wrap_counter)
707  {
710  }
711  else
712  {
715  }
716 
717  d->id = next;
718  d->flags = flags;
719  vring->buffers[next] = bi;
720  n_added++;
721 
722 done:
723  if (drop_inline != ~0)
724  virtio_interface_drop_inline (vm, vif, node->node_index, &bi, 1,
725  drop_inline);
726 
727  return n_added;
728 }
729 
730 static uword
734  virtio_vring_t *vring, u32 *buffers,
735  u16 n_left, const int do_gso,
736  const int csum_offload)
737 {
738  int is_pci = (type == VIRTIO_IF_TYPE_PCI);
739  int is_tun = (type == VIRTIO_IF_TYPE_TUN);
740  int is_indirect =
741  ((vif->features & VIRTIO_FEATURE (VIRTIO_RING_F_INDIRECT_DESC)) != 0);
742  int is_any_layout =
743  ((vif->features & VIRTIO_FEATURE (VIRTIO_F_ANY_LAYOUT)) != 0);
744  const int hdr_sz = vif->virtio_net_hdr_sz;
745  u16 sz = vring->size;
746  u16 used, next, n_buffers = 0, n_buffers_left = 0;
747  u16 n_vectors = n_left;
748 
749 
750  used = vring->desc_in_use;
751  next = vring->desc_next;
752 
753  if (vif->packet_buffering)
754  {
755  n_buffers = n_buffers_left = virtio_vring_n_buffers (vring->buffering);
756 
757  while (n_buffers_left && used < sz)
758  {
759  u16 n_added = 0;
760 
762  if (bi == ~0)
763  break;
764  n_added = add_buffer_to_slot_packed (
765  vm, node, vif, vring, bi, next, hdr_sz, do_gso, csum_offload,
766  is_pci, is_tun, is_indirect, is_any_layout);
767  n_buffers_left--;
768  if (PREDICT_FALSE (n_added == 0))
769  continue;
770 
771  used++;
772  next++;
773  if (next >= sz)
774  {
775  next = 0;
776  vring->avail_wrap_counter ^= 1;
777  }
778  }
779  }
780 
781  while (n_left && used < sz)
782  {
783  u16 n_added = 0;
784 
785  n_added = add_buffer_to_slot_packed (
786  vm, node, vif, vring, buffers[0], next, hdr_sz, do_gso, csum_offload,
787  is_pci, is_tun, is_indirect, is_any_layout);
788  buffers++;
789  n_left--;
790  if (PREDICT_FALSE (n_added == 0))
791  continue;
792 
793  used++;
794  next++;
795  if (next >= sz)
796  {
797  next = 0;
798  vring->avail_wrap_counter ^= 1;
799  }
800  }
801 
802  if (n_left != n_vectors || n_buffers != n_buffers_left)
803  {
805  vring->desc_next = next;
806  vring->desc_in_use = used;
808  if (vring->device_event->flags != VRING_EVENT_F_DISABLE)
809  virtio_kick (vm, vring, vif);
810  }
811 
812  return n_left;
813 }
814 
815 static void
817  u16 next, u32 *first_free_desc_index,
818  u16 *free_desc_count)
819 {
820  u16 start = 0;
821  /* next is used as hint: from where to start looking */
822  for (u16 i = 0; i < size; i++, next++)
823  {
824  if (vring->buffers[next & mask] == ~0)
825  {
826  if (*first_free_desc_index == ~0)
827  {
828  *first_free_desc_index = (next & mask);
829  start = i;
830  (*free_desc_count)++;
831  req--;
832  if (req == 0)
833  break;
834  }
835  else
836  {
837  if (start + *free_desc_count == i)
838  {
839  (*free_desc_count)++;
840  req--;
841  if (req == 0)
842  break;
843  }
844  else
845  break;
846  }
847  }
848  }
849 }
850 
851 static u16
855  virtio_vring_t *vring, u32 *buffers,
856  u16 n_left, int do_gso, int csum_offload)
857 {
858  u16 used, next, avail, n_buffers = 0, n_buffers_left = 0;
859  int is_pci = (type == VIRTIO_IF_TYPE_PCI);
860  int is_tun = (type == VIRTIO_IF_TYPE_TUN);
861  int is_indirect =
862  ((vif->features & VIRTIO_FEATURE (VIRTIO_RING_F_INDIRECT_DESC)) != 0);
863  int is_any_layout =
864  ((vif->features & VIRTIO_FEATURE (VIRTIO_F_ANY_LAYOUT)) != 0);
865  u16 sz = vring->size;
866  int hdr_sz = vif->virtio_net_hdr_sz;
867  u16 mask = sz - 1;
868  u16 n_vectors = n_left;
869 
870  used = vring->desc_in_use;
871  next = vring->desc_next;
872  avail = vring->avail->idx;
873 
874  u16 free_desc_count = 0;
875 
877  {
878  u32 first_free_desc_index = ~0;
879 
880  virtio_find_free_desc (vring, sz, mask, n_left, next,
881  &first_free_desc_index, &free_desc_count);
882 
883  if (free_desc_count)
884  next = first_free_desc_index;
885  }
886  else
887  free_desc_count = sz - used;
888 
889  if (vif->packet_buffering)
890  {
891  n_buffers = n_buffers_left = virtio_vring_n_buffers (vring->buffering);
892 
893  while (n_buffers_left && free_desc_count)
894  {
895  u16 n_added = 0;
896 
898  if (bi == ~0)
899  break;
900 
901  n_added = add_buffer_to_slot (vm, node, vif, vring, bi,
902  free_desc_count, avail, next, mask,
903  hdr_sz, do_gso, csum_offload, is_pci,
904  is_tun, is_indirect, is_any_layout);
905  if (PREDICT_FALSE (n_added == 0))
906  {
907  n_buffers_left--;
908  continue;
909  }
910  else if (PREDICT_FALSE (n_added > free_desc_count))
911  break;
912 
913  avail++;
914  next = (next + n_added) & mask;
915  used += n_added;
916  n_buffers_left--;
917  free_desc_count -= n_added;
918  }
919  }
920 
921  while (n_left && free_desc_count)
922  {
923  u16 n_added = 0;
924 
925  n_added =
926  add_buffer_to_slot (vm, node, vif, vring, buffers[0], free_desc_count,
927  avail, next, mask, hdr_sz, do_gso, csum_offload,
928  is_pci, is_tun, is_indirect, is_any_layout);
929 
930  if (PREDICT_FALSE (n_added == 0))
931  {
932  buffers++;
933  n_left--;
934  continue;
935  }
936  else if (PREDICT_FALSE (n_added > free_desc_count))
937  break;
938 
939  avail++;
940  next = (next + n_added) & mask;
941  used += n_added;
942  buffers++;
943  n_left--;
944  free_desc_count -= n_added;
945  }
946 
947  if (n_left != n_vectors || n_buffers != n_buffers_left)
948  {
949  clib_atomic_store_seq_cst (&vring->avail->idx, avail);
950  vring->desc_next = next;
951  vring->desc_in_use = used;
952  if ((clib_atomic_load_seq_cst (&vring->used->flags) &
954  virtio_kick (vm, vring, vif);
955  }
956 
957  return n_left;
958 }
959 
960 static u16
963  virtio_vring_t *vring, u32 *buffers,
964  u16 n_left, int packed, int do_gso,
965  int csum_offload)
966 {
967  if (packed)
968  return virtio_interface_tx_packed_gso_inline (vm, node, vif, type, vring,
969  buffers, n_left,
970  do_gso, csum_offload);
971  else
972  return virtio_interface_tx_split_gso_inline (vm, node, vif, type, vring,
973  buffers, n_left,
974  do_gso, csum_offload);
975 }
976 
977 static u16
979  virtio_if_t *vif, virtio_vring_t *vring,
980  virtio_if_type_t type, u32 *buffers, u16 n_left,
981  int packed)
982 {
983  vnet_main_t *vnm = vnet_get_main ();
985 
987  return virtio_interface_tx_gso_inline (vm, node, vif, type, vring,
988  buffers, n_left, packed,
989  1 /* do_gso */ ,
990  1 /* checksum offload */ );
992  return virtio_interface_tx_gso_inline (vm, node, vif, type, vring,
993  buffers, n_left, packed,
994  0 /* no do_gso */ ,
995  1 /* checksum offload */ );
996  else
997  return virtio_interface_tx_gso_inline (vm, node, vif, type, vring,
998  buffers, n_left, packed,
999  0 /* no do_gso */ ,
1000  0 /* no checksum offload */ );
1001 }
1002 
1005  vlib_frame_t * frame)
1006 {
1008  vnet_interface_output_runtime_t *rund = (void *) node->runtime_data;
1010  u16 qid = vm->thread_index % vif->num_txqs;
1011  virtio_vring_t *vring = vec_elt_at_index (vif->txq_vrings, qid);
1012  u16 n_left = frame->n_vectors;
1013  u32 *buffers = vlib_frame_vector_args (frame);
1015  int packed = vif->is_packed;
1016  u16 n_vectors = frame->n_vectors;
1017 
1019 
1020  if (vif->packet_coalesce)
1021  {
1022  n_vectors = n_left =
1023  vnet_gro_inline (vm, vring->flow_table, buffers, n_left, to);
1024  buffers = to;
1025  }
1026 
1027  u16 retry_count = 2;
1028 
1029 retry:
1030  /* free consumed buffers */
1031  virtio_free_used_device_desc (vm, vring, node->node_index, packed);
1032 
1033  if (vif->type == VIRTIO_IF_TYPE_TAP)
1034  n_left = virtio_interface_tx_inline (vm, node, vif, vring,
1035  VIRTIO_IF_TYPE_TAP,
1036  &buffers[n_vectors - n_left],
1037  n_left, packed);
1038  else if (vif->type == VIRTIO_IF_TYPE_PCI)
1039  n_left = virtio_interface_tx_inline (vm, node, vif, vring,
1040  VIRTIO_IF_TYPE_PCI,
1041  &buffers[n_vectors - n_left],
1042  n_left, packed);
1043  else if (vif->type == VIRTIO_IF_TYPE_TUN)
1044  n_left = virtio_interface_tx_inline (vm, node, vif, vring,
1045  VIRTIO_IF_TYPE_TUN,
1046  &buffers[n_vectors - n_left],
1047  n_left, packed);
1048  else
1049  ASSERT (0);
1050 
1051  if (n_left && retry_count--)
1052  goto retry;
1053 
1054  if (vif->packet_buffering && n_left)
1055  {
1056  u16 n_buffered = virtio_vring_buffering_store_packets (vring->buffering,
1057  &buffers
1058  [n_vectors
1059  - n_left],
1060  n_left);
1061  n_left -= n_buffered;
1062  }
1063  if (n_left)
1064  virtio_interface_drop_inline (vm, vif, node->node_index,
1065  &buffers[n_vectors - n_left], n_left,
1066  VIRTIO_TX_ERROR_NO_FREE_SLOTS);
1067 
1069 
1070  return frame->n_vectors - n_left;
1071 }
1072 
1073 static void
1075  u32 node_index)
1076 {
1077  virtio_main_t *apm = &virtio_main;
1078  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
1080 
1081  /* Shut off redirection */
1082  if (node_index == ~0)
1083  {
1085  return;
1086  }
1087 
1090  node_index);
1091 }
1092 
1093 static void
1095 {
1096  /* Nothing for now */
1097 }
1098 
1099 static void
1101 {
1102  if (vif->is_packed)
1103  vring->driver_event->flags &= ~VRING_EVENT_F_DISABLE;
1104  else
1106 }
1107 
1108 static void
1110 {
1111  if (vif->is_packed)
1112  vring->driver_event->flags |= VRING_EVENT_F_DISABLE;
1113  else
1115 }
1116 
1117 static clib_error_t *
1120 {
1121  vlib_main_t *vm = vnm->vlib_main;
1122  virtio_main_t *mm = &virtio_main;
1123  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
1125  virtio_vring_t *rx_vring = vec_elt_at_index (vif->rxq_vrings, qid);
1126 
1127  if (vif->type == VIRTIO_IF_TYPE_PCI && !(vif->support_int_mode))
1128  {
1129  virtio_set_rx_polling (vif, rx_vring);
1130  return clib_error_return (0, "interrupt mode is not supported");
1131  }
1132 
1134  {
1135  if (vif->packet_coalesce || vif->packet_buffering)
1136  {
1137  if (mm->interrupt_queues_count > 0)
1138  mm->interrupt_queues_count--;
1139  if (mm->interrupt_queues_count == 0)
1143  }
1144  virtio_set_rx_polling (vif, rx_vring);
1145  }
1146  else
1147  {
1148  if (vif->packet_coalesce || vif->packet_buffering)
1149  {
1150  mm->interrupt_queues_count++;
1151  if (mm->interrupt_queues_count == 1)
1155  }
1156  virtio_set_rx_interrupt (vif, rx_vring);
1157  }
1158 
1159  rx_vring->mode = mode;
1160 
1161  return 0;
1162 }
1163 
1164 static clib_error_t *
1166 {
1167  virtio_main_t *mm = &virtio_main;
1168  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
1170 
1172  {
1173  vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP;
1176  }
1177  else
1178  {
1179  vif->flags &= ~VIRTIO_IF_FLAG_ADMIN_UP;
1181  }
1182  return 0;
1183 }
1184 
1185 static clib_error_t *
1187  u32 hw_if_index,
1188  struct vnet_sw_interface_t *st, int is_add)
1189 {
1190  /* Nothing for now */
1191  return 0;
1192 }
1193 
1194 /* *INDENT-OFF* */
1196  .name = "virtio",
1197  .format_device_name = format_virtio_device_name,
1198  .format_device = format_virtio_device,
1199  .format_tx_trace = format_virtio_tx_trace,
1200  .tx_function_n_errors = VIRTIO_TX_N_ERROR,
1201  .tx_function_error_strings = virtio_tx_func_error_strings,
1202  .rx_redirect_to_node = virtio_set_interface_next_node,
1203  .clear_counters = virtio_clear_hw_interface_counters,
1204  .admin_up_down_function = virtio_interface_admin_up_down,
1205  .subif_add_del_function = virtio_subif_add_del_function,
1206  .rx_mode_change_function = virtio_interface_rx_mode_change,
1207 };
1208 
1209 /* *INDENT-ON* */
1210 
1211 /*
1212  * fd.io coding-style-patch-verification: ON
1213  *
1214  * Local Variables:
1215  * eval: (c-set-style "gnu")
1216  * End:
1217  */
virtio_free_used_device_desc_packed
static void virtio_free_used_device_desc_packed(vlib_main_t *vm, virtio_vring_t *vring, uword node_index)
Definition: device.c:234
vlib.h
to
u32 * to
Definition: interface_output.c:1096
vlib_buffer_t::next_buffer
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:149
vring_used_elem_t
Definition: virtio_std.h:109
vnet_gro_inline
static_always_inline u32 vnet_gro_inline(vlib_main_t *vm, gro_flow_table_t *flow_table, u32 *from, u16 n_left_from, u32 *to)
coalesce buffers with flow tables
Definition: gro_func.h:588
vlib_buffer_free
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:979
format_virtio_tx_trace
static u8 * format_virtio_tx_trace(u8 *s, va_list *va)
Definition: device.c:84
virtio_vring_t::flow_table
gro_flow_table_t * flow_table
Definition: virtio.h:110
virtio_interface_admin_up_down
static clib_error_t * virtio_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: device.c:1165
vnet_sw_interface_t
Definition: interface.h:869
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
vlib_buffer_get_current_pa
static uword vlib_buffer_get_current_pa(vlib_main_t *vm, vlib_buffer_t *b)
Definition: buffer_funcs.h:494
virtio_tx_func_error_strings
static char * virtio_tx_func_error_strings[]
Definition: device.c:53
format_generic_header_offset
static_always_inline u8 * format_generic_header_offset(u8 *s, va_list *args)
Definition: hdr_offset_parser.h:81
VNET_HW_INTERFACE_CAP_SUPPORTS_L4_TX_CKSUM
#define VNET_HW_INTERFACE_CAP_SUPPORTS_L4_TX_CKSUM
Definition: interface.h:555
vnet_hw_interface_t::caps
vnet_hw_interface_capabilities_t caps
Definition: interface.h:645
n_buffers
u32 n_buffers
Definition: interface_output.c:421
vlib_node_add_next
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1177
tcp_packet.h
ip4
vl_api_ip4_address_t ip4
Definition: one.api:376
virtio_vring_t
Definition: virtio.h:63
vring_used_t::flags
u16 flags
Definition: virtio_std.h:117
virtio.h
clib_spinlock_lock_if_init
static_always_inline void clib_spinlock_lock_if_init(clib_spinlock_t *p)
Definition: lock.h:106
virtio_interface_tx_gso_inline
static u16 virtio_interface_tx_gso_inline(vlib_main_t *vm, vlib_node_runtime_t *node, virtio_if_t *vif, virtio_if_type_t type, virtio_vring_t *vring, u32 *buffers, u16 n_left, int packed, int do_gso, int csum_offload)
Definition: device.c:961
vlib_get_buffer
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
pointer_to_uword
static uword pointer_to_uword(const void *p)
Definition: types.h:131
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:549
vring_avail_t::ring
u16 ring[0]
Definition: virtio_std.h:105
virtio_if_t::flags
u32 flags
Definition: virtio.h:132
virtio_tx_trace_t::gho
generic_header_offset_t gho
Definition: device.c:79
virtio_kick
static_always_inline void virtio_kick(vlib_main_t *vm, virtio_vring_t *vring, virtio_if_t *vif)
Definition: virtio.h:252
foreach_virtio_tx_func_error
#define foreach_virtio_tx_func_error
Definition: device.c:36
generic_header_offset_t::l4_hdr_offset
i16 l4_hdr_offset
Definition: hdr_offset_parser.h:74
tcp_header_t
struct _tcp_header tcp_header_t
nat44_ei_main_s::interfaces
nat44_ei_interface_t * interfaces
Definition: nat44_ei.h:340
next
u16 * next
Definition: nat44_ei_out2in.c:718
virtio_tx_trace
static void virtio_tx_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b0, u32 bi, int is_tun)
Definition: device.c:104
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
virtio_free_used_device_desc
static void virtio_free_used_device_desc(vlib_main_t *vm, virtio_vring_t *vring, uword node_index, int packed)
Definition: device.c:275
vnet_buffer_oflags_t
vnet_buffer_oflags_t
Definition: buffer.h:119
add_buffer_to_slot_packed
static u16 add_buffer_to_slot_packed(vlib_main_t *vm, vlib_node_runtime_t *node, virtio_if_t *vif, virtio_vring_t *vring, u32 bi, u16 next, int hdr_sz, int do_gso, int csum_offload, int is_pci, int is_tun, int is_indirect, int is_any_layout)
Definition: device.c:583
clib_error_return
#define clib_error_return(e, args...)
Definition: error.h:99
VNET_DEVICE_CLASS
VNET_DEVICE_CLASS(af_xdp_device_class)
virtio_vring_n_buffers
static_always_inline u16 virtio_vring_n_buffers(virtio_vring_buffering_t *buffering)
Definition: virtio_buffering.h:149
virtio_if_t::per_interface_next_index
u32 per_interface_next_index
Definition: virtio.h:133
u16
unsigned short u16
Definition: types.h:57
vring_desc_t::addr
u64 addr
Definition: virtio_std.h:95
mode
vl_api_tunnel_mode_t mode
Definition: gre.api:48
virtio_set_rx_interrupt
static void virtio_set_rx_interrupt(virtio_if_t *vif, virtio_vring_t *vring)
Definition: device.c:1100
VNET_SW_INTERFACE_FLAG_ADMIN_UP
@ VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:844
VNET_HW_IF_RX_MODE_POLLING
@ VNET_HW_IF_RX_MODE_POLLING
Definition: interface.h:56
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
VRING_DESC_F_USED
#define VRING_DESC_F_USED
Definition: virtio_std.h:76
node_index
node node_index
Definition: interface_output.c:440
VNET_HW_INTERFACE_FLAG_LINK_UP
@ VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:509
VIRTIO_FEATURE
#define VIRTIO_FEATURE(X)
Definition: virtio_std.h:67
vnet_interface_main_t::sw_if_counters
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:1023
virtio_set_rx_polling
static void virtio_set_rx_polling(virtio_if_t *vif, virtio_vring_t *vring)
Definition: device.c:1109
virtio_if_t::packet_coalesce
int packet_coalesce
Definition: virtio.h:156
virtio_main_t::interrupt_queues_count
u32 interrupt_queues_count
Definition: virtio.h:216
virtio_tx_func_error_t
virtio_tx_func_error_t
Definition: device.c:45
vnet_buffer2
#define vnet_buffer2(b)
Definition: buffer.h:505
vring_used_elem_t::id
u32 id
Definition: virtio_std.h:111
vnet_hw_interface_t::dev_instance
u32 dev_instance
Definition: interface.h:660
vlib_error_count
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:57
vlib_frame_t
Definition: node.h:372
vlib_process_signal_event
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:1019
clib_memcpy_fast
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
virtio_vring_t::size
u16 size
Definition: virtio.h:83
udp_header_t
Definition: udp_packet.h:45
ip4_header_t
Definition: ip4_packet.h:87
ethernet.h
virtio_vring_t::avail
vring_avail_t * avail
Definition: virtio.h:73
VNET_DEVICE_CLASS_TX_FN
#define VNET_DEVICE_CLASS_TX_FN(devclass)
Definition: interface.h:317
error
Definition: cJSON.c:88
virtio_find_free_desc
static void 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:816
virtio_interface_tx_split_gso_inline
static u16 virtio_interface_tx_split_gso_inline(vlib_main_t *vm, vlib_node_runtime_t *node, virtio_if_t *vif, virtio_if_type_t type, virtio_vring_t *vring, u32 *buffers, u16 n_left, int do_gso, int csum_offload)
Definition: device.c:852
virtio_send_interrupt_node
vlib_node_registration_t virtio_send_interrupt_node
(constructor) VLIB_REGISTER_NODE (virtio_send_interrupt_node)
Definition: virtio_process.c:74
ip6_packet.h
virtio_interface_tx_packed_gso_inline
static uword virtio_interface_tx_packed_gso_inline(vlib_main_t *vm, vlib_node_runtime_t *node, virtio_if_t *vif, virtio_if_type_t type, virtio_vring_t *vring, u32 *buffers, u16 n_left, const int do_gso, const int csum_offload)
Definition: device.c:731
virtio_if_t::packet_buffering
int packet_buffering
Definition: virtio.h:157
virtio_main
virtio_main_t virtio_main
Definition: virtio.c:37
STRUCT_OFFSET_OF
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:73
vlib_buffer_t::current_data
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:119
virtio_interface_drop_inline
static void virtio_interface_drop_inline(vlib_main_t *vm, virtio_if_t *vif, uword node_index, u32 *buffers, u16 n, virtio_tx_func_error_t error)
Definition: device.c:140
virtio_device_class
VNET_DEVICE_CLASS_TX_FN() virtio_device_class(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: device.c:1003
vlib_buffer_free_from_ring
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:1026
vlib_increment_simple_counter
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 increment)
Increment a simple counter.
Definition: counter.h:74
VIRTIO_NET_HDR_GSO_TCPV4
#define VIRTIO_NET_HDR_GSO_TCPV4
Definition: virtio_std.h:144
clib_memset_u32
static_always_inline void clib_memset_u32(void *p, u32 val, uword count)
Definition: string.h:349
count
u8 count
Definition: dhcp.api:208
vlib_physmem_get_pa
static u64 vlib_physmem_get_pa(vlib_main_t *vm, void *mem)
Definition: physmem_funcs.h:103
virtio_subif_add_del_function
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:1186
CLIB_MEMORY_STORE_BARRIER
#define CLIB_MEMORY_STORE_BARRIER()
Definition: clib.h:140
virtio_vring_t::desc_next
u16 desc_next
Definition: virtio.h:87
virtio_vring_t::used
vring_used_t * used
Definition: virtio.h:72
slot
u8 slot
Definition: pci_types.api:22
vnet_interface_output_runtime_t::dev_instance
u32 dev_instance
Definition: interface_funcs.h:479
vring_desc_t::flags
u16 flags
Definition: virtio_std.h:97
virtio_vring_t::lockp
clib_spinlock_t lockp
Definition: virtio.h:66
vring_desc_t
Definition: virtio_std.h:93
vlib_buffer_alloc
static __clib_warn_unused_result u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:702
vring_avail_t::flags
u16 flags
Definition: virtio_std.h:103
virtio_free_used_device_desc_split
static void virtio_free_used_device_desc_split(vlib_main_t *vm, virtio_vring_t *vring, uword node_index)
Definition: device.c:168
VRING_DESC_F_AVAIL
#define VRING_DESC_F_AVAIL
Definition: virtio_std.h:75
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:441
virtio_vring_t::desc
vring_desc_t * desc
Definition: virtio.h:71
vec_elt_at_index
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Definition: vec_bootstrap.h:203
vnet_get_hw_interface
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface_funcs.h:44
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
virtio_if_type_t
virtio_if_type_t
Definition: virtio.h:50
VIRTIO_EVENT_STOP_TIMER
#define VIRTIO_EVENT_STOP_TIMER
Definition: virtio.h:61
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO
@ VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO
Definition: interface.h:537
virtio_if_t::features
u64 features
Definition: virtio.h:131
vlib_frame_vector_args
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
virtio_memset_ring_u32
static void virtio_memset_ring_u32(u32 *ring, u32 start, u32 ring_size, u32 n_buffers)
Definition: device.c:152
vnet_hw_if_rx_mode
vnet_hw_if_rx_mode
Definition: interface.h:53
virtio_vring_buffering_read_from_front
static_always_inline u32 virtio_vring_buffering_read_from_front(virtio_vring_buffering_t *buffering)
Definition: virtio_buffering.h:178
VRING_DESC_F_INDIRECT
#define VRING_DESC_F_INDIRECT
Definition: virtio_std.h:73
udp_packet.h
uword
u64 uword
Definition: types.h:112
last
static heap_elt_t * last(heap_header_t *h)
Definition: heap.c:53
vlib_main_t::thread_index
u32 thread_index
Definition: main.h:215
virtio_if_t::hw_if_index
u32 hw_if_index
Definition: virtio.h:152
VRING_DESC_F_NEXT
#define VRING_DESC_F_NEXT
Definition: virtio_std.h:71
GRO_TO_VECTOR_SIZE
#define GRO_TO_VECTOR_SIZE(X)
Definition: gro.h:27
virtio_vring_t::mode
vnet_hw_if_rx_mode mode
Definition: virtio.h:108
mask
vl_api_pnat_mask_t mask
Definition: pnat.api:45
vring_desc_t::len
u32 len
Definition: virtio_std.h:96
clib_atomic_load_seq_cst
#define clib_atomic_load_seq_cst(a)
Definition: atomics.h:55
vnet_main_t::vlib_main
vlib_main_t * vlib_main
Definition: vnet.h:111
format_vnet_buffer_no_chain
format_function_t format_vnet_buffer_no_chain
Definition: buffer.h:520
VRING_AVAIL_F_NO_INTERRUPT
#define VRING_AVAIL_F_NO_INTERRUPT
Definition: virtio_std.h:91
CLIB_MEMORY_BARRIER
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:137
VRING_USED_F_NO_NOTIFY
#define VRING_USED_F_NO_NOTIFY
Definition: virtio_std.h:90
virtio_if_t::sw_if_index
u32 sw_if_index
Definition: virtio.h:153
clib_memset_u8
static_always_inline void clib_memset_u8(void *p, u8 val, uword count)
Definition: string.h:441
vlib_buffer_t::current_length
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:122
set_checksum_offsets
static void set_checksum_offsets(vlib_buffer_t *b, virtio_net_hdr_v1_t *hdr, const int is_l2)
Definition: device.c:286
generic_header_offset_t::l3_hdr_offset
i16 l3_hdr_offset
Definition: hdr_offset_parser.h:73
virtio_vring_t::driver_event
vring_desc_event_t * driver_event
Definition: virtio.h:78
virtio_vring_t::last_used_idx
u16 last_used_idx
Definition: virtio.h:88
ip4_packet.h
add_buffer_to_slot
static u16 add_buffer_to_slot(vlib_main_t *vm, vlib_node_runtime_t *node, virtio_if_t *vif, virtio_vring_t *vring, u32 bi, u16 free_desc_count, u16 avail, u16 next, u16 mask, int hdr_sz, int do_gso, int csum_offload, int is_pci, int is_tun, int is_indirect, int is_any_layout)
Definition: device.c:376
virtio_main_t
Definition: virtio.h:214
is_ip6
bool is_ip6
Definition: ip.api:43
virtio_vring_t::avail_wrap_counter
u16 avail_wrap_counter
Definition: virtio.h:100
vnet_hw_interface_t
Definition: interface.h:638
vnet_main_t
Definition: vnet.h:76
VRING_TX_OUT_OF_ORDER
#define VRING_TX_OUT_OF_ORDER
Definition: virtio.h:105
size
u32 size
Definition: vhost_user.h:125
virtio_set_interface_next_node
static void virtio_set_interface_next_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: device.c:1074
format_virtio_device
static u8 * format_virtio_device(u8 *s, va_list *args)
Definition: device.c:60
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
format_get_indent
static u32 format_get_indent(u8 *s)
Definition: format.h:72
u32
unsigned int u32
Definition: types.h:88
virtio_if_t::virtio_net_hdr_sz
u16 virtio_net_hdr_sz
Definition: virtio.h:149
virtio_input_node
vlib_node_registration_t virtio_input_node
(constructor) VLIB_REGISTER_NODE (virtio_input_node)
Definition: node.c:498
format_ethernet_header_with_length
u8 * format_ethernet_header_with_length(u8 *s, va_list *args)
Definition: format.c:97
VIRTIO_NET_HDR_GSO_TCPV6
#define VIRTIO_NET_HDR_GSO_TCPV6
Definition: virtio_std.h:146
virtio_if_t::support_int_mode
u8 support_int_mode
Definition: virtio.h:206
virtio_vring_t::packed_desc
vring_packed_desc_t * packed_desc
Definition: virtio.h:77
generic_header_offset_t
Definition: hdr_offset_parser.h:65
VIRTIO_EVENT_START_TIMER
#define VIRTIO_EVENT_START_TIMER
Definition: virtio.h:60
n_left
u32 n_left
Definition: interface_output.c:1096
clib_atomic_store_seq_cst
#define clib_atomic_store_seq_cst(a, b)
Definition: atomics.h:53
instance
u32 instance
Definition: gre.api:51
n_vectors
return frame n_vectors
Definition: nat44_ei_hairpinning.c:488
virtio_if_t::type
virtio_if_type_t type
Definition: virtio.h:150
vring_used_t::idx
u16 idx
Definition: virtio_std.h:118
virtio_if_t
Definition: virtio.h:128
VIRTIO_NET_HDR_F_NEEDS_CSUM
#define VIRTIO_NET_HDR_F_NEEDS_CSUM
Definition: virtio_std.h:140
nm
nat44_ei_main_t * nm
Definition: nat44_ei_hairpinning.c:413
virtio_tx_trace_t
Definition: device.c:75
VIRTIO_TX_MAX_CHAIN_LEN
#define VIRTIO_TX_MAX_CHAIN_LEN
Definition: device.c:34
virtio_if_t::rxq_vrings
virtio_vring_t * rxq_vrings
Definition: virtio.h:136
virtio_interface_tx_inline
static u16 virtio_interface_tx_inline(vlib_main_t *vm, vlib_node_runtime_t *node, virtio_if_t *vif, virtio_vring_t *vring, virtio_if_type_t type, u32 *buffers, u16 n_left, int packed)
Definition: device.c:978
virtio_main_t::interfaces
virtio_if_t * interfaces
Definition: virtio.h:220
virtio_tx_trace_t::buffer
vlib_buffer_t buffer
Definition: device.c:80
format_virtio_device_name
format_function_t format_virtio_device_name
Definition: virtio.h:248
vnet_main
vnet_main_t vnet_main
Definition: misc.c:43
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vlib_main_t
Definition: main.h:102
vlib_node_t
Definition: node.h:247
virtio_vring_t::buffers
u32 * buffers
Definition: virtio.h:82
vlib_add_trace
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
vlib_get_main
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
vnet_hw_interface_set_flags
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:513
vnet_generic_header_offset_parser
static_always_inline void vnet_generic_header_offset_parser(vlib_buffer_t *b0, generic_header_offset_t *gho, int is_l2, int is_ip4, int is_ip6)
Definition: hdr_offset_parser.h:471
unix.h
vlib_buffer_get_current
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
ip4_header_checksum
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:314
vring_used_t::ring
vring_used_elem_t ring[0]
Definition: virtio_std.h:119
virtio_vring_t::buffering
virtio_vring_buffering_t * buffering
Definition: virtio.h:109
virtio_vring_t::desc_in_use
u16 desc_in_use
Definition: virtio.h:86
virtio_vring_t::flags
u16 flags
Definition: virtio.h:106
i
int i
Definition: flowhash_template.h:376
generic_header_offset_t::hdr_sz
u16 hdr_sz
Definition: hdr_offset_parser.h:76
vring_desc_t::next
u16 next
Definition: virtio_std.h:98
set_gso_offsets
static void set_gso_offsets(vlib_buffer_t *b, virtio_net_hdr_v1_t *hdr, const int is_l2)
Definition: device.c:336
virtio_vring_t::device_event
vring_desc_event_t * device_event
Definition: virtio.h:79
virtio_clear_hw_interface_counters
static void virtio_clear_hw_interface_counters(u32 instance)
Definition: device.c:1094
vlib_buffer_t::pre_data
u8 pre_data[VLIB_BUFFER_PRE_DATA_SIZE]
Space for inserting data before buffer start.
Definition: buffer.h:201
vnet.h
vlib_node_runtime_t
Definition: node.h:454
clib_spinlock_unlock_if_init
static_always_inline void clib_spinlock_unlock_if_init(clib_spinlock_t *p)
Definition: lock.h:129
virtio_vring_buffering_store_packets
static_always_inline u16 virtio_vring_buffering_store_packets(virtio_vring_buffering_t *buffering, u32 *bi, u16 n_store)
Definition: virtio_buffering.h:155
PREDICT_TRUE
#define PREDICT_TRUE(x)
Definition: clib.h:125
virtio_if_t::is_packed
int is_packed
Definition: virtio.h:211
VIRTIO_TX_N_ERROR
@ VIRTIO_TX_N_ERROR
Definition: device.c:50
VLIB_TX
@ VLIB_TX
Definition: defs.h:47
hdr_offset_parser.h
virtio_vring_t::used_wrap_counter
u16 used_wrap_counter
Definition: virtio.h:101
virtio_interface_rx_mode_change
static clib_error_t * virtio_interface_rx_mode_change(vnet_main_t *vnm, u32 hw_if_index, u32 qid, vnet_hw_if_rx_mode mode)
Definition: device.c:1118
vring_avail_t::idx
u16 idx
Definition: virtio_std.h:104
virtio_tx_trace_t::buffer_index
u32 buffer_index
Definition: device.c:77
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
VNET_INTERFACE_COUNTER_DROP
@ VNET_INTERFACE_COUNTER_DROP
Definition: interface.h:904
virtio_tx_trace_t::sw_if_index
u32 sw_if_index
Definition: device.c:78
vnet_main_t::interface_main
vnet_interface_main_t interface_main
Definition: vnet.h:81
format_white_space
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
vlib_buffer_t::flags
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,...
Definition: buffer.h:133
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
vnet_interface_output_runtime_t
Definition: interface_funcs.h:475
flags
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
gro_func.h