FD.io VPP  v17.07-30-g839fa73
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/feature/feature.h>
42 
43 typedef struct
44 {
46  u8 data[128 - sizeof (u32)];
47 }
49 
50 u8 *
52 {
53  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
54  vlib_node_t *node = va_arg (*va, vlib_node_t *);
56  vnet_main_t *vnm = vnet_get_main ();
58  uword indent;
59 
60  if (t->sw_if_index != (u32) ~ 0)
61  {
62  indent = format_get_indent (s);
63 
66  {
67  /* the interface may have been deleted by the time the trace is printed */
68  s = format (s, "sw_if_index: %d\n%U%U",
69  t->sw_if_index,
70  format_white_space, indent,
71  node->format_buffer ? node->
72  format_buffer : format_hex_bytes, t->data,
73  sizeof (t->data));
74  }
75  else
76  {
77  si = vnet_get_sw_interface (vnm, t->sw_if_index);
78 
79  s = format (s, "%U\n%U%U",
81  format_white_space, indent,
82  node->format_buffer ? node->
83  format_buffer : format_hex_bytes, t->data,
84  sizeof (t->data));
85  }
86  }
87  return s;
88 }
89 
90 static void
92  vlib_node_runtime_t * node,
93  vlib_frame_t * frame, uword n_buffers)
94 {
95  u32 n_left, *from;
96 
97  n_left = n_buffers;
98  from = vlib_frame_args (frame);
99 
100  while (n_left >= 4)
101  {
102  u32 bi0, bi1;
103  vlib_buffer_t *b0, *b1;
104  interface_output_trace_t *t0, *t1;
105 
106  /* Prefetch next iteration. */
107  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
108  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
109 
110  bi0 = from[0];
111  bi1 = from[1];
112 
113  b0 = vlib_get_buffer (vm, bi0);
114  b1 = vlib_get_buffer (vm, bi1);
115 
116  if (b0->flags & VLIB_BUFFER_IS_TRACED)
117  {
118  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
119  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
121  sizeof (t0->data));
122  }
123  if (b1->flags & VLIB_BUFFER_IS_TRACED)
124  {
125  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
126  t1->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_TX];
128  sizeof (t1->data));
129  }
130  from += 2;
131  n_left -= 2;
132  }
133 
134  while (n_left >= 1)
135  {
136  u32 bi0;
137  vlib_buffer_t *b0;
139 
140  bi0 = from[0];
141 
142  b0 = vlib_get_buffer (vm, bi0);
143 
144  if (b0->flags & VLIB_BUFFER_IS_TRACED)
145  {
146  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
147  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
149  sizeof (t0->data));
150  }
151  from += 1;
152  n_left -= 1;
153  }
154 }
155 
156 static never_inline u32
158  u32 bi,
159  vlib_buffer_t * b,
160  u32 n_left_to_tx, u32 * to_tx, u32 * n_slow_bytes_result)
161 {
162  /* We've already enqueued a single buffer. */
163  u32 n_buffers = 0;
164  u32 n_slow_bytes = 0;
165 
166  while (n_left_to_tx > 0)
167  {
168  to_tx[0] = bi;
169  to_tx += 1;
170  n_left_to_tx -= 1;
171  n_buffers += 1;
172  n_slow_bytes += vlib_buffer_length_in_chain (vm, b);
173 
174  /* Be grumpy about zero length buffers for benefit of
175  driver tx function. */
176  ASSERT (b->current_length > 0);
177 
178  if (!(b->flags & VLIB_BUFFER_NEXT_PRESENT))
179  break;
180 
181  bi = b->next_buffer;
182  b = vlib_get_buffer (vm, bi);
183  }
184 
185  /* Ran out of space in next frame trying to enqueue buffers? */
187  return 0;
188 
189  *n_slow_bytes_result = n_slow_bytes;
190  return n_buffers;
191 }
192 
193 /*
194  * Increment TX stats. Roll up consecutive increments to the same sw_if_index
195  * into one increment.
196  */
199  u32 thread_index,
200  u32 length,
201  u32 sw_if_index,
202  u32 * last_sw_if_index, u32 * n_packets, u32 * n_bytes)
203 {
205 
206  if (PREDICT_TRUE (sw_if_index == *last_sw_if_index))
207  {
208  *n_packets += 1;
209  *n_bytes += length;
210  }
211  else
212  {
213  if (PREDICT_TRUE (*last_sw_if_index != ~0))
214  {
215  im = &vnm->interface_main;
216 
219  thread_index,
220  *last_sw_if_index,
221  *n_packets, *n_bytes);
222  }
223  *last_sw_if_index = sw_if_index;
224  *n_packets = 1;
225  *n_bytes = length;
226  }
227 }
228 
229 
230 /* Interface output functions. */
231 uword
233  vlib_node_runtime_t * node,
234  vlib_frame_t * frame)
235 {
236  vnet_main_t *vnm = vnet_get_main ();
237  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
240  u32 n_left_to_tx, *from, *from_end, *to_tx;
241  u32 n_bytes, n_buffers, n_packets;
242  u32 last_sw_if_index;
243  u32 thread_index = vm->thread_index;
244 
245  n_buffers = frame->n_vectors;
246 
247  if (node->flags & VLIB_NODE_FLAG_TRACE)
248  vnet_interface_output_trace (vm, node, frame, n_buffers);
249 
250  from = vlib_frame_args (frame);
251 
252  if (rt->is_deleted)
253  return vlib_error_drop_buffers (vm, node, from,
254  /* buffer stride */ 1,
255  n_buffers,
257  node->node_index,
259 
260  si = vnet_get_sw_interface (vnm, rt->sw_if_index);
262  if (!(si->flags & (VNET_SW_INTERFACE_FLAG_ADMIN_UP |
265  {
267 
270  vlib_increment_simple_counter (cm, thread_index,
271  rt->sw_if_index, n_buffers);
272  return vlib_error_drop_buffers (vm, node, from,
273  /* buffer stride */ 1,
274  n_buffers,
276  node->node_index,
278  }
279 
280  from_end = from + n_buffers;
281 
282  /* Total byte count of all buffers. */
283  n_bytes = 0;
284  n_packets = 0;
285  last_sw_if_index = ~0;
286 
287  while (from < from_end)
288  {
289  /* Get new next frame since previous incomplete frame may have less
290  than VNET_FRAME_SIZE vectors in it. */
292  to_tx, n_left_to_tx);
293 
294  while (from + 4 <= from_end && n_left_to_tx >= 2)
295  {
296  u32 bi0, bi1;
297  vlib_buffer_t *b0, *b1;
298 
299  /* Prefetch next iteration. */
300  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
301  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
302 
303  bi0 = from[0];
304  bi1 = from[1];
305  to_tx[0] = bi0;
306  to_tx[1] = bi1;
307  from += 2;
308  to_tx += 2;
309  n_left_to_tx -= 2;
310 
311  b0 = vlib_get_buffer (vm, bi0);
312  b1 = vlib_get_buffer (vm, bi1);
313 
314  /* Be grumpy about zero length buffers for benefit of
315  driver tx function. */
316  ASSERT (b0->current_length > 0);
317  ASSERT (b1->current_length > 0);
318 
319  if (PREDICT_FALSE
320  ((b0->flags | b1->flags) & VLIB_BUFFER_NEXT_PRESENT))
321  {
322  u32 n_buffers, n_slow_bytes, i;
323 
324  /* Undo. */
325  from -= 2;
326  to_tx -= 2;
327  n_left_to_tx += 2;
328 
329  /* Do slow path two times. */
330  for (i = 0; i < 2; i++)
331  {
332  u32 bi = i ? bi1 : bi0;
333  vlib_buffer_t *b = i ? b1 : b0;
334 
335  n_buffers = slow_path (vm, bi, b,
336  n_left_to_tx, to_tx, &n_slow_bytes);
337 
338  /* Not enough room for single packet? */
339  if (n_buffers == 0)
340  goto put;
341 
342  from += 1;
343  to_tx += n_buffers;
344  n_left_to_tx -= n_buffers;
345  incr_output_stats (vnm, thread_index, n_slow_bytes,
346  vnet_buffer (b)->sw_if_index[VLIB_TX],
347  &last_sw_if_index, &n_packets, &n_bytes);
348  }
349  }
350  else
351  {
352  incr_output_stats (vnm, thread_index,
354  vnet_buffer (b0)->sw_if_index[VLIB_TX],
355  &last_sw_if_index, &n_packets, &n_bytes);
356  incr_output_stats (vnm, thread_index,
358  vnet_buffer (b1)->sw_if_index[VLIB_TX],
359  &last_sw_if_index, &n_packets, &n_bytes);
360  }
361  }
362 
363  while (from + 1 <= from_end && n_left_to_tx >= 1)
364  {
365  u32 bi0;
366  vlib_buffer_t *b0;
367 
368  bi0 = from[0];
369  to_tx[0] = bi0;
370  from += 1;
371  to_tx += 1;
372  n_left_to_tx -= 1;
373 
374  b0 = vlib_get_buffer (vm, bi0);
375 
376  /* Be grumpy about zero length buffers for benefit of
377  driver tx function. */
378  ASSERT (b0->current_length > 0);
379 
381  {
382  u32 n_buffers, n_slow_bytes;
383 
384  /* Undo. */
385  from -= 1;
386  to_tx -= 1;
387  n_left_to_tx += 1;
388 
389  n_buffers = slow_path (vm, bi0, b0,
390  n_left_to_tx, to_tx, &n_slow_bytes);
391 
392  /* Not enough room for single packet? */
393  if (n_buffers == 0)
394  goto put;
395 
396  from += 1;
397  to_tx += n_buffers;
398  n_left_to_tx -= n_buffers;
399  }
400  incr_output_stats (vnm, thread_index,
402  vnet_buffer (b0)->sw_if_index[VLIB_TX],
403  &last_sw_if_index, &n_packets, &n_bytes);
404  }
405 
406  put:
408  n_left_to_tx);
409  }
410 
411  /* Final update of interface stats. */
412  incr_output_stats (vnm, thread_index, 0, ~0, /* ~0 will flush stats */
413  &last_sw_if_index, &n_packets, &n_bytes);
414 
415  return n_buffers;
416 }
417 
420 
421 uword
423  vlib_node_runtime_t * node, vlib_frame_t * frame)
424 {
425  vnet_main_t *vnm = vnet_get_main ();
426  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
429  u32 n_left_to_tx, *from, *from_end, *to_tx;
430  u32 n_bytes, n_buffers, n_packets;
431  u32 n_bytes_b0, n_bytes_b1, n_bytes_b2, n_bytes_b3;
432  u32 thread_index = vm->thread_index;
434  u32 next_index = VNET_INTERFACE_OUTPUT_NEXT_TX;
435  u32 current_config_index = ~0;
436  u8 arc = im->output_feature_arc_index;
437 
438  n_buffers = frame->n_vectors;
439 
440  if (node->flags & VLIB_NODE_FLAG_TRACE)
441  vnet_interface_output_trace (vm, node, frame, n_buffers);
442 
443  from = vlib_frame_args (frame);
444 
445  if (rt->is_deleted)
446  return vlib_error_drop_buffers (vm, node, from,
447  /* buffer stride */ 1,
448  n_buffers,
450  node->node_index,
452 
453  si = vnet_get_sw_interface (vnm, rt->sw_if_index);
455  if (!(si->flags & (VNET_SW_INTERFACE_FLAG_ADMIN_UP |
458  {
460 
463  vlib_increment_simple_counter (cm, thread_index,
464  rt->sw_if_index, n_buffers);
465 
466  return vlib_error_drop_buffers (vm, node, from,
467  /* buffer stride */ 1,
468  n_buffers,
470  node->node_index,
472  }
473 
474  from_end = from + n_buffers;
475 
476  /* Total byte count of all buffers. */
477  n_bytes = 0;
478  n_packets = 0;
479 
480  /* interface-output feature arc handling */
482  {
484  fcm = vnet_feature_get_config_main (arc);
485  current_config_index = vnet_get_feature_config_index (arc,
486  rt->sw_if_index);
487  vnet_get_config_data (&fcm->config_main, &current_config_index,
488  &next_index, 0);
489  }
490 
491  while (from < from_end)
492  {
493  /* Get new next frame since previous incomplete frame may have less
494  than VNET_FRAME_SIZE vectors in it. */
495  vlib_get_new_next_frame (vm, node, next_index, to_tx, n_left_to_tx);
496 
497  while (from + 8 <= from_end && n_left_to_tx >= 4)
498  {
499  u32 bi0, bi1, bi2, bi3;
500  vlib_buffer_t *b0, *b1, *b2, *b3;
501  u32 tx_swif0, tx_swif1, tx_swif2, tx_swif3;
502 
503  /* Prefetch next iteration. */
504  vlib_prefetch_buffer_with_index (vm, from[4], LOAD);
505  vlib_prefetch_buffer_with_index (vm, from[5], LOAD);
506  vlib_prefetch_buffer_with_index (vm, from[6], LOAD);
507  vlib_prefetch_buffer_with_index (vm, from[7], LOAD);
508 
509  bi0 = from[0];
510  bi1 = from[1];
511  bi2 = from[2];
512  bi3 = from[3];
513  to_tx[0] = bi0;
514  to_tx[1] = bi1;
515  to_tx[2] = bi2;
516  to_tx[3] = bi3;
517  from += 4;
518  to_tx += 4;
519  n_left_to_tx -= 4;
520 
521  b0 = vlib_get_buffer (vm, bi0);
522  b1 = vlib_get_buffer (vm, bi1);
523  b2 = vlib_get_buffer (vm, bi2);
524  b3 = vlib_get_buffer (vm, bi3);
525 
526  /* Be grumpy about zero length buffers for benefit of
527  driver tx function. */
528  ASSERT (b0->current_length > 0);
529  ASSERT (b1->current_length > 0);
530  ASSERT (b2->current_length > 0);
531  ASSERT (b3->current_length > 0);
532 
533  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b0);
534  n_bytes_b1 = vlib_buffer_length_in_chain (vm, b1);
535  n_bytes_b2 = vlib_buffer_length_in_chain (vm, b2);
536  n_bytes_b3 = vlib_buffer_length_in_chain (vm, b3);
537  tx_swif0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
538  tx_swif1 = vnet_buffer (b1)->sw_if_index[VLIB_TX];
539  tx_swif2 = vnet_buffer (b2)->sw_if_index[VLIB_TX];
540  tx_swif3 = vnet_buffer (b3)->sw_if_index[VLIB_TX];
541 
542  n_bytes += n_bytes_b0 + n_bytes_b1;
543  n_bytes += n_bytes_b2 + n_bytes_b3;
544  n_packets += 4;
545 
546  if (PREDICT_FALSE (current_config_index != ~0))
547  {
548  b0->feature_arc_index = arc;
549  b1->feature_arc_index = arc;
550  b2->feature_arc_index = arc;
551  b3->feature_arc_index = arc;
552  b0->current_config_index = current_config_index;
553  b1->current_config_index = current_config_index;
554  b2->current_config_index = current_config_index;
555  b3->current_config_index = current_config_index;
556  }
557 
558  /* update vlan subif tx counts, if required */
559  if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
560  {
561  vlib_increment_combined_counter (im->combined_sw_if_counters +
563  thread_index, tx_swif0, 1,
564  n_bytes_b0);
565  }
566 
567  if (PREDICT_FALSE (tx_swif1 != rt->sw_if_index))
568  {
569 
570  vlib_increment_combined_counter (im->combined_sw_if_counters +
572  thread_index, tx_swif1, 1,
573  n_bytes_b1);
574  }
575 
576  if (PREDICT_FALSE (tx_swif2 != rt->sw_if_index))
577  {
578 
579  vlib_increment_combined_counter (im->combined_sw_if_counters +
581  thread_index, tx_swif2, 1,
582  n_bytes_b2);
583  }
584  if (PREDICT_FALSE (tx_swif3 != rt->sw_if_index))
585  {
586 
587  vlib_increment_combined_counter (im->combined_sw_if_counters +
589  thread_index, tx_swif3, 1,
590  n_bytes_b3);
591  }
592  }
593 
594  while (from + 1 <= from_end && n_left_to_tx >= 1)
595  {
596  u32 bi0;
597  vlib_buffer_t *b0;
598  u32 tx_swif0;
599 
600  bi0 = from[0];
601  to_tx[0] = bi0;
602  from += 1;
603  to_tx += 1;
604  n_left_to_tx -= 1;
605 
606  b0 = vlib_get_buffer (vm, bi0);
607 
608  /* Be grumpy about zero length buffers for benefit of
609  driver tx function. */
610  ASSERT (b0->current_length > 0);
611 
612  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b0);
613  tx_swif0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
614  n_bytes += n_bytes_b0;
615  n_packets += 1;
616 
617  if (PREDICT_FALSE (current_config_index != ~0))
618  {
619  b0->feature_arc_index = arc;
620  b0->current_config_index = current_config_index;
621  }
622 
623  if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
624  {
625 
626  vlib_increment_combined_counter (im->combined_sw_if_counters +
628  thread_index, tx_swif0, 1,
629  n_bytes_b0);
630  }
631  }
632 
633  vlib_put_next_frame (vm, node, next_index, n_left_to_tx);
634  }
635 
636  /* Update main interface stats. */
637  vlib_increment_combined_counter (im->combined_sw_if_counters
639  thread_index,
640  rt->sw_if_index, n_packets, n_bytes);
641  return n_buffers;
642 }
643 
646 
647 /* Use buffer's sw_if_index[VNET_TX] to choose output interface. */
648 static uword
650  vlib_node_runtime_t * node,
651  vlib_frame_t * frame)
652 {
653  vnet_main_t *vnm = vnet_get_main ();
654  u32 n_left_to_next, *from, *to_next;
655  u32 n_left_from, next_index;
656 
657  n_left_from = frame->n_vectors;
658 
659  from = vlib_frame_args (frame);
660  next_index = node->cached_next_index;
661 
662  while (n_left_from > 0)
663  {
664  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
665 
666  while (n_left_from >= 4 && n_left_to_next >= 2)
667  {
668  u32 bi0, bi1, next0, next1;
669  vlib_buffer_t *b0, *b1;
670  vnet_hw_interface_t *hi0, *hi1;
671 
672  /* Prefetch next iteration. */
673  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
674  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
675 
676  bi0 = from[0];
677  bi1 = from[1];
678  to_next[0] = bi0;
679  to_next[1] = bi1;
680  from += 2;
681  to_next += 2;
682  n_left_to_next -= 2;
683  n_left_from -= 2;
684 
685  b0 = vlib_get_buffer (vm, bi0);
686  b1 = vlib_get_buffer (vm, bi1);
687 
688  hi0 =
690  vnet_buffer (b0)->sw_if_index
691  [VLIB_TX]);
692  hi1 =
694  vnet_buffer (b1)->sw_if_index
695  [VLIB_TX]);
696 
697  next0 = hi0->hw_if_index;
698  next1 = hi1->hw_if_index;
699 
700  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
701  n_left_to_next, bi0, bi1, next0,
702  next1);
703  }
704 
705  while (n_left_from > 0 && n_left_to_next > 0)
706  {
707  u32 bi0, next0;
708  vlib_buffer_t *b0;
709  vnet_hw_interface_t *hi0;
710 
711  bi0 = from[0];
712  to_next[0] = bi0;
713  from += 1;
714  to_next += 1;
715  n_left_to_next -= 1;
716  n_left_from -= 1;
717 
718  b0 = vlib_get_buffer (vm, bi0);
719 
720  hi0 =
722  vnet_buffer (b0)->sw_if_index
723  [VLIB_TX]);
724 
725  next0 = hi0->hw_if_index;
726 
727  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
728  n_left_to_next, bi0, next0);
729  }
730 
731  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
732  }
733 
734  return frame->n_vectors;
735 }
736 
739 {
740  vlib_node_t *n;
741  u32 ci, ni;
742 
743  ni = vlib_error_get_node (e);
744  n = vlib_get_node (vm, ni);
745 
746  ci = vlib_error_get_code (e);
747  ASSERT (ci < n->n_errors);
748 
749  ci += n->error_heap_index;
750 
751  return ci;
752 }
753 
754 static u8 *
755 format_vnet_error_trace (u8 * s, va_list * va)
756 {
757  vlib_main_t *vm = va_arg (*va, vlib_main_t *);
758  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
759  vlib_error_t *e = va_arg (*va, vlib_error_t *);
760  vlib_node_t *error_node;
761  vlib_error_main_t *em = &vm->error_main;
762  u32 i;
763 
764  error_node = vlib_get_node (vm, vlib_error_get_node (e[0]));
765  i = counter_index (vm, e[0]);
766  s = format (s, "%v: %s", error_node->name, em->error_strings_heap[i]);
767 
768  return s;
769 }
770 
771 static void
773  vlib_node_runtime_t * node, vlib_frame_t * frame)
774 {
775  u32 n_left, *buffers;
776 
777  buffers = vlib_frame_vector_args (frame);
778  n_left = frame->n_vectors;
779 
780  while (n_left >= 4)
781  {
782  u32 bi0, bi1;
783  vlib_buffer_t *b0, *b1;
784  vlib_error_t *t0, *t1;
785 
786  /* Prefetch next iteration. */
787  vlib_prefetch_buffer_with_index (vm, buffers[2], LOAD);
788  vlib_prefetch_buffer_with_index (vm, buffers[3], LOAD);
789 
790  bi0 = buffers[0];
791  bi1 = buffers[1];
792 
793  b0 = vlib_get_buffer (vm, bi0);
794  b1 = vlib_get_buffer (vm, bi1);
795 
796  if (b0->flags & VLIB_BUFFER_IS_TRACED)
797  {
798  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
799  t0[0] = b0->error;
800  }
801  if (b1->flags & VLIB_BUFFER_IS_TRACED)
802  {
803  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
804  t1[0] = b1->error;
805  }
806  buffers += 2;
807  n_left -= 2;
808  }
809 
810  while (n_left >= 1)
811  {
812  u32 bi0;
813  vlib_buffer_t *b0;
814  vlib_error_t *t0;
815 
816  bi0 = buffers[0];
817 
818  b0 = vlib_get_buffer (vm, bi0);
819 
820  if (b0->flags & VLIB_BUFFER_IS_TRACED)
821  {
822  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
823  t0[0] = b0->error;
824  }
825  buffers += 1;
826  n_left -= 1;
827  }
828 }
829 
830 static u8 *
832 {
833  uword node_index = vlib_error_get_node (e[0]);
834  uword code = vlib_error_get_code (e[0]);
835  vlib_node_t *n;
836 
837  if (node_index >= vec_len (vm->node_main.nodes))
838  return format (0, "[%d], node index out of range 0x%x, error 0x%x",
839  index, node_index, e[0]);
840 
841  n = vlib_get_node (vm, node_index);
842  if (code >= n->n_errors)
843  return format (0, "[%d], code %d out of range for node %v",
844  index, code, n->name);
845 
846  return 0;
847 }
848 
849 static u8 *
851  vlib_node_runtime_t * node, vlib_frame_t * f)
852 {
853  u32 *buffers = vlib_frame_args (f);
854  vlib_buffer_t *b;
855  u8 *msg = 0;
856  uword i;
857 
858  for (i = 0; i < f->n_vectors; i++)
859  {
860  b = vlib_get_buffer (vm, buffers[i]);
861  msg = validate_error (vm, &b->error, i);
862  if (msg)
863  return msg;
864  }
865 
866  return msg;
867 }
868 
869 typedef enum
870 {
875 
876 always_inline void
878 {
879  vlib_error_main_t *em = &vm->error_main;
880  u32 i = counter_index (vm, a);
881  em->counters[i] += 1;
882  vlib_error_elog_count (vm, i, 1);
883 }
884 
887  vlib_node_runtime_t * node,
888  vlib_frame_t * frame, vnet_error_disposition_t disposition)
889 {
890  vnet_main_t *vnm = vnet_get_main ();
891  vlib_error_main_t *em = &vm->error_main;
892  u32 *buffers, *first_buffer;
893  vlib_error_t current_error;
894  u32 current_counter_index, n_errors_left;
895  u32 current_sw_if_index, n_errors_current_sw_if_index;
896  u64 current_counter;
898  u32 thread_index = vm->thread_index;
899 
901  static char memory_init[VNET_ERROR_N_DISPOSITION];
902 
903  buffers = vlib_frame_args (frame);
904  first_buffer = buffers;
905 
906  {
907  vlib_buffer_t *b = vlib_get_buffer (vm, first_buffer[0]);
908 
909  if (!memory_init[disposition])
910  {
911  memory_init[disposition] = 1;
912  memory[disposition] = b->error;
913  }
914 
915  current_sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
916  n_errors_current_sw_if_index = 0;
917  }
918 
919  current_error = memory[disposition];
920  current_counter_index = counter_index (vm, memory[disposition]);
921  current_counter = em->counters[current_counter_index];
922 
923  if (node->flags & VLIB_NODE_FLAG_TRACE)
924  trace_errors_with_buffers (vm, node, frame);
925 
926  n_errors_left = frame->n_vectors;
928  (disposition == VNET_ERROR_DISPOSITION_PUNT
931 
932  while (n_errors_left >= 2)
933  {
934  vlib_buffer_t *b0, *b1;
935  vnet_sw_interface_t *sw_if0, *sw_if1;
936  vlib_error_t e0, e1;
937  u32 bi0, bi1;
938  u32 sw_if_index0, sw_if_index1;
939 
940  bi0 = buffers[0];
941  bi1 = buffers[1];
942 
943  buffers += 2;
944  n_errors_left -= 2;
945 
946  b0 = vlib_get_buffer (vm, bi0);
947  b1 = vlib_get_buffer (vm, bi1);
948 
949  e0 = b0->error;
950  e1 = b1->error;
951 
952  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
953  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
954 
955  /* Speculate that sw_if_index == sw_if_index[01]. */
956  n_errors_current_sw_if_index += 2;
957 
958  /* Speculatively assume all 2 (node, code) pairs are equal
959  to current (node, code). */
960  current_counter += 2;
961 
962  if (PREDICT_FALSE (e0 != current_error
963  || e1 != current_error
964  || sw_if_index0 != current_sw_if_index
965  || sw_if_index1 != current_sw_if_index))
966  {
967  current_counter -= 2;
968  n_errors_current_sw_if_index -= 2;
969 
970  vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
971  vlib_increment_simple_counter (cm, thread_index, sw_if_index1, 1);
972 
973  /* Increment super-interface drop/punt counters for
974  sub-interfaces. */
975  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index0);
977  (cm, thread_index, sw_if0->sup_sw_if_index,
978  sw_if0->sup_sw_if_index != sw_if_index0);
979 
980  sw_if1 = vnet_get_sw_interface (vnm, sw_if_index1);
982  (cm, thread_index, sw_if1->sup_sw_if_index,
983  sw_if1->sup_sw_if_index != sw_if_index1);
984 
985  em->counters[current_counter_index] = current_counter;
986  do_packet (vm, e0);
987  do_packet (vm, e1);
988 
989  /* For 2 repeated errors, change current error. */
990  if (e0 == e1 && e1 != current_error)
991  {
992  current_error = e0;
993  current_counter_index = counter_index (vm, e0);
994  }
995  current_counter = em->counters[current_counter_index];
996  }
997  }
998 
999  while (n_errors_left >= 1)
1000  {
1001  vlib_buffer_t *b0;
1002  vnet_sw_interface_t *sw_if0;
1003  vlib_error_t e0;
1004  u32 bi0, sw_if_index0;
1005 
1006  bi0 = buffers[0];
1007 
1008  buffers += 1;
1009  n_errors_left -= 1;
1010  current_counter += 1;
1011 
1012  b0 = vlib_get_buffer (vm, bi0);
1013  e0 = b0->error;
1014 
1015  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1016 
1017  /* Increment drop/punt counters. */
1018  vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
1019 
1020  /* Increment super-interface drop/punt counters for sub-interfaces. */
1021  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index0);
1022  vlib_increment_simple_counter (cm, thread_index,
1023  sw_if0->sup_sw_if_index,
1024  sw_if0->sup_sw_if_index != sw_if_index0);
1025 
1026  if (PREDICT_FALSE (e0 != current_error))
1027  {
1028  current_counter -= 1;
1029 
1030  vlib_error_elog_count (vm, current_counter_index,
1031  (current_counter
1032  - em->counters[current_counter_index]));
1033 
1034  em->counters[current_counter_index] = current_counter;
1035 
1036  do_packet (vm, e0);
1037  current_error = e0;
1038  current_counter_index = counter_index (vm, e0);
1039  current_counter = em->counters[current_counter_index];
1040  }
1041  }
1042 
1043  if (n_errors_current_sw_if_index > 0)
1044  {
1045  vnet_sw_interface_t *si;
1046 
1047  vlib_increment_simple_counter (cm, thread_index, current_sw_if_index,
1048  n_errors_current_sw_if_index);
1049 
1050  si = vnet_get_sw_interface (vnm, current_sw_if_index);
1051  if (si->sup_sw_if_index != current_sw_if_index)
1052  vlib_increment_simple_counter (cm, thread_index, si->sup_sw_if_index,
1053  n_errors_current_sw_if_index);
1054  }
1055 
1056  vlib_error_elog_count (vm, current_counter_index,
1057  (current_counter
1058  - em->counters[current_counter_index]));
1059 
1060  /* Return cached counter. */
1061  em->counters[current_counter_index] = current_counter;
1062 
1063  /* Save memory for next iteration. */
1064  memory[disposition] = current_error;
1065 
1066  if (disposition == VNET_ERROR_DISPOSITION_DROP || !vm->os_punt_frame)
1067  {
1068  vlib_buffer_free (vm, first_buffer, frame->n_vectors);
1069 
1070  /* If there is no punt function, free the frame as well. */
1071  if (disposition == VNET_ERROR_DISPOSITION_PUNT && !vm->os_punt_frame)
1072  vlib_frame_free (vm, node, frame);
1073  }
1074  else
1075  vm->os_punt_frame (vm, node, frame);
1076 
1077  return frame->n_vectors;
1078 }
1079 
1080 static inline void
1083 {
1084  u32 *from;
1085  u32 n_left = f->n_vectors;
1086  vlib_buffer_t *b0, *p1;
1087  u32 bi0;
1088  i16 save_current_data;
1089  u16 save_current_length;
1090 
1091  from = vlib_frame_vector_args (f);
1092 
1093  while (n_left > 0)
1094  {
1095  if (PREDICT_TRUE (n_left > 1))
1096  {
1097  p1 = vlib_get_buffer (vm, from[1]);
1098  vlib_prefetch_buffer_header (p1, LOAD);
1099  }
1100 
1101  bi0 = from[0];
1102  b0 = vlib_get_buffer (vm, bi0);
1103  from++;
1104  n_left--;
1105 
1106  /* See if we're pointedly ignoring this specific error */
1107  if (im->pcap_drop_filter_hash
1108  && hash_get (im->pcap_drop_filter_hash, b0->error))
1109  continue;
1110 
1111  /* Trace all drops, or drops received on a specific interface */
1112  if (im->pcap_sw_if_index == 0 ||
1113  im->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_RX])
1114  {
1115  save_current_data = b0->current_data;
1116  save_current_length = b0->current_length;
1117 
1118  /*
1119  * Typically, we'll need to rewind the buffer
1120  */
1121  if (b0->current_data > 0)
1122  vlib_buffer_advance (b0, (word) - b0->current_data);
1123 
1124  pcap_add_buffer (&im->pcap_main, vm, bi0, 512);
1125 
1126  b0->current_data = save_current_data;
1127  b0->current_length = save_current_length;
1128  }
1129  }
1130 }
1131 
1132 void
1133 vnet_pcap_drop_trace_filter_add_del (u32 error_index, int is_add)
1134 {
1136 
1137  if (im->pcap_drop_filter_hash == 0)
1138  im->pcap_drop_filter_hash = hash_create (0, sizeof (uword));
1139 
1140  if (is_add)
1141  hash_set (im->pcap_drop_filter_hash, error_index, 1);
1142  else
1143  hash_unset (im->pcap_drop_filter_hash, error_index);
1144 }
1145 
1146 static uword
1148  vlib_node_runtime_t * node, vlib_frame_t * frame)
1149 {
1151 
1152  if (PREDICT_FALSE (im->drop_pcap_enable))
1153  pcap_drop_trace (vm, im, frame);
1154 
1155  return process_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_DROP);
1156 }
1157 
1158 static uword
1160  vlib_node_runtime_t * node, vlib_frame_t * frame)
1161 {
1162  return process_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_PUNT);
1163 }
1164 
1165 /* *INDENT-OFF* */
1167  .function = process_drop,
1168  .name = "error-drop",
1169  .flags = VLIB_NODE_FLAG_IS_DROP,
1170  .vector_size = sizeof (u32),
1171  .format_trace = format_vnet_error_trace,
1172  .validate_frame = validate_error_frame,
1173 };
1174 /* *INDENT-ON* */
1175 
1177 
1178 /* *INDENT-OFF* */
1180  .function = process_punt,
1183  .name = "error-punt",
1184  .vector_size = sizeof (u32),
1185  .format_trace = format_vnet_error_trace,
1186  .validate_frame = validate_error_frame,
1187 };
1188 /* *INDENT-ON* */
1189 
1191 
1192 /* *INDENT-OFF* */
1195  .name = "interface-output",
1196  .vector_size = sizeof (u32),
1197 };
1198 /* *INDENT-ON* */
1199 
1202 
1203 static uword
1205  vlib_frame_t * from_frame)
1206 {
1207  vnet_main_t *vnm = vnet_get_main ();
1208  u32 last_sw_if_index = ~0;
1209  vlib_frame_t *to_frame = 0;
1210  vnet_hw_interface_t *hw = 0;
1211  u32 *from, *to_next = 0;
1212  u32 n_left_from;
1213 
1214  from = vlib_frame_vector_args (from_frame);
1215  n_left_from = from_frame->n_vectors;
1216  while (n_left_from > 0)
1217  {
1218  u32 bi0;
1219  vlib_buffer_t *b0;
1220  u32 sw_if_index0;
1221 
1222  bi0 = from[0];
1223  from++;
1224  n_left_from--;
1225  b0 = vlib_get_buffer (vm, bi0);
1226  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
1227 
1228  if (PREDICT_FALSE ((last_sw_if_index != sw_if_index0) || to_frame == 0))
1229  {
1230  if (to_frame)
1231  {
1232  hw = vnet_get_sup_hw_interface (vnm, last_sw_if_index);
1233  vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1234  }
1235  last_sw_if_index = sw_if_index0;
1236  hw = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1237  to_frame = vlib_get_frame_to_node (vm, hw->tx_node_index);
1238  to_next = vlib_frame_vector_args (to_frame);
1239  }
1240 
1241  to_next[0] = bi0;
1242  to_next++;
1243  to_frame->n_vectors++;
1244  }
1245  vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1246  return from_frame->n_vectors;
1247 }
1248 
1249 /* *INDENT-OFF* */
1251  .function = interface_tx_node_fn,
1252  .name = "interface-tx",
1253  .vector_size = sizeof (u32),
1254  .n_next_nodes = 1,
1255  .next_nodes = {
1256  [0] = "error-drop",
1257  },
1258 };
1259 
1260 VNET_FEATURE_ARC_INIT (interface_output, static) =
1261 {
1262  .arc_name = "interface-output",
1263  .start_nodes = VNET_FEATURES (0),
1265 };
1266 
1267 VNET_FEATURE_INIT (span_tx, static) = {
1268  .arc_name = "interface-output",
1269  .node_name = "span-output",
1270  .runs_before = VNET_FEATURES ("interface-tx"),
1271 };
1272 
1273 VNET_FEATURE_INIT (interface_tx, static) = {
1274  .arc_name = "interface-output",
1275  .node_name = "interface-tx",
1276  .runs_before = 0,
1277 };
1278 /* *INDENT-ON* */
1279 
1280 clib_error_t *
1282  u32 hw_if_index,
1283  u32 is_create)
1284 {
1285  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1286  u32 next_index;
1287 
1288  next_index = vlib_node_add_next_with_slot
1290  hi->output_node_index,
1291  /* next_index */ hw_if_index);
1292 
1293  ASSERT (next_index == hw_if_index);
1294 
1295  return 0;
1296 }
1297 
1300 
1301 static clib_error_t *
1303  unformat_input_t * input,
1304  vlib_cli_command_t * cmd)
1305 {
1306  vnet_main_t *vnm = vnet_get_main ();
1308  u8 *filename;
1309  u32 max;
1310  int matched = 0;
1311  clib_error_t *error = 0;
1312 
1313  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1314  {
1315  if (unformat (input, "on"))
1316  {
1317  if (im->drop_pcap_enable == 0)
1318  {
1319  if (im->pcap_filename == 0)
1320  im->pcap_filename = format (0, "/tmp/drop.pcap%c", 0);
1321 
1322  memset (&im->pcap_main, 0, sizeof (im->pcap_main));
1323  im->pcap_main.file_name = (char *) im->pcap_filename;
1324  im->pcap_main.n_packets_to_capture = 100;
1325  if (im->pcap_pkts_to_capture)
1327 
1328  im->pcap_main.packet_type = PCAP_PACKET_TYPE_ethernet;
1329  im->drop_pcap_enable = 1;
1330  matched = 1;
1331  vlib_cli_output (vm, "pcap drop capture on...");
1332  }
1333  else
1334  {
1335  vlib_cli_output (vm, "pcap drop capture already on...");
1336  }
1337  matched = 1;
1338  }
1339  else if (unformat (input, "off"))
1340  {
1341  matched = 1;
1342 
1343  if (im->drop_pcap_enable)
1344  {
1345  vlib_cli_output (vm, "captured %d pkts...",
1347  if (im->pcap_main.n_packets_captured)
1348  {
1351  error = pcap_write (&im->pcap_main);
1352  if (error)
1353  clib_error_report (error);
1354  else
1355  vlib_cli_output (vm, "saved to %s...", im->pcap_filename);
1356  }
1357  }
1358  else
1359  {
1360  vlib_cli_output (vm, "pcap drop capture already off...");
1361  }
1362 
1363  im->drop_pcap_enable = 0;
1364  }
1365  else if (unformat (input, "max %d", &max))
1366  {
1367  im->pcap_pkts_to_capture = max;
1368  matched = 1;
1369  }
1370 
1371  else if (unformat (input, "intfc %U",
1373  &im->pcap_sw_if_index))
1374  matched = 1;
1375  else if (unformat (input, "intfc any"))
1376  {
1377  im->pcap_sw_if_index = 0;
1378  matched = 1;
1379  }
1380  else if (unformat (input, "file %s", &filename))
1381  {
1382  u8 *chroot_filename;
1383  /* Brain-police user path input */
1384  if (strstr ((char *) filename, "..")
1385  || index ((char *) filename, '/'))
1386  {
1387  vlib_cli_output (vm, "illegal characters in filename '%s'",
1388  filename);
1389  continue;
1390  }
1391 
1392  chroot_filename = format (0, "/tmp/%s%c", filename, 0);
1393  vec_free (filename);
1394 
1395  if (im->pcap_filename)
1396  vec_free (im->pcap_filename);
1397  im->pcap_filename = chroot_filename;
1398  im->pcap_main.file_name = (char *) im->pcap_filename;
1399  matched = 1;
1400  }
1401  else if (unformat (input, "status"))
1402  {
1403  if (im->drop_pcap_enable == 0)
1404  {
1405  vlib_cli_output (vm, "pcap drop capture is off...");
1406  continue;
1407  }
1408 
1409  vlib_cli_output (vm, "pcap drop capture: %d of %d pkts...",
1412  matched = 1;
1413  }
1414 
1415  else
1416  break;
1417  }
1418 
1419  if (matched == 0)
1420  return clib_error_return (0, "unknown input `%U'",
1421  format_unformat_error, input);
1422 
1423  return 0;
1424 }
1425 
1426 /* *INDENT-OFF* */
1427 VLIB_CLI_COMMAND (pcap_trace_command, static) = {
1428  .path = "pcap drop trace",
1429  .short_help =
1430  "pcap drop trace on off max <nn> intfc <intfc> file <name> status",
1431  .function = pcap_drop_trace_command_fn,
1432 };
1433 /* *INDENT-ON* */
1434 
1435 /*
1436  * fd.io coding-style-patch-verification: ON
1437  *
1438  * Local Variables:
1439  * eval: (c-set-style "gnu")
1440  * End:
1441  */
u8 * format_vnet_interface_output_trace(u8 *s, va_list *va)
vnet_config_main_t config_main
Definition: feature.h:65
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:187
vmrglw vmrglh hi
u32 error_heap_index
Definition: node.h:279
VNET_FEATURE_ARC_INIT(interface_output, static)
#define hash_set(h, key, value)
Definition: hash.h:254
char * file_name
File name of pcap output.
Definition: pcap.h:124
pcap_main_t pcap_main
Definition: interface.h:659
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
#define CLIB_UNUSED(x)
Definition: clib.h:79
#define hash_unset(h, key)
Definition: hash.h:260
a
Definition: bitmap.h:516
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:211
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:290
u8 runtime_data[0]
Function dependent node-runtime data.
Definition: node.h:468
u32 n_packets_to_capture
Number of packets to capture.
Definition: pcap.h:127
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:116
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)
vnet_interface_main_t interface_main
Definition: vnet.h:56
#define PREDICT_TRUE(x)
Definition: clib.h:98
uword vnet_interface_output_node_flatten(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
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:459
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u32 thread_index
Definition: main.h:159
clib_error_t * vnet_per_buffer_interface_output_hw_interface_add_del(vnet_main_t *vnm, u32 hw_if_index, u32 is_create)
CLIB_MULTIARCH_SELECT_FN(vnet_interface_output_node_flatten)
static void vnet_interface_output_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, uword n_buffers)
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
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
unformat_function_t unformat_vnet_sw_interface
static_always_inline int vnet_have_features(u8 arc, u32 sw_if_index)
Definition: feature.h:167
void vnet_pcap_drop_trace_filter_add_del(u32 error_index, int is_add)
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:397
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:100
void vlib_frame_free(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_frame_t *f)
Definition: main.c:216
vhost_user_memory_t memory
Definition: vhost-user.h:83
static_always_inline void incr_output_stats(vnet_main_t *vnm, u32 thread_index, u32 length, u32 sw_if_index, u32 *last_sw_if_index, u32 *n_packets, u32 *n_bytes)
#define VLIB_BUFFER_NEXT_PRESENT
Definition: buffer.h:87
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:67
#define static_always_inline
Definition: clib.h:85
uword * pcap_drop_filter_hash
Definition: interface.h:663
#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:170
#define VLIB_NODE_FLAG_IS_DROP
Definition: node.h:255
static u8 * validate_error_frame(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *f)
#define always_inline
Definition: clib.h:84
static uword format_get_indent(u8 *s)
Definition: format.h:72
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:653
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
static u32 counter_index(vlib_main_t *vm, vlib_error_t e)
vlib_node_t ** nodes
Definition: node.h:638
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:164
uword vlib_node_add_next_with_slot(vlib_main_t *vm, uword node_index, uword next_node_index, uword slot)
Definition: node.c:205
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
u8 * format_hex_bytes(u8 *s, va_list *va)
Definition: std-formats.c:84
u8 feature_arc_index
Used to identify feature arcs by intermediate feature node.
Definition: buffer.h:120
#define vlib_get_new_next_frame(vm, node, next_index, vectors, n_vectors_left)
Definition: node_funcs.h:371
#define clib_error_return(e, args...)
Definition: error.h:99
unsigned long u64
Definition: types.h:89
static vlib_node_registration_t drop_buffers
(constructor) VLIB_REGISTER_NODE (drop_buffers)
A collection of simple counters.
Definition: counter.h:58
static void pcap_drop_trace(vlib_main_t *vm, vnet_interface_main_t *im, vlib_frame_t *f)
static vlib_node_registration_t vnet_per_buffer_interface_output_node
(constructor) VLIB_REGISTER_NODE (vnet_per_buffer_interface_output_node)
static uword interface_tx_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
u8 data[128-sizeof(u32)]
#define hash_get(h, key)
Definition: hash.h:248
format_function_t format_vnet_sw_interface_name
vlib_main_t * vlib_main
Definition: vnet.h:78
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:71
static u8 * format_vnet_error_trace(u8 *s, va_list *va)
vlib_error_main_t error_main
Definition: main.h:124
#define VNET_SW_INTERFACE_FLAG_BOND_SLAVE
Definition: interface.h:569
VNET_FEATURE_INIT(span_tx, static)
uword vnet_interface_output_node(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
uword vlib_error_drop_buffers(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u32 next_buffer_stride, u32 n_buffers, u32 next_index, u32 drop_error_node, u32 drop_error_code)
Definition: error.c:44
struct _unformat_input_t unformat_input_t
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:188
vnet_error_disposition_t
static void * vnet_get_config_data(vnet_config_main_t *cm, u32 *config_index, u32 *next_index, u32 n_data_bytes)
Definition: config.h:122
static void pcap_add_buffer(pcap_main_t *pm, vlib_main_t *vm, u32 buffer_index, u32 n_bytes_in_trace)
Add buffer (vlib_buffer_t) to the trace.
Definition: pcap.h:201
#define PREDICT_FALSE(x)
Definition: clib.h:97
u32 vlib_error_t
Definition: error.h:44
vnet_main_t vnet_main
Definition: misc.c:43
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:652
format_function_t * format_buffer
Definition: node.h:312
u32 node_index
Node index.
Definition: node.h:441
#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:216
#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:366
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:113
static u32 vlib_error_get_code(vlib_error_t e)
Definition: error.h:53
u8 * name
Definition: node.h:222
u64 * counters
Definition: error.h:78
static_always_inline uword process_drop_punt(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, vnet_error_disposition_t disposition)
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
char ** error_strings_heap
Definition: error.h:85
u16 n_vectors
Definition: node.h:345
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:85
#define clib_memcpy(a, b, c)
Definition: string.h:69
VLIB_NODE_FUNCTION_MULTIARCH(drop_buffers, process_drop)
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:238
VLIB_NODE_FUNCTION_MULTIARCH_CLONE(vnet_interface_output_node_flatten)
clib_error_t * pcap_write(pcap_main_t *pm)
Write PCAP file.
Definition: pcap.c:89
static uword process_drop(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
#define never_inline
Definition: clib.h:81
#define hash_create(elts, value_bytes)
Definition: hash.h:658
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:460
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:560
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
#define VLIB_NODE_FLAG_IS_PUNT
Definition: node.h:256
static void trace_errors_with_buffers(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:109
#define clib_error_report(e)
Definition: error.h:113
static void * vlib_frame_args(vlib_frame_t *f)
Get pointer to frame scalar data.
Definition: node_funcs.h:286
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:201
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:260
static vlib_node_registration_t interface_tx
(constructor) VLIB_REGISTER_NODE (interface_tx)
#define VNET_FEATURES(...)
Definition: feature.h:368
u64 uword
Definition: types.h:112
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
VNET_HW_INTERFACE_ADD_DEL_FUNCTION(vnet_per_buffer_interface_output_hw_interface_add_del)
pcap_packet_type_t packet_type
Packet type.
Definition: pcap.h:130
Definition: defs.h:47
unsigned short u16
Definition: types.h:57
i64 word
Definition: types.h:111
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
static_always_inline u32 vnet_get_feature_config_index(u8 arc, u32 sw_if_index)
Definition: feature.h:174
vlib_node_main_t node_main
Definition: main.h:115
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:644
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:269
static clib_error_t * pcap_drop_trace_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
short i16
Definition: types.h:46
#define vnet_buffer(b)
Definition: buffer.h:303
static void vlib_error_elog_count(vlib_main_t *vm, uword counter, uword increment)
Definition: error_funcs.h:46
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:144
u16 n_errors
Definition: node.h:272
static vlib_node_registration_t punt_buffers
(constructor) VLIB_REGISTER_NODE (punt_buffers)
static uword vnet_per_buffer_interface_output(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
void(* os_punt_frame)(struct vlib_main_t *vm, struct vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: main.h:128
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:58
u16 flags
Copy of main node flags.
Definition: node.h:454
static uword process_punt(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:196
static u32 vlib_error_get_node(vlib_error_t e)
Definition: error.h:47
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:74
#define VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH
Definition: node.h:251
static_always_inline vnet_feature_config_main_t * vnet_feature_get_config_main(u16 arc)
Definition: feature.h:160
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
static void do_packet(vlib_main_t *vm, vlib_error_t a)
u32 n_packets_captured
Number of packets currently captured.
Definition: pcap.h:133
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
Definition: defs.h:46
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
static u8 * validate_error(vlib_main_t *vm, vlib_error_t *e, u32 index)
static never_inline u32 slow_path(vlib_main_t *vm, u32 bi, vlib_buffer_t *b, u32 n_left_to_tx, u32 *to_tx, u32 *n_slow_bytes_result)