FD.io VPP  v17.04-9-g99c0734
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, n_bytes_b2, n_bytes_b3;
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 + 8 <= from_end && n_left_to_tx >= 4)
496  {
497  u32 bi0, bi1, bi2, bi3;
498  vlib_buffer_t *b0, *b1, *b2, *b3;
499  u32 tx_swif0, tx_swif1, tx_swif2, tx_swif3;
500 
501  /* Prefetch next iteration. */
502  vlib_prefetch_buffer_with_index (vm, from[4], LOAD);
503  vlib_prefetch_buffer_with_index (vm, from[5], LOAD);
504  vlib_prefetch_buffer_with_index (vm, from[6], LOAD);
505  vlib_prefetch_buffer_with_index (vm, from[7], LOAD);
506 
507  bi0 = from[0];
508  bi1 = from[1];
509  bi2 = from[2];
510  bi3 = from[3];
511  to_tx[0] = bi0;
512  to_tx[1] = bi1;
513  to_tx[2] = bi2;
514  to_tx[3] = bi3;
515  from += 4;
516  to_tx += 4;
517  n_left_to_tx -= 4;
518 
519  b0 = vlib_get_buffer (vm, bi0);
520  b1 = vlib_get_buffer (vm, bi1);
521  b2 = vlib_get_buffer (vm, bi2);
522  b3 = vlib_get_buffer (vm, bi3);
523 
524  /* Be grumpy about zero length buffers for benefit of
525  driver tx function. */
526  ASSERT (b0->current_length > 0);
527  ASSERT (b1->current_length > 0);
528  ASSERT (b2->current_length > 0);
529  ASSERT (b3->current_length > 0);
530 
531  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b0);
532  n_bytes_b1 = vlib_buffer_length_in_chain (vm, b1);
533  n_bytes_b2 = vlib_buffer_length_in_chain (vm, b2);
534  n_bytes_b3 = vlib_buffer_length_in_chain (vm, b3);
535  tx_swif0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
536  tx_swif1 = vnet_buffer (b1)->sw_if_index[VLIB_TX];
537  tx_swif2 = vnet_buffer (b2)->sw_if_index[VLIB_TX];
538  tx_swif3 = vnet_buffer (b3)->sw_if_index[VLIB_TX];
539 
540  n_bytes += n_bytes_b0 + n_bytes_b1;
541  n_bytes += n_bytes_b2 + n_bytes_b3;
542  n_packets += 4;
543 
544  if (PREDICT_FALSE (current_config_index != ~0))
545  {
546  b0->feature_arc_index = arc;
547  b1->feature_arc_index = arc;
548  b2->feature_arc_index = arc;
549  b3->feature_arc_index = arc;
550  b0->current_config_index = current_config_index;
551  b1->current_config_index = current_config_index;
552  b2->current_config_index = current_config_index;
553  b3->current_config_index = current_config_index;
554  }
555 
556  /* update vlan subif tx counts, if required */
557  if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
558  {
559  vlib_increment_combined_counter (im->combined_sw_if_counters +
561  cpu_index, tx_swif0, 1,
562  n_bytes_b0);
563  }
564 
565  if (PREDICT_FALSE (tx_swif1 != rt->sw_if_index))
566  {
567 
568  vlib_increment_combined_counter (im->combined_sw_if_counters +
570  cpu_index, tx_swif1, 1,
571  n_bytes_b1);
572  }
573 
574  if (PREDICT_FALSE (tx_swif2 != rt->sw_if_index))
575  {
576 
577  vlib_increment_combined_counter (im->combined_sw_if_counters +
579  cpu_index, tx_swif2, 1,
580  n_bytes_b2);
581  }
582  if (PREDICT_FALSE (tx_swif3 != rt->sw_if_index))
583  {
584 
585  vlib_increment_combined_counter (im->combined_sw_if_counters +
587  cpu_index, tx_swif3, 1,
588  n_bytes_b3);
589  }
590  }
591 
592  while (from + 1 <= from_end && n_left_to_tx >= 1)
593  {
594  u32 bi0;
595  vlib_buffer_t *b0;
596  u32 tx_swif0;
597 
598  bi0 = from[0];
599  to_tx[0] = bi0;
600  from += 1;
601  to_tx += 1;
602  n_left_to_tx -= 1;
603 
604  b0 = vlib_get_buffer (vm, bi0);
605 
606  /* Be grumpy about zero length buffers for benefit of
607  driver tx function. */
608  ASSERT (b0->current_length > 0);
609 
610  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b0);
611  tx_swif0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
612  n_bytes += n_bytes_b0;
613  n_packets += 1;
614 
615  if (PREDICT_FALSE (current_config_index != ~0))
616  {
617  b0->feature_arc_index = arc;
618  b0->current_config_index = current_config_index;
619  }
620 
621  if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
622  {
623 
624  vlib_increment_combined_counter (im->combined_sw_if_counters +
626  cpu_index, tx_swif0, 1,
627  n_bytes_b0);
628  }
629  }
630 
631  vlib_put_next_frame (vm, node, next_index, n_left_to_tx);
632  }
633 
634  /* Update main interface stats. */
635  vlib_increment_combined_counter (im->combined_sw_if_counters
637  cpu_index,
638  rt->sw_if_index, n_packets, n_bytes);
639  return n_buffers;
640 }
641 
644 
645 /* Use buffer's sw_if_index[VNET_TX] to choose output interface. */
646 static uword
648  vlib_node_runtime_t * node,
649  vlib_frame_t * frame)
650 {
651  vnet_main_t *vnm = vnet_get_main ();
652  u32 n_left_to_next, *from, *to_next;
653  u32 n_left_from, next_index;
654 
655  n_left_from = frame->n_vectors;
656 
657  from = vlib_frame_args (frame);
658  next_index = node->cached_next_index;
659 
660  while (n_left_from > 0)
661  {
662  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
663 
664  while (n_left_from >= 4 && n_left_to_next >= 2)
665  {
666  u32 bi0, bi1, next0, next1;
667  vlib_buffer_t *b0, *b1;
668  vnet_hw_interface_t *hi0, *hi1;
669 
670  /* Prefetch next iteration. */
671  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
672  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
673 
674  bi0 = from[0];
675  bi1 = from[1];
676  to_next[0] = bi0;
677  to_next[1] = bi1;
678  from += 2;
679  to_next += 2;
680  n_left_to_next -= 2;
681  n_left_from -= 2;
682 
683  b0 = vlib_get_buffer (vm, bi0);
684  b1 = vlib_get_buffer (vm, bi1);
685 
686  hi0 =
688  vnet_buffer (b0)->sw_if_index
689  [VLIB_TX]);
690  hi1 =
692  vnet_buffer (b1)->sw_if_index
693  [VLIB_TX]);
694 
695  next0 = hi0->hw_if_index;
696  next1 = hi1->hw_if_index;
697 
698  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
699  n_left_to_next, bi0, bi1, next0,
700  next1);
701  }
702 
703  while (n_left_from > 0 && n_left_to_next > 0)
704  {
705  u32 bi0, next0;
706  vlib_buffer_t *b0;
707  vnet_hw_interface_t *hi0;
708 
709  bi0 = from[0];
710  to_next[0] = bi0;
711  from += 1;
712  to_next += 1;
713  n_left_to_next -= 1;
714  n_left_from -= 1;
715 
716  b0 = vlib_get_buffer (vm, bi0);
717 
718  hi0 =
720  vnet_buffer (b0)->sw_if_index
721  [VLIB_TX]);
722 
723  next0 = hi0->hw_if_index;
724 
725  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
726  n_left_to_next, bi0, next0);
727  }
728 
729  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
730  }
731 
732  return frame->n_vectors;
733 }
734 
737 {
738  vlib_node_t *n;
739  u32 ci, ni;
740 
741  ni = vlib_error_get_node (e);
742  n = vlib_get_node (vm, ni);
743 
744  ci = vlib_error_get_code (e);
745  ASSERT (ci < n->n_errors);
746 
747  ci += n->error_heap_index;
748 
749  return ci;
750 }
751 
752 static u8 *
753 format_vnet_error_trace (u8 * s, va_list * va)
754 {
755  vlib_main_t *vm = va_arg (*va, vlib_main_t *);
756  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
757  vlib_error_t *e = va_arg (*va, vlib_error_t *);
758  vlib_node_t *error_node;
759  vlib_error_main_t *em = &vm->error_main;
760  u32 i;
761 
762  error_node = vlib_get_node (vm, vlib_error_get_node (e[0]));
763  i = counter_index (vm, e[0]);
764  s = format (s, "%v: %s", error_node->name, em->error_strings_heap[i]);
765 
766  return s;
767 }
768 
769 static void
771  vlib_node_runtime_t * node, vlib_frame_t * frame)
772 {
773  u32 n_left, *buffers;
774 
775  buffers = vlib_frame_vector_args (frame);
776  n_left = frame->n_vectors;
777 
778  while (n_left >= 4)
779  {
780  u32 bi0, bi1;
781  vlib_buffer_t *b0, *b1;
782  vlib_error_t *t0, *t1;
783 
784  /* Prefetch next iteration. */
785  vlib_prefetch_buffer_with_index (vm, buffers[2], LOAD);
786  vlib_prefetch_buffer_with_index (vm, buffers[3], LOAD);
787 
788  bi0 = buffers[0];
789  bi1 = buffers[1];
790 
791  b0 = vlib_get_buffer (vm, bi0);
792  b1 = vlib_get_buffer (vm, bi1);
793 
794  if (b0->flags & VLIB_BUFFER_IS_TRACED)
795  {
796  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
797  t0[0] = b0->error;
798  }
799  if (b1->flags & VLIB_BUFFER_IS_TRACED)
800  {
801  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
802  t1[0] = b1->error;
803  }
804  buffers += 2;
805  n_left -= 2;
806  }
807 
808  while (n_left >= 1)
809  {
810  u32 bi0;
811  vlib_buffer_t *b0;
812  vlib_error_t *t0;
813 
814  bi0 = buffers[0];
815 
816  b0 = vlib_get_buffer (vm, bi0);
817 
818  if (b0->flags & VLIB_BUFFER_IS_TRACED)
819  {
820  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
821  t0[0] = b0->error;
822  }
823  buffers += 1;
824  n_left -= 1;
825  }
826 }
827 
828 static u8 *
830 {
831  uword node_index = vlib_error_get_node (e[0]);
832  uword code = vlib_error_get_code (e[0]);
833  vlib_node_t *n;
834 
835  if (node_index >= vec_len (vm->node_main.nodes))
836  return format (0, "[%d], node index out of range 0x%x, error 0x%x",
837  index, node_index, e[0]);
838 
839  n = vlib_get_node (vm, node_index);
840  if (code >= n->n_errors)
841  return format (0, "[%d], code %d out of range for node %v",
842  index, code, n->name);
843 
844  return 0;
845 }
846 
847 static u8 *
849  vlib_node_runtime_t * node, vlib_frame_t * f)
850 {
851  u32 *buffers = vlib_frame_args (f);
852  vlib_buffer_t *b;
853  u8 *msg = 0;
854  uword i;
855 
856  for (i = 0; i < f->n_vectors; i++)
857  {
858  b = vlib_get_buffer (vm, buffers[i]);
859  msg = validate_error (vm, &b->error, i);
860  if (msg)
861  return msg;
862  }
863 
864  return msg;
865 }
866 
867 typedef enum
868 {
873 
874 always_inline void
876 {
877  vlib_error_main_t *em = &vm->error_main;
878  u32 i = counter_index (vm, a);
879  em->counters[i] += 1;
880  vlib_error_elog_count (vm, i, 1);
881 }
882 
885  vlib_node_runtime_t * node,
886  vlib_frame_t * frame, vnet_error_disposition_t disposition)
887 {
888  vnet_main_t *vnm = vnet_get_main ();
889  vlib_error_main_t *em = &vm->error_main;
890  u32 *buffers, *first_buffer;
891  vlib_error_t current_error;
892  u32 current_counter_index, n_errors_left;
893  u32 current_sw_if_index, n_errors_current_sw_if_index;
894  u64 current_counter;
896  u32 cpu_index = vm->cpu_index;
897 
899  static char memory_init[VNET_ERROR_N_DISPOSITION];
900 
901  buffers = vlib_frame_args (frame);
902  first_buffer = buffers;
903 
904  {
905  vlib_buffer_t *b = vlib_get_buffer (vm, first_buffer[0]);
906 
907  if (!memory_init[disposition])
908  {
909  memory_init[disposition] = 1;
910  memory[disposition] = b->error;
911  }
912 
913  current_sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
914  n_errors_current_sw_if_index = 0;
915  }
916 
917  current_error = memory[disposition];
918  current_counter_index = counter_index (vm, memory[disposition]);
919  current_counter = em->counters[current_counter_index];
920 
921  if (node->flags & VLIB_NODE_FLAG_TRACE)
922  trace_errors_with_buffers (vm, node, frame);
923 
924  n_errors_left = frame->n_vectors;
926  (disposition == VNET_ERROR_DISPOSITION_PUNT
929 
930  while (n_errors_left >= 2)
931  {
932  vlib_buffer_t *b0, *b1;
933  vnet_sw_interface_t *sw_if0, *sw_if1;
934  vlib_error_t e0, e1;
935  u32 bi0, bi1;
936  u32 sw_if_index0, sw_if_index1;
937 
938  bi0 = buffers[0];
939  bi1 = buffers[1];
940 
941  buffers += 2;
942  n_errors_left -= 2;
943 
944  b0 = vlib_get_buffer (vm, bi0);
945  b1 = vlib_get_buffer (vm, bi1);
946 
947  e0 = b0->error;
948  e1 = b1->error;
949 
950  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
951  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
952 
953  /* Speculate that sw_if_index == sw_if_index[01]. */
954  n_errors_current_sw_if_index += 2;
955 
956  /* Speculatively assume all 2 (node, code) pairs are equal
957  to current (node, code). */
958  current_counter += 2;
959 
960  if (PREDICT_FALSE (e0 != current_error
961  || e1 != current_error
962  || sw_if_index0 != current_sw_if_index
963  || sw_if_index1 != current_sw_if_index))
964  {
965  current_counter -= 2;
966  n_errors_current_sw_if_index -= 2;
967 
968  vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1);
969  vlib_increment_simple_counter (cm, cpu_index, sw_if_index1, 1);
970 
971  /* Increment super-interface drop/punt counters for
972  sub-interfaces. */
973  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index0);
975  (cm, cpu_index, sw_if0->sup_sw_if_index,
976  sw_if0->sup_sw_if_index != sw_if_index0);
977 
978  sw_if1 = vnet_get_sw_interface (vnm, sw_if_index1);
980  (cm, cpu_index, sw_if1->sup_sw_if_index,
981  sw_if1->sup_sw_if_index != sw_if_index1);
982 
983  em->counters[current_counter_index] = current_counter;
984  do_packet (vm, e0);
985  do_packet (vm, e1);
986 
987  /* For 2 repeated errors, change current error. */
988  if (e0 == e1 && e1 != current_error)
989  {
990  current_error = e0;
991  current_counter_index = counter_index (vm, e0);
992  }
993  current_counter = em->counters[current_counter_index];
994  }
995  }
996 
997  while (n_errors_left >= 1)
998  {
999  vlib_buffer_t *b0;
1000  vnet_sw_interface_t *sw_if0;
1001  vlib_error_t e0;
1002  u32 bi0, sw_if_index0;
1003 
1004  bi0 = buffers[0];
1005 
1006  buffers += 1;
1007  n_errors_left -= 1;
1008  current_counter += 1;
1009 
1010  b0 = vlib_get_buffer (vm, bi0);
1011  e0 = b0->error;
1012 
1013  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1014 
1015  /* Increment drop/punt counters. */
1016  vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1);
1017 
1018  /* Increment super-interface drop/punt counters for sub-interfaces. */
1019  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index0);
1020  vlib_increment_simple_counter (cm, cpu_index, sw_if0->sup_sw_if_index,
1021  sw_if0->sup_sw_if_index != sw_if_index0);
1022 
1023  if (PREDICT_FALSE (e0 != current_error))
1024  {
1025  current_counter -= 1;
1026 
1027  vlib_error_elog_count (vm, current_counter_index,
1028  (current_counter
1029  - em->counters[current_counter_index]));
1030 
1031  em->counters[current_counter_index] = current_counter;
1032 
1033  do_packet (vm, e0);
1034  current_error = e0;
1035  current_counter_index = counter_index (vm, e0);
1036  current_counter = em->counters[current_counter_index];
1037  }
1038  }
1039 
1040  if (n_errors_current_sw_if_index > 0)
1041  {
1042  vnet_sw_interface_t *si;
1043 
1044  vlib_increment_simple_counter (cm, cpu_index, current_sw_if_index,
1045  n_errors_current_sw_if_index);
1046 
1047  si = vnet_get_sw_interface (vnm, current_sw_if_index);
1048  if (si->sup_sw_if_index != current_sw_if_index)
1049  vlib_increment_simple_counter (cm, cpu_index, si->sup_sw_if_index,
1050  n_errors_current_sw_if_index);
1051  }
1052 
1053  vlib_error_elog_count (vm, current_counter_index,
1054  (current_counter
1055  - em->counters[current_counter_index]));
1056 
1057  /* Return cached counter. */
1058  em->counters[current_counter_index] = current_counter;
1059 
1060  /* Save memory for next iteration. */
1061  memory[disposition] = current_error;
1062 
1063  if (disposition == VNET_ERROR_DISPOSITION_DROP || !vm->os_punt_frame)
1064  {
1065  vlib_buffer_free (vm, first_buffer, frame->n_vectors);
1066 
1067  /* If there is no punt function, free the frame as well. */
1068  if (disposition == VNET_ERROR_DISPOSITION_PUNT && !vm->os_punt_frame)
1069  vlib_frame_free (vm, node, frame);
1070  }
1071  else
1072  vm->os_punt_frame (vm, node, frame);
1073 
1074  return frame->n_vectors;
1075 }
1076 
1077 static inline void
1080 {
1081  u32 *from;
1082  u32 n_left = f->n_vectors;
1083  vlib_buffer_t *b0, *p1;
1084  u32 bi0;
1085  i16 save_current_data;
1086  u16 save_current_length;
1087 
1088  from = vlib_frame_vector_args (f);
1089 
1090  while (n_left > 0)
1091  {
1092  if (PREDICT_TRUE (n_left > 1))
1093  {
1094  p1 = vlib_get_buffer (vm, from[1]);
1095  vlib_prefetch_buffer_header (p1, LOAD);
1096  }
1097 
1098  bi0 = from[0];
1099  b0 = vlib_get_buffer (vm, bi0);
1100  from++;
1101  n_left--;
1102 
1103  /* See if we're pointedly ignoring this specific error */
1104  if (im->pcap_drop_filter_hash
1105  && hash_get (im->pcap_drop_filter_hash, b0->error))
1106  continue;
1107 
1108  /* Trace all drops, or drops received on a specific interface */
1109  if (im->pcap_sw_if_index == 0 ||
1110  im->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_RX])
1111  {
1112  save_current_data = b0->current_data;
1113  save_current_length = b0->current_length;
1114 
1115  /*
1116  * Typically, we'll need to rewind the buffer
1117  */
1118  if (b0->current_data > 0)
1119  vlib_buffer_advance (b0, (word) - b0->current_data);
1120 
1121  pcap_add_buffer (&im->pcap_main, vm, bi0, 512);
1122 
1123  b0->current_data = save_current_data;
1124  b0->current_length = save_current_length;
1125  }
1126  }
1127 }
1128 
1129 void
1130 vnet_pcap_drop_trace_filter_add_del (u32 error_index, int is_add)
1131 {
1133 
1134  if (im->pcap_drop_filter_hash == 0)
1135  im->pcap_drop_filter_hash = hash_create (0, sizeof (uword));
1136 
1137  if (is_add)
1138  hash_set (im->pcap_drop_filter_hash, error_index, 1);
1139  else
1140  hash_unset (im->pcap_drop_filter_hash, error_index);
1141 }
1142 
1143 static uword
1145  vlib_node_runtime_t * node, vlib_frame_t * frame)
1146 {
1148 
1149  if (PREDICT_FALSE (im->drop_pcap_enable))
1150  pcap_drop_trace (vm, im, frame);
1151 
1152  return process_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_DROP);
1153 }
1154 
1155 static uword
1157  vlib_node_runtime_t * node, vlib_frame_t * frame)
1158 {
1159  return process_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_PUNT);
1160 }
1161 
1162 /* *INDENT-OFF* */
1164  .function = process_drop,
1165  .name = "error-drop",
1166  .flags = VLIB_NODE_FLAG_IS_DROP,
1167  .vector_size = sizeof (u32),
1168  .format_trace = format_vnet_error_trace,
1169  .validate_frame = validate_error_frame,
1170 };
1171 /* *INDENT-ON* */
1172 
1174 
1175 /* *INDENT-OFF* */
1177  .function = process_punt,
1180  .name = "error-punt",
1181  .vector_size = sizeof (u32),
1182  .format_trace = format_vnet_error_trace,
1183  .validate_frame = validate_error_frame,
1184 };
1185 /* *INDENT-ON* */
1186 
1188 
1189 /* *INDENT-OFF* */
1192  .name = "interface-output",
1193  .vector_size = sizeof (u32),
1194 };
1195 /* *INDENT-ON* */
1196 
1199 
1200 static uword
1202  vlib_frame_t * from_frame)
1203 {
1204  vnet_main_t *vnm = vnet_get_main ();
1205  u32 last_sw_if_index = ~0;
1206  vlib_frame_t *to_frame = 0;
1207  vnet_hw_interface_t *hw = 0;
1208  u32 *from, *to_next = 0;
1209  u32 n_left_from;
1210 
1211  from = vlib_frame_vector_args (from_frame);
1212  n_left_from = from_frame->n_vectors;
1213  while (n_left_from > 0)
1214  {
1215  u32 bi0;
1216  vlib_buffer_t *b0;
1217  u32 sw_if_index0;
1218 
1219  bi0 = from[0];
1220  from++;
1221  n_left_from--;
1222  b0 = vlib_get_buffer (vm, bi0);
1223  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
1224 
1225  if (PREDICT_FALSE ((last_sw_if_index != sw_if_index0) || to_frame == 0))
1226  {
1227  if (to_frame)
1228  {
1229  hw = vnet_get_sup_hw_interface (vnm, last_sw_if_index);
1230  vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1231  }
1232  last_sw_if_index = sw_if_index0;
1233  hw = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1234  to_frame = vlib_get_frame_to_node (vm, hw->tx_node_index);
1235  to_next = vlib_frame_vector_args (to_frame);
1236  }
1237 
1238  to_next[0] = bi0;
1239  to_next++;
1240  to_frame->n_vectors++;
1241  }
1242  vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1243  return from_frame->n_vectors;
1244 }
1245 
1246 /* *INDENT-OFF* */
1248  .function = interface_tx_node_fn,
1249  .name = "interface-tx",
1250  .vector_size = sizeof (u32),
1251  .n_next_nodes = 1,
1252  .next_nodes = {
1253  [0] = "error-drop",
1254  },
1255 };
1256 
1257 VNET_FEATURE_ARC_INIT (interface_output, static) =
1258 {
1259  .arc_name = "interface-output",
1260  .start_nodes = VNET_FEATURES (0),
1262 };
1263 
1264 VNET_FEATURE_INIT (span_tx, static) = {
1265  .arc_name = "interface-output",
1266  .node_name = "span-output",
1267  .runs_before = VNET_FEATURES ("interface-tx"),
1268 };
1269 
1270 VNET_FEATURE_INIT (interface_tx, static) = {
1271  .arc_name = "interface-output",
1272  .node_name = "interface-tx",
1273  .runs_before = 0,
1274 };
1275 /* *INDENT-ON* */
1276 
1277 clib_error_t *
1279  u32 hw_if_index,
1280  u32 is_create)
1281 {
1282  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1283  u32 next_index;
1284 
1285  next_index = vlib_node_add_next_with_slot
1287  hi->output_node_index,
1288  /* next_index */ hw_if_index);
1289 
1290  ASSERT (next_index == hw_if_index);
1291 
1292  return 0;
1293 }
1294 
1297 
1298 static clib_error_t *
1300  unformat_input_t * input,
1301  vlib_cli_command_t * cmd)
1302 {
1303  vnet_main_t *vnm = vnet_get_main ();
1305  u8 *filename;
1306  u32 max;
1307  int matched = 0;
1308  clib_error_t *error = 0;
1309 
1310  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1311  {
1312  if (unformat (input, "on"))
1313  {
1314  if (im->drop_pcap_enable == 0)
1315  {
1316  if (im->pcap_filename == 0)
1317  im->pcap_filename = format (0, "/tmp/drop.pcap%c", 0);
1318 
1319  memset (&im->pcap_main, 0, sizeof (im->pcap_main));
1320  im->pcap_main.file_name = (char *) im->pcap_filename;
1321  im->pcap_main.n_packets_to_capture = 100;
1322  if (im->pcap_pkts_to_capture)
1324 
1325  im->pcap_main.packet_type = PCAP_PACKET_TYPE_ethernet;
1326  im->drop_pcap_enable = 1;
1327  matched = 1;
1328  vlib_cli_output (vm, "pcap drop capture on...");
1329  }
1330  else
1331  {
1332  vlib_cli_output (vm, "pcap drop capture already on...");
1333  }
1334  matched = 1;
1335  }
1336  else if (unformat (input, "off"))
1337  {
1338  matched = 1;
1339 
1340  if (im->drop_pcap_enable)
1341  {
1342  vlib_cli_output (vm, "captured %d pkts...",
1344  if (im->pcap_main.n_packets_captured)
1345  {
1348  error = pcap_write (&im->pcap_main);
1349  if (error)
1350  clib_error_report (error);
1351  else
1352  vlib_cli_output (vm, "saved to %s...", im->pcap_filename);
1353  }
1354  }
1355  else
1356  {
1357  vlib_cli_output (vm, "pcap drop capture already off...");
1358  }
1359 
1360  im->drop_pcap_enable = 0;
1361  }
1362  else if (unformat (input, "max %d", &max))
1363  {
1364  im->pcap_pkts_to_capture = max;
1365  matched = 1;
1366  }
1367 
1368  else if (unformat (input, "intfc %U",
1370  &im->pcap_sw_if_index))
1371  matched = 1;
1372  else if (unformat (input, "intfc any"))
1373  {
1374  im->pcap_sw_if_index = 0;
1375  matched = 1;
1376  }
1377  else if (unformat (input, "file %s", &filename))
1378  {
1379  u8 *chroot_filename;
1380  /* Brain-police user path input */
1381  if (strstr ((char *) filename, "..")
1382  || index ((char *) filename, '/'))
1383  {
1384  vlib_cli_output (vm, "illegal characters in filename '%s'",
1385  filename);
1386  continue;
1387  }
1388 
1389  chroot_filename = format (0, "/tmp/%s%c", filename, 0);
1390  vec_free (filename);
1391 
1392  if (im->pcap_filename)
1393  vec_free (im->pcap_filename);
1394  vec_add1 (filename, 0);
1395  im->pcap_filename = chroot_filename;
1396  matched = 1;
1397  }
1398  else if (unformat (input, "status"))
1399  {
1400  if (im->drop_pcap_enable == 0)
1401  {
1402  vlib_cli_output (vm, "pcap drop capture is off...");
1403  continue;
1404  }
1405 
1406  vlib_cli_output (vm, "pcap drop capture: %d of %d pkts...",
1409  matched = 1;
1410  }
1411 
1412  else
1413  break;
1414  }
1415 
1416  if (matched == 0)
1417  return clib_error_return (0, "unknown input `%U'",
1418  format_unformat_error, input);
1419 
1420  return 0;
1421 }
1422 
1423 /* *INDENT-OFF* */
1424 VLIB_CLI_COMMAND (pcap_trace_command, static) = {
1425  .path = "pcap drop trace",
1426  .short_help =
1427  "pcap drop trace on off max <nn> intfc <intfc> file <name> status",
1428  .function = pcap_drop_trace_command_fn,
1429 };
1430 /* *INDENT-ON* */
1431 
1432 /*
1433  * fd.io coding-style-patch-verification: ON
1434  *
1435  * Local Variables:
1436  * eval: (c-set-style "gnu")
1437  * End:
1438  */
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: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:632
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#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_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:463
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:57
#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)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
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:418
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:379
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:85
#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:636
#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 uword format_get_indent(u8 *s)
Definition: format.h:72
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:626
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:633
#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:156
#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:355
#define clib_error_return(e, args...)
Definition: error.h:111
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: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:79
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
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:625
format_function_t * format_buffer
Definition: node.h:311
u32 node_index
Node index.
Definition: node.h:436
#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
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: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)
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
char ** error_strings_heap
Definition: error.h:85
u16 n_vectors
Definition: node.h:344
vlib_main_t * vm
Definition: buffer.c:276
#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:455
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:536
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:211
#define VLIB_NODE_FLAG_IS_PUNT
Definition: node.h:255
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:125
static void * vlib_frame_args(vlib_frame_t *f)
Get pointer to frame scalar data.
Definition: node_funcs.h:270
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:259
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:617
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 vnet_buffer(b)
Definition: buffer.h:294
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:143
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
u16 flags
Copy of main node flags.
Definition: node.h:449
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:250
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:577
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
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 cpu_index, u32 index, u64 increment)
Increment a simple counter.
Definition: counter.h:78
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:971
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)