FD.io VPP  v21.01.1
Vector Packet Processing
mpls_output.c
Go to the documentation of this file.
1 /*
2  * mpls_output.c: MPLS Adj rewrite
3  *
4  * Copyright (c) 2012-2014 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vlib/vlib.h>
19 #include <vnet/ip/ip.h>
20 #include <vnet/mpls/mpls.h>
21 #include <vnet/ip/ip_frag.h>
22 
23 typedef struct {
24  /* Adjacency taken. */
28 
29 typedef enum {
33 
34 #define foreach_mpls_output_next \
35 _(DROP, "error-drop") \
36 _(FRAG, "mpls-frag")
37 
38 typedef enum {
39 #define _(s,n) MPLS_OUTPUT_NEXT_##s,
41 #undef _
44 
45 static u8 *
46 format_mpls_output_trace (u8 * s, va_list * args)
47 {
48  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
49  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
50  mpls_output_trace_t * t = va_arg (*args, mpls_output_trace_t *);
51 
52  s = format (s, "adj-idx %d : %U flow hash: 0x%08x",
53  t->adj_index,
55  t->flow_hash);
56  return s;
57 }
58 
59 static inline uword
62  vlib_frame_t * from_frame,
64 {
65  u32 n_left_from, next_index, * from, * to_next, thread_index;
66  vlib_node_runtime_t * error_node;
67  u32 n_left_to_next;
68  mpls_main_t *mm;
69 
70  thread_index = vlib_get_thread_index();
71  error_node = vlib_node_get_runtime (vm, mpls_output_node.index);
72  from = vlib_frame_vector_args (from_frame);
73  n_left_from = from_frame->n_vectors;
74  next_index = node->cached_next_index;
75  mm = &mpls_main;
76 
77  while (n_left_from > 0)
78  {
79  vlib_get_next_frame (vm, node, next_index,
80  to_next, n_left_to_next);
81 
82  while (n_left_from >= 4 && n_left_to_next >= 2)
83  {
84  ip_adjacency_t * adj0;
86  vlib_buffer_t * p0;
87  u32 pi0, adj_index0, next0, error0;
88  word rw_len0;
89 
90  ip_adjacency_t * adj1;
92  vlib_buffer_t * p1;
93  u32 pi1, adj_index1, next1, error1;
94  word rw_len1;
95 
96  /* Prefetch next iteration. */
97  {
98  vlib_buffer_t * p2, * p3;
99 
100  p2 = vlib_get_buffer (vm, from[2]);
101  p3 = vlib_get_buffer (vm, from[3]);
102 
103  vlib_prefetch_buffer_header (p2, STORE);
104  vlib_prefetch_buffer_header (p3, STORE);
105 
106  CLIB_PREFETCH (p2->data, sizeof (hdr0[0]), STORE);
107  CLIB_PREFETCH (p3->data, sizeof (hdr1[0]), STORE);
108  }
109 
110  pi0 = to_next[0] = from[0];
111  pi1 = to_next[1] = from[1];
112 
113  from += 2;
114  n_left_from -= 2;
115  to_next += 2;
116  n_left_to_next -= 2;
117 
118  p0 = vlib_get_buffer (vm, pi0);
119  p1 = vlib_get_buffer (vm, pi1);
120 
121  adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
122  adj_index1 = vnet_buffer (p1)->ip.adj_index[VLIB_TX];
123 
124  adj0 = adj_get(adj_index0);
125  adj1 = adj_get(adj_index1);
126  hdr0 = vlib_buffer_get_current (p0);
127  hdr1 = vlib_buffer_get_current (p1);
128 
129  /* Guess we are only writing on simple Ethernet header. */
130  vnet_rewrite_two_headers (adj0[0], adj1[0], hdr0, hdr1,
131  sizeof (ethernet_header_t));
132 
133  /* Update packet buffer attributes/set output interface. */
134  rw_len0 = adj0[0].rewrite_header.data_bytes;
135  rw_len1 = adj1[0].rewrite_header.data_bytes;
136  vnet_buffer (p0)->mpls.save_rewrite_length = rw_len0;
137  vnet_buffer (p1)->mpls.save_rewrite_length = rw_len1;
138 
139  /* Bump the adj counters for packet and bytes */
142  thread_index,
143  adj_index0,
144  1,
145  vlib_buffer_length_in_chain (vm, p0) + rw_len0);
148  thread_index,
149  adj_index1,
150  1,
151  vlib_buffer_length_in_chain (vm, p1) + rw_len1);
152 
153  /* Check MTU of outgoing interface. */
155  adj0[0].rewrite_header.max_l3_packet_bytes))
156  {
157  vlib_buffer_advance(p0, -rw_len0);
158 
159  vnet_buffer (p0)->sw_if_index[VLIB_TX] =
160  adj0[0].rewrite_header.sw_if_index;
161  next0 = adj0[0].rewrite_header.next_index;
162  error0 = IP4_ERROR_NONE;
163 
164  if (PREDICT_FALSE(adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
166  adj0[0].rewrite_header.sw_if_index,
167  &next0, p0);
168  }
169  else
170  {
171  error0 = IP4_ERROR_MTU_EXCEEDED;
172  next0 = MPLS_OUTPUT_NEXT_FRAG;
174  MPLS_ERROR_PKTS_NEED_FRAG,
175  1);
176  }
178  adj1[0].rewrite_header.max_l3_packet_bytes))
179  {
180  vlib_buffer_advance(p1, -rw_len1);
181 
182  vnet_buffer (p1)->sw_if_index[VLIB_TX] =
183  adj1[0].rewrite_header.sw_if_index;
184  next1 = adj1[0].rewrite_header.next_index;
185  error1 = IP4_ERROR_NONE;
186 
187  if (PREDICT_FALSE(adj1[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
189  adj1[0].rewrite_header.sw_if_index,
190  &next1, p1);
191  }
192  else
193  {
194  error1 = IP4_ERROR_MTU_EXCEEDED;
195  next1 = MPLS_OUTPUT_NEXT_FRAG;
197  MPLS_ERROR_PKTS_NEED_FRAG,
198  1);
199  }
200  if (mode == MPLS_OUTPUT_MIDCHAIN_MODE)
201  {
202  adj0->sub_type.midchain.fixup_func
203  (vm, adj0, p0,
204  adj0->sub_type.midchain.fixup_data);
205  adj1->sub_type.midchain.fixup_func
206  (vm, adj1, p1,
207  adj1->sub_type.midchain.fixup_data);
208  }
209 
210  p0->error = error_node->errors[error0];
211  p1->error = error_node->errors[error1];
212 
213  if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED))
214  {
215  mpls_output_trace_t *tr = vlib_add_trace (vm, node,
216  p0, sizeof (*tr));
217  tr->adj_index = vnet_buffer(p0)->ip.adj_index[VLIB_TX];
218  tr->flow_hash = vnet_buffer(p0)->ip.flow_hash;
219  }
220  if (PREDICT_FALSE(p1->flags & VLIB_BUFFER_IS_TRACED))
221  {
222  mpls_output_trace_t *tr = vlib_add_trace (vm, node,
223  p1, sizeof (*tr));
224  tr->adj_index = vnet_buffer(p1)->ip.adj_index[VLIB_TX];
225  tr->flow_hash = vnet_buffer(p1)->ip.flow_hash;
226  }
227 
228  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
229  to_next, n_left_to_next,
230  pi0, pi1, next0, next1);
231  }
232 
233  while (n_left_from > 0 && n_left_to_next > 0)
234  {
235  ip_adjacency_t * adj0;
236  mpls_unicast_header_t *hdr0;
237  vlib_buffer_t * p0;
238  u32 pi0, adj_index0, next0, error0;
239  word rw_len0;
240 
241  pi0 = to_next[0] = from[0];
242 
243  p0 = vlib_get_buffer (vm, pi0);
244 
245  adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
246 
247  adj0 = adj_get(adj_index0);
248  hdr0 = vlib_buffer_get_current (p0);
249 
250  /* Guess we are only writing on simple Ethernet header. */
251  vnet_rewrite_one_header (adj0[0], hdr0,
252  sizeof (ethernet_header_t));
253 
254  /* Update packet buffer attributes/set output interface. */
255  rw_len0 = adj0[0].rewrite_header.data_bytes;
256  vnet_buffer (p0)->mpls.save_rewrite_length = rw_len0;
257 
260  thread_index,
261  adj_index0,
262  1,
263  vlib_buffer_length_in_chain (vm, p0) + rw_len0);
264 
265  /* Check MTU of outgoing interface. */
267  adj0[0].rewrite_header.max_l3_packet_bytes))
268  {
269  vlib_buffer_advance(p0, -rw_len0);
270 
271  vnet_buffer (p0)->sw_if_index[VLIB_TX] =
272  adj0[0].rewrite_header.sw_if_index;
273  next0 = adj0[0].rewrite_header.next_index;
274  error0 = IP4_ERROR_NONE;
275 
276  if (PREDICT_FALSE(adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
278  adj0[0].rewrite_header.sw_if_index,
279  &next0, p0);
280  }
281  else
282  {
283  error0 = IP4_ERROR_MTU_EXCEEDED;
284  next0 = MPLS_OUTPUT_NEXT_FRAG;
286  MPLS_ERROR_PKTS_NEED_FRAG,
287  1);
288  }
289  if (mode == MPLS_OUTPUT_MIDCHAIN_MODE)
290  {
291  adj0->sub_type.midchain.fixup_func
292  (vm, adj0, p0,
293  adj0->sub_type.midchain.fixup_data);
294  }
295 
296  p0->error = error_node->errors[error0];
297 
298  from += 1;
299  n_left_from -= 1;
300  to_next += 1;
301  n_left_to_next -= 1;
302 
303  if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED))
304  {
305  mpls_output_trace_t *tr = vlib_add_trace (vm, node,
306  p0, sizeof (*tr));
307  tr->adj_index = vnet_buffer(p0)->ip.adj_index[VLIB_TX];
308  tr->flow_hash = vnet_buffer(p0)->ip.flow_hash;
309  }
310 
311  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
312  to_next, n_left_to_next,
313  pi0, next0);
314  }
315 
316  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
317  }
319  MPLS_ERROR_PKTS_ENCAP,
320  from_frame->n_vectors);
321 
322  return from_frame->n_vectors;
323 }
324 
325 static char * mpls_error_strings[] = {
326 #define mpls_error(n,s) s,
327 #include "error.def"
328 #undef mpls_error
329 };
330 
333  vlib_frame_t * from_frame)
334 {
335  return (mpls_output_inline(vm, node, from_frame, MPLS_OUTPUT_MODE));
336 }
337 
339  .name = "mpls-output",
340  /* Takes a vector of packets. */
341  .vector_size = sizeof (u32),
342  .n_errors = MPLS_N_ERROR,
343  .error_strings = mpls_error_strings,
344 
345  .n_next_nodes = MPLS_OUTPUT_N_NEXT,
346  .next_nodes = {
347  [MPLS_OUTPUT_NEXT_DROP] = "mpls-drop",
348  [MPLS_OUTPUT_NEXT_FRAG] = "mpls-frag",
349  },
350  .format_trace = format_mpls_output_trace,
351 };
352 
355  vlib_frame_t * from_frame)
356 {
357  return (mpls_output_inline(vm, node, from_frame, MPLS_OUTPUT_MIDCHAIN_MODE));
358 }
359 
361  .name = "mpls-midchain",
362  .vector_size = sizeof (u32),
363 
364  .n_errors = MPLS_N_ERROR,
365  .error_strings = mpls_error_strings,
366 
367  .sibling_of = "mpls-output",
368  .format_trace = format_mpls_output_trace,
369 };
370 
371 static char *mpls_frag_error_strings[] = {
372 #define _(sym,string) string,
374 #undef _
375 };
376 
377 typedef struct mpls_frag_trace_t_
378 {
382 
383 typedef enum
384 {
391 
392 static uword
396 {
397  u32 n_left_from, next_index, * from, * to_next, n_left_to_next, *frags;
398  vlib_node_runtime_t * error_node;
399 
400  error_node = vlib_node_get_runtime (vm, mpls_output_node.index);
401  from = vlib_frame_vector_args (frame);
402  n_left_from = frame->n_vectors;
403  next_index = node->cached_next_index;
404  frags = NULL;
405 
406  while (n_left_from > 0)
407  {
408  vlib_get_next_frame (vm, node, next_index,
409  to_next, n_left_to_next);
410 
411  while (n_left_from > 0 && n_left_to_next > 0)
412  {
413  ip_adjacency_t * adj0;
414  vlib_buffer_t * p0;
415  mpls_frag_next_t next0;
416  u32 pi0, adj_index0;
417  ip_frag_error_t error0 = IP_FRAG_ERROR_NONE;
418  i16 encap_size;
419  u8 is_ip4;
420 
421  pi0 = to_next[0] = from[0];
422  p0 = vlib_get_buffer (vm, pi0);
423  from += 1;
424  n_left_from -= 1;
425  is_ip4 = vnet_buffer (p0)->mpls.pyld_proto == DPO_PROTO_IP4;
426 
427  adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
428  adj0 = adj_get(adj_index0);
429 
430  /* the size of the MPLS stack */
431  encap_size = vnet_buffer(p0)->l3_hdr_offset - p0->current_data;
432 
433  /* IP fragmentation */
434  if (is_ip4)
435  error0 = ip4_frag_do_fragment (vm, pi0,
436  adj0->rewrite_header.max_l3_packet_bytes,
437  encap_size, &frags);
438  else
439  error0 = ip6_frag_do_fragment (vm, pi0,
440  adj0->rewrite_header.max_l3_packet_bytes,
441  encap_size, &frags);
442 
443  if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED))
444  {
445  mpls_frag_trace_t *tr =
446  vlib_add_trace (vm, node, p0, sizeof (*tr));
447  tr->mtu = adj0->rewrite_header.max_l3_packet_bytes;
449  }
450 
451  if (PREDICT_TRUE(error0 == IP_FRAG_ERROR_NONE))
452  {
453  /* Free original buffer chain */
454  vlib_buffer_free_one (vm, pi0); /* Free original packet */
455  next0 = (IP_LOOKUP_NEXT_MIDCHAIN == adj0->lookup_next_index ?
458  }
459  else if (is_ip4 && error0 == IP_FRAG_ERROR_DONT_FRAGMENT_SET)
460  {
462  p0, ICMP4_destination_unreachable,
463  ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
464  vnet_buffer (p0)->ip_frag.mtu);
466  }
467  else
468  {
469  vlib_error_count (vm, mpls_output_node.index, error0, 1);
470  vec_add1 (frags, pi0); /* Get rid of the original buffer */
471  next0 = MPLS_FRAG_NEXT_DROP;
472  }
473 
474  /* Send fragments that were added in the frame */
475  u32 *frag_from, frag_left;
476 
477  frag_from = frags;
478  frag_left = vec_len (frags);
479 
480  while (frag_left > 0)
481  {
482  while (frag_left > 0 && n_left_to_next > 0)
483  {
484  u32 i;
485  i = to_next[0] = frag_from[0];
486  frag_from += 1;
487  frag_left -= 1;
488  to_next += 1;
489  n_left_to_next -= 1;
490 
491  p0 = vlib_get_buffer (vm, i);
492  p0->error = error_node->errors[error0];
493 
494  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
495  to_next, n_left_to_next, i,
496  next0);
497  }
498  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
499  vlib_get_next_frame (vm, node, next_index, to_next,
500  n_left_to_next);
501  }
502  vec_reset_length (frags);
503  }
504  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
505  }
506  vec_free (frags);
507 
508  return frame->n_vectors;
509 }
510 
511 static u8 *
512 format_mpls_frag_trace (u8 * s, va_list * args)
513 {
514  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
515  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
516  mpls_frag_trace_t *t = va_arg (*args, mpls_frag_trace_t *);
517 
518  s = format (s, "mtu:%d pkt-size:%d", t->mtu, t->pkt_size);
519  return s;
520 }
521 
523  .function = mpls_frag,
524  .name = "mpls-frag",
525  .vector_size = sizeof (u32),
526  .format_trace = format_mpls_frag_trace,
528 
529  .n_errors = IP_FRAG_N_ERROR,
530  .error_strings = mpls_frag_error_strings,
531 
532  .n_next_nodes = MPLS_FRAG_N_NEXT,
533  .next_nodes = {
534  [MPLS_FRAG_NEXT_REWRITE] = "mpls-output",
535  [MPLS_FRAG_NEXT_REWRITE_MIDCHAIN] = "mpls-midchain",
536  [MPLS_FRAG_NEXT_ICMP_ERROR] = "ip4-icmp-error",
537  [MPLS_FRAG_NEXT_DROP] = "mpls-drop"
538  },
539 };
540 
541 /*
542  * @brief Next index values from the MPLS incomplete adj node
543  */
544 #define foreach_mpls_adj_incomplete_next \
545 _(DROP, "error-drop") \
546 _(IP4, "ip4-arp") \
547 _(IP6, "ip6-discover-neighbor")
548 
549 typedef enum {
550 #define _(s,n) MPLS_ADJ_INCOMPLETE_NEXT_##s,
552 #undef _
555 
556 /**
557  * @brief A struct to hold tracing information for the MPLS label imposition
558  * node.
559  */
561 {
564 
565 
566 /**
567  * @brief Graph node for incomplete MPLS adjacency.
568  * This node will push traffic to either the v4-arp or v6-nd node
569  * based on the next-hop proto of the adj.
570  * We pay a cost for this 'routing' node, but an incomplete adj is the
571  * exception case.
572  */
575  vlib_frame_t * from_frame)
576 {
577  u32 n_left_from, next_index, * from, * to_next;
578 
579  from = vlib_frame_vector_args (from_frame);
580  n_left_from = from_frame->n_vectors;
581  next_index = node->cached_next_index;
582 
583  while (n_left_from > 0)
584  {
585  u32 n_left_to_next;
586 
587  vlib_get_next_frame (vm, node, next_index,
588  to_next, n_left_to_next);
589 
590  while (n_left_from > 0 && n_left_to_next > 0)
591  {
592  u32 pi0, next0, adj_index0;
593  ip_adjacency_t * adj0;
594  vlib_buffer_t * p0;
595 
596  pi0 = to_next[0] = from[0];
597  p0 = vlib_get_buffer (vm, pi0);
598  from += 1;
599  n_left_from -= 1;
600  to_next += 1;
601  n_left_to_next -= 1;
602 
603  adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
604 
605  adj0 = adj_get(adj_index0);
606 
608  {
609  next0 = MPLS_ADJ_INCOMPLETE_NEXT_IP4;
610  }
611  else
612  {
613  next0 = MPLS_ADJ_INCOMPLETE_NEXT_IP6;
614  }
615 
616  if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED))
617  {
619  vlib_add_trace (vm, node, p0, sizeof (*tr));
620  tr->next = next0;
621  }
622 
623  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
624  to_next, n_left_to_next,
625  pi0, next0);
626  }
627 
628  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
629  }
630 
631  return from_frame->n_vectors;
632 }
633 
634 static u8 *
636 {
637  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
638  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
640  u32 indent;
641 
642  t = va_arg (*args, mpls_adj_incomplete_trace_t *);
643  indent = format_get_indent (s);
644 
645  s = format (s, "%Unext:%d",
646  format_white_space, indent,
647  t->next);
648  return (s);
649 }
650 
652  .name = "mpls-adj-incomplete",
653  .format_trace = format_mpls_adj_incomplete_trace,
654  /* Takes a vector of packets. */
655  .vector_size = sizeof (u32),
656  .n_errors = MPLS_N_ERROR,
657  .error_strings = mpls_error_strings,
658 
659  .n_next_nodes = MPLS_ADJ_INCOMPLETE_N_NEXT,
660  .next_nodes = {
661 #define _(s,n) [MPLS_ADJ_INCOMPLETE_NEXT_##s] = n,
663 #undef _
664  },
665 };
#define vnet_rewrite_one_header(rw0, p0, most_likely_size)
Definition: rewrite.h:216
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:124
#define foreach_mpls_output_next
Definition: mpls_output.c:34
#define CLIB_UNUSED(x)
Definition: clib.h:87
#define foreach_ip_frag_error
Definition: ip_frag.h:60
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:239
#define PREDICT_TRUE(x)
Definition: clib.h:122
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:57
IP unicast adjacency.
Definition: adj.h:235
A struct to hold tracing information for the MPLS label imposition node.
Definition: mpls_output.c:560
static u8 * format_mpls_frag_trace(u8 *s, va_list *args)
Definition: mpls_output.c:512
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
static u8 * format_mpls_adj_incomplete_trace(u8 *s, va_list *args)
Definition: mpls_output.c:635
static u32 format_get_indent(u8 *s)
Definition: format.h:72
struct ip_adjacency_t_::@161::@163 midchain
IP_LOOKUP_NEXT_MIDCHAIN.
vlib_main_t * vm
Definition: in2out_ed.c:1580
#define VLIB_NODE_FN(node)
Definition: node.h:203
mpls_frag_next_t
Definition: mpls_output.c:383
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:470
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:402
unsigned char u8
Definition: types.h:56
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static u8 * format_mpls_output_trace(u8 *s, va_list *args)
Definition: mpls_output.c:46
vlib_node_registration_t mpls_midchain_node
(constructor) VLIB_REGISTER_NODE (mpls_midchain_node)
Definition: mpls_output.c:360
vlib_node_registration_t mpls_output_node
(constructor) VLIB_REGISTER_NODE (mpls_output_node)
Definition: mpls_output.c:338
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:467
i64 word
Definition: types.h:111
format_function_t format_ip_adjacency
Definition: format.h:58
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
description fragment has unexpected format
Definition: map.api:433
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:207
mpls_adj_incomplete_next_t
Definition: mpls_output.c:549
mpls_output_next_t
Definition: mpls_output.c:38
unsigned int u32
Definition: types.h:88
u8 output_feature_arc_index
Definition: mpls.h:57
static uword mpls_output_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, mpls_output_mode_t mode)
Definition: mpls_output.c:60
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
vlib_node_registration_t mpls_frag_node
(constructor) VLIB_REGISTER_NODE (mpls_frag_node)
Definition: mpls_output.c:522
unsigned short u16
Definition: types.h:57
static char * mpls_frag_error_strings[]
Definition: mpls_output.c:371
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:233
#define PREDICT_FALSE(x)
Definition: clib.h:121
#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:224
#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:391
vlib_combined_counter_main_t adjacency_counters
Adjacency packet counters.
Definition: adj.c:25
vl_api_tunnel_mode_t mode
Definition: gre.api:48
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1231
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:170
u16 n_vectors
Definition: node.h:397
mpls_main_t mpls_main
Definition: mpls.c:25
ip_frag_error_t ip6_frag_do_fragment(vlib_main_t *vm, u32 from_bi, u16 mtu, u16 l2unfragmentablesize, u32 **buffer)
Definition: ip_frag.c:382
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:219
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
mpls_output_mode_t
Definition: mpls_output.c:29
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
ip_frag_error_t
Definition: ip_frag.h:71
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
#define foreach_mpls_adj_incomplete_next
Definition: mpls_output.c:544
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:115
u8 data[]
Packet data.
Definition: buffer.h:181
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:483
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1580
This packets follow a mid-chain adjacency.
Definition: adj.h:76
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:511
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:252
static char * mpls_error_strings[]
Definition: mpls_output.c:325
union ip_adjacency_t_::@161 sub_type
fib_protocol_t ia_nh_proto
The protocol of the neighbor/peer.
Definition: adj.h:350
Definition: defs.h:47
struct mpls_frag_trace_t_ mpls_frag_trace_t
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:337
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1581
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
ip_frag_error_t ip4_frag_do_fragment(vlib_main_t *vm, u32 from_bi, u16 mtu, u16 l2unfragmentablesize, u32 **buffer)
Definition: ip_frag.c:94
#define vnet_buffer(b)
Definition: buffer.h:417
struct mpls_adj_incomplete_trace_t_ mpls_adj_incomplete_trace_t
A struct to hold tracing information for the MPLS label imposition node.
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:634
static void vlib_buffer_free_one(vlib_main_t *vm, u32 buffer_index)
Free one buffer Shorthand to free a single buffer chain.
Definition: buffer_funcs.h:970
vlib_node_registration_t mpls_adj_incomplete_node
(constructor) VLIB_REGISTER_NODE (mpls_adj_incomplete_node)
Definition: mpls_output.c:651
#define vnet_rewrite_two_headers(rw0, rw1, p0, p1, most_likely_size)
Definition: rewrite.h:220
This adjacency/interface has output features configured.
Definition: rewrite.h:57
static_always_inline void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.h:51
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
static uword mpls_frag(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: mpls_output.c:393
signed short i16
Definition: types.h:46
static_always_inline void vnet_feature_arc_start(u8 arc, u32 sw_if_index, u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:302