FD.io VPP  v16.06
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-gre/mpls.h>
20 
22 
23 u8 * format_mpls_gre_tx_trace (u8 * s, va_list * args)
24 {
25  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
26  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
27  mpls_gre_tx_trace_t * t = va_arg (*args, mpls_gre_tx_trace_t *);
28  mpls_main_t * mm = &mpls_main;
29 
30  if (t->lookup_miss)
31  s = format (s, "MPLS: lookup miss");
32  else
33  {
34  s = format (s, "MPLS: tunnel %d labels %U len %d src %U dst %U",
35  t->tunnel_id,
37  clib_net_to_host_u16 (t->length),
40  }
41  return s;
42 }
43 
44 u8 * format_mpls_eth_tx_trace (u8 * s, va_list * args)
45 {
46  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
47  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
48  mpls_eth_tx_trace_t * t = va_arg (*args, mpls_eth_tx_trace_t *);
49  mpls_main_t * mm = &mpls_main;
50 
51  if (t->lookup_miss)
52  s = format (s, "MPLS: lookup miss");
53  else
54  {
55  s = format (s, "MPLS: tunnel %d labels %U len %d tx_sw_index %d dst %U",
56  t->tunnel_id,
58  clib_net_to_host_u16 (t->length),
59  t->tx_sw_if_index,
61  }
62  return s;
63 }
64 
65 u8 * format_mpls_eth_header_with_length (u8 * s, va_list * args)
66 {
67  ethernet_header_t * h = va_arg (*args, ethernet_header_t *);
69  u32 max_header_bytes = va_arg (*args, u32);
70  uword header_bytes;
71 
72  header_bytes = sizeof (h[0]);
73  if (max_header_bytes != 0 && header_bytes > max_header_bytes)
74  return format (s, "ethernet header truncated");
75 
76  s = format
77  (s, "ETHERNET-MPLS label %d",
78  vnet_mpls_uc_get_label (clib_net_to_host_u32 (m->label_exp_s_ttl)));
79 
80  return s;
81 }
82 
83 u8 * format_mpls_gre_header_with_length (u8 * s, va_list * args)
84 {
85  gre_header_t * h = va_arg (*args, gre_header_t *);
87  u32 max_header_bytes = va_arg (*args, u32);
88  uword header_bytes;
89 
90  header_bytes = sizeof (h[0]);
91  if (max_header_bytes != 0 && header_bytes > max_header_bytes)
92  return format (s, "gre header truncated");
93 
94  s = format
95  (s, "GRE-MPLS label %d",
96  vnet_mpls_uc_get_label (clib_net_to_host_u32 (m->label_exp_s_ttl)));
97 
98  return s;
99 }
100 
101 u8 * format_mpls_gre_header (u8 * s, va_list * args)
102 {
103  gre_header_t * h = va_arg (*args, gre_header_t *);
104  return format (s, "%U", format_mpls_gre_header_with_length, h, 0);
105 }
106 
107 uword
109 {
110  u8 ** result = va_arg (*args, u8 **);
111  gre_header_t _g, * g = &_g;
112  mpls_unicast_header_t _h, * h = &_h;
113  u32 label, label_exp_s_ttl;
114 
115  if (! unformat (input, "MPLS %d", &label))
116  return 0;
117 
118  g->protocol = clib_host_to_net_u16 (GRE_PROTOCOL_mpls_unicast);
119 
120  label_exp_s_ttl = (label<<12) | (1<<8) /* s-bit */ | 0xFF;
121  h->label_exp_s_ttl = clib_host_to_net_u32 (label_exp_s_ttl);
122 
123  /* Add gre, mpls headers to result. */
124  {
125  void * p;
126  u32 g_n_bytes = sizeof (g[0]);
127  u32 h_n_bytes = sizeof (h[0]);
128 
129  vec_add2 (*result, p, g_n_bytes);
130  clib_memcpy (p, g, g_n_bytes);
131 
132  vec_add2 (*result, p, h_n_bytes);
133  clib_memcpy (p, h, h_n_bytes);
134  }
135 
136  return 1;
137 }
138 
139 uword
141  va_list * args)
142 {
143  u32 * result = va_arg (*args, u32 *);
144  u32 label;
145 
146  if (!unformat (input, "MPLS: label %d", &label))
147  return 0;
148 
149  label = (label<<12) | (1<<8) /* s-bit set */ | 0xFF /* ttl */;
150 
151  *result = clib_host_to_net_u32 (label);
152  return 1;
153 }
154 
155 mpls_encap_t *
156 mpls_encap_by_fib_and_dest (mpls_main_t * mm, u32 rx_fib, u32 dst_address)
157 {
158  uword * p;
159  mpls_encap_t * e;
160  u64 key;
161 
162  key = ((u64)rx_fib<<32) | ((u64) dst_address);
163  p = hash_get (mm->mpls_encap_by_fib_and_dest, key);
164 
165  if (!p)
166  return 0;
167 
168  e = pool_elt_at_index (mm->encaps, p[0]);
169  return e;
170 }
171 
173  u32 *labels_host_byte_order,
174  u32 policy_tunnel_index,
175  int no_dst_hash, u32 * indexp, int is_add)
176 {
177  mpls_main_t * mm = &mpls_main;
178  ip4_main_t * im = &ip4_main;
179  mpls_encap_t * e;
180  u32 label_net_byte_order, label_host_byte_order;
181  u32 fib_index;
182  u64 key;
183  uword *p;
184  int i;
185 
186  p = hash_get (im->fib_index_by_table_id, fib_id);
187  if (! p)
188  return VNET_API_ERROR_NO_SUCH_FIB;
189 
190  fib_index = p[0];
191 
192  key = ((u64)fib_index<<32) | ((u64) dest->as_u32);
193 
194  if (is_add)
195  {
196  pool_get (mm->encaps, e);
197  memset (e, 0, sizeof (*e));
198 
199  for (i = 0; i < vec_len (labels_host_byte_order); i++)
200  {
202  label_host_byte_order = labels_host_byte_order[i];
203 
204  /* Reformat label into mpls_unicast_header_t */
205  label_host_byte_order <<= 12;
206  if (i == vec_len(labels_host_byte_order) - 1)
207  label_host_byte_order |= 1<<8; /* S=1 */
208  label_host_byte_order |= 0xff; /* TTL=FF */
209  label_net_byte_order = clib_host_to_net_u32 (label_host_byte_order);
210  h.label_exp_s_ttl = label_net_byte_order;
211  vec_add1 (e->labels, h);
212  }
213  if (no_dst_hash == 0)
214  hash_set (mm->mpls_encap_by_fib_and_dest, key, e - mm->encaps);
215  if (indexp)
216  *indexp = e - mm->encaps;
217  if (policy_tunnel_index != ~0)
218  return vnet_mpls_policy_tunnel_add_rewrite (mm, e, policy_tunnel_index);
219  }
220  else
221  {
222  p = hash_get (mm->mpls_encap_by_fib_and_dest, key);
223  if (!p)
224  return VNET_API_ERROR_NO_SUCH_LABEL;
225 
226  e = pool_elt_at_index (mm->encaps, p[0]);
227 
228  vec_free (e->labels);
229  vec_free (e->rewrite);
230  pool_put(mm->encaps, e);
231 
232  if (no_dst_hash == 0)
234  }
235  return 0;
236 }
237 
238 static clib_error_t *
240  unformat_input_t * input,
241  vlib_cli_command_t * cmd)
242 {
243  u32 fib_id;
244  u32 *labels = 0;
245  u32 this_label;
246  ip4_address_t dest;
247  u32 policy_tunnel_index = ~0;
248  int no_dst_hash = 0;
249  int rv;
250  int fib_set = 0;
251  int dest_set = 0;
252 
254  {
255  if (unformat (input, "fib %d", &fib_id))
256  fib_set = 1;
257  else if (unformat (input, "dest %U", unformat_ip4_address, &dest))
258  dest_set = 1;
259  else if (unformat (input, "no-dst-hash"))
260  no_dst_hash = 1;
261  else if (unformat (input, "label %d", &this_label))
262  vec_add1 (labels, this_label);
263  else if (unformat (input, "policy-tunnel %d", &policy_tunnel_index))
264  ;
265  else
266  break;
267  }
268 
269  if (fib_set == 0)
270  return clib_error_return (0, "fib-id missing");
271  if (dest_set == 0)
272  return clib_error_return (0, "destination IP address missing");
273  if (vec_len (labels) == 0)
274  return clib_error_return (0, "label stack missing");
275 
276  rv = vnet_mpls_add_del_encap (&dest, fib_id, labels,
277  policy_tunnel_index,
278  no_dst_hash, 0 /* indexp */,
279  1 /* is_add */);
280  vec_free (labels);
281 
282  switch (rv)
283  {
284  case 0:
285  break;
286 
287  case VNET_API_ERROR_NO_SUCH_FIB:
288  return clib_error_return (0, "fib id %d unknown", fib_id);
289 
290  default:
291  return clib_error_return (0, "vnet_mpls_add_del_encap returned %d",
292  rv);
293  }
294 
295  return 0;
296 }
297 
298 VLIB_CLI_COMMAND (mpls_add_encap_command, static) = {
299  .path = "mpls encap add",
300  .short_help =
301  "mpls encap add label <label> ... fib <id> dest <ip4-address>",
302  .function = mpls_add_encap_command_fn,
303 };
304 
306 {
307  mpls_unicast_header_t *h = va_arg(*args, mpls_unicast_header_t *);
308  u32 label = h->label_exp_s_ttl;
309 
310  s = format (s, "label %d exp %d, s %d, ttl %d",
311  vnet_mpls_uc_get_label (label),
312  vnet_mpls_uc_get_exp (label),
313  vnet_mpls_uc_get_s (label),
314  vnet_mpls_uc_get_ttl (label));
315  return s;
316 }
317 
319 {
320  mpls_unicast_header_t *h = va_arg(*args, mpls_unicast_header_t *);
321  mpls_unicast_header_t h_host;
322 
323  h_host.label_exp_s_ttl = clib_net_to_host_u32 (h->label_exp_s_ttl);
324 
326  &h_host);
327 }
328 
329 static clib_error_t *
331  unformat_input_t * input,
332  vlib_cli_command_t * cmd)
333 {
334  u32 fib_id;
335  ip4_address_t dest;
336  int rv;
337 
338  if (unformat (input, "fib %d dest %U", &fib_id,
339  unformat_ip4_address, &dest))
340  {
341  rv = vnet_mpls_add_del_encap (&dest, fib_id, 0 /* labels */,
342  ~0 /* policy_tunnel_index */,
343  0 /* no_dst_hash */,
344  0 /* indexp */,
345  0 /* is_add */);
346  switch (rv)
347  {
348  case VNET_API_ERROR_NO_SUCH_FIB:
349  return clib_error_return (0, "fib id %d unknown", fib_id);
350  case VNET_API_ERROR_NO_SUCH_ENTRY:
351  return clib_error_return (0, "dest %U not in fib %d",
352  format_ip4_address, &dest, fib_id);
353  default:
354  break;
355  }
356  return 0;
357  }
358  else
359  return clib_error_return (0, "unknown input `%U'",
360  format_unformat_error, input);
361 }
362 
363 VLIB_CLI_COMMAND (mpls_del_encap_command, static) = {
364  .path = "mpls encap delete",
365  .short_help = "mpls encap delete fib <id> dest <ip4-address>",
366  .function = mpls_del_encap_command_fn,
367 };
368 
369 int vnet_mpls_add_del_decap (u32 rx_fib_id,
370  u32 tx_fib_id,
371  u32 label_host_byte_order,
372  int s_bit, int next_index, int is_add)
373 {
374  mpls_main_t * mm = &mpls_main;
375  ip4_main_t * im = &ip4_main;
376  mpls_decap_t * d;
377  u32 rx_fib_index, tx_fib_index_or_output_swif_index;
378  uword *p;
379  u64 key;
380 
381  p = hash_get (im->fib_index_by_table_id, rx_fib_id);
382  if (! p)
383  return VNET_API_ERROR_NO_SUCH_FIB;
384 
385  rx_fib_index = p[0];
386 
387  /* L3 decap => transform fib ID to fib index */
388  if (next_index == MPLS_INPUT_NEXT_IP4_INPUT)
389  {
390  p = hash_get (im->fib_index_by_table_id, tx_fib_id);
391  if (! p)
392  return VNET_API_ERROR_NO_SUCH_INNER_FIB;
393 
394  tx_fib_index_or_output_swif_index = p[0];
395  }
396  else
397  {
398  /* L2 decap, tx_fib_id is actually the output sw_if_index */
399  tx_fib_index_or_output_swif_index = tx_fib_id;
400  }
401 
402  key = ((u64)rx_fib_index<<32) | ((u64) (label_host_byte_order<<12))
403  | ((u64) s_bit<<8);
404 
406 
407  /* If deleting, or replacing an old entry */
408  if (is_add == 0 || p)
409  {
410  if (is_add == 0 && p == 0)
411  return VNET_API_ERROR_NO_SUCH_LABEL;
412 
413  d = pool_elt_at_index (mm->decaps, p[0]);
415  pool_put (mm->decaps, d);
416  /* Deleting, we're done... */
417  if (is_add == 0)
418  return 0;
419  }
420 
421  /* add decap entry... */
422  pool_get (mm->decaps, d);
423  memset (d, 0, sizeof (*d));
424  d->tx_fib_index = tx_fib_index_or_output_swif_index;
425  d->next_index = next_index;
426 
427  hash_set (mm->mpls_decap_by_rx_fib_and_label, key, d - mm->decaps);
428 
429  return 0;
430 }
431 
432 uword
434 {
435  u32 * result = va_arg (*args, u32 *);
436  int rv = 0;
437 
438  if (unformat (input, "lookup"))
439  {
440  *result = MPLS_INPUT_NEXT_IP4_INPUT;
441  rv = 1;
442  }
443  else if (unformat (input, "output"))
444  {
445  *result = MPLS_INPUT_NEXT_L2_OUTPUT;
446  rv = 1;
447  }
448  return rv;
449 }
450 
451 static clib_error_t *
453  unformat_input_t * input,
454  vlib_cli_command_t * cmd)
455 {
456  vnet_main_t * vnm = vnet_get_main();
457  u32 rx_fib_id = 0;
458  u32 tx_fib_or_sw_if_index;
459  u32 label;
460  int s_bit = 1;
461  u32 next_index = 1; /* ip4_lookup, see node.c */
462  int tx_fib_id_set = 0;
463  int label_set = 0;
464  int rv;
465 
467  {
468  if (unformat (input, "fib %d", &tx_fib_or_sw_if_index))
469  tx_fib_id_set = 1;
470  else if (unformat (input, "sw_if_index %d", &tx_fib_or_sw_if_index))
471  tx_fib_id_set = 1;
472  else if (unformat (input, "%U", unformat_vnet_sw_interface, vnm,
473  &tx_fib_or_sw_if_index))
474  tx_fib_id_set = 1;
475  else if (unformat (input, "rx-fib %d", &rx_fib_id))
476  ;
477  else if (unformat (input, "label %d", &label))
478  label_set = 1;
479  else if (unformat (input, "s-bit-clear"))
480  s_bit = 0;
481  else if (unformat (input, "next %U", unformat_mpls_gre_input_next,
482  &next_index))
483  ;
484  else
485  break;
486  }
487 
488  if (tx_fib_id_set == 0)
489  return clib_error_return (0, "lookup FIB ID not set");
490  if (label_set == 0)
491  return clib_error_return (0, "missing label");
492 
493  rv = vnet_mpls_add_del_decap (rx_fib_id, tx_fib_or_sw_if_index,
494  label, s_bit, next_index, 1 /* is_add */);
495  switch (rv)
496  {
497  case 0:
498  break;
499 
500  case VNET_API_ERROR_NO_SUCH_FIB:
501  return clib_error_return (0, "no such rx fib id %d", rx_fib_id);
502 
503  case VNET_API_ERROR_NO_SUCH_INNER_FIB:
504  return clib_error_return (0, "no such tx fib / swif %d",
505  tx_fib_or_sw_if_index);
506 
507  default:
508  return clib_error_return (0, "vnet_mpls_add_del_decap returned %d",
509  rv);
510  }
511  return 0;
512 }
513 
514 VLIB_CLI_COMMAND (mpls_add_decap_command, static) = {
515  .path = "mpls decap add",
516  .short_help =
517  "mpls decap add fib <id> label <nn> [s-bit-clear] [next-index <nn>]",
518  .function = mpls_add_decap_command_fn,
519 };
520 
521 static clib_error_t *
523  unformat_input_t * input,
524  vlib_cli_command_t * cmd)
525 {
526  u32 rx_fib_id = 0;
527  u32 tx_fib_id = 0;
528  u32 label;
529  int s_bit = 1;
530  int label_set = 0;
531  int rv;
532 
534  {
535  if (unformat (input, "rx-fib %d", &rx_fib_id))
536  ;
537  else if (unformat (input, "label %d", &label))
538  label_set = 1;
539  else if (unformat (input, "s-bit-clear"))
540  s_bit = 0;
541  }
542 
543  if (!label_set)
544  return clib_error_return (0, "label not set");
545 
546  rv = vnet_mpls_add_del_decap (rx_fib_id,
547  tx_fib_id /* not interesting */,
548  label, s_bit,
549  0 /* next_index not interesting */,
550  0 /* is_add */);
551  switch (rv)
552  {
553  case 0:
554  break;
555 
556  case VNET_API_ERROR_NO_SUCH_FIB:
557  return clib_error_return (0, "no such rx fib id %d", rx_fib_id);
558 
559  case VNET_API_ERROR_NO_SUCH_INNER_FIB:
560  return clib_error_return (0, "no such lookup fib id %d", tx_fib_id);
561 
562  case VNET_API_ERROR_NO_SUCH_LABEL:
563  return clib_error_return (0, "no such label %d rx fib id %d",
564  label, rx_fib_id);
565 
566  default:
567  return clib_error_return (0, "vnet_mpls_add_del_decap returned %d",
568  rv);
569  }
570  return 0;
571 }
572 
573 
574 VLIB_CLI_COMMAND (mpls_del_decap_command, static) = {
575  .path = "mpls decap delete",
576  .short_help = "mpls decap delete label <label> rx-fib <id> [s-bit-clear]",
577  .function = mpls_del_decap_command_fn,
578 };
579 
580 typedef struct {
587 
588 static int
589 mpls_dest_cmp(void * a1, void * a2)
590 {
591  show_mpls_fib_t * r1 = a1;
592  show_mpls_fib_t * r2 = a2;
593 
594  return clib_net_to_host_u32(r1->dest) - clib_net_to_host_u32(r2->dest);
595 }
596 
597 static int
598 mpls_fib_index_cmp(void * a1, void * a2)
599 {
600  show_mpls_fib_t * r1 = a1;
601  show_mpls_fib_t * r2 = a2;
602 
603  return r1->fib_index - r2->fib_index;
604 }
605 
606 static int
607 mpls_label_cmp(void * a1, void * a2)
608 {
609  show_mpls_fib_t * r1 = a1;
610  show_mpls_fib_t * r2 = a2;
611 
612  return r1->label - r2->label;
613 }
614 
615 static clib_error_t *
617  unformat_input_t * input,
618  vlib_cli_command_t * cmd)
619 {
620  u64 key;
621  u32 value;
622  show_mpls_fib_t *records = 0;
623  show_mpls_fib_t *s;
624  mpls_main_t * mm = &mpls_main;
625  ip4_main_t * im = &ip4_main;
626  ip4_fib_t * rx_fib, * tx_fib;
627  u32 tx_table_id;
628  char *swif_tag;
629 
630  hash_foreach (key, value, mm->mpls_encap_by_fib_and_dest,
631  ({
632  vec_add2 (records, s, 1);
633  s->fib_index = (u32)(key>>32);
634  s->dest = (u32)(key & 0xFFFFFFFF);
635  s->entry_index = (u32) value;
636  }));
637 
638  if (!vec_len(records))
639  {
640  vlib_cli_output (vm, "MPLS encap table empty");
641  goto decap_table;
642  }
643  /* sort output by dst address within fib */
646  vlib_cli_output (vm, "MPLS encap table");
647  vlib_cli_output (vm, "%=6s%=16s%=16s", "Table", "Dest address", "Labels");
648  vec_foreach (s, records)
649  {
650  rx_fib = vec_elt_at_index (im->fibs, s->fib_index);
651  vlib_cli_output (vm, "%=6d%=16U%=16U", rx_fib->table_id,
654  }
655 
656  decap_table:
657  vec_reset_length(records);
658 
660  ({
661  vec_add2 (records, s, 1);
662  s->fib_index = (u32)(key>>32);
663  s->entry_index = (u32) value;
664  s->label = ((u32) key)>>12;
665  s->s_bit = (key & (1<<8)) != 0;
666  }));
667 
668  if (!vec_len(records))
669  {
670  vlib_cli_output (vm, "MPLS decap table empty");
671  goto out;
672  }
673 
675 
676  vlib_cli_output (vm, "MPLS decap table");
677  vlib_cli_output (vm, "%=10s%=15s%=6s%=6s", "RX Table", "TX Table/Intfc",
678  "Label", "S-bit");
679  vec_foreach (s, records)
680  {
681  mpls_decap_t * d;
682  d = pool_elt_at_index (mm->decaps, s->entry_index);
683  if (d->next_index == MPLS_INPUT_NEXT_IP4_INPUT)
684  {
685  tx_fib = vec_elt_at_index (im->fibs, d->tx_fib_index);
686  tx_table_id = tx_fib->table_id;
687  swif_tag = " ";
688  }
689  else
690  {
691  tx_table_id = d->tx_fib_index;
692  swif_tag = "(i) ";
693  }
694  rx_fib = vec_elt_at_index (im->fibs, s->fib_index);
695 
696  vlib_cli_output (vm, "%=10d%=10d%=5s%=6d%=6d", rx_fib->table_id,
697  tx_table_id, swif_tag, s->label, s->s_bit);
698  }
699 
700  out:
701  vec_free(records);
702  return 0;
703 }
704 
705 VLIB_CLI_COMMAND (show_mpls_fib_command, static) = {
706  .path = "show mpls fib",
707  .short_help = "show mpls fib",
708  .function = show_mpls_fib_command_fn,
709 };
710 
712 {
713  u64 key;
714  u32 value;
715  show_mpls_fib_t *records = 0;
716  show_mpls_fib_t *s;
717  mpls_main_t * mm = &mpls_main;
718  ip4_main_t * im = &ip4_main;
719  u32 fib_index;
720  uword *p;
721 
722  p = hash_get (im->fib_index_by_table_id, fib_id);
723  if (! p)
724  return VNET_API_ERROR_NO_SUCH_FIB;
725 
726  fib_index = p[0];
727 
728  hash_foreach (key, value, mm->mpls_encap_by_fib_and_dest,
729  ({
730  if (fib_index == (u32)(key>>32)) {
731  vec_add2 (records, s, 1);
732  s->dest = (u32)(key & 0xFFFFFFFF);
733  s->entry_index = (u32) value;
734  }
735  }));
736 
737  vec_foreach (s, records)
738  {
739  key = ((u64)fib_index<<32) | ((u64) s->dest);
740  hash_unset (mm->mpls_encap_by_fib_and_dest, key);
741  pool_put_index (mm->encaps, s->entry_index);
742  }
743 
744  vec_reset_length(records);
745 
746  hash_foreach (key, value, mm->mpls_decap_by_rx_fib_and_label,
747  ({
748  if (fib_index == (u32) (key>>32)) {
749  vec_add2 (records, s, 1);
750  s->entry_index = value;
751  s->fib_index = fib_index;
752  s->s_bit = key & (1<<8);
753  s->dest = (u32)((key & 0xFFFFFFFF)>>12);
754  }
755  }));
756 
757  vec_foreach (s, records)
758  {
759  key = ((u64)fib_index <<32) | ((u64)(s->dest<<12)) |
760  ((u64)s->s_bit);
761 
762  hash_unset (mm->mpls_decap_by_rx_fib_and_label, key);
763  pool_put_index (mm->decaps, s->entry_index);
764  }
765 
766  vec_free(records);
767  return 0;
768 }
769 
771 {
772  mpls_main_t * mm = &mpls_main;
773  clib_error_t * error;
774 
775  memset (mm, 0, sizeof (mm[0]));
776  mm->vlib_main = vm;
777  mm->vnet_main = vnet_get_main();
778 
779  if ((error = vlib_call_init_function (vm, ip_main_init)))
780  return error;
781 
782  mm->mpls_encap_by_fib_and_dest = hash_create (0, sizeof (uword));
784 
786 }
787 
789 
791 {
793  return &mpls_main;
794 }
795 
#define hash_set(h, key, value)
Definition: hash.h:237
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
static clib_error_t * mpls_del_decap_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: mpls.c:522
#define CLIB_UNUSED(x)
Definition: clib.h:79
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:942
static u32 vnet_mpls_uc_get_label(u32 label_exp_s_ttl)
Definition: packet.h:29
#define hash_unset(h, key)
Definition: hash.h:243
u32 table_id
Definition: ip4.h:58
u32 next_index
Definition: mpls.h:78
#define UNFORMAT_END_OF_INPUT
Definition: format.h:142
static clib_error_t * mpls_input_init(vlib_main_t *vm)
Definition: node.c:346
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:480
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:519
u8 * format_mpls_unicast_header_host_byte_order(u8 *s, va_list *args)
Definition: mpls.c:305
unformat_function_t unformat_vnet_sw_interface
uword * mpls_encap_by_fib_and_dest
Definition: mpls.h:92
#define pool_get(P, E)
Definition: pool.h:186
format_function_t format_ip4_address
Definition: format.h:71
static u32 vnet_mpls_uc_get_s(u32 label_exp_s_ttl)
Definition: packet.h:39
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
uword unformat_mpls_gre_input_next(unformat_input_t *input, va_list *args)
Definition: mpls.c:433
ip4_address_t dst
Definition: mpls.h:192
always_inline uword unformat_check_input(unformat_input_t *i)
Definition: format.h:168
static clib_error_t * mpls_add_encap_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: mpls.c:239
static int mpls_fib_index_cmp(void *a1, void *a2)
Definition: mpls.c:598
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
mpls_decap_t * decaps
Definition: mpls.h:95
u8 * format_mpls_eth_tx_trace(u8 *s, va_list *args)
Definition: mpls.c:44
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:43
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:109
int mpls_fib_reset_labels(u32 fib_id)
Definition: mpls.c:711
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:380
static int mpls_dest_cmp(void *a1, void *a2)
Definition: mpls.c:589
ip4_address_t src
Definition: mpls.h:191
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
unsigned long u64
Definition: types.h:89
static clib_error_t * show_mpls_fib_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: mpls.c:616
#define vlib_call_init_function(vm, x)
Definition: init.h:159
static int mpls_label_cmp(void *a1, void *a2)
Definition: mpls.c:607
unformat_function_t unformat_ip4_address
Definition: format.h:68
#define hash_get(h, key)
Definition: hash.h:231
static u32 vnet_mpls_uc_get_exp(u32 label_exp_s_ttl)
Definition: packet.h:34
#define pool_elt_at_index(p, i)
Definition: pool.h:346
uword * fib_index_by_table_id
Definition: ip4.h:141
u32 entry_index
Definition: mpls.c:582
static u32 vnet_mpls_uc_get_ttl(u32 label_exp_s_ttl)
Definition: packet.h:44
#define pool_put(P, E)
Definition: pool.h:200
vnet_main_t * vnet_main
Definition: mpls.h:103
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:538
clib_error_t * ip_main_init(vlib_main_t *vm)
Definition: ip_init.c:45
u8 * rewrite
Definition: mpls.h:72
mpls_main_t mpls_main
Definition: mpls.c:21
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
Definition: ip4.h:47
u16 protocol
Definition: packet.h:51
#define clib_memcpy(a, b, c)
Definition: string.h:63
int vnet_mpls_add_del_decap(u32 rx_fib_id, u32 tx_fib_id, u32 label_host_byte_order, int s_bit, int next_index, int is_add)
Definition: mpls.c:369
u8 * format_mpls_gre_header_with_length(u8 *s, va_list *args)
Definition: mpls.c:83
int vnet_mpls_add_del_encap(ip4_address_t *dest, u32 fib_id, u32 *labels_host_byte_order, u32 policy_tunnel_index, int no_dst_hash, u32 *indexp, int is_add)
Definition: mpls.c:172
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:150
u32 mpls_encap_index
Definition: mpls.h:221
u32 fib_index
Definition: mpls.c:581
#define hash_create(elts, value_bytes)
Definition: hash.h:615
#define pool_put_index(p, i)
Definition: pool.h:214
unsigned int u32
Definition: types.h:88
ip4_fib_t * fibs
Definition: ip4.h:132
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:87
u32 tx_fib_index
Definition: mpls.h:77
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
uword unformat_mpls_label_net_byte_order(unformat_input_t *input, va_list *args)
Definition: mpls.c:140
uword * mpls_decap_by_rx_fib_and_label
Definition: mpls.h:96
uword unformat_mpls_gre_header(unformat_input_t *input, va_list *args)
Definition: mpls.c:108
int vnet_mpls_policy_tunnel_add_rewrite(mpls_main_t *mm, mpls_encap_t *e, u32 policy_tunnel_index)
Definition: interface.c:1592
u8 * format_mpls_eth_header_with_length(u8 *s, va_list *args)
Definition: mpls.c:65
mpls_encap_t * mpls_encap_by_fib_and_dest(mpls_main_t *mm, u32 rx_fib, u32 dst_address)
Definition: mpls.c:156
u64 uword
Definition: types.h:112
static clib_error_t * mpls_init(vlib_main_t *vm)
Definition: mpls.c:770
u8 * format_mpls_unicast_header_net_byte_order(u8 *s, va_list *args)
Definition: mpls.c:318
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:898
u8 * format_mpls_gre_header(u8 *s, va_list *args)
Definition: mpls.c:101
vlib_main_t * vlib_main
Definition: mpls.h:102
u8 * format_mpls_gre_tx_trace(u8 *s, va_list *args)
Definition: mpls.c:23
u32 mpls_encap_index
Definition: mpls.h:185
mpls_main_t * mpls_get_main(vlib_main_t *vm)
Definition: mpls.c:790
ip4_main_t ip4_main
Definition: ip4_forward.c:1394
#define vec_foreach(var, vec)
Vector iterator.
format_function_t format_mpls_encap_index
Definition: mpls.h:114
#define clib_error_return(e, args...)
Definition: error.h:112
struct _unformat_input_t unformat_input_t
u32 tx_sw_if_index
Definition: mpls.h:218
static clib_error_t * mpls_del_encap_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: mpls.c:330
static clib_error_t * mpls_add_decap_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: mpls.c:452
mpls_unicast_header_t * labels
Definition: mpls.h:70
mpls_encap_t * encaps
Definition: mpls.h:91