FD.io VPP  v20.05.1-6-gf53edbc3b
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/ip/icmp46_packet.h>
42 #include <vnet/ip/ip4.h>
43 #include <vnet/ip/ip6.h>
44 #include <vnet/udp/udp_packet.h>
45 #include <vnet/feature/feature.h>
47 #include <vnet/interface_output.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  vlib_node_runtime_t * node,
165  vlib_frame_t * frame,
166  vnet_main_t * vnm,
168  int do_tx_offloads)
169 {
170  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
172  u32 n_left_to_tx, *from, *from_end, *to_tx;
173  u32 n_bytes, n_buffers, n_packets;
174  u32 n_bytes_b0, n_bytes_b1, n_bytes_b2, n_bytes_b3;
175  u32 thread_index = vm->thread_index;
177  u32 next_index = VNET_INTERFACE_OUTPUT_NEXT_TX;
178  u32 current_config_index = ~0;
179  u8 arc = im->output_feature_arc_index;
180  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
181 
182  n_buffers = frame->n_vectors;
183 
184  if (node->flags & VLIB_NODE_FLAG_TRACE)
185  vnet_interface_output_trace (vm, node, frame, n_buffers);
186 
187  from = vlib_frame_vector_args (frame);
188  vlib_get_buffers (vm, from, b, n_buffers);
189 
190  if (rt->is_deleted)
191  return vlib_error_drop_buffers (vm, node, from,
192  /* buffer stride */ 1,
193  n_buffers,
195  node->node_index,
197 
198  si = vnet_get_sw_interface (vnm, rt->sw_if_index);
199  hi = vnet_get_sup_hw_interface (vnm, rt->sw_if_index);
200  if (!(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ||
202  {
204 
207  vlib_increment_simple_counter (cm, thread_index,
208  rt->sw_if_index, n_buffers);
209 
210  return vlib_error_drop_buffers (vm, node, from,
211  /* buffer stride */ 1,
212  n_buffers,
214  node->node_index,
216  }
217 
218  from_end = from + n_buffers;
219 
220  /* Total byte count of all buffers. */
221  n_bytes = 0;
222  n_packets = 0;
223 
224  /* interface-output feature arc handling */
226  {
228  fcm = vnet_feature_get_config_main (arc);
229  current_config_index = vnet_get_feature_config_index (arc,
230  rt->sw_if_index);
231  vnet_get_config_data (&fcm->config_main, &current_config_index,
232  &next_index, 0);
233  }
234 
235  while (from < from_end)
236  {
237  /* Get new next frame since previous incomplete frame may have less
238  than VNET_FRAME_SIZE vectors in it. */
239  vlib_get_new_next_frame (vm, node, next_index, to_tx, n_left_to_tx);
240 
241  while (from + 8 <= from_end && n_left_to_tx >= 4)
242  {
243  u32 bi0, bi1, bi2, bi3;
244  u32 tx_swif0, tx_swif1, tx_swif2, tx_swif3;
245  u32 or_flags;
246 
247  /* Prefetch next iteration. */
248  vlib_prefetch_buffer_header (b[4], LOAD);
249  vlib_prefetch_buffer_header (b[5], LOAD);
250  vlib_prefetch_buffer_header (b[6], LOAD);
251  vlib_prefetch_buffer_header (b[7], LOAD);
252 
253  bi0 = from[0];
254  bi1 = from[1];
255  bi2 = from[2];
256  bi3 = from[3];
257  to_tx[0] = bi0;
258  to_tx[1] = bi1;
259  to_tx[2] = bi2;
260  to_tx[3] = bi3;
261 
262  or_flags = b[0]->flags | b[1]->flags | b[2]->flags | b[3]->flags;
263 
264  from += 4;
265  to_tx += 4;
266  n_left_to_tx -= 4;
267 
268  /* Be grumpy about zero length buffers for benefit of
269  driver tx function. */
270  ASSERT (b[0]->current_length > 0);
271  ASSERT (b[1]->current_length > 0);
272  ASSERT (b[2]->current_length > 0);
273  ASSERT (b[3]->current_length > 0);
274 
275  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b[0]);
276  n_bytes_b1 = vlib_buffer_length_in_chain (vm, b[1]);
277  n_bytes_b2 = vlib_buffer_length_in_chain (vm, b[2]);
278  n_bytes_b3 = vlib_buffer_length_in_chain (vm, b[3]);
279  tx_swif0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
280  tx_swif1 = vnet_buffer (b[1])->sw_if_index[VLIB_TX];
281  tx_swif2 = vnet_buffer (b[2])->sw_if_index[VLIB_TX];
282  tx_swif3 = vnet_buffer (b[3])->sw_if_index[VLIB_TX];
283 
284  n_bytes += n_bytes_b0 + n_bytes_b1;
285  n_bytes += n_bytes_b2 + n_bytes_b3;
286  n_packets += 4;
287 
288  if (PREDICT_FALSE (current_config_index != ~0))
289  {
290  vnet_buffer (b[0])->feature_arc_index = arc;
291  vnet_buffer (b[1])->feature_arc_index = arc;
292  vnet_buffer (b[2])->feature_arc_index = arc;
293  vnet_buffer (b[3])->feature_arc_index = arc;
294  b[0]->current_config_index = current_config_index;
295  b[1]->current_config_index = current_config_index;
296  b[2]->current_config_index = current_config_index;
297  b[3]->current_config_index = current_config_index;
298  }
299 
300  /* update vlan subif tx counts, if required */
301  if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
302  {
303  vlib_increment_combined_counter (im->combined_sw_if_counters +
305  thread_index, tx_swif0, 1,
306  n_bytes_b0);
307  }
308 
309  if (PREDICT_FALSE (tx_swif1 != rt->sw_if_index))
310  {
311 
312  vlib_increment_combined_counter (im->combined_sw_if_counters +
314  thread_index, tx_swif1, 1,
315  n_bytes_b1);
316  }
317 
318  if (PREDICT_FALSE (tx_swif2 != rt->sw_if_index))
319  {
320 
321  vlib_increment_combined_counter (im->combined_sw_if_counters +
323  thread_index, tx_swif2, 1,
324  n_bytes_b2);
325  }
326  if (PREDICT_FALSE (tx_swif3 != rt->sw_if_index))
327  {
328 
329  vlib_increment_combined_counter (im->combined_sw_if_counters +
331  thread_index, tx_swif3, 1,
332  n_bytes_b3);
333  }
334 
335  if (do_tx_offloads)
336  {
337  u32 vnet_buffer_offload_flags =
338  (VNET_BUFFER_F_OFFLOAD_TCP_CKSUM |
339  VNET_BUFFER_F_OFFLOAD_UDP_CKSUM |
340  VNET_BUFFER_F_OFFLOAD_IP_CKSUM);
341  if (or_flags & vnet_buffer_offload_flags)
342  {
343  if (b[0]->flags & vnet_buffer_offload_flags)
345  (vm, b[0],
346  b[0]->flags & VNET_BUFFER_F_IS_IP4,
347  b[0]->flags & VNET_BUFFER_F_IS_IP6, 1 /* with gso */ );
348  if (b[1]->flags & vnet_buffer_offload_flags)
350  (vm, b[1],
351  b[1]->flags & VNET_BUFFER_F_IS_IP4,
352  b[1]->flags & VNET_BUFFER_F_IS_IP6, 1 /* with gso */ );
353  if (b[2]->flags & vnet_buffer_offload_flags)
355  (vm, b[2],
356  b[2]->flags & VNET_BUFFER_F_IS_IP4,
357  b[2]->flags & VNET_BUFFER_F_IS_IP6, 1 /* with gso */ );
358  if (b[3]->flags & vnet_buffer_offload_flags)
360  (vm, b[3],
361  b[3]->flags & VNET_BUFFER_F_IS_IP4,
362  b[3]->flags & VNET_BUFFER_F_IS_IP6, 1 /* with gso */ );
363  }
364  }
365  b += 4;
366 
367  }
368 
369  while (from + 1 <= from_end && n_left_to_tx >= 1)
370  {
371  u32 bi0;
372  u32 tx_swif0;
373 
374  bi0 = from[0];
375  to_tx[0] = bi0;
376  from += 1;
377  to_tx += 1;
378  n_left_to_tx -= 1;
379 
380  /* Be grumpy about zero length buffers for benefit of
381  driver tx function. */
382  ASSERT (b[0]->current_length > 0);
383 
384  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b[0]);
385  tx_swif0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
386  n_bytes += n_bytes_b0;
387  n_packets += 1;
388 
389  if (PREDICT_FALSE (current_config_index != ~0))
390  {
391  vnet_buffer (b[0])->feature_arc_index = arc;
392  b[0]->current_config_index = current_config_index;
393  }
394 
395  if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
396  {
397 
398  vlib_increment_combined_counter (im->combined_sw_if_counters +
400  thread_index, tx_swif0, 1,
401  n_bytes_b0);
402  }
403 
404  if (do_tx_offloads)
405  {
406  if (b[0]->flags &
407  (VNET_BUFFER_F_OFFLOAD_TCP_CKSUM |
408  VNET_BUFFER_F_OFFLOAD_UDP_CKSUM |
409  VNET_BUFFER_F_OFFLOAD_IP_CKSUM))
411  (vm, b[0],
412  b[0]->flags & VNET_BUFFER_F_IS_IP4,
413  b[0]->flags & VNET_BUFFER_F_IS_IP6, 1 /* with gso */ );
414  }
415  b += 1;
416  }
417 
418  vlib_put_next_frame (vm, node, next_index, n_left_to_tx);
419  }
420 
421  /* Update main interface stats. */
422  vlib_increment_combined_counter (im->combined_sw_if_counters
424  thread_index,
425  rt->sw_if_index, n_packets, n_bytes);
426  return n_buffers;
427 }
428 #endif /* CLIB_MARCH_VARIANT */
429 
432  int sw_if_index_from_buffer)
433 {
434  u32 n_left_from, *from;
437 
438  if (PREDICT_TRUE (pp->pcap_tx_enable == 0))
439  return;
440 
441  if (sw_if_index_from_buffer == 0)
442  {
443  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
444  sw_if_index = rt->sw_if_index;
445  }
446  else
447  sw_if_index = ~0;
448 
449  n_left_from = frame->n_vectors;
450  from = vlib_frame_vector_args (frame);
451 
452  while (n_left_from > 0)
453  {
454  int classify_filter_result;
455  u32 bi0 = from[0];
456  vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0);
457  from++;
458  n_left_from--;
459 
460  if (pp->filter_classify_table_index != ~0)
461  {
462  classify_filter_result =
464  (b0, pp->filter_classify_table_index, 0 /* full classify */ );
465  if (classify_filter_result)
466  pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
467  continue;
468  }
469 
470  if (sw_if_index_from_buffer)
471  sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
472 
473  if (pp->pcap_sw_if_index == 0 || pp->pcap_sw_if_index == sw_if_index)
474  {
475  vnet_main_t *vnm = vnet_get_main ();
477  vnet_get_sup_hw_interface (vnm, sw_if_index);
478  /* Capture pkt if not filtered, or if filter hits */
479  if (hi->trace_classify_table_index == ~0 ||
481  (b0, hi->trace_classify_table_index, 0 /* full classify */ ))
482  pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
483  }
484  }
485 }
486 
487 #ifndef CLIB_MARCH_VARIANT
488 
489 uword
491  vlib_frame_t * frame)
492 {
493  vnet_main_t *vnm = vnet_get_main ();
495  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
496  hi = vnet_get_sup_hw_interface (vnm, rt->sw_if_index);
497 
498  vnet_interface_pcap_tx_trace (vm, node, frame,
499  0 /* sw_if_index_from_buffer */ );
500 
502  return vnet_interface_output_node_inline (vm, node, frame, vnm, hi,
503  /* do_tx_offloads */ 0);
504  else
505  return vnet_interface_output_node_inline (vm, node, frame, vnm, hi,
506  /* do_tx_offloads */ 1);
507 }
508 #endif /* CLIB_MARCH_VARIANT */
509 
510 /* Use buffer's sw_if_index[VNET_TX] to choose output interface. */
511 VLIB_NODE_FN (vnet_per_buffer_interface_output_node) (vlib_main_t * vm,
513  node,
515 {
516  vnet_main_t *vnm = vnet_get_main ();
517  u32 n_left_to_next, *from, *to_next;
518  u32 n_left_from, next_index;
519 
520  vnet_interface_pcap_tx_trace (vm, node, frame,
521  1 /* sw_if_index_from_buffer */ );
522 
523  n_left_from = frame->n_vectors;
524 
525  from = vlib_frame_vector_args (frame);
526  next_index = node->cached_next_index;
527 
528  while (n_left_from > 0)
529  {
530  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
531 
532  while (n_left_from >= 4 && n_left_to_next >= 2)
533  {
534  u32 bi0, bi1, next0, next1;
535  vlib_buffer_t *b0, *b1;
536  vnet_hw_interface_t *hi0, *hi1;
537 
538  /* Prefetch next iteration. */
539  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
540  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
541 
542  bi0 = from[0];
543  bi1 = from[1];
544  to_next[0] = bi0;
545  to_next[1] = bi1;
546  from += 2;
547  to_next += 2;
548  n_left_to_next -= 2;
549  n_left_from -= 2;
550 
551  b0 = vlib_get_buffer (vm, bi0);
552  b1 = vlib_get_buffer (vm, bi1);
553 
554  hi0 =
557  [VLIB_TX]);
558  hi1 =
561  [VLIB_TX]);
562 
563  next0 = hi0->output_node_next_index;
564  next1 = hi1->output_node_next_index;
565 
566  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
567  n_left_to_next, bi0, bi1, next0,
568  next1);
569  }
570 
571  while (n_left_from > 0 && n_left_to_next > 0)
572  {
573  u32 bi0, next0;
574  vlib_buffer_t *b0;
575  vnet_hw_interface_t *hi0;
576 
577  bi0 = from[0];
578  to_next[0] = bi0;
579  from += 1;
580  to_next += 1;
581  n_left_to_next -= 1;
582  n_left_from -= 1;
583 
584  b0 = vlib_get_buffer (vm, bi0);
585 
586  hi0 =
589  [VLIB_TX]);
590 
591  next0 = hi0->output_node_next_index;
592 
593  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
594  n_left_to_next, bi0, next0);
595  }
596 
597  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
598  }
599 
600  return frame->n_vectors;
601 }
602 
603 typedef struct vnet_error_trace_t_
604 {
607 
608 
609 static u8 *
610 format_vnet_error_trace (u8 * s, va_list * va)
611 {
612  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
613  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
614  vnet_error_trace_t *t = va_arg (*va, vnet_error_trace_t *);
615 
616  s = format (s, "rx:%U", format_vnet_sw_if_index_name,
617  vnet_get_main (), t->sw_if_index);
618 
619  return s;
620 }
621 
622 static void
624  vlib_node_runtime_t * node, vlib_frame_t * frame)
625 {
626  u32 n_left, *buffers;
627 
628  buffers = vlib_frame_vector_args (frame);
629  n_left = frame->n_vectors;
630 
631  while (n_left >= 4)
632  {
633  u32 bi0, bi1;
634  vlib_buffer_t *b0, *b1;
635  vnet_error_trace_t *t0, *t1;
636 
637  /* Prefetch next iteration. */
638  vlib_prefetch_buffer_with_index (vm, buffers[2], LOAD);
639  vlib_prefetch_buffer_with_index (vm, buffers[3], LOAD);
640 
641  bi0 = buffers[0];
642  bi1 = buffers[1];
643 
644  b0 = vlib_get_buffer (vm, bi0);
645  b1 = vlib_get_buffer (vm, bi1);
646 
647  if (b0->flags & VLIB_BUFFER_IS_TRACED)
648  {
649  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
650  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
651  }
652  if (b1->flags & VLIB_BUFFER_IS_TRACED)
653  {
654  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
655  t1->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX];
656  }
657  buffers += 2;
658  n_left -= 2;
659  }
660 
661  while (n_left >= 1)
662  {
663  u32 bi0;
664  vlib_buffer_t *b0;
665  vnet_error_trace_t *t0;
666 
667  bi0 = buffers[0];
668 
669  b0 = vlib_get_buffer (vm, bi0);
670 
671  if (b0->flags & VLIB_BUFFER_IS_TRACED)
672  {
673  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
674  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
675  }
676  buffers += 1;
677  n_left -= 1;
678  }
679 }
680 
681 typedef enum
682 {
687 
690  vlib_node_runtime_t * node,
691  vlib_frame_t * frame,
692  vnet_error_disposition_t disposition)
693 {
694  u32 *from, n_left, thread_index, *sw_if_index;
695  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
696  u32 sw_if_indices[VLIB_FRAME_SIZE];
698  u16 nexts[VLIB_FRAME_SIZE];
699  vnet_main_t *vnm;
700 
701  vnm = vnet_get_main ();
702  thread_index = vm->thread_index;
703  from = vlib_frame_vector_args (frame);
704  n_left = frame->n_vectors;
705  b = bufs;
706  sw_if_index = sw_if_indices;
707 
708  vlib_get_buffers (vm, from, bufs, n_left);
709 
710  if (node->flags & VLIB_NODE_FLAG_TRACE)
711  interface_trace_buffers (vm, node, frame);
712 
713  /* All going to drop regardless, this is just a counting exercise */
714  clib_memset (nexts, 0, sizeof (nexts));
715 
717  (disposition == VNET_ERROR_DISPOSITION_PUNT
720 
721  /* collect the array of interfaces first ... */
722  while (n_left >= 4)
723  {
724  if (n_left >= 12)
725  {
726  /* Prefetch 8 ahead - there's not much going on in each iteration */
727  vlib_prefetch_buffer_header (b[4], LOAD);
728  vlib_prefetch_buffer_header (b[5], LOAD);
729  vlib_prefetch_buffer_header (b[6], LOAD);
730  vlib_prefetch_buffer_header (b[7], LOAD);
731  }
732  sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
733  sw_if_index[1] = vnet_buffer (b[1])->sw_if_index[VLIB_RX];
734  sw_if_index[2] = vnet_buffer (b[2])->sw_if_index[VLIB_RX];
735  sw_if_index[3] = vnet_buffer (b[3])->sw_if_index[VLIB_RX];
736 
737  sw_if_index += 4;
738  n_left -= 4;
739  b += 4;
740  }
741  while (n_left)
742  {
743  sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
744 
745  sw_if_index += 1;
746  n_left -= 1;
747  b += 1;
748  }
749 
750  /* ... then count against them in blocks */
751  n_left = frame->n_vectors;
752 
753  while (n_left)
754  {
755  vnet_sw_interface_t *sw_if0;
756  u16 off, count;
757 
758  off = frame->n_vectors - n_left;
759 
760  sw_if_index = sw_if_indices + off;
761 
762  count = clib_count_equal_u32 (sw_if_index, n_left);
763  n_left -= count;
764 
765  vlib_increment_simple_counter (cm, thread_index, sw_if_index[0], count);
766 
767  /* Increment super-interface drop/punt counters for
768  sub-interfaces. */
769  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index[0]);
770  if (sw_if0->sup_sw_if_index != sw_if_index[0])
772  (cm, thread_index, sw_if0->sup_sw_if_index, count);
773  }
774 
775  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
776 
777  return frame->n_vectors;
778 }
779 
780 static inline void
783  vnet_pcap_t * pp, vlib_frame_t * f)
784 {
785  u32 *from;
786  u32 n_left = f->n_vectors;
787  vlib_buffer_t *b0, *p1;
788  u32 bi0;
789  i16 save_current_data;
790  u16 save_current_length;
791  vlib_error_main_t *em = &vm->error_main;
792  int do_trace = 0;
793 
794 
795  from = vlib_frame_vector_args (f);
796 
797  while (n_left > 0)
798  {
799  if (PREDICT_TRUE (n_left > 1))
800  {
801  p1 = vlib_get_buffer (vm, from[1]);
802  vlib_prefetch_buffer_header (p1, LOAD);
803  }
804 
805  bi0 = from[0];
806  b0 = vlib_get_buffer (vm, bi0);
807  from++;
808  n_left--;
809 
810  /* See if we're pointedly ignoring this specific error */
811  if (im->pcap_drop_filter_hash
812  && hash_get (im->pcap_drop_filter_hash, b0->error))
813  continue;
814 
815  do_trace = (pp->pcap_sw_if_index == 0) ||
816  pp->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_RX];
817 
818  if (PREDICT_FALSE
819  (do_trace == 0 && pp->filter_classify_table_index != ~0))
820  {
822  (b0, pp->filter_classify_table_index, 0 /* full classify */ );
823  }
824 
825  /* Trace all drops, or drops received on a specific interface */
826  if (do_trace)
827  {
828  save_current_data = b0->current_data;
829  save_current_length = b0->current_length;
830 
831  /*
832  * Typically, we'll need to rewind the buffer
833  * if l2_hdr_offset is valid, make sure to rewind to the start of
834  * the L2 header. This may not be the buffer start in case we pop-ed
835  * vlan tags.
836  * Otherwise, rewind to buffer start and hope for the best.
837  */
838  if (b0->flags & VNET_BUFFER_F_L2_HDR_OFFSET_VALID)
839  {
840  if (b0->current_data > vnet_buffer (b0)->l2_hdr_offset)
842  vnet_buffer (b0)->l2_hdr_offset -
843  b0->current_data);
844  }
845  else if (b0->current_data > 0)
846  vlib_buffer_advance (b0, (word) - b0->current_data);
847 
848  {
849  vlib_buffer_t *last = b0;
850  u32 error_node_index;
851  int drop_string_len;
852  vlib_node_t *n;
853  /* Length of the error string */
854  int error_string_len =
855  clib_strnlen (em->error_strings_heap[b0->error], 128);
856 
857  /* Dig up the drop node */
858  error_node_index = vm->node_main.node_by_error[b0->error];
859  n = vlib_get_node (vm, error_node_index);
860 
861  /* Length of full drop string, w/ "nodename: " prepended */
862  drop_string_len = error_string_len + vec_len (n->name) + 2;
863 
864  /* Find the last buffer in the chain */
865  while (last->flags & VLIB_BUFFER_NEXT_PRESENT)
866  last = vlib_get_buffer (vm, last->next_buffer);
867 
868  /*
869  * Append <nodename>: <error-string> to the capture,
870  * only if we can do that without allocating a new buffer.
871  */
872  if (PREDICT_TRUE ((last->current_data + last->current_length)
874  - drop_string_len)))
875  {
876  clib_memcpy_fast (last->data + last->current_data +
877  last->current_length, n->name,
878  vec_len (n->name));
879  clib_memcpy_fast (last->data + last->current_data +
880  last->current_length + vec_len (n->name),
881  ": ", 2);
882  clib_memcpy_fast (last->data + last->current_data +
883  last->current_length + vec_len (n->name) +
884  2, em->error_strings_heap[b0->error],
885  error_string_len);
886  last->current_length += drop_string_len;
887  b0->flags &= ~(VLIB_BUFFER_TOTAL_LENGTH_VALID);
888  pcap_add_buffer (&pp->pcap_main, vm, bi0,
889  pp->max_bytes_per_pkt);
890  last->current_length -= drop_string_len;
891  b0->current_data = save_current_data;
892  b0->current_length = save_current_length;
893  continue;
894  }
895  }
896 
897  /*
898  * Didn't have space in the last buffer, here's the dropped
899  * packet as-is
900  */
901  pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
902 
903  b0->current_data = save_current_data;
904  b0->current_length = save_current_length;
905  }
906  }
907 }
908 
909 #ifndef CLIB_MARCH_VARIANT
910 void
911 vnet_pcap_drop_trace_filter_add_del (u32 error_index, int is_add)
912 {
914 
915  if (im->pcap_drop_filter_hash == 0)
916  im->pcap_drop_filter_hash = hash_create (0, sizeof (uword));
917 
918  if (is_add)
919  hash_set (im->pcap_drop_filter_hash, error_index, 1);
920  else
921  hash_unset (im->pcap_drop_filter_hash, error_index);
922 }
923 #endif /* CLIB_MARCH_VARIANT */
924 
925 VLIB_NODE_FN (interface_drop) (vlib_main_t * vm,
928 {
931 
933  pcap_drop_trace (vm, im, pp, frame);
934 
935  return interface_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_DROP);
936 }
937 
938 VLIB_NODE_FN (interface_punt) (vlib_main_t * vm,
941 {
942  return interface_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_PUNT);
943 }
944 
945 /* *INDENT-OFF* */
946 VLIB_REGISTER_NODE (interface_drop) = {
947  .name = "error-drop",
948  .vector_size = sizeof (u32),
949  .format_trace = format_vnet_error_trace,
950  .n_next_nodes = 1,
951  .next_nodes = {
952  [0] = "drop",
953  },
954 };
955 /* *INDENT-ON* */
956 
957 /* *INDENT-OFF* */
958 VLIB_REGISTER_NODE (interface_punt) = {
959  .name = "error-punt",
960  .vector_size = sizeof (u32),
961  .format_trace = format_vnet_error_trace,
962  .n_next_nodes = 1,
963  .next_nodes = {
964  [0] = "punt",
965  },
966 };
967 /* *INDENT-ON* */
968 
969 /* *INDENT-OFF* */
970 VLIB_REGISTER_NODE (vnet_per_buffer_interface_output_node) = {
971  .name = "interface-output",
972  .vector_size = sizeof (u32),
973 };
974 /* *INDENT-ON* */
975 
976 static uword
978  vlib_frame_t * from_frame)
979 {
980  vnet_main_t *vnm = vnet_get_main ();
981  u32 last_sw_if_index = ~0;
982  vlib_frame_t *to_frame = 0;
983  vnet_hw_interface_t *hw = 0;
984  u32 *from, *to_next = 0;
985  u32 n_left_from;
986 
987  from = vlib_frame_vector_args (from_frame);
988  n_left_from = from_frame->n_vectors;
989  while (n_left_from > 0)
990  {
991  u32 bi0;
992  vlib_buffer_t *b0;
993  u32 sw_if_index0;
994 
995  bi0 = from[0];
996  from++;
997  n_left_from--;
998  b0 = vlib_get_buffer (vm, bi0);
999  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
1000 
1001  if (PREDICT_FALSE ((last_sw_if_index != sw_if_index0) || to_frame == 0))
1002  {
1003  if (to_frame)
1004  {
1005  hw = vnet_get_sup_hw_interface (vnm, last_sw_if_index);
1006  vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1007  }
1008  last_sw_if_index = sw_if_index0;
1009  hw = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1010  to_frame = vlib_get_frame_to_node (vm, hw->tx_node_index);
1011  to_next = vlib_frame_vector_args (to_frame);
1012  }
1013 
1014  to_next[0] = bi0;
1015  to_next++;
1016  to_frame->n_vectors++;
1017  }
1018  vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1019  return from_frame->n_vectors;
1020 }
1021 
1022 /* *INDENT-OFF* */
1023 VLIB_REGISTER_NODE (interface_tx) = {
1024  .function = interface_tx_node_fn,
1025  .name = "interface-tx",
1026  .vector_size = sizeof (u32),
1027  .n_next_nodes = 1,
1028  .next_nodes = {
1029  [0] = "error-drop",
1030  },
1031 };
1032 
1033 VNET_FEATURE_ARC_INIT (interface_output, static) =
1034 {
1035  .arc_name = "interface-output",
1036  .start_nodes = VNET_FEATURES (0),
1037  .last_in_arc = "interface-tx",
1039 };
1040 
1041 VNET_FEATURE_INIT (span_tx, static) = {
1042  .arc_name = "interface-output",
1043  .node_name = "span-output",
1044  .runs_before = VNET_FEATURES ("interface-tx"),
1045 };
1046 
1047 VNET_FEATURE_INIT (ipsec_if_tx, static) = {
1048  .arc_name = "interface-output",
1049  .node_name = "ipsec-if-output",
1050  .runs_before = VNET_FEATURES ("interface-tx"),
1051 };
1052 
1053 VNET_FEATURE_INIT (interface_tx, static) = {
1054  .arc_name = "interface-output",
1055  .node_name = "interface-tx",
1056  .runs_before = 0,
1057 };
1058 /* *INDENT-ON* */
1059 
1060 #ifndef CLIB_MARCH_VARIANT
1061 clib_error_t *
1063  u32 hw_if_index,
1064  u32 is_create)
1065 {
1066  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1067  u32 next_index;
1068 
1069  if (hi->output_node_index == 0)
1070  return 0;
1071 
1072  next_index = vlib_node_add_next
1073  (vnm->vlib_main, vnet_per_buffer_interface_output_node.index,
1074  hi->output_node_index);
1075  hi->output_node_next_index = next_index;
1076 
1077  return 0;
1078 }
1079 
1082 
1083 void
1085  u32 hw_if_index, u32 node_index)
1086 {
1087  ASSERT (node_index);
1088  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1089  u32 next_index = vlib_node_add_next
1090  (vnm->vlib_main, vnet_per_buffer_interface_output_node.index, node_index);
1091  hi->output_node_next_index = next_index;
1092  hi->output_node_index = node_index;
1093 }
1094 #endif /* CLIB_MARCH_VARIANT */
1095 
1096 /*
1097  * fd.io coding-style-patch-verification: ON
1098  *
1099  * Local Variables:
1100  * eval: (c-set-style "gnu")
1101  * End:
1102  */
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:1999
VNET_FEATURE_ARC_INIT(interface_output, static)
#define hash_set(h, key, value)
Definition: hash.h:255
#define CLIB_UNUSED(x)
Definition: clib.h:86
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:525
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:119
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
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:251
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:402
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:106
uword * pcap_drop_filter_hash
Definition: interface.h:876
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:476
vl_api_interface_index_t sw_if_index
Definition: gre.api:53
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:526
#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:182
#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:380
Use the vpp classifier to decide whether to trace packets.
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:53
#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:216
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:123
u32 * node_by_error
Definition: node.h:769
u8 data[128 - 2 *sizeof(u32)]
#define PREDICT_FALSE(x)
Definition: clib.h:118
vnet_main_t vnet_main
Definition: misc.c:43
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:866
format_function_t * format_buffer
Definition: node.h:360
u32 node_index
Node index.
Definition: node.h:498
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:224
#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:1599
u8 * name
Definition: node.h:266
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u32 flags
Definition: vhost_user.h:248
char ** error_strings_heap
Definition: error.h:55
u16 n_vectors
Definition: node.h:399
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:339
u8 data[]
Packet data.
Definition: buffer.h:181
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:299
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:483
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:1599
u32 trace_classify_table_index
Definition: interface.h:607
#define hash_create(elts, value_bytes)
Definition: hash.h:696
#define ASSERT(truth)
u8 data[128]
Definition: ipsec_types.api:89
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:470
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:258
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:858
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:417
#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:1600
u16 flags
Copy of main node flags.
Definition: node.h:511
u8 pcap_tx_enable
Definition: main.h:66
u8 si
Definition: lisp_types.api:47
vnet_pcap_t pcap
Definition: main.h:173
static_always_inline void vnet_calc_checksums_inline(vlib_main_t *vm, vlib_buffer_t *b, int is_ip4, int is_ip6, int with_gso)
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:280
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:304
static_always_inline vnet_feature_config_main_t * vnet_feature_get_config_main(u16 arc)
Definition: feature.h:244
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
Definition: defs.h:46
signed short i16
Definition: types.h:46