FD.io VPP  v20.01-48-g3e0dafb74
Vector Packet Processing
interface_output.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  * interface_output.c: interface output node
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #include <vnet/vnet.h>
41 #include <vnet/gso/gso.h>
42 #include <vnet/ip/icmp46_packet.h>
43 #include <vnet/ip/ip4.h>
44 #include <vnet/ip/ip6.h>
45 #include <vnet/udp/udp_packet.h>
46 #include <vnet/feature/feature.h>
48 
49 typedef struct
50 {
53  u8 data[128 - 2 * sizeof (u32)];
54 }
56 
57 #ifndef CLIB_MARCH_VARIANT
58 u8 *
60 {
61  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
62  vlib_node_t *node = va_arg (*va, vlib_node_t *);
63  interface_output_trace_t *t = va_arg (*va, interface_output_trace_t *);
64  vnet_main_t *vnm = vnet_get_main ();
66  u32 indent;
67 
68  if (t->sw_if_index != (u32) ~ 0)
69  {
70  indent = format_get_indent (s);
71 
74  {
75  /* the interface may have been deleted by the time the trace is printed */
76  s = format (s, "sw_if_index: %d ", t->sw_if_index);
77  }
78  else
79  {
80  si = vnet_get_sw_interface (vnm, t->sw_if_index);
81  s =
82  format (s, "%U ", format_vnet_sw_interface_name, vnm, si,
83  t->flags);
84  }
85  s =
86  format (s, "\n%U%U", format_white_space, indent,
88  t->data, sizeof (t->data));
89  }
90  return s;
91 }
92 
93 static void
95  vlib_node_runtime_t * node,
96  vlib_frame_t * frame, uword n_buffers)
97 {
98  u32 n_left, *from;
99 
100  n_left = n_buffers;
101  from = vlib_frame_vector_args (frame);
102 
103  while (n_left >= 4)
104  {
105  u32 bi0, bi1;
106  vlib_buffer_t *b0, *b1;
107  interface_output_trace_t *t0, *t1;
108 
109  /* Prefetch next iteration. */
110  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
111  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
112 
113  bi0 = from[0];
114  bi1 = from[1];
115 
116  b0 = vlib_get_buffer (vm, bi0);
117  b1 = vlib_get_buffer (vm, bi1);
118 
119  if (b0->flags & VLIB_BUFFER_IS_TRACED)
120  {
121  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
122  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
123  t0->flags = b0->flags;
125  sizeof (t0->data));
126  }
127  if (b1->flags & VLIB_BUFFER_IS_TRACED)
128  {
129  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
130  t1->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_TX];
131  t1->flags = b1->flags;
133  sizeof (t1->data));
134  }
135  from += 2;
136  n_left -= 2;
137  }
138 
139  while (n_left >= 1)
140  {
141  u32 bi0;
142  vlib_buffer_t *b0;
143  interface_output_trace_t *t0;
144 
145  bi0 = from[0];
146 
147  b0 = vlib_get_buffer (vm, bi0);
148 
149  if (b0->flags & VLIB_BUFFER_IS_TRACED)
150  {
151  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
152  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
153  t0->flags = b0->flags;
155  sizeof (t0->data));
156  }
157  from += 1;
158  n_left -= 1;
159  }
160 }
161 
164 {
165  tcp_header_t *th;
166  udp_header_t *uh;
167  gso_header_offset_t gho = { 0 };
168 
169  int is_ip4 = (b->flags & VNET_BUFFER_F_IS_IP4) != 0;
170  int is_ip6 = (b->flags & VNET_BUFFER_F_IS_IP6) != 0;
171 
172  ASSERT (!(is_ip4 && is_ip6));
173 
174  gho = vnet_gso_header_offset_parser (b, is_ip6);
177 
178  if (is_ip4)
179  {
180  ip4_header_t *ip4;
181 
182  ip4 =
184  if (b->flags & VNET_BUFFER_F_OFFLOAD_IP_CKSUM)
185  ip4->checksum = ip4_header_checksum (ip4);
186  if (b->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM)
187  {
188  th->checksum = 0;
189  th->checksum = ip4_tcp_udp_compute_checksum (vm, b, ip4);
190  }
191  else if (b->flags & VNET_BUFFER_F_OFFLOAD_UDP_CKSUM)
192  uh->checksum = ip4_tcp_udp_compute_checksum (vm, b, ip4);
193  }
194  else if (is_ip6)
195  {
196  int bogus;
197  ip6_header_t *ip6;
198 
199  ip6 =
201  if (b->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM)
202  {
203  th->checksum = 0;
204  th->checksum =
205  ip6_tcp_udp_icmp_compute_checksum (vm, b, ip6, &bogus);
206  }
207  else if (b->flags & VNET_BUFFER_F_OFFLOAD_UDP_CKSUM)
208  {
209  uh->checksum = 0;
210  uh->checksum =
211  ip6_tcp_udp_icmp_compute_checksum (vm, b, ip6, &bogus);
212  }
213  }
214  b->flags &= ~VNET_BUFFER_F_OFFLOAD_TCP_CKSUM;
215  b->flags &= ~VNET_BUFFER_F_OFFLOAD_UDP_CKSUM;
216  b->flags &= ~VNET_BUFFER_F_OFFLOAD_IP_CKSUM;
217 }
218 
221  vlib_node_runtime_t * node,
222  vlib_frame_t * frame,
223  vnet_main_t * vnm,
225  int do_tx_offloads)
226 {
227  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
229  u32 n_left_to_tx, *from, *from_end, *to_tx;
230  u32 n_bytes, n_buffers, n_packets;
231  u32 n_bytes_b0, n_bytes_b1, n_bytes_b2, n_bytes_b3;
232  u32 thread_index = vm->thread_index;
234  u32 next_index = VNET_INTERFACE_OUTPUT_NEXT_TX;
235  u32 current_config_index = ~0;
236  u8 arc = im->output_feature_arc_index;
237  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
238 
239  n_buffers = frame->n_vectors;
240 
241  if (node->flags & VLIB_NODE_FLAG_TRACE)
242  vnet_interface_output_trace (vm, node, frame, n_buffers);
243 
244  from = vlib_frame_vector_args (frame);
245  vlib_get_buffers (vm, from, b, n_buffers);
246 
247  if (rt->is_deleted)
248  return vlib_error_drop_buffers (vm, node, from,
249  /* buffer stride */ 1,
250  n_buffers,
252  node->node_index,
254 
255  si = vnet_get_sw_interface (vnm, rt->sw_if_index);
256  hi = vnet_get_sup_hw_interface (vnm, rt->sw_if_index);
257  if (!(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ||
259  {
261 
264  vlib_increment_simple_counter (cm, thread_index,
265  rt->sw_if_index, n_buffers);
266 
267  return vlib_error_drop_buffers (vm, node, from,
268  /* buffer stride */ 1,
269  n_buffers,
271  node->node_index,
273  }
274 
275  from_end = from + n_buffers;
276 
277  /* Total byte count of all buffers. */
278  n_bytes = 0;
279  n_packets = 0;
280 
281  /* interface-output feature arc handling */
283  {
285  fcm = vnet_feature_get_config_main (arc);
286  current_config_index = vnet_get_feature_config_index (arc,
287  rt->sw_if_index);
288  vnet_get_config_data (&fcm->config_main, &current_config_index,
289  &next_index, 0);
290  }
291 
292  while (from < from_end)
293  {
294  /* Get new next frame since previous incomplete frame may have less
295  than VNET_FRAME_SIZE vectors in it. */
296  vlib_get_new_next_frame (vm, node, next_index, to_tx, n_left_to_tx);
297 
298  while (from + 8 <= from_end && n_left_to_tx >= 4)
299  {
300  u32 bi0, bi1, bi2, bi3;
301  u32 tx_swif0, tx_swif1, tx_swif2, tx_swif3;
302  u32 or_flags;
303 
304  /* Prefetch next iteration. */
305  vlib_prefetch_buffer_header (b[4], LOAD);
306  vlib_prefetch_buffer_header (b[5], LOAD);
307  vlib_prefetch_buffer_header (b[6], LOAD);
308  vlib_prefetch_buffer_header (b[7], LOAD);
309 
310  bi0 = from[0];
311  bi1 = from[1];
312  bi2 = from[2];
313  bi3 = from[3];
314  to_tx[0] = bi0;
315  to_tx[1] = bi1;
316  to_tx[2] = bi2;
317  to_tx[3] = bi3;
318 
319  or_flags = b[0]->flags | b[1]->flags | b[2]->flags | b[3]->flags;
320 
321  from += 4;
322  to_tx += 4;
323  n_left_to_tx -= 4;
324 
325  /* Be grumpy about zero length buffers for benefit of
326  driver tx function. */
327  ASSERT (b[0]->current_length > 0);
328  ASSERT (b[1]->current_length > 0);
329  ASSERT (b[2]->current_length > 0);
330  ASSERT (b[3]->current_length > 0);
331 
332  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b[0]);
333  n_bytes_b1 = vlib_buffer_length_in_chain (vm, b[1]);
334  n_bytes_b2 = vlib_buffer_length_in_chain (vm, b[2]);
335  n_bytes_b3 = vlib_buffer_length_in_chain (vm, b[3]);
336  tx_swif0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
337  tx_swif1 = vnet_buffer (b[1])->sw_if_index[VLIB_TX];
338  tx_swif2 = vnet_buffer (b[2])->sw_if_index[VLIB_TX];
339  tx_swif3 = vnet_buffer (b[3])->sw_if_index[VLIB_TX];
340 
341  n_bytes += n_bytes_b0 + n_bytes_b1;
342  n_bytes += n_bytes_b2 + n_bytes_b3;
343  n_packets += 4;
344 
345  if (PREDICT_FALSE (current_config_index != ~0))
346  {
347  vnet_buffer (b[0])->feature_arc_index = arc;
348  vnet_buffer (b[1])->feature_arc_index = arc;
349  vnet_buffer (b[2])->feature_arc_index = arc;
350  vnet_buffer (b[3])->feature_arc_index = arc;
351  b[0]->current_config_index = current_config_index;
352  b[1]->current_config_index = current_config_index;
353  b[2]->current_config_index = current_config_index;
354  b[3]->current_config_index = current_config_index;
355  }
356 
357  /* update vlan subif tx counts, if required */
358  if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
359  {
360  vlib_increment_combined_counter (im->combined_sw_if_counters +
362  thread_index, tx_swif0, 1,
363  n_bytes_b0);
364  }
365 
366  if (PREDICT_FALSE (tx_swif1 != rt->sw_if_index))
367  {
368 
369  vlib_increment_combined_counter (im->combined_sw_if_counters +
371  thread_index, tx_swif1, 1,
372  n_bytes_b1);
373  }
374 
375  if (PREDICT_FALSE (tx_swif2 != rt->sw_if_index))
376  {
377 
378  vlib_increment_combined_counter (im->combined_sw_if_counters +
380  thread_index, tx_swif2, 1,
381  n_bytes_b2);
382  }
383  if (PREDICT_FALSE (tx_swif3 != rt->sw_if_index))
384  {
385 
386  vlib_increment_combined_counter (im->combined_sw_if_counters +
388  thread_index, tx_swif3, 1,
389  n_bytes_b3);
390  }
391 
392  if (do_tx_offloads)
393  {
394  if (or_flags &
395  (VNET_BUFFER_F_OFFLOAD_TCP_CKSUM |
396  VNET_BUFFER_F_OFFLOAD_UDP_CKSUM |
397  VNET_BUFFER_F_OFFLOAD_IP_CKSUM))
398  {
399  calc_checksums (vm, b[0]);
400  calc_checksums (vm, b[1]);
401  calc_checksums (vm, b[2]);
402  calc_checksums (vm, b[3]);
403  }
404  }
405  b += 4;
406 
407  }
408 
409  while (from + 1 <= from_end && n_left_to_tx >= 1)
410  {
411  u32 bi0;
412  u32 tx_swif0;
413 
414  bi0 = from[0];
415  to_tx[0] = bi0;
416  from += 1;
417  to_tx += 1;
418  n_left_to_tx -= 1;
419 
420  /* Be grumpy about zero length buffers for benefit of
421  driver tx function. */
422  ASSERT (b[0]->current_length > 0);
423 
424  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b[0]);
425  tx_swif0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
426  n_bytes += n_bytes_b0;
427  n_packets += 1;
428 
429  if (PREDICT_FALSE (current_config_index != ~0))
430  {
431  vnet_buffer (b[0])->feature_arc_index = arc;
432  b[0]->current_config_index = current_config_index;
433  }
434 
435  if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
436  {
437 
438  vlib_increment_combined_counter (im->combined_sw_if_counters +
440  thread_index, tx_swif0, 1,
441  n_bytes_b0);
442  }
443 
444  if (do_tx_offloads)
445  {
446  if (b[0]->flags &
447  (VNET_BUFFER_F_OFFLOAD_TCP_CKSUM |
448  VNET_BUFFER_F_OFFLOAD_UDP_CKSUM |
449  VNET_BUFFER_F_OFFLOAD_IP_CKSUM))
450  calc_checksums (vm, b[0]);
451  }
452  b += 1;
453  }
454 
455  vlib_put_next_frame (vm, node, next_index, n_left_to_tx);
456  }
457 
458  /* Update main interface stats. */
459  vlib_increment_combined_counter (im->combined_sw_if_counters
461  thread_index,
462  rt->sw_if_index, n_packets, n_bytes);
463  return n_buffers;
464 }
465 #endif /* CLIB_MARCH_VARIANT */
466 
469  int sw_if_index_from_buffer)
470 {
471  u32 n_left_from, *from;
474 
475  if (PREDICT_TRUE (pp->pcap_tx_enable == 0))
476  return;
477 
478  if (sw_if_index_from_buffer == 0)
479  {
480  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
481  sw_if_index = rt->sw_if_index;
482  }
483  else
484  sw_if_index = ~0;
485 
486  n_left_from = frame->n_vectors;
487  from = vlib_frame_vector_args (frame);
488 
489  while (n_left_from > 0)
490  {
491  int classify_filter_result;
492  u32 bi0 = from[0];
493  vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0);
494  from++;
495  n_left_from--;
496 
497  if (pp->filter_classify_table_index != ~0)
498  {
499  classify_filter_result =
501  (b0, pp->filter_classify_table_index, 0 /* full classify */ );
502  if (classify_filter_result)
503  pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
504  continue;
505  }
506 
507  if (sw_if_index_from_buffer)
508  sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
509 
510  if (pp->pcap_sw_if_index == 0 || pp->pcap_sw_if_index == sw_if_index)
511  {
512  vnet_main_t *vnm = vnet_get_main ();
514  vnet_get_sup_hw_interface (vnm, sw_if_index);
515  /* Capture pkt if not filtered, or if filter hits */
516  if (hi->trace_classify_table_index == ~0 ||
518  (b0, hi->trace_classify_table_index, 0 /* full classify */ ))
519  pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
520  }
521  }
522 }
523 
524 #ifndef CLIB_MARCH_VARIANT
525 
526 uword
528  vlib_frame_t * frame)
529 {
530  vnet_main_t *vnm = vnet_get_main ();
532  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
533  hi = vnet_get_sup_hw_interface (vnm, rt->sw_if_index);
534 
535  vnet_interface_pcap_tx_trace (vm, node, frame,
536  0 /* sw_if_index_from_buffer */ );
537 
539  return vnet_interface_output_node_inline (vm, node, frame, vnm, hi,
540  /* do_tx_offloads */ 0);
541  else
542  return vnet_interface_output_node_inline (vm, node, frame, vnm, hi,
543  /* do_tx_offloads */ 1);
544 }
545 #endif /* CLIB_MARCH_VARIANT */
546 
547 /* Use buffer's sw_if_index[VNET_TX] to choose output interface. */
548 VLIB_NODE_FN (vnet_per_buffer_interface_output_node) (vlib_main_t * vm,
550  node,
552 {
553  vnet_main_t *vnm = vnet_get_main ();
554  u32 n_left_to_next, *from, *to_next;
555  u32 n_left_from, next_index;
556 
557  vnet_interface_pcap_tx_trace (vm, node, frame,
558  1 /* sw_if_index_from_buffer */ );
559 
560  n_left_from = frame->n_vectors;
561 
562  from = vlib_frame_vector_args (frame);
563  next_index = node->cached_next_index;
564 
565  while (n_left_from > 0)
566  {
567  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
568 
569  while (n_left_from >= 4 && n_left_to_next >= 2)
570  {
571  u32 bi0, bi1, next0, next1;
572  vlib_buffer_t *b0, *b1;
573  vnet_hw_interface_t *hi0, *hi1;
574 
575  /* Prefetch next iteration. */
576  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
577  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
578 
579  bi0 = from[0];
580  bi1 = from[1];
581  to_next[0] = bi0;
582  to_next[1] = bi1;
583  from += 2;
584  to_next += 2;
585  n_left_to_next -= 2;
586  n_left_from -= 2;
587 
588  b0 = vlib_get_buffer (vm, bi0);
589  b1 = vlib_get_buffer (vm, bi1);
590 
591  hi0 =
594  [VLIB_TX]);
595  hi1 =
598  [VLIB_TX]);
599 
600  next0 = hi0->output_node_next_index;
601  next1 = hi1->output_node_next_index;
602 
603  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
604  n_left_to_next, bi0, bi1, next0,
605  next1);
606  }
607 
608  while (n_left_from > 0 && n_left_to_next > 0)
609  {
610  u32 bi0, next0;
611  vlib_buffer_t *b0;
612  vnet_hw_interface_t *hi0;
613 
614  bi0 = from[0];
615  to_next[0] = bi0;
616  from += 1;
617  to_next += 1;
618  n_left_to_next -= 1;
619  n_left_from -= 1;
620 
621  b0 = vlib_get_buffer (vm, bi0);
622 
623  hi0 =
626  [VLIB_TX]);
627 
628  next0 = hi0->output_node_next_index;
629 
630  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
631  n_left_to_next, bi0, next0);
632  }
633 
634  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
635  }
636 
637  return frame->n_vectors;
638 }
639 
640 typedef struct vnet_error_trace_t_
641 {
644 
645 
646 static u8 *
647 format_vnet_error_trace (u8 * s, va_list * va)
648 {
649  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
650  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
651  vnet_error_trace_t *t = va_arg (*va, vnet_error_trace_t *);
652 
653  s = format (s, "rx:%U", format_vnet_sw_if_index_name,
654  vnet_get_main (), t->sw_if_index);
655 
656  return s;
657 }
658 
659 static void
661  vlib_node_runtime_t * node, vlib_frame_t * frame)
662 {
663  u32 n_left, *buffers;
664 
665  buffers = vlib_frame_vector_args (frame);
666  n_left = frame->n_vectors;
667 
668  while (n_left >= 4)
669  {
670  u32 bi0, bi1;
671  vlib_buffer_t *b0, *b1;
672  vnet_error_trace_t *t0, *t1;
673 
674  /* Prefetch next iteration. */
675  vlib_prefetch_buffer_with_index (vm, buffers[2], LOAD);
676  vlib_prefetch_buffer_with_index (vm, buffers[3], LOAD);
677 
678  bi0 = buffers[0];
679  bi1 = buffers[1];
680 
681  b0 = vlib_get_buffer (vm, bi0);
682  b1 = vlib_get_buffer (vm, bi1);
683 
684  if (b0->flags & VLIB_BUFFER_IS_TRACED)
685  {
686  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
687  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
688  }
689  if (b1->flags & VLIB_BUFFER_IS_TRACED)
690  {
691  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
692  t1->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX];
693  }
694  buffers += 2;
695  n_left -= 2;
696  }
697 
698  while (n_left >= 1)
699  {
700  u32 bi0;
701  vlib_buffer_t *b0;
702  vnet_error_trace_t *t0;
703 
704  bi0 = buffers[0];
705 
706  b0 = vlib_get_buffer (vm, bi0);
707 
708  if (b0->flags & VLIB_BUFFER_IS_TRACED)
709  {
710  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
711  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
712  }
713  buffers += 1;
714  n_left -= 1;
715  }
716 }
717 
718 typedef enum
719 {
724 
727  vlib_node_runtime_t * node,
728  vlib_frame_t * frame,
729  vnet_error_disposition_t disposition)
730 {
731  u32 *from, n_left, thread_index, *sw_if_index;
732  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
733  u32 sw_if_indices[VLIB_FRAME_SIZE];
735  u16 nexts[VLIB_FRAME_SIZE];
736  vnet_main_t *vnm;
737 
738  vnm = vnet_get_main ();
739  thread_index = vm->thread_index;
740  from = vlib_frame_vector_args (frame);
741  n_left = frame->n_vectors;
742  b = bufs;
743  sw_if_index = sw_if_indices;
744 
745  vlib_get_buffers (vm, from, bufs, n_left);
746 
747  if (node->flags & VLIB_NODE_FLAG_TRACE)
748  interface_trace_buffers (vm, node, frame);
749 
750  /* All going to drop regardless, this is just a counting exercise */
751  clib_memset (nexts, 0, sizeof (nexts));
752 
754  (disposition == VNET_ERROR_DISPOSITION_PUNT
757 
758  /* collect the array of interfaces first ... */
759  while (n_left >= 4)
760  {
761  if (n_left >= 12)
762  {
763  /* Prefetch 8 ahead - there's not much going on in each iteration */
764  vlib_prefetch_buffer_header (b[4], LOAD);
765  vlib_prefetch_buffer_header (b[5], LOAD);
766  vlib_prefetch_buffer_header (b[6], LOAD);
767  vlib_prefetch_buffer_header (b[7], LOAD);
768  }
769  sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
770  sw_if_index[1] = vnet_buffer (b[1])->sw_if_index[VLIB_RX];
771  sw_if_index[2] = vnet_buffer (b[2])->sw_if_index[VLIB_RX];
772  sw_if_index[3] = vnet_buffer (b[3])->sw_if_index[VLIB_RX];
773 
774  sw_if_index += 4;
775  n_left -= 4;
776  b += 4;
777  }
778  while (n_left)
779  {
780  sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
781 
782  sw_if_index += 1;
783  n_left -= 1;
784  b += 1;
785  }
786 
787  /* ... then count against them in blocks */
788  n_left = frame->n_vectors;
789 
790  while (n_left)
791  {
792  vnet_sw_interface_t *sw_if0;
793  u16 off, count;
794 
795  off = frame->n_vectors - n_left;
796 
797  sw_if_index = sw_if_indices + off;
798 
799  count = clib_count_equal_u32 (sw_if_index, n_left);
800  n_left -= count;
801 
802  vlib_increment_simple_counter (cm, thread_index, sw_if_index[0], count);
803 
804  /* Increment super-interface drop/punt counters for
805  sub-interfaces. */
806  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index[0]);
807  if (sw_if0->sup_sw_if_index != sw_if_index[0])
809  (cm, thread_index, sw_if0->sup_sw_if_index, count);
810  }
811 
812  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
813 
814  return frame->n_vectors;
815 }
816 
817 static inline void
820  vnet_pcap_t * pp, vlib_frame_t * f)
821 {
822  u32 *from;
823  u32 n_left = f->n_vectors;
824  vlib_buffer_t *b0, *p1;
825  u32 bi0;
826  i16 save_current_data;
827  u16 save_current_length;
828  vlib_error_main_t *em = &vm->error_main;
829  int do_trace = 0;
830 
831 
832  from = vlib_frame_vector_args (f);
833 
834  while (n_left > 0)
835  {
836  if (PREDICT_TRUE (n_left > 1))
837  {
838  p1 = vlib_get_buffer (vm, from[1]);
839  vlib_prefetch_buffer_header (p1, LOAD);
840  }
841 
842  bi0 = from[0];
843  b0 = vlib_get_buffer (vm, bi0);
844  from++;
845  n_left--;
846 
847  /* See if we're pointedly ignoring this specific error */
848  if (im->pcap_drop_filter_hash
849  && hash_get (im->pcap_drop_filter_hash, b0->error))
850  continue;
851 
852  do_trace = (pp->pcap_sw_if_index == 0) ||
853  pp->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_RX];
854 
855  if (PREDICT_FALSE
856  (do_trace == 0 && pp->filter_classify_table_index != ~0))
857  {
859  (b0, pp->filter_classify_table_index, 0 /* full classify */ );
860  }
861 
862  /* Trace all drops, or drops received on a specific interface */
863  if (do_trace)
864  {
865  save_current_data = b0->current_data;
866  save_current_length = b0->current_length;
867 
868  /*
869  * Typically, we'll need to rewind the buffer
870  * if l2_hdr_offset is valid, make sure to rewind to the start of
871  * the L2 header. This may not be the buffer start in case we pop-ed
872  * vlan tags.
873  * Otherwise, rewind to buffer start and hope for the best.
874  */
875  if (b0->flags & VNET_BUFFER_F_L2_HDR_OFFSET_VALID)
876  {
877  if (b0->current_data > vnet_buffer (b0)->l2_hdr_offset)
879  vnet_buffer (b0)->l2_hdr_offset -
880  b0->current_data);
881  }
882  else if (b0->current_data > 0)
883  vlib_buffer_advance (b0, (word) - b0->current_data);
884 
885  {
886  vlib_buffer_t *last = b0;
887  u32 error_node_index;
888  int drop_string_len;
889  vlib_node_t *n;
890  /* Length of the error string */
891  int error_string_len =
892  clib_strnlen (em->error_strings_heap[b0->error], 128);
893 
894  /* Dig up the drop node */
895  error_node_index = vm->node_main.node_by_error[b0->error];
896  n = vlib_get_node (vm, error_node_index);
897 
898  /* Length of full drop string, w/ "nodename: " prepended */
899  drop_string_len = error_string_len + vec_len (n->name) + 2;
900 
901  /* Find the last buffer in the chain */
902  while (last->flags & VLIB_BUFFER_NEXT_PRESENT)
903  last = vlib_get_buffer (vm, last->next_buffer);
904 
905  /*
906  * Append <nodename>: <error-string> to the capture,
907  * only if we can do that without allocating a new buffer.
908  */
909  if (PREDICT_TRUE ((last->current_data + last->current_length)
911  - drop_string_len)))
912  {
913  clib_memcpy_fast (last->data + last->current_data +
914  last->current_length, n->name,
915  vec_len (n->name));
916  clib_memcpy_fast (last->data + last->current_data +
917  last->current_length + vec_len (n->name),
918  ": ", 2);
919  clib_memcpy_fast (last->data + last->current_data +
920  last->current_length + vec_len (n->name) +
921  2, em->error_strings_heap[b0->error],
922  error_string_len);
923  last->current_length += drop_string_len;
924  b0->flags &= ~(VLIB_BUFFER_TOTAL_LENGTH_VALID);
925  pcap_add_buffer (&pp->pcap_main, vm, bi0,
926  pp->max_bytes_per_pkt);
927  last->current_length -= drop_string_len;
928  b0->current_data = save_current_data;
929  b0->current_length = save_current_length;
930  continue;
931  }
932  }
933 
934  /*
935  * Didn't have space in the last buffer, here's the dropped
936  * packet as-is
937  */
938  pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
939 
940  b0->current_data = save_current_data;
941  b0->current_length = save_current_length;
942  }
943  }
944 }
945 
946 #ifndef CLIB_MARCH_VARIANT
947 void
948 vnet_pcap_drop_trace_filter_add_del (u32 error_index, int is_add)
949 {
951 
952  if (im->pcap_drop_filter_hash == 0)
953  im->pcap_drop_filter_hash = hash_create (0, sizeof (uword));
954 
955  if (is_add)
956  hash_set (im->pcap_drop_filter_hash, error_index, 1);
957  else
958  hash_unset (im->pcap_drop_filter_hash, error_index);
959 }
960 #endif /* CLIB_MARCH_VARIANT */
961 
962 VLIB_NODE_FN (interface_drop) (vlib_main_t * vm,
965 {
968 
970  pcap_drop_trace (vm, im, pp, frame);
971 
972  return interface_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_DROP);
973 }
974 
975 VLIB_NODE_FN (interface_punt) (vlib_main_t * vm,
978 {
979  return interface_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_PUNT);
980 }
981 
982 /* *INDENT-OFF* */
983 VLIB_REGISTER_NODE (interface_drop) = {
984  .name = "error-drop",
985  .vector_size = sizeof (u32),
986  .format_trace = format_vnet_error_trace,
987  .n_next_nodes = 1,
988  .next_nodes = {
989  [0] = "drop",
990  },
991 };
992 /* *INDENT-ON* */
993 
994 /* *INDENT-OFF* */
995 VLIB_REGISTER_NODE (interface_punt) = {
996  .name = "error-punt",
997  .vector_size = sizeof (u32),
998  .format_trace = format_vnet_error_trace,
999  .n_next_nodes = 1,
1000  .next_nodes = {
1001  [0] = "punt",
1002  },
1003 };
1004 /* *INDENT-ON* */
1005 
1006 /* *INDENT-OFF* */
1007 VLIB_REGISTER_NODE (vnet_per_buffer_interface_output_node) = {
1008  .name = "interface-output",
1009  .vector_size = sizeof (u32),
1010 };
1011 /* *INDENT-ON* */
1012 
1013 static uword
1015  vlib_frame_t * from_frame)
1016 {
1017  vnet_main_t *vnm = vnet_get_main ();
1018  u32 last_sw_if_index = ~0;
1019  vlib_frame_t *to_frame = 0;
1020  vnet_hw_interface_t *hw = 0;
1021  u32 *from, *to_next = 0;
1022  u32 n_left_from;
1023 
1024  from = vlib_frame_vector_args (from_frame);
1025  n_left_from = from_frame->n_vectors;
1026  while (n_left_from > 0)
1027  {
1028  u32 bi0;
1029  vlib_buffer_t *b0;
1030  u32 sw_if_index0;
1031 
1032  bi0 = from[0];
1033  from++;
1034  n_left_from--;
1035  b0 = vlib_get_buffer (vm, bi0);
1036  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
1037 
1038  if (PREDICT_FALSE ((last_sw_if_index != sw_if_index0) || to_frame == 0))
1039  {
1040  if (to_frame)
1041  {
1042  hw = vnet_get_sup_hw_interface (vnm, last_sw_if_index);
1043  vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1044  }
1045  last_sw_if_index = sw_if_index0;
1046  hw = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1047  to_frame = vlib_get_frame_to_node (vm, hw->tx_node_index);
1048  to_next = vlib_frame_vector_args (to_frame);
1049  }
1050 
1051  to_next[0] = bi0;
1052  to_next++;
1053  to_frame->n_vectors++;
1054  }
1055  vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1056  return from_frame->n_vectors;
1057 }
1058 
1059 /* *INDENT-OFF* */
1060 VLIB_REGISTER_NODE (interface_tx) = {
1061  .function = interface_tx_node_fn,
1062  .name = "interface-tx",
1063  .vector_size = sizeof (u32),
1064  .n_next_nodes = 1,
1065  .next_nodes = {
1066  [0] = "error-drop",
1067  },
1068 };
1069 
1070 VNET_FEATURE_ARC_INIT (interface_output, static) =
1071 {
1072  .arc_name = "interface-output",
1073  .start_nodes = VNET_FEATURES (0),
1074  .last_in_arc = "interface-tx",
1076 };
1077 
1078 VNET_FEATURE_INIT (span_tx, static) = {
1079  .arc_name = "interface-output",
1080  .node_name = "span-output",
1081  .runs_before = VNET_FEATURES ("interface-tx"),
1082 };
1083 
1084 VNET_FEATURE_INIT (ipsec_if_tx, static) = {
1085  .arc_name = "interface-output",
1086  .node_name = "ipsec-if-output",
1087  .runs_before = VNET_FEATURES ("interface-tx"),
1088 };
1089 
1090 VNET_FEATURE_INIT (interface_tx, static) = {
1091  .arc_name = "interface-output",
1092  .node_name = "interface-tx",
1093  .runs_before = 0,
1094 };
1095 /* *INDENT-ON* */
1096 
1097 #ifndef CLIB_MARCH_VARIANT
1098 clib_error_t *
1100  u32 hw_if_index,
1101  u32 is_create)
1102 {
1103  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1104  u32 next_index;
1105 
1106  if (hi->output_node_index == 0)
1107  return 0;
1108 
1109  next_index = vlib_node_add_next
1110  (vnm->vlib_main, vnet_per_buffer_interface_output_node.index,
1111  hi->output_node_index);
1112  hi->output_node_next_index = next_index;
1113 
1114  return 0;
1115 }
1116 
1119 
1120 void
1122  u32 hw_if_index, u32 node_index)
1123 {
1124  ASSERT (node_index);
1125  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1126  u32 next_index = vlib_node_add_next
1127  (vnm->vlib_main, vnet_per_buffer_interface_output_node.index, node_index);
1128  hi->output_node_next_index = next_index;
1129  hi->output_node_index = node_index;
1130 }
1131 #endif /* CLIB_MARCH_VARIANT */
1132 
1133 /*
1134  * fd.io coding-style-patch-verification: ON
1135  *
1136  * Local Variables:
1137  * eval: (c-set-style "gnu")
1138  * End:
1139  */
u8 * format_vnet_interface_output_trace(u8 *s, va_list *va)
vnet_config_main_t config_main
Definition: feature.h:82
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
u8 count
Definition: dhcp.api:208
pcap_main_t pcap_main
Definition: main.h:72
vlib_main_t vlib_global_main
Definition: main.c:1943
VNET_FEATURE_ARC_INIT(interface_output, static)
#define hash_set(h, key, value)
Definition: hash.h:255
#define CLIB_UNUSED(x)
Definition: clib.h:82
void vnet_set_interface_output_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Set interface output node - for interface registered without its output/tx nodes created because its ...
static_always_inline uword vnet_interface_output_node_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, vnet_main_t *vnm, vnet_hw_interface_t *hi, int do_tx_offloads)
#define hash_unset(h, key)
Definition: hash.h:261
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:220
u8 runtime_data[0]
Function dependent node-runtime data.
Definition: node.h:523
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
u32 max_bytes_per_pkt
Definition: main.h:70
vnet_interface_main_t interface_main
Definition: vnet.h:56
#define PREDICT_TRUE(x)
Definition: clib.h:112
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
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
u8 data[0]
Packet data.
Definition: buffer.h:181
static heap_elt_t * last(heap_header_t *h)
Definition: heap.c:53
clib_error_t * vnet_per_buffer_interface_output_hw_interface_add_del(vnet_main_t *vnm, u32 hw_if_index, u32 is_create)
static void vnet_interface_output_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, uword n_buffers)
static u32 format_get_indent(u8 *s)
Definition: format.h:72
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
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:78
static_always_inline int vnet_have_features(u8 arc, u32 sw_if_index)
Definition: feature.h:248
void vnet_pcap_drop_trace_filter_add_del(u32 error_index, int is_add)
#define VLIB_NODE_FN(node)
Definition: node.h:202
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:366
struct _tcp_header tcp_header_t
format_function_t format_vnet_sw_if_index_name
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
#define static_always_inline
Definition: clib.h:99
uword * pcap_drop_filter_hash
Definition: interface.h:872
i16 l3_hdr_offset
Definition: gso.h:28
i64 word
Definition: types.h:111
#define vlib_prefetch_buffer_with_index(vm, bi, type)
Prefetch buffer metadata by buffer index The first 64 bytes of buffer contains most header informatio...
Definition: buffer_funcs.h:440
vl_api_interface_index_t sw_if_index
Definition: gre.api:59
static_always_inline void calc_checksums(vlib_main_t *vm, vlib_buffer_t *b)
struct vnet_error_trace_t_ vnet_error_trace_t
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
vnet_hw_interface_flags_t flags
Definition: interface.h:523
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:203
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
u32 filter_classify_table_index
Definition: main.h:73
u8 * format_hex_bytes(u8 *s, va_list *va)
Definition: std-formats.c:84
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:185
#define vlib_get_new_next_frame(vm, node, next_index, vectors, n_vectors_left)
Definition: node_funcs.h:343
unsigned int u32
Definition: types.h:88
A collection of simple counters.
Definition: counter.h:57
#define VLIB_FRAME_SIZE
Definition: node.h:378
Use the vpp classifier to decide whether to trace packets.
bool is_ip6
Definition: ip.api:43
static uword interface_tx_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
vnet_crypto_main_t * cm
Definition: quic_crypto.c:41
#define hash_get(h, key)
Definition: hash.h:249
format_function_t format_vnet_sw_interface_name
vlib_main_t * vlib_main
Definition: vnet.h:80
u8 pcap_drop_enable
Definition: main.h:68
static u8 * format_vnet_error_trace(u8 *s, va_list *va)
vlib_error_main_t error_main
Definition: main.h:179
VNET_FEATURE_INIT(span_tx, static)
uword vnet_interface_output_node(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
uword vlib_error_drop_buffers(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u32 next_buffer_stride, u32 n_buffers, u32 next_index, u32 drop_error_node, u32 drop_error_code)
Definition: error.c:45
unsigned short u16
Definition: types.h:57
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:194
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
vnet_error_disposition_t
static void * vnet_get_config_data(vnet_config_main_t *cm, u32 *config_index, u32 *next_index, u32 n_data_bytes)
Definition: config.h:122
u32 * node_by_error
Definition: node.h:767
u8 data[128 - 2 *sizeof(u32)]
#define PREDICT_FALSE(x)
Definition: clib.h:111
vnet_main_t vnet_main
Definition: misc.c:43
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:862
format_function_t * format_buffer
Definition: node.h:358
u32 node_index
Node index.
Definition: node.h:496
u32 pcap_sw_if_index
Definition: main.h:71
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:218
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:338
static void interface_trace_buffers(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
vlib_main_t * vm
Definition: in2out_ed.c:1810
u8 * name
Definition: node.h:264
u8 is_ip4
Definition: lisp_gpe.api:232
u8 ip6[16]
Definition: one.api:477
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u32 flags
Definition: vhost_user.h:141
char ** error_strings_heap
Definition: error.h:55
u16 n_vectors
Definition: node.h:397
static_always_inline void vlib_buffer_enqueue_to_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 *nexts, uword count)
Definition: buffer_node.h:332
i16 l4_hdr_offset
Definition: gso.h:29
static void pcap_drop_trace(vlib_main_t *vm, vnet_interface_main_t *im, vnet_pcap_t *pp, vlib_frame_t *f)
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:284
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:456
static int vnet_is_packet_traced_inline(vlib_buffer_t *b, u32 classify_table_index, int func)
vnet_is_packet_traced
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1810
u32 trace_classify_table_index
Definition: interface.h:603
u16 ip6_tcp_udp_icmp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip6_header_t *ip0, int *bogus_lengthp)
Definition: ip6_forward.c:1021
#define hash_create(elts, value_bytes)
Definition: hash.h:696
#define ASSERT(truth)
u16 ip4_tcp_udp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip4_header_t *ip0)
Definition: ip4_forward.c:1302
u8 data[128]
Definition: ipsec_types.api:87
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
static_always_inline void vnet_interface_pcap_tx_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int sw_if_index_from_buffer)
#define VNET_FEATURES(...)
Definition: feature.h:442
vl_api_ip4_address_t hi
Definition: arp.api:37
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
VNET_HW_INTERFACE_ADD_DEL_FUNCTION(vnet_per_buffer_interface_output_hw_interface_add_del)
Definition: defs.h:47
#define VLIB_BUFFER_DEFAULT_DATA_SIZE
Definition: buffer.h:53
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static_always_inline u32 vnet_get_feature_config_index(u8 arc, u32 sw_if_index)
Definition: feature.h:255
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:140
vlib_node_main_t node_main
Definition: main.h:158
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:854
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
#define vnet_buffer(b)
Definition: buffer.h:408
#define clib_strnlen(s, m)
Definition: string.h:785
static_always_inline uword clib_count_equal_u32(u32 *data, uword max_count)
Definition: string.h:520
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:59
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1811
u16 flags
Copy of main node flags.
Definition: node.h:509
u8 pcap_tx_enable
Definition: main.h:66
u32 ip4
Definition: one.api:440
vnet_pcap_t pcap
Definition: main.h:173
static_always_inline uword interface_drop_punt(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, vnet_error_disposition_t disposition)
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
Definition: buffer_funcs.h:244
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:302
static_always_inline vnet_feature_config_main_t * vnet_feature_get_config_main(u16 arc)
Definition: feature.h:241
static void pcap_add_buffer(pcap_main_t *pm, struct vlib_main_t *vm, u32 buffer_index, u32 n_bytes_in_trace)
Add buffer (vlib_buffer_t) to the trace.
Definition: pcap_funcs.h:67
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
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:247
Definition: defs.h:46
static_always_inline gso_header_offset_t vnet_gso_header_offset_parser(vlib_buffer_t *b0, int is_ip6)
Definition: gso.h:48
signed short i16
Definition: types.h:46