FD.io VPP  v21.06
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 #include <vppinfra/vector_funcs.h>
51 
52 typedef struct
53 {
56  u8 data[128 - 2 * sizeof (u32)];
57 }
59 
60 #ifndef CLIB_MARCH_VARIANT
61 u8 *
63 {
64  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
65  vlib_node_t *node = va_arg (*va, vlib_node_t *);
66  interface_output_trace_t *t = va_arg (*va, interface_output_trace_t *);
67  vnet_main_t *vnm = vnet_get_main ();
69  u32 indent;
70 
71  if (t->sw_if_index != (u32) ~ 0)
72  {
73  indent = format_get_indent (s);
74 
77  {
78  /* the interface may have been deleted by the time the trace is printed */
79  s = format (s, "sw_if_index: %d ", t->sw_if_index);
80  }
81  else
82  {
83  si = vnet_get_sw_interface (vnm, t->sw_if_index);
84  s =
85  format (s, "%U ", format_vnet_sw_interface_name, vnm, si,
86  t->flags);
87  }
88  s =
89  format (s, "\n%U%U", format_white_space, indent,
91  t->data, sizeof (t->data));
92  }
93  return s;
94 }
95 #endif /* CLIB_MARCH_VARIANT */
96 
97 static void
99  vlib_node_runtime_t * node,
101 {
102  u32 n_left, *from;
103 
104  n_left = n_buffers;
105  from = vlib_frame_vector_args (frame);
106 
107  while (n_left >= 4)
108  {
109  u32 bi0, bi1;
110  vlib_buffer_t *b0, *b1;
111  interface_output_trace_t *t0, *t1;
112 
113  /* Prefetch next iteration. */
114  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
115  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
116 
117  bi0 = from[0];
118  bi1 = from[1];
119 
120  b0 = vlib_get_buffer (vm, bi0);
121  b1 = vlib_get_buffer (vm, bi1);
122 
123  if (b0->flags & VLIB_BUFFER_IS_TRACED)
124  {
125  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
126  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
127  t0->flags = b0->flags;
129  sizeof (t0->data));
130  }
131  if (b1->flags & VLIB_BUFFER_IS_TRACED)
132  {
133  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
134  t1->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_TX];
135  t1->flags = b1->flags;
137  sizeof (t1->data));
138  }
139  from += 2;
140  n_left -= 2;
141  }
142 
143  while (n_left >= 1)
144  {
145  u32 bi0;
146  vlib_buffer_t *b0;
147  interface_output_trace_t *t0;
148 
149  bi0 = from[0];
150 
151  b0 = vlib_get_buffer (vm, bi0);
152 
153  if (b0->flags & VLIB_BUFFER_IS_TRACED)
154  {
155  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
156  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
157  t0->flags = b0->flags;
159  sizeof (t0->data));
160  }
161  from += 1;
162  n_left -= 1;
163  }
164 }
165 
168 {
169  vnet_calc_checksums_inline (vm, b, b->flags & VNET_BUFFER_F_IS_IP4,
170  b->flags & VNET_BUFFER_F_IS_IP6);
171 }
172 
177  u32 n_left, int do_tx_offloads,
178  int arc_or_subif)
179 {
180  u32 n_bytes = 0;
181  u32 n_bytes0, n_bytes1, n_bytes2, n_bytes3;
182  u32 ti = vm->thread_index;
183 
184  while (n_left >= 8)
185  {
186  u32 or_flags;
187 
188  /* Prefetch next iteration. */
189  vlib_prefetch_buffer_header (b[4], LOAD);
190  vlib_prefetch_buffer_header (b[5], LOAD);
191  vlib_prefetch_buffer_header (b[6], LOAD);
192  vlib_prefetch_buffer_header (b[7], LOAD);
193 
194  if (do_tx_offloads)
195  or_flags = b[0]->flags | b[1]->flags | b[2]->flags | b[3]->flags;
196 
197  /* Be grumpy about zero length buffers for benefit of
198  driver tx function. */
199  ASSERT (b[0]->current_length > 0);
200  ASSERT (b[1]->current_length > 0);
201  ASSERT (b[2]->current_length > 0);
202  ASSERT (b[3]->current_length > 0);
203 
204  n_bytes += n_bytes0 = vlib_buffer_length_in_chain (vm, b[0]);
205  n_bytes += n_bytes1 = vlib_buffer_length_in_chain (vm, b[1]);
206  n_bytes += n_bytes2 = vlib_buffer_length_in_chain (vm, b[2]);
207  n_bytes += n_bytes3 = vlib_buffer_length_in_chain (vm, b[3]);
208 
209  if (arc_or_subif)
210  {
211  u32 tx_swif0, tx_swif1, tx_swif2, tx_swif3;
212  tx_swif0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
213  tx_swif1 = vnet_buffer (b[1])->sw_if_index[VLIB_TX];
214  tx_swif2 = vnet_buffer (b[2])->sw_if_index[VLIB_TX];
215  tx_swif3 = vnet_buffer (b[3])->sw_if_index[VLIB_TX];
216 
217  /* update vlan subif tx counts, if required */
218  if (PREDICT_FALSE (tx_swif0 != sw_if_index))
219  vlib_increment_combined_counter (ccm, ti, tx_swif0, 1, n_bytes0);
220 
221  if (PREDICT_FALSE (tx_swif1 != sw_if_index))
222  vlib_increment_combined_counter (ccm, ti, tx_swif1, 1, n_bytes1);
223 
224  if (PREDICT_FALSE (tx_swif2 != sw_if_index))
225  vlib_increment_combined_counter (ccm, ti, tx_swif2, 1, n_bytes2);
226 
227  if (PREDICT_FALSE (tx_swif3 != sw_if_index))
228  vlib_increment_combined_counter (ccm, ti, tx_swif3, 1, n_bytes3);
229 
230  if (PREDICT_FALSE (config_index != ~0))
231  {
232  vnet_buffer (b[0])->feature_arc_index = arc;
234  vnet_buffer (b[1])->feature_arc_index = arc;
236  vnet_buffer (b[2])->feature_arc_index = arc;
238  vnet_buffer (b[3])->feature_arc_index = arc;
240  }
241  }
242 
243  if (do_tx_offloads && (or_flags & VNET_BUFFER_F_OFFLOAD))
244  {
249  }
250 
251  n_left -= 4;
252  b += 4;
253  }
254 
255  while (n_left)
256  {
257  /* Be grumpy about zero length buffers for benefit of
258  driver tx function. */
259  ASSERT (b[0]->current_length > 0);
260 
261  n_bytes += n_bytes0 = vlib_buffer_length_in_chain (vm, b[0]);
262 
263  if (arc_or_subif)
264  {
265  u32 tx_swif0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
266 
267  if (PREDICT_FALSE (config_index != ~0))
268  {
269  vnet_buffer (b[0])->feature_arc_index = arc;
271  }
272 
273  if (PREDICT_FALSE (tx_swif0 != sw_if_index))
274  vlib_increment_combined_counter (ccm, ti, tx_swif0, 1, n_bytes0);
275  }
276 
277  if (do_tx_offloads)
279 
280  n_left -= 1;
281  b += 1;
282  }
283 
284  return n_bytes;
285 }
286 
289  int sw_if_index_from_buffer)
290 {
291  vnet_main_t *vnm = vnet_get_main ();
292  u32 n_left_from, *from;
294  vnet_pcap_t *pp = &vnm->pcap;
295 
296  if (PREDICT_TRUE (pp->pcap_tx_enable == 0))
297  return;
298 
299  if (sw_if_index_from_buffer == 0)
300  {
301  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
302  sw_if_index = rt->sw_if_index;
303  }
304  else
305  sw_if_index = ~0;
306 
307  n_left_from = frame->n_vectors;
308  from = vlib_frame_vector_args (frame);
309 
310  while (n_left_from > 0)
311  {
312  u32 bi0 = from[0];
313  vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0);
314  from++;
315  n_left_from--;
316 
317  if (sw_if_index_from_buffer)
318  sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
319 
320  if (vnet_is_packet_pcaped (pp, b0, sw_if_index))
321  pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
322  }
323 }
324 
328 {
329  if (r)
330  clib_memcpy_fast (tf, &r->frame, sizeof (vnet_hw_if_tx_frame_t));
331 }
332 
335  vnet_hw_interface_t *hi, u32 *from, u32 n_vectors)
336 {
337  u32 next_index = VNET_INTERFACE_OUTPUT_NEXT_TX;
339  u32 n_free, n_copy, *to;
341  vlib_frame_t *f;
342 
343  ASSERT (n_vectors <= VLIB_FRAME_SIZE);
344 
347 
348  f = vlib_get_next_frame_internal (vm, node, next_index, 0);
349  tf = vlib_frame_scalar_args (f);
350 
351  if (f->n_vectors > 0 && (r == 0 || tf->queue_id == r->frame.queue_id))
352  {
353  /* append current next frame */
354  n_free = VLIB_FRAME_SIZE - f->n_vectors;
355  n_copy = clib_min (n_vectors, n_free);
356  n_vectors -= n_copy;
357  to = vlib_frame_vector_args (f);
358  to += f->n_vectors;
359  }
360  else
361  {
362  if (f->n_vectors > 0)
363  {
364  /* current frame doesn't fit - grab empty one */
365  f = vlib_get_next_frame_internal (vm, node, next_index, 1);
366  tf = vlib_frame_scalar_args (f);
367  }
368 
369  /* empty frame - store scalar data */
371  to = vlib_frame_vector_args (f);
372  n_free = VLIB_FRAME_SIZE;
373  n_copy = n_vectors;
374  n_vectors = 0;
375  }
376 
377  vlib_buffer_copy_indices (to, from, n_copy);
378  vlib_put_next_frame (vm, node, next_index, n_free - n_copy);
379 
380  if (n_vectors == 0)
381  return;
382 
383  /* we have more indices to store, take empty frame */
384  from += n_copy;
385  f = vlib_get_next_frame_internal (vm, node, next_index, 1);
387  vlib_buffer_copy_indices (vlib_frame_vector_args (f), from, n_vectors);
388  vlib_put_next_frame (vm, node, next_index, VLIB_FRAME_SIZE - n_vectors);
389 }
390 
391 VLIB_NODE_FN (vnet_interface_output_node)
393 {
394  vnet_main_t *vnm = vnet_get_main ();
399  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
401  u32 n_bytes, n_buffers = frame->n_vectors;
403  u32 sw_if_index = rt->sw_if_index;
407  int arc_or_subif = 0;
408  int do_tx_offloads = 0;
409  u32 *from;
410 
411  if (node->flags & VLIB_NODE_FLAG_TRACE)
413 
414  from = vlib_frame_vector_args (frame);
415 
416  if (rt->is_deleted)
417  return vlib_error_drop_buffers (
418  vm, node, from,
419  /* buffer stride */ 1, n_buffers, VNET_INTERFACE_OUTPUT_NEXT_DROP,
421 
423  0 /* sw_if_index_from_buffer */ );
424 
425  vlib_get_buffers (vm, from, bufs, n_buffers);
426 
427  si = vnet_get_sw_interface (vnm, sw_if_index);
428  hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
429 
432  {
434 
437  vlib_increment_simple_counter (cm, ti, sw_if_index, n_buffers);
438 
439  return vlib_error_drop_buffers (
440  vm, node, from,
441  /* buffer stride */ 1, n_buffers, VNET_INTERFACE_OUTPUT_NEXT_DROP,
443  }
444 
445  /* interface-output feature arc handling */
446  if (PREDICT_FALSE (vnet_have_features (arc, sw_if_index)))
447  {
451  vnet_get_config_data (&fcm->config_main, &config_index, &next_index, 0);
452  arc_or_subif = 1;
453  }
455  arc_or_subif = 1;
456 
458 
460  do_tx_offloads = 1;
461 
462  if (do_tx_offloads == 0 && arc_or_subif == 0)
464  vm, sw_if_index, ccm, bufs, config_index, arc, n_buffers, 0, 0);
465  else if (do_tx_offloads == 0 && arc_or_subif == 1)
467  vm, sw_if_index, ccm, bufs, config_index, arc, n_buffers, 0, 1);
468  else if (do_tx_offloads == 1 && arc_or_subif == 0)
470  vm, sw_if_index, ccm, bufs, config_index, arc, n_buffers, 1, 0);
471  else
473  vm, sw_if_index, ccm, bufs, config_index, arc, n_buffers, 1, 1);
474 
475  from = vlib_frame_vector_args (frame);
476  if (PREDICT_TRUE (next_index == VNET_INTERFACE_OUTPUT_NEXT_TX))
477  {
478  enqueu_to_tx_node (vm, node, hi, from, frame->n_vectors);
479  }
480  else
481  {
482  vlib_buffer_enqueue_to_single_next (vm, node, from, next_index,
483  frame->n_vectors);
484  }
485 
486  /* Update main interface stats. */
487  vlib_increment_combined_counter (ccm, ti, sw_if_index, n_buffers, n_bytes);
488  return n_buffers;
489 }
490 
491 VLIB_REGISTER_NODE (vnet_interface_output_node) = {
492  .name = "interface-output-template",
493  .vector_size = sizeof (u32),
494 };
495 
496 /* Use buffer's sw_if_index[VNET_TX] to choose output interface. */
497 VLIB_NODE_FN (vnet_per_buffer_interface_output_node) (vlib_main_t * vm,
499  node,
501 {
502  vnet_main_t *vnm = vnet_get_main ();
503  u32 n_left_to_next, *from, *to_next;
505 
507  1 /* sw_if_index_from_buffer */ );
508 
509  n_left_from = frame->n_vectors;
510 
511  from = vlib_frame_vector_args (frame);
512  next_index = node->cached_next_index;
513 
514  while (n_left_from > 0)
515  {
516  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
517 
518  while (n_left_from >= 4 && n_left_to_next >= 2)
519  {
520  u32 bi0, bi1, next0, next1;
521  vlib_buffer_t *b0, *b1;
522  vnet_hw_interface_t *hi0, *hi1;
523 
524  /* Prefetch next iteration. */
525  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
526  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
527 
528  bi0 = from[0];
529  bi1 = from[1];
530  to_next[0] = bi0;
531  to_next[1] = bi1;
532  from += 2;
533  to_next += 2;
534  n_left_to_next -= 2;
535  n_left_from -= 2;
536 
537  b0 = vlib_get_buffer (vm, bi0);
538  b1 = vlib_get_buffer (vm, bi1);
539 
540  hi0 =
542  vnet_buffer (b0)->sw_if_index
543  [VLIB_TX]);
544  hi1 =
546  vnet_buffer (b1)->sw_if_index
547  [VLIB_TX]);
548 
549  next0 = hi0->output_node_next_index;
550  next1 = hi1->output_node_next_index;
551 
552  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
553  n_left_to_next, bi0, bi1, next0,
554  next1);
555  }
556 
557  while (n_left_from > 0 && n_left_to_next > 0)
558  {
559  u32 bi0, next0;
560  vlib_buffer_t *b0;
561  vnet_hw_interface_t *hi0;
562 
563  bi0 = from[0];
564  to_next[0] = bi0;
565  from += 1;
566  to_next += 1;
567  n_left_to_next -= 1;
568  n_left_from -= 1;
569 
570  b0 = vlib_get_buffer (vm, bi0);
571 
572  hi0 =
574  vnet_buffer (b0)->sw_if_index
575  [VLIB_TX]);
576 
577  next0 = hi0->output_node_next_index;
578 
579  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
580  n_left_to_next, bi0, next0);
581  }
582 
583  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
584  }
585 
586  return frame->n_vectors;
587 }
588 
589 typedef struct vnet_error_trace_t_
590 {
594  u8 pad[2];
596  ip46_address_t src, dst;
598 
599 static u8 *
600 format_vnet_error_trace (u8 * s, va_list * va)
601 {
602  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
603  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
604  vnet_error_trace_t *t = va_arg (*va, vnet_error_trace_t *);
605 
606  /* Normal, non-catchup trace */
607  if (t->details_valid == 0)
608  {
609  s = format (s, "rx:%U", format_vnet_sw_if_index_name,
610  vnet_get_main (), t->sw_if_index);
611  }
612  else if (t->details_valid == 1)
613  {
614  /* The trace capture code didn't understant the mactype */
615  s = format (s, "mactype 0x%4x (not decoded)", t->mactype);
616  }
617  else if (t->details_valid == 2)
618  {
619  /* Dump the src/dst addresses */
620  if (t->is_ip6 == 0)
621  s = format (s, "IP4: %U -> %U",
622  format_ip4_address, &t->src.ip4,
623  format_ip4_address, &t->dst.ip4);
624  else
625  s = format (s, "IP6: %U -> %U",
626  format_ip6_address, &t->src.ip6,
627  format_ip6_address, &t->dst.ip6);
628  }
629  return s;
630 }
631 
632 static void
635 {
636  u32 n_left, *buffers;
637 
638  buffers = vlib_frame_vector_args (frame);
639  n_left = frame->n_vectors;
640 
641  while (n_left >= 4)
642  {
643  u32 bi0, bi1;
644  vlib_buffer_t *b0, *b1;
645  vnet_error_trace_t *t0, *t1;
646 
647  /* Prefetch next iteration. */
648  vlib_prefetch_buffer_with_index (vm, buffers[2], LOAD);
649  vlib_prefetch_buffer_with_index (vm, buffers[3], LOAD);
650 
651  bi0 = buffers[0];
652  bi1 = buffers[1];
653 
654  b0 = vlib_get_buffer (vm, bi0);
655  b1 = vlib_get_buffer (vm, bi1);
656 
657  if (b0->flags & VLIB_BUFFER_IS_TRACED)
658  {
659  t0 = vlib_add_trace (vm, node, b0,
661  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
662  t0->details_valid = 0;
663  }
664  if (b1->flags & VLIB_BUFFER_IS_TRACED)
665  {
666  t1 = vlib_add_trace (vm, node, b1,
668  t1->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX];
669  t1->details_valid = 0;
670  }
671  buffers += 2;
672  n_left -= 2;
673  }
674 
675  while (n_left >= 1)
676  {
677  u32 bi0;
678  vlib_buffer_t *b0;
679  vnet_error_trace_t *t0;
680 
681  bi0 = buffers[0];
682 
683  b0 = vlib_get_buffer (vm, bi0);
684 
685  if (b0->flags & VLIB_BUFFER_IS_TRACED)
686  {
687  t0 = vlib_add_trace (vm, node, b0,
689  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
690  t0->details_valid = 0;
691  }
692  buffers += 1;
693  n_left -= 1;
694  }
695 }
696 
697 typedef enum
698 {
703 
704 static void
707 {
708  /* Can we safely rewind the buffer? If not, fagedaboudit */
709  if (b->flags & VNET_BUFFER_F_L2_HDR_OFFSET_VALID)
710  {
712  ip4_header_t *ip4;
713  ip6_header_t *ip6;
714  ethernet_header_t *eh;
715  i16 delta;
716 
717  t = vlib_add_trace (vm, node, b, sizeof (*t));
718  delta = vnet_buffer (b)->l2_hdr_offset - b->current_data;
719  vlib_buffer_advance (b, delta);
720 
721  eh = vlib_buffer_get_current (b);
722  /* Save mactype */
723  t->mactype = clib_net_to_host_u16 (eh->type);
724  t->details_valid = 1;
725  switch (t->mactype)
726  {
727  case ETHERNET_TYPE_IP4:
728  ip4 = (void *) (eh + 1);
729  t->details_valid = 2;
730  t->is_ip6 = 0;
731  t->src.ip4.as_u32 = ip4->src_address.as_u32;
732  t->dst.ip4.as_u32 = ip4->dst_address.as_u32;
733  break;
734 
735  case ETHERNET_TYPE_IP6:
736  ip6 = (void *) (eh + 1);
737  t->details_valid = 2;
738  t->is_ip6 = 1;
739  clib_memcpy_fast (t->src.as_u8, ip6->src_address.as_u8,
740  sizeof (ip6_address_t));
741  clib_memcpy_fast (t->dst.as_u8, ip6->dst_address.as_u8,
742  sizeof (ip6_address_t));
743  break;
744 
745  default:
746  /* Dunno, do nothing, leave details_valid alone */
747  break;
748  }
749  /* Restore current data (probably unnecessary) */
750  vlib_buffer_advance (b, -delta);
751  }
752 }
753 
756  vlib_node_runtime_t * node,
758  vnet_error_disposition_t disposition)
759 {
761  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
762  u32 sw_if_indices[VLIB_FRAME_SIZE];
765  u32 n_trace;
766  vnet_main_t *vnm;
767 
768  vnm = vnet_get_main ();
769  thread_index = vm->thread_index;
770  from = vlib_frame_vector_args (frame);
771  n_left = frame->n_vectors;
772  b = bufs;
773  sw_if_index = sw_if_indices;
774 
775  vlib_get_buffers (vm, from, bufs, n_left);
776 
777  /* "trace add error-drop NNN?" */
778  if (PREDICT_FALSE ((n_trace = vlib_get_trace_count (vm, node))))
779  {
780  /* If pkts aren't otherwise traced... */
781  if ((node->flags & VLIB_NODE_FLAG_TRACE) == 0)
782  {
783  /* Trace them from here */
784  node->flags |= VLIB_NODE_FLAG_TRACE;
785  while (n_trace && n_left)
786  {
787  if (PREDICT_TRUE
788  (vlib_trace_buffer (vm, node, 0 /* next_index */ , b[0],
789  0 /* follow chain */ )))
790  {
791  /*
792  * Here we have a wireshark dissector problem.
793  * Packets may be well-formed, or not. We
794  * must not blow chunks in any case.
795  *
796  * Try to produce trace records which will help
797  * folks understand what's going on.
798  */
799  drop_catchup_trace (vm, node, b[0]);
800  n_trace--;
801  }
802  n_left--;
803  b++;
804  }
805  }
806 
807  vlib_set_trace_count (vm, node, n_trace);
808  b = bufs;
809  n_left = frame->n_vectors;
810  }
811 
812  if (node->flags & VLIB_NODE_FLAG_TRACE)
813  interface_trace_buffers (vm, node, frame);
814 
815  /* All going to drop regardless, this is just a counting exercise */
816  clib_memset (nexts, 0, sizeof (nexts));
817 
819  (disposition == VNET_ERROR_DISPOSITION_PUNT
822 
823  /* collect the array of interfaces first ... */
824  while (n_left >= 4)
825  {
826  if (n_left >= 12)
827  {
828  /* Prefetch 8 ahead - there's not much going on in each iteration */
829  vlib_prefetch_buffer_header (b[4], LOAD);
830  vlib_prefetch_buffer_header (b[5], LOAD);
831  vlib_prefetch_buffer_header (b[6], LOAD);
832  vlib_prefetch_buffer_header (b[7], LOAD);
833  }
834  sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
835  sw_if_index[1] = vnet_buffer (b[1])->sw_if_index[VLIB_RX];
836  sw_if_index[2] = vnet_buffer (b[2])->sw_if_index[VLIB_RX];
837  sw_if_index[3] = vnet_buffer (b[3])->sw_if_index[VLIB_RX];
838 
839  sw_if_index += 4;
840  n_left -= 4;
841  b += 4;
842  }
843  while (n_left)
844  {
845  sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
846 
847  sw_if_index += 1;
848  n_left -= 1;
849  b += 1;
850  }
851 
852  /* ... then count against them in blocks */
853  n_left = frame->n_vectors;
854 
855  while (n_left)
856  {
857  vnet_sw_interface_t *sw_if0;
858  u16 off, count;
859 
860  off = frame->n_vectors - n_left;
861 
862  sw_if_index = sw_if_indices + off;
863 
864  count = clib_count_equal_u32 (sw_if_index, n_left);
865  n_left -= count;
866 
867  vlib_increment_simple_counter (cm, thread_index, sw_if_index[0], count);
868 
869  /* Increment super-interface drop/punt counters for
870  sub-interfaces. */
871  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index[0]);
872  if (sw_if0->sup_sw_if_index != sw_if_index[0])
874  (cm, thread_index, sw_if0->sup_sw_if_index, count);
875  }
876 
877  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
878 
879  return frame->n_vectors;
880 }
881 
882 static inline void
885  vnet_pcap_t * pp, vlib_frame_t * f)
886 {
887  u32 *from;
888  u32 n_left = f->n_vectors;
889  vlib_buffer_t *b0, *p1;
890  u32 bi0;
891  i16 save_current_data;
892  u16 save_current_length;
893  vlib_error_main_t *em = &vm->error_main;
894 
895  from = vlib_frame_vector_args (f);
896 
897  while (n_left > 0)
898  {
899  if (PREDICT_TRUE (n_left > 1))
900  {
901  p1 = vlib_get_buffer (vm, from[1]);
902  vlib_prefetch_buffer_header (p1, LOAD);
903  }
904 
905  bi0 = from[0];
906  b0 = vlib_get_buffer (vm, bi0);
907  from++;
908  n_left--;
909 
910  /* See if we're pointedly ignoring this specific error */
911  if (im->pcap_drop_filter_hash
912  && hash_get (im->pcap_drop_filter_hash, b0->error))
913  continue;
914 
915  if (!vnet_is_packet_pcaped (pp, b0, ~0))
916  continue; /* not matching, skip */
917 
918  /* Trace all drops, or drops received on a specific interface */
919  save_current_data = b0->current_data;
920  save_current_length = b0->current_length;
921 
922  /*
923  * Typically, we'll need to rewind the buffer
924  * if l2_hdr_offset is valid, make sure to rewind to the start of
925  * the L2 header. This may not be the buffer start in case we pop-ed
926  * vlan tags.
927  * Otherwise, rewind to buffer start and hope for the best.
928  */
929  if (b0->flags & VNET_BUFFER_F_L2_HDR_OFFSET_VALID)
930  {
931  if (b0->current_data > vnet_buffer (b0)->l2_hdr_offset)
932  vlib_buffer_advance (b0, vnet_buffer (b0)->l2_hdr_offset -
933  b0->current_data);
934  }
935  else if (b0->current_data > 0)
936  {
938  }
939 
940  {
941  vlib_buffer_t *last = b0;
942  u32 error_node_index;
943  int drop_string_len;
944  vlib_node_t *n;
945  /* Length of the error string */
946  int error_string_len =
947  clib_strnlen (em->counters_heap[b0->error].name, 128);
948 
949  /* Dig up the drop node */
950  error_node_index = vm->node_main.node_by_error[b0->error];
951  n = vlib_get_node (vm, error_node_index);
952 
953  /* Length of full drop string, w/ "nodename: " prepended */
954  drop_string_len = error_string_len + vec_len (n->name) + 2;
955 
956  /* Find the last buffer in the chain */
957  while (last->flags & VLIB_BUFFER_NEXT_PRESENT)
958  last = vlib_get_buffer (vm, last->next_buffer);
959 
960  /*
961  * Append <nodename>: <error-string> to the capture,
962  * only if we can do that without allocating a new buffer.
963  */
964  if (PREDICT_TRUE ((last->current_data + last->current_length) <
965  (VLIB_BUFFER_DEFAULT_DATA_SIZE - drop_string_len)))
966  {
967  clib_memcpy_fast (last->data + last->current_data +
968  last->current_length,
969  n->name, vec_len (n->name));
970  clib_memcpy_fast (last->data + last->current_data +
971  last->current_length + vec_len (n->name),
972  ": ", 2);
973  clib_memcpy_fast (last->data + last->current_data +
974  last->current_length + vec_len (n->name) + 2,
975  em->counters_heap[b0->error].name,
976  error_string_len);
977  last->current_length += drop_string_len;
978  b0->flags &= ~(VLIB_BUFFER_TOTAL_LENGTH_VALID);
979  pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
980  last->current_length -= drop_string_len;
981  b0->current_data = save_current_data;
982  b0->current_length = save_current_length;
983  continue;
984  }
985  }
986 
987  /*
988  * Didn't have space in the last buffer, here's the dropped
989  * packet as-is
990  */
991  pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
992 
993  b0->current_data = save_current_data;
994  b0->current_length = save_current_length;
995  }
996 }
997 
998 #ifndef CLIB_MARCH_VARIANT
999 void
1000 vnet_pcap_drop_trace_filter_add_del (u32 error_index, int is_add)
1001 {
1003 
1004  if (im->pcap_drop_filter_hash == 0)
1005  im->pcap_drop_filter_hash = hash_create (0, sizeof (uword));
1006 
1007  if (is_add)
1008  hash_set (im->pcap_drop_filter_hash, error_index, 1);
1009  else
1010  hash_unset (im->pcap_drop_filter_hash, error_index);
1011 }
1012 #endif /* CLIB_MARCH_VARIANT */
1013 
1014 VLIB_NODE_FN (interface_drop) (vlib_main_t * vm,
1016  vlib_frame_t * frame)
1017 {
1018  vnet_main_t *vnm = vnet_get_main ();
1020  vnet_pcap_t *pp = &vnm->pcap;
1021 
1022  if (PREDICT_FALSE (pp->pcap_drop_enable))
1023  pcap_drop_trace (vm, im, pp, frame);
1024 
1026 }
1027 
1028 VLIB_NODE_FN (interface_punt) (vlib_main_t * vm,
1030  vlib_frame_t * frame)
1031 {
1033 }
1034 
1035 /* *INDENT-OFF* */
1036 VLIB_REGISTER_NODE (interface_drop) = {
1037  .name = "error-drop",
1038  .vector_size = sizeof (u32),
1039  .format_trace = format_vnet_error_trace,
1041  .n_next_nodes = 1,
1042  .next_nodes = {
1043  [0] = "drop",
1044  },
1045 };
1046 /* *INDENT-ON* */
1047 
1048 /* *INDENT-OFF* */
1049 VLIB_REGISTER_NODE (interface_punt) = {
1050  .name = "error-punt",
1051  .vector_size = sizeof (u32),
1052  .format_trace = format_vnet_error_trace,
1054  .n_next_nodes = 1,
1055  .next_nodes = {
1056  [0] = "punt",
1057  },
1058 };
1059 /* *INDENT-ON* */
1060 
1061 VLIB_REGISTER_NODE (vnet_per_buffer_interface_output_node) = {
1062  .name = "interface-output",
1063  .vector_size = sizeof (u32),
1064 };
1065 
1066 VLIB_NODE_FN (vnet_interface_output_arc_end_node)
1068 {
1069  vnet_main_t *vnm = vnet_get_main ();
1075  u32 sw_if_indices[VLIB_FRAME_SIZE], *sw_if_index = sw_if_indices;
1076  u64 used_elts[VLIB_FRAME_SIZE / 64] = {};
1077  u64 mask[VLIB_FRAME_SIZE / 64] = {};
1079  u16 next_index;
1081 
1082  from = vlib_frame_vector_args (frame);
1083  n_left = frame->n_vectors;
1084  vlib_get_buffers (vm, from, bufs, n_left);
1085 
1086  while (n_left >= 8)
1087  {
1088  vlib_prefetch_buffer_header (b[4], LOAD);
1089  vlib_prefetch_buffer_header (b[5], LOAD);
1090  vlib_prefetch_buffer_header (b[6], LOAD);
1091  vlib_prefetch_buffer_header (b[7], LOAD);
1092  sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
1093  sw_if_index[1] = vnet_buffer (b[1])->sw_if_index[VLIB_TX];
1094  sw_if_index[2] = vnet_buffer (b[2])->sw_if_index[VLIB_TX];
1095  sw_if_index[3] = vnet_buffer (b[3])->sw_if_index[VLIB_TX];
1096 
1097  b += 4;
1098  sw_if_index += 4;
1099  n_left -= 4;
1100  }
1101 
1102  while (n_left)
1103  {
1104  sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
1105  b++;
1106  sw_if_index++;
1107  n_left--;
1108  }
1109 
1110  n_left = frame->n_vectors;
1111  swif = sw_if_indices[0];
1112  off = 0;
1113 
1114  /* a bit ugly but it allows us to reuse stack space for temporary store
1115  * which may also improve memory latency */
1116  tmp = (u32 *) bufs;
1117 
1118 more:
1119  next_index = vec_elt (im->if_out_arc_end_next_index_by_sw_if_index, swif);
1120  hi = vnet_get_sup_hw_interface (vnm, swif);
1123  f = vlib_get_next_frame_internal (vm, node, next_index, 0);
1124  tf = vlib_frame_scalar_args (f);
1125 
1126  if (f->n_vectors > 0 && (r == 0 || r->frame.queue_id == tf->queue_id))
1127  {
1128  /* append frame */
1129  n_free = VLIB_FRAME_SIZE - f->n_vectors;
1130  if (n_free >= f->n_vectors)
1131  to = (u32 *) vlib_frame_vector_args (f) + f->n_vectors;
1132  else
1133  to = tmp;
1134  }
1135  else
1136  {
1137  if (f->n_vectors > 0)
1138  {
1139  /* current frame doesn't fit - grab empty one */
1140  f = vlib_get_next_frame_internal (vm, node, next_index, 1);
1141  tf = vlib_frame_scalar_args (f);
1142  }
1143 
1144  /* empty frame - store scalar data */
1146  n_free = VLIB_FRAME_SIZE;
1147  to = vlib_frame_vector_args (f);
1148  }
1149 
1150  /* compare and compress based on comparison mask */
1151  clib_mask_compare_u32 (swif, sw_if_indices, mask, frame->n_vectors);
1152  n_comp = clib_compress_u32 (to, from, mask, frame->n_vectors);
1153 
1154  if (tmp != to)
1155  {
1156  /* indices already written to frame, just close it */
1157  vlib_put_next_frame (vm, node, next_index, n_free - n_comp);
1158  }
1159  else if (n_free >= n_comp)
1160  {
1161  /* enough space in the existing frame */
1162  to = (u32 *) vlib_frame_vector_args (f) + f->n_vectors;
1163  vlib_buffer_copy_indices (to, tmp, n_comp);
1164  vlib_put_next_frame (vm, node, next_index, n_free - n_comp);
1165  }
1166  else
1167  {
1168  /* full frame */
1169  to = (u32 *) vlib_frame_vector_args (f) + f->n_vectors;
1170  vlib_buffer_copy_indices (to, tmp, n_free);
1171  vlib_put_next_frame (vm, node, next_index, 0);
1172 
1173  /* second frame */
1174  u32 n_frame2 = n_comp - n_free;
1175  f = vlib_get_next_frame_internal (vm, node, next_index, 1);
1176  to = vlib_frame_vector_args (f);
1177  vlib_buffer_copy_indices (to, tmp + n_free, n_frame2);
1178  tf = vlib_frame_scalar_args (f);
1180  vlib_put_next_frame (vm, node, next_index, VLIB_FRAME_SIZE - n_frame2);
1181  }
1182 
1183  n_left -= n_comp;
1184  if (n_left)
1185  {
1186  /* store comparison mask so we can find next unused element */
1187  for (int i = 0; i < ARRAY_LEN (used_elts); i++)
1188  used_elts[i] |= mask[i];
1189 
1190  /* fine first unused sw_if_index by scanning trough used_elts bitmap */
1191  while (PREDICT_FALSE (used_elts[off] == ~0))
1192  off++;
1193 
1194  swif =
1195  sw_if_indices[(off << 6) + count_trailing_zeros (~used_elts[off])];
1196  goto more;
1197  }
1198 
1199  return frame->n_vectors;
1200 }
1201 
1202 VLIB_REGISTER_NODE (vnet_interface_output_arc_end_node) = {
1203  .name = "interface-output-arc-end",
1204  .vector_size = sizeof (u32),
1205  .n_next_nodes = 1,
1206  .next_nodes = {
1207  [0] = "error-drop",
1208  },
1209 };
1210 
1211 VNET_FEATURE_ARC_INIT (interface_output, static) = {
1212  .arc_name = "interface-output",
1213  .start_nodes = VNET_FEATURES (0),
1214  .last_in_arc = "interface-output-arc-end",
1216 };
1217 
1218 VNET_FEATURE_INIT (span_tx, static) = {
1219  .arc_name = "interface-output",
1220  .node_name = "span-output",
1221  .runs_before = VNET_FEATURES ("interface-output-arc-end"),
1222 };
1223 
1224 VNET_FEATURE_INIT (ipsec_if_tx, static) = {
1225  .arc_name = "interface-output",
1226  .node_name = "ipsec-if-output",
1227  .runs_before = VNET_FEATURES ("interface-output-arc-end"),
1228 };
1229 
1230 VNET_FEATURE_INIT (interface_output_arc_end, static) = {
1231  .arc_name = "interface-output",
1232  .node_name = "interface-output-arc-end",
1233  .runs_before = 0,
1234 };
1235 
1236 #ifndef CLIB_MARCH_VARIANT
1237 clib_error_t *
1239  u32 hw_if_index,
1240  u32 is_create)
1241 {
1242  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1243  u32 next_index;
1244 
1245  if (hi->output_node_index == 0)
1246  return 0;
1247 
1248  next_index = vlib_node_add_next
1249  (vnm->vlib_main, vnet_per_buffer_interface_output_node.index,
1250  hi->output_node_index);
1252 
1253  return 0;
1254 }
1255 
1258 
1259 void
1261  u32 hw_if_index, u32 node_index)
1262 {
1263  ASSERT (node_index);
1264  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1265  u32 next_index = vlib_node_add_next
1266  (vnm->vlib_main, vnet_per_buffer_interface_output_node.index, node_index);
1269 }
1270 #endif /* CLIB_MARCH_VARIANT */
1271 
1272 /*
1273  * fd.io coding-style-patch-verification: ON
1274  *
1275  * Local Variables:
1276  * eval: (c-set-style "gnu")
1277  * End:
1278  */
vnet_hw_if_output_node_runtime_t * output_node_thread_runtimes
Definition: interface.h:673
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:133
pcap_main_t pcap_main
Definition: vnet.h:71
vnet_hw_if_tx_frame_t frame
Definition: interface.h:632
vnet_hw_if_tx_frame_t * tf
int arc_or_subif
clib_mask_compare_u32(swif, sw_if_indices, mask, frame->n_vectors)
VNET_FEATURE_ARC_INIT(interface_output, static)
#define hash_set(h, key, value)
Definition: hash.h:255
#define clib_min(x, y)
Definition: clib.h:342
#define CLIB_UNUSED(x)
Definition: clib.h:90
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 ...
u32 n_free
static u32 vlib_get_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt)
Definition: trace_funcs.h:212
#define hash_unset(h, key)
Definition: hash.h:261
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
u8 runtime_data[0]
Function dependent node-runtime data.
Definition: node.h:506
u32 sw_if_indices[VLIB_FRAME_SIZE]
vlib_frame_t * vlib_get_next_frame_internal(vlib_main_t *vm, vlib_node_runtime_t *node, u32 next_index, u32 allocate_new_next_frame)
Definition: main.c:384
ip4_address_t src_address
Definition: ip4_packet.h:125
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
u32 max_bytes_per_pkt
Definition: vnet.h:69
static_always_inline u32 clib_compress_u32(u32 *dst, u32 *src, u64 *mask, u32 n_elts)
Compare array of 32-bit elemments into destination array based on mask.
Definition: vector_funcs.h:210
vlib_buffer_copy_indices(to, tmp, n_free)
vnet_interface_main_t interface_main
Definition: vnet.h:81
u32 n_bytes
u32 thread_index
#define PREDICT_TRUE(x)
Definition: clib.h:125
VNET_INTERFACE_OUTPUT_NEXT_DROP
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:119
unsigned long u64
Definition: types.h:89
u16 nexts[VLIB_FRAME_SIZE]
vlib_increment_combined_counter(ccm, ti, sw_if_index, n_buffers, n_bytes)
vnet_feature_config_main_t * cm
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
#define VLIB_NODE_FLAG_TRACE_SUPPORTED
Definition: node.h:296
vnet_hw_interface_capabilities_t caps
Definition: interface.h:645
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u32 thread_index
Definition: main.h:213
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:122
char * name
Definition: error.h:56
u32 * from
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:73
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
uword * sub_interface_sw_if_index_by_id
Definition: interface.h:703
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 increment)
Increment a simple counter.
Definition: counter.h:74
vlib_get_buffers(vm, from, bufs, n_buffers)
static_always_inline int vnet_have_features(u8 arc, u32 sw_if_index)
Definition: feature.h:251
vnet_hw_interface_t * hi
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:433
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:1177
unsigned char u8
Definition: types.h:56
#define count_trailing_zeros(x)
Definition: clib.h:161
u8 data[128]
Definition: ipsec_types.api:92
u16 * if_out_arc_end_next_index_by_sw_if_index
Definition: interface.h:1046
vlib_combined_counter_main_t * ccm
unsigned int u32
Definition: types.h:88
vlib_frame_t * f
static_always_inline void store_tx_frame_scalar_data(vnet_hw_if_output_node_runtime_t *r, vnet_hw_if_tx_frame_t *tf)
format_function_t format_ip4_address
Definition: format.h:73
if(node->flags &VLIB_NODE_FLAG_TRACE) vnet_interface_output_trace(vm
#define static_always_inline
Definition: clib.h:112
uword * pcap_drop_filter_hash
Definition: interface.h:1032
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:507
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
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:1023
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
vlib_main_t vlib_node_runtime_t * node
description fragment has unexpected format
Definition: map.api:433
vnet_hw_interface_flags_t flags
Definition: interface.h:642
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:231
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static_always_inline void vlib_buffer_enqueue_to_single_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 next_index, u32 count)
Definition: buffer_node.h:348
u8 * format_hex_bytes(u8 *s, va_list *va)
Definition: std-formats.c:84
vnet_main_t * vnet_get_main(void)
vlib_buffer_enqueue_to_next(vm, node, from,(u16 *) nexts, frame->n_vectors)
A collection of simple counters.
Definition: counter.h:57
static_always_inline void vnet_interface_output_handle_offload(vlib_main_t *vm, vlib_buffer_t *b)
#define VLIB_FRAME_SIZE
Definition: node.h:369
vlib_main_t * vm
u8 arc
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:145
#define hash_get(h, key)
Definition: hash.h:249
format_function_t format_vnet_sw_interface_name
u32 * to
static_always_inline uword vnet_interface_output_node_inline(vlib_main_t *vm, u32 sw_if_index, vlib_combined_counter_main_t *ccm, vlib_buffer_t **b, u32 config_index, u8 arc, u32 n_left, int do_tx_offloads, int arc_or_subif)
vlib_main_t * vlib_main
Definition: vnet.h:111
u8 pcap_drop_enable
Definition: vnet.h:67
static u8 * format_vnet_error_trace(u8 *s, va_list *va)
vlib_error_main_t error_main
Definition: main.h:177
static void drop_catchup_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b)
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
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:153
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
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
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 * tmp
int do_tx_offloads
u32 * node_by_error
Definition: node.h:734
u8 data[128 - 2 *sizeof(u32)]
#define PREDICT_FALSE(x)
Definition: clib.h:124
vnet_sw_interface_flags_t flags
Definition: interface.h:872
vl_api_ip4_address_t ip4
Definition: one.api:376
vlib_buffer_t * bufs[VLIB_FRAME_SIZE]
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:1022
format_function_t * format_buffer
Definition: node.h:349
#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:395
static void interface_trace_buffers(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
u32 n_left
u32 config_index
u8 * name
Definition: node.h:254
u32 next_index
#define VNET_HW_INTERFACE_CAP_SUPPORTS_TX_CKSUM
Definition: interface.h:559
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u32 sw_if_index
u16 n_vectors
Definition: node.h:388
format_function_t format_ip6_address
Definition: format.h:91
u32 ti
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
u8 data[]
Packet data.
Definition: buffer.h:204
static void pcap_drop_trace(vlib_main_t *vm, vnet_interface_main_t *im, vnet_pcap_t *pp, vlib_frame_t *f)
static void * vlib_frame_scalar_args(vlib_frame_t *f)
Get pointer to frame scalar data.
Definition: node_funcs.h:315
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:302
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:156
#define ARRAY_LEN(x)
Definition: clib.h:70
#define hash_create(elts, value_bytes)
Definition: hash.h:696
vnet_pcap_t pcap
Definition: vnet.h:103
static uword hash_elts(void *v)
Definition: hash.h:118
#define ASSERT(truth)
vnet_sw_interface_t * si
u32 n_frame2
vlib_buffer_t ** b
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.
vlib_put_next_frame(vm, node, next_index, 0)
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:276
u32 n_buffers
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)
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
static_always_inline void enqueu_to_tx_node(vlib_main_t *vm, vlib_node_runtime_t *node, vnet_hw_interface_t *hi, u32 *from, u32 n_vectors)
vlib_error_desc_t * counters_heap
Definition: error.h:71
#define VNET_FEATURES(...)
Definition: feature.h:470
Use the vpp classifier to decide whether to capture packets.
VNET_HW_INTERFACE_ADD_DEL_FUNCTION(vnet_per_buffer_interface_output_hw_interface_add_del)
#define vec_elt(v, i)
Get vector value at index i.
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:149
vlib_node_main_t node_main
Definition: main.h:171
VLIB buffer representation.
Definition: buffer.h:111
u64 uword
Definition: types.h:112
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:1014
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
u32 swif
node node_index
A collection of combined counters.
Definition: counter.h:203
static_always_inline void vnet_calc_checksums_inline(vlib_main_t *vm, vlib_buffer_t *b, int is_ip4, int is_ip6)
u32 off
u32 n_comp
#define vnet_buffer(b)
Definition: buffer.h:437
static_always_inline int vnet_is_packet_pcaped(vnet_pcap_t *pp, vlib_buffer_t *b, u32 sw_if_index)
vnet_is_packet_pcaped
Definition: pcap_classify.h:32
#define clib_strnlen(s, m)
Definition: string.h:782
static_always_inline uword clib_count_equal_u32(u32 *data, uword max_count)
Definition: string.h:535
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:86
u8 count
Definition: dhcp.api:208
u16 flags
Copy of main node flags.
Definition: node.h:492
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
u8 pcap_tx_enable
Definition: vnet.h:65
static void vlib_set_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt, u32 count)
Definition: trace_funcs.h:226
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)
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:292
static_always_inline vnet_feature_config_main_t * vnet_feature_get_config_main(u16 arc)
Definition: feature.h:244
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
node VNET_INTERFACE_OUTPUT_ERROR_INTERFACE_DELETED
Definition: defs.h:46
ip6_address_t dst_address
Definition: ip6_packet.h:310
signed short i16
Definition: types.h:46
return frame n_vectors