FD.io VPP  v21.01
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,
107  ip6_address_t * ip6_prefix,
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
407 map_pre_resolve (ip4_address_t * ip4, ip6_address_t * ip6, bool is_del)
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;
510  ip6_address_t ip6_prefix;
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 %s", &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  vec_free (tag);
577  unformat_free (line_input);
578 
579  return error;
580 }
581 
582 static clib_error_t *
584  unformat_input_t * input, vlib_cli_command_t * cmd)
585 {
586  unformat_input_t _line_input, *line_input = &_line_input;
587  u32 num_m_args = 0;
588  u32 map_domain_index;
589  clib_error_t *error = NULL;
590 
591  /* Get a line of input. */
592  if (!unformat_user (input, unformat_line_input, line_input))
593  return 0;
594 
595  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
596  {
597  if (unformat (line_input, "index %d", &map_domain_index))
598  num_m_args++;
599  else
600  {
601  error = clib_error_return (0, "unknown input `%U'",
602  format_unformat_error, line_input);
603  goto done;
604  }
605  }
606 
607  if (num_m_args != 1)
608  {
609  error = clib_error_return (0, "mandatory argument(s) missing");
610  goto done;
611  }
612 
613  map_delete_domain (map_domain_index);
614 
615 done:
616  unformat_free (line_input);
617 
618  return error;
619 }
620 
621 static clib_error_t *
623  unformat_input_t * input, vlib_cli_command_t * cmd)
624 {
625  unformat_input_t _line_input, *line_input = &_line_input;
626  ip6_address_t tep;
627  u32 num_m_args = 0;
628  u32 psid = 0, map_domain_index;
629  clib_error_t *error = NULL;
630 
631  /* Get a line of input. */
632  if (!unformat_user (input, unformat_line_input, line_input))
633  return 0;
634 
635  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
636  {
637  if (unformat (line_input, "index %d", &map_domain_index))
638  num_m_args++;
639  else if (unformat (line_input, "psid %d", &psid))
640  num_m_args++;
641  else
642  if (unformat (line_input, "ip6-dst %U", unformat_ip6_address, &tep))
643  num_m_args++;
644  else
645  {
646  error = clib_error_return (0, "unknown input `%U'",
647  format_unformat_error, line_input);
648  goto done;
649  }
650  }
651 
652  if (num_m_args != 3)
653  {
654  error = clib_error_return (0, "mandatory argument(s) missing");
655  goto done;
656  }
657 
658  if (map_add_del_psid (map_domain_index, psid, &tep, 1) != 0)
659  {
660  error = clib_error_return (0, "Failing to add Mapping Rule");
661  goto done;
662  }
663 
664 done:
665  unformat_free (line_input);
666 
667  return error;
668 }
669 
670 #if MAP_SKIP_IP6_LOOKUP
671 static clib_error_t *
673  unformat_input_t * input,
674  vlib_cli_command_t * cmd)
675 {
676  unformat_input_t _line_input, *line_input = &_line_input;
677  ip4_address_t ip4nh, *p_v4 = NULL;
678  ip6_address_t ip6nh, *p_v6 = NULL;
679  clib_error_t *error = NULL;
680  bool is_del = false;
681 
682  clib_memset (&ip4nh, 0, sizeof (ip4nh));
683  clib_memset (&ip6nh, 0, sizeof (ip6nh));
684 
685  /* Get a line of input. */
686  if (!unformat_user (input, unformat_line_input, line_input))
687  return 0;
688 
689  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
690  {
691  if (unformat (line_input, "ip4-nh %U", unformat_ip4_address, &ip4nh))
692  p_v4 = &ip4nh;
693  else
694  if (unformat (line_input, "ip6-nh %U", unformat_ip6_address, &ip6nh))
695  p_v6 = &ip6nh;
696  else if (unformat (line_input, "del"))
697  is_del = true;
698  else
699  {
700  error = clib_error_return (0, "unknown input `%U'",
701  format_unformat_error, line_input);
702  goto done;
703  }
704  }
705 
706  map_pre_resolve (p_v4, p_v6, is_del);
707 
708 done:
709  unformat_free (line_input);
710 
711  return error;
712 }
713 #endif
714 
715 static clib_error_t *
717  unformat_input_t * input,
718  vlib_cli_command_t * cmd)
719 {
720  unformat_input_t _line_input, *line_input = &_line_input;
721  ip4_address_t icmp_src_address;
722  ip4_address_t *p_icmp_addr = 0;
723  map_main_t *mm = &map_main;
724  clib_error_t *error = NULL;
725 
726  mm->icmp4_src_address.as_u32 = 0;
727 
728  /* Get a line of input. */
729  if (!unformat_user (input, unformat_line_input, line_input))
730  return 0;
731 
732  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
733  {
734  if (unformat
735  (line_input, "%U", unformat_ip4_address, &icmp_src_address))
736  {
737  mm->icmp4_src_address = icmp_src_address;
738  p_icmp_addr = &icmp_src_address;
739  }
740  else
741  {
742  error = clib_error_return (0, "unknown input `%U'",
743  format_unformat_error, line_input);
744  goto done;
745  }
746  }
747 
748  map_param_set_icmp (p_icmp_addr);
749 
750 done:
751  unformat_free (line_input);
752 
753  return error;
754 }
755 
756 static clib_error_t *
758  unformat_input_t * input,
759  vlib_cli_command_t * cmd)
760 {
761  unformat_input_t _line_input, *line_input = &_line_input;
762  int num_m_args = 0;
763  clib_error_t *error = NULL;
764  bool enabled = false;
765 
766  /* Get a line of input. */
767  if (!unformat_user (input, unformat_line_input, line_input))
768  return 0;
769 
770  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
771  {
772  num_m_args++;
773  if (unformat (line_input, "on"))
774  enabled = true;
775  else if (unformat (line_input, "off"))
776  enabled = false;
777  else
778  {
779  error = clib_error_return (0, "unknown input `%U'",
780  format_unformat_error, line_input);
781  goto done;
782  }
783  }
784 
785 
786  if (num_m_args != 1)
787  error = clib_error_return (0, "mandatory argument(s) missing");
788 
789 
790  map_param_set_icmp6 (enabled);
791 
792 done:
793  unformat_free (line_input);
794 
795  return error;
796 }
797 
798 
799 static clib_error_t *
801  unformat_input_t * input, vlib_cli_command_t * cmd)
802 {
803  unformat_input_t _line_input, *line_input = &_line_input;
804  clib_error_t *error = NULL;
805  bool frag_inner = false;
806  bool frag_ignore_df = false;
807  bool saw_in_out = false;
808  bool saw_df = false;
809 
810  /* Get a line of input. */
811  if (!unformat_user (input, unformat_line_input, line_input))
812  return 0;
813 
814  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
815  {
816  if (unformat (line_input, "inner"))
817  {
818  frag_inner = true;
819  saw_in_out = true;
820  }
821  else if (unformat (line_input, "outer"))
822  {
823  frag_inner = false;
824  saw_in_out = true;
825  }
826  else if (unformat (line_input, "ignore-df"))
827  {
828  frag_ignore_df = true;
829  saw_df = true;
830  }
831  else if (unformat (line_input, "honor-df"))
832  {
833  frag_ignore_df = false;
834  saw_df = true;
835  }
836  else
837  {
838  error = clib_error_return (0, "unknown input `%U'",
839  format_unformat_error, line_input);
840  goto done;
841  }
842  }
843 
844  if (!saw_in_out)
845  {
846  error = clib_error_return (0, "Must specify 'inner' or 'outer'");
847  goto done;
848  }
849 
850  if (!saw_df)
851  {
852  error = clib_error_return (0, "Must specify 'ignore-df' or 'honor-df'");
853  goto done;
854  }
855 
856  map_param_set_fragmentation (frag_inner, frag_ignore_df);
857 
858 done:
859  unformat_free (line_input);
860 
861  return error;
862 }
863 
864 static clib_error_t *
866  unformat_input_t * input,
867  vlib_cli_command_t * cmd)
868 {
869  unformat_input_t _line_input, *line_input = &_line_input;
870  u32 tc = 0;
871  clib_error_t *error = NULL;
872  bool tc_copy = false;
873 
874 
875  /* Get a line of input. */
876  if (!unformat_user (input, unformat_line_input, line_input))
877  return 0;
878 
879  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
880  {
881  if (unformat (line_input, "copy"))
882  tc_copy = true;
883  else if (unformat (line_input, "%x", &tc))
884  tc = tc & 0xff;
885  else
886  {
887  error = clib_error_return (0, "unknown input `%U'",
888  format_unformat_error, line_input);
889  goto done;
890  }
891  }
892 
893  map_param_set_traffic_class (tc_copy, tc);
894 
895 done:
896  unformat_free (line_input);
897 
898  return error;
899 }
900 
901 static char *
903 {
904  if (flags & MAP_DOMAIN_PREFIX)
905  return "prefix";
906  return "";
907 }
908 
909 static u8 *
910 format_map_domain (u8 * s, va_list * args)
911 {
912  map_domain_t *d = va_arg (*args, map_domain_t *);
913  bool counters = va_arg (*args, int);
914  map_main_t *mm = &map_main;
915  ip6_address_t ip6_prefix;
916  u32 map_domain_index = d - mm->domains;
917  map_domain_extra_t *de = 0;
918 
919  if (d->rules)
920  clib_memset (&ip6_prefix, 0, sizeof (ip6_prefix));
921  else
922  ip6_prefix = d->ip6_prefix;
923 
924  if (map_domain_index < vec_len (mm->domain_extras))
925  de = vec_elt_at_index (mm->domain_extras, map_domain_index);
926 
927  s = format (s,
928  "[%d] tag {%s} ip4-pfx %U/%d ip6-pfx %U/%d ip6-src %U/%d "
929  "ea-bits-len %d psid-offset %d psid-len %d mtu %d %s",
930  map_domain_index, (de && de->tag) ? de->tag : (u8 *) "[no-tag]",
932  format_ip6_address, &ip6_prefix, d->ip6_prefix_len,
934  d->ea_bits_len, d->psid_offset, d->psid_length, d->mtu,
936 
937  if (counters)
938  {
940  vlib_counter_t v;
942  map_domain_index, &v);
943  s = format (s, " TX: %lld/%lld", v.packets, v.bytes);
945  map_domain_index, &v);
946  s = format (s, " RX: %lld/%lld", v.packets, v.bytes);
948  }
949  s = format (s, "\n");
950 
951  if (d->rules)
952  {
953  int i;
954  ip6_address_t dst;
955  for (i = 0; i < (0x1 << d->psid_length); i++)
956  {
957  dst = d->rules[i];
958  if (dst.as_u64[0] == 0 && dst.as_u64[1] == 0)
959  continue;
960  s = format (s,
961  " rule psid: %d ip6-dst %U\n", i, format_ip6_address,
962  &dst);
963  }
964  }
965  return s;
966 }
967 
968 static clib_error_t *
970  vlib_cli_command_t * cmd)
971 {
972  unformat_input_t _line_input, *line_input = &_line_input;
973  map_main_t *mm = &map_main;
974  map_domain_t *d;
975  bool counters = false;
976  u32 map_domain_index = ~0;
977  clib_error_t *error = NULL;
978 
979  /* Get a line of input. */
980  if (!unformat_user (input, unformat_line_input, line_input))
981  {
982  /* *INDENT-OFF* */
983  pool_foreach (d, mm->domains)
984  {vlib_cli_output(vm, "%U", format_map_domain, d, counters);}
985  /* *INDENT-ON* */
986  return 0;
987  }
988 
989  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
990  {
991  if (unformat (line_input, "counters"))
992  counters = true;
993  else if (unformat (line_input, "index %d", &map_domain_index))
994  ;
995  else
996  {
997  error = clib_error_return (0, "unknown input `%U'",
998  format_unformat_error, line_input);
999  goto done;
1000  }
1001  }
1002 
1003  if (pool_elts (mm->domains) == 0)
1004  {
1005  vlib_cli_output (vm, "No MAP domains are configured...");
1006  goto done;
1007  }
1008 
1009  if (map_domain_index == ~0)
1010  {
1011  /* *INDENT-OFF* */
1012  pool_foreach (d, mm->domains)
1013  {vlib_cli_output(vm, "%U", format_map_domain, d, counters);}
1014  /* *INDENT-ON* */
1015  }
1016  else
1017  {
1018  if (pool_is_free_index (mm->domains, map_domain_index))
1019  {
1020  error = clib_error_return (0, "MAP domain does not exists %d",
1021  map_domain_index);
1022  goto done;
1023  }
1024 
1025  d = pool_elt_at_index (mm->domains, map_domain_index);
1026  vlib_cli_output (vm, "%U", format_map_domain, d, counters);
1027  }
1028 
1029 done:
1030  unformat_free (line_input);
1031 
1032  return error;
1033 }
1034 
1035 u64
1036 map_error_counter_get (u32 node_index, map_error_t map_error)
1037 {
1039  vlib_node_runtime_t *error_node = vlib_node_get_runtime (vm, node_index);
1040  vlib_error_main_t *em = &vm->error_main;
1041  vlib_error_t e = error_node->errors[map_error];
1042  vlib_node_t *n = vlib_get_node (vm, node_index);
1043  u32 ci;
1044 
1045  ci = vlib_error_get_code (&vm->node_main, e);
1046  ASSERT (ci < n->n_errors);
1047  ci += n->error_heap_index;
1048 
1049  return (em->counters[ci]);
1050 }
1051 
1052 static clib_error_t *
1054  vlib_cli_command_t * cmd)
1055 {
1056  map_main_t *mm = &map_main;
1057  map_domain_t *d;
1058  int domains = 0, rules = 0, domaincount = 0, rulecount = 0;
1059  if (pool_elts (mm->domains) == 0)
1060  {
1061  vlib_cli_output (vm, "No MAP domains are configured...");
1062  return 0;
1063  }
1064 
1065  /* *INDENT-OFF* */
1066  pool_foreach (d, mm->domains) {
1067  if (d->rules) {
1068  rulecount+= 0x1 << d->psid_length;
1069  rules += sizeof(ip6_address_t) * 0x1 << d->psid_length;
1070  }
1071  domains += sizeof(*d);
1072  domaincount++;
1073  }
1074  /* *INDENT-ON* */
1075 
1076  vlib_cli_output (vm, "MAP domains structure: %d\n", sizeof (map_domain_t));
1077  vlib_cli_output (vm, "MAP domains: %d (%d bytes)\n", domaincount, domains);
1078  vlib_cli_output (vm, "MAP rules: %d (%d bytes)\n", rulecount, rules);
1079  vlib_cli_output (vm, "Total: %d bytes)\n", rules + domains);
1080 
1081 #if MAP_SKIP_IP6_LOOKUP
1082  vlib_cli_output (vm,
1083  "MAP pre-resolve: IP6 next-hop: %U, IP4 next-hop: %U\n",
1084  format_map_pre_resolve, &pre_resolved[FIB_PROTOCOL_IP6],
1085  format_map_pre_resolve, &pre_resolved[FIB_PROTOCOL_IP4]);
1086 
1087 #endif
1088 
1089  if (mm->tc_copy)
1090  vlib_cli_output (vm, "MAP traffic-class: copy");
1091  else
1092  vlib_cli_output (vm, "MAP traffic-class: %x", mm->tc);
1093 
1094  if (mm->tcp_mss)
1095  vlib_cli_output (vm, "MAP TCP MSS clamping: %u", mm->tcp_mss);
1096 
1097  vlib_cli_output (vm,
1098  "MAP IPv6 inbound security check: %s, fragmented packet security check: %s",
1099  mm->sec_check ? "enabled" : "disabled",
1100  mm->sec_check_frag ? "enabled" : "disabled");
1101 
1102  vlib_cli_output (vm, "ICMP-relay IPv4 source address: %U\n",
1104  vlib_cli_output (vm, "ICMP6 unreachables sent for unmatched packets: %s\n",
1105  mm->icmp6_enabled ? "enabled" : "disabled");
1106  vlib_cli_output (vm, "Inner fragmentation: %s\n",
1107  mm->frag_inner ? "enabled" : "disabled");
1108  vlib_cli_output (vm, "Fragment packets regardless of DF flag: %s\n",
1109  mm->frag_ignore_df ? "enabled" : "disabled");
1110 
1111  /*
1112  * Counters
1113  */
1115  u64 total_pkts[MAP_N_DOMAIN_COUNTER];
1116  u64 total_bytes[MAP_N_DOMAIN_COUNTER];
1117  int which, i;
1118  vlib_counter_t v;
1119 
1120  clib_memset (total_pkts, 0, sizeof (total_pkts));
1121  clib_memset (total_bytes, 0, sizeof (total_bytes));
1122 
1124  vec_foreach (cm, mm->domain_counters)
1125  {
1126  which = cm - mm->domain_counters;
1127 
1128  for (i = 0; i < vlib_combined_counter_n_counters (cm); i++)
1129  {
1130  vlib_get_combined_counter (cm, i, &v);
1131  total_pkts[which] += v.packets;
1132  total_bytes[which] += v.bytes;
1133  }
1134  }
1136 
1137  vlib_cli_output (vm, "Encapsulated packets: %lld bytes: %lld\n",
1138  total_pkts[MAP_DOMAIN_COUNTER_TX],
1139  total_bytes[MAP_DOMAIN_COUNTER_TX]);
1140  vlib_cli_output (vm, "Decapsulated packets: %lld bytes: %lld\n",
1141  total_pkts[MAP_DOMAIN_COUNTER_RX],
1142  total_bytes[MAP_DOMAIN_COUNTER_RX]);
1143 
1144  vlib_cli_output (vm, "ICMP relayed packets: %d\n",
1146 
1147  return 0;
1148 }
1149 
1150 static clib_error_t *
1152  unformat_input_t * input, vlib_cli_command_t * cmd)
1153 {
1154  unformat_input_t _line_input, *line_input = &_line_input;
1155  clib_error_t *error = NULL;
1156  bool is_enable = true, is_translation = false;
1157  vnet_main_t *vnm = vnet_get_main ();
1158  u32 sw_if_index = ~0;
1159 
1160  /* Get a line of input. */
1161  if (!unformat_user (input, unformat_line_input, line_input))
1162  return 0;
1163 
1164  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1165  {
1166  if (unformat
1167  (line_input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
1168  ;
1169  else if (unformat (line_input, "del"))
1170  is_enable = false;
1171  else if (unformat (line_input, "map-t"))
1172  is_translation = true;
1173  else
1174  {
1175  error = clib_error_return (0, "unknown input `%U'",
1176  format_unformat_error, line_input);
1177  goto done;
1178  }
1179  }
1180 
1181 done:
1182  unformat_free (line_input);
1183 
1184  if (sw_if_index == ~0)
1185  {
1186  error = clib_error_return (0, "unknown interface");
1187  return error;
1188  }
1189 
1190  int rv = map_if_enable_disable (is_enable, sw_if_index, is_translation);
1191  if (rv)
1192  {
1193  error = clib_error_return (0, "failure enabling MAP on interface");
1194  }
1195 
1196  return error;
1197 }
1198 
1199 
1200 /*
1201  * packet trace format function
1202  */
1203 u8 *
1204 format_map_trace (u8 * s, va_list * args)
1205 {
1206  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1207  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1208  map_trace_t *t = va_arg (*args, map_trace_t *);
1209  u32 map_domain_index = t->map_domain_index;
1210  u16 port = t->port;
1211 
1212  s =
1213  format (s, "MAP domain index: %d L4 port: %u", map_domain_index,
1214  clib_net_to_host_u16 (port));
1215 
1216  return s;
1217 }
1218 
1219 static clib_error_t *
1221  unformat_input_t * input, vlib_cli_command_t * cmd)
1222 {
1223  unformat_input_t _line_input, *line_input = &_line_input;
1224  clib_error_t *error = NULL;
1225  u32 tcp_mss = 0;
1226 
1227  /* Get a line of input. */
1228  if (!unformat_user (input, unformat_line_input, line_input))
1229  return 0;
1230 
1231  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1232  {
1233  if (unformat (line_input, "%u", &tcp_mss))
1234  ;
1235  else
1236  {
1237  error = clib_error_return (0, "unknown input `%U'",
1238  format_unformat_error, line_input);
1239  goto done;
1240  }
1241  }
1242 
1243  if (tcp_mss >= (0x1 << 16))
1244  {
1245  error = clib_error_return (0, "invalid value `%u'", tcp_mss);
1246  goto done;
1247  }
1248 
1249  map_param_set_tcp (tcp_mss);
1250 
1251 done:
1252  unformat_free (line_input);
1253 
1254  return error;
1255 }
1256 
1257 
1258 /* *INDENT-OFF* */
1259 
1260 /*?
1261  * Set or copy the IP TOS/Traffic Class field
1262  *
1263  * @cliexpar
1264  * @cliexstart{map params traffic-class}
1265  *
1266  * This command is used to set the traffic-class field in translated
1267  * or encapsulated packets. If copy is specifed (the default) then the
1268  * traffic-class/TOS field is copied from the original packet to the
1269  * translated / encapsulating header.
1270  * @cliexend
1271  ?*/
1272 VLIB_CLI_COMMAND(map_traffic_class_command, static) = {
1273  .path = "map params traffic-class",
1274  .short_help = "map params traffic-class {0x0-0xff | copy}",
1275  .function = map_traffic_class_command_fn,
1276 };
1277 
1278 /*?
1279  * TCP MSS clamping
1280  *
1281  * @cliexpar
1282  * @cliexstart{map params tcp-mss}
1283  *
1284  * This command is used to set the TCP MSS in translated
1285  * or encapsulated packets.
1286  * @cliexend
1287  ?*/
1288 VLIB_CLI_COMMAND(map_tcp_mss_command, static) = {
1289  .path = "map params tcp-mss",
1290  .short_help = "map params tcp-mss <value>",
1291  .function = map_tcp_mss_command_fn,
1292 };
1293 
1294 /*?
1295  * Bypass IP4/IP6 lookup
1296  *
1297  * @cliexpar
1298  * @cliexstart{map params pre-resolve}
1299  *
1300  * Bypass a second FIB lookup of the translated or encapsulated
1301  * packet, and forward the packet directly to the specified
1302  * next-hop. This optimization trades forwarding flexibility for
1303  * performance.
1304  * @cliexend
1305  ?*/
1306 VLIB_CLI_COMMAND(map_pre_resolve_command, static) = {
1307  .path = "map params pre-resolve",
1308  .short_help = " map params pre-resolve {ip4-nh <address>} "
1309  "| {ip6-nh <address>}",
1310  .function = map_pre_resolve_command_fn,
1311 };
1312 
1313 /*?
1314  * Enable or disable the MAP-E inbound security check
1315  * Specifiy if the inbound security check should be done on fragments
1316  *
1317  * @cliexpar
1318  * @cliexstart{map params security-check}
1319  *
1320  * By default, a decapsulated packet's IPv4 source address will be
1321  * verified against the outer header's IPv6 source address. Disabling
1322  * this feature will allow IPv4 source address spoofing.
1323  *
1324  * Typically the inbound on-decapsulation security check is only done
1325  * on the first packet. The packet that contains the L4
1326  * information. While a security check on every fragment is possible,
1327  * it has a cost. State must be created on the first fragment.
1328  * @cliexend
1329  ?*/
1330 VLIB_CLI_COMMAND(map_security_check_command, static) = {
1331  .path = "map params security-check",
1332  .short_help = "map params security-check enable|disable fragments on|off",
1333  .function = map_security_check_command_fn,
1334 };
1335 
1336 
1337 /*?
1338  * Specifiy the IPv4 source address used for relayed ICMP error messages
1339  *
1340  * @cliexpar
1341  * @cliexstart{map params icmp source-address}
1342  *
1343  * This command specifies which IPv4 source address (must be local to
1344  * the system), that is used for relayed received IPv6 ICMP error
1345  * messages.
1346  * @cliexend
1347  ?*/
1348 VLIB_CLI_COMMAND(map_icmp_relay_source_address_command, static) = {
1349  .path = "map params icmp source-address",
1350  .short_help = "map params icmp source-address <ip4-address>",
1352 };
1353 
1354 /*?
1355  * Send IPv6 ICMP unreachables
1356  *
1357  * @cliexpar
1358  * @cliexstart{map params icmp6 unreachables}
1359  *
1360  * Send IPv6 ICMP unreachable messages back if security check fails or
1361  * no MAP domain exists.
1362  * @cliexend
1363  ?*/
1364 VLIB_CLI_COMMAND(map_icmp_unreachables_command, static) = {
1365  .path = "map params icmp6 unreachables",
1366  .short_help = "map params icmp6 unreachables {on|off}",
1368 };
1369 
1370 /*?
1371  * Configure MAP fragmentation behaviour
1372  *
1373  * @cliexpar
1374  * @cliexstart{map params fragment}
1375  *
1376  * Allows fragmentation of the IPv4 packet even if the DF bit is
1377  * set. The choice between inner or outer fragmentation of tunnel
1378  * packets is complicated. The benefit of inner fragmentation is that
1379  * the ultimate endpoint must reassemble, instead of the tunnel
1380  * endpoint.
1381  * @cliexend
1382  ?*/
1383 VLIB_CLI_COMMAND(map_fragment_command, static) = {
1384  .path = "map params fragment",
1385  .short_help = "map params fragment inner|outer ignore-df|honor-df",
1386  .function = map_fragment_command_fn,
1387 };
1388 
1389 
1390 /*?
1391  * Add MAP domain
1392  *
1393  * @cliexpar
1394  * @cliexstart{map add domain}
1395  * @cliexend
1396  ?*/
1397 VLIB_CLI_COMMAND(map_add_domain_command, static) = {
1398  .path = "map add domain",
1399  .short_help = "map add domain [tag <tag>] ip4-pfx <ip4-pfx> "
1400  "ip6-pfx <ip6-pfx> "
1401  "ip6-src <ip6-pfx> ea-bits-len <n> psid-offset <n> psid-len <n> "
1402  "[map-t] [mtu <mtu>]",
1403  .function = map_add_domain_command_fn,
1404 };
1405 
1406 /*?
1407  * Add MAP rule to a domain
1408  *
1409  * @cliexpar
1410  * @cliexstart{map add rule}
1411  * @cliexend
1412  ?*/
1413 VLIB_CLI_COMMAND(map_add_rule_command, static) = {
1414  .path = "map add rule",
1415  .short_help = "map add rule index <domain> psid <psid> ip6-dst <ip6-addr>",
1416  .function = map_add_rule_command_fn,
1417 };
1418 
1419 /*?
1420  * Delete MAP domain
1421  *
1422  * @cliexpar
1423  * @cliexstart{map del domain}
1424  * @cliexend
1425  ?*/
1426 VLIB_CLI_COMMAND(map_del_command, static) = {
1427  .path = "map del domain",
1428  .short_help = "map del domain index <domain>",
1429  .function = map_del_domain_command_fn,
1430 };
1431 
1432 /*?
1433  * Show MAP domains
1434  *
1435  * @cliexpar
1436  * @cliexstart{show map domain}
1437  * @cliexend
1438  ?*/
1439 VLIB_CLI_COMMAND(show_map_domain_command, static) = {
1440  .path = "show map domain",
1441  .short_help = "show map domain index <n> [counters]",
1442  .function = show_map_domain_command_fn,
1443 };
1444 
1445 /*?
1446  * Show MAP statistics
1447  *
1448  * @cliexpar
1449  * @cliexstart{show map stats}
1450  * @cliexend
1451  ?*/
1452 VLIB_CLI_COMMAND(show_map_stats_command, static) = {
1453  .path = "show map stats",
1454  .short_help = "show map stats",
1455  .function = show_map_stats_command_fn,
1456 };
1457 
1458 /*?
1459  * Enable MAP processing on interface (input feature)
1460  *
1461  ?*/
1462 VLIB_CLI_COMMAND(map_if_command, static) = {
1463  .path = "map interface",
1464  .short_help = "map interface <interface-name> [map-t] [del]",
1465  .function = map_if_command_fn,
1466 };
1467 
1469  .version = VPP_BUILD_VER,
1470  .description = "Mapping of Address and Port (MAP)",
1471 };
1472 
1473 /* *INDENT-ON* */
1474 
1475 /*
1476  * map_init
1477  */
1478 clib_error_t *
1480 {
1481  map_main_t *mm = &map_main;
1482  clib_error_t *error = 0;
1483 
1484  memset (mm, 0, sizeof (*mm));
1485 
1486  mm->vnet_main = vnet_get_main ();
1487  mm->vlib_main = vm;
1488 
1489 #ifdef MAP_SKIP_IP6_LOOKUP
1491 
1492  FOR_EACH_FIB_PROTOCOL (proto)
1493  {
1494  map_pre_resolve_init (&pre_resolved[proto]);
1495  }
1496 #endif
1497 
1498  /* traffic class */
1499  mm->tc = 0;
1500  mm->tc_copy = true;
1501 
1502  /* Inbound security check */
1503  mm->sec_check = true;
1504  mm->sec_check_frag = false;
1505 
1506  /* ICMP6 Type 1, Code 5 for security check failure */
1507  mm->icmp6_enabled = false;
1508 
1509  /* Inner or outer fragmentation */
1510  mm->frag_inner = false;
1511  mm->frag_ignore_df = false;
1512 
1514  mm->domain_counters[MAP_DOMAIN_COUNTER_RX].name = "/map/rx";
1515  mm->domain_counters[MAP_DOMAIN_COUNTER_TX].name = "/map/tx";
1516 
1519  mm->icmp_relayed.stat_segment_name = "/map/icmp-relayed";
1520 
1521  /* IP6 virtual reassembly */
1522 
1523 #ifdef MAP_SKIP_IP6_LOOKUP
1525 #endif
1526 
1527  /* LPM lookup tables */
1531 
1532  mm->bm_trans_enabled_by_sw_if = 0;
1533  mm->bm_encap_enabled_by_sw_if = 0;
1534 
1535  error = map_plugin_api_hookup (vm);
1536 
1537  return error;
1538 }
1539 
1541 
1542 /*
1543  * fd.io coding-style-patch-verification: ON
1544  *
1545  * Local Variables:
1546  * eval: (c-set-style "gnu")
1547  * End:
1548  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
int map_param_set_icmp(ip4_address_t *ip4_err_relay_src)
Definition: map_api.c:304
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:211
u8 psid_length
Definition: map.h:92
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:140
static clib_error_t * map_fragment_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:800
#define CLIB_UNUSED(x)
Definition: clib.h:87
int map_delete_domain(u32 map_domain_index)
Definition: map.c:204
map_domain_flags_e flags
Definition: map.h:87
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:108
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
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:527
int map_if_enable_disable(bool is_enable, u32 sw_if_index, bool is_translation)
Definition: map_api.c:482
void fib_node_init(fib_node_t *node, fib_node_type_t type)
Definition: fib_node.c:185
unsigned long u64
Definition: types.h:89
dpo_id_t dpo
The Load-balance object index to use to forward.
Definition: map.h:155
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static u8 * format_map_domain(u8 *s, va_list *args)
Definition: map.c:910
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:969
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:1036
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:194
u8 tc
Definition: map.h:180
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:135
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:130
static void map_domain_counter_unlock(map_main_t *mm)
Definition: map.h:386
Combined counter to hold both packets and byte differences.
Definition: counter_types.h:26
u16 vlib_error_t
Definition: error.h:43
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
u32 suffix_mask
Definition: map.h:83
bool sec_check_frag
Definition: map.h:184
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:70
vlib_main_t * vm
Definition: in2out_ed.c:1578
const fib_prefix_t * fib_entry_get_prefix(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:1712
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:201
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:111
unsigned char u8
Definition: types.h:56
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
u16 port
Definition: map.h:218
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:132
format_function_t format_ip4_address
Definition: format.h:73
manual_print typedef ip6_prefix
Definition: ip_types.api:125
bool tc_copy
Definition: map.h:181
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:672
#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:757
int which
Definition: cJSON.h:234
vl_api_ip6_address_t ip6
Definition: one.api:424
vlib_combined_counter_main_t * domain_counters
Definition: map.h:173
ip4_address_t icmp4_src_address
Definition: map.h:190
description fragment has unexpected format
Definition: map.api:433
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:202
#define clib_error_return(e, args...)
Definition: error.h:99
vlib_simple_counter_main_t icmp_relayed
Definition: map.h:191
ip6_address_t * rules
Definition: map.h:82
u8 ea_bits_len
Definition: map.h:90
unsigned int u32
Definition: types.h:88
u8 ip6_prefix_len
Definition: map.h:88
unformat_function_t unformat_line_input
Definition: format.h:282
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
vnet_crypto_main_t * cm
Definition: quic_crypto.c:53
Definition: cJSON.c:84
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
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:304
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:1151
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:622
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:225
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:1220
vlib_error_main_t error_main
Definition: main.h:210
vl_api_ip_proto_t proto
Definition: acl_types.api:51
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:198
long ctx[MAX_CONNS]
Definition: main.c:144
int map_param_set_traffic_class(bool copy, u8 tc)
Definition: map_api.c:393
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:175
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
map_domain_t * domains
Definition: map.h:168
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:301
#define FOR_EACH_FIB_PROTOCOL(_item)
Definition: fib_types.h:64
vl_api_ip4_address_t ip4
Definition: one.api:376
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:55
u8 ip6_src_len
Definition: map.h:89
u8 psid_shift
Definition: map.h:95
u8 suffix_shift
Definition: map.h:96
static u32 vlib_error_get_code(vlib_node_main_t *nm, vlib_error_t e)
Definition: node.h:762
u8 len
Definition: ip_types.api:103
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:245
u64 * counters
Definition: error.h:62
vl_counter_map_enum_t map_error_t
Definition: map.h:212
lpm_t * ip6_src_prefix_tbl
Definition: map.h:207
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
ip4_address_t ip4_prefix
Definition: map.h:84
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:278
uword * bm_encap_enabled_by_sw_if
Definition: map.h:202
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
u8 psid_offset
Definition: map.h:91
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:716
#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:115
fib_node_get_t fnv_get
Definition: fib_node.h:283
bool icmp6_enabled
Definition: map.h:185
int map_param_set_fragmentation(bool inner, bool ignore_df)
Definition: map_api.c:279
u32 sibling
This object sibling index on the FIB entry&#39;s child dependency list.
Definition: map.h:150
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:29
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:298
static void map_pre_resolve_init(map_main_pre_resolved_t *pr)
Definition: map.c:286
ip6_address_t ip6_src
Definition: map.h:80
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:583
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1578
static void map_domain_counter_lock(map_main_t *mm)
Definition: map.h:378
Context passed between object during a back walk.
Definition: fib_node.h:208
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
#define vec_validate_init_c_string(V, S, L)
Make a vector containing a NULL terminated c-string.
Definition: vec.h:1067
vl_api_gbp_rule_t rules[n_rules]
Definition: gbp.api:338
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.
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
bool sec_check
Definition: map.h:183
bool frag_inner
Definition: map.h:197
u16 psid_mask
Definition: map.h:85
static void clib_mem_free(void *p)
Definition: mem.h:311
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:158
u8 * format_map_trace(u8 *s, va_list *args)
Definition: map.c:1204
void(* delete)(struct lpm_ *lpm, void *addr_v, u8 pfxlen)
Definition: lpm.h:26
u8 ea_shift
Definition: map.h:97
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:81
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:865
counter_t bytes
byte counter
Definition: counter_types.h:29
vnet_main_t * vnet_main
Definition: map.h:195
int map_param_set_security_check(bool enable, bool fragments)
Definition: map_api.c:368
char * stat_segment_name
Name in stat segment directory.
Definition: counter.h:65
u16 mtu
Definition: map.h:86
int map_param_set_icmp6(u8 enable_unreachable)
Definition: map_api.c:331
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:188
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:30
#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:557
fib_node_index_t fei
The FIB entry index of the next-hop.
Definition: map.h:145
vlib_node_main_t node_main
Definition: main.h:188
map_domain_extra_t * domain_extras
Definition: map.h:169
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
char * name
The counter collection&#39;s name.
Definition: counter.h:212
u32 index
Definition: flow_types.api:221
u16 tcp_mss
Definition: map.h:187
lpm_t * ip4_prefix_tbl
Definition: map.h:205
A collection of combined counters.
Definition: counter.h:207
u16 port
Definition: lb_types.api:73
#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:51
u8 ip4_prefix_len
Definition: map.h:100
A FIB graph nodes virtual function table.
Definition: fib_node.h:282
vlib_simple_counter_main_t * simple_domain_counters
Definition: map.h:172
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:261
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:418
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:85
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:217
static char * map_flags_to_string(u32 flags)
Definition: map.c:902
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
lpm_t * ip6_prefix_tbl
Definition: map.h:206
clib_error_t * map_init(vlib_main_t *vm)
Definition: map.c:1479
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
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
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:1053
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127