FD.io VPP  v17.04-9-g99c0734
Vector Packet Processing
mpls_tunnel.c
Go to the documentation of this file.
1 /*
2  * mpls_tunnel.c: MPLS tunnel interfaces (i.e. for RSVP-TE)
3  *
4  * Copyright (c) 2012 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 <vnet/vnet.h>
19 #include <vnet/pg/pg.h>
20 #include <vnet/mpls/mpls_tunnel.h>
21 #include <vnet/ip/ip.h>
22 #include <vnet/fib/fib_path_list.h>
23 #include <vnet/adj/adj_midchain.h>
24 
25 /**
26  * @brief pool of tunnel instances
27  */
29 
30 /**
31  * @brief Pool of free tunnel SW indices - i.e. recycled indices
32  */
34 
35 /**
36  * @brief DB of SW index to tunnel index
37  */
39 
40 /**
41  * @brief Get a tunnel object from a SW interface index
42  */
43 static mpls_tunnel_t*
45 {
46  if ((vec_len(mpls_tunnel_db) < sw_if_index) ||
47  (~0 == mpls_tunnel_db[sw_if_index]))
48  return (NULL);
49 
50  return (pool_elt_at_index(mpls_tunnel_pool,
51  mpls_tunnel_db[sw_if_index]));
52 }
53 
54 /**
55  * @brief Return true if the label stack is imp-null only
56  */
59 {
60  if ((1 == vec_len(mt->mt_label_stack)) &&
62  {
63  /*
64  * the only label in the label stack is implicit null
65  * we need to build an IP chain.
66  */
68  {
70  }
71  else
72  {
74  }
75  }
76  else
77  {
79  }
80 }
81 
82 /**
83  * @brief Build a rewrite string for the MPLS tunnel.
84  *
85  * We have choices here;
86  * 1 - have an Adjacency with a zero length string and stack it on
87  * MPLS label objects
88  * 2 - put the label header rewrites in the adjacency string.
89  *
90  * We choose 2 since it results in fewer graph nodes in the egress path
91  */
92 static u8*
94  u32 sw_if_index,
95  vnet_link_t link_type,
96  const void *dst_address)
97 {
99  mpls_tunnel_t *mt;
100  u8 *rewrite;
101  u32 mti, ii;
102 
103  rewrite = NULL;
104  mti = mpls_tunnel_db[sw_if_index];
105  mt = pool_elt_at_index(mpls_tunnel_pool, mti);
106 
107  /*
108  * The vector must be allocated as u8 so the length is correct
109  */
110  ASSERT(0 < vec_len(mt->mt_label_stack));
111  vec_validate(rewrite, (sizeof(*muh) * vec_len(mt->mt_label_stack)) - 1);
112  ASSERT(rewrite);
113  muh = (mpls_unicast_header_t *)rewrite;
114 
115  /*
116  * The last (inner most) label in the stack may be EOS, all the rest Non-EOS
117  */
118  for (ii = 0; ii < vec_len(mt->mt_label_stack)-1; ii++)
119  {
120  vnet_mpls_uc_set_label(&muh[ii].label_exp_s_ttl, mt->mt_label_stack[ii]);
121  vnet_mpls_uc_set_ttl(&muh[ii].label_exp_s_ttl, 255);
122  vnet_mpls_uc_set_exp(&muh[ii].label_exp_s_ttl, 0);
123  vnet_mpls_uc_set_s(&muh[ii].label_exp_s_ttl, MPLS_NON_EOS);
124  muh[ii].label_exp_s_ttl = clib_host_to_net_u32(muh[ii].label_exp_s_ttl);
125  }
126 
127  vnet_mpls_uc_set_label(&muh[ii].label_exp_s_ttl, mt->mt_label_stack[ii]);
128  vnet_mpls_uc_set_ttl(&muh[ii].label_exp_s_ttl, 255);
129  vnet_mpls_uc_set_exp(&muh[ii].label_exp_s_ttl, 0);
130 
131  if ((VNET_LINK_MPLS == link_type) &&
133  {
134  vnet_mpls_uc_set_s(&muh[ii].label_exp_s_ttl, MPLS_NON_EOS);
135  }
136  else
137  {
138  vnet_mpls_uc_set_s(&muh[ii].label_exp_s_ttl, MPLS_EOS);
139  }
140 
141  muh[ii].label_exp_s_ttl = clib_host_to_net_u32(muh[ii].label_exp_s_ttl);
142 
143  return (rewrite);
144 }
145 
146 /**
147  * mpls_tunnel_stack
148  *
149  * 'stack' (resolve the recursion for) the tunnel's midchain adjacency
150  */
151 static void
153 {
154  ip_adjacency_t *adj;
155  mpls_tunnel_t *mt;
156  u32 sw_if_index;
157 
158  adj = adj_get(ai);
159  sw_if_index = adj->rewrite_header.sw_if_index;
160 
161  mt = mpls_tunnel_get_from_sw_if_index(sw_if_index);
162 
163  if (NULL == mt)
164  return;
165 
166  /*
167  * find the adjacency that is contributed by the FIB path-list
168  * that this tunnel resovles via, and use it as the next adj
169  * in the midchain
170  */
172  mt->mt_hw_if_index) &
174  {
175  dpo_id_t dpo = DPO_INVALID;
176 
179  &dpo);
180 
181  if (DPO_LOAD_BALANCE == dpo.dpoi_type)
182  {
183  /*
184  * we don't support multiple paths, so no need to load-balance.
185  * pull the first and only choice and stack directly on that.
186  */
187  load_balance_t *lb;
188 
189  lb = load_balance_get (dpo.dpoi_index);
190 
191  ASSERT(1 == lb->lb_n_buckets);
192 
193  dpo_copy(&dpo, load_balance_get_bucket_i (lb, 0));
194  }
195 
196  adj_nbr_midchain_stack(ai, &dpo);
197  dpo_reset(&dpo);
198  }
199  else
200  {
202  }
203 }
204 
205 /**
206  * @brief Call back when restacking all adjacencies on a MPLS interface
207  */
208 static adj_walk_rc_t
210  void *ctx)
211 {
212  mpls_tunnel_stack(ai);
213 
214  return (ADJ_WALK_RC_CONTINUE);
215 }
216 
217 static void
219 {
220  fib_protocol_t proto;
221 
222  /*
223  * walk all the adjacencies on the MPLS interface and restack them
224  */
225  FOR_EACH_FIB_PROTOCOL(proto)
226  {
228  proto,
230  NULL);
231  }
232 }
233 
234 static clib_error_t *
236  u32 hw_if_index,
237  u32 flags)
238 {
240  mpls_tunnel_t *mt;
241 
242  hi = vnet_get_hw_interface (vnm, hw_if_index);
243 
245 
246  if (NULL == mt)
247  return (NULL);
248 
250  vnet_hw_interface_set_flags (vnm, hw_if_index,
252  else
253  vnet_hw_interface_set_flags (vnm, hw_if_index, 0 /* down */);
254 
256 
257  return (NULL);
258 }
259 
260 /**
261  * @brief Fixup the adj rewrite post encap. This is a no-op since the
262  * rewrite is a stack of labels.
263  */
264 static void
266  ip_adjacency_t *adj,
267  vlib_buffer_t *b0)
268 {
269 }
270 
271 static void
273  u32 sw_if_index,
274  adj_index_t ai)
275 {
277  ai, mpls_tunnel_fixup,
279  mpls_tunnel_build_rewrite(vnm, sw_if_index,
280  adj_get_link_type(ai),
281  NULL));
282 
283  mpls_tunnel_stack(ai);
284 }
285 
286 static u8 *
287 format_mpls_tunnel_name (u8 * s, va_list * args)
288 {
289  u32 dev_instance = va_arg (*args, u32);
290  return format (s, "mpls-tunnel%d", dev_instance);
291 }
292 
293 static u8 *
294 format_mpls_tunnel_device (u8 * s, va_list * args)
295 {
296  u32 dev_instance = va_arg (*args, u32);
297  CLIB_UNUSED (int verbose) = va_arg (*args, int);
298 
299  return (format (s, "MPLS-tunnel: id %d\n", dev_instance));
300 }
301 
302 /**
303  * @brief Packet trace structure
304  */
305 typedef struct mpls_tunnel_trace_t_
306 {
307  /**
308  * Tunnel-id / index in tunnel vector
309  */
312 
313 static u8 *
315  va_list * args)
316 {
317  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
318  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
319  mpls_tunnel_trace_t * t = va_arg (*args, mpls_tunnel_trace_t *);
320 
321  s = format (s, "MPLS: tunnel %d", t->tunnel_id);
322  return s;
323 }
324 
325 /**
326  * @brief TX function. Only called L2. L3 traffic uses the adj-midchains
327  */
328 static uword
330  vlib_node_runtime_t * node,
331  vlib_frame_t * frame)
332 {
333  u32 next_index;
334  u32 * from, * to_next, n_left_from, n_left_to_next;
335  vnet_interface_output_runtime_t * rd = (void *) node->runtime_data;
336  const mpls_tunnel_t *mt;
337 
338  mt = pool_elt_at_index(mpls_tunnel_pool, rd->dev_instance);
339 
340  /* Vector of buffer / pkt indices we're supposed to process */
341  from = vlib_frame_vector_args (frame);
342 
343  /* Number of buffers / pkts */
344  n_left_from = frame->n_vectors;
345 
346  /* Speculatively send the first buffer to the last disposition we used */
347  next_index = node->cached_next_index;
348 
349  while (n_left_from > 0)
350  {
351  /* set up to enqueue to our disposition with index = next_index */
352  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
353 
354  /*
355  * FIXME DUAL LOOP
356  */
357  while (n_left_from > 0 && n_left_to_next > 0)
358  {
359  vlib_buffer_t * b0;
360  u32 bi0;
361 
362  bi0 = from[0];
363  to_next[0] = bi0;
364  from += 1;
365  to_next += 1;
366  n_left_from -= 1;
367  n_left_to_next -= 1;
368 
369  b0 = vlib_get_buffer(vm, bi0);
370 
371  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mt->mt_l2_adj;
372 
374  {
375  mpls_tunnel_trace_t *tr = vlib_add_trace (vm, node,
376  b0, sizeof (*tr));
377  tr->tunnel_id = rd->dev_instance;
378  }
379 
380  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
381  to_next, n_left_to_next,
382  bi0, mt->mt_l2_tx_arc);
383  }
384 
385  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
386  }
387 
388  return frame->n_vectors;
389 }
390 
391 VNET_DEVICE_CLASS (mpls_tunnel_class) = {
392  .name = "MPLS tunnel device",
393  .format_device_name = format_mpls_tunnel_name,
394  .format_device = format_mpls_tunnel_device,
395  .format_tx_trace = format_mpls_tunnel_tx_trace,
396  .tx_function = mpls_tunnel_tx,
397  .admin_up_down_function = mpls_tunnel_admin_up_down,
398 };
399 
400 VNET_HW_INTERFACE_CLASS (mpls_tunnel_hw_interface_class) = {
401  .name = "MPLS-Tunnel",
402 // .format_header = format_mpls_eth_header_with_length,
403 // .unformat_header = unformat_mpls_eth_header,
404  .update_adjacency = mpls_tunnel_update_adj,
405  .build_rewrite = mpls_tunnel_build_rewrite,
407 };
408 
409 const mpls_tunnel_t *
411 {
412  return (pool_elt_at_index(mpls_tunnel_pool, mti));
413 }
414 
415 /**
416  * @brief Walk all the MPLS tunnels
417  */
418 void
420  void *ctx)
421 {
422  u32 mti;
423 
424  pool_foreach_index(mti, mpls_tunnel_pool,
425  ({
426  cb(mti, ctx);
427  }));
428 }
429 
430 void
432 {
433  mpls_tunnel_t *mt;
434 
435  mt = mpls_tunnel_get_from_sw_if_index(sw_if_index);
436 
437  if (NULL == mt)
438  return;
439 
441  mt->mt_sibling_index);
442  if (ADJ_INDEX_INVALID != mt->mt_l2_adj)
443  adj_unlock(mt->mt_l2_adj);
444 
446 
448  pool_put(mpls_tunnel_pool, mt);
449  mpls_tunnel_db[sw_if_index] = ~0;
450 }
451 
452 void
454  mpls_label_t *label_stack,
455  u8 l2_only,
456  u32 *sw_if_index)
457 {
459  mpls_tunnel_t *mt;
460  vnet_main_t * vnm;
461  u32 mti;
462 
463  vnm = vnet_get_main();
464  pool_get(mpls_tunnel_pool, mt);
465  memset (mt, 0, sizeof (*mt));
466  mti = mt - mpls_tunnel_pool;
469 
470  /*
471  * Create a new, or re=use and old, tunnel HW interface
472  */
474  {
475  mt->mt_hw_if_index =
477  _vec_len (mpls_tunnel_free_hw_if_indices) -= 1;
478  hi = vnet_get_hw_interface (vnm, mt->mt_hw_if_index);
479  hi->hw_instance = mti;
480  hi->dev_instance = mti;
481  }
482  else
483  {
485  vnm,
486  mpls_tunnel_class.index,
487  mti,
488  mpls_tunnel_hw_interface_class.index,
489  mti);
490  hi = vnet_get_hw_interface(vnm, mt->mt_hw_if_index);
491  }
492 
493  /*
494  * Add the new tunnel to the tunnel DB - key:SW if index
495  */
496  mt->mt_sw_if_index = hi->sw_if_index;
498  mpls_tunnel_db[mt->mt_sw_if_index] = mti;
499 
500  /*
501  * construct a path-list from the path provided
502  */
506  mti);
507 
508  mt->mt_label_stack = vec_dup(label_stack);
509 
510  if (l2_only)
511  {
512  mt->mt_l2_adj =
515  &zero_addr,
516  mt->mt_sw_if_index);
517 
519  hi->tx_node_index,
520  "adj-l2-midchain");
521  }
522 
523  *sw_if_index = mt->mt_sw_if_index;
524 }
525 
526 static clib_error_t *
528  unformat_input_t * input,
529  vlib_cli_command_t * cmd)
530 {
531  unformat_input_t _line_input, * line_input = &_line_input;
532  vnet_main_t * vnm = vnet_get_main();
533  u8 is_del = 0;
534  u8 l2_only = 0;
535  fib_route_path_t rpath, *rpaths = NULL;
536  mpls_label_t out_label = MPLS_LABEL_INVALID, *labels = NULL;
537  u32 sw_if_index;
538  clib_error_t *error = NULL;
539 
540  memset(&rpath, 0, sizeof(rpath));
541 
542  /* Get a line of input. */
543  if (! unformat_user (input, unformat_line_input, line_input))
544  return 0;
545 
546  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
547  {
548  if (unformat (line_input, "del %U",
550  &sw_if_index))
551  is_del = 1;
552  else if (unformat (line_input, "add"))
553  is_del = 0;
554  else if (unformat (line_input, "out-label %U",
555  unformat_mpls_unicast_label, &out_label))
556  {
557  vec_add1(labels, out_label);
558  }
559  else if (unformat (line_input, "via %U %U",
561  &rpath.frp_addr.ip4,
563  &rpath.frp_sw_if_index))
564  {
565  rpath.frp_weight = 1;
566  rpath.frp_proto = FIB_PROTOCOL_IP4;
567  }
568 
569  else if (unformat (line_input, "via %U %U",
571  &rpath.frp_addr.ip6,
573  &rpath.frp_sw_if_index))
574  {
575  rpath.frp_weight = 1;
576  rpath.frp_proto = FIB_PROTOCOL_IP6;
577  }
578  else if (unformat (line_input, "via %U",
580  &rpath.frp_addr.ip6))
581  {
582  rpath.frp_fib_index = 0;
583  rpath.frp_weight = 1;
584  rpath.frp_sw_if_index = ~0;
585  rpath.frp_proto = FIB_PROTOCOL_IP6;
586  }
587  else if (unformat (line_input, "via %U",
589  &rpath.frp_addr.ip4))
590  {
591  rpath.frp_fib_index = 0;
592  rpath.frp_weight = 1;
593  rpath.frp_sw_if_index = ~0;
594  rpath.frp_proto = FIB_PROTOCOL_IP4;
595  }
596  else if (unformat (line_input, "l2-only"))
597  l2_only = 1;
598  else
599  {
600  error = clib_error_return (0, "unknown input '%U'",
601  format_unformat_error, line_input);
602  goto done;
603  }
604  }
605 
606  if (is_del)
607  {
608  vnet_mpls_tunnel_del(sw_if_index);
609  }
610  else
611  {
612  if (0 == vec_len(labels))
613  {
614  error = clib_error_return (0, "No Output Labels '%U'",
615  format_unformat_error, line_input);
616  goto done;
617  }
618 
619  vec_add1(rpaths, rpath);
620  vnet_mpls_tunnel_add(rpaths, labels, l2_only, &sw_if_index);
621  }
622 
623 done:
624  vec_free(labels);
625  vec_free(rpaths);
626  unformat_free (line_input);
627 
628  return error;
629 }
630 
631 /*?
632  * This command create a uni-directional MPLS tunnel
633  *
634  * @cliexpar
635  * @cliexstart{create mpls tunnel}
636  * create mpls tunnel via 10.0.0.1 GigEthernet0/8/0 out-label 33 out-label 34
637  * @cliexend
638  ?*/
639 VLIB_CLI_COMMAND (create_mpls_tunnel_command, static) = {
640  .path = "mpls tunnel",
641  .short_help =
642  "mpls tunnel via [addr] [interface] [out-labels]",
644 };
645 
646 static u8 *
647 format_mpls_tunnel (u8 * s, va_list * args)
648 {
649  mpls_tunnel_t *mt = va_arg (*args, mpls_tunnel_t *);
650  int ii;
651 
652  s = format(s, "mpls_tunnel%d: sw_if_index:%d hw_if_index:%d",
653  mt - mpls_tunnel_pool,
654  mt->mt_sw_if_index,
655  mt->mt_hw_if_index);
656  s = format(s, "\n label-stack:\n ");
657  for (ii = 0; ii < vec_len(mt->mt_label_stack); ii++)
658  {
659  s = format(s, "%d, ", mt->mt_label_stack[ii]);
660  }
661  s = format(s, "\n via:\n");
663  s = format(s, "\n");
664 
665  return (s);
666 }
667 
668 static clib_error_t *
670  unformat_input_t * input,
671  vlib_cli_command_t * cmd)
672 {
673  mpls_tunnel_t * mt;
674  u32 mti = ~0;
675 
676  if (pool_elts (mpls_tunnel_pool) == 0)
677  vlib_cli_output (vm, "No MPLS tunnels configured...");
678 
680  {
681  if (unformat (input, "%d", &mti))
682  ;
683  else
684  break;
685  }
686 
687  if (~0 == mti)
688  {
689  pool_foreach (mt, mpls_tunnel_pool,
690  ({
691  vlib_cli_output (vm, "[@%d] %U",
692  mt - mpls_tunnel_pool,
693  format_mpls_tunnel, mt);
694  }));
695  }
696  else
697  {
698  if (pool_is_free_index(mpls_tunnel_pool, mti))
699  return clib_error_return (0, "Not atunnel index %d", mti);
700 
701  mt = pool_elt_at_index(mpls_tunnel_pool, mti);
702 
703  vlib_cli_output (vm, "[@%d] %U",
704  mt - mpls_tunnel_pool,
705  format_mpls_tunnel, mt);
706  }
707 
708  return 0;
709 }
710 
711 /*?
712  * This command to show MPLS tunnels
713  *
714  * @cliexpar
715  * @cliexstart{sh mpls tunnel 2}
716  * [@2] mpls_tunnel2: sw_if_index:5 hw_if_index:5
717  * label-stack:
718  * 3,
719  * via:
720  * index:26 locks:1 proto:ipv4 uPRF-list:26 len:1 itfs:[2, ]
721  * index:26 pl-index:26 ipv4 weight=1 attached-nexthop: oper-flags:resolved,
722  * 10.0.0.2 loop0
723  * [@0]: ipv4 via 10.0.0.2 loop0: IP4: de:ad:00:00:00:00 -> 00:00:11:aa:bb:cc
724  * @cliexend
725  ?*/
726 VLIB_CLI_COMMAND (show_mpls_tunnel_command, static) = {
727  .path = "show mpls tunnel",
728  .function = show_mpls_tunnel_command_fn,
729 };
730 
731 static mpls_tunnel_t *
733 {
734 #if (CLIB_DEBUG > 0)
736 #endif
737  return ((mpls_tunnel_t*) (((char*)node) -
738  STRUCT_OFFSET_OF(mpls_tunnel_t, mt_node)));
739 }
740 
741 /**
742  * Function definition to backwalk a FIB node
743  */
747 {
749 
751 }
752 
753 /**
754  * Function definition to get a FIB node from its index
755  */
756 static fib_node_t*
758 {
759  mpls_tunnel_t * mt;
760 
761  mt = pool_elt_at_index(mpls_tunnel_pool, index);
762 
763  return (&mt->mt_node);
764 }
765 
766 /**
767  * Function definition to inform the FIB node that its last lock has gone.
768  */
769 static void
771 {
772  /*
773  * The MPLS MPLS tunnel is a root of the graph. As such
774  * it never has children and thus is never locked.
775  */
776  ASSERT(0);
777 }
778 
779 /*
780  * Virtual function table registered by MPLS MPLS tunnels
781  * for participation in the FIB object graph.
782  */
783 const static fib_node_vft_t mpls_vft = {
785  .fnv_last_lock = mpls_tunnel_last_lock_gone,
786  .fnv_back_walk = mpls_tunnel_back_walk,
787 };
788 
789 static clib_error_t *
791 {
793 
794  return 0;
795 }
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:436
u16 lb_n_buckets
number of buckets in the load-balance.
Definition: load_balance.h:88
static u8 * format_mpls_tunnel_tx_trace(u8 *s, va_list *args)
Definition: mpls_tunnel.c:314
vmrglw vmrglh hi
fib_protocol_t frp_proto
The protocol of the address below.
Definition: fib_types.h:313
Packet trace structure.
Definition: mpls_tunnel.c:305
ip46_address_t frp_addr
The next-hop address.
Definition: fib_types.h:322
Contribute an object that is to be used to forward IP6 packets.
Definition: fib_types.h:85
#define CLIB_UNUSED(x)
Definition: clib.h:79
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:530
void fib_path_list_child_remove(fib_node_index_t path_list_index, u32 si)
mpls_label_t * mt_label_stack
The Label stack to apply to egress packets.
Definition: mpls_tunnel.h:55
u8 runtime_data[0]
Function dependent node-runtime data.
Definition: node.h:463
A representation of a path as described by a route producer.
Definition: fib_types.h:308
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
fib_node_index_t mt_path_list
The path-list over which the tunnel&#39;s destination is reachable.
Definition: mpls_tunnel.h:45
void fib_node_init(fib_node_t *node, fib_node_type_t type)
Definition: fib_node.c:183
static uword vlib_node_add_named_next(vlib_main_t *vm, uword node, char *name)
Definition: node_funcs.h:1074
vnet_link_t adj_get_link_type(adj_index_t ai)
Return the link type of the adjacency.
Definition: adj.c:340
#define NULL
Definition: clib.h:55
IP unicast adjacency.
Definition: lookup.h:193
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function.
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:459
A uni-directional MPLS tunnel.
Definition: mpls_tunnel.h:24
u32 mpls_label_t
A label value only, i.e.
Definition: packet.h:24
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
fib_protocol_t fib_path_list_get_proto(fib_node_index_t path_list_index)
#define MPLS_IETF_IMPLICIT_NULL_LABEL
Definition: mpls_types.h:16
static clib_error_t * mpls_tunnel_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: mpls_tunnel.c:235
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:224
fib_node_t mt_node
The tunnel hooks into the FIB control plane graph.
Definition: mpls_tunnel.h:29
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:982
Contribute an object that is to be used to forward IP4 packets.
Definition: fib_types.h:81
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:62
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
unformat_function_t unformat_vnet_sw_interface
static uword mpls_tunnel_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
TX function.
Definition: mpls_tunnel.c:329
static u8 * format_mpls_tunnel_name(u8 *s, va_list *args)
Definition: mpls_tunnel.c:287
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:379
const mpls_tunnel_t * mpls_tunnel_get(u32 mti)
Definition: mpls_tunnel.c:410
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
u32 fib_path_list_child_add(fib_node_index_t path_list_index, fib_node_type_t child_type, fib_node_index_t child_index)
static u8 * format_mpls_tunnel_device(u8 *s, va_list *args)
Definition: mpls_tunnel.c:294
void(* mpls_tunnel_walk_cb_t)(u32 index, void *ctx)
Callback function invoked while walking MPLS tunnels.
Definition: mpls_tunnel.h:90
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
static fib_node_back_walk_rc_t mpls_tunnel_back_walk(fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
Function definition to backwalk a FIB node.
Definition: mpls_tunnel.c:745
unformat_function_t unformat_mpls_unicast_label
Definition: mpls.h:103
void fib_node_register_type(fib_node_type_t type, const fib_node_vft_t *vft)
fib_node_register_type
Definition: fib_node.c:58
void adj_nbr_midchain_update_rewrite(adj_index_t adj_index, adj_midchain_fixup_t fixup, adj_midchain_flag_t flags, u8 *rewrite)
adj_nbr_midchain_update_rewrite
Definition: adj_midchain.c:395
adj_index_t mt_l2_adj
If the tunnel is an L2 tunnel, this is the link type ETHERNET adjacency.
Definition: mpls_tunnel.h:35
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:128
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
unformat_function_t unformat_ip4_address
Definition: format.h:76
u32 frp_sw_if_index
The interface.
Definition: fib_types.h:334
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static u32 * mpls_tunnel_db
DB of SW index to tunnel index.
Definition: mpls_tunnel.c:38
enum adj_walk_rc_t_ adj_walk_rc_t
return codes from a adjacency walker callback function
VNET_HW_INTERFACE_CLASS(mpls_tunnel_hw_interface_class)
void fib_path_list_contribute_forwarding(fib_node_index_t path_list_index, fib_forward_chain_type_t fct, dpo_id_t *dpo)
#define clib_error_return(e, args...)
Definition: error.h:111
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:215
static u8 * format_mpls_tunnel(u8 *s, va_list *args)
Definition: mpls_tunnel.c:647
u32 vnet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u32 hw_class_index, u32 hw_instance)
Definition: interface.c:681
static void vnet_mpls_uc_set_label(mpls_label_t *label_exp_s_ttl, u32 value)
Definition: packet.h:97
static void mpls_tunnel_fixup(vlib_main_t *vm, ip_adjacency_t *adj, vlib_buffer_t *b0)
Fixup the adj rewrite post encap.
Definition: mpls_tunnel.c:265
unformat_function_t unformat_line_input
Definition: format.h:281
static void vnet_mpls_uc_set_exp(mpls_label_t *label_exp_s_ttl, u32 exp)
Definition: packet.h:104
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:146
void vnet_mpls_tunnel_del(u32 sw_if_index)
Definition: mpls_tunnel.c:431
#define ADJ_INDEX_INVALID
Invalid ADJ index - used when no adj is known likewise blazoned capitals INVALID speak volumes where ...
Definition: adj_types.h:36
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:397
fib_node_index_t fib_path_list_create(fib_path_list_flags_t flags, const fib_route_path_t *rpaths)
static uword vnet_hw_interface_get_flags(vnet_main_t *vnm, u32 hw_if_index)
dpo_type_t dpoi_type
the type
Definition: dpo.h:150
static const dpo_id_t * load_balance_get_bucket_i(const load_balance_t *lb, u32 bucket)
Definition: load_balance.h:202
u32 mt_l2_tx_arc
on a L2 tunnel this is the VLIB arc from the L2-tx to the l2-midchain
Definition: mpls_tunnel.h:40
struct _unformat_input_t unformat_input_t
load-balancing over a choice of [un]equal cost paths
Definition: dpo.h:104
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:374
#define FOR_EACH_FIB_PROTOCOL(_item)
Definition: fib_types.h:57
static mpls_tunnel_t * mpls_tunnel_get_from_sw_if_index(u32 sw_if_index)
Get a tunnel object from a SW interface index.
Definition: mpls_tunnel.c:44
The FIB DPO provieds;.
Definition: load_balance.h:84
#define PREDICT_FALSE(x)
Definition: clib.h:97
u32 mt_sibling_index
sibling index on the path-list so notifications are received.
Definition: mpls_tunnel.h:50
fib_node_type_t fn_type
The node&#39;s type.
Definition: fib_node.h:282
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:216
An node in the FIB graph.
Definition: fib_node.h:277
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:350
static adj_walk_rc_t mpls_adj_walk_cb(adj_index_t ai, void *ctx)
Call back when restacking all adjacencies on a MPLS interface.
Definition: mpls_tunnel.c:209
unformat_function_t unformat_ip6_address
Definition: format.h:94
u32 tunnel_id
Tunnel-id / index in tunnel vector.
Definition: mpls_tunnel.c:310
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
u16 n_vectors
Definition: node.h:344
vlib_main_t * vm
Definition: buffer.c:276
VNET_DEVICE_CLASS(mpls_tunnel_class)
#define MPLS_LABEL_INVALID
Definition: mpls_types.h:33
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
u32 frp_weight
[un]equal cost path weight
Definition: fib_types.h:343
static void mpls_tunnel_restack(mpls_tunnel_t *mt)
Definition: mpls_tunnel.c:218
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:85
fib_node_get_t fnv_get
Definition: fib_node.h:265
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:28
void mpls_tunnel_walk(mpls_tunnel_walk_cb_t cb, void *ctx)
Walk all the MPLS tunnels.
Definition: mpls_tunnel.c:419
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:238
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
void adj_nbr_walk(u32 sw_if_index, fib_protocol_t adj_nh_proto, adj_walk_cb_t cb, void *ctx)
Walk the neighbour Adjacencies on a given interface.
Definition: adj_nbr.c:569
static clib_error_t * mpls_tunnel_init(vlib_main_t *vm)
Definition: mpls_tunnel.c:790
Context passed between object during a back walk.
Definition: fib_node.h:190
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
static mpls_tunnel_t * mpls_tunnel_pool
pool of tunnel instances
Definition: mpls_tunnel.c:28
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:455
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:536
#define ASSERT(truth)
void adj_nbr_midchain_stack(adj_index_t adj_index, const dpo_id_t *next)
adj_nbr_midchain_stack
Definition: adj_midchain.c:483
unsigned int u32
Definition: types.h:88
void vnet_mpls_tunnel_add(fib_route_path_t *rpaths, mpls_label_t *label_stack, u8 l2_only, u32 *sw_if_index)
Create a new MPLS tunnel.
Definition: mpls_tunnel.c:453
enum vnet_link_t_ vnet_link_t
Link Type: A description of the protocol of packets on the link.
static load_balance_t * load_balance_get(index_t lbi)
Definition: load_balance.h:193
enum fib_forward_chain_type_t_ fib_forward_chain_type_t
FIB output chain type.
u32 mt_hw_if_index
The HW interface index of the tunnel interfaces.
Definition: mpls_tunnel.h:66
mpls_label_t label_exp_s_ttl
Definition: packet.h:31
void adj_nbr_midchain_unstack(adj_index_t adj_index)
adj_nbr_midchain_unstack
Definition: adj_midchain.c:460
static void vnet_mpls_uc_set_s(mpls_label_t *label_exp_s_ttl, u32 eos)
Definition: packet.h:111
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static u8 * mpls_tunnel_build_rewrite(vnet_main_t *vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address)
Build a rewrite string for the MPLS tunnel.
Definition: mpls_tunnel.c:93
u64 uword
Definition: types.h:112
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
Definition: defs.h:47
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:162
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static u32 * mpls_tunnel_free_hw_if_indices
Pool of free tunnel SW indices - i.e.
Definition: mpls_tunnel.c:33
unsigned char u8
Definition: types.h:56
static clib_error_t * vnet_create_mpls_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: mpls_tunnel.c:527
static void mpls_tunnel_stack(adj_index_t ai)
mpls_tunnel_stack
Definition: mpls_tunnel.c:152
u8 * fib_path_list_format(fib_node_index_t path_list_index, u8 *s)
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
struct mpls_tunnel_trace_t_ mpls_tunnel_trace_t
Packet trace structure.
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:173
a point 2 point interface
Definition: interface.h:274
static void mpls_tunnel_last_lock_gone(fib_node_t *node)
Function definition to inform the FIB node that its last lock has gone.
Definition: mpls_tunnel.c:770
A FIB graph nodes virtual function table.
Definition: fib_node.h:264
static void vnet_mpls_uc_set_ttl(mpls_label_t *label_exp_s_ttl, u32 ttl)
Definition: packet.h:118
#define vnet_buffer(b)
Definition: buffer.h:294
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
adj_index_t adj_nbr_add_or_lock(fib_protocol_t nh_proto, vnet_link_t link_type, const ip46_address_t *nh_addr, u32 sw_if_index)
Neighbour Adjacency sub-type.
Definition: adj_nbr.c:216
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:194
u32 mt_sw_if_index
The SW interface index of the tunnel interfaces.
Definition: mpls_tunnel.h:71
Contribute an object that is to be used to forward non-end-of-stack MPLS packets. ...
Definition: fib_types.h:90
static fib_node_t * mpls_tunnel_fib_node_get(fib_node_index_t index)
Function definition to get a FIB node from its index.
Definition: mpls_tunnel.c:757
#define pool_foreach_index(i, v, body)
Iterate pool by index.
Definition: pool.h:418
u32 flags
Definition: vhost-user.h:78
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:485
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:74
static fib_forward_chain_type_t mpls_tunnel_get_fwd_chain_type(const mpls_tunnel_t *mt)
Return true if the label stack is imp-null only.
Definition: mpls_tunnel.c:58
u32 frp_fib_index
The FIB index to lookup the nexthop Only valid for recursive paths.
Definition: fib_types.h:339
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:577
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
const ip46_address_t zero_addr
Definition: lookup.c:354
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:971
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
static clib_error_t * show_mpls_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: mpls_tunnel.c:669
static void mpls_tunnel_update_adj(vnet_main_t *vnm, u32 sw_if_index, adj_index_t ai)
Definition: mpls_tunnel.c:272
static mpls_tunnel_t * mpls_tunnel_from_fib_node(fib_node_t *node)
Definition: mpls_tunnel.c:732
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109