FD.io VPP  v18.07-rc0-415-g6c78436
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  case MPLS_LABEL_POP:
51  s = format (s, "pop");
52  break;
53  default:
54  s = format (s, "%d", label);
55  break;
56  }
57  return s;
58 }
59 
61 {
62  mpls_label_t *label = va_arg (*args, mpls_label_t*);
63 
68  else if (unformat (input, MPLS_IETF_ROUTER_ALERT_STRING))
70  else if (unformat (input, MPLS_IETF_IMPLICIT_NULL_STRING))
80  else if (unformat (input, "%d", label))
81  ;
82  else
83  return (0);
84 
85  return (1);
86 }
87 
88 u8 * format_mpls_eos_bit (u8 * s, va_list * args)
89 {
90  mpls_eos_bit_t eb = va_arg (*args, mpls_eos_bit_t);
91 
92  ASSERT(eb <= MPLS_EOS);
93 
94  s = format(s, "%s", mpls_eos_bit_names[eb]);
95 
96  return (s);
97 }
98 
99 u8 * format_mpls_header (u8 * s, va_list * args)
100 {
101  mpls_unicast_header_t hdr = va_arg (*args, mpls_unicast_header_t);
102 
103  return (format(s, "[%U:%d:%d:%U]",
110 }
111 
112 uword
113 unformat_mpls_header (unformat_input_t * input, va_list * args)
114 {
115  u8 ** result = va_arg (*args, u8 **);
116  mpls_unicast_header_t _h, * h = &_h;
117  u32 label, label_exp_s_ttl;
118 
119  if (! unformat (input, "MPLS %d", &label))
120  return 0;
121 
122  label_exp_s_ttl = (label<<12) | (1<<8) /* s-bit */ | 0xFF;
123  h->label_exp_s_ttl = clib_host_to_net_u32 (label_exp_s_ttl);
124 
125  /* Add gre, mpls headers to result. */
126  {
127  void * p;
128  u32 h_n_bytes = sizeof (h[0]);
129 
130  vec_add2 (*result, p, h_n_bytes);
131  clib_memcpy (p, h, h_n_bytes);
132  }
133 
134  return 1;
135 }
136 
137 uword
139  va_list * args)
140 {
141  u32 * result = va_arg (*args, u32 *);
142  u32 label;
143 
144  if (!unformat (input, "MPLS: label %d", &label))
145  return 0;
146 
147  label = (label<<12) | (1<<8) /* s-bit set */ | 0xFF /* ttl */;
148 
149  *result = clib_host_to_net_u32 (label);
150  return 1;
151 }
152 
154 {
155  mpls_unicast_header_t *h = va_arg(*args, mpls_unicast_header_t *);
156  u32 label = h->label_exp_s_ttl;
157 
158  s = format (s, "label %d exp %d, s %d, ttl %d",
159  vnet_mpls_uc_get_label (label),
160  vnet_mpls_uc_get_exp (label),
161  vnet_mpls_uc_get_s (label),
162  vnet_mpls_uc_get_ttl (label));
163  return s;
164 }
165 
167 {
168  mpls_unicast_header_t *h = va_arg(*args, mpls_unicast_header_t *);
169  mpls_unicast_header_t h_host;
170 
171  h_host.label_exp_s_ttl = clib_net_to_host_u32 (h->label_exp_s_ttl);
172 
174  &h_host);
175 }
176 
177 typedef struct {
184 
185 int
186 mpls_dest_cmp(void * a1, void * a2)
187 {
188  show_mpls_fib_t * r1 = a1;
189  show_mpls_fib_t * r2 = a2;
190 
191  return clib_net_to_host_u32(r1->dest) - clib_net_to_host_u32(r2->dest);
192 }
193 
194 int
195 mpls_fib_index_cmp(void * a1, void * a2)
196 {
197  show_mpls_fib_t * r1 = a1;
198  show_mpls_fib_t * r2 = a2;
199 
200  return r1->fib_index - r2->fib_index;
201 }
202 
203 int
204 mpls_label_cmp(void * a1, void * a2)
205 {
206  show_mpls_fib_t * r1 = a1;
207  show_mpls_fib_t * r2 = a2;
208 
209  return r1->label - r2->label;
210 }
211 
212 static clib_error_t *
214  unformat_input_t * input,
215  vlib_cli_command_t * cmd)
216 {
217  unformat_input_t _line_input, * line_input = &_line_input;
218  u32 table_id, is_del, is_ip, payload_proto;
219  fib_route_path_t *rpaths = NULL, rpath;
220  mpls_label_t local_label;
221  clib_error_t * error;
222  mpls_eos_bit_t eos;
223  fib_prefix_t pfx;
224 
225  error = NULL;
226  is_ip = 0;
227  table_id = 0;
228  eos = MPLS_EOS;
229  is_del = 0;
230  local_label = MPLS_LABEL_INVALID;
231  memset(&pfx, 0, sizeof(pfx));
232  payload_proto = DPO_PROTO_MPLS;
233 
234  /* Get a line of input. */
235  if (! unformat_user (input, unformat_line_input, line_input))
236  return 0;
237 
238  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
239  {
240  if (unformat (line_input, "table %d", &table_id))
241  ;
242  else if (unformat (line_input, "del"))
243  is_del = 1;
244  else if (unformat (line_input, "add"))
245  is_del = 0;
246  else if (unformat (line_input, "eos"))
247  pfx.fp_eos = MPLS_EOS;
248  else if (unformat (line_input, "non-eos"))
249  pfx.fp_eos = MPLS_NON_EOS;
250  else if (unformat (line_input, "%U/%d",
252  &pfx.fp_addr.ip4,
253  &pfx.fp_len))
254  {
256  is_ip = 1;
257  }
258  else if (unformat (line_input, "%U/%d",
260  &pfx.fp_addr.ip6,
261  &pfx.fp_len))
262  {
264  is_ip = 1;
265  }
266  else if (unformat (line_input, "via %U",
268  &rpath, &payload_proto))
269  {
270  pfx.fp_payload_proto = payload_proto;
271  vec_add1(rpaths, rpath);
272  }
273  else if (unformat (line_input, "%d", &local_label))
274  ;
275  else
276  {
277  error = clib_error_return (0, "unknown input: %U",
278  format_unformat_error, line_input);
279  goto done;
280  }
281 
282  }
283 
284  if (MPLS_LABEL_INVALID == local_label)
285  {
286  error = clib_error_return (0, "local-label required: %U",
287  format_unformat_error, input);
288  goto done;
289  }
290 
291 
292  if (is_ip)
293  {
294  u32 fib_index = fib_table_find(pfx.fp_proto, table_id);
295 
296  if (FIB_NODE_INDEX_INVALID == fib_index)
297  {
298  error = clib_error_return (0, "%U table-id %d does not exist",
299  format_fib_protocol, pfx.fp_proto, table_id);
300  goto done;
301  }
302 
303  if (is_del)
304  {
305  fib_table_entry_local_label_remove(fib_index, &pfx, local_label);
306  }
307  else
308  {
309  fib_table_entry_local_label_add(fib_index, &pfx, local_label);
310  }
311  }
312  else
313  {
314  fib_node_index_t fib_index;
315  u32 fi;
316 
317  if (NULL == rpaths)
318  {
319  error = clib_error_return(0 , "no paths");
320  goto done;
321  }
322 
324  pfx.fp_len = 21;
325  pfx.fp_label = local_label;
326  pfx.fp_payload_proto = rpaths[0].frp_proto;
327 
328  /*
329  * the CLI parsing stored table Ids, swap to FIB indicies
330  */
331  if (FIB_NODE_INDEX_INVALID == rpath.frp_sw_if_index)
332  {
334  rpaths[0].frp_fib_index);
335 
336  if (~0 == fi)
337  {
338  error = clib_error_return(0 , "%U Via table %d does not exist",
340  rpaths[0].frp_fib_index);
341  goto done;
342  }
343  rpaths[0].frp_fib_index = fi;
344  }
345 
346  fib_index = mpls_fib_index_from_table_id(table_id);
347 
348  if (FIB_NODE_INDEX_INVALID == fib_index)
349  {
350  error = clib_error_return (0, "MPLS table-id %d does not exist",
351  table_id);
352  goto done;
353  }
354 
355  if (is_del)
356  {
358  &pfx,
360  rpaths);
361  }
362  else
363  {
364  fib_node_index_t lfe;
365 
366  lfe = fib_table_entry_path_add2(fib_index,
367  &pfx,
370  rpaths);
371 
372  if (FIB_NODE_INDEX_INVALID == lfe)
373  {
374  error = clib_error_return (0, "Failed to create %U-%U in MPLS table-id %d",
375  format_mpls_unicast_label, local_label,
376  format_mpls_eos_bit, eos,
377  table_id);
378  goto done;
379  }
380  }
381  }
382 
383 done:
384  unformat_free (line_input);
385 
386  return error;
387 }
388 
389 VLIB_CLI_COMMAND (mpls_local_label_command, static) = {
390  .path = "mpls local-label",
391  .function = vnet_mpls_local_label,
392  .short_help = "mpls local-label [add|del] <label-value> [eos|non-eos] via [next-hop-address] [next-hop-interface] [next-hop-table <value>] [weight <value>] [preference <value>] [udp-encap-id <value>] [ip4-lookup-in-table <value>] [ip6-lookup-in-table <value>] [mpls-lookup-in-table <value>] [resolve-via-host] [resolve-via-attached] [rx-ip4 <interface>] [out-labels <value value value>]",
393 };
394 
395 clib_error_t *
397  unformat_input_t * main_input,
398  vlib_cli_command_t * cmdo)
399 {
400  unformat_input_t _line_input, *line_input = &_line_input;
401  clib_error_t *error = NULL;
402  u32 table_id, is_add;
403  u8 *name = NULL;
404 
405  is_add = 1;
406  table_id = ~0;
407 
408  /* Get a line of input. */
409  if (!unformat_user (main_input, unformat_line_input, line_input))
410  return 0;
411 
412  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
413  {
414  if (unformat (line_input, "%d", &table_id))
415  ;
416  else if (unformat (line_input, "del"))
417  is_add = 0;
418  else if (unformat (line_input, "add"))
419  is_add = 1;
420  else if (unformat (line_input, "name %s", &name))
421  ;
422  else
423  {
424  error = unformat_parse_error (line_input);
425  goto done;
426  }
427  }
428 
429  if (~0 == table_id)
430  {
431  error = clib_error_return (0, "No table id");
432  goto done;
433  }
434  else
435  {
436  if (is_add)
437  {
438  mpls_table_create (table_id, 0, name);
439  }
440  else
441  {
442  mpls_table_delete (table_id, 0);
443  }
444  }
445 
446  done:
447  unformat_free (line_input);
448  return error;
449 }
450 
451 /* *INDENT-ON* */
452 /*?
453  * This command is used to add or delete MPLS Tables. All
454  * Tables must be explicitly added before that can be used,
455  * Including the default table.
456  ?*/
457 /* *INDENT-OFF* */
458 VLIB_CLI_COMMAND (mpls_table_command, static) = {
459  .path = "mpls table",
460  .short_help = "mpls table [add|del] <table-id>",
461  .function = vnet_mpls_table_cmd,
462  .is_mp_safe = 1,
463 };
464 
465 int
467 {
468  // FIXME
469  return 0;
470 }
471 
472 static clib_error_t *
474 {
475  clib_error_t * error;
476 
477  if ((error = vlib_call_init_function (vm, ip_main_init)))
478  return error;
479 
481 }
482 
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:197
uword unformat_mpls_unicast_label(unformat_input_t *input, va_list *args)
Definition: mpls.c:60
A representation of a path as described by a route producer.
Definition: fib_types.h:455
uword unformat_fib_route_path(unformat_input_t *input, va_list *args)
Unformat a fib_route_path_t from CLI input.
Definition: fib_types.c:383
#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:556
u32 mpls_label_t
A label value only, i.e.
Definition: packet.h:24
#define MPLS_IETF_IMPLICIT_NULL_LABEL
Definition: mpls_types.h:30
From the CLI.
Definition: fib_entry.h:74
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:523
#define MPLS_IETF_ROUTER_ALERT_LABEL
Definition: mpls_types.h:28
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:562
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:983
u8 * format_mpls_unicast_header_host_byte_order(u8 *s, va_list *args)
Definition: mpls.c:153
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
dpo_proto_t frp_proto
The protocol of the address below.
Definition: fib_types.h:460
int mpls_dest_cmp(void *a1, void *a2)
Definition: mpls.c:186
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:916
#define MPLS_IETF_IPV4_EXPLICIT_NULL_BRIEF_STRING
Definition: mpls_types.h:36
unsigned char u8
Definition: types.h:56
u8 * format_fib_protocol(u8 *s, va_list *ap)
Definition: fib_types.c:31
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:221
unformat_function_t unformat_ip4_address
Definition: format.h:76
#define MPLS_IETF_ROUTER_ALERT_STRING
Definition: mpls_types.h:39
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:156
int mpls_fib_reset_labels(u32 fib_id)
Definition: mpls.c:466
Aggregrate type for a prefix.
Definition: fib_types.h:188
#define clib_error_return(e, args...)
Definition: error.h:99
static const char * mpls_eos_bit_names[]
Definition: mpls.c:23
unsigned int u32
Definition: types.h:88
#define MPLS_IETF_ROUTER_ALERT_BRIEF_STRING
Definition: mpls_types.h:40
static u32 vnet_mpls_uc_get_ttl(mpls_label_t label_exp_s_ttl)
Definition: packet.h:118
#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:1056
fib_protocol_t dpo_proto_to_fib(dpo_proto_t dpo_proto)
Definition: fib_types.c:252
u16 fp_len
The mask length.
Definition: fib_types.h:192
#define vlib_call_init_function(vm, x)
Definition: init.h:227
#define MPLS_IETF_IPV6_EXPLICIT_NULL_BRIEF_STRING
Definition: mpls_types.h:42
Definition: fib_entry.h:270
unformat_function_t unformat_line_input
Definition: format.h:281
#define MPLS_IETF_GAL_STRING
Definition: mpls_types.h:45
void mpls_table_delete(u32 table_id, u8 is_api)
Definition: mpls_api.c:63
#define MPLS_IETF_ELI_LABEL
Definition: mpls_types.h:31
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:211
u32 entry_index
Definition: mpls.c:179
struct _unformat_input_t unformat_input_t
clib_error_t * vnet_mpls_table_cmd(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmdo)
Definition: mpls.c:396
void fib_table_entry_path_remove2(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_route_path_t *rpath)
Remove n paths to an entry (aka route) in the FIB.
Definition: fib_table.c:600
static u32 vnet_mpls_uc_get_label(mpls_label_t label_exp_s_ttl)
Definition: packet.h:103
uword unformat_mpls_header(unformat_input_t *input, va_list *args)
Definition: mpls.c:113
#define MPLS_IETF_IPV4_EXPLICIT_NULL_STRING
Definition: mpls_types.h:35
unformat_function_t unformat_ip6_address
Definition: format.h:97
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:889
mpls_main_t mpls_main
Definition: mpls.c:25
vlib_main_t * vm
Definition: buffer.c:294
#define MPLS_LABEL_INVALID
Definition: mpls_types.h:48
#define MPLS_IETF_IPV4_EXPLICIT_NULL_LABEL
Definition: mpls_types.h:27
#define clib_memcpy(a, b, c)
Definition: string.h:75
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
#define MPLS_IETF_IMPLICIT_NULL_BRIEF_STRING
Definition: mpls_types.h:38
u32 mpls_fib_index_from_table_id(u32 table_id)
Definition: mpls_fib.c:73
mpls_label_t fp_label
Definition: fib_types.h:214
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
static clib_error_t * mpls_input_init(vlib_main_t *vm)
Definition: mpls_input.c:284
u32 fib_index
Definition: mpls.c:178
#define MPLS_IETF_IPV6_EXPLICIT_NULL_STRING
Definition: mpls_types.h:41
#define ASSERT(truth)
static clib_error_t * vnet_mpls_local_label(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: mpls.c:213
#define MPLS_IETF_GAL_LABEL
Definition: mpls_types.h:32
void mpls_table_create(u32 table_id, u8 is_api, const u8 *name)
Definition: mpls_api.c:275
uword unformat_mpls_label_net_byte_order(unformat_input_t *input, va_list *args)
Definition: mpls.c:138
#define MPLS_IETF_ELI_STRING
Definition: mpls_types.h:43
mpls_label_t label_exp_s_ttl
Definition: packet.h:31
#define MPLS_LABEL_POP
A value that is explicit about the end of the LSP.
Definition: mpls_types.h:56
#define MPLS_IETF_IMPLICIT_NULL_STRING
Definition: mpls_types.h:37
static clib_error_t * mpls_init(vlib_main_t *vm)
Definition: mpls.c:473
#define unformat_parse_error(input)
Definition: format.h:267
u8 * format_mpls_unicast_header_net_byte_order(u8 *s, va_list *args)
Definition: mpls.c:166
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:31
static u32 vnet_mpls_uc_get_s(mpls_label_t label_exp_s_ttl)
Definition: packet.h:113
u64 uword
Definition: types.h:112
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
#define MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL
Definition: mpls_types.h:29
u8 * format_dpo_proto(u8 *s, va_list *args)
format a DPO protocol
Definition: dpo.c:177
u8 * format_mpls_eos_bit(u8 *s, va_list *args)
Definition: mpls.c:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
int mpls_label_cmp(void *a1, void *a2)
Definition: mpls.c:204
static u32 vnet_mpls_uc_get_exp(mpls_label_t label_exp_s_ttl)
Definition: packet.h:108
u32 frp_fib_index
The FIB index to lookup the nexthop Only valid for recursive paths.
Definition: fib_types.h:501
int mpls_fib_index_cmp(void *a1, void *a2)
Definition: mpls.c:195
u8 * format_mpls_header(u8 *s, va_list *args)
Definition: mpls.c:99
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
mpls_eos_bit_t fp_eos
Definition: fib_types.h:215
enum mpls_eos_bit_t_ mpls_eos_bit_t