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