FD.io VPP  v20.01-48-g3e0dafb74
Vector Packet Processing
map.c
Go to the documentation of this file.
1 /*
2  * map.c : MAP support
3  *
4  * Copyright (c) 2015 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/fib/fib_table.h>
20 #include <vnet/fib/ip6_fib.h>
21 #include <vnet/adj/adj.h>
22 #include <vppinfra/crc32.h>
23 #include <vnet/plugin/plugin.h>
24 #include <vpp/app/version.h>
25 #include "map.h"
26 
28 
29 /*
30  * This code supports the following MAP modes:
31  *
32  * Algorithmic Shared IPv4 address (ea_bits_len > 0):
33  * ea_bits_len + ip4_prefix > 32
34  * psid_length > 0, ip6_prefix < 64, ip4_prefix <= 32
35  * Algorithmic Full IPv4 address (ea_bits_len > 0):
36  * ea_bits_len + ip4_prefix = 32
37  * psid_length = 0, ip6_prefix < 64, ip4_prefix <= 32
38  * Algorithmic IPv4 prefix (ea_bits_len > 0):
39  * ea_bits_len + ip4_prefix < 32
40  * psid_length = 0, ip6_prefix < 64, ip4_prefix <= 32
41  *
42  * Independent Shared IPv4 address (ea_bits_len = 0):
43  * ip4_prefix = 32
44  * psid_length > 0
45  * Rule IPv6 address = 128, Rule PSID Set
46  * Independent Full IPv4 address (ea_bits_len = 0):
47  * ip4_prefix = 32
48  * psid_length = 0, ip6_prefix = 128
49  * Independent IPv4 prefix (ea_bits_len = 0):
50  * ip4_prefix < 32
51  * psid_length = 0, ip6_prefix = 128
52  *
53  */
54 
55 /*
56  * This code supports MAP-T:
57  *
58  * With a DMR prefix length of 64 or 96 (RFC6052).
59  *
60  */
61 
62 
63 /*
64  * Save user-assigned MAP domain names ("tags") in a vector of
65  * extra domain information.
66  */
67 static void
68 map_save_extras (u32 map_domain_index, u8 * tag)
69 {
70  map_main_t *mm = &map_main;
72 
73  if (map_domain_index == ~0)
74  return;
75 
76  vec_validate (mm->domain_extras, map_domain_index);
77  de = vec_elt_at_index (mm->domain_extras, map_domain_index);
78  clib_memset (de, 0, sizeof (*de));
79 
80  if (!tag)
81  return;
82 
83  vec_validate_init_c_string (de->tag, tag, strlen ((char *) tag));
84 }
85 
86 
87 static void
88 map_free_extras (u32 map_domain_index)
89 {
90  map_main_t *mm = &map_main;
92 
93  if (map_domain_index == ~0)
94  return;
95 
96  if (map_domain_index >= vec_len (mm->domain_extras))
97  return;
98 
99  de = vec_elt_at_index (mm->domain_extras, map_domain_index);
100  vec_free (de->tag);
101 }
102 
103 
104 int
106  u8 ip4_prefix_len,
108  u8 ip6_prefix_len,
109  ip6_address_t * ip6_src,
110  u8 ip6_src_len,
111  u8 ea_bits_len,
112  u8 psid_offset,
113  u8 psid_length,
114  u32 * map_domain_index, u16 mtu, u8 flags, u8 * tag)
115 {
116  u8 suffix_len, suffix_shift;
117  map_main_t *mm = &map_main;
118  map_domain_t *d;
119 
120  /* How many, and which bits to grab from the IPv4 DA */
121  if (ip4_prefix_len + ea_bits_len < 32)
122  {
123  flags |= MAP_DOMAIN_PREFIX;
124  suffix_shift = 32 - ip4_prefix_len - ea_bits_len;
125  suffix_len = ea_bits_len;
126  }
127  else
128  {
129  suffix_shift = 0;
130  suffix_len = 32 - ip4_prefix_len;
131  }
132 
133  /* EA bits must be within the first 64 bits */
134  if (ea_bits_len > 0 && ((ip6_prefix_len + ea_bits_len) > 64 ||
135  ip6_prefix_len + suffix_len + psid_length > 64))
136  {
138  ("Embedded Address bits must be within the first 64 bits of "
139  "the IPv6 prefix");
140  return -1;
141  }
142 
143  /* Get domain index */
145  clib_memset (d, 0, sizeof (*d));
146  *map_domain_index = d - mm->domains;
147 
148  /* Init domain struct */
149  d->ip4_prefix.as_u32 = ip4_prefix->as_u32;
150  d->ip4_prefix_len = ip4_prefix_len;
151  d->ip6_prefix = *ip6_prefix;
152  d->ip6_prefix_len = ip6_prefix_len;
153  d->ip6_src = *ip6_src;
154  d->ip6_src_len = ip6_src_len;
155  d->ea_bits_len = ea_bits_len;
156  d->psid_offset = psid_offset;
157  d->psid_length = psid_length;
158  d->mtu = mtu;
159  d->flags = flags;
160  d->suffix_shift = suffix_shift;
161  d->suffix_mask = (1 << suffix_len) - 1;
162 
163  d->psid_shift = 16 - psid_length - psid_offset;
164  d->psid_mask = (1 << d->psid_length) - 1;
165  d->ea_shift = 64 - ip6_prefix_len - suffix_len - d->psid_length;
166 
167  /* Save a user-assigned MAP domain name if provided. */
168  if (tag)
169  map_save_extras (*map_domain_index, tag);
170 
171  /* MAP longest match lookup table (input feature / FIB) */
173  d->ip4_prefix_len, *map_domain_index);
174 
175  /* Really needed? Or always use FIB? */
177  d->ip6_src_len, *map_domain_index);
178 
179  /* Validate packet/byte counters */
181  int i;
182  for (i = 0; i < vec_len (mm->simple_domain_counters); i++)
183  {
185  *map_domain_index);
187  *map_domain_index);
188  }
189  for (i = 0; i < vec_len (mm->domain_counters); i++)
190  {
192  *map_domain_index);
193  vlib_zero_combined_counter (&mm->domain_counters[i], *map_domain_index);
194  }
196 
197  return 0;
198 }
199 
200 /*
201  * map_delete_domain
202  */
203 int
204 map_delete_domain (u32 map_domain_index)
205 {
206  map_main_t *mm = &map_main;
207  map_domain_t *d;
208 
209  if (pool_is_free_index (mm->domains, map_domain_index))
210  {
211  clib_warning ("MAP domain delete: domain does not exist: %d",
212  map_domain_index);
213  return -1;
214  }
215 
216  d = pool_elt_at_index (mm->domains, map_domain_index);
218  d->ip4_prefix_len);
220  d->ip6_src_len);
221 
222  /* Release user-assigned MAP domain name. */
223  map_free_extras (map_domain_index);
224 
225  /* Deleting rules */
226  if (d->rules)
227  clib_mem_free (d->rules);
228 
229  pool_put (mm->domains, d);
230 
231  return 0;
232 }
233 
234 int
235 map_add_del_psid (u32 map_domain_index, u16 psid, ip6_address_t * tep,
236  bool is_add)
237 {
238  map_domain_t *d;
239  map_main_t *mm = &map_main;
240 
241  if (pool_is_free_index (mm->domains, map_domain_index))
242  {
243  clib_warning ("MAP rule: domain does not exist: %d", map_domain_index);
244  return -1;
245  }
246  d = pool_elt_at_index (mm->domains, map_domain_index);
247 
248  /* Rules are only used in 1:1 independent case */
249  if (d->ea_bits_len > 0)
250  return (-1);
251 
252  if (!d->rules)
253  {
254  u32 l = (0x1 << d->psid_length) * sizeof (ip6_address_t);
256  if (!d->rules)
257  return -1;
258  clib_memset (d->rules, 0, l);
259  }
260 
261  if (psid >= (0x1 << d->psid_length))
262  {
263  clib_warning ("MAP rule: PSID outside bounds: %d [%d]", psid,
264  0x1 << d->psid_length);
265  return -1;
266  }
267 
268  if (is_add)
269  {
270  d->rules[psid] = *tep;
271  }
272  else
273  {
274  clib_memset (&d->rules[psid], 0, sizeof (ip6_address_t));
275  }
276  return 0;
277 }
278 
279 #ifdef MAP_SKIP_IP6_LOOKUP
280 /**
281  * Pre-resolved per-protocol global next-hops
282  */
284 
285 static void
287 {
290 }
291 
292 static u8 *
293 format_map_pre_resolve (u8 * s, va_list * ap)
294 {
295  map_main_pre_resolved_t *pr = va_arg (*ap, map_main_pre_resolved_t *);
296 
297  if (FIB_NODE_INDEX_INVALID != pr->fei)
298  {
299  const fib_prefix_t *pfx;
300 
301  pfx = fib_entry_get_prefix (pr->fei);
302 
303  return (format (s, "%U (%u)",
305  pr->dpo.dpoi_index));
306  }
307  else
308  {
309  return (format (s, "un-set"));
310  }
311 }
312 
313 
314 /**
315  * Function definition to inform the FIB node that its last lock has gone.
316  */
317 static void
319 {
320  /*
321  * The MAP is a root of the graph. As such
322  * it never has children and thus is never locked.
323  */
324  ASSERT (0);
325 }
326 
329 {
331  return ((map_main_pre_resolved_t *)
332  (((char *) node) -
334 }
335 
336 static void
338 {
339  const dpo_id_t *dpo;
340 
342 
343  dpo_copy (&pr->dpo, dpo);
344 }
345 
346 /**
347  * Function definition to backwalk a FIB node
348  */
351 {
352  map_stack (map_from_fib_node (node));
353 
355 }
356 
357 /**
358  * Function definition to get a FIB node from its index
359  */
360 static fib_node_t *
362 {
363  return (&pre_resolved[index].node);
364 }
365 
366 /*
367  * Virtual function table registered by MPLS GRE tunnels
368  * for participation in the FIB object graph.
369  */
370 const static fib_node_vft_t map_vft = {
372  .fnv_last_lock = map_last_lock_gone,
373  .fnv_back_walk = map_back_walk,
374 };
375 
376 static void
378  fib_protocol_t proto, u8 len, const ip46_address_t * addr)
379 {
380  fib_prefix_t pfx = {
381  .fp_proto = proto,
382  .fp_len = len,
383  .fp_addr = *addr,
384  };
385 
386  pr->fei = fib_entry_track (0, // default fib
387  &pfx, FIB_NODE_TYPE_MAP_E, proto, &pr->sibling);
388  map_stack (pr);
389 }
390 
391 static void
393  fib_protocol_t proto, u8 len, const ip46_address_t * addr)
394 {
395  if (pr->fei != FIB_NODE_INDEX_INVALID)
396  {
397  fib_entry_untrack (pr->fei, pr->sibling);
398 
399  dpo_reset (&pr->dpo);
400 
403  }
404 }
405 
406 void
408 {
409  if (ip6 && (ip6->as_u64[0] != 0 || ip6->as_u64[1] != 0))
410  {
411  ip46_address_t addr = {
412  .ip6 = *ip6,
413  };
414  if (is_del)
415  map_fib_unresolve (&pre_resolved[FIB_PROTOCOL_IP6],
416  FIB_PROTOCOL_IP6, 128, &addr);
417  else
418  map_fib_resolve (&pre_resolved[FIB_PROTOCOL_IP6],
419  FIB_PROTOCOL_IP6, 128, &addr);
420  }
421  if (ip4 && (ip4->as_u32 != 0))
422  {
423  ip46_address_t addr = {
424  .ip4 = *ip4,
425  };
426  if (is_del)
427  map_fib_unresolve (&pre_resolved[FIB_PROTOCOL_IP4],
428  FIB_PROTOCOL_IP4, 32, &addr);
429  else
430  map_fib_resolve (&pre_resolved[FIB_PROTOCOL_IP4],
431  FIB_PROTOCOL_IP4, 32, &addr);
432  }
433 }
434 #endif
435 
436 static clib_error_t *
438  unformat_input_t * input,
439  vlib_cli_command_t * cmd)
440 {
441  unformat_input_t _line_input, *line_input = &_line_input;
442  clib_error_t *error = NULL;
443  bool enable = false;
444  bool check_frag = false;
445  bool saw_enable = false;
446  bool saw_frag = false;
447 
448  /* Get a line of input. */
449  if (!unformat_user (input, unformat_line_input, line_input))
450  return 0;
451 
452  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
453  {
454  if (unformat (line_input, "enable"))
455  {
456  enable = true;
457  saw_enable = true;
458  }
459  else if (unformat (line_input, "disable"))
460  {
461  enable = false;
462  saw_enable = true;
463  }
464  else if (unformat (line_input, "fragments on"))
465  {
466  check_frag = true;
467  saw_frag = true;
468  }
469  else if (unformat (line_input, "fragments off"))
470  {
471  check_frag = false;
472  saw_frag = true;
473  }
474  else
475  {
476  error = clib_error_return (0, "unknown input `%U'",
477  format_unformat_error, line_input);
478  goto done;
479  }
480  }
481 
482  if (!saw_enable)
483  {
484  error = clib_error_return (0,
485  "Must specify enable 'enable' or 'disable'");
486  goto done;
487  }
488 
489  if (!saw_frag)
490  {
491  error = clib_error_return (0, "Must specify fragments 'on' or 'off'");
492  goto done;
493  }
494 
495  map_param_set_security_check (enable, check_frag);
496 
497 done:
498  unformat_free (line_input);
499 
500  return error;
501 }
502 
503 
504 static clib_error_t *
506  unformat_input_t * input, vlib_cli_command_t * cmd)
507 {
508  unformat_input_t _line_input, *line_input = &_line_input;
511  ip6_address_t ip6_src;
512  u32 ip6_prefix_len = 0, ip4_prefix_len = 0, map_domain_index, ip6_src_len;
513  u32 num_m_args = 0;
514  /* Optional arguments */
515  u32 ea_bits_len = 0, psid_offset = 0, psid_length = 0;
516  u32 mtu = 0;
517  u8 flags = 0;
518  u8 *tag = 0;
519  ip6_src_len = 128;
520  clib_error_t *error = NULL;
521 
522  /* Get a line of input. */
523  if (!unformat_user (input, unformat_line_input, line_input))
524  return 0;
525 
526  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
527  {
528  if (unformat
529  (line_input, "ip4-pfx %U/%d", unformat_ip4_address, &ip4_prefix,
530  &ip4_prefix_len))
531  num_m_args++;
532  else
533  if (unformat
534  (line_input, "ip6-pfx %U/%d", unformat_ip6_address, &ip6_prefix,
535  &ip6_prefix_len))
536  num_m_args++;
537  else
538  if (unformat
539  (line_input, "ip6-src %U/%d", unformat_ip6_address, &ip6_src,
540  &ip6_src_len))
541  num_m_args++;
542  else
543  if (unformat
544  (line_input, "ip6-src %U", unformat_ip6_address, &ip6_src))
545  num_m_args++;
546  else if (unformat (line_input, "ea-bits-len %d", &ea_bits_len))
547  num_m_args++;
548  else if (unformat (line_input, "psid-offset %d", &psid_offset))
549  num_m_args++;
550  else if (unformat (line_input, "psid-len %d", &psid_length))
551  num_m_args++;
552  else if (unformat (line_input, "mtu %d", &mtu))
553  num_m_args++;
554  else if (unformat (line_input, "tag %v", &tag))
555  ;
556  else
557  {
558  error = clib_error_return (0, "unknown input `%U'",
559  format_unformat_error, line_input);
560  goto done;
561  }
562  }
563 
564  if (num_m_args < 3)
565  {
566  error = clib_error_return (0, "mandatory argument(s) missing");
567  goto done;
568  }
569 
570  map_create_domain (&ip4_prefix, ip4_prefix_len,
571  &ip6_prefix, ip6_prefix_len, &ip6_src, ip6_src_len,
572  ea_bits_len, psid_offset, psid_length, &map_domain_index,
573  mtu, flags, tag);
574 
575 done:
576  unformat_free (line_input);
577 
578  return error;
579 }
580 
581 static clib_error_t *
583  unformat_input_t * input, vlib_cli_command_t * cmd)
584 {
585  unformat_input_t _line_input, *line_input = &_line_input;
586  u32 num_m_args = 0;
587  u32 map_domain_index;
588  clib_error_t *error = NULL;
589 
590  /* Get a line of input. */
591  if (!unformat_user (input, unformat_line_input, line_input))
592  return 0;
593 
594  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
595  {
596  if (unformat (line_input, "index %d", &map_domain_index))
597  num_m_args++;
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 (num_m_args != 1)
607  {
608  error = clib_error_return (0, "mandatory argument(s) missing");
609  goto done;
610  }
611 
612  map_delete_domain (map_domain_index);
613 
614 done:
615  unformat_free (line_input);
616 
617  return error;
618 }
619 
620 static clib_error_t *
622  unformat_input_t * input, vlib_cli_command_t * cmd)
623 {
624  unformat_input_t _line_input, *line_input = &_line_input;
625  ip6_address_t tep;
626  u32 num_m_args = 0;
627  u32 psid = 0, map_domain_index;
628  clib_error_t *error = NULL;
629 
630  /* Get a line of input. */
631  if (!unformat_user (input, unformat_line_input, line_input))
632  return 0;
633 
634  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
635  {
636  if (unformat (line_input, "index %d", &map_domain_index))
637  num_m_args++;
638  else if (unformat (line_input, "psid %d", &psid))
639  num_m_args++;
640  else
641  if (unformat (line_input, "ip6-dst %U", unformat_ip6_address, &tep))
642  num_m_args++;
643  else
644  {
645  error = clib_error_return (0, "unknown input `%U'",
646  format_unformat_error, line_input);
647  goto done;
648  }
649  }
650 
651  if (num_m_args != 3)
652  {
653  error = clib_error_return (0, "mandatory argument(s) missing");
654  goto done;
655  }
656 
657  if (map_add_del_psid (map_domain_index, psid, &tep, 1) != 0)
658  {
659  error = clib_error_return (0, "Failing to add Mapping Rule");
660  goto done;
661  }
662 
663 done:
664  unformat_free (line_input);
665 
666  return error;
667 }
668 
669 #if MAP_SKIP_IP6_LOOKUP
670 static clib_error_t *
672  unformat_input_t * input,
673  vlib_cli_command_t * cmd)
674 {
675  unformat_input_t _line_input, *line_input = &_line_input;
676  ip4_address_t ip4nh, *p_v4 = NULL;
677  ip6_address_t ip6nh, *p_v6 = NULL;
678  clib_error_t *error = NULL;
679  bool is_del = false;
680 
681  clib_memset (&ip4nh, 0, sizeof (ip4nh));
682  clib_memset (&ip6nh, 0, sizeof (ip6nh));
683 
684  /* Get a line of input. */
685  if (!unformat_user (input, unformat_line_input, line_input))
686  return 0;
687 
688  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
689  {
690  if (unformat (line_input, "ip4-nh %U", unformat_ip4_address, &ip4nh))
691  p_v4 = &ip4nh;
692  else
693  if (unformat (line_input, "ip6-nh %U", unformat_ip6_address, &ip6nh))
694  p_v6 = &ip6nh;
695  else if (unformat (line_input, "del"))
696  is_del = true;
697  else
698  {
699  error = clib_error_return (0, "unknown input `%U'",
700  format_unformat_error, line_input);
701  goto done;
702  }
703  }
704 
705  map_pre_resolve (p_v4, p_v6, is_del);
706 
707 done:
708  unformat_free (line_input);
709 
710  return error;
711 }
712 #endif
713 
714 static clib_error_t *
716  unformat_input_t * input,
717  vlib_cli_command_t * cmd)
718 {
719  unformat_input_t _line_input, *line_input = &_line_input;
720  ip4_address_t icmp_src_address;
721  ip4_address_t *p_icmp_addr = 0;
722  map_main_t *mm = &map_main;
723  clib_error_t *error = NULL;
724 
725  mm->icmp4_src_address.as_u32 = 0;
726 
727  /* Get a line of input. */
728  if (!unformat_user (input, unformat_line_input, line_input))
729  return 0;
730 
731  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
732  {
733  if (unformat
734  (line_input, "%U", unformat_ip4_address, &icmp_src_address))
735  {
736  mm->icmp4_src_address = icmp_src_address;
737  p_icmp_addr = &icmp_src_address;
738  }
739  else
740  {
741  error = clib_error_return (0, "unknown input `%U'",
742  format_unformat_error, line_input);
743  goto done;
744  }
745  }
746 
747  map_param_set_icmp (p_icmp_addr);
748 
749 done:
750  unformat_free (line_input);
751 
752  return error;
753 }
754 
755 static clib_error_t *
757  unformat_input_t * input,
758  vlib_cli_command_t * cmd)
759 {
760  unformat_input_t _line_input, *line_input = &_line_input;
761  int num_m_args = 0;
762  clib_error_t *error = NULL;
763  bool enabled = false;
764 
765  /* Get a line of input. */
766  if (!unformat_user (input, unformat_line_input, line_input))
767  return 0;
768 
769  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
770  {
771  num_m_args++;
772  if (unformat (line_input, "on"))
773  enabled = true;
774  else if (unformat (line_input, "off"))
775  enabled = false;
776  else
777  {
778  error = clib_error_return (0, "unknown input `%U'",
779  format_unformat_error, line_input);
780  goto done;
781  }
782  }
783 
784 
785  if (num_m_args != 1)
786  error = clib_error_return (0, "mandatory argument(s) missing");
787 
788 
789  map_param_set_icmp6 (enabled);
790 
791 done:
792  unformat_free (line_input);
793 
794  return error;
795 }
796 
797 
798 static clib_error_t *
800  unformat_input_t * input, vlib_cli_command_t * cmd)
801 {
802  unformat_input_t _line_input, *line_input = &_line_input;
803  clib_error_t *error = NULL;
804  bool frag_inner = false;
805  bool frag_ignore_df = false;
806  bool saw_in_out = false;
807  bool saw_df = false;
808 
809  /* Get a line of input. */
810  if (!unformat_user (input, unformat_line_input, line_input))
811  return 0;
812 
813  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
814  {
815  if (unformat (line_input, "inner"))
816  {
817  frag_inner = true;
818  saw_in_out = true;
819  }
820  else if (unformat (line_input, "outer"))
821  {
822  frag_inner = false;
823  saw_in_out = true;
824  }
825  else if (unformat (line_input, "ignore-df"))
826  {
827  frag_ignore_df = true;
828  saw_df = true;
829  }
830  else if (unformat (line_input, "honor-df"))
831  {
832  frag_ignore_df = false;
833  saw_df = true;
834  }
835  else
836  {
837  error = clib_error_return (0, "unknown input `%U'",
838  format_unformat_error, line_input);
839  goto done;
840  }
841  }
842 
843  if (!saw_in_out)
844  {
845  error = clib_error_return (0, "Must specify 'inner' or 'outer'");
846  goto done;
847  }
848 
849  if (!saw_df)
850  {
851  error = clib_error_return (0, "Must specify 'ignore-df' or 'honor-df'");
852  goto done;
853  }
854 
855  map_param_set_fragmentation (frag_inner, frag_ignore_df);
856 
857 done:
858  unformat_free (line_input);
859 
860  return error;
861 }
862 
863 static clib_error_t *
865  unformat_input_t * input,
866  vlib_cli_command_t * cmd)
867 {
868  unformat_input_t _line_input, *line_input = &_line_input;
869  u32 tc = 0;
870  clib_error_t *error = NULL;
871  bool tc_copy = false;
872 
873 
874  /* Get a line of input. */
875  if (!unformat_user (input, unformat_line_input, line_input))
876  return 0;
877 
878  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
879  {
880  if (unformat (line_input, "copy"))
881  tc_copy = true;
882  else if (unformat (line_input, "%x", &tc))
883  tc = tc & 0xff;
884  else
885  {
886  error = clib_error_return (0, "unknown input `%U'",
887  format_unformat_error, line_input);
888  goto done;
889  }
890  }
891 
892  map_param_set_traffic_class (tc_copy, tc);
893 
894 done:
895  unformat_free (line_input);
896 
897  return error;
898 }
899 
900 static char *
902 {
903  if (flags & MAP_DOMAIN_PREFIX)
904  return "prefix";
905  return "";
906 }
907 
908 static u8 *
909 format_map_domain (u8 * s, va_list * args)
910 {
911  map_domain_t *d = va_arg (*args, map_domain_t *);
912  bool counters = va_arg (*args, int);
913  map_main_t *mm = &map_main;
915  u32 map_domain_index = d - mm->domains;
916  map_domain_extra_t *de = 0;
917 
918  if (d->rules)
919  clib_memset (&ip6_prefix, 0, sizeof (ip6_prefix));
920  else
921  ip6_prefix = d->ip6_prefix;
922 
923  if (map_domain_index < vec_len (mm->domain_extras))
924  de = vec_elt_at_index (mm->domain_extras, map_domain_index);
925 
926  s = format (s,
927  "[%d] tag {%s} ip4-pfx %U/%d ip6-pfx %U/%d ip6-src %U/%d "
928  "ea-bits-len %d psid-offset %d psid-len %d mtu %d %s",
929  map_domain_index, (de && de->tag) ? de->tag : (u8 *) "[no-tag]",
931  format_ip6_address, &ip6_prefix, d->ip6_prefix_len,
933  d->ea_bits_len, d->psid_offset, d->psid_length, d->mtu,
935 
936  if (counters)
937  {
939  vlib_counter_t v;
941  map_domain_index, &v);
942  s = format (s, " TX: %lld/%lld", v.packets, v.bytes);
944  map_domain_index, &v);
945  s = format (s, " RX: %lld/%lld", v.packets, v.bytes);
947  }
948  s = format (s, "\n");
949 
950  if (d->rules)
951  {
952  int i;
954  for (i = 0; i < (0x1 << d->psid_length); i++)
955  {
956  dst = d->rules[i];
957  if (dst.as_u64[0] == 0 && dst.as_u64[1] == 0)
958  continue;
959  s = format (s,
960  " rule psid: %d ip6-dst %U\n", i, format_ip6_address,
961  &dst);
962  }
963  }
964  return s;
965 }
966 
967 static clib_error_t *
969  vlib_cli_command_t * cmd)
970 {
971  unformat_input_t _line_input, *line_input = &_line_input;
972  map_main_t *mm = &map_main;
973  map_domain_t *d;
974  bool counters = false;
975  u32 map_domain_index = ~0;
976  clib_error_t *error = NULL;
977 
978  /* Get a line of input. */
979  if (!unformat_user (input, unformat_line_input, line_input))
980  {
981  /* *INDENT-OFF* */
982  pool_foreach(d, mm->domains,
983  ({vlib_cli_output(vm, "%U", format_map_domain, d, counters);}));
984  /* *INDENT-ON* */
985  return 0;
986  }
987 
988  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
989  {
990  if (unformat (line_input, "counters"))
991  counters = true;
992  else if (unformat (line_input, "index %d", &map_domain_index))
993  ;
994  else
995  {
996  error = clib_error_return (0, "unknown input `%U'",
997  format_unformat_error, line_input);
998  goto done;
999  }
1000  }
1001 
1002  if (pool_elts (mm->domains) == 0)
1003  {
1004  vlib_cli_output (vm, "No MAP domains are configured...");
1005  goto done;
1006  }
1007 
1008  if (map_domain_index == ~0)
1009  {
1010  /* *INDENT-OFF* */
1011  pool_foreach(d, mm->domains,
1012  ({vlib_cli_output(vm, "%U", format_map_domain, d, counters);}));
1013  /* *INDENT-ON* */
1014  }
1015  else
1016  {
1017  if (pool_is_free_index (mm->domains, map_domain_index))
1018  {
1019  error = clib_error_return (0, "MAP domain does not exists %d",
1020  map_domain_index);
1021  goto done;
1022  }
1023 
1024  d = pool_elt_at_index (mm->domains, map_domain_index);
1025  vlib_cli_output (vm, "%U", format_map_domain, d, counters);
1026  }
1027 
1028 done:
1029  unformat_free (line_input);
1030 
1031  return error;
1032 }
1033 
1034 u64
1035 map_error_counter_get (u32 node_index, map_error_t map_error)
1036 {
1038  vlib_node_runtime_t *error_node = vlib_node_get_runtime (vm, node_index);
1039  vlib_error_main_t *em = &vm->error_main;
1040  vlib_error_t e = error_node->errors[map_error];
1041  vlib_node_t *n = vlib_get_node (vm, node_index);
1042  u32 ci;
1043 
1044  ci = vlib_error_get_code (&vm->node_main, e);
1045  ASSERT (ci < n->n_errors);
1046  ci += n->error_heap_index;
1047 
1048  return (em->counters[ci]);
1049 }
1050 
1051 static clib_error_t *
1053  vlib_cli_command_t * cmd)
1054 {
1055  map_main_t *mm = &map_main;
1056  map_domain_t *d;
1057  int domains = 0, rules = 0, domaincount = 0, rulecount = 0;
1058  if (pool_elts (mm->domains) == 0)
1059  {
1060  vlib_cli_output (vm, "No MAP domains are configured...");
1061  return 0;
1062  }
1063 
1064  /* *INDENT-OFF* */
1065  pool_foreach(d, mm->domains, ({
1066  if (d->rules) {
1067  rulecount+= 0x1 << d->psid_length;
1068  rules += sizeof(ip6_address_t) * 0x1 << d->psid_length;
1069  }
1070  domains += sizeof(*d);
1071  domaincount++;
1072  }));
1073  /* *INDENT-ON* */
1074 
1075  vlib_cli_output (vm, "MAP domains structure: %d\n", sizeof (map_domain_t));
1076  vlib_cli_output (vm, "MAP domains: %d (%d bytes)\n", domaincount, domains);
1077  vlib_cli_output (vm, "MAP rules: %d (%d bytes)\n", rulecount, rules);
1078  vlib_cli_output (vm, "Total: %d bytes)\n", rules + domains);
1079 
1080 #if MAP_SKIP_IP6_LOOKUP
1082  "MAP pre-resolve: IP6 next-hop: %U, IP4 next-hop: %U\n",
1083  format_map_pre_resolve, &pre_resolved[FIB_PROTOCOL_IP6],
1084  format_map_pre_resolve, &pre_resolved[FIB_PROTOCOL_IP4]);
1085 
1086 #endif
1087 
1088  if (mm->tc_copy)
1089  vlib_cli_output (vm, "MAP traffic-class: copy");
1090  else
1091  vlib_cli_output (vm, "MAP traffic-class: %x", mm->tc);
1092 
1093  if (mm->tcp_mss)
1094  vlib_cli_output (vm, "MAP TCP MSS clamping: %u", mm->tcp_mss);
1095 
1097  "MAP IPv6 inbound security check: %s, fragmented packet security check: %s",
1098  mm->sec_check ? "enabled" : "disabled",
1099  mm->sec_check_frag ? "enabled" : "disabled");
1100 
1101  vlib_cli_output (vm, "ICMP-relay IPv4 source address: %U\n",
1102  format_ip4_address, &mm->icmp4_src_address);
1103  vlib_cli_output (vm, "ICMP6 unreachables sent for unmatched packets: %s\n",
1104  mm->icmp6_enabled ? "enabled" : "disabled");
1105  vlib_cli_output (vm, "Inner fragmentation: %s\n",
1106  mm->frag_inner ? "enabled" : "disabled");
1107  vlib_cli_output (vm, "Fragment packets regardless of DF flag: %s\n",
1108  mm->frag_ignore_df ? "enabled" : "disabled");
1109 
1110  /*
1111  * Counters
1112  */
1113  vlib_combined_counter_main_t *cm = mm->domain_counters;
1114  u64 total_pkts[MAP_N_DOMAIN_COUNTER];
1115  u64 total_bytes[MAP_N_DOMAIN_COUNTER];
1116  int which, i;
1117  vlib_counter_t v;
1118 
1119  clib_memset (total_pkts, 0, sizeof (total_pkts));
1120  clib_memset (total_bytes, 0, sizeof (total_bytes));
1121 
1123  vec_foreach (cm, mm->domain_counters)
1124  {
1125  which = cm - mm->domain_counters;
1126 
1127  for (i = 0; i < vlib_combined_counter_n_counters (cm); i++)
1128  {
1129  vlib_get_combined_counter (cm, i, &v);
1130  total_pkts[which] += v.packets;
1131  total_bytes[which] += v.bytes;
1132  }
1133  }
1135 
1136  vlib_cli_output (vm, "Encapsulated packets: %lld bytes: %lld\n",
1137  total_pkts[MAP_DOMAIN_COUNTER_TX],
1138  total_bytes[MAP_DOMAIN_COUNTER_TX]);
1139  vlib_cli_output (vm, "Decapsulated packets: %lld bytes: %lld\n",
1140  total_pkts[MAP_DOMAIN_COUNTER_RX],
1141  total_bytes[MAP_DOMAIN_COUNTER_RX]);
1142 
1143  vlib_cli_output (vm, "ICMP relayed packets: %d\n",
1144  vlib_get_simple_counter (&mm->icmp_relayed, 0));
1145 
1146  return 0;
1147 }
1148 
1149 static clib_error_t *
1151  unformat_input_t * input, vlib_cli_command_t * cmd)
1152 {
1153  unformat_input_t _line_input, *line_input = &_line_input;
1154  clib_error_t *error = NULL;
1155  bool is_enable = true, is_translation = false;
1156  vnet_main_t *vnm = vnet_get_main ();
1157  u32 sw_if_index = ~0;
1158 
1159  /* Get a line of input. */
1160  if (!unformat_user (input, unformat_line_input, line_input))
1161  return 0;
1162 
1163  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1164  {
1165  if (unformat
1166  (line_input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
1167  ;
1168  else if (unformat (line_input, "del"))
1169  is_enable = false;
1170  else if (unformat (line_input, "map-t"))
1171  is_translation = true;
1172  else
1173  {
1174  error = clib_error_return (0, "unknown input `%U'",
1175  format_unformat_error, line_input);
1176  goto done;
1177  }
1178  }
1179 
1180 done:
1181  unformat_free (line_input);
1182 
1183  if (sw_if_index == ~0)
1184  {
1185  error = clib_error_return (0, "unknown interface");
1186  return error;
1187  }
1188 
1189  int rv = map_if_enable_disable (is_enable, sw_if_index, is_translation);
1190  if (rv)
1191  {
1192  error = clib_error_return (0, "failure enabling MAP on interface");
1193  }
1194 
1195  return error;
1196 }
1197 
1198 
1199 /*
1200  * packet trace format function
1201  */
1202 u8 *
1203 format_map_trace (u8 * s, va_list * args)
1204 {
1205  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1206  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1207  map_trace_t *t = va_arg (*args, map_trace_t *);
1208  u32 map_domain_index = t->map_domain_index;
1209  u16 port = t->port;
1210 
1211  s =
1212  format (s, "MAP domain index: %d L4 port: %u", map_domain_index,
1213  clib_net_to_host_u16 (port));
1214 
1215  return s;
1216 }
1217 
1218 static clib_error_t *
1220  unformat_input_t * input, vlib_cli_command_t * cmd)
1221 {
1222  unformat_input_t _line_input, *line_input = &_line_input;
1223  clib_error_t *error = NULL;
1224  u32 tcp_mss = 0;
1225 
1226  /* Get a line of input. */
1227  if (!unformat_user (input, unformat_line_input, line_input))
1228  return 0;
1229 
1230  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1231  {
1232  if (unformat (line_input, "%u", &tcp_mss))
1233  ;
1234  else
1235  {
1236  error = clib_error_return (0, "unknown input `%U'",
1237  format_unformat_error, line_input);
1238  goto done;
1239  }
1240  }
1241 
1242  if (tcp_mss >= (0x1 << 16))
1243  {
1244  error = clib_error_return (0, "invalid value `%u'", tcp_mss);
1245  goto done;
1246  }
1247 
1248  map_param_set_tcp (tcp_mss);
1249 
1250 done:
1251  unformat_free (line_input);
1252 
1253  return error;
1254 }
1255 
1256 
1257 /* *INDENT-OFF* */
1258 
1259 /*?
1260  * Set or copy the IP TOS/Traffic Class field
1261  *
1262  * @cliexpar
1263  * @cliexstart{map params traffic-class}
1264  *
1265  * This command is used to set the traffic-class field in translated
1266  * or encapsulated packets. If copy is specifed (the default) then the
1267  * traffic-class/TOS field is copied from the original packet to the
1268  * translated / encapsulating header.
1269  * @cliexend
1270  ?*/
1271 VLIB_CLI_COMMAND(map_traffic_class_command, static) = {
1272  .path = "map params traffic-class",
1273  .short_help = "map params traffic-class {0x0-0xff | copy}",
1274  .function = map_traffic_class_command_fn,
1275 };
1276 
1277 /*?
1278  * TCP MSS clamping
1279  *
1280  * @cliexpar
1281  * @cliexstart{map params tcp-mss}
1282  *
1283  * This command is used to set the TCP MSS in translated
1284  * or encapsulated packets.
1285  * @cliexend
1286  ?*/
1287 VLIB_CLI_COMMAND(map_tcp_mss_command, static) = {
1288  .path = "map params tcp-mss",
1289  .short_help = "map params tcp-mss <value>",
1290  .function = map_tcp_mss_command_fn,
1291 };
1292 
1293 /*?
1294  * Bypass IP4/IP6 lookup
1295  *
1296  * @cliexpar
1297  * @cliexstart{map params pre-resolve}
1298  *
1299  * Bypass a second FIB lookup of the translated or encapsulated
1300  * packet, and forward the packet directly to the specified
1301  * next-hop. This optimization trades forwarding flexibility for
1302  * performance.
1303  * @cliexend
1304  ?*/
1305 VLIB_CLI_COMMAND(map_pre_resolve_command, static) = {
1306  .path = "map params pre-resolve",
1307  .short_help = " map params pre-resolve {ip4-nh <address>} "
1308  "| {ip6-nh <address>}",
1309  .function = map_pre_resolve_command_fn,
1310 };
1311 
1312 /*?
1313  * Enable or disable the MAP-E inbound security check
1314  * Specifiy if the inbound security check should be done on fragments
1315  *
1316  * @cliexpar
1317  * @cliexstart{map params security-check}
1318  *
1319  * By default, a decapsulated packet's IPv4 source address will be
1320  * verified against the outer header's IPv6 source address. Disabling
1321  * this feature will allow IPv4 source address spoofing.
1322  *
1323  * Typically the inbound on-decapsulation security check is only done
1324  * on the first packet. The packet that contains the L4
1325  * information. While a security check on every fragment is possible,
1326  * it has a cost. State must be created on the first fragment.
1327  * @cliexend
1328  ?*/
1329 VLIB_CLI_COMMAND(map_security_check_command, static) = {
1330  .path = "map params security-check",
1331  .short_help = "map params security-check enable|disable fragments on|off",
1332  .function = map_security_check_command_fn,
1333 };
1334 
1335 
1336 /*?
1337  * Specifiy the IPv4 source address used for relayed ICMP error messages
1338  *
1339  * @cliexpar
1340  * @cliexstart{map params icmp source-address}
1341  *
1342  * This command specifies which IPv4 source address (must be local to
1343  * the system), that is used for relayed received IPv6 ICMP error
1344  * messages.
1345  * @cliexend
1346  ?*/
1347 VLIB_CLI_COMMAND(map_icmp_relay_source_address_command, static) = {
1348  .path = "map params icmp source-address",
1349  .short_help = "map params icmp source-address <ip4-address>",
1351 };
1352 
1353 /*?
1354  * Send IPv6 ICMP unreachables
1355  *
1356  * @cliexpar
1357  * @cliexstart{map params icmp6 unreachables}
1358  *
1359  * Send IPv6 ICMP unreachable messages back if security check fails or
1360  * no MAP domain exists.
1361  * @cliexend
1362  ?*/
1363 VLIB_CLI_COMMAND(map_icmp_unreachables_command, static) = {
1364  .path = "map params icmp6 unreachables",
1365  .short_help = "map params icmp6 unreachables {on|off}",
1367 };
1368 
1369 /*?
1370  * Configure MAP fragmentation behaviour
1371  *
1372  * @cliexpar
1373  * @cliexstart{map params fragment}
1374  *
1375  * Allows fragmentation of the IPv4 packet even if the DF bit is
1376  * set. The choice between inner or outer fragmentation of tunnel
1377  * packets is complicated. The benefit of inner fragmentation is that
1378  * the ultimate endpoint must reassemble, instead of the tunnel
1379  * endpoint.
1380  * @cliexend
1381  ?*/
1382 VLIB_CLI_COMMAND(map_fragment_command, static) = {
1383  .path = "map params fragment",
1384  .short_help = "map params fragment inner|outer ignore-df|honor-df",
1385  .function = map_fragment_command_fn,
1386 };
1387 
1388 
1389 /*?
1390  * Add MAP domain
1391  *
1392  * @cliexpar
1393  * @cliexstart{map add domain}
1394  * @cliexend
1395  ?*/
1396 VLIB_CLI_COMMAND(map_add_domain_command, static) = {
1397  .path = "map add domain",
1398  .short_help = "map add domain [tag <tag>] ip4-pfx <ip4-pfx> "
1399  "ip6-pfx <ip6-pfx> "
1400  "ip6-src <ip6-pfx> ea-bits-len <n> psid-offset <n> psid-len <n> "
1401  "[map-t] [mtu <mtu>]",
1402  .function = map_add_domain_command_fn,
1403 };
1404 
1405 /*?
1406  * Add MAP rule to a domain
1407  *
1408  * @cliexpar
1409  * @cliexstart{map add rule}
1410  * @cliexend
1411  ?*/
1412 VLIB_CLI_COMMAND(map_add_rule_command, static) = {
1413  .path = "map add rule",
1414  .short_help = "map add rule index <domain> psid <psid> ip6-dst <ip6-addr>",
1415  .function = map_add_rule_command_fn,
1416 };
1417 
1418 /*?
1419  * Delete MAP domain
1420  *
1421  * @cliexpar
1422  * @cliexstart{map del domain}
1423  * @cliexend
1424  ?*/
1425 VLIB_CLI_COMMAND(map_del_command, static) = {
1426  .path = "map del domain",
1427  .short_help = "map del domain index <domain>",
1428  .function = map_del_domain_command_fn,
1429 };
1430 
1431 /*?
1432  * Show MAP domains
1433  *
1434  * @cliexpar
1435  * @cliexstart{show map domain}
1436  * @cliexend
1437  ?*/
1438 VLIB_CLI_COMMAND(show_map_domain_command, static) = {
1439  .path = "show map domain",
1440  .short_help = "show map domain index <n> [counters]",
1441  .function = show_map_domain_command_fn,
1442 };
1443 
1444 /*?
1445  * Show MAP statistics
1446  *
1447  * @cliexpar
1448  * @cliexstart{show map stats}
1449  * @cliexend
1450  ?*/
1451 VLIB_CLI_COMMAND(show_map_stats_command, static) = {
1452  .path = "show map stats",
1453  .short_help = "show map stats",
1454  .function = show_map_stats_command_fn,
1455 };
1456 
1457 /*?
1458  * Enable MAP processing on interface (input feature)
1459  *
1460  ?*/
1461 VLIB_CLI_COMMAND(map_if_command, static) = {
1462  .path = "map interface",
1463  .short_help = "map interface <interface-name> [map-t] [del]",
1464  .function = map_if_command_fn,
1465 };
1466 
1468  .version = VPP_BUILD_VER,
1469  .description = "Mapping of Address and Port (MAP)",
1470 };
1471 
1472 /* *INDENT-ON* */
1473 
1474 /*
1475  * map_init
1476  */
1477 clib_error_t *
1479 {
1480  map_main_t *mm = &map_main;
1481  clib_error_t *error = 0;
1482 
1483  memset (mm, 0, sizeof (*mm));
1484 
1485  mm->vnet_main = vnet_get_main ();
1486  mm->vlib_main = vm;
1487 
1488 #ifdef MAP_SKIP_IP6_LOOKUP
1490 
1491  FOR_EACH_FIB_PROTOCOL (proto)
1492  {
1493  map_pre_resolve_init (&pre_resolved[proto]);
1494  }
1495 #endif
1496 
1497  /* traffic class */
1498  mm->tc = 0;
1499  mm->tc_copy = true;
1500 
1501  /* Inbound security check */
1502  mm->sec_check = true;
1503  mm->sec_check_frag = false;
1504 
1505  /* ICMP6 Type 1, Code 5 for security check failure */
1506  mm->icmp6_enabled = false;
1507 
1508  /* Inner or outer fragmentation */
1509  mm->frag_inner = false;
1510  mm->frag_ignore_df = false;
1511 
1513  mm->domain_counters[MAP_DOMAIN_COUNTER_RX].name = "/map/rx";
1514  mm->domain_counters[MAP_DOMAIN_COUNTER_TX].name = "/map/tx";
1515 
1518  mm->icmp_relayed.stat_segment_name = "/map/icmp-relayed";
1519 
1520  /* IP6 virtual reassembly */
1521 
1522 #ifdef MAP_SKIP_IP6_LOOKUP
1524 #endif
1525 
1526  /* LPM lookup tables */
1530 
1531  mm->bm_trans_enabled_by_sw_if = 0;
1532  mm->bm_encap_enabled_by_sw_if = 0;
1533 
1534  error = map_plugin_api_hookup (vm);
1535 
1536  return error;
1537 }
1538 
1540 
1541 /*
1542  * fd.io coding-style-patch-verification: ON
1543  *
1544  * Local Variables:
1545  * eval: (c-set-style "gnu")
1546  * End:
1547  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:440
int map_param_set_icmp(ip4_address_t *ip4_err_relay_src)
Definition: map_api.c:271
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
u8 psid_length
Definition: map.h:88
int map_add_del_psid(u32 map_domain_index, u16 psid, ip6_address_t *tep, bool is_add)
Definition: map.c:235
fib_node_index_t fib_entry_track(u32 fib_index, const fib_prefix_t *prefix, fib_node_type_t child_type, index_t child_index, u32 *sibling)
Trackers are used on FIB entries by objects that which to track the changing state of the entry...
lpm_t * lpm_table_init(enum lpm_type_e lpm_type)
Definition: lpm.c:157
u32 error_heap_index
Definition: node.h:325
fib_node_t node
Linkage into the FIB graph.
Definition: map.h:136
u8 proto
Definition: acl_types.api:47
static clib_error_t * map_fragment_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:799
#define CLIB_UNUSED(x)
Definition: clib.h:82
int map_delete_domain(u32 map_domain_index)
Definition: map.c:204
map_domain_flags_e flags
Definition: map.h:83
map_main_t map_main
Definition: map.c:27
void vlib_validate_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
validate a combined counter
Definition: counter.c:94
static fib_node_t * map_fib_node_get(fib_node_index_t index)
Function definition to get a FIB node from its index.
Definition: map.c:361
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
int map_if_enable_disable(bool is_enable, u32 sw_if_index, bool is_translation)
Definition: map_api.c:449
void fib_node_init(fib_node_t *node, fib_node_type_t type)
Definition: fib_node.c:185
u64 as_u64[2]
Definition: ip6_packet.h:51
unsigned long u64
Definition: types.h:89
map_error_t
Definition: map.h:230
dpo_id_t dpo
The Load-balance object index to use to forward.
Definition: map.h:151
#define NULL
Definition: clib.h:58
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static u8 * format_map_domain(u8 *s, va_list *args)
Definition: map.c:909
static clib_error_t * show_map_domain_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:968
static clib_error_t * map_security_check_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:437
u64 map_error_counter_get(u32 node_index, map_error_t map_error)
Definition: map.c:1035
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function.
const dpo_id_t * fib_entry_contribute_ip_forwarding(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:506
vlib_main_t * vlib_main
Definition: map.h:190
u8 tc
Definition: map.h:176
static void map_fib_resolve(map_main_pre_resolved_t *pr, fib_protocol_t proto, u8 len, const ip46_address_t *addr)
Definition: map.c:377
static void map_free_extras(u32 map_domain_index)
Definition: map.c:88
A pre-resolved next-hop.
Definition: map.h:131
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:262
manual_print typedef ip4_prefix
Definition: ip_types.api:106
static void map_domain_counter_unlock(map_main_t *mm)
Definition: map.h:411
Combined counter to hold both packets and byte differences.
Definition: counter_types.h:26
u16 vlib_error_t
Definition: error.h:43
int i
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
u32 suffix_mask
Definition: map.h:79
bool sec_check_frag
Definition: map.h:180
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:65
const fib_prefix_t * fib_entry_get_prefix(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:1691
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
unformat_function_t unformat_vnet_sw_interface
int map_create_domain(ip4_address_t *ip4_prefix, u8 ip4_prefix_len, ip6_address_t *ip6_prefix, u8 ip6_prefix_len, ip6_address_t *ip6_src, u8 ip6_src_len, u8 ea_bits_len, u8 psid_offset, u8 psid_length, u32 *map_domain_index, u16 mtu, u8 flags, u8 *tag)
Definition: map.c:105
uword * bm_trans_enabled_by_sw_if
Definition: map.h:197
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:470
void map_pre_resolve(ip4_address_t *ip4, ip6_address_t *ip6, bool is_del)
Definition: map.c:407
vhost_vring_addr_t addr
Definition: vhost_user.h:147
unsigned char u8
Definition: types.h:56
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
u16 port
Definition: map.h:243
void fib_node_register_type(fib_node_type_t type, const fib_node_vft_t *vft)
fib_node_register_type
Definition: fib_node.c:60
static counter_t vlib_get_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Get the value of a simple counter Scrapes the entire set of per-thread counters.
Definition: counter.h:113
format_function_t format_ip4_address
Definition: format.h:73
manual_print typedef ip6_prefix
Definition: ip_types.api:101
bool tc_copy
Definition: map.h:177
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:498
unformat_function_t unformat_ip4_address
Definition: format.h:68
void(* add)(struct lpm_ *lpm, void *addr_v, u8 pfxlen, u32 value)
Definition: lpm.h:25
static clib_error_t * map_pre_resolve_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:671
vl_api_interface_index_t sw_if_index
Definition: gre.api:59
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
static clib_error_t * map_icmp_unreachables_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:756
vlib_combined_counter_main_t * domain_counters
Definition: map.h:169
ip4_address_t icmp4_src_address
Definition: map.h:186
static clib_error_t * map_add_domain_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:505
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Aggregate type for a prefix.
Definition: fib_types.h:203
#define clib_error_return(e, args...)
Definition: error.h:99
vlib_simple_counter_main_t icmp_relayed
Definition: map.h:187
ip6_address_t * rules
Definition: map.h:78
u8 ea_bits_len
Definition: map.h:86
unsigned int u32
Definition: types.h:88
u8 ip6_prefix_len
Definition: map.h:84
unformat_function_t unformat_line_input
Definition: format.h:283
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:170
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:519
static void vlib_zero_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
Clear a combined counter Clears the set of per-thread counters.
Definition: counter.h:285
counter_t packets
packet counter
Definition: counter_types.h:28
static clib_error_t * map_if_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:1150
static clib_error_t * map_add_rule_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:621
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:226
static clib_error_t * map_tcp_mss_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:1219
vlib_error_main_t error_main
Definition: main.h:179
static map_main_pre_resolved_t * map_from_fib_node(fib_node_t *node)
Definition: map.c:328
bool frag_ignore_df
Definition: map.h:194
long ctx[MAX_CONNS]
Definition: main.c:144
int map_param_set_traffic_class(bool copy, u8 tc)
Definition: map_api.c:360
u32 vlib_combined_counter_n_counters(const vlib_combined_counter_main_t *cm)
The number of counters (not the number of per-thread counters)
Definition: counter.c:109
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
map_domain_t * domains
Definition: map.h:164
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:287
#define FOR_EACH_FIB_PROTOCOL(_item)
Definition: fib_types.h:65
fib_node_type_t fn_type
The node&#39;s type.
Definition: fib_node.h:299
An node in the FIB graph.
Definition: fib_node.h:295
vl_api_address_t dst
Definition: gre.api:61
u8 ip6_src_len
Definition: map.h:85
u8 psid_shift
Definition: map.h:91
vlib_main_t * vm
Definition: in2out_ed.c:1810
u8 suffix_shift
Definition: map.h:92
static u32 vlib_error_get_code(vlib_node_main_t *nm, vlib_error_t e)
Definition: node.h:779
u8 len
Definition: ip_types.api:91
format_function_t format_ip46_address
Definition: ip46_address.h:50
unformat_function_t unformat_ip6_address
Definition: format.h:89
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P with alignment A.
Definition: pool.h:231
u64 * counters
Definition: error.h:48
u8 ip6[16]
Definition: one.api:477
lpm_t * ip6_src_prefix_tbl
Definition: map.h:203
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
u32 flags
Definition: vhost_user.h:141
ip4_address_t ip4_prefix
Definition: map.h:80
format_function_t format_ip6_address
Definition: format.h:91
static void vlib_get_combined_counter(const vlib_combined_counter_main_t *cm, u32 index, vlib_counter_t *result)
Get the value of a combined counter, never called in the speed path Scrapes the entire set of per-thr...
Definition: counter.h:259
uword * bm_encap_enabled_by_sw_if
Definition: map.h:198
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:342
u8 psid_offset
Definition: map.h:87
static clib_error_t * map_icmp_relay_source_address_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:715
#define clib_warning(format, args...)
Definition: error.h:59
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:89
fib_node_get_t fnv_get
Definition: fib_node.h:283
bool icmp6_enabled
Definition: map.h:181
int map_param_set_fragmentation(bool inner, bool ignore_df)
Definition: map_api.c:246
u32 sibling
This object sibling index on the FIB entry&#39;s child dependency list.
Definition: map.h:146
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:284
static void map_pre_resolve_init(map_main_pre_resolved_t *pr)
Definition: map.c:286
ip6_address_t ip6_src
Definition: map.h:76
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1810
static clib_error_t * map_del_domain_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:582
static void map_domain_counter_lock(map_main_t *mm)
Definition: map.h:403
Context passed between object during a back walk.
Definition: fib_node.h:208
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
#define vec_validate_init_c_string(V, S, L)
Make a vector containing a NULL terminated c-string.
Definition: vec.h:994
vl_api_gbp_rule_t rules[n_rules]
Definition: gbp.api:315
static void map_save_extras(u32 map_domain_index, u8 *tag)
Definition: map.c:68
void vlib_validate_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
validate a simple counter
Definition: counter.c:79
#define ASSERT(truth)
void fib_entry_untrack(fib_node_index_t fei, u32 sibling)
Stop tracking a FIB entry.
bool sec_check
Definition: map.h:179
bool frag_inner
Definition: map.h:193
u16 psid_mask
Definition: map.h:81
static void clib_mem_free(void *p)
Definition: mem.h:226
static void vlib_zero_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Clear a simple counter Clears the set of per-thread u16 counters, and the u64 counter.
Definition: counter.h:139
u8 * format_map_trace(u8 *s, va_list *args)
Definition: map.c:1203
void(* delete)(struct lpm_ *lpm, void *addr_v, u8 pfxlen)
Definition: lpm.h:26
u8 ea_shift
Definition: map.h:93
static u8 * format_map_pre_resolve(u8 *s, va_list *ap)
Definition: map.c:293
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
ip6_address_t ip6_prefix
Definition: map.h:77
VLIB_PLUGIN_REGISTER()
static clib_error_t * map_traffic_class_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:864
counter_t bytes
byte counter
Definition: counter_types.h:29
vnet_main_t * vnet_main
Definition: map.h:191
int map_param_set_security_check(bool enable, bool fragments)
Definition: map_api.c:335
char * stat_segment_name
Name in stat segment directory.
Definition: counter.h:65
u16 mtu
Definition: map.h:82
int map_param_set_icmp6(u8 enable_unreachable)
Definition: map_api.c:298
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:186
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:31
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
clib_error_t * map_plugin_api_hookup(vlib_main_t *vm)
Definition: map_api.c:524
fib_node_index_t fei
The FIB entry index of the next-hop.
Definition: map.h:141
vlib_node_main_t node_main
Definition: main.h:158
map_domain_extra_t * domain_extras
Definition: map.h:165
static void unformat_free(unformat_input_t *i)
Definition: format.h:163
char * name
The counter collection&#39;s name.
Definition: counter.h:193
lpm_t * ip4_prefix_tbl
Definition: map.h:201
A collection of combined counters.
Definition: counter.h:188
u16 port
Definition: lb_types.api:72
#define FIB_PROTOCOL_MAX
Definition outside of enum so it does not need to be included in non-defaulted switch statements...
Definition: fib_types.h:52
u8 ip4_prefix_len
Definition: map.h:96
A FIB graph nodes virtual function table.
Definition: fib_node.h:282
vlib_simple_counter_main_t * simple_domain_counters
Definition: map.h:168
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:161
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
int map_param_set_tcp(u16 tcp_mss)
Definition: map_api.c:385
static fib_node_back_walk_rc_t map_back_walk(fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
Function definition to backwalk a FIB node.
Definition: map.c:350
static void map_stack(map_main_pre_resolved_t *pr)
Definition: map.c:337
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:59
static void map_last_lock_gone(fib_node_t *node)
Function definition to inform the FIB node that its last lock has gone.
Definition: map.c:318
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:232
#define vec_foreach(var, vec)
Vector iterator.
u32 map_domain_index
Definition: map.h:242
u32 ip4
Definition: one.api:440
static char * map_flags_to_string(u32 flags)
Definition: map.c:901
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
lpm_t * ip6_prefix_tbl
Definition: map.h:202
clib_error_t * map_init(vlib_main_t *vm)
Definition: map.c:1478
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
static void map_fib_unresolve(map_main_pre_resolved_t *pr, fib_protocol_t proto, u8 len, const ip46_address_t *addr)
Definition: map.c:392
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
static clib_error_t * show_map_stats_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:1052
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128