FD.io VPP  v19.01.3-6-g70449b9b9
Vector Packet Processing
interface_output.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  * interface_output.c: interface output node
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #include <vnet/vnet.h>
41 #include <vnet/ip/icmp46_packet.h>
42 #include <vnet/ip/ip4.h>
43 #include <vnet/ip/ip6.h>
44 #include <vnet/udp/udp_packet.h>
45 #include <vnet/feature/feature.h>
46 
47 typedef struct
48 {
50  u8 data[128 - sizeof (u32)];
51 }
53 
54 u8 *
56 {
57  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
58  vlib_node_t *node = va_arg (*va, vlib_node_t *);
60  vnet_main_t *vnm = vnet_get_main ();
62  u32 indent;
63 
64  if (t->sw_if_index != (u32) ~ 0)
65  {
66  indent = format_get_indent (s);
67 
70  {
71  /* the interface may have been deleted by the time the trace is printed */
72  s = format (s, "sw_if_index: %d\n%U%U",
73  t->sw_if_index,
74  format_white_space, indent,
75  node->format_buffer ? node->
76  format_buffer : format_hex_bytes, t->data,
77  sizeof (t->data));
78  }
79  else
80  {
81  si = vnet_get_sw_interface (vnm, t->sw_if_index);
82 
83  s = format (s, "%U\n%U%U",
85  format_white_space, indent,
86  node->format_buffer ? node->
87  format_buffer : format_hex_bytes, t->data,
88  sizeof (t->data));
89  }
90  }
91  return s;
92 }
93 
94 static void
96  vlib_node_runtime_t * node,
97  vlib_frame_t * frame, uword n_buffers)
98 {
99  u32 n_left, *from;
100 
101  n_left = n_buffers;
102  from = vlib_frame_vector_args (frame);
103 
104  while (n_left >= 4)
105  {
106  u32 bi0, bi1;
107  vlib_buffer_t *b0, *b1;
108  interface_output_trace_t *t0, *t1;
109 
110  /* Prefetch next iteration. */
111  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
112  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
113 
114  bi0 = from[0];
115  bi1 = from[1];
116 
117  b0 = vlib_get_buffer (vm, bi0);
118  b1 = vlib_get_buffer (vm, bi1);
119 
120  if (b0->flags & VLIB_BUFFER_IS_TRACED)
121  {
122  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
123  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
125  sizeof (t0->data));
126  }
127  if (b1->flags & VLIB_BUFFER_IS_TRACED)
128  {
129  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
130  t1->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_TX];
132  sizeof (t1->data));
133  }
134  from += 2;
135  n_left -= 2;
136  }
137 
138  while (n_left >= 1)
139  {
140  u32 bi0;
141  vlib_buffer_t *b0;
143 
144  bi0 = from[0];
145 
146  b0 = vlib_get_buffer (vm, bi0);
147 
148  if (b0->flags & VLIB_BUFFER_IS_TRACED)
149  {
150  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
151  t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
153  sizeof (t0->data));
154  }
155  from += 1;
156  n_left -= 1;
157  }
158 }
159 
162 {
163  ip4_header_t *ip4;
164  ip6_header_t *ip6;
165  tcp_header_t *th;
166  udp_header_t *uh;
167 
168  int is_ip4 = (b->flags & VNET_BUFFER_F_IS_IP4) != 0;
169  int is_ip6 = (b->flags & VNET_BUFFER_F_IS_IP6) != 0;
170 
171  ASSERT (!(is_ip4 && is_ip6));
172 
173  ip4 = (ip4_header_t *) (b->data + vnet_buffer (b)->l3_hdr_offset);
174  ip6 = (ip6_header_t *) (b->data + vnet_buffer (b)->l3_hdr_offset);
175  th = (tcp_header_t *) (b->data + vnet_buffer (b)->l4_hdr_offset);
176  uh = (udp_header_t *) (b->data + vnet_buffer (b)->l4_hdr_offset);
177 
178  if (is_ip4)
179  {
180  ip4 = (ip4_header_t *) (b->data + vnet_buffer (b)->l3_hdr_offset);
181  if (b->flags & VNET_BUFFER_F_OFFLOAD_IP_CKSUM)
182  ip4->checksum = ip4_header_checksum (ip4);
183  if (b->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM)
184  {
185  th->checksum = 0;
186  th->checksum = ip4_tcp_udp_compute_checksum (vm, b, ip4);
187  }
188  if (b->flags & VNET_BUFFER_F_OFFLOAD_UDP_CKSUM)
189  uh->checksum = ip4_tcp_udp_compute_checksum (vm, b, ip4);
190  }
191  if (is_ip6)
192  {
193  int bogus;
194  if (b->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM)
195  th->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b, ip6, &bogus);
196  if (b->flags & VNET_BUFFER_F_OFFLOAD_UDP_CKSUM)
197  uh->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b, ip6, &bogus);
198  }
199 
200  b->flags &= ~VNET_BUFFER_F_OFFLOAD_TCP_CKSUM;
201  b->flags &= ~VNET_BUFFER_F_OFFLOAD_UDP_CKSUM;
202  b->flags &= ~VNET_BUFFER_F_OFFLOAD_IP_CKSUM;
203 }
204 
207  vlib_node_runtime_t * node,
208  vlib_frame_t * frame, vnet_main_t * vnm,
210  int do_tx_offloads)
211 {
212  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
214  u32 n_left_to_tx, *from, *from_end, *to_tx;
215  u32 n_bytes, n_buffers, n_packets;
216  u32 n_bytes_b0, n_bytes_b1, n_bytes_b2, n_bytes_b3;
217  u32 thread_index = vm->thread_index;
219  u32 next_index = VNET_INTERFACE_OUTPUT_NEXT_TX;
220  u32 current_config_index = ~0;
221  u8 arc = im->output_feature_arc_index;
222 
223  n_buffers = frame->n_vectors;
224 
225  if (node->flags & VLIB_NODE_FLAG_TRACE)
226  vnet_interface_output_trace (vm, node, frame, n_buffers);
227 
228  from = vlib_frame_vector_args (frame);
229 
230  if (rt->is_deleted)
231  return vlib_error_drop_buffers (vm, node, from,
232  /* buffer stride */ 1,
233  n_buffers,
235  node->node_index,
237 
238  si = vnet_get_sw_interface (vnm, rt->sw_if_index);
239  hi = vnet_get_sup_hw_interface (vnm, rt->sw_if_index);
240  if (!(si->flags & (VNET_SW_INTERFACE_FLAG_ADMIN_UP |
243  {
245 
248  vlib_increment_simple_counter (cm, thread_index,
249  rt->sw_if_index, n_buffers);
250 
251  return vlib_error_drop_buffers (vm, node, from,
252  /* buffer stride */ 1,
253  n_buffers,
255  node->node_index,
257  }
258 
259  from_end = from + n_buffers;
260 
261  /* Total byte count of all buffers. */
262  n_bytes = 0;
263  n_packets = 0;
264 
265  /* interface-output feature arc handling */
267  {
269  fcm = vnet_feature_get_config_main (arc);
270  current_config_index = vnet_get_feature_config_index (arc,
271  rt->sw_if_index);
272  vnet_get_config_data (&fcm->config_main, &current_config_index,
273  &next_index, 0);
274  }
275 
276  while (from < from_end)
277  {
278  /* Get new next frame since previous incomplete frame may have less
279  than VNET_FRAME_SIZE vectors in it. */
280  vlib_get_new_next_frame (vm, node, next_index, to_tx, n_left_to_tx);
281 
282  while (from + 8 <= from_end && n_left_to_tx >= 4)
283  {
284  u32 bi0, bi1, bi2, bi3;
285  vlib_buffer_t *b0, *b1, *b2, *b3;
286  u32 tx_swif0, tx_swif1, tx_swif2, tx_swif3;
287  u32 or_flags;
288 
289  /* Prefetch next iteration. */
290  vlib_prefetch_buffer_with_index (vm, from[4], LOAD);
291  vlib_prefetch_buffer_with_index (vm, from[5], LOAD);
292  vlib_prefetch_buffer_with_index (vm, from[6], LOAD);
293  vlib_prefetch_buffer_with_index (vm, from[7], LOAD);
294 
295  bi0 = from[0];
296  bi1 = from[1];
297  bi2 = from[2];
298  bi3 = from[3];
299  to_tx[0] = bi0;
300  to_tx[1] = bi1;
301  to_tx[2] = bi2;
302  to_tx[3] = bi3;
303  from += 4;
304  to_tx += 4;
305  n_left_to_tx -= 4;
306 
307  b0 = vlib_get_buffer (vm, bi0);
308  b1 = vlib_get_buffer (vm, bi1);
309  b2 = vlib_get_buffer (vm, bi2);
310  b3 = vlib_get_buffer (vm, bi3);
311 
312  /* Be grumpy about zero length buffers for benefit of
313  driver tx function. */
314  ASSERT (b0->current_length > 0);
315  ASSERT (b1->current_length > 0);
316  ASSERT (b2->current_length > 0);
317  ASSERT (b3->current_length > 0);
318 
319  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b0);
320  n_bytes_b1 = vlib_buffer_length_in_chain (vm, b1);
321  n_bytes_b2 = vlib_buffer_length_in_chain (vm, b2);
322  n_bytes_b3 = vlib_buffer_length_in_chain (vm, b3);
323  tx_swif0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
324  tx_swif1 = vnet_buffer (b1)->sw_if_index[VLIB_TX];
325  tx_swif2 = vnet_buffer (b2)->sw_if_index[VLIB_TX];
326  tx_swif3 = vnet_buffer (b3)->sw_if_index[VLIB_TX];
327 
328  n_bytes += n_bytes_b0 + n_bytes_b1;
329  n_bytes += n_bytes_b2 + n_bytes_b3;
330  n_packets += 4;
331 
332  if (PREDICT_FALSE (current_config_index != ~0))
333  {
334  vnet_buffer (b0)->feature_arc_index = arc;
335  vnet_buffer (b1)->feature_arc_index = arc;
336  vnet_buffer (b2)->feature_arc_index = arc;
337  vnet_buffer (b3)->feature_arc_index = arc;
338  b0->current_config_index = current_config_index;
339  b1->current_config_index = current_config_index;
340  b2->current_config_index = current_config_index;
341  b3->current_config_index = current_config_index;
342  }
343 
344  /* update vlan subif tx counts, if required */
345  if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
346  {
347  vlib_increment_combined_counter (im->combined_sw_if_counters +
349  thread_index, tx_swif0, 1,
350  n_bytes_b0);
351  }
352 
353  if (PREDICT_FALSE (tx_swif1 != rt->sw_if_index))
354  {
355 
356  vlib_increment_combined_counter (im->combined_sw_if_counters +
358  thread_index, tx_swif1, 1,
359  n_bytes_b1);
360  }
361 
362  if (PREDICT_FALSE (tx_swif2 != rt->sw_if_index))
363  {
364 
365  vlib_increment_combined_counter (im->combined_sw_if_counters +
367  thread_index, tx_swif2, 1,
368  n_bytes_b2);
369  }
370  if (PREDICT_FALSE (tx_swif3 != rt->sw_if_index))
371  {
372 
373  vlib_increment_combined_counter (im->combined_sw_if_counters +
375  thread_index, tx_swif3, 1,
376  n_bytes_b3);
377  }
378 
379  or_flags = b0->flags | b1->flags | b2->flags | b3->flags;
380 
381  if (do_tx_offloads)
382  {
383  if (or_flags &
384  (VNET_BUFFER_F_OFFLOAD_TCP_CKSUM |
385  VNET_BUFFER_F_OFFLOAD_UDP_CKSUM |
386  VNET_BUFFER_F_OFFLOAD_IP_CKSUM))
387  {
388  calc_checksums (vm, b0);
389  calc_checksums (vm, b1);
390  calc_checksums (vm, b2);
391  calc_checksums (vm, b3);
392  }
393  }
394  }
395 
396  while (from + 1 <= from_end && n_left_to_tx >= 1)
397  {
398  u32 bi0;
399  vlib_buffer_t *b0;
400  u32 tx_swif0;
401 
402  bi0 = from[0];
403  to_tx[0] = bi0;
404  from += 1;
405  to_tx += 1;
406  n_left_to_tx -= 1;
407 
408  b0 = vlib_get_buffer (vm, bi0);
409 
410  /* Be grumpy about zero length buffers for benefit of
411  driver tx function. */
412  ASSERT (b0->current_length > 0);
413 
414  n_bytes_b0 = vlib_buffer_length_in_chain (vm, b0);
415  tx_swif0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
416  n_bytes += n_bytes_b0;
417  n_packets += 1;
418 
419  if (PREDICT_FALSE (current_config_index != ~0))
420  {
421  vnet_buffer (b0)->feature_arc_index = arc;
422  b0->current_config_index = current_config_index;
423  }
424 
425  if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
426  {
427 
428  vlib_increment_combined_counter (im->combined_sw_if_counters +
430  thread_index, tx_swif0, 1,
431  n_bytes_b0);
432  }
433 
434  if (do_tx_offloads)
435  calc_checksums (vm, b0);
436  }
437 
438  vlib_put_next_frame (vm, node, next_index, n_left_to_tx);
439  }
440 
441  /* Update main interface stats. */
442  vlib_increment_combined_counter (im->combined_sw_if_counters
444  thread_index,
445  rt->sw_if_index, n_packets, n_bytes);
446  return n_buffers;
447 }
448 
449 static uword
451  vlib_frame_t * frame)
452 {
453  vnet_main_t *vnm = vnet_get_main ();
455  vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
456  hi = vnet_get_sup_hw_interface (vnm, rt->sw_if_index);
457 
459  return vnet_interface_output_node_inline (vm, node, frame, vnm, hi,
460  /* do_tx_offloads */ 0);
461  else
462  return vnet_interface_output_node_inline (vm, node, frame, vnm, hi,
463  /* do_tx_offloads */ 1);
464 }
465 
468 
469 /* Use buffer's sw_if_index[VNET_TX] to choose output interface. */
470 static uword
472  vlib_node_runtime_t * node,
473  vlib_frame_t * frame)
474 {
475  vnet_main_t *vnm = vnet_get_main ();
476  u32 n_left_to_next, *from, *to_next;
477  u32 n_left_from, next_index;
478 
479  n_left_from = frame->n_vectors;
480 
481  from = vlib_frame_vector_args (frame);
482  next_index = node->cached_next_index;
483 
484  while (n_left_from > 0)
485  {
486  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
487 
488  while (n_left_from >= 4 && n_left_to_next >= 2)
489  {
490  u32 bi0, bi1, next0, next1;
491  vlib_buffer_t *b0, *b1;
492  vnet_hw_interface_t *hi0, *hi1;
493 
494  /* Prefetch next iteration. */
495  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
496  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
497 
498  bi0 = from[0];
499  bi1 = from[1];
500  to_next[0] = bi0;
501  to_next[1] = bi1;
502  from += 2;
503  to_next += 2;
504  n_left_to_next -= 2;
505  n_left_from -= 2;
506 
507  b0 = vlib_get_buffer (vm, bi0);
508  b1 = vlib_get_buffer (vm, bi1);
509 
510  hi0 =
513  [VLIB_TX]);
514  hi1 =
517  [VLIB_TX]);
518 
519  next0 = hi0->output_node_next_index;
520  next1 = hi1->output_node_next_index;
521 
522  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
523  n_left_to_next, bi0, bi1, next0,
524  next1);
525  }
526 
527  while (n_left_from > 0 && n_left_to_next > 0)
528  {
529  u32 bi0, next0;
530  vlib_buffer_t *b0;
531  vnet_hw_interface_t *hi0;
532 
533  bi0 = from[0];
534  to_next[0] = bi0;
535  from += 1;
536  to_next += 1;
537  n_left_to_next -= 1;
538  n_left_from -= 1;
539 
540  b0 = vlib_get_buffer (vm, bi0);
541 
542  hi0 =
545  [VLIB_TX]);
546 
547  next0 = hi0->output_node_next_index;
548 
549  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
550  n_left_to_next, bi0, next0);
551  }
552 
553  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
554  }
555 
556  return frame->n_vectors;
557 }
558 
561 {
562  vlib_node_t *n;
563  u32 ci, ni;
564 
565  ni = vlib_error_get_node (&vm->node_main, e);
566  n = vlib_get_node (vm, ni);
567 
568  ci = vlib_error_get_code (&vm->node_main, e);
569  ASSERT (ci < n->n_errors);
570 
571  ci += n->error_heap_index;
572 
573  return ci;
574 }
575 
576 static u8 *
577 format_vnet_error_trace (u8 * s, va_list * va)
578 {
579  vlib_main_t *vm = va_arg (*va, vlib_main_t *);
580  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
581  vlib_error_t *e = va_arg (*va, vlib_error_t *);
582  vlib_node_t *error_node;
583  vlib_error_main_t *em = &vm->error_main;
584  u32 i;
585 
586  error_node = vlib_get_node (vm, vlib_error_get_node (&vm->node_main, e[0]));
587  i = counter_index (vm, vlib_error_get_code (&vm->node_main, e[0]));
588  s = format (s, "%v: %s", error_node->name, em->error_strings_heap[i]);
589 
590  return s;
591 }
592 
593 static void
595  vlib_node_runtime_t * node, vlib_frame_t * frame)
596 {
597  u32 n_left, *buffers;
598 
599  buffers = vlib_frame_vector_args (frame);
600  n_left = frame->n_vectors;
601 
602  while (n_left >= 4)
603  {
604  u32 bi0, bi1;
605  vlib_buffer_t *b0, *b1;
606  vlib_error_t *t0, *t1;
607 
608  /* Prefetch next iteration. */
609  vlib_prefetch_buffer_with_index (vm, buffers[2], LOAD);
610  vlib_prefetch_buffer_with_index (vm, buffers[3], LOAD);
611 
612  bi0 = buffers[0];
613  bi1 = buffers[1];
614 
615  b0 = vlib_get_buffer (vm, bi0);
616  b1 = vlib_get_buffer (vm, bi1);
617 
618  if (b0->flags & VLIB_BUFFER_IS_TRACED)
619  {
620  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
621  t0[0] = b0->error;
622  }
623  if (b1->flags & VLIB_BUFFER_IS_TRACED)
624  {
625  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
626  t1[0] = b1->error;
627  }
628  buffers += 2;
629  n_left -= 2;
630  }
631 
632  while (n_left >= 1)
633  {
634  u32 bi0;
635  vlib_buffer_t *b0;
636  vlib_error_t *t0;
637 
638  bi0 = buffers[0];
639 
640  b0 = vlib_get_buffer (vm, bi0);
641 
642  if (b0->flags & VLIB_BUFFER_IS_TRACED)
643  {
644  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
645  t0[0] = b0->error;
646  }
647  buffers += 1;
648  n_left -= 1;
649  }
650 }
651 
652 static u8 *
654 {
655  uword node_index = vlib_error_get_node (&vm->node_main, e[0]);
656  uword code = vlib_error_get_code (&vm->node_main, e[0]);
657  vlib_node_t *n;
658 
659  if (node_index >= vec_len (vm->node_main.nodes))
660  return format (0, "[%d], node index out of range 0x%x, error 0x%x",
661  index, node_index, e[0]);
662 
663  n = vlib_get_node (vm, node_index);
664  if (code >= n->n_errors)
665  return format (0, "[%d], code %d out of range for node %v",
666  index, code, n->name);
667 
668  return 0;
669 }
670 
671 static u8 *
673  vlib_node_runtime_t * node, vlib_frame_t * f)
674 {
675  u32 *buffers = vlib_frame_vector_args (f);
676  vlib_buffer_t *b;
677  u8 *msg = 0;
678  uword i;
679 
680  for (i = 0; i < f->n_vectors; i++)
681  {
682  b = vlib_get_buffer (vm, buffers[i]);
683  msg = validate_error (vm, &b->error, i);
684  if (msg)
685  return msg;
686  }
687 
688  return msg;
689 }
690 
691 typedef enum
692 {
697 
698 always_inline void
700 {
701  vlib_error_main_t *em = &vm->error_main;
702  u32 i = counter_index (vm, a);
703  em->counters[i] += 1;
704  vlib_error_elog_count (vm, i, 1);
705 }
706 
709  vlib_node_runtime_t * node,
710  vlib_frame_t * frame, vnet_error_disposition_t disposition)
711 {
712  vnet_main_t *vnm = vnet_get_main ();
713  vlib_error_main_t *em = &vm->error_main;
714  u32 *buffers, *first_buffer;
715  vlib_error_t current_error;
716  u32 current_counter_index, n_errors_left;
717  u32 current_sw_if_index, n_errors_current_sw_if_index;
718  u64 current_counter;
720  u32 thread_index = vm->thread_index;
721 
723  static char memory_init[VNET_ERROR_N_DISPOSITION];
724 
725  buffers = vlib_frame_vector_args (frame);
726  first_buffer = buffers;
727 
728  {
729  vlib_buffer_t *b = vlib_get_buffer (vm, first_buffer[0]);
730 
731  if (!memory_init[disposition])
732  {
733  memory_init[disposition] = 1;
734  memory[disposition] = b->error;
735  }
736 
737  current_sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
738  n_errors_current_sw_if_index = 0;
739  }
740 
741  current_error = memory[disposition];
742  current_counter_index = counter_index (vm, memory[disposition]);
743  current_counter = em->counters[current_counter_index];
744 
745  if (node->flags & VLIB_NODE_FLAG_TRACE)
746  trace_errors_with_buffers (vm, node, frame);
747 
748  n_errors_left = frame->n_vectors;
750  (disposition == VNET_ERROR_DISPOSITION_PUNT
753 
754  while (n_errors_left >= 2)
755  {
756  vlib_buffer_t *b0, *b1;
757  vnet_sw_interface_t *sw_if0, *sw_if1;
758  vlib_error_t e0, e1;
759  u32 bi0, bi1;
760  u32 sw_if_index0, sw_if_index1;
761 
762  bi0 = buffers[0];
763  bi1 = buffers[1];
764 
765  buffers += 2;
766  n_errors_left -= 2;
767 
768  b0 = vlib_get_buffer (vm, bi0);
769  b1 = vlib_get_buffer (vm, bi1);
770 
771  e0 = b0->error;
772  e1 = b1->error;
773 
774  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
775  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
776 
777  /* Speculate that sw_if_index == sw_if_index[01]. */
778  n_errors_current_sw_if_index += 2;
779 
780  /* Speculatively assume all 2 (node, code) pairs are equal
781  to current (node, code). */
782  current_counter += 2;
783 
784  if (PREDICT_FALSE (e0 != current_error
785  || e1 != current_error
786  || sw_if_index0 != current_sw_if_index
787  || sw_if_index1 != current_sw_if_index))
788  {
789  current_counter -= 2;
790  n_errors_current_sw_if_index -= 2;
791 
792  vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
793  vlib_increment_simple_counter (cm, thread_index, sw_if_index1, 1);
794 
795  /* Increment super-interface drop/punt counters for
796  sub-interfaces. */
797  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index0);
799  (cm, thread_index, sw_if0->sup_sw_if_index,
800  sw_if0->sup_sw_if_index != sw_if_index0);
801 
802  sw_if1 = vnet_get_sw_interface (vnm, sw_if_index1);
804  (cm, thread_index, sw_if1->sup_sw_if_index,
805  sw_if1->sup_sw_if_index != sw_if_index1);
806 
807  em->counters[current_counter_index] = current_counter;
808  do_packet (vm, e0);
809  do_packet (vm, e1);
810 
811  /* For 2 repeated errors, change current error. */
812  if (e0 == e1 && e1 != current_error)
813  {
814  current_error = e0;
815  current_counter_index = counter_index (vm, e0);
816  }
817  current_counter = em->counters[current_counter_index];
818  }
819  }
820 
821  while (n_errors_left >= 1)
822  {
823  vlib_buffer_t *b0;
824  vnet_sw_interface_t *sw_if0;
825  vlib_error_t e0;
826  u32 bi0, sw_if_index0;
827 
828  bi0 = buffers[0];
829 
830  buffers += 1;
831  n_errors_left -= 1;
832  current_counter += 1;
833 
834  b0 = vlib_get_buffer (vm, bi0);
835  e0 = b0->error;
836 
837  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
838 
839  /* Increment drop/punt counters. */
840  vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
841 
842  /* Increment super-interface drop/punt counters for sub-interfaces. */
843  sw_if0 = vnet_get_sw_interface (vnm, sw_if_index0);
844  vlib_increment_simple_counter (cm, thread_index,
845  sw_if0->sup_sw_if_index,
846  sw_if0->sup_sw_if_index != sw_if_index0);
847 
848  if (PREDICT_FALSE (e0 != current_error))
849  {
850  current_counter -= 1;
851 
852  vlib_error_elog_count (vm, current_counter_index,
853  (current_counter
854  - em->counters[current_counter_index]));
855 
856  em->counters[current_counter_index] = current_counter;
857 
858  do_packet (vm, e0);
859  current_error = e0;
860  current_counter_index = counter_index (vm, e0);
861  current_counter = em->counters[current_counter_index];
862  }
863  }
864 
865  if (n_errors_current_sw_if_index > 0)
866  {
868 
869  vlib_increment_simple_counter (cm, thread_index, current_sw_if_index,
870  n_errors_current_sw_if_index);
871 
872  si = vnet_get_sw_interface (vnm, current_sw_if_index);
873  if (si->sup_sw_if_index != current_sw_if_index)
874  vlib_increment_simple_counter (cm, thread_index, si->sup_sw_if_index,
875  n_errors_current_sw_if_index);
876  }
877 
878  vlib_error_elog_count (vm, current_counter_index,
879  (current_counter
880  - em->counters[current_counter_index]));
881 
882  /* Return cached counter. */
883  em->counters[current_counter_index] = current_counter;
884 
885  /* Save memory for next iteration. */
886  memory[disposition] = current_error;
887 
888  if (disposition == VNET_ERROR_DISPOSITION_DROP || !vm->os_punt_frame)
889  {
890  vlib_buffer_free (vm, first_buffer, frame->n_vectors);
891 
892  /* If there is no punt function, free the frame as well. */
893  if (disposition == VNET_ERROR_DISPOSITION_PUNT && !vm->os_punt_frame)
894  vlib_frame_free (vm, node, frame);
895  }
896  else
897  vm->os_punt_frame (vm, node, frame);
898 
899  return frame->n_vectors;
900 }
901 
902 static inline void
905 {
906  u32 *from;
907  u32 n_left = f->n_vectors;
908  vlib_buffer_t *b0, *p1;
909  u32 bi0;
910  i16 save_current_data;
911  u16 save_current_length;
912 
913  from = vlib_frame_vector_args (f);
914 
915  while (n_left > 0)
916  {
917  if (PREDICT_TRUE (n_left > 1))
918  {
919  p1 = vlib_get_buffer (vm, from[1]);
920  vlib_prefetch_buffer_header (p1, LOAD);
921  }
922 
923  bi0 = from[0];
924  b0 = vlib_get_buffer (vm, bi0);
925  from++;
926  n_left--;
927 
928  /* See if we're pointedly ignoring this specific error */
929  if (im->pcap_drop_filter_hash
930  && hash_get (im->pcap_drop_filter_hash, b0->error))
931  continue;
932 
933  /* Trace all drops, or drops received on a specific interface */
934  if (im->pcap_sw_if_index == 0 ||
936  {
937  save_current_data = b0->current_data;
938  save_current_length = b0->current_length;
939 
940  /*
941  * Typically, we'll need to rewind the buffer
942  */
943  if (b0->current_data > 0)
944  vlib_buffer_advance (b0, (word) - b0->current_data);
945 
946  pcap_add_buffer (&im->pcap_main, vm, bi0, 512);
947 
948  b0->current_data = save_current_data;
949  b0->current_length = save_current_length;
950  }
951  }
952 }
953 
954 void
955 vnet_pcap_drop_trace_filter_add_del (u32 error_index, int is_add)
956 {
958 
959  if (im->pcap_drop_filter_hash == 0)
960  im->pcap_drop_filter_hash = hash_create (0, sizeof (uword));
961 
962  if (is_add)
963  hash_set (im->pcap_drop_filter_hash, error_index, 1);
964  else
965  hash_unset (im->pcap_drop_filter_hash, error_index);
966 }
967 
968 static uword
970  vlib_node_runtime_t * node, vlib_frame_t * frame)
971 {
973 
975  pcap_drop_trace (vm, im, frame);
976 
977  return process_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_DROP);
978 }
979 
980 static uword
982  vlib_node_runtime_t * node, vlib_frame_t * frame)
983 {
984  return process_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_PUNT);
985 }
986 
987 /* *INDENT-OFF* */
989  .function = process_drop,
990  .name = "error-drop",
991  .flags = VLIB_NODE_FLAG_IS_DROP,
992  .vector_size = sizeof (u32),
993  .format_trace = format_vnet_error_trace,
994  .validate_frame = validate_error_frame,
995 };
996 /* *INDENT-ON* */
997 
999 
1000 /* *INDENT-OFF* */
1002  .function = process_punt,
1005  .name = "error-punt",
1006  .vector_size = sizeof (u32),
1007  .format_trace = format_vnet_error_trace,
1008  .validate_frame = validate_error_frame,
1009 };
1010 /* *INDENT-ON* */
1011 
1013 
1014 /* *INDENT-OFF* */
1017  .name = "interface-output",
1018  .vector_size = sizeof (u32),
1019 };
1020 /* *INDENT-ON* */
1021 
1024 
1025 static uword
1027  vlib_frame_t * from_frame)
1028 {
1029  vnet_main_t *vnm = vnet_get_main ();
1030  u32 last_sw_if_index = ~0;
1031  vlib_frame_t *to_frame = 0;
1032  vnet_hw_interface_t *hw = 0;
1033  u32 *from, *to_next = 0;
1034  u32 n_left_from;
1035 
1036  from = vlib_frame_vector_args (from_frame);
1037  n_left_from = from_frame->n_vectors;
1038  while (n_left_from > 0)
1039  {
1040  u32 bi0;
1041  vlib_buffer_t *b0;
1042  u32 sw_if_index0;
1043 
1044  bi0 = from[0];
1045  from++;
1046  n_left_from--;
1047  b0 = vlib_get_buffer (vm, bi0);
1048  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
1049 
1050  if (PREDICT_FALSE ((last_sw_if_index != sw_if_index0) || to_frame == 0))
1051  {
1052  if (to_frame)
1053  {
1054  hw = vnet_get_sup_hw_interface (vnm, last_sw_if_index);
1055  vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1056  }
1057  last_sw_if_index = sw_if_index0;
1058  hw = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1059  to_frame = vlib_get_frame_to_node (vm, hw->tx_node_index);
1060  to_next = vlib_frame_vector_args (to_frame);
1061  }
1062 
1063  to_next[0] = bi0;
1064  to_next++;
1065  to_frame->n_vectors++;
1066  }
1067  vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1068  return from_frame->n_vectors;
1069 }
1070 
1071 /* *INDENT-OFF* */
1073  .function = interface_tx_node_fn,
1074  .name = "interface-tx",
1075  .vector_size = sizeof (u32),
1076  .n_next_nodes = 1,
1077  .next_nodes = {
1078  [0] = "error-drop",
1079  },
1080 };
1081 
1082 VNET_FEATURE_ARC_INIT (interface_output, static) =
1083 {
1084  .arc_name = "interface-output",
1085  .start_nodes = VNET_FEATURES (0),
1086  .last_in_arc = "interface-tx",
1088 };
1089 
1090 VNET_FEATURE_INIT (span_tx, static) = {
1091  .arc_name = "interface-output",
1092  .node_name = "span-output",
1093  .runs_before = VNET_FEATURES ("interface-tx"),
1094 };
1095 
1096 VNET_FEATURE_INIT (ipsec_if_tx, static) = {
1097  .arc_name = "interface-output",
1098  .node_name = "ipsec-if-output",
1099  .runs_before = VNET_FEATURES ("interface-tx"),
1100 };
1101 
1102 VNET_FEATURE_INIT (interface_tx, static) = {
1103  .arc_name = "interface-output",
1104  .node_name = "interface-tx",
1105  .runs_before = 0,
1106 };
1107 /* *INDENT-ON* */
1108 
1109 clib_error_t *
1111  u32 hw_if_index,
1112  u32 is_create)
1113 {
1114  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1115  u32 next_index;
1116 
1117  if (hi->output_node_index == 0)
1118  return 0;
1119 
1120  next_index = vlib_node_add_next
1122  hi->output_node_index);
1123  hi->output_node_next_index = next_index;
1124 
1125  return 0;
1126 }
1127 
1130 
1131 void
1133  u32 hw_if_index, u32 node_index)
1134 {
1135  ASSERT (node_index);
1136  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1137  u32 next_index = vlib_node_add_next
1138  (vnm->vlib_main, vnet_per_buffer_interface_output_node.index, node_index);
1139  hi->output_node_next_index = next_index;
1140  hi->output_node_index = node_index;
1141 }
1142 
1143 static clib_error_t *
1145  unformat_input_t * input,
1146  vlib_cli_command_t * cmd)
1147 {
1148  vnet_main_t *vnm = vnet_get_main ();
1150  u8 *filename;
1151  u32 max;
1152  int matched = 0;
1153  clib_error_t *error = 0;
1154 
1155  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1156  {
1157  if (unformat (input, "on"))
1158  {
1159  if (im->drop_pcap_enable == 0)
1160  {
1161  if (im->pcap_filename == 0)
1162  im->pcap_filename = format (0, "/tmp/drop.pcap%c", 0);
1163 
1164  clib_memset (&im->pcap_main, 0, sizeof (im->pcap_main));
1165  im->pcap_main.file_name = (char *) im->pcap_filename;
1166  im->pcap_main.n_packets_to_capture = 100;
1167  if (im->pcap_pkts_to_capture)
1169 
1170  im->pcap_main.packet_type = PCAP_PACKET_TYPE_ethernet;
1171  im->drop_pcap_enable = 1;
1172  matched = 1;
1173  vlib_cli_output (vm, "pcap drop capture on...");
1174  }
1175  else
1176  {
1177  vlib_cli_output (vm, "pcap drop capture already on...");
1178  }
1179  matched = 1;
1180  }
1181  else if (unformat (input, "off"))
1182  {
1183  matched = 1;
1184 
1185  if (im->drop_pcap_enable)
1186  {
1187  vlib_cli_output (vm, "captured %d pkts...",
1189  if (im->pcap_main.n_packets_captured)
1190  {
1193  error = pcap_write (&im->pcap_main);
1194  if (error)
1195  clib_error_report (error);
1196  else
1197  vlib_cli_output (vm, "saved to %s...", im->pcap_filename);
1198  }
1199  }
1200  else
1201  {
1202  vlib_cli_output (vm, "pcap drop capture already off...");
1203  }
1204 
1205  im->drop_pcap_enable = 0;
1206  }
1207  else if (unformat (input, "max %d", &max))
1208  {
1209  im->pcap_pkts_to_capture = max;
1210  matched = 1;
1211  }
1212 
1213  else if (unformat (input, "intfc %U",
1215  &im->pcap_sw_if_index))
1216  matched = 1;
1217  else if (unformat (input, "intfc any"))
1218  {
1219  im->pcap_sw_if_index = 0;
1220  matched = 1;
1221  }
1222  else if (unformat (input, "file %s", &filename))
1223  {
1224  u8 *chroot_filename;
1225  /* Brain-police user path input */
1226  if (strstr ((char *) filename, "..")
1227  || index ((char *) filename, '/'))
1228  {
1229  vlib_cli_output (vm, "illegal characters in filename '%s'",
1230  filename);
1231  continue;
1232  }
1233 
1234  chroot_filename = format (0, "/tmp/%s%c", filename, 0);
1235  vec_free (filename);
1236 
1237  if (im->pcap_filename)
1238  vec_free (im->pcap_filename);
1239  im->pcap_filename = chroot_filename;
1240  im->pcap_main.file_name = (char *) im->pcap_filename;
1241  matched = 1;
1242  }
1243  else if (unformat (input, "status"))
1244  {
1245  if (im->drop_pcap_enable == 0)
1246  {
1247  vlib_cli_output (vm, "pcap drop capture is off...");
1248  continue;
1249  }
1250 
1251  vlib_cli_output (vm, "pcap drop capture: %d of %d pkts...",
1254  matched = 1;
1255  }
1256 
1257  else
1258  break;
1259  }
1260 
1261  if (matched == 0)
1262  return clib_error_return (0, "unknown input `%U'",
1263  format_unformat_error, input);
1264 
1265  return 0;
1266 }
1267 
1268 /* *INDENT-OFF* */
1269 VLIB_CLI_COMMAND (pcap_trace_command, static) = {
1270  .path = "pcap drop trace",
1271  .short_help =
1272  "pcap drop trace on off max <nn> intfc <intfc> file <name> status",
1273  .function = pcap_drop_trace_command_fn,
1274 };
1275 /* *INDENT-ON* */
1276 
1277 /*
1278  * fd.io coding-style-patch-verification: ON
1279  *
1280  * Local Variables:
1281  * eval: (c-set-style "gnu")
1282  * End:
1283  */
u8 * format_vnet_interface_output_trace(u8 *s, va_list *va)
vnet_config_main_t config_main
Definition: feature.h:82
vmrglw vmrglh hi
u32 error_heap_index
Definition: node.h:348
VNET_FEATURE_ARC_INIT(interface_output, static)
#define hash_set(h, key, value)
Definition: hash.h:255
char * file_name
File name of pcap output.
Definition: pcap.h:162
pcap_main_t pcap_main
Definition: interface.h:845
vhost_user_memory_t memory
Definition: vhost_user.h:122
#define CLIB_UNUSED(x)
Definition: clib.h:82
void vnet_set_interface_output_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Set interface output node - for interface registered without its output/tx nodes created because its ...
static_always_inline uword vnet_interface_output_node_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, vnet_main_t *vnm, vnet_hw_interface_t *hi, int do_tx_offloads)
VLIB_NODE_FUNCTION_MULTIARCH_CLONE(vnet_interface_output_node)
#define hash_unset(h, key)
Definition: hash.h:261
a
Definition: bitmap.h:538
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:220
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:529
u8 runtime_data[0]
Function dependent node-runtime data.
Definition: node.h:545
u32 n_packets_to_capture
Number of packets to capture.
Definition: pcap.h:165
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:136
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
static uword vnet_interface_output_node(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
vnet_interface_main_t interface_main
Definition: vnet.h:56
#define PREDICT_TRUE(x)
Definition: clib.h:112
unsigned long u64
Definition: types.h:89
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u32 thread_index
Definition: main.h:179
#define VLIB_NODE_FLAG_IS_PUNT
Definition: node.h:322
clib_error_t * vnet_per_buffer_interface_output_hw_interface_add_del(vnet_main_t *vnm, u32 hw_if_index, u32 is_create)
u16 vlib_error_t
Definition: error.h:43
static void vnet_interface_output_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, uword n_buffers)
int i
static u32 format_get_indent(u8 *s)
Definition: format.h:72
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 increment)
Increment a simple counter.
Definition: counter.h:78
unformat_function_t unformat_vnet_sw_interface
static_always_inline int vnet_have_features(u8 arc, u32 sw_if_index)
Definition: feature.h:241
void vnet_pcap_drop_trace_filter_add_del(u32 error_index, int is_add)
CLIB_MULTIARCH_SELECT_FN(vnet_interface_output_node)
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:267
struct _tcp_header tcp_header_t
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1092
unsigned char u8
Definition: types.h:56
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
#define static_always_inline
Definition: clib.h:99
uword * pcap_drop_filter_hash
Definition: interface.h:849
i64 word
Definition: types.h:111
#define vlib_prefetch_buffer_with_index(vm, bi, type)
Prefetch buffer metadata by buffer index The first 64 bytes of buffer contains most header informatio...
Definition: buffer_funcs.h:341
static u8 * validate_error_frame(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *f)
u32 sw_if_index
Definition: vxlan_gbp.api:37
#define always_inline
Definition: clib.h:98
static_always_inline void calc_checksums(vlib_main_t *vm, vlib_buffer_t *b)
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
static u32 counter_index(vlib_main_t *vm, vlib_error_t e)
vlib_node_t ** nodes
Definition: node.h:721
vnet_hw_interface_flags_t flags
Definition: interface.h:516
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:188
#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
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:181
#define vlib_get_new_next_frame(vm, node, next_index, vectors, n_vectors_left)
Definition: node_funcs.h:343
#define clib_error_return(e, args...)
Definition: error.h:99
unsigned int u32
Definition: types.h:88
static vlib_node_registration_t drop_buffers
(constructor) VLIB_REGISTER_NODE (drop_buffers)
u8 data[128 - sizeof(u32)]
A collection of simple counters.
Definition: counter.h:57
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)
#define hash_get(h, key)
Definition: hash.h:249
format_function_t format_vnet_sw_interface_name
vlib_main_t * vlib_main
Definition: vnet.h:80
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:114
static u8 * format_vnet_error_trace(u8 *s, va_list *va)
vlib_error_main_t error_main
Definition: main.h:143
VNET_FEATURE_INIT(span_tx, static)
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
unsigned short u16
Definition: types.h:57
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:190
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:214
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
void vlib_frame_free(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_frame_t *f)
Definition: main.c:210
#define PREDICT_FALSE(x)
Definition: clib.h:111
vnet_main_t vnet_main
Definition: misc.c:43
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:838
format_function_t * format_buffer
Definition: node.h:381
u32 node_index
Node index.
Definition: node.h:518
#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:218
#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:338
u8 name[64]
Definition: memclnt.api:152
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:139
static u32 vlib_error_get_code(vlib_node_main_t *nm, vlib_error_t e)
Definition: node.h:801
u8 * name
Definition: node.h:288
u64 * counters
Definition: error.h:48
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
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:144
char ** error_strings_heap
Definition: error.h:55
u16 n_vectors
Definition: node.h:420
vlib_main_t * vm
Definition: buffer.c:301
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
#define VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH
Definition: node.h:317
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:283
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:452
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:155
u16 ip6_tcp_udp_icmp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip6_header_t *ip0, int *bogus_lengthp)
Definition: ip6_forward.c:944
#define hash_create(elts, value_bytes)
Definition: hash.h:696
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:537
#define ASSERT(truth)
u16 ip4_tcp_udp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip4_header_t *ip0)
Definition: ip4_forward.c:1129
static void trace_errors_with_buffers(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define clib_error_report(e)
Definition: error.h:113
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:233
static vlib_node_registration_t interface_tx
(constructor) VLIB_REGISTER_NODE (interface_tx)
#define VNET_FEATURES(...)
Definition: feature.h:435
static u32 vlib_error_get_node(vlib_node_main_t *nm, vlib_error_t e)
Definition: node.h:795
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:57
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:168
Definition: defs.h:47
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static_always_inline u32 vnet_get_feature_config_index(u8 arc, u32 sw_if_index)
Definition: feature.h:248
vlib_node_main_t node_main
Definition: main.h:129
u64 uword
Definition: types.h:112
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:830
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
#define VLIB_NODE_FLAG_IS_DROP
Definition: node.h:321
static clib_error_t * pcap_drop_trace_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define vnet_buffer(b)
Definition: buffer.h:368
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
u16 n_errors
Definition: node.h:341
static vlib_node_registration_t punt_buffers
(constructor) VLIB_REGISTER_NODE (punt_buffers)
u8 data[0]
Packet data.
Definition: buffer.h:176
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:147
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:59
u16 flags
Copy of main node flags.
Definition: node.h:531
static uword process_punt(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:326
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:117
static_always_inline vnet_feature_config_main_t * vnet_feature_get_config_main(u16 arc)
Definition: feature.h:234
static void pcap_add_buffer(pcap_main_t *pm, struct vlib_main_t *vm, u32 buffer_index, u32 n_bytes_in_trace)
Add buffer (vlib_buffer_t) to the trace.
Definition: pcap_funcs.h:63
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:762
static void do_packet(vlib_main_t *vm, vlib_error_t a)
u32 n_packets_captured
Number of packets currently captured.
Definition: pcap.h:171
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:62
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:247
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
Definition: defs.h:46
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
signed short i16
Definition: types.h:46
static u8 * validate_error(vlib_main_t *vm, vlib_error_t *e, u32 index)