FD.io VPP  v17.04.2-2-ga8f93f8
Vector Packet Processing
mpls.c
Go to the documentation of this file.
1 /*
2  * mpls.c: mpls
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/mpls/mpls.h>
20 #include <vnet/fib/ip4_fib.h>
21 #include <vnet/fib/mpls_fib.h>
22 
23 const static char* mpls_eos_bit_names[] = MPLS_EOS_BITS;
24 
26 
27 u8 * format_mpls_unicast_label (u8 * s, va_list * args)
28 {
29  mpls_label_t label = va_arg (*args, mpls_label_t);
30 
31  switch (label) {
34  break;
37  break;
40  break;
43  break;
45  s = format (s, "%s", MPLS_IETF_ELI_STRING);
46  break;
48  s = format (s, "%s", MPLS_IETF_GAL_STRING);
49  break;
50  default:
51  s = format (s, "%d", label);
52  break;
53  }
54  return s;
55 }
56 
58 {
59  mpls_label_t *label = va_arg (*args, mpls_label_t*);
60 
65  else if (unformat (input, MPLS_IETF_ROUTER_ALERT_STRING))
67  else if (unformat (input, MPLS_IETF_IMPLICIT_NULL_STRING))
69  else if (unformat (input, "%d", label))
70  ;
71 
72  return (1);
73 }
74 
75 u8 * format_mpls_eos_bit (u8 * s, va_list * args)
76 {
77  mpls_eos_bit_t eb = va_arg (*args, mpls_eos_bit_t);
78 
79  ASSERT(eb <= MPLS_EOS);
80 
81  s = format(s, "%s", mpls_eos_bit_names[eb]);
82 
83  return (s);
84 }
85 
86 u8 * format_mpls_header (u8 * s, va_list * args)
87 {
88  mpls_unicast_header_t hdr = va_arg (*args, mpls_unicast_header_t);
89 
90  return (format(s, "[%U:%d:%d:%U]",
97 }
98 
99 uword
100 unformat_mpls_header (unformat_input_t * input, va_list * args)
101 {
102  u8 ** result = va_arg (*args, u8 **);
103  mpls_unicast_header_t _h, * h = &_h;
104  u32 label, label_exp_s_ttl;
105 
106  if (! unformat (input, "MPLS %d", &label))
107  return 0;
108 
109  label_exp_s_ttl = (label<<12) | (1<<8) /* s-bit */ | 0xFF;
110  h->label_exp_s_ttl = clib_host_to_net_u32 (label_exp_s_ttl);
111 
112  /* Add gre, mpls headers to result. */
113  {
114  void * p;
115  u32 h_n_bytes = sizeof (h[0]);
116 
117  vec_add2 (*result, p, h_n_bytes);
118  clib_memcpy (p, h, h_n_bytes);
119  }
120 
121  return 1;
122 }
123 
124 uword
126  va_list * args)
127 {
128  u32 * result = va_arg (*args, u32 *);
129  u32 label;
130 
131  if (!unformat (input, "MPLS: label %d", &label))
132  return 0;
133 
134  label = (label<<12) | (1<<8) /* s-bit set */ | 0xFF /* ttl */;
135 
136  *result = clib_host_to_net_u32 (label);
137  return 1;
138 }
139 
141 {
142  mpls_unicast_header_t *h = va_arg(*args, mpls_unicast_header_t *);
143  u32 label = h->label_exp_s_ttl;
144 
145  s = format (s, "label %d exp %d, s %d, ttl %d",
146  vnet_mpls_uc_get_label (label),
147  vnet_mpls_uc_get_exp (label),
148  vnet_mpls_uc_get_s (label),
149  vnet_mpls_uc_get_ttl (label));
150  return s;
151 }
152 
154 {
155  mpls_unicast_header_t *h = va_arg(*args, mpls_unicast_header_t *);
156  mpls_unicast_header_t h_host;
157 
158  h_host.label_exp_s_ttl = clib_net_to_host_u32 (h->label_exp_s_ttl);
159 
161  &h_host);
162 }
163 
164 typedef struct {
171 
172 int
173 mpls_dest_cmp(void * a1, void * a2)
174 {
175  show_mpls_fib_t * r1 = a1;
176  show_mpls_fib_t * r2 = a2;
177 
178  return clib_net_to_host_u32(r1->dest) - clib_net_to_host_u32(r2->dest);
179 }
180 
181 int
182 mpls_fib_index_cmp(void * a1, void * a2)
183 {
184  show_mpls_fib_t * r1 = a1;
185  show_mpls_fib_t * r2 = a2;
186 
187  return r1->fib_index - r2->fib_index;
188 }
189 
190 int
191 mpls_label_cmp(void * a1, void * a2)
192 {
193  show_mpls_fib_t * r1 = a1;
194  show_mpls_fib_t * r2 = a2;
195 
196  return r1->label - r2->label;
197 }
198 
199 static clib_error_t *
201  unformat_input_t * input,
202  vlib_cli_command_t * cmd)
203 {
204  unformat_input_t _line_input, * line_input = &_line_input;
205  fib_route_path_t *rpaths = NULL, rpath;
206  u32 table_id, is_del, is_ip;
207  mpls_label_t local_label;
208  mpls_label_t out_label;
209  clib_error_t * error;
210  mpls_eos_bit_t eos;
211  vnet_main_t * vnm;
212  fib_prefix_t pfx;
213 
214  vnm = vnet_get_main();
215  error = NULL;
216  is_ip = 0;
217  table_id = 0;
218  eos = MPLS_EOS;
219  is_del = 0;
220  local_label = MPLS_LABEL_INVALID;
221  memset(&pfx, 0, sizeof(pfx));
222 
223  /* Get a line of input. */
224  if (! unformat_user (input, unformat_line_input, line_input))
225  return 0;
226 
227  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
228  {
229  memset(&rpath, 0, sizeof(rpath));
230 
231  if (unformat (line_input, "table %d", &table_id))
232  ;
233  else if (unformat (line_input, "del"))
234  is_del = 1;
235  else if (unformat (line_input, "add"))
236  is_del = 0;
237  else if (unformat (line_input, "eos"))
238  pfx.fp_eos = MPLS_EOS;
239  else if (unformat (line_input, "non-eos"))
240  pfx.fp_eos = MPLS_NON_EOS;
241  else if (unformat (line_input, "%U/%d",
243  &pfx.fp_addr.ip4,
244  &pfx.fp_len))
245  {
247  is_ip = 1;
248  }
249  else if (unformat (line_input, "%U/%d",
251  &pfx.fp_addr.ip6,
252  &pfx.fp_len))
253  {
255  is_ip = 1;
256  }
257  else if (unformat (line_input, "via %U %U weight %u",
259  &rpath.frp_addr.ip4,
261  &rpath.frp_sw_if_index,
262  &rpath.frp_weight))
263  {
264  rpath.frp_proto = FIB_PROTOCOL_IP4;
265  vec_add1(rpaths, rpath);
266  }
267 
268  else if (unformat (line_input, "via %U %U weight %u",
270  &rpath.frp_addr.ip6,
272  &rpath.frp_sw_if_index,
273  &rpath.frp_weight))
274  {
275  rpath.frp_proto = FIB_PROTOCOL_IP6;
276  vec_add1(rpaths, rpath);
277  }
278 
279  else if (unformat (line_input, "via %U %U",
281  &rpath.frp_addr.ip4,
283  &rpath.frp_sw_if_index))
284  {
285  rpath.frp_weight = 1;
286  rpath.frp_proto = FIB_PROTOCOL_IP4;
287  vec_add1(rpaths, rpath);
288  }
289 
290  else if (unformat (line_input, "via %U %U",
292  &rpath.frp_addr.ip6,
294  &rpath.frp_sw_if_index))
295  {
296  rpath.frp_weight = 1;
297  rpath.frp_proto = FIB_PROTOCOL_IP6;
298  vec_add1(rpaths, rpath);
299  }
300  else if (unformat (line_input, "via %U next-hop-table %d",
302  &rpath.frp_addr.ip4,
303  &rpath.frp_fib_index))
304  {
305  rpath.frp_weight = 1;
306  rpath.frp_sw_if_index = ~0;
307  rpath.frp_proto = FIB_PROTOCOL_IP4;
308  vec_add1(rpaths, rpath);
309  }
310  else if (unformat (line_input, "via %U next-hop-table %d",
312  &rpath.frp_addr.ip6,
313  &rpath.frp_fib_index))
314  {
315  rpath.frp_weight = 1;
316  rpath.frp_sw_if_index = ~0;
317  rpath.frp_proto = FIB_PROTOCOL_IP6;
318  vec_add1(rpaths, rpath);
319  }
320  else if (unformat (line_input, "via %U",
322  &rpath.frp_addr.ip4))
323  {
324  /*
325  * the recursive next-hops are by default in the same table
326  * as the prefix
327  */
328  rpath.frp_fib_index = table_id;
329  rpath.frp_weight = 1;
330  rpath.frp_sw_if_index = ~0;
331  rpath.frp_proto = FIB_PROTOCOL_IP4;
332  vec_add1(rpaths, rpath);
333  }
334  else if (unformat (line_input, "via %U",
336  &rpath.frp_addr.ip6))
337  {
338  rpath.frp_fib_index = table_id;
339  rpath.frp_weight = 1;
340  rpath.frp_sw_if_index = ~0;
341  rpath.frp_proto = FIB_PROTOCOL_IP6;
342  vec_add1(rpaths, rpath);
343  }
344  else if (unformat (line_input, "%d", &local_label))
345  ;
346  else if (unformat (line_input,
347  "ip4-lookup-in-table %d",
348  &rpath.frp_fib_index))
349  {
350  rpath.frp_proto = FIB_PROTOCOL_IP4;
351  rpath.frp_sw_if_index = FIB_NODE_INDEX_INVALID;
353  vec_add1(rpaths, rpath);
354  }
355  else if (unformat (line_input,
356  "ip6-lookup-in-table %d",
357  &rpath.frp_fib_index))
358  {
359  rpath.frp_proto = FIB_PROTOCOL_IP6;
360  rpath.frp_sw_if_index = FIB_NODE_INDEX_INVALID;
361  vec_add1(rpaths, rpath);
363  }
364  else if (unformat (line_input,
365  "mpls-lookup-in-table %d",
366  &rpath.frp_fib_index))
367  {
368  rpath.frp_proto = FIB_PROTOCOL_MPLS;
369  rpath.frp_sw_if_index = FIB_NODE_INDEX_INVALID;
371  vec_add1(rpaths, rpath);
372  }
373  else if (unformat (line_input, "out-label %U",
375  &out_label))
376  {
377  if (vec_len(rpaths) == 0)
378  {
379  error = clib_error_return(0 , "Paths then labels");
380  goto done;
381  }
382  vec_add1(rpaths[vec_len(rpaths)-1].frp_label_stack, out_label);
383  }
384  else
385  {
386  error = clib_error_return (0, "unkown input: %U",
387  format_unformat_error, line_input);
388  goto done;
389  }
390 
391  }
392 
393  if (MPLS_LABEL_INVALID == local_label)
394  {
395  error = clib_error_return (0, "local-label required: %U",
396  format_unformat_error, input);
397  goto done;
398  }
399 
400 
401  if (is_ip)
402  {
403  u32 fib_index = fib_table_find(pfx.fp_proto, table_id);
404 
405  if (FIB_NODE_INDEX_INVALID == fib_index)
406  {
407  error = clib_error_return (0, "%U table-id %d does not exist",
408  format_fib_protocol, pfx.fp_proto, table_id);
409  goto done;
410  }
411 
412  if (is_del)
413  {
414  fib_table_entry_local_label_remove(fib_index, &pfx, local_label);
415  }
416  else
417  {
418  fib_table_entry_local_label_add(fib_index, &pfx, local_label);
419  }
420  }
421  else
422  {
423  fib_node_index_t lfe, fib_index;
424  u32 fi;
425 
426  if (NULL == rpaths)
427  {
428  error = clib_error_return(0 , "no paths");
429  goto done;
430  }
431 
433  pfx.fp_len = 21;
434  pfx.fp_label = local_label;
435  pfx.fp_payload_proto = fib_proto_to_dpo(rpaths[0].frp_proto);
436 
437  /*
438  * the CLI parsing stored table Ids, swap to FIB indicies
439  */
440  if (FIB_NODE_INDEX_INVALID == rpath.frp_sw_if_index)
441  {
443  rpaths[0].frp_fib_index);
444 
445  if (~0 == fi)
446  {
447  error = clib_error_return(0 , "%U Via table %d does not exist",
449  rpaths[0].frp_fib_index);
450  goto done;
451  }
452  rpaths[0].frp_fib_index = fi;
453  }
454 
455  fib_index = mpls_fib_index_from_table_id(table_id);
456 
457  if (FIB_NODE_INDEX_INVALID == fib_index)
458  {
459  error = clib_error_return (0, "MPLS table-id %d does not exist",
460  table_id);
461  goto done;
462  }
463 
464  lfe = fib_table_entry_path_add2(fib_index,
465  &pfx,
468  rpaths);
469 
470  if (FIB_NODE_INDEX_INVALID == lfe)
471  {
472  error = clib_error_return (0, "Failed to create %U-%U in MPLS table-id %d",
473  format_mpls_unicast_label, local_label,
474  format_mpls_eos_bit, eos,
475  table_id);
476  goto done;
477  }
478  }
479 
480 done:
481  unformat_free (line_input);
482 
483  return error;
484 }
485 
486 VLIB_CLI_COMMAND (mpls_local_label_command, static) = {
487  .path = "mpls local-label",
488  .function = vnet_mpls_local_label,
489  .short_help = "Create/Delete MPL local labels",
490 };
491 
492 int
494 {
495  // FIXME
496  return 0;
497 }
498 
499 static clib_error_t *
501 {
502  mpls_main_t * mm = &mpls_main;
503  clib_error_t * error;
504 
505  mm->vlib_main = vm;
506  mm->vnet_main = vnet_get_main();
507 
508  if ((error = vlib_call_init_function (vm, ip_main_init)))
509  return error;
510 
512 }
513 
515 
517 {
519  return &mpls_main;
520 }
521 
u32 fib_table_id_find_fib_index(fib_protocol_t proto, u32 table_id)
Definition: lookup.c:360
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:169
uword unformat_mpls_unicast_label(unformat_input_t *input, va_list *args)
Definition: mpls.c:57
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
#define NULL
Definition: clib.h:55
fib_node_index_t fib_table_entry_path_add2(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, fib_route_path_t *rpath)
Add n paths to an entry (aka route) in the FIB.
Definition: fib_table.c:511
u32 mpls_label_t
A label value only, i.e.
Definition: packet.h:24
#define MPLS_IETF_IMPLICIT_NULL_LABEL
Definition: mpls_types.h:16
From the CLI.
Definition: fib_entry.h:62
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
#define MPLS_IETF_ROUTER_ALERT_LABEL
Definition: mpls_types.h:14
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:561
u8 * format_mpls_unicast_label(u8 *s, va_list *args)
Definition: mpls.c:27
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:982
u8 * format_mpls_unicast_header_host_byte_order(u8 *s, va_list *args)
Definition: mpls.c:140
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
unformat_function_t unformat_vnet_sw_interface
int mpls_dest_cmp(void *a1, void *a2)
Definition: mpls.c:173
void fib_table_entry_local_label_remove(u32 fib_index, const fib_prefix_t *prefix, mpls_label_t label)
remove a MPLS local label for the prefix/route.
Definition: fib_table.c:860
dpo_proto_t fp_payload_proto
This protocol determines the payload protocol of packets that will be forwarded by this entry once th...
Definition: fib_types.h:193
unformat_function_t unformat_ip4_address
Definition: format.h:76
#define MPLS_IETF_ROUTER_ALERT_STRING
Definition: mpls_types.h:24
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
int mpls_fib_reset_labels(u32 fib_id)
Definition: mpls.c:493
Aggregrate type for a prefix.
Definition: fib_types.h:160
#define clib_error_return(e, args...)
Definition: error.h:111
static const char * mpls_eos_bit_names[]
Definition: mpls.c:23
static u32 vnet_mpls_uc_get_ttl(mpls_label_t label_exp_s_ttl)
Definition: packet.h:92
#define MPLS_EOS_BITS
Definition: packet.h:40
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:938
fib_protocol_t dpo_proto_to_fib(dpo_proto_t dpo_proto)
Definition: fib_types.c:236
u16 fp_len
The mask length.
Definition: fib_types.h:164
#define vlib_call_init_function(vm, x)
Definition: init.h:162
Definition: fib_entry.h:227
unformat_function_t unformat_line_input
Definition: format.h:281
#define MPLS_IETF_GAL_STRING
Definition: mpls_types.h:30
#define MPLS_IETF_ELI_LABEL
Definition: mpls_types.h:17
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:183
u32 entry_index
Definition: mpls.c:166
struct _unformat_input_t unformat_input_t
static u32 vnet_mpls_uc_get_label(mpls_label_t label_exp_s_ttl)
Definition: packet.h:77
vnet_main_t * vnet_main
Definition: mpls.h:82
uword unformat_mpls_header(unformat_input_t *input, va_list *args)
Definition: mpls.c:100
#define MPLS_IETF_IPV4_EXPLICIT_NULL_STRING
Definition: mpls_types.h:20
unformat_function_t unformat_ip6_address
Definition: format.h:94
clib_error_t * ip_main_init(vlib_main_t *vm)
Definition: ip_init.c:45
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
fib_node_index_t fib_table_entry_local_label_add(u32 fib_index, const fib_prefix_t *prefix, mpls_label_t label)
Add a MPLS local label for the prefix/route.
Definition: fib_table.c:833
mpls_main_t mpls_main
Definition: mpls.c:25
vlib_main_t * vm
Definition: buffer.c:276
vec_header_t h
Definition: buffer.c:275
#define MPLS_LABEL_INVALID
Definition: mpls_types.h:33
#define MPLS_IETF_IPV4_EXPLICIT_NULL_LABEL
Definition: mpls_types.h:13
#define clib_memcpy(a, b, c)
Definition: string.h:69
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:28
u32 mpls_fib_index_from_table_id(u32 table_id)
Definition: mpls_fib.c:78
mpls_label_t fp_label
Definition: fib_types.h:186
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
static clib_error_t * mpls_input_init(vlib_main_t *vm)
Definition: mpls_input.c:298
u32 fib_index
Definition: mpls.c:165
#define MPLS_IETF_IPV6_EXPLICIT_NULL_STRING
Definition: mpls_types.h:26
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
static clib_error_t * vnet_mpls_local_label(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: mpls.c:200
#define MPLS_IETF_GAL_LABEL
Definition: mpls_types.h:18
uword unformat_mpls_label_net_byte_order(unformat_input_t *input, va_list *args)
Definition: mpls.c:125
#define MPLS_IETF_ELI_STRING
Definition: mpls_types.h:28
mpls_label_t label_exp_s_ttl
Definition: packet.h:31
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:220
#define MPLS_IETF_IMPLICIT_NULL_STRING
Definition: mpls_types.h:22
u8 * format_fib_protocol(u8 *s, va_list ap)
Definition: fib_types.c:30
u64 uword
Definition: types.h:112
static clib_error_t * mpls_init(vlib_main_t *vm)
Definition: mpls.c:500
u8 * format_mpls_unicast_header_net_byte_order(u8 *s, va_list *args)
Definition: mpls.c:153
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:29
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static u32 vnet_mpls_uc_get_s(mpls_label_t label_exp_s_ttl)
Definition: packet.h:87
unsigned char u8
Definition: types.h:56
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
#define MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL
Definition: mpls_types.h:15
u8 * format_dpo_proto(u8 *s, va_list *args)
format a DPO protocol
Definition: dpo.c:149
vlib_main_t * vlib_main
Definition: mpls.h:81
u8 * format_mpls_eos_bit(u8 *s, va_list *args)
Definition: mpls.c:75
mpls_main_t * mpls_get_main(vlib_main_t *vm)
Definition: mpls.c:516
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
int mpls_label_cmp(void *a1, void *a2)
Definition: mpls.c:191
static u32 vnet_mpls_uc_get_exp(mpls_label_t label_exp_s_ttl)
Definition: packet.h:82
u32 frp_fib_index
The FIB index to lookup the nexthop Only valid for recursive paths.
Definition: fib_types.h:339
int mpls_fib_index_cmp(void *a1, void *a2)
Definition: mpls.c:182
u8 * format_mpls_header(u8 *s, va_list *args)
Definition: mpls.c:86
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
mpls_eos_bit_t fp_eos
Definition: fib_types.h:187
enum mpls_eos_bit_t_ mpls_eos_bit_t