FD.io VPP  v16.06
Vector Packet Processing
interface_output.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  * interface_output.c: interface output node
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #include <vnet/vnet.h>
41 
42 typedef struct {
44  u8 data[128 - sizeof (u32)];
46 
48 {
49  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
50  vlib_node_t * node = va_arg (*va, vlib_node_t *);
52  vnet_main_t * vnm = vnet_get_main();
54  uword indent;
55 
56  if (t->sw_if_index != (u32)~0)
57  {
58  si = vnet_get_sw_interface (vnm, t->sw_if_index);
59  indent = format_get_indent (s);
60 
61  s = format (s, "%U\n%U%U",
63  format_white_space, indent,
65  t->data, sizeof (t->data));
66  }
67  return s;
68 }
69 
70 static void
72  vlib_node_runtime_t * node,
73  vlib_frame_t * frame,
74  uword n_buffers)
75 {
76  u32 n_left, * from;
77 
78  n_left = n_buffers;
79  from = vlib_frame_args (frame);
80 
81  while (n_left >= 4)
82  {
83  u32 bi0, bi1;
84  vlib_buffer_t * b0, * b1;
85  interface_output_trace_t * t0, * t1;
86 
87  /* Prefetch next iteration. */
88  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
89  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
90 
91  bi0 = from[0];
92  bi1 = from[1];
93 
94  b0 = vlib_get_buffer (vm, bi0);
95  b1 = vlib_get_buffer (vm, bi1);
96 
97  if (b0->flags & VLIB_BUFFER_IS_TRACED)
98  {
99  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
100  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
102  sizeof (t0->data));
103  }
104  if (b1->flags & VLIB_BUFFER_IS_TRACED)
105  {
106  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
107  t1->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_TX];
109  sizeof (t1->data));
110  }
111  from += 2;
112  n_left -= 2;
113  }
114 
115  while (n_left >= 1)
116  {
117  u32 bi0;
118  vlib_buffer_t * b0;
120 
121  bi0 = from[0];
122 
123  b0 = vlib_get_buffer (vm, bi0);
124 
125  if (b0->flags & VLIB_BUFFER_IS_TRACED)
126  {
127  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
128  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
130  sizeof (t0->data));
131  }
132  from += 1;
133  n_left -= 1;
134  }
135 }
136 
137 static never_inline u32
139  u32 bi,
140  vlib_buffer_t * b,
141  u32 n_left_to_tx,
142  u32 * to_tx,
143  u32 * n_slow_bytes_result)
144 {
145  /* We've already enqueued a single buffer. */
146  u32 n_buffers = 0;
147  u32 n_slow_bytes = 0;
148 
149  while (n_left_to_tx > 0)
150  {
151  to_tx[0] = bi;
152  to_tx += 1;
153  n_left_to_tx -= 1;
154  n_buffers += 1;
155  n_slow_bytes += vlib_buffer_length_in_chain (vm, b);
156 
157  /* Be grumpy about zero length buffers for benefit of
158  driver tx function. */
159  ASSERT (b->current_length > 0);
160 
161  if (! (b->flags & VLIB_BUFFER_NEXT_PRESENT))
162  break;
163 
164  bi = b->next_buffer;
165  b = vlib_get_buffer (vm, bi);
166  }
167 
168  /* Ran out of space in next frame trying to enqueue buffers? */
170  return 0;
171 
172  *n_slow_bytes_result = n_slow_bytes;
173  return n_buffers;
174 }
175 
176 /*
177  * Increment TX stats. Roll up consecutive increments to the same sw_if_index
178  * into one increment.
179  */
182  u32 cpu_index,
183  u32 length,
184  u32 sw_if_index,
185  u32 * last_sw_if_index,
186  u32 * n_packets,
187  u32 * n_bytes) {
189 
190  if (PREDICT_TRUE (sw_if_index == *last_sw_if_index)) {
191  *n_packets += 1;
192  *n_bytes += length;
193  } else {
194  if (PREDICT_TRUE (*last_sw_if_index != ~0)) {
195  im = &vnm->interface_main;
196 
199  cpu_index,
200  *last_sw_if_index,
201  *n_packets,
202  *n_bytes);
203  }
204  *last_sw_if_index = sw_if_index;
205  *n_packets = 1;
206  *n_bytes = length;
207  }
208 }
209 
210 
211 /* Interface output functions. */
212 uword
214  vlib_node_runtime_t * node,
215  vlib_frame_t * frame)
216 {
217  vnet_main_t * vnm = vnet_get_main();
218  vnet_interface_output_runtime_t * rt = (void *) node->runtime_data;
219  vnet_sw_interface_t * si;
221  u32 n_left_to_tx, * from, * from_end, * to_tx;
222  u32 n_bytes, n_buffers, n_packets;
223  u32 last_sw_if_index;
224  u32 cpu_index = vm->cpu_index;
225 
226  n_buffers = frame->n_vectors;
227 
228  if (node->flags & VLIB_NODE_FLAG_TRACE)
229  vnet_interface_output_trace (vm, node, frame, n_buffers);
230 
231  from = vlib_frame_args (frame);
232 
233  if (rt->is_deleted)
234  return vlib_error_drop_buffers (vm, node,
235  from,
236  /* buffer stride */ 1,
237  n_buffers,
239  node->node_index,
241 
242  si = vnet_get_sw_interface (vnm, rt->sw_if_index);
244  if (! (si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ||
245  ! (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP))
246  {
248 
251  vlib_increment_simple_counter (cm, cpu_index,
252  rt->sw_if_index, n_buffers);
253  return vlib_error_drop_buffers (vm, node,
254  from,
255  /* buffer stride */ 1,
256  n_buffers,
258  node->node_index,
260  }
261 
262  from_end = from + n_buffers;
263 
264  /* Total byte count of all buffers. */
265  n_bytes = 0;
266  n_packets = 0;
267  last_sw_if_index = ~0;
268 
269  while (from < from_end)
270  {
271  /* Get new next frame since previous incomplete frame may have less
272  than VNET_FRAME_SIZE vectors in it. */
274  to_tx, n_left_to_tx);
275 
276  while (from + 4 <= from_end && n_left_to_tx >= 2)
277  {
278  u32 bi0, bi1;
279  vlib_buffer_t * b0, * b1;
280 
281  /* Prefetch next iteration. */
282  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
283  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
284 
285  bi0 = from[0];
286  bi1 = from[1];
287  to_tx[0] = bi0;
288  to_tx[1] = bi1;
289  from += 2;
290  to_tx += 2;
291  n_left_to_tx -= 2;
292 
293  b0 = vlib_get_buffer (vm, bi0);
294  b1 = vlib_get_buffer (vm, bi1);
295 
296  /* Be grumpy about zero length buffers for benefit of
297  driver tx function. */
298  ASSERT (b0->current_length > 0);
299  ASSERT (b1->current_length > 0);
300 
302  {
303  u32 n_buffers, n_slow_bytes, i;
304 
305  /* Undo. */
306  from -= 2;
307  to_tx -= 2;
308  n_left_to_tx += 2;
309 
310  /* Do slow path two times. */
311  for (i = 0; i < 2; i++)
312  {
313  u32 bi = i ? bi1 : bi0;
314  vlib_buffer_t * b = i ? b1 : b0;
315 
316  n_buffers = slow_path (vm, bi, b,
317  n_left_to_tx, to_tx, &n_slow_bytes);
318 
319  /* Not enough room for single packet? */
320  if (n_buffers == 0)
321  goto put;
322 
323  from += 1;
324  to_tx += n_buffers;
325  n_left_to_tx -= n_buffers;
326  incr_output_stats (vnm, cpu_index, n_slow_bytes,
327  vnet_buffer(b)->sw_if_index[VLIB_TX],
328  &last_sw_if_index, &n_packets, &n_bytes);
329  }
330  } else {
331  incr_output_stats (vnm, cpu_index,
333  vnet_buffer(b0)->sw_if_index[VLIB_TX],
334  &last_sw_if_index, &n_packets, &n_bytes);
335  incr_output_stats (vnm, cpu_index,
337  vnet_buffer(b1)->sw_if_index[VLIB_TX],
338  &last_sw_if_index, &n_packets, &n_bytes);
339  }
340  }
341 
342  while (from + 1 <= from_end && n_left_to_tx >= 1)
343  {
344  u32 bi0;
345  vlib_buffer_t * b0;
346 
347  bi0 = from[0];
348  to_tx[0] = bi0;
349  from += 1;
350  to_tx += 1;
351  n_left_to_tx -= 1;
352 
353  b0 = vlib_get_buffer (vm, bi0);
354 
355  /* Be grumpy about zero length buffers for benefit of
356  driver tx function. */
357  ASSERT (b0->current_length > 0);
358 
360  {
361  u32 n_buffers, n_slow_bytes;
362 
363  /* Undo. */
364  from -= 1;
365  to_tx -= 1;
366  n_left_to_tx += 1;
367 
368  n_buffers = slow_path (vm, bi0, b0,
369  n_left_to_tx, to_tx, &n_slow_bytes);
370 
371  /* Not enough room for single packet? */
372  if (n_buffers == 0)
373  goto put;
374 
375  from += 1;
376  to_tx += n_buffers;
377  n_left_to_tx -= n_buffers;
378  }
379  incr_output_stats (vnm, cpu_index,
381  vnet_buffer(b0)->sw_if_index[VLIB_TX],
382  &last_sw_if_index, &n_packets, &n_bytes);
383  }
384 
385  put:
386  vlib_put_next_frame (vm, node, VNET_INTERFACE_OUTPUT_NEXT_TX, n_left_to_tx);
387  }
388 
389  /* Final update of interface stats. */
390  incr_output_stats (vnm, cpu_index, 0, ~0, /* ~0 will flush stats */
391  &last_sw_if_index, &n_packets, &n_bytes);
392 
393  return n_buffers;
394 }
395 
398  vlib_node_runtime_t * node,
399  vlib_frame_t * frame,
400  int with_features)
401 {
402  vnet_main_t * vnm = vnet_get_main();
403  vnet_interface_output_runtime_t * rt = (void *) node->runtime_data;
404  vnet_sw_interface_t * si;
406  u32 n_left_to_tx, * from, * from_end, * to_tx;
407  u32 n_bytes, n_buffers, n_packets;
408  u32 n_bytes_b0, n_bytes_b1;
409  u32 cpu_index = vm->cpu_index;
411  u32 next_index = VNET_INTERFACE_OUTPUT_NEXT_TX;
412 
413  n_buffers = frame->n_vectors;
414 
415  if (node->flags & VLIB_NODE_FLAG_TRACE)
416  vnet_interface_output_trace (vm, node, frame, n_buffers);
417 
418  from = vlib_frame_args (frame);
419 
420  if (rt->is_deleted)
421  return vlib_error_drop_buffers (vm, node,
422  from,
423  /* buffer stride */ 1,
424  n_buffers,
426  node->node_index,
428 
429  si = vnet_get_sw_interface (vnm, rt->sw_if_index);
431  if (! (si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ||
432  ! (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP))
433  {
435 
438  vlib_increment_simple_counter (cm, cpu_index,
439  rt->sw_if_index, n_buffers);
440 
441  return vlib_error_drop_buffers (vm, node,
442  from,
443  /* buffer stride */ 1,
444  n_buffers,
446  node->node_index,
448  }
449 
450  from_end = from + n_buffers;
451 
452  /* Total byte count of all buffers. */
453  n_bytes = 0;
454  n_packets = 0;
455 
456  while (from < from_end)
457  {
458  /* Get new next frame since previous incomplete frame may have less
459  than VNET_FRAME_SIZE vectors in it. */
460  vlib_get_new_next_frame (vm, node, next_index,
461  to_tx, n_left_to_tx);
462 
463  while (from + 4 <= from_end && n_left_to_tx >= 2)
464  {
465  u32 bi0, bi1;
466  vlib_buffer_t * b0, * b1;
467  u32 tx_swif0, tx_swif1;
468  u32 next0, next1;
469 
470  /* Prefetch next iteration. */
471  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
472  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
473 
474  bi0 = from[0];
475  bi1 = from[1];
476  to_tx[0] = bi0;
477  to_tx[1] = bi1;
478  from += 2;
479  to_tx += 2;
480  n_left_to_tx -= 2;
481 
482  b0 = vlib_get_buffer (vm, bi0);
483  b1 = vlib_get_buffer (vm, bi1);
484 
485  /* Be grumpy about zero length buffers for benefit of
486  driver tx function. */
487  ASSERT (b0->current_length > 0);
488  ASSERT (b1->current_length > 0);
489 
490  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b0);
491  n_bytes_b1 = vlib_buffer_length_in_chain (vm, b1);
492  tx_swif0 = vnet_buffer(b0)->sw_if_index[VLIB_TX];
493  tx_swif1 = vnet_buffer(b1)->sw_if_index[VLIB_TX];
494 
495  n_bytes += n_bytes_b0 + n_bytes_b1;
496  n_packets += 2;
497  if (with_features)
498  {
500  vnet_buffer(b0)->output_features.bitmap = si->output_feature_bitmap;
501  count_trailing_zeros(next0, vnet_buffer(b0)->output_features.bitmap);
502  vnet_buffer(b0)->output_features.bitmap &= ~(1 << next0);
503  }
504  else
505  {
507  vnet_buffer(b0)->output_features.bitmap = 0;
508 
509  if (PREDICT_FALSE(tx_swif0 != rt->sw_if_index))
510  {
511  /* update vlan subif tx counts, if required */
512  vlib_increment_combined_counter (im->combined_sw_if_counters
514  cpu_index,
515  tx_swif0,
516  1,
517  n_bytes_b0);
518  }
519  }
520 
521  if (with_features)
522  {
524  vnet_buffer(b1)->output_features.bitmap = si->output_feature_bitmap;
525  count_trailing_zeros(next1, vnet_buffer(b1)->output_features.bitmap);
526  vnet_buffer(b1)->output_features.bitmap &= ~(1 << next1);
527  }
528  else
529  {
531  vnet_buffer(b1)->output_features.bitmap = 0;
532 
533  /* update vlan subif tx counts, if required */
534  if (PREDICT_FALSE(tx_swif1 != rt->sw_if_index))
535  {
536 
537  vlib_increment_combined_counter (im->combined_sw_if_counters
539  cpu_index,
540  tx_swif1,
541  1,
542  n_bytes_b1);
543  }
544  }
545  if (with_features)
546  vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_tx,
547  n_left_to_tx, bi0, bi1, next0, next1);
548  }
549 
550  while (from + 1 <= from_end && n_left_to_tx >= 1)
551  {
552  u32 bi0;
553  vlib_buffer_t * b0;
554  u32 tx_swif0;
555 
556  bi0 = from[0];
557  to_tx[0] = bi0;
558  from += 1;
559  to_tx += 1;
560  n_left_to_tx -= 1;
561 
562  b0 = vlib_get_buffer (vm, bi0);
563 
564  /* Be grumpy about zero length buffers for benefit of
565  driver tx function. */
566  ASSERT (b0->current_length > 0);
567 
568  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b0);
569  tx_swif0 = vnet_buffer(b0)->sw_if_index[VLIB_TX];
570  n_bytes += n_bytes_b0;
571  n_packets += 1;
572 
573  if (with_features)
574  {
575  u32 next0;
577  vnet_buffer(b0)->output_features.bitmap = si->output_feature_bitmap;
578  count_trailing_zeros(next0, vnet_buffer(b0)->output_features.bitmap);
579  vnet_buffer(b0)->output_features.bitmap &= ~(1 << next0);
580  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_tx,
581  n_left_to_tx, bi0, next0);
582  }
583  else
584  {
585  vnet_buffer(b0)->output_features.bitmap = 0;
586 
587  if (PREDICT_FALSE(tx_swif0 != rt->sw_if_index))
588  {
589 
590  vlib_increment_combined_counter (im->combined_sw_if_counters
592  cpu_index,
593  tx_swif0,
594  1,
595  n_bytes_b0);
596  }
597  }
598  }
599 
600  vlib_put_next_frame (vm, node, next_index,
601  n_left_to_tx);
602  }
603 
604  /* Update main interface stats. */
605  vlib_increment_combined_counter (im->combined_sw_if_counters
607  cpu_index,
608  rt->sw_if_index,
609  n_packets,
610  n_bytes);
611  return n_buffers;
612 }
613 
614 uword
616  vlib_node_runtime_t * node,
617  vlib_frame_t * frame)
618 {
619  vnet_main_t * vnm = vnet_get_main ();
620  vnet_interface_output_runtime_t * rt = (void *) node->runtime_data;
621  vnet_sw_interface_t * si;
622  si = vnet_get_sw_interface (vnm, rt->sw_if_index);
623 
624  if (PREDICT_FALSE(si->output_feature_bitmap))
625  {
626  /* if first pakcet in the frame have BUFFER_OUTPUT_FEAT_DONE flag set
627  then whole frame is arriving from feature node */
628 
629  u32 * from = vlib_frame_args (frame);
630  vlib_buffer_t * b = vlib_get_buffer (vm, from[0]);
631 
632  if ((b->flags & BUFFER_OUTPUT_FEAT_DONE) == 0)
633  return vnet_interface_output_node_no_flatten_inline (vm, node, frame, 1);
634  }
635  return vnet_interface_output_node_no_flatten_inline (vm, node, frame, 0);
636 }
637 
638 /* Use buffer's sw_if_index[VNET_TX] to choose output interface. */
639 static uword
641  vlib_node_runtime_t * node,
642  vlib_frame_t * frame)
643 {
644  vnet_main_t * vnm = vnet_get_main();
645  u32 n_left_to_next, * from, * to_next;
646  u32 n_left_from, next_index;
647 
648  n_left_from = frame->n_vectors;
649 
650  from = vlib_frame_args (frame);
651  next_index = node->cached_next_index;
652 
653  while (n_left_from > 0)
654  {
655  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
656 
657  while (n_left_from >= 4 && n_left_to_next >= 2)
658  {
659  u32 bi0, bi1, next0, next1;
660  vlib_buffer_t * b0, * b1;
661  vnet_hw_interface_t * hi0, * hi1;
662 
663  /* Prefetch next iteration. */
664  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
665  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
666 
667  bi0 = from[0];
668  bi1 = from[1];
669  to_next[0] = bi0;
670  to_next[1] = bi1;
671  from += 2;
672  to_next += 2;
673  n_left_to_next -= 2;
674  n_left_from -= 2;
675 
676  b0 = vlib_get_buffer (vm, bi0);
677  b1 = vlib_get_buffer (vm, bi1);
678 
679  hi0 = vnet_get_sup_hw_interface (vnm, vnet_buffer (b0)->sw_if_index[VLIB_TX]);
680  hi1 = vnet_get_sup_hw_interface (vnm, vnet_buffer (b1)->sw_if_index[VLIB_TX]);
681 
682  next0 = hi0->hw_if_index;
683  next1 = hi1->hw_if_index;
684 
685  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, n_left_to_next,
686  bi0, bi1, next0, next1);
687  }
688 
689  while (n_left_from > 0 && n_left_to_next > 0)
690  {
691  u32 bi0, next0;
692  vlib_buffer_t * b0;
693  vnet_hw_interface_t * hi0;
694 
695  bi0 = from[0];
696  to_next[0] = bi0;
697  from += 1;
698  to_next += 1;
699  n_left_to_next -= 1;
700  n_left_from -= 1;
701 
702  b0 = vlib_get_buffer (vm, bi0);
703 
704  hi0 = vnet_get_sup_hw_interface (vnm, vnet_buffer (b0)->sw_if_index[VLIB_TX]);
705 
706  next0 = hi0->hw_if_index;
707 
708  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next,
709  bi0, next0);
710  }
711 
712  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
713  }
714 
715  return frame->n_vectors;
716 }
717 
720 {
721  vlib_node_t * n;
722  u32 ci, ni;
723 
724  ni = vlib_error_get_node (e);
725  n = vlib_get_node (vm, ni);
726 
727  ci = vlib_error_get_code (e);
728  ASSERT (ci < n->n_errors);
729 
730  ci += n->error_heap_index;
731 
732  return ci;
733 }
734 
735 static u8 * format_vnet_error_trace (u8 * s, va_list * va)
736 {
737  vlib_main_t * vm = va_arg (*va, vlib_main_t *);
738  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
739  vlib_error_t * e = va_arg (*va, vlib_error_t *);
740  vlib_node_t * error_node;
741  vlib_error_main_t * em = &vm->error_main;
742  u32 i;
743 
744  error_node = vlib_get_node (vm, vlib_error_get_node (e[0]));
745  i = counter_index (vm, e[0]);
746  s = format (s, "%v: %s", error_node->name, em->error_strings_heap[i]);
747 
748  return s;
749 }
750 
751 static void
753  vlib_node_runtime_t * node,
754  vlib_frame_t * frame)
755 {
756  u32 n_left, * buffers;
757 
758  buffers = vlib_frame_vector_args (frame);
759  n_left = frame->n_vectors;
760 
761  while (n_left >= 4)
762  {
763  u32 bi0, bi1;
764  vlib_buffer_t * b0, * b1;
765  vlib_error_t * t0, * t1;
766 
767  /* Prefetch next iteration. */
768  vlib_prefetch_buffer_with_index (vm, buffers[2], LOAD);
769  vlib_prefetch_buffer_with_index (vm, buffers[3], LOAD);
770 
771  bi0 = buffers[0];
772  bi1 = buffers[1];
773 
774  b0 = vlib_get_buffer (vm, bi0);
775  b1 = vlib_get_buffer (vm, bi1);
776 
777  if (b0->flags & VLIB_BUFFER_IS_TRACED)
778  {
779  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
780  t0[0] = b0->error;
781  }
782  if (b1->flags & VLIB_BUFFER_IS_TRACED)
783  {
784  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
785  t1[0] = b1->error;
786  }
787  buffers += 2;
788  n_left -= 2;
789  }
790 
791  while (n_left >= 1)
792  {
793  u32 bi0;
794  vlib_buffer_t * b0;
795  vlib_error_t * t0;
796 
797  bi0 = buffers[0];
798 
799  b0 = vlib_get_buffer (vm, bi0);
800 
801  if (b0->flags & VLIB_BUFFER_IS_TRACED)
802  {
803  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
804  t0[0] = b0->error;
805  }
806  buffers += 1;
807  n_left -= 1;
808  }
809 }
810 
811 static u8 *
813 {
814  uword node_index = vlib_error_get_node (e[0]);
815  uword code = vlib_error_get_code (e[0]);
816  vlib_node_t * n;
817 
818  if (node_index >= vec_len (vm->node_main.nodes))
819  return format (0, "[%d], node index out of range 0x%x, error 0x%x",
820  index, node_index, e[0]);
821 
822  n = vlib_get_node (vm, node_index);
823  if (code >= n->n_errors)
824  return format (0, "[%d], code %d out of range for node %v",
825  index, code, n->name);
826 
827  return 0;
828 }
829 
830 static u8 *
832  vlib_node_runtime_t * node,
833  vlib_frame_t * f)
834 {
835  u32 * buffers = vlib_frame_args (f);
836  vlib_buffer_t * b;
837  u8 * msg = 0;
838  uword i;
839 
840  for (i = 0; i < f->n_vectors; i++)
841  {
842  b = vlib_get_buffer (vm, buffers[i]);
843  msg = validate_error (vm, &b->error, i);
844  if (msg)
845  return msg;
846  }
847 
848  return msg;
849 }
850 
851 typedef enum {
856 
857 always_inline void
859 {
860  vlib_error_main_t * em = &vm->error_main;
861  u32 i = counter_index (vm, a);
862  em->counters[i] += 1;
863  vlib_error_elog_count (vm, i, 1);
864 }
865 
868  vlib_node_runtime_t * node,
869  vlib_frame_t * frame,
870  vnet_error_disposition_t disposition)
871 {
872  vnet_main_t * vnm = vnet_get_main();
873  vlib_error_main_t * em = &vm->error_main;
874  u32 * buffers, * first_buffer;
875  vlib_error_t current_error;
876  u32 current_counter_index, n_errors_left;
877  u32 current_sw_if_index, n_errors_current_sw_if_index;
878  u64 current_counter;
880  u32 cpu_index = vm->cpu_index;
881 
883  static char memory_init[VNET_ERROR_N_DISPOSITION];
884 
885  buffers = vlib_frame_args (frame);
886  first_buffer = buffers;
887 
888  {
889  vlib_buffer_t * b = vlib_get_buffer (vm, first_buffer[0]);
890 
891  if (! memory_init[disposition])
892  {
893  memory_init[disposition] = 1;
894  memory[disposition] = b->error;
895  }
896 
897  current_sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
898  n_errors_current_sw_if_index = 0;
899  }
900 
901  current_error = memory[disposition];
902  current_counter_index = counter_index (vm, memory[disposition]);
903  current_counter = em->counters[current_counter_index];
904 
905  if (node->flags & VLIB_NODE_FLAG_TRACE)
906  trace_errors_with_buffers (vm, node, frame);
907 
908  n_errors_left = frame->n_vectors;
910  (disposition == VNET_ERROR_DISPOSITION_PUNT
913 
914  while (n_errors_left >= 2)
915  {
916  vlib_buffer_t * b0, * b1;
917  vnet_sw_interface_t * sw_if0, * sw_if1;
918  vlib_error_t e0, e1;
919  u32 bi0, bi1;
920  u32 sw_if_index0, sw_if_index1;
921 
922  bi0 = buffers[0];
923  bi1 = buffers[1];
924 
925  buffers += 2;
926  n_errors_left -= 2;
927 
928  b0 = vlib_get_buffer (vm, bi0);
929  b1 = vlib_get_buffer (vm, bi1);
930 
931  e0 = b0->error;
932  e1 = b1->error;
933 
934  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
935  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
936 
937  /* Speculate that sw_if_index == sw_if_index[01]. */
938  n_errors_current_sw_if_index += 2;
939 
940  /* Speculatively assume all 2 (node, code) pairs are equal
941  to current (node, code). */
942  current_counter += 2;
943 
944  if (PREDICT_FALSE (e0 != current_error
945  || e1 != current_error
946  || sw_if_index0 != current_sw_if_index
947  || sw_if_index1 != current_sw_if_index))
948  {
949  current_counter -= 2;
950  n_errors_current_sw_if_index -= 2;
951 
952  vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1);
953  vlib_increment_simple_counter (cm, cpu_index, sw_if_index1, 1);
954 
955  /* Increment super-interface drop/punt counters for
956  sub-interfaces. */
957  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index0);
959  (cm, cpu_index, sw_if0->sup_sw_if_index,
960  sw_if0->sup_sw_if_index != sw_if_index0);
961 
962  sw_if1 = vnet_get_sw_interface (vnm, sw_if_index1);
964  (cm, cpu_index, sw_if1->sup_sw_if_index,
965  sw_if1->sup_sw_if_index != sw_if_index1);
966 
967  em->counters[current_counter_index] = current_counter;
968  do_packet (vm, e0);
969  do_packet (vm, e1);
970 
971  /* For 2 repeated errors, change current error. */
972  if (e0 == e1 && e1 != current_error)
973  {
974  current_error = e0;
975  current_counter_index = counter_index (vm, e0);
976  }
977  current_counter = em->counters[current_counter_index];
978  }
979  }
980 
981  while (n_errors_left >= 1)
982  {
983  vlib_buffer_t * b0;
984  vnet_sw_interface_t * sw_if0;
985  vlib_error_t e0;
986  u32 bi0, sw_if_index0;
987 
988  bi0 = buffers[0];
989 
990  buffers += 1;
991  n_errors_left -= 1;
992  current_counter += 1;
993 
994  b0 = vlib_get_buffer (vm, bi0);
995  e0 = b0->error;
996 
997  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
998 
999  /* Increment drop/punt counters. */
1000  vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1);
1001 
1002  /* Increment super-interface drop/punt counters for sub-interfaces. */
1003  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index0);
1004  vlib_increment_simple_counter (cm, cpu_index, sw_if0->sup_sw_if_index,
1005  sw_if0->sup_sw_if_index != sw_if_index0);
1006 
1007  if (PREDICT_FALSE (e0 != current_error))
1008  {
1009  current_counter -= 1;
1010 
1011  vlib_error_elog_count (vm, current_counter_index,
1012  (current_counter
1013  - em->counters[current_counter_index]));
1014 
1015  em->counters[current_counter_index] = current_counter;
1016 
1017  do_packet (vm, e0);
1018  current_error = e0;
1019  current_counter_index = counter_index (vm, e0);
1020  current_counter = em->counters[current_counter_index];
1021  }
1022  }
1023 
1024  if (n_errors_current_sw_if_index > 0)
1025  {
1026  vnet_sw_interface_t * si;
1027 
1028  vlib_increment_simple_counter (cm, cpu_index, current_sw_if_index,
1029  n_errors_current_sw_if_index);
1030 
1031  si = vnet_get_sw_interface (vnm, current_sw_if_index);
1032  if (si->sup_sw_if_index != current_sw_if_index)
1033  vlib_increment_simple_counter (cm, cpu_index, si->sup_sw_if_index,
1034  n_errors_current_sw_if_index);
1035  }
1036 
1037  vlib_error_elog_count (vm, current_counter_index,
1038  (current_counter
1039  - em->counters[current_counter_index]));
1040 
1041  /* Return cached counter. */
1042  em->counters[current_counter_index] = current_counter;
1043 
1044  /* Save memory for next iteration. */
1045  memory[disposition] = current_error;
1046 
1047  if (disposition == VNET_ERROR_DISPOSITION_DROP
1048  || ! vm->os_punt_frame)
1049  {
1051  (vm,
1052  first_buffer,
1053  frame->n_vectors);
1054 
1055  /* If there is no punt function, free the frame as well. */
1056  if (disposition == VNET_ERROR_DISPOSITION_PUNT && ! vm->os_punt_frame)
1057  vlib_frame_free (vm, node, frame);
1058  }
1059  else
1060  vm->os_punt_frame (vm, node, frame);
1061 
1062  return frame->n_vectors;
1063 }
1064 
1065 static inline void
1067  vnet_interface_main_t * im,
1068  vlib_frame_t * f)
1069 {
1070  u32 * from;
1071  u32 n_left = f->n_vectors;
1072  vlib_buffer_t * b0, * p1;
1073  u32 bi0;
1074  i16 save_current_data;
1075  u16 save_current_length;
1076 
1077  from = vlib_frame_vector_args (f);
1078 
1079  while (n_left > 0)
1080  {
1081  if (PREDICT_TRUE (n_left > 1))
1082  {
1083  p1 = vlib_get_buffer (vm, from[1]);
1084  vlib_prefetch_buffer_header (p1, LOAD);
1085  }
1086 
1087  bi0 = from[0];
1088  b0 = vlib_get_buffer (vm, bi0);
1089  from++;
1090  n_left--;
1091 
1092  /* See if we're pointedly ignoring this specific error */
1093  if (im->pcap_drop_filter_hash
1094  && hash_get (im->pcap_drop_filter_hash, b0->error))
1095  continue;
1096 
1097  /* Trace all drops, or drops received on a specific interface */
1098  if (im->pcap_sw_if_index == 0 ||
1099  im->pcap_sw_if_index == vnet_buffer(b0)->sw_if_index [VLIB_RX])
1100  {
1101  save_current_data = b0->current_data;
1102  save_current_length = b0->current_length;
1103 
1104  /*
1105  * Typically, we'll need to rewind the buffer
1106  */
1107  if (b0->current_data > 0)
1108  vlib_buffer_advance (b0, (word) -b0->current_data);
1109 
1110  pcap_add_buffer (&im->pcap_main, vm, bi0, 512);
1111 
1112  b0->current_data = save_current_data;
1113  b0->current_length = save_current_length;
1114  }
1115  }
1116 }
1117 
1118 void vnet_pcap_drop_trace_filter_add_del (u32 error_index, int is_add)
1119 {
1121 
1122  if (im->pcap_drop_filter_hash == 0)
1123  im->pcap_drop_filter_hash = hash_create (0, sizeof (uword));
1124 
1125  if (is_add)
1126  hash_set (im->pcap_drop_filter_hash, error_index, 1);
1127  else
1128  hash_unset (im->pcap_drop_filter_hash, error_index);
1129 }
1130 
1131 static uword
1133  vlib_node_runtime_t * node,
1134  vlib_frame_t * frame)
1135 {
1137 
1138  if (PREDICT_FALSE (im->drop_pcap_enable))
1139  pcap_drop_trace (vm, im, frame);
1140 
1141  return process_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_DROP);
1142 }
1143 
1144 static uword
1146  vlib_node_runtime_t * node,
1147  vlib_frame_t * frame)
1148 {
1149  return process_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_PUNT);
1150 }
1151 
1153  .function = process_drop,
1154  .name = "error-drop",
1155  .flags = VLIB_NODE_FLAG_IS_DROP,
1156  .vector_size = sizeof (u32),
1157  .format_trace = format_vnet_error_trace,
1158  .validate_frame = validate_error_frame,
1159 };
1160 
1162  .function = process_punt,
1165  .name = "error-punt",
1166  .vector_size = sizeof (u32),
1167  .format_trace = format_vnet_error_trace,
1168  .validate_frame = validate_error_frame,
1169 };
1170 
1173  .name = "interface-output",
1174  .vector_size = sizeof (u32),
1175 };
1176 
1177 clib_error_t *
1179  u32 hw_if_index,
1180  u32 is_create)
1181 {
1182  vnet_hw_interface_t * hi = vnet_get_hw_interface (vnm, hw_if_index);
1183  u32 next_index;
1184 
1185  next_index = vlib_node_add_next_with_slot
1187  hi->output_node_index,
1188  /* next_index */ hw_if_index);
1189 
1190  ASSERT (next_index == hw_if_index);
1191 
1192  return 0;
1193 }
1194 
1197 
1198 static clib_error_t *
1200  unformat_input_t * input,
1201  vlib_cli_command_t * cmd)
1202 {
1203  vnet_main_t * vnm = vnet_get_main();
1205  u8 * filename;
1206  u32 max;
1207  int matched = 0;
1208  clib_error_t * error = 0;
1209 
1210  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1211  {
1212  if (unformat (input, "on"))
1213  {
1214  if (im->drop_pcap_enable == 0)
1215  {
1216  if (im->pcap_filename == 0)
1217  im->pcap_filename = format (0, "/tmp/drop.pcap%c", 0);
1218 
1219  memset (&im->pcap_main, 0, sizeof (im->pcap_main));
1220  im->pcap_main.file_name = (char *) im->pcap_filename;
1221  im->pcap_main.n_packets_to_capture = 100;
1222  if (im->pcap_pkts_to_capture)
1224 
1225  im->pcap_main.packet_type = PCAP_PACKET_TYPE_ethernet;
1226  im->drop_pcap_enable = 1;
1227  matched = 1;
1228  vlib_cli_output (vm, "pcap drop capture on...");
1229  }
1230  else
1231  {
1232  vlib_cli_output (vm, "pcap drop capture already on...");
1233  }
1234  matched = 1;
1235  }
1236  else if (unformat (input, "off"))
1237  {
1238  matched = 1;
1239 
1240  if (im->drop_pcap_enable)
1241  {
1242  vlib_cli_output (vm, "captured %d pkts...",
1244  if (im->pcap_main.n_packets_captured)
1245  {
1248  error = pcap_write (&im->pcap_main);
1249  if (error)
1250  clib_error_report (error);
1251  else
1252  vlib_cli_output (vm, "saved to %s...", im->pcap_filename);
1253  }
1254  }
1255  else
1256  {
1257  vlib_cli_output (vm, "pcap drop capture already off...");
1258  }
1259 
1260  im->drop_pcap_enable = 0;
1261  }
1262  else if (unformat (input, "max %d", &max))
1263  {
1264  im->pcap_pkts_to_capture = max;
1265  matched = 1;
1266  }
1267 
1268  else if (unformat (input, "intfc %U",
1270  &im->pcap_sw_if_index))
1271  matched = 1;
1272  else if (unformat (input, "intfc any"))
1273  {
1274  im->pcap_sw_if_index = 0;
1275  matched = 1;
1276  }
1277  else if (unformat (input, "file %s", &filename))
1278  {
1279  u8 * chroot_filename;
1280  /* Brain-police user path input */
1281  if (strstr((char *)filename, "..") || index((char *)filename, '/'))
1282  {
1283  vlib_cli_output (vm, "illegal characters in filename '%s'",
1284  filename);
1285  continue;
1286  }
1287 
1288  chroot_filename = format (0, "/tmp/%s%c", filename, 0);
1289  vec_free (filename);
1290 
1291  if (im->pcap_filename)
1292  vec_free (im->pcap_filename);
1293  vec_add1 (filename, 0);
1294  im->pcap_filename = chroot_filename;
1295  matched = 1;
1296  }
1297  else if (unformat (input, "status"))
1298  {
1299  if (im->drop_pcap_enable == 0)
1300  {
1301  vlib_cli_output (vm, "pcap drop capture is off...");
1302  continue;
1303  }
1304 
1305  vlib_cli_output (vm, "pcap drop capture: %d of %d pkts...",
1308  matched = 1;
1309  }
1310 
1311  else
1312  break;
1313  }
1314 
1315  if (matched == 0)
1316  return clib_error_return (0, "unknown input `%U'",
1317  format_unformat_error, input);
1318 
1319  return 0;
1320 }
1321 
1322 VLIB_CLI_COMMAND (pcap_trace_command, static) = {
1323  .path = "pcap drop trace",
1324  .short_help =
1325  "pcap drop trace on off max <nn> intfc <intfc> file <name> status",
1326  .function = pcap_drop_trace_command_fn,
1327 };
u8 * format_vnet_interface_output_trace(u8 *s, va_list *va)
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Definition: main.c:459
vmrglw vmrglh hi
u32 error_heap_index
Definition: node.h:244
#define hash_set(h, key, value)
Definition: hash.h:237
void(* os_punt_frame)(struct vlib_main_t *vm, struct vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: main.h:128
char * file_name
Definition: pcap.h:107
pcap_main_t pcap_main
Definition: interface.h:464
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
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:942
#define hash_unset(h, key)
Definition: hash.h:243
a
Definition: bitmap.h:393
u32 n_packets_to_capture
Definition: pcap.h:110
always_inline vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Definition: node_funcs.h:46
vnet_interface_main_t interface_main
Definition: vnet.h:62
#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:154
#define UNFORMAT_END_OF_INPUT
Definition: format.h:142
always_inline u32 vlib_error_get_node(vlib_error_t e)
Definition: error.h:47
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:480
clib_error_t * vnet_per_buffer_interface_output_hw_interface_add_del(vnet_main_t *vnm, u32 hw_if_index, u32 is_create)
static void vnet_interface_output_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, uword n_buffers)
unformat_function_t unformat_vnet_sw_interface
void vnet_pcap_drop_trace_filter_add_del(u32 error_index, int is_add)
#define clib_error_report(e)
Definition: error.h:126
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:241
always_inline void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:184
always_inline uword unformat_check_input(unformat_input_t *i)
Definition: format.h:168
vhost_user_memory_t memory
Definition: vhost-user.h:79
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:77
#define static_always_inline
Definition: clib.h:85
uword * pcap_drop_filter_hash
Definition: interface.h:468
#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:181
#define VLIB_NODE_FLAG_IS_DROP
Definition: node.h:220
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
always_inline u32 vlib_error_get_code(vlib_error_t e)
Definition: error.h:51
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:458
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:107
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)
always_inline void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u32 packet_increment, u32 byte_increment)
Definition: counter.h:210
vlib_node_t ** nodes
Definition: node.h:570
#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:79
#define vlib_get_new_next_frame(vm, node, next_index, vectors, n_vectors_left)
Definition: node_funcs.h:270
always_inline 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:112
u32 cpu_index
Definition: main.h:159
unsigned long u64
Definition: types.h:89
vlib_node_registration_t drop_buffers
(constructor) VLIB_REGISTER_NODE (drop_buffers)
static void pcap_drop_trace(vlib_main_t *vm, vnet_interface_main_t *im, vlib_frame_t *f)
always_inline void * vlib_frame_vector_args(vlib_frame_t *f)
Definition: node_funcs.h:202
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:93
u8 data[128-sizeof(u32)]
#define hash_get(h, key)
Definition: hash.h:231
format_function_t format_vnet_sw_interface_name
u32 vlib_error_t
Definition: error.h:44
vlib_main_t * vlib_main
Definition: vnet.h:78
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.c:1060
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:81
static u8 * format_vnet_error_trace(u8 *s, va_list *va)
vlib_error_main_t error_main
Definition: main.h:124
void vlib_frame_free(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_frame_t *f)
Definition: main.c:211
uword vnet_interface_output_node(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
always_inline void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 cpu_index, u32 index, u32 increment)
Definition: counter.h:70
vnet_error_disposition_t
static void pcap_add_buffer(pcap_main_t *pm, vlib_main_t *vm, u32 buffer_index, u32 n_bytes_in_trace)
Definition: pcap.h:159
#define PREDICT_FALSE(x)
Definition: clib.h:97
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:457
format_function_t * format_buffer
Definition: node.h:277
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Definition: buffer_node.h:43
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Definition: buffer_node.h:83
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Definition: node_funcs.h:265
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:538
always_inline void * vlib_frame_args(vlib_frame_t *f)
Definition: node_funcs.h:209
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:129
u8 * name
Definition: node.h:187
u64 * counters
Definition: error.h:73
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:80
u16 n_vectors
Definition: node.h:307
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
#define BUFFER_OUTPUT_FEAT_DONE
Definition: buffer.h:65
#define clib_memcpy(a, b, c)
Definition: string.h:63
always_inline vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
always_inline vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
clib_error_t * pcap_write(pcap_main_t *pm)
Definition: pcap.c:62
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:150
#define never_inline
Definition: clib.h:81
#define hash_create(elts, value_bytes)
Definition: hash.h:615
u16 cached_next_index
Definition: node.h:422
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:373
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:87
#define VLIB_NODE_FLAG_IS_PUNT
Definition: node.h:221
#define vnet_buffer(b)
Definition: buffer.h:300
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
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:112
always_inline void vlib_error_elog_count(vlib_main_t *vm, uword counter, uword increment)
Definition: error_funcs.h:46
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:225
uword vnet_interface_output_node_no_flatten(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:91
always_inline uword format_get_indent(u8 *s)
Definition: format.h:72
u64 uword
Definition: types.h:112
VNET_HW_INTERFACE_ADD_DEL_FUNCTION(vnet_per_buffer_interface_output_hw_interface_add_del)
pcap_packet_type_t packet_type
Definition: pcap.h:112
Definition: defs.h:46
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)
always_inline void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:197
unsigned char u8
Definition: types.h:56
vlib_node_main_t node_main
Definition: main.h:115
always_inline vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
always_inline uword vnet_interface_output_node_no_flatten_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int with_features)
always_inline 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
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:162
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:140
u16 n_errors
Definition: node.h:237
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)
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:112
struct _unformat_input_t unformat_input_t
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:84
#define VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH
Definition: node.h:216
uword runtime_data[(128-1 *sizeof(vlib_node_function_t *)-1 *sizeof(vlib_error_t *)-11 *sizeof(u32)-5 *sizeof(u16))/sizeof(uword)]
Definition: node.h:432
always_inline vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
u32 n_packets_captured
Definition: pcap.h:115
always_inline u32 counter_index(vlib_main_t *vm, vlib_error_t e)
Definition: defs.h:45
always_inline void do_packet(vlib_main_t *vm, vlib_error_t a)
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)