FD.io VPP  v20.09-64-g4f7b92f0a
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/ethernet/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 #include <vnet/interface_output.h>
49 
50 typedef struct
51 {
54  u8 data[128 - 2 * sizeof (u32)];
55 }
57 
58 #ifndef CLIB_MARCH_VARIANT
59 u8 *
61 {
62  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
63  vlib_node_t *node = va_arg (*va, vlib_node_t *);
64  interface_output_trace_t *t = va_arg (*va, interface_output_trace_t *);
65  vnet_main_t *vnm = vnet_get_main ();
67  u32 indent;
68 
69  if (t->sw_if_index != (u32) ~ 0)
70  {
71  indent = format_get_indent (s);
72 
75  {
76  /* the interface may have been deleted by the time the trace is printed */
77  s = format (s, "sw_if_index: %d ", t->sw_if_index);
78  }
79  else
80  {
81  si = vnet_get_sw_interface (vnm, t->sw_if_index);
82  s =
83  format (s, "%U ", format_vnet_sw_interface_name, vnm, si,
84  t->flags);
85  }
86  s =
87  format (s, "\n%U%U", format_white_space, indent,
89  t->data, sizeof (t->data));
90  }
91  return s;
92 }
93 
94 static void
96  vlib_node_runtime_t * node,
97  vlib_frame_t * frame, uword n_buffers)
98 {
99  u32 n_left, *from;
100 
101  n_left = n_buffers;
102  from = vlib_frame_vector_args (frame);
103 
104  while (n_left >= 4)
105  {
106  u32 bi0, bi1;
107  vlib_buffer_t *b0, *b1;
108  interface_output_trace_t *t0, *t1;
109 
110  /* Prefetch next iteration. */
111  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
112  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
113 
114  bi0 = from[0];
115  bi1 = from[1];
116 
117  b0 = vlib_get_buffer (vm, bi0);
118  b1 = vlib_get_buffer (vm, bi1);
119 
120  if (b0->flags & VLIB_BUFFER_IS_TRACED)
121  {
122  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
123  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
124  t0->flags = b0->flags;
126  sizeof (t0->data));
127  }
128  if (b1->flags & VLIB_BUFFER_IS_TRACED)
129  {
130  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
131  t1->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_TX];
132  t1->flags = b1->flags;
134  sizeof (t1->data));
135  }
136  from += 2;
137  n_left -= 2;
138  }
139 
140  while (n_left >= 1)
141  {
142  u32 bi0;
143  vlib_buffer_t *b0;
144  interface_output_trace_t *t0;
145 
146  bi0 = from[0];
147 
148  b0 = vlib_get_buffer (vm, bi0);
149 
150  if (b0->flags & VLIB_BUFFER_IS_TRACED)
151  {
152  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
153  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
154  t0->flags = b0->flags;
156  sizeof (t0->data));
157  }
158  from += 1;
159  n_left -= 1;
160  }
161 }
162 
165  vlib_node_runtime_t * node,
166  vlib_frame_t * frame,
167  vnet_main_t * vnm,
169  int do_tx_offloads)
170 {
171  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
173  u32 n_left_to_tx, *from, *from_end, *to_tx;
174  u32 n_bytes, n_buffers, n_packets;
175  u32 n_bytes_b0, n_bytes_b1, n_bytes_b2, n_bytes_b3;
176  u32 thread_index = vm->thread_index;
178  u32 next_index = VNET_INTERFACE_OUTPUT_NEXT_TX;
179  u32 current_config_index = ~0;
180  u8 arc = im->output_feature_arc_index;
181  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
182 
183  n_buffers = frame->n_vectors;
184 
185  if (node->flags & VLIB_NODE_FLAG_TRACE)
186  vnet_interface_output_trace (vm, node, frame, n_buffers);
187 
188  from = vlib_frame_vector_args (frame);
189  vlib_get_buffers (vm, from, b, n_buffers);
190 
191  if (rt->is_deleted)
192  return vlib_error_drop_buffers (vm, node, from,
193  /* buffer stride */ 1,
194  n_buffers,
196  node->node_index,
198 
199  si = vnet_get_sw_interface (vnm, rt->sw_if_index);
200  hi = vnet_get_sup_hw_interface (vnm, rt->sw_if_index);
201  if (!(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ||
203  {
205 
208  vlib_increment_simple_counter (cm, thread_index,
209  rt->sw_if_index, n_buffers);
210 
211  return vlib_error_drop_buffers (vm, node, from,
212  /* buffer stride */ 1,
213  n_buffers,
215  node->node_index,
217  }
218 
219  from_end = from + n_buffers;
220 
221  /* Total byte count of all buffers. */
222  n_bytes = 0;
223  n_packets = 0;
224 
225  /* interface-output feature arc handling */
227  {
229  fcm = vnet_feature_get_config_main (arc);
230  current_config_index = vnet_get_feature_config_index (arc,
231  rt->sw_if_index);
232  vnet_get_config_data (&fcm->config_main, &current_config_index,
233  &next_index, 0);
234  }
235 
236  while (from < from_end)
237  {
238  /* Get new next frame since previous incomplete frame may have less
239  than VNET_FRAME_SIZE vectors in it. */
240  vlib_get_new_next_frame (vm, node, next_index, to_tx, n_left_to_tx);
241 
242  while (from + 8 <= from_end && n_left_to_tx >= 4)
243  {
244  u32 bi0, bi1, bi2, bi3;
245  u32 tx_swif0, tx_swif1, tx_swif2, tx_swif3;
246  u32 or_flags;
247 
248  /* Prefetch next iteration. */
249  vlib_prefetch_buffer_header (b[4], LOAD);
250  vlib_prefetch_buffer_header (b[5], LOAD);
251  vlib_prefetch_buffer_header (b[6], LOAD);
252  vlib_prefetch_buffer_header (b[7], LOAD);
253 
254  bi0 = from[0];
255  bi1 = from[1];
256  bi2 = from[2];
257  bi3 = from[3];
258  to_tx[0] = bi0;
259  to_tx[1] = bi1;
260  to_tx[2] = bi2;
261  to_tx[3] = bi3;
262 
263  or_flags = b[0]->flags | b[1]->flags | b[2]->flags | b[3]->flags;
264 
265  from += 4;
266  to_tx += 4;
267  n_left_to_tx -= 4;
268 
269  /* Be grumpy about zero length buffers for benefit of
270  driver tx function. */
271  ASSERT (b[0]->current_length > 0);
272  ASSERT (b[1]->current_length > 0);
273  ASSERT (b[2]->current_length > 0);
274  ASSERT (b[3]->current_length > 0);
275 
276  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b[0]);
277  n_bytes_b1 = vlib_buffer_length_in_chain (vm, b[1]);
278  n_bytes_b2 = vlib_buffer_length_in_chain (vm, b[2]);
279  n_bytes_b3 = vlib_buffer_length_in_chain (vm, b[3]);
280  tx_swif0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
281  tx_swif1 = vnet_buffer (b[1])->sw_if_index[VLIB_TX];
282  tx_swif2 = vnet_buffer (b[2])->sw_if_index[VLIB_TX];
283  tx_swif3 = vnet_buffer (b[3])->sw_if_index[VLIB_TX];
284 
285  n_bytes += n_bytes_b0 + n_bytes_b1;
286  n_bytes += n_bytes_b2 + n_bytes_b3;
287  n_packets += 4;
288 
289  if (PREDICT_FALSE (current_config_index != ~0))
290  {
291  vnet_buffer (b[0])->feature_arc_index = arc;
292  vnet_buffer (b[1])->feature_arc_index = arc;
293  vnet_buffer (b[2])->feature_arc_index = arc;
294  vnet_buffer (b[3])->feature_arc_index = arc;
295  b[0]->current_config_index = current_config_index;
296  b[1]->current_config_index = current_config_index;
297  b[2]->current_config_index = current_config_index;
298  b[3]->current_config_index = current_config_index;
299  }
300 
301  /* update vlan subif tx counts, if required */
302  if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
303  {
304  vlib_increment_combined_counter (im->combined_sw_if_counters +
306  thread_index, tx_swif0, 1,
307  n_bytes_b0);
308  }
309 
310  if (PREDICT_FALSE (tx_swif1 != rt->sw_if_index))
311  {
312 
313  vlib_increment_combined_counter (im->combined_sw_if_counters +
315  thread_index, tx_swif1, 1,
316  n_bytes_b1);
317  }
318 
319  if (PREDICT_FALSE (tx_swif2 != rt->sw_if_index))
320  {
321 
322  vlib_increment_combined_counter (im->combined_sw_if_counters +
324  thread_index, tx_swif2, 1,
325  n_bytes_b2);
326  }
327  if (PREDICT_FALSE (tx_swif3 != rt->sw_if_index))
328  {
329 
330  vlib_increment_combined_counter (im->combined_sw_if_counters +
332  thread_index, tx_swif3, 1,
333  n_bytes_b3);
334  }
335 
336  if (do_tx_offloads)
337  {
338  u32 vnet_buffer_offload_flags =
339  (VNET_BUFFER_F_OFFLOAD_TCP_CKSUM |
340  VNET_BUFFER_F_OFFLOAD_UDP_CKSUM |
341  VNET_BUFFER_F_OFFLOAD_IP_CKSUM);
342  if (or_flags & vnet_buffer_offload_flags)
343  {
344  if (b[0]->flags & vnet_buffer_offload_flags)
346  (vm, b[0],
347  b[0]->flags & VNET_BUFFER_F_IS_IP4,
348  b[0]->flags & VNET_BUFFER_F_IS_IP6);
349  if (b[1]->flags & vnet_buffer_offload_flags)
351  (vm, b[1],
352  b[1]->flags & VNET_BUFFER_F_IS_IP4,
353  b[1]->flags & VNET_BUFFER_F_IS_IP6);
354  if (b[2]->flags & vnet_buffer_offload_flags)
356  (vm, b[2],
357  b[2]->flags & VNET_BUFFER_F_IS_IP4,
358  b[2]->flags & VNET_BUFFER_F_IS_IP6);
359  if (b[3]->flags & vnet_buffer_offload_flags)
361  (vm, b[3],
362  b[3]->flags & VNET_BUFFER_F_IS_IP4,
363  b[3]->flags & VNET_BUFFER_F_IS_IP6);
364  }
365  }
366  b += 4;
367 
368  }
369 
370  while (from + 1 <= from_end && n_left_to_tx >= 1)
371  {
372  u32 bi0;
373  u32 tx_swif0;
374 
375  bi0 = from[0];
376  to_tx[0] = bi0;
377  from += 1;
378  to_tx += 1;
379  n_left_to_tx -= 1;
380 
381  /* Be grumpy about zero length buffers for benefit of
382  driver tx function. */
383  ASSERT (b[0]->current_length > 0);
384 
385  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b[0]);
386  tx_swif0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
387  n_bytes += n_bytes_b0;
388  n_packets += 1;
389 
390  if (PREDICT_FALSE (current_config_index != ~0))
391  {
392  vnet_buffer (b[0])->feature_arc_index = arc;
393  b[0]->current_config_index = current_config_index;
394  }
395 
396  if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
397  {
398 
399  vlib_increment_combined_counter (im->combined_sw_if_counters +
401  thread_index, tx_swif0, 1,
402  n_bytes_b0);
403  }
404 
405  if (do_tx_offloads)
406  {
407  if (b[0]->flags &
408  (VNET_BUFFER_F_OFFLOAD_TCP_CKSUM |
409  VNET_BUFFER_F_OFFLOAD_UDP_CKSUM |
410  VNET_BUFFER_F_OFFLOAD_IP_CKSUM))
412  (vm, b[0],
413  b[0]->flags & VNET_BUFFER_F_IS_IP4,
414  b[0]->flags & VNET_BUFFER_F_IS_IP6);
415  }
416  b += 1;
417  }
418 
419  vlib_put_next_frame (vm, node, next_index, n_left_to_tx);
420  }
421 
422  /* Update main interface stats. */
423  vlib_increment_combined_counter (im->combined_sw_if_counters
425  thread_index,
426  rt->sw_if_index, n_packets, n_bytes);
427  return n_buffers;
428 }
429 #endif /* CLIB_MARCH_VARIANT */
430 
433  int sw_if_index_from_buffer)
434 {
435  u32 n_left_from, *from;
438 
439  if (PREDICT_TRUE (pp->pcap_tx_enable == 0))
440  return;
441 
442  if (sw_if_index_from_buffer == 0)
443  {
444  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
445  sw_if_index = rt->sw_if_index;
446  }
447  else
448  sw_if_index = ~0;
449 
450  n_left_from = frame->n_vectors;
451  from = vlib_frame_vector_args (frame);
452 
453  while (n_left_from > 0)
454  {
455  int classify_filter_result;
456  u32 bi0 = from[0];
457  vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0);
458  from++;
459  n_left_from--;
460 
461  if (pp->filter_classify_table_index != ~0)
462  {
463  classify_filter_result =
465  (b0, pp->filter_classify_table_index, 0 /* full classify */ );
466  if (classify_filter_result)
467  pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
468  continue;
469  }
470 
471  if (sw_if_index_from_buffer)
472  sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
473 
474  if (pp->pcap_sw_if_index == 0 || pp->pcap_sw_if_index == sw_if_index)
475  {
476  vnet_main_t *vnm = vnet_get_main ();
478  vnet_get_sup_hw_interface (vnm, sw_if_index);
479  /* Capture pkt if not filtered, or if filter hits */
480  if (hi->trace_classify_table_index == ~0 ||
482  (b0, hi->trace_classify_table_index, 0 /* full classify */ ))
483  pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
484  }
485  }
486 }
487 
488 #ifndef CLIB_MARCH_VARIANT
489 
490 uword
492  vlib_frame_t * frame)
493 {
494  vnet_main_t *vnm = vnet_get_main ();
496  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
497  hi = vnet_get_sup_hw_interface (vnm, rt->sw_if_index);
498 
499  vnet_interface_pcap_tx_trace (vm, node, frame,
500  0 /* sw_if_index_from_buffer */ );
501 
503  return vnet_interface_output_node_inline (vm, node, frame, vnm, hi,
504  /* do_tx_offloads */ 0);
505  else
506  return vnet_interface_output_node_inline (vm, node, frame, vnm, hi,
507  /* do_tx_offloads */ 1);
508 }
509 #endif /* CLIB_MARCH_VARIANT */
510 
511 /* Use buffer's sw_if_index[VNET_TX] to choose output interface. */
512 VLIB_NODE_FN (vnet_per_buffer_interface_output_node) (vlib_main_t * vm,
514  node,
516 {
517  vnet_main_t *vnm = vnet_get_main ();
518  u32 n_left_to_next, *from, *to_next;
519  u32 n_left_from, next_index;
520 
521  vnet_interface_pcap_tx_trace (vm, node, frame,
522  1 /* sw_if_index_from_buffer */ );
523 
524  n_left_from = frame->n_vectors;
525 
526  from = vlib_frame_vector_args (frame);
527  next_index = node->cached_next_index;
528 
529  while (n_left_from > 0)
530  {
531  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
532 
533  while (n_left_from >= 4 && n_left_to_next >= 2)
534  {
535  u32 bi0, bi1, next0, next1;
536  vlib_buffer_t *b0, *b1;
537  vnet_hw_interface_t *hi0, *hi1;
538 
539  /* Prefetch next iteration. */
540  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
541  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
542 
543  bi0 = from[0];
544  bi1 = from[1];
545  to_next[0] = bi0;
546  to_next[1] = bi1;
547  from += 2;
548  to_next += 2;
549  n_left_to_next -= 2;
550  n_left_from -= 2;
551 
552  b0 = vlib_get_buffer (vm, bi0);
553  b1 = vlib_get_buffer (vm, bi1);
554 
555  hi0 =
558  [VLIB_TX]);
559  hi1 =
562  [VLIB_TX]);
563 
564  next0 = hi0->output_node_next_index;
565  next1 = hi1->output_node_next_index;
566 
567  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
568  n_left_to_next, bi0, bi1, next0,
569  next1);
570  }
571 
572  while (n_left_from > 0 && n_left_to_next > 0)
573  {
574  u32 bi0, next0;
575  vlib_buffer_t *b0;
576  vnet_hw_interface_t *hi0;
577 
578  bi0 = from[0];
579  to_next[0] = bi0;
580  from += 1;
581  to_next += 1;
582  n_left_to_next -= 1;
583  n_left_from -= 1;
584 
585  b0 = vlib_get_buffer (vm, bi0);
586 
587  hi0 =
590  [VLIB_TX]);
591 
592  next0 = hi0->output_node_next_index;
593 
594  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
595  n_left_to_next, bi0, next0);
596  }
597 
598  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
599  }
600 
601  return frame->n_vectors;
602 }
603 
604 typedef struct vnet_error_trace_t_
605 {
609  u8 pad[2];
611  ip46_address_t src, dst;
613 
614 static u8 *
615 format_vnet_error_trace (u8 * s, va_list * va)
616 {
617  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
618  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
619  vnet_error_trace_t *t = va_arg (*va, vnet_error_trace_t *);
620 
621  /* Normal, non-catchup trace */
622  if (t->details_valid == 0)
623  {
624  s = format (s, "rx:%U", format_vnet_sw_if_index_name,
625  vnet_get_main (), t->sw_if_index);
626  }
627  else if (t->details_valid == 1)
628  {
629  /* The trace capture code didn't understant the mactype */
630  s = format (s, "mactype 0x%4x (not decoded)", t->mactype);
631  }
632  else if (t->details_valid == 2)
633  {
634  /* Dump the src/dst addresses */
635  if (t->is_ip6 == 0)
636  s = format (s, "IP4: %U -> %U",
637  format_ip4_address, &t->src.ip4,
638  format_ip4_address, &t->dst.ip4);
639  else
640  s = format (s, "IP6: %U -> %U",
641  format_ip6_address, &t->src.ip6,
642  format_ip6_address, &t->dst.ip6);
643  }
644  return s;
645 }
646 
647 static void
649  vlib_node_runtime_t * node, vlib_frame_t * frame)
650 {
651  u32 n_left, *buffers;
652 
653  buffers = vlib_frame_vector_args (frame);
654  n_left = frame->n_vectors;
655 
656  while (n_left >= 4)
657  {
658  u32 bi0, bi1;
659  vlib_buffer_t *b0, *b1;
660  vnet_error_trace_t *t0, *t1;
661 
662  /* Prefetch next iteration. */
663  vlib_prefetch_buffer_with_index (vm, buffers[2], LOAD);
664  vlib_prefetch_buffer_with_index (vm, buffers[3], LOAD);
665 
666  bi0 = buffers[0];
667  bi1 = buffers[1];
668 
669  b0 = vlib_get_buffer (vm, bi0);
670  b1 = vlib_get_buffer (vm, bi1);
671 
672  if (b0->flags & VLIB_BUFFER_IS_TRACED)
673  {
674  t0 = vlib_add_trace (vm, node, b0,
676  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
677  t0->details_valid = 0;
678  }
679  if (b1->flags & VLIB_BUFFER_IS_TRACED)
680  {
681  t1 = vlib_add_trace (vm, node, b1,
683  t1->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX];
684  t1->details_valid = 0;
685  }
686  buffers += 2;
687  n_left -= 2;
688  }
689 
690  while (n_left >= 1)
691  {
692  u32 bi0;
693  vlib_buffer_t *b0;
694  vnet_error_trace_t *t0;
695 
696  bi0 = buffers[0];
697 
698  b0 = vlib_get_buffer (vm, bi0);
699 
700  if (b0->flags & VLIB_BUFFER_IS_TRACED)
701  {
702  t0 = vlib_add_trace (vm, node, b0,
704  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
705  t0->details_valid = 0;
706  }
707  buffers += 1;
708  n_left -= 1;
709  }
710 }
711 
712 typedef enum
713 {
718 
719 static void
722 {
723  /* Can we safely rewind the buffer? If not, fagedaboudit */
724  if (b->flags & VNET_BUFFER_F_L2_HDR_OFFSET_VALID)
725  {
727  ip4_header_t *ip4;
728  ip6_header_t *ip6;
729  ethernet_header_t *eh;
730  i16 delta;
731 
732  t = vlib_add_trace (vm, node, b, sizeof (*t));
733  delta = vnet_buffer (b)->l2_hdr_offset - b->current_data;
734  vlib_buffer_advance (b, delta);
735 
736  eh = vlib_buffer_get_current (b);
737  /* Save mactype */
738  t->mactype = clib_net_to_host_u16 (eh->type);
739  t->details_valid = 1;
740  switch (t->mactype)
741  {
742  case ETHERNET_TYPE_IP4:
743  ip4 = (void *) (eh + 1);
744  t->details_valid = 2;
745  t->is_ip6 = 0;
746  t->src.ip4.as_u32 = ip4->src_address.as_u32;
747  t->dst.ip4.as_u32 = ip4->dst_address.as_u32;
748  break;
749 
750  case ETHERNET_TYPE_IP6:
751  ip6 = (void *) (eh + 1);
752  t->details_valid = 2;
753  t->is_ip6 = 1;
754  clib_memcpy_fast (t->src.as_u8, ip6->src_address.as_u8,
755  sizeof (ip6_address_t));
756  clib_memcpy_fast (t->dst.as_u8, ip6->dst_address.as_u8,
757  sizeof (ip6_address_t));
758  break;
759 
760  default:
761  /* Dunno, do nothing, leave details_valid alone */
762  break;
763  }
764  /* Restore current data (probably unnecessary) */
765  vlib_buffer_advance (b, -delta);
766  }
767 }
768 
771  vlib_node_runtime_t * node,
772  vlib_frame_t * frame,
773  vnet_error_disposition_t disposition)
774 {
775  u32 *from, n_left, thread_index, *sw_if_index;
776  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
777  u32 sw_if_indices[VLIB_FRAME_SIZE];
779  u16 nexts[VLIB_FRAME_SIZE];
780  u32 n_trace;
781  vnet_main_t *vnm;
782 
783  vnm = vnet_get_main ();
784  thread_index = vm->thread_index;
785  from = vlib_frame_vector_args (frame);
786  n_left = frame->n_vectors;
787  b = bufs;
788  sw_if_index = sw_if_indices;
789 
790  vlib_get_buffers (vm, from, bufs, n_left);
791 
792  /* "trace add error-drop NNN?" */
793  if (PREDICT_FALSE ((n_trace = vlib_get_trace_count (vm, node))))
794  {
795  /* If pkts aren't otherwise traced... */
796  if ((node->flags & VLIB_NODE_FLAG_TRACE) == 0)
797  {
798  /* Trace them from here */
799  node->flags |= VLIB_NODE_FLAG_TRACE;
800  while (n_trace && n_left)
801  {
802  vlib_trace_buffer (vm, node, 0 /* next_index */ ,
803  b[0], 0 /* follow chain */ );
804  /*
805  * Here we have a wireshark dissector problem.
806  * Packets may be well-formed, or not. We
807  * must not blow chunks in any case.
808  *
809  * Try to produce trace records which will help
810  * folks understand what's going on.
811  */
812  drop_catchup_trace (vm, node, b[0]);
813 
814  n_trace--;
815  n_left--;
816  b++;
817  }
818  }
819 
820  vlib_set_trace_count (vm, node, n_trace);
821  b = bufs;
822  n_left = frame->n_vectors;
823  }
824 
825  if (node->flags & VLIB_NODE_FLAG_TRACE)
826  interface_trace_buffers (vm, node, frame);
827 
828  /* All going to drop regardless, this is just a counting exercise */
829  clib_memset (nexts, 0, sizeof (nexts));
830 
832  (disposition == VNET_ERROR_DISPOSITION_PUNT
835 
836  /* collect the array of interfaces first ... */
837  while (n_left >= 4)
838  {
839  if (n_left >= 12)
840  {
841  /* Prefetch 8 ahead - there's not much going on in each iteration */
842  vlib_prefetch_buffer_header (b[4], LOAD);
843  vlib_prefetch_buffer_header (b[5], LOAD);
844  vlib_prefetch_buffer_header (b[6], LOAD);
845  vlib_prefetch_buffer_header (b[7], LOAD);
846  }
847  sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
848  sw_if_index[1] = vnet_buffer (b[1])->sw_if_index[VLIB_RX];
849  sw_if_index[2] = vnet_buffer (b[2])->sw_if_index[VLIB_RX];
850  sw_if_index[3] = vnet_buffer (b[3])->sw_if_index[VLIB_RX];
851 
852  sw_if_index += 4;
853  n_left -= 4;
854  b += 4;
855  }
856  while (n_left)
857  {
858  sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
859 
860  sw_if_index += 1;
861  n_left -= 1;
862  b += 1;
863  }
864 
865  /* ... then count against them in blocks */
866  n_left = frame->n_vectors;
867 
868  while (n_left)
869  {
870  vnet_sw_interface_t *sw_if0;
871  u16 off, count;
872 
873  off = frame->n_vectors - n_left;
874 
875  sw_if_index = sw_if_indices + off;
876 
877  count = clib_count_equal_u32 (sw_if_index, n_left);
878  n_left -= count;
879 
880  vlib_increment_simple_counter (cm, thread_index, sw_if_index[0], count);
881 
882  /* Increment super-interface drop/punt counters for
883  sub-interfaces. */
884  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index[0]);
885  if (sw_if0->sup_sw_if_index != sw_if_index[0])
887  (cm, thread_index, sw_if0->sup_sw_if_index, count);
888  }
889 
890  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
891 
892  return frame->n_vectors;
893 }
894 
895 static inline void
898  vnet_pcap_t * pp, vlib_frame_t * f)
899 {
900  u32 *from;
901  u32 n_left = f->n_vectors;
902  vlib_buffer_t *b0, *p1;
903  u32 bi0;
904  i16 save_current_data;
905  u16 save_current_length;
906  vlib_error_main_t *em = &vm->error_main;
907  int do_trace = 0;
908 
909 
910  from = vlib_frame_vector_args (f);
911 
912  while (n_left > 0)
913  {
914  if (PREDICT_TRUE (n_left > 1))
915  {
916  p1 = vlib_get_buffer (vm, from[1]);
917  vlib_prefetch_buffer_header (p1, LOAD);
918  }
919 
920  bi0 = from[0];
921  b0 = vlib_get_buffer (vm, bi0);
922  from++;
923  n_left--;
924 
925  /* See if we're pointedly ignoring this specific error */
926  if (im->pcap_drop_filter_hash
927  && hash_get (im->pcap_drop_filter_hash, b0->error))
928  continue;
929 
930  do_trace = (pp->pcap_sw_if_index == 0) ||
931  pp->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_RX];
932 
933  if (PREDICT_FALSE
934  (do_trace == 0 && pp->filter_classify_table_index != ~0))
935  {
937  (b0, pp->filter_classify_table_index, 0 /* full classify */ );
938  }
939 
940  /* Trace all drops, or drops received on a specific interface */
941  if (do_trace)
942  {
943  save_current_data = b0->current_data;
944  save_current_length = b0->current_length;
945 
946  /*
947  * Typically, we'll need to rewind the buffer
948  * if l2_hdr_offset is valid, make sure to rewind to the start of
949  * the L2 header. This may not be the buffer start in case we pop-ed
950  * vlan tags.
951  * Otherwise, rewind to buffer start and hope for the best.
952  */
953  if (b0->flags & VNET_BUFFER_F_L2_HDR_OFFSET_VALID)
954  {
955  if (b0->current_data > vnet_buffer (b0)->l2_hdr_offset)
957  vnet_buffer (b0)->l2_hdr_offset -
958  b0->current_data);
959  }
960  else if (b0->current_data > 0)
961  vlib_buffer_advance (b0, (word) - b0->current_data);
962 
963  {
964  vlib_buffer_t *last = b0;
965  u32 error_node_index;
966  int drop_string_len;
967  vlib_node_t *n;
968  /* Length of the error string */
969  int error_string_len =
970  clib_strnlen (em->error_strings_heap[b0->error], 128);
971 
972  /* Dig up the drop node */
973  error_node_index = vm->node_main.node_by_error[b0->error];
974  n = vlib_get_node (vm, error_node_index);
975 
976  /* Length of full drop string, w/ "nodename: " prepended */
977  drop_string_len = error_string_len + vec_len (n->name) + 2;
978 
979  /* Find the last buffer in the chain */
980  while (last->flags & VLIB_BUFFER_NEXT_PRESENT)
981  last = vlib_get_buffer (vm, last->next_buffer);
982 
983  /*
984  * Append <nodename>: <error-string> to the capture,
985  * only if we can do that without allocating a new buffer.
986  */
987  if (PREDICT_TRUE ((last->current_data + last->current_length)
989  - drop_string_len)))
990  {
991  clib_memcpy_fast (last->data + last->current_data +
992  last->current_length, n->name,
993  vec_len (n->name));
994  clib_memcpy_fast (last->data + last->current_data +
995  last->current_length + vec_len (n->name),
996  ": ", 2);
997  clib_memcpy_fast (last->data + last->current_data +
998  last->current_length + vec_len (n->name) +
999  2, em->error_strings_heap[b0->error],
1000  error_string_len);
1001  last->current_length += drop_string_len;
1002  b0->flags &= ~(VLIB_BUFFER_TOTAL_LENGTH_VALID);
1003  pcap_add_buffer (&pp->pcap_main, vm, bi0,
1004  pp->max_bytes_per_pkt);
1005  last->current_length -= drop_string_len;
1006  b0->current_data = save_current_data;
1007  b0->current_length = save_current_length;
1008  continue;
1009  }
1010  }
1011 
1012  /*
1013  * Didn't have space in the last buffer, here's the dropped
1014  * packet as-is
1015  */
1016  pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
1017 
1018  b0->current_data = save_current_data;
1019  b0->current_length = save_current_length;
1020  }
1021  }
1022 }
1023 
1024 #ifndef CLIB_MARCH_VARIANT
1025 void
1026 vnet_pcap_drop_trace_filter_add_del (u32 error_index, int is_add)
1027 {
1029 
1030  if (im->pcap_drop_filter_hash == 0)
1031  im->pcap_drop_filter_hash = hash_create (0, sizeof (uword));
1032 
1033  if (is_add)
1034  hash_set (im->pcap_drop_filter_hash, error_index, 1);
1035  else
1036  hash_unset (im->pcap_drop_filter_hash, error_index);
1037 }
1038 #endif /* CLIB_MARCH_VARIANT */
1039 
1040 VLIB_NODE_FN (interface_drop) (vlib_main_t * vm,
1042  vlib_frame_t * frame)
1043 {
1046 
1047  if (PREDICT_FALSE (pp->pcap_drop_enable))
1048  pcap_drop_trace (vm, im, pp, frame);
1049 
1050  return interface_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_DROP);
1051 }
1052 
1053 VLIB_NODE_FN (interface_punt) (vlib_main_t * vm,
1055  vlib_frame_t * frame)
1056 {
1057  return interface_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_PUNT);
1058 }
1059 
1060 /* *INDENT-OFF* */
1061 VLIB_REGISTER_NODE (interface_drop) = {
1062  .name = "error-drop",
1063  .vector_size = sizeof (u32),
1064  .format_trace = format_vnet_error_trace,
1066  .n_next_nodes = 1,
1067  .next_nodes = {
1068  [0] = "drop",
1069  },
1070 };
1071 /* *INDENT-ON* */
1072 
1073 /* *INDENT-OFF* */
1074 VLIB_REGISTER_NODE (interface_punt) = {
1075  .name = "error-punt",
1076  .vector_size = sizeof (u32),
1077  .format_trace = format_vnet_error_trace,
1079  .n_next_nodes = 1,
1080  .next_nodes = {
1081  [0] = "punt",
1082  },
1083 };
1084 /* *INDENT-ON* */
1085 
1086 /* *INDENT-OFF* */
1087 VLIB_REGISTER_NODE (vnet_per_buffer_interface_output_node) = {
1088  .name = "interface-output",
1089  .vector_size = sizeof (u32),
1090 };
1091 /* *INDENT-ON* */
1092 
1093 static uword
1095  vlib_frame_t * from_frame)
1096 {
1097  vnet_main_t *vnm = vnet_get_main ();
1098  u32 last_sw_if_index = ~0;
1099  vlib_frame_t *to_frame = 0;
1100  vnet_hw_interface_t *hw = 0;
1101  u32 *from, *to_next = 0;
1102  u32 n_left_from;
1103 
1104  from = vlib_frame_vector_args (from_frame);
1105  n_left_from = from_frame->n_vectors;
1106  while (n_left_from > 0)
1107  {
1108  u32 bi0;
1109  vlib_buffer_t *b0;
1110  u32 sw_if_index0;
1111 
1112  bi0 = from[0];
1113  from++;
1114  n_left_from--;
1115  b0 = vlib_get_buffer (vm, bi0);
1116  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
1117 
1118  if (PREDICT_FALSE ((last_sw_if_index != sw_if_index0) || to_frame == 0))
1119  {
1120  if (to_frame)
1121  {
1122  hw = vnet_get_sup_hw_interface (vnm, last_sw_if_index);
1123  vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1124  }
1125  last_sw_if_index = sw_if_index0;
1126  hw = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1127  to_frame = vlib_get_frame_to_node (vm, hw->tx_node_index);
1128  to_next = vlib_frame_vector_args (to_frame);
1129  }
1130 
1131  to_next[0] = bi0;
1132  to_next++;
1133  to_frame->n_vectors++;
1134  }
1135  vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1136  return from_frame->n_vectors;
1137 }
1138 
1139 /* *INDENT-OFF* */
1140 VLIB_REGISTER_NODE (interface_tx) = {
1141  .function = interface_tx_node_fn,
1142  .name = "interface-tx",
1143  .vector_size = sizeof (u32),
1144  .n_next_nodes = 1,
1145  .next_nodes = {
1146  [0] = "error-drop",
1147  },
1148 };
1149 
1150 VNET_FEATURE_ARC_INIT (interface_output, static) =
1151 {
1152  .arc_name = "interface-output",
1153  .start_nodes = VNET_FEATURES (0),
1154  .last_in_arc = "interface-tx",
1156 };
1157 
1158 VNET_FEATURE_INIT (span_tx, static) = {
1159  .arc_name = "interface-output",
1160  .node_name = "span-output",
1161  .runs_before = VNET_FEATURES ("interface-tx"),
1162 };
1163 
1164 VNET_FEATURE_INIT (ipsec_if_tx, static) = {
1165  .arc_name = "interface-output",
1166  .node_name = "ipsec-if-output",
1167  .runs_before = VNET_FEATURES ("interface-tx"),
1168 };
1169 
1170 VNET_FEATURE_INIT (interface_tx, static) = {
1171  .arc_name = "interface-output",
1172  .node_name = "interface-tx",
1173  .runs_before = 0,
1174 };
1175 /* *INDENT-ON* */
1176 
1177 #ifndef CLIB_MARCH_VARIANT
1178 clib_error_t *
1180  u32 hw_if_index,
1181  u32 is_create)
1182 {
1183  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1184  u32 next_index;
1185 
1186  if (hi->output_node_index == 0)
1187  return 0;
1188 
1189  next_index = vlib_node_add_next
1190  (vnm->vlib_main, vnet_per_buffer_interface_output_node.index,
1191  hi->output_node_index);
1192  hi->output_node_next_index = next_index;
1193 
1194  return 0;
1195 }
1196 
1199 
1200 void
1202  u32 hw_if_index, u32 node_index)
1203 {
1204  ASSERT (node_index);
1205  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1206  u32 next_index = vlib_node_add_next
1207  (vnm->vlib_main, vnet_per_buffer_interface_output_node.index, node_index);
1208  hi->output_node_next_index = next_index;
1209  hi->output_node_index = node_index;
1210 }
1211 #endif /* CLIB_MARCH_VARIANT */
1212 
1213 /*
1214  * fd.io coding-style-patch-verification: ON
1215  *
1216  * Local Variables:
1217  * eval: (c-set-style "gnu")
1218  * End:
1219  */
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:73
vlib_main_t vlib_global_main
Definition: main.c:1983
VNET_FEATURE_ARC_INIT(interface_output, static)
#define hash_set(h, key, value)
Definition: hash.h:255
#define CLIB_UNUSED(x)
Definition: clib.h:87
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)
static u32 vlib_get_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt)
Definition: trace_funcs.h:193
#define hash_unset(h, key)
Definition: hash.h:261
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:103
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:518
ip4_address_t src_address
Definition: ip4_packet.h:125
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:71
vnet_interface_main_t interface_main
Definition: vnet.h:59
#define PREDICT_TRUE(x)
Definition: clib.h:121
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)
#define VLIB_NODE_FLAG_TRACE_SUPPORTED
Definition: node.h:305
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u32 thread_index
Definition: main.h:249
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
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:70
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
vlib_main_t * vm
Definition: in2out_ed.c:1582
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
ip6_address_t src_address
Definition: ip6_packet.h:310
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:1173
unsigned char u8
Definition: types.h:56
u8 data[128]
Definition: ipsec_types.api:89
static void vlib_trace_buffer(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, vlib_buffer_t *b, int follow_chain)
Definition: trace_funcs.h:136
format_function_t format_ip4_address
Definition: format.h:73
#define static_always_inline
Definition: clib.h:108
uword * pcap_drop_filter_hash
Definition: interface.h:890
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_ip6_address_t ip6
Definition: one.api:424
ip4_address_t dst_address
Definition: ip4_packet.h:125
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:537
#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:74
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:396
unsigned int u32
Definition: types.h:88
A collection of simple counters.
Definition: counter.h:57
#define VLIB_FRAME_SIZE
Definition: node.h:377
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:86
u8 pcap_drop_enable
Definition: main.h:69
static u8 * format_vnet_error_trace(u8 *s, va_list *va)
vlib_error_main_t error_main
Definition: main.h:210
static void drop_catchup_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b)
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:749
u8 data[128 - 2 *sizeof(u32)]
#define PREDICT_FALSE(x)
Definition: clib.h:120
vl_api_ip4_address_t ip4
Definition: one.api:376
vnet_main_t vnet_main
Definition: misc.c:43
signed char i8
Definition: types.h:45
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:880
format_function_t * format_buffer
Definition: node.h:357
u32 node_index
Node index.
Definition: node.h:487
u32 pcap_sw_if_index
Definition: main.h:72
#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:391
static void interface_trace_buffers(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
u8 * name
Definition: node.h:263
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
char ** error_strings_heap
Definition: error.h:55
u16 n_vectors
Definition: node.h:396
format_function_t format_ip6_address
Definition: format.h:91
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
u32 trace_classify_table_index
Definition: interface.h:621
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1582
#define hash_create(elts, value_bytes)
Definition: hash.h:696
#define ASSERT(truth)
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
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:189
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1583
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:872
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
static_always_inline void vnet_calc_checksums_inline(vlib_main_t *vm, vlib_buffer_t *b, int is_ip4, int is_ip6)
#define vnet_buffer(b)
Definition: buffer.h:417
#define clib_strnlen(s, m)
Definition: string.h:768
static_always_inline uword clib_count_equal_u32(u32 *data, uword max_count)
Definition: string.h:518
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:85
u16 flags
Copy of main node flags.
Definition: node.h:500
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:577
u8 pcap_tx_enable
Definition: main.h:67
u8 si
Definition: lisp_types.api:47
vnet_pcap_t pcap
Definition: main.h:204
static void vlib_set_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt, u32 count)
Definition: trace_funcs.h:209
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:301
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
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:33
Definition: defs.h:46
ip6_address_t dst_address
Definition: ip6_packet.h:310
signed short i16
Definition: types.h:46