FD.io VPP  v17.01.1-3-gc6833f8
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 cpu_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  cpu_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 cpu_index = vm->cpu_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) ||
264  {
266 
269  vlib_increment_simple_counter (cm, cpu_index,
270  rt->sw_if_index, n_buffers);
271  return vlib_error_drop_buffers (vm, node, from,
272  /* buffer stride */ 1,
273  n_buffers,
275  node->node_index,
277  }
278 
279  from_end = from + n_buffers;
280 
281  /* Total byte count of all buffers. */
282  n_bytes = 0;
283  n_packets = 0;
284  last_sw_if_index = ~0;
285 
286  while (from < from_end)
287  {
288  /* Get new next frame since previous incomplete frame may have less
289  than VNET_FRAME_SIZE vectors in it. */
291  to_tx, n_left_to_tx);
292 
293  while (from + 4 <= from_end && n_left_to_tx >= 2)
294  {
295  u32 bi0, bi1;
296  vlib_buffer_t *b0, *b1;
297 
298  /* Prefetch next iteration. */
299  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
300  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
301 
302  bi0 = from[0];
303  bi1 = from[1];
304  to_tx[0] = bi0;
305  to_tx[1] = bi1;
306  from += 2;
307  to_tx += 2;
308  n_left_to_tx -= 2;
309 
310  b0 = vlib_get_buffer (vm, bi0);
311  b1 = vlib_get_buffer (vm, bi1);
312 
313  /* Be grumpy about zero length buffers for benefit of
314  driver tx function. */
315  ASSERT (b0->current_length > 0);
316  ASSERT (b1->current_length > 0);
317 
318  if (PREDICT_FALSE
319  ((b0->flags | b1->flags) & VLIB_BUFFER_NEXT_PRESENT))
320  {
321  u32 n_buffers, n_slow_bytes, i;
322 
323  /* Undo. */
324  from -= 2;
325  to_tx -= 2;
326  n_left_to_tx += 2;
327 
328  /* Do slow path two times. */
329  for (i = 0; i < 2; i++)
330  {
331  u32 bi = i ? bi1 : bi0;
332  vlib_buffer_t *b = i ? b1 : b0;
333 
334  n_buffers = slow_path (vm, bi, b,
335  n_left_to_tx, to_tx, &n_slow_bytes);
336 
337  /* Not enough room for single packet? */
338  if (n_buffers == 0)
339  goto put;
340 
341  from += 1;
342  to_tx += n_buffers;
343  n_left_to_tx -= n_buffers;
344  incr_output_stats (vnm, cpu_index, n_slow_bytes,
345  vnet_buffer (b)->sw_if_index[VLIB_TX],
346  &last_sw_if_index, &n_packets, &n_bytes);
347  }
348  }
349  else
350  {
351  incr_output_stats (vnm, cpu_index,
353  vnet_buffer (b0)->sw_if_index[VLIB_TX],
354  &last_sw_if_index, &n_packets, &n_bytes);
355  incr_output_stats (vnm, cpu_index,
357  vnet_buffer (b1)->sw_if_index[VLIB_TX],
358  &last_sw_if_index, &n_packets, &n_bytes);
359  }
360  }
361 
362  while (from + 1 <= from_end && n_left_to_tx >= 1)
363  {
364  u32 bi0;
365  vlib_buffer_t *b0;
366 
367  bi0 = from[0];
368  to_tx[0] = bi0;
369  from += 1;
370  to_tx += 1;
371  n_left_to_tx -= 1;
372 
373  b0 = vlib_get_buffer (vm, bi0);
374 
375  /* Be grumpy about zero length buffers for benefit of
376  driver tx function. */
377  ASSERT (b0->current_length > 0);
378 
380  {
381  u32 n_buffers, n_slow_bytes;
382 
383  /* Undo. */
384  from -= 1;
385  to_tx -= 1;
386  n_left_to_tx += 1;
387 
388  n_buffers = slow_path (vm, bi0, b0,
389  n_left_to_tx, to_tx, &n_slow_bytes);
390 
391  /* Not enough room for single packet? */
392  if (n_buffers == 0)
393  goto put;
394 
395  from += 1;
396  to_tx += n_buffers;
397  n_left_to_tx -= n_buffers;
398  }
399  incr_output_stats (vnm, cpu_index,
401  vnet_buffer (b0)->sw_if_index[VLIB_TX],
402  &last_sw_if_index, &n_packets, &n_bytes);
403  }
404 
405  put:
407  n_left_to_tx);
408  }
409 
410  /* Final update of interface stats. */
411  incr_output_stats (vnm, cpu_index, 0, ~0, /* ~0 will flush stats */
412  &last_sw_if_index, &n_packets, &n_bytes);
413 
414  return n_buffers;
415 }
416 
419 
420 uword
422  vlib_node_runtime_t * node, vlib_frame_t * frame)
423 {
424  vnet_main_t *vnm = vnet_get_main ();
425  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
428  u32 n_left_to_tx, *from, *from_end, *to_tx;
429  u32 n_bytes, n_buffers, n_packets;
430  u32 n_bytes_b0, n_bytes_b1;
431  u32 cpu_index = vm->cpu_index;
433  u32 next_index = VNET_INTERFACE_OUTPUT_NEXT_TX;
434  u32 current_config_index = ~0;
435  u8 arc = im->output_feature_arc_index;
436 
437  n_buffers = frame->n_vectors;
438 
439  if (node->flags & VLIB_NODE_FLAG_TRACE)
440  vnet_interface_output_trace (vm, node, frame, n_buffers);
441 
442  from = vlib_frame_args (frame);
443 
444  if (rt->is_deleted)
445  return vlib_error_drop_buffers (vm, node, from,
446  /* buffer stride */ 1,
447  n_buffers,
449  node->node_index,
451 
452  si = vnet_get_sw_interface (vnm, rt->sw_if_index);
454  if (!(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ||
456  {
458 
461  vlib_increment_simple_counter (cm, cpu_index,
462  rt->sw_if_index, n_buffers);
463 
464  return vlib_error_drop_buffers (vm, node, from,
465  /* buffer stride */ 1,
466  n_buffers,
468  node->node_index,
470  }
471 
472  from_end = from + n_buffers;
473 
474  /* Total byte count of all buffers. */
475  n_bytes = 0;
476  n_packets = 0;
477 
478  /* interface-output feature arc handling */
480  {
482  fcm = vnet_feature_get_config_main (arc);
483  current_config_index = vnet_get_feature_config_index (arc,
484  rt->sw_if_index);
485  vnet_get_config_data (&fcm->config_main, &current_config_index,
486  &next_index, 0);
487  }
488 
489  while (from < from_end)
490  {
491  /* Get new next frame since previous incomplete frame may have less
492  than VNET_FRAME_SIZE vectors in it. */
493  vlib_get_new_next_frame (vm, node, next_index, to_tx, n_left_to_tx);
494 
495  while (from + 4 <= from_end && n_left_to_tx >= 2)
496  {
497  u32 bi0, bi1;
498  vlib_buffer_t *b0, *b1;
499  u32 tx_swif0, tx_swif1;
500 
501  /* Prefetch next iteration. */
502  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
503  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
504 
505  bi0 = from[0];
506  bi1 = from[1];
507  to_tx[0] = bi0;
508  to_tx[1] = bi1;
509  from += 2;
510  to_tx += 2;
511  n_left_to_tx -= 2;
512 
513  b0 = vlib_get_buffer (vm, bi0);
514  b1 = vlib_get_buffer (vm, bi1);
515 
516  /* Be grumpy about zero length buffers for benefit of
517  driver tx function. */
518  ASSERT (b0->current_length > 0);
519  ASSERT (b1->current_length > 0);
520 
521  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b0);
522  n_bytes_b1 = vlib_buffer_length_in_chain (vm, b1);
523  tx_swif0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
524  tx_swif1 = vnet_buffer (b1)->sw_if_index[VLIB_TX];
525 
526  n_bytes += n_bytes_b0 + n_bytes_b1;
527  n_packets += 2;
528 
529  if (PREDICT_FALSE (current_config_index != ~0))
530  {
531  b0->feature_arc_index = arc;
532  b1->feature_arc_index = arc;
533  b0->current_config_index = current_config_index;
534  b1->current_config_index = current_config_index;
535  }
536 
537  if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
538  {
539  /* update vlan subif tx counts, if required */
540  vlib_increment_combined_counter (im->combined_sw_if_counters +
542  cpu_index, tx_swif0, 1,
543  n_bytes_b0);
544  }
545 
546  /* update vlan subif tx counts, if required */
547  if (PREDICT_FALSE (tx_swif1 != rt->sw_if_index))
548  {
549 
550  vlib_increment_combined_counter (im->combined_sw_if_counters +
552  cpu_index, tx_swif1, 1,
553  n_bytes_b1);
554  }
555  }
556 
557  while (from + 1 <= from_end && n_left_to_tx >= 1)
558  {
559  u32 bi0;
560  vlib_buffer_t *b0;
561  u32 tx_swif0;
562 
563  bi0 = from[0];
564  to_tx[0] = bi0;
565  from += 1;
566  to_tx += 1;
567  n_left_to_tx -= 1;
568 
569  b0 = vlib_get_buffer (vm, bi0);
570 
571  /* Be grumpy about zero length buffers for benefit of
572  driver tx function. */
573  ASSERT (b0->current_length > 0);
574 
575  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b0);
576  tx_swif0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
577  n_bytes += n_bytes_b0;
578  n_packets += 1;
579 
580  if (PREDICT_FALSE (current_config_index != ~0))
581  {
582  b0->feature_arc_index = arc;
583  b0->current_config_index = current_config_index;
584  }
585 
586  if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
587  {
588 
589  vlib_increment_combined_counter (im->combined_sw_if_counters +
591  cpu_index, tx_swif0, 1,
592  n_bytes_b0);
593  }
594  }
595 
596  vlib_put_next_frame (vm, node, next_index, n_left_to_tx);
597  }
598 
599  /* Update main interface stats. */
600  vlib_increment_combined_counter (im->combined_sw_if_counters
602  cpu_index,
603  rt->sw_if_index, n_packets, n_bytes);
604  return n_buffers;
605 }
606 
609 
610 /* Use buffer's sw_if_index[VNET_TX] to choose output interface. */
611 static uword
613  vlib_node_runtime_t * node,
614  vlib_frame_t * frame)
615 {
616  vnet_main_t *vnm = vnet_get_main ();
617  u32 n_left_to_next, *from, *to_next;
618  u32 n_left_from, next_index;
619 
620  n_left_from = frame->n_vectors;
621 
622  from = vlib_frame_args (frame);
623  next_index = node->cached_next_index;
624 
625  while (n_left_from > 0)
626  {
627  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
628 
629  while (n_left_from >= 4 && n_left_to_next >= 2)
630  {
631  u32 bi0, bi1, next0, next1;
632  vlib_buffer_t *b0, *b1;
633  vnet_hw_interface_t *hi0, *hi1;
634 
635  /* Prefetch next iteration. */
636  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
637  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
638 
639  bi0 = from[0];
640  bi1 = from[1];
641  to_next[0] = bi0;
642  to_next[1] = bi1;
643  from += 2;
644  to_next += 2;
645  n_left_to_next -= 2;
646  n_left_from -= 2;
647 
648  b0 = vlib_get_buffer (vm, bi0);
649  b1 = vlib_get_buffer (vm, bi1);
650 
651  hi0 =
653  vnet_buffer (b0)->sw_if_index
654  [VLIB_TX]);
655  hi1 =
657  vnet_buffer (b1)->sw_if_index
658  [VLIB_TX]);
659 
660  next0 = hi0->hw_if_index;
661  next1 = hi1->hw_if_index;
662 
663  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
664  n_left_to_next, bi0, bi1, next0,
665  next1);
666  }
667 
668  while (n_left_from > 0 && n_left_to_next > 0)
669  {
670  u32 bi0, next0;
671  vlib_buffer_t *b0;
672  vnet_hw_interface_t *hi0;
673 
674  bi0 = from[0];
675  to_next[0] = bi0;
676  from += 1;
677  to_next += 1;
678  n_left_to_next -= 1;
679  n_left_from -= 1;
680 
681  b0 = vlib_get_buffer (vm, bi0);
682 
683  hi0 =
685  vnet_buffer (b0)->sw_if_index
686  [VLIB_TX]);
687 
688  next0 = hi0->hw_if_index;
689 
690  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
691  n_left_to_next, bi0, next0);
692  }
693 
694  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
695  }
696 
697  return frame->n_vectors;
698 }
699 
702 {
703  vlib_node_t *n;
704  u32 ci, ni;
705 
706  ni = vlib_error_get_node (e);
707  n = vlib_get_node (vm, ni);
708 
709  ci = vlib_error_get_code (e);
710  ASSERT (ci < n->n_errors);
711 
712  ci += n->error_heap_index;
713 
714  return ci;
715 }
716 
717 static u8 *
718 format_vnet_error_trace (u8 * s, va_list * va)
719 {
720  vlib_main_t *vm = va_arg (*va, vlib_main_t *);
721  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
722  vlib_error_t *e = va_arg (*va, vlib_error_t *);
723  vlib_node_t *error_node;
724  vlib_error_main_t *em = &vm->error_main;
725  u32 i;
726 
727  error_node = vlib_get_node (vm, vlib_error_get_node (e[0]));
728  i = counter_index (vm, e[0]);
729  s = format (s, "%v: %s", error_node->name, em->error_strings_heap[i]);
730 
731  return s;
732 }
733 
734 static void
736  vlib_node_runtime_t * node, vlib_frame_t * frame)
737 {
738  u32 n_left, *buffers;
739 
740  buffers = vlib_frame_vector_args (frame);
741  n_left = frame->n_vectors;
742 
743  while (n_left >= 4)
744  {
745  u32 bi0, bi1;
746  vlib_buffer_t *b0, *b1;
747  vlib_error_t *t0, *t1;
748 
749  /* Prefetch next iteration. */
750  vlib_prefetch_buffer_with_index (vm, buffers[2], LOAD);
751  vlib_prefetch_buffer_with_index (vm, buffers[3], LOAD);
752 
753  bi0 = buffers[0];
754  bi1 = buffers[1];
755 
756  b0 = vlib_get_buffer (vm, bi0);
757  b1 = vlib_get_buffer (vm, bi1);
758 
759  if (b0->flags & VLIB_BUFFER_IS_TRACED)
760  {
761  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
762  t0[0] = b0->error;
763  }
764  if (b1->flags & VLIB_BUFFER_IS_TRACED)
765  {
766  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
767  t1[0] = b1->error;
768  }
769  buffers += 2;
770  n_left -= 2;
771  }
772 
773  while (n_left >= 1)
774  {
775  u32 bi0;
776  vlib_buffer_t *b0;
777  vlib_error_t *t0;
778 
779  bi0 = buffers[0];
780 
781  b0 = vlib_get_buffer (vm, bi0);
782 
783  if (b0->flags & VLIB_BUFFER_IS_TRACED)
784  {
785  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
786  t0[0] = b0->error;
787  }
788  buffers += 1;
789  n_left -= 1;
790  }
791 }
792 
793 static u8 *
795 {
796  uword node_index = vlib_error_get_node (e[0]);
797  uword code = vlib_error_get_code (e[0]);
798  vlib_node_t *n;
799 
800  if (node_index >= vec_len (vm->node_main.nodes))
801  return format (0, "[%d], node index out of range 0x%x, error 0x%x",
802  index, node_index, e[0]);
803 
804  n = vlib_get_node (vm, node_index);
805  if (code >= n->n_errors)
806  return format (0, "[%d], code %d out of range for node %v",
807  index, code, n->name);
808 
809  return 0;
810 }
811 
812 static u8 *
814  vlib_node_runtime_t * node, vlib_frame_t * f)
815 {
816  u32 *buffers = vlib_frame_args (f);
817  vlib_buffer_t *b;
818  u8 *msg = 0;
819  uword i;
820 
821  for (i = 0; i < f->n_vectors; i++)
822  {
823  b = vlib_get_buffer (vm, buffers[i]);
824  msg = validate_error (vm, &b->error, i);
825  if (msg)
826  return msg;
827  }
828 
829  return msg;
830 }
831 
832 typedef enum
833 {
838 
839 always_inline void
841 {
842  vlib_error_main_t *em = &vm->error_main;
843  u32 i = counter_index (vm, a);
844  em->counters[i] += 1;
845  vlib_error_elog_count (vm, i, 1);
846 }
847 
850  vlib_node_runtime_t * node,
851  vlib_frame_t * frame, vnet_error_disposition_t disposition)
852 {
853  vnet_main_t *vnm = vnet_get_main ();
854  vlib_error_main_t *em = &vm->error_main;
855  u32 *buffers, *first_buffer;
856  vlib_error_t current_error;
857  u32 current_counter_index, n_errors_left;
858  u32 current_sw_if_index, n_errors_current_sw_if_index;
859  u64 current_counter;
861  u32 cpu_index = vm->cpu_index;
862 
864  static char memory_init[VNET_ERROR_N_DISPOSITION];
865 
866  buffers = vlib_frame_args (frame);
867  first_buffer = buffers;
868 
869  {
870  vlib_buffer_t *b = vlib_get_buffer (vm, first_buffer[0]);
871 
872  if (!memory_init[disposition])
873  {
874  memory_init[disposition] = 1;
875  memory[disposition] = b->error;
876  }
877 
878  current_sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
879  n_errors_current_sw_if_index = 0;
880  }
881 
882  current_error = memory[disposition];
883  current_counter_index = counter_index (vm, memory[disposition]);
884  current_counter = em->counters[current_counter_index];
885 
886  if (node->flags & VLIB_NODE_FLAG_TRACE)
887  trace_errors_with_buffers (vm, node, frame);
888 
889  n_errors_left = frame->n_vectors;
891  (disposition == VNET_ERROR_DISPOSITION_PUNT
894 
895  while (n_errors_left >= 2)
896  {
897  vlib_buffer_t *b0, *b1;
898  vnet_sw_interface_t *sw_if0, *sw_if1;
899  vlib_error_t e0, e1;
900  u32 bi0, bi1;
901  u32 sw_if_index0, sw_if_index1;
902 
903  bi0 = buffers[0];
904  bi1 = buffers[1];
905 
906  buffers += 2;
907  n_errors_left -= 2;
908 
909  b0 = vlib_get_buffer (vm, bi0);
910  b1 = vlib_get_buffer (vm, bi1);
911 
912  e0 = b0->error;
913  e1 = b1->error;
914 
915  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
916  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
917 
918  /* Speculate that sw_if_index == sw_if_index[01]. */
919  n_errors_current_sw_if_index += 2;
920 
921  /* Speculatively assume all 2 (node, code) pairs are equal
922  to current (node, code). */
923  current_counter += 2;
924 
925  if (PREDICT_FALSE (e0 != current_error
926  || e1 != current_error
927  || sw_if_index0 != current_sw_if_index
928  || sw_if_index1 != current_sw_if_index))
929  {
930  current_counter -= 2;
931  n_errors_current_sw_if_index -= 2;
932 
933  vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1);
934  vlib_increment_simple_counter (cm, cpu_index, sw_if_index1, 1);
935 
936  /* Increment super-interface drop/punt counters for
937  sub-interfaces. */
938  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index0);
940  (cm, cpu_index, sw_if0->sup_sw_if_index,
941  sw_if0->sup_sw_if_index != sw_if_index0);
942 
943  sw_if1 = vnet_get_sw_interface (vnm, sw_if_index1);
945  (cm, cpu_index, sw_if1->sup_sw_if_index,
946  sw_if1->sup_sw_if_index != sw_if_index1);
947 
948  em->counters[current_counter_index] = current_counter;
949  do_packet (vm, e0);
950  do_packet (vm, e1);
951 
952  /* For 2 repeated errors, change current error. */
953  if (e0 == e1 && e1 != current_error)
954  {
955  current_error = e0;
956  current_counter_index = counter_index (vm, e0);
957  }
958  current_counter = em->counters[current_counter_index];
959  }
960  }
961 
962  while (n_errors_left >= 1)
963  {
964  vlib_buffer_t *b0;
965  vnet_sw_interface_t *sw_if0;
966  vlib_error_t e0;
967  u32 bi0, sw_if_index0;
968 
969  bi0 = buffers[0];
970 
971  buffers += 1;
972  n_errors_left -= 1;
973  current_counter += 1;
974 
975  b0 = vlib_get_buffer (vm, bi0);
976  e0 = b0->error;
977 
978  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
979 
980  /* Increment drop/punt counters. */
981  vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1);
982 
983  /* Increment super-interface drop/punt counters for sub-interfaces. */
984  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index0);
985  vlib_increment_simple_counter (cm, cpu_index, sw_if0->sup_sw_if_index,
986  sw_if0->sup_sw_if_index != sw_if_index0);
987 
988  if (PREDICT_FALSE (e0 != current_error))
989  {
990  current_counter -= 1;
991 
992  vlib_error_elog_count (vm, current_counter_index,
993  (current_counter
994  - em->counters[current_counter_index]));
995 
996  em->counters[current_counter_index] = current_counter;
997 
998  do_packet (vm, e0);
999  current_error = e0;
1000  current_counter_index = counter_index (vm, e0);
1001  current_counter = em->counters[current_counter_index];
1002  }
1003  }
1004 
1005  if (n_errors_current_sw_if_index > 0)
1006  {
1007  vnet_sw_interface_t *si;
1008 
1009  vlib_increment_simple_counter (cm, cpu_index, current_sw_if_index,
1010  n_errors_current_sw_if_index);
1011 
1012  si = vnet_get_sw_interface (vnm, current_sw_if_index);
1013  if (si->sup_sw_if_index != current_sw_if_index)
1014  vlib_increment_simple_counter (cm, cpu_index, si->sup_sw_if_index,
1015  n_errors_current_sw_if_index);
1016  }
1017 
1018  vlib_error_elog_count (vm, current_counter_index,
1019  (current_counter
1020  - em->counters[current_counter_index]));
1021 
1022  /* Return cached counter. */
1023  em->counters[current_counter_index] = current_counter;
1024 
1025  /* Save memory for next iteration. */
1026  memory[disposition] = current_error;
1027 
1028  if (disposition == VNET_ERROR_DISPOSITION_DROP || !vm->os_punt_frame)
1029  {
1030  vlib_buffer_free (vm, first_buffer, frame->n_vectors);
1031 
1032  /* If there is no punt function, free the frame as well. */
1033  if (disposition == VNET_ERROR_DISPOSITION_PUNT && !vm->os_punt_frame)
1034  vlib_frame_free (vm, node, frame);
1035  }
1036  else
1037  vm->os_punt_frame (vm, node, frame);
1038 
1039  return frame->n_vectors;
1040 }
1041 
1042 static inline void
1045 {
1046  u32 *from;
1047  u32 n_left = f->n_vectors;
1048  vlib_buffer_t *b0, *p1;
1049  u32 bi0;
1050  i16 save_current_data;
1051  u16 save_current_length;
1052 
1053  from = vlib_frame_vector_args (f);
1054 
1055  while (n_left > 0)
1056  {
1057  if (PREDICT_TRUE (n_left > 1))
1058  {
1059  p1 = vlib_get_buffer (vm, from[1]);
1060  vlib_prefetch_buffer_header (p1, LOAD);
1061  }
1062 
1063  bi0 = from[0];
1064  b0 = vlib_get_buffer (vm, bi0);
1065  from++;
1066  n_left--;
1067 
1068  /* See if we're pointedly ignoring this specific error */
1069  if (im->pcap_drop_filter_hash
1070  && hash_get (im->pcap_drop_filter_hash, b0->error))
1071  continue;
1072 
1073  /* Trace all drops, or drops received on a specific interface */
1074  if (im->pcap_sw_if_index == 0 ||
1075  im->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_RX])
1076  {
1077  save_current_data = b0->current_data;
1078  save_current_length = b0->current_length;
1079 
1080  /*
1081  * Typically, we'll need to rewind the buffer
1082  */
1083  if (b0->current_data > 0)
1084  vlib_buffer_advance (b0, (word) - b0->current_data);
1085 
1086  pcap_add_buffer (&im->pcap_main, vm, bi0, 512);
1087 
1088  b0->current_data = save_current_data;
1089  b0->current_length = save_current_length;
1090  }
1091  }
1092 }
1093 
1094 void
1095 vnet_pcap_drop_trace_filter_add_del (u32 error_index, int is_add)
1096 {
1098 
1099  if (im->pcap_drop_filter_hash == 0)
1100  im->pcap_drop_filter_hash = hash_create (0, sizeof (uword));
1101 
1102  if (is_add)
1103  hash_set (im->pcap_drop_filter_hash, error_index, 1);
1104  else
1105  hash_unset (im->pcap_drop_filter_hash, error_index);
1106 }
1107 
1108 static uword
1110  vlib_node_runtime_t * node, vlib_frame_t * frame)
1111 {
1113 
1114  if (PREDICT_FALSE (im->drop_pcap_enable))
1115  pcap_drop_trace (vm, im, frame);
1116 
1117  return process_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_DROP);
1118 }
1119 
1120 static uword
1122  vlib_node_runtime_t * node, vlib_frame_t * frame)
1123 {
1124  return process_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_PUNT);
1125 }
1126 
1127 /* *INDENT-OFF* */
1129  .function = process_drop,
1130  .name = "error-drop",
1131  .flags = VLIB_NODE_FLAG_IS_DROP,
1132  .vector_size = sizeof (u32),
1133  .format_trace = format_vnet_error_trace,
1134  .validate_frame = validate_error_frame,
1135 };
1136 /* *INDENT-ON* */
1137 
1139 
1140 /* *INDENT-OFF* */
1142  .function = process_punt,
1145  .name = "error-punt",
1146  .vector_size = sizeof (u32),
1147  .format_trace = format_vnet_error_trace,
1148  .validate_frame = validate_error_frame,
1149 };
1150 /* *INDENT-ON* */
1151 
1153 
1154 /* *INDENT-OFF* */
1157  .name = "interface-output",
1158  .vector_size = sizeof (u32),
1159 };
1160 /* *INDENT-ON* */
1161 
1164 
1165 static uword
1167  vlib_frame_t * from_frame)
1168 {
1169  vnet_main_t *vnm = vnet_get_main ();
1170  u32 last_sw_if_index = ~0;
1171  vlib_frame_t *to_frame = 0;
1172  vnet_hw_interface_t *hw = 0;
1173  u32 *from, *to_next = 0;
1174  u32 n_left_from;
1175 
1176  from = vlib_frame_vector_args (from_frame);
1177  n_left_from = from_frame->n_vectors;
1178  while (n_left_from > 0)
1179  {
1180  u32 bi0;
1181  vlib_buffer_t *b0;
1182  u32 sw_if_index0;
1183 
1184  bi0 = from[0];
1185  from++;
1186  n_left_from--;
1187  b0 = vlib_get_buffer (vm, bi0);
1188  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
1189 
1190  if (PREDICT_FALSE ((last_sw_if_index != sw_if_index0) || to_frame == 0))
1191  {
1192  if (to_frame)
1193  {
1194  hw = vnet_get_sup_hw_interface (vnm, last_sw_if_index);
1195  vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1196  }
1197  last_sw_if_index = sw_if_index0;
1198  hw = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1199  to_frame = vlib_get_frame_to_node (vm, hw->tx_node_index);
1200  to_next = vlib_frame_vector_args (to_frame);
1201  }
1202 
1203  to_next[0] = bi0;
1204  to_next++;
1205  to_frame->n_vectors++;
1206  }
1207  vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1208  return from_frame->n_vectors;
1209 }
1210 
1211 /* *INDENT-OFF* */
1213  .function = interface_tx_node_fn,
1214  .name = "interface-tx",
1215  .vector_size = sizeof (u32),
1216  .n_next_nodes = 1,
1217  .next_nodes = {
1218  [0] = "error-drop",
1219  },
1220 };
1221 
1222 VNET_FEATURE_ARC_INIT (interface_output, static) =
1223 {
1224  .arc_name = "interface-output",
1225  .start_nodes = VNET_FEATURES (0),
1226  .end_node = "interface-tx",
1228 };
1229 
1230 VNET_FEATURE_INIT (span_tx, static) = {
1231  .arc_name = "interface-output",
1232  .node_name = "span-output",
1233  .runs_before = VNET_FEATURES ("interface-tx"),
1234 };
1235 
1236 VNET_FEATURE_INIT (interface_tx, static) = {
1237  .arc_name = "interface-output",
1238  .node_name = "interface-tx",
1239  .runs_before = 0,
1240 };
1241 /* *INDENT-ON* */
1242 
1243 clib_error_t *
1245  u32 hw_if_index,
1246  u32 is_create)
1247 {
1248  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1249  u32 next_index;
1250 
1251  next_index = vlib_node_add_next_with_slot
1253  hi->output_node_index,
1254  /* next_index */ hw_if_index);
1255 
1256  ASSERT (next_index == hw_if_index);
1257 
1258  return 0;
1259 }
1260 
1263 
1264 static clib_error_t *
1266  unformat_input_t * input,
1267  vlib_cli_command_t * cmd)
1268 {
1269  vnet_main_t *vnm = vnet_get_main ();
1271  u8 *filename;
1272  u32 max;
1273  int matched = 0;
1274  clib_error_t *error = 0;
1275 
1276  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1277  {
1278  if (unformat (input, "on"))
1279  {
1280  if (im->drop_pcap_enable == 0)
1281  {
1282  if (im->pcap_filename == 0)
1283  im->pcap_filename = format (0, "/tmp/drop.pcap%c", 0);
1284 
1285  memset (&im->pcap_main, 0, sizeof (im->pcap_main));
1286  im->pcap_main.file_name = (char *) im->pcap_filename;
1287  im->pcap_main.n_packets_to_capture = 100;
1288  if (im->pcap_pkts_to_capture)
1290 
1291  im->pcap_main.packet_type = PCAP_PACKET_TYPE_ethernet;
1292  im->drop_pcap_enable = 1;
1293  matched = 1;
1294  vlib_cli_output (vm, "pcap drop capture on...");
1295  }
1296  else
1297  {
1298  vlib_cli_output (vm, "pcap drop capture already on...");
1299  }
1300  matched = 1;
1301  }
1302  else if (unformat (input, "off"))
1303  {
1304  matched = 1;
1305 
1306  if (im->drop_pcap_enable)
1307  {
1308  vlib_cli_output (vm, "captured %d pkts...",
1310  if (im->pcap_main.n_packets_captured)
1311  {
1314  error = pcap_write (&im->pcap_main);
1315  if (error)
1316  clib_error_report (error);
1317  else
1318  vlib_cli_output (vm, "saved to %s...", im->pcap_filename);
1319  }
1320  }
1321  else
1322  {
1323  vlib_cli_output (vm, "pcap drop capture already off...");
1324  }
1325 
1326  im->drop_pcap_enable = 0;
1327  }
1328  else if (unformat (input, "max %d", &max))
1329  {
1330  im->pcap_pkts_to_capture = max;
1331  matched = 1;
1332  }
1333 
1334  else if (unformat (input, "intfc %U",
1336  &im->pcap_sw_if_index))
1337  matched = 1;
1338  else if (unformat (input, "intfc any"))
1339  {
1340  im->pcap_sw_if_index = 0;
1341  matched = 1;
1342  }
1343  else if (unformat (input, "file %s", &filename))
1344  {
1345  u8 *chroot_filename;
1346  /* Brain-police user path input */
1347  if (strstr ((char *) filename, "..")
1348  || index ((char *) filename, '/'))
1349  {
1350  vlib_cli_output (vm, "illegal characters in filename '%s'",
1351  filename);
1352  continue;
1353  }
1354 
1355  chroot_filename = format (0, "/tmp/%s%c", filename, 0);
1356  vec_free (filename);
1357 
1358  if (im->pcap_filename)
1359  vec_free (im->pcap_filename);
1360  vec_add1 (filename, 0);
1361  im->pcap_filename = chroot_filename;
1362  matched = 1;
1363  }
1364  else if (unformat (input, "status"))
1365  {
1366  if (im->drop_pcap_enable == 0)
1367  {
1368  vlib_cli_output (vm, "pcap drop capture is off...");
1369  continue;
1370  }
1371 
1372  vlib_cli_output (vm, "pcap drop capture: %d of %d pkts...",
1375  matched = 1;
1376  }
1377 
1378  else
1379  break;
1380  }
1381 
1382  if (matched == 0)
1383  return clib_error_return (0, "unknown input `%U'",
1384  format_unformat_error, input);
1385 
1386  return 0;
1387 }
1388 
1389 /* *INDENT-OFF* */
1390 VLIB_CLI_COMMAND (pcap_trace_command, static) = {
1391  .path = "pcap drop trace",
1392  .short_help =
1393  "pcap drop trace on off max <nn> intfc <intfc> file <name> status",
1394  .function = pcap_drop_trace_command_fn,
1395 };
1396 /* *INDENT-ON* */
1397 
1398 /*
1399  * fd.io coding-style-patch-verification: ON
1400  *
1401  * Local Variables:
1402  * eval: (c-set-style "gnu")
1403  * End:
1404  */
u8 * format_vnet_interface_output_trace(u8 *s, va_list *va)
vnet_config_main_t config_main
Definition: feature.h:66
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 void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 cpu_index, u32 index, u32 increment)
Increment a simple counter.
Definition: counter.h:78
vmrglw vmrglh hi
u32 error_heap_index
Definition: node.h:278
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:621
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
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
#define CLIB_UNUSED(x)
Definition: clib.h:79
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
#define hash_unset(h, key)
Definition: hash.h:260
a
Definition: bitmap.h:516
u8 runtime_data[0]
Definition: node.h:469
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:124
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:57
#define PREDICT_TRUE(x)
Definition: clib.h:98
uword vlib_node_add_next_with_slot(vlib_main_t *vm, uword node_index, uword next_node_index, uword slot)
Definition: node.c:156
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
uword vnet_interface_output_node_flatten(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
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)
unformat_function_t unformat_vnet_sw_interface
static_always_inline int vnet_have_features(u8 arc, u32 sw_if_index)
Definition: feature.h:169
void vnet_pcap_drop_trace_filter_add_del(u32 error_index, int is_add)
#define clib_error_report(e)
Definition: error.h:125
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:377
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
vhost_user_memory_t memory
Definition: vhost-user.h:82
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:78
#define static_always_inline
Definition: clib.h:85
uword * pcap_drop_filter_hash
Definition: interface.h:625
#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:254
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 void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:194
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:615
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
static_always_inline void incr_output_stats(vnet_main_t *vnm, u32 cpu_index, u32 length, u32 sw_if_index, u32 *last_sw_if_index, u32 *n_packets, u32 *n_bytes)
static u32 counter_index(vlib_main_t *vm, vlib_error_t e)
vlib_node_t ** nodes
Definition: node.h:630
#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:128
#define vlib_get_new_next_frame(vm, node, next_index, vectors, n_vectors_left)
Definition: node_funcs.h:355
static u32 vlib_error_get_node(vlib_error_t e)
Definition: error.h:47
u32 cpu_index
Definition: main.h:159
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:59
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)
#define VLIB_BUFFER_NEXT_PRESENT
Definition: buffer.h:97
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
static uword format_get_indent(u8 *s)
Definition: format.h:72
u32 vlib_error_t
Definition: error.h:44
vlib_main_t * vlib_main
Definition: vnet.h:79
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:82
static u8 * format_vnet_error_trace(u8 *s, va_list *va)
vlib_error_main_t error_main
Definition: main.h:124
static u32 vlib_error_get_code(vlib_error_t e)
Definition: error.h:53
void vlib_frame_free(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_frame_t *f)
Definition: main.c:216
VNET_FEATURE_INIT(span_tx, static)
uword vnet_interface_output_node(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
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
vnet_main_t vnet_main
Definition: misc.c:43
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:614
format_function_t * format_buffer
Definition: node.h:311
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:196
#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:350
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:576
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:121
u8 * name
Definition: node.h:221
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)
char ** error_strings_heap
Definition: error.h:85
u16 n_vectors
Definition: node.h:344
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
#define clib_memcpy(a, b, c)
Definition: string.h:69
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:207
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:211
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
Definition: node.h:463
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:528
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u32 packet_increment, u32 byte_increment)
Increment a combined counter.
Definition: counter.h:241
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define VLIB_NODE_FLAG_IS_PUNT
Definition: node.h:255
#define vnet_buffer(b)
Definition: buffer.h:361
void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
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:117
static void * vlib_frame_args(vlib_frame_t *f)
Get pointer to frame scalar data.
Definition: node_funcs.h:270
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:259
static vlib_node_registration_t interface_tx
(constructor) VLIB_REGISTER_NODE (interface_tx)
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:95
#define VNET_FEATURES(...)
Definition: feature.h:363
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:176
vlib_node_main_t node_main
Definition: main.h:115
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:606
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
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 vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:170
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
static void vlib_error_elog_count(vlib_main_t *vm, uword counter, uword increment)
Definition: error_funcs.h:46
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
u16 n_errors
Definition: node.h:271
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
static uword process_punt(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:187
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
#define VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH
Definition: node.h:250
static_always_inline vnet_feature_config_main_t * vnet_feature_get_config_main(u16 arc)
Definition: feature.h:162
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
Definition: defs.h:46
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)