FD.io VPP  v18.07.1-19-g511ce25
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>
19 #include <vnet/fib/ip6_fib.h>
20 #include <vnet/adj/adj.h>
21 #include <map/map_dpo.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 DMR prefix length equal to 96.
59  *
60  */
61 
62 
63 
64 int
66  u8 ip4_prefix_len,
67  ip6_address_t * ip6_prefix,
68  u8 ip6_prefix_len,
69  ip6_address_t * ip6_src,
70  u8 ip6_src_len,
71  u8 ea_bits_len,
72  u8 psid_offset,
73  u8 psid_length, u32 * map_domain_index, u16 mtu, u8 flags)
74 {
75  u8 suffix_len, suffix_shift;
76  map_main_t *mm = &map_main;
77  dpo_id_t dpo_v4 = DPO_INVALID;
78  dpo_id_t dpo_v6 = DPO_INVALID;
79  map_domain_t *d;
80 
81  /* Sanity check on the src prefix length */
82  if (flags & MAP_DOMAIN_TRANSLATION)
83  {
84  if (ip6_src_len != 96)
85  {
86  clib_warning ("MAP-T only supports ip6_src_len = 96 for now.");
87  return -1;
88  }
89  if ((flags & MAP_DOMAIN_RFC6052) && ip6_prefix_len != 96)
90  {
91  clib_warning ("RFC6052 translation only supports ip6_prefix_len = "
92  "96 for now");
93  return -1;
94  }
95  }
96  else
97  {
98  if (ip6_src_len != 128)
99  {
101  ("MAP-E requires a BR address, not a prefix (ip6_src_len should "
102  "be 128).");
103  return -1;
104  }
105  }
106 
107  /* How many, and which bits to grab from the IPv4 DA */
108  if (ip4_prefix_len + ea_bits_len < 32)
109  {
110  if (!(flags & MAP_DOMAIN_TRANSLATION))
111  flags |= MAP_DOMAIN_PREFIX;
112  suffix_shift = 32 - ip4_prefix_len - ea_bits_len;
113  suffix_len = ea_bits_len;
114  }
115  else
116  {
117  suffix_shift = 0;
118  suffix_len = 32 - ip4_prefix_len;
119  }
120 
121  /* EA bits must be within the first 64 bits */
122  if (ea_bits_len > 0 && ((ip6_prefix_len + ea_bits_len) > 64 ||
123  ip6_prefix_len + suffix_len + psid_length > 64))
124  {
126  ("Embedded Address bits must be within the first 64 bits of "
127  "the IPv6 prefix");
128  return -1;
129  }
130 
131  if (mm->is_ce && !(flags & MAP_DOMAIN_TRANSLATION))
132  {
133  clib_warning ("MAP-E CE is not supported yet");
134  return -1;
135  }
136 
137  /* Get domain index */
139  memset (d, 0, sizeof (*d));
140  *map_domain_index = d - mm->domains;
141 
142  /* Init domain struct */
143  d->ip4_prefix.as_u32 = ip4_prefix->as_u32;
144  d->ip4_prefix_len = ip4_prefix_len;
145  d->ip6_prefix = *ip6_prefix;
146  d->ip6_prefix_len = ip6_prefix_len;
147  d->ip6_src = *ip6_src;
148  d->ip6_src_len = ip6_src_len;
149  d->ea_bits_len = ea_bits_len;
150  d->psid_offset = psid_offset;
151  d->psid_length = psid_length;
152  d->mtu = mtu;
153  d->flags = flags;
154  d->suffix_shift = suffix_shift;
155  d->suffix_mask = (1 << suffix_len) - 1;
156 
157  d->psid_shift = 16 - psid_length - psid_offset;
158  d->psid_mask = (1 << d->psid_length) - 1;
159  d->ea_shift = 64 - ip6_prefix_len - suffix_len - d->psid_length;
160 
161  /* MAP data-plane object */
162  if (d->flags & MAP_DOMAIN_TRANSLATION)
163  map_t_dpo_create (DPO_PROTO_IP4, *map_domain_index, &dpo_v4);
164  else
165  map_dpo_create (DPO_PROTO_IP4, *map_domain_index, &dpo_v4);
166 
167  /* Create ip4 route */
168  u8 ip4_pfx_len;
169  ip4_address_t ip4_pfx;
170  if (mm->is_ce)
171  {
172  ip4_pfx_len = 0;
173  ip4_pfx.as_u32 = 0;
174  }
175  else
176  {
177  ip4_pfx_len = d->ip4_prefix_len;
178  ip4_pfx = d->ip4_prefix;
179  }
180  fib_prefix_t pfx = {
182  .fp_len = ip4_pfx_len,
183  .fp_addr = {
184  .ip4 = ip4_pfx,
185  }
186  ,
187  };
190  FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v4);
191  dpo_reset (&dpo_v4);
192 
193  /*
194  * construct a DPO to use the v6 domain
195  */
196  if (d->flags & MAP_DOMAIN_TRANSLATION)
197  map_t_dpo_create (DPO_PROTO_IP6, *map_domain_index, &dpo_v6);
198  else
199  map_dpo_create (DPO_PROTO_IP6, *map_domain_index, &dpo_v6);
200 
201  /*
202  * Multiple MAP domains may share same source IPv6 TEP. Which is just dandy.
203  * We are not tracking the sharing. So a v4 lookup to find the correct
204  * domain post decap/trnaslate is always done
205  *
206  * Create ip6 route. This is a reference counted add. If the prefix
207  * already exists and is MAP sourced, it is now MAP source n+1 times
208  * and will need to be removed n+1 times.
209  */
210  u8 ip6_pfx_len;
211  ip6_address_t ip6_pfx;
212  if (mm->is_ce)
213  {
214  ip6_pfx_len = d->ip6_prefix_len;
215  ip6_pfx = d->ip6_prefix;
216  }
217  else
218  {
219  ip6_pfx_len = d->ip6_src_len;
220  ip6_pfx = d->ip6_src;
221  }
222  fib_prefix_t pfx6 = {
224  .fp_len = ip6_pfx_len,
225  .fp_addr.ip6 = ip6_pfx,
226  };
227 
230  FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v6);
231  dpo_reset (&dpo_v6);
232 
233  /* Validate packet/byte counters */
235  int i;
236  for (i = 0; i < vec_len (mm->simple_domain_counters); i++)
237  {
239  *map_domain_index);
241  *map_domain_index);
242  }
243  for (i = 0; i < vec_len (mm->domain_counters); i++)
244  {
246  *map_domain_index);
247  vlib_zero_combined_counter (&mm->domain_counters[i], *map_domain_index);
248  }
250 
251  return 0;
252 }
253 
254 /*
255  * map_delete_domain
256  */
257 int
258 map_delete_domain (u32 map_domain_index)
259 {
260  map_main_t *mm = &map_main;
261  map_domain_t *d;
262 
263  if (pool_is_free_index (mm->domains, map_domain_index))
264  {
265  clib_warning ("MAP domain delete: domain does not exist: %d",
266  map_domain_index);
267  return -1;
268  }
269 
270  d = pool_elt_at_index (mm->domains, map_domain_index);
271 
272  fib_prefix_t pfx = {
274  .fp_len = d->ip4_prefix_len,
275  .fp_addr = {
276  .ip4 = d->ip4_prefix,
277  }
278  ,
279  };
281 
282  fib_prefix_t pfx6 = {
284  .fp_len = d->ip6_src_len,
285  .fp_addr = {
286  .ip6 = d->ip6_src,
287  }
288  ,
289  };
291 
292  /* Deleting rules */
293  if (d->rules)
294  clib_mem_free (d->rules);
295 
296  pool_put (mm->domains, d);
297 
298  return 0;
299 }
300 
301 int
302 map_add_del_psid (u32 map_domain_index, u16 psid, ip6_address_t * tep,
303  u8 is_add)
304 {
305  map_domain_t *d;
306  map_main_t *mm = &map_main;
307 
308  if (pool_is_free_index (mm->domains, map_domain_index))
309  {
310  clib_warning ("MAP rule: domain does not exist: %d", map_domain_index);
311  return -1;
312  }
313  d = pool_elt_at_index (mm->domains, map_domain_index);
314 
315  /* Rules are only used in 1:1 independent case */
316  if (d->ea_bits_len > 0)
317  return (-1);
318 
319  if (!d->rules)
320  {
321  u32 l = (0x1 << d->psid_length) * sizeof (ip6_address_t);
323  if (!d->rules)
324  return -1;
325  memset (d->rules, 0, l);
326  }
327 
328  if (psid >= (0x1 << d->psid_length))
329  {
330  clib_warning ("MAP rule: PSID outside bounds: %d [%d]", psid,
331  0x1 << d->psid_length);
332  return -1;
333  }
334 
335  if (is_add)
336  {
337  d->rules[psid] = *tep;
338  }
339  else
340  {
341  memset (&d->rules[psid], 0, sizeof (ip6_address_t));
342  }
343  return 0;
344 }
345 
346 #ifdef MAP_SKIP_IP6_LOOKUP
347 /**
348  * Pre-resolvd per-protocol global next-hops
349  */
351 
352 static void
354 {
357 }
358 
359 static u8 *
360 format_map_pre_resolve (u8 * s, va_list * ap)
361 {
362  map_main_pre_resolved_t *pr = va_arg (*ap, map_main_pre_resolved_t *);
363 
364  if (FIB_NODE_INDEX_INVALID != pr->fei)
365  {
366  fib_prefix_t pfx;
367 
368  fib_entry_get_prefix (pr->fei, &pfx);
369 
370  return (format (s, "%U (%u)",
372  pr->dpo.dpoi_index));
373  }
374  else
375  {
376  return (format (s, "un-set"));
377  }
378 }
379 
380 
381 /**
382  * Function definition to inform the FIB node that its last lock has gone.
383  */
384 static void
386 {
387  /*
388  * The MAP is a root of the graph. As such
389  * it never has children and thus is never locked.
390  */
391  ASSERT (0);
392 }
393 
396 {
398  return ((map_main_pre_resolved_t *)
399  (((char *) node) -
401 }
402 
403 static void
405 {
406  const dpo_id_t *dpo;
407 
409 
410  dpo_copy (&pr->dpo, dpo);
411 }
412 
413 /**
414  * Function definition to backwalk a FIB node
415  */
418 {
419  map_stack (map_from_fib_node (node));
420 
422 }
423 
424 /**
425  * Function definition to get a FIB node from its index
426  */
427 static fib_node_t *
429 {
430  return (&pre_resolved[index].node);
431 }
432 
433 /*
434  * Virtual function table registered by MPLS GRE tunnels
435  * for participation in the FIB object graph.
436  */
437 const static fib_node_vft_t map_vft = {
439  .fnv_last_lock = map_last_lock_gone,
440  .fnv_back_walk = map_back_walk,
441 };
442 
443 static void
445  fib_protocol_t proto, u8 len, const ip46_address_t * addr)
446 {
447  fib_prefix_t pfx = {
448  .fp_proto = proto,
449  .fp_len = len,
450  .fp_addr = *addr,
451  };
452 
453  pr->fei = fib_table_entry_special_add (0, // default fib
454  &pfx,
457  map_stack (pr);
458 }
459 
460 static void
462  fib_protocol_t proto, u8 len, const ip46_address_t * addr)
463 {
464  fib_prefix_t pfx = {
465  .fp_proto = proto,
466  .fp_len = len,
467  .fp_addr = *addr,
468  };
469 
471 
472  fib_table_entry_special_remove (0, // default fib
473  &pfx, FIB_SOURCE_RR);
474  dpo_reset (&pr->dpo);
475 
478 }
479 
480 static void
481 map_pre_resolve (ip4_address_t * ip4, ip6_address_t * ip6, int is_del)
482 {
483  if (ip6 && (ip6->as_u64[0] != 0 || ip6->as_u64[1] != 0))
484  {
485  ip46_address_t addr = {
486  .ip6 = *ip6,
487  };
488  if (is_del)
489  map_fib_unresolve (&pre_resolved[FIB_PROTOCOL_IP6],
490  FIB_PROTOCOL_IP6, 128, &addr);
491  else
492  map_fib_resolve (&pre_resolved[FIB_PROTOCOL_IP6],
493  FIB_PROTOCOL_IP6, 128, &addr);
494  }
495  if (ip4 && (ip4->as_u32 != 0))
496  {
497  ip46_address_t addr = {
498  .ip4 = *ip4,
499  };
500  if (is_del)
501  map_fib_unresolve (&pre_resolved[FIB_PROTOCOL_IP4],
502  FIB_PROTOCOL_IP4, 32, &addr);
503  else
504  map_fib_resolve (&pre_resolved[FIB_PROTOCOL_IP4],
505  FIB_PROTOCOL_IP4, 32, &addr);
506  }
507 }
508 #endif
509 
510 static clib_error_t *
512  unformat_input_t * input,
513  vlib_cli_command_t * cmd)
514 {
515  unformat_input_t _line_input, *line_input = &_line_input;
516  map_main_t *mm = &map_main;
517  clib_error_t *error = NULL;
518 
519  /* Get a line of input. */
520  if (!unformat_user (input, unformat_line_input, line_input))
521  return 0;
522 
523  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
524  {
525  if (unformat (line_input, "off"))
526  mm->sec_check = false;
527  else if (unformat (line_input, "on"))
528  mm->sec_check = true;
529  else
530  {
531  error = clib_error_return (0, "unknown input `%U'",
532  format_unformat_error, line_input);
533  goto done;
534  }
535  }
536 
537 done:
538  unformat_free (line_input);
539 
540  return error;
541 }
542 
543 static clib_error_t *
545  unformat_input_t * input,
546  vlib_cli_command_t * cmd)
547 {
548  unformat_input_t _line_input, *line_input = &_line_input;
549  map_main_t *mm = &map_main;
550  clib_error_t *error = NULL;
551 
552  /* Get a line of input. */
553  if (!unformat_user (input, unformat_line_input, line_input))
554  return 0;
555 
556  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
557  {
558  if (unformat (line_input, "off"))
559  mm->sec_check_frag = false;
560  else if (unformat (line_input, "on"))
561  mm->sec_check_frag = true;
562  else
563  {
564  error = clib_error_return (0, "unknown input `%U'",
565  format_unformat_error, line_input);
566  goto done;
567  }
568  }
569 
570 done:
571  unformat_free (line_input);
572 
573  return error;
574 }
575 
576 static clib_error_t *
578  unformat_input_t * input, vlib_cli_command_t * cmd)
579 {
580  unformat_input_t _line_input, *line_input = &_line_input;
581  ip4_address_t ip4_prefix;
582  ip6_address_t ip6_prefix;
583  ip6_address_t ip6_src;
584  u32 ip6_prefix_len = 0, ip4_prefix_len = 0, map_domain_index, ip6_src_len;
585  u32 num_m_args = 0;
586  /* Optional arguments */
587  u32 ea_bits_len = 0, psid_offset = 0, psid_length = 0;
588  u32 mtu = 0;
589  u8 flags = 0;
590  ip6_src_len = 128;
591  clib_error_t *error = NULL;
592 
593  /* Get a line of input. */
594  if (!unformat_user (input, unformat_line_input, line_input))
595  return 0;
596 
597  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
598  {
599  if (unformat
600  (line_input, "ip4-pfx %U/%d", unformat_ip4_address, &ip4_prefix,
601  &ip4_prefix_len))
602  num_m_args++;
603  else
604  if (unformat
605  (line_input, "ip6-pfx %U/%d", unformat_ip6_address, &ip6_prefix,
606  &ip6_prefix_len))
607  num_m_args++;
608  else
609  if (unformat
610  (line_input, "ip6-src %U/%d", unformat_ip6_address, &ip6_src,
611  &ip6_src_len))
612  num_m_args++;
613  else
614  if (unformat
615  (line_input, "ip6-src %U", unformat_ip6_address, &ip6_src))
616  num_m_args++;
617  else if (unformat (line_input, "ea-bits-len %d", &ea_bits_len))
618  num_m_args++;
619  else if (unformat (line_input, "psid-offset %d", &psid_offset))
620  num_m_args++;
621  else if (unformat (line_input, "psid-len %d", &psid_length))
622  num_m_args++;
623  else if (unformat (line_input, "mtu %d", &mtu))
624  num_m_args++;
625  else if (unformat (line_input, "map-t"))
626  flags |= MAP_DOMAIN_TRANSLATION;
627  else if (unformat (line_input, "rfc6052"))
629  else
630  {
631  error = clib_error_return (0, "unknown input `%U'",
632  format_unformat_error, line_input);
633  goto done;
634  }
635  }
636 
637  if (num_m_args < 3)
638  {
639  error = clib_error_return (0, "mandatory argument(s) missing");
640  goto done;
641  }
642 
643  map_create_domain (&ip4_prefix, ip4_prefix_len,
644  &ip6_prefix, ip6_prefix_len, &ip6_src, ip6_src_len,
645  ea_bits_len, psid_offset, psid_length, &map_domain_index,
646  mtu, flags);
647 
648 done:
649  unformat_free (line_input);
650 
651  return error;
652 }
653 
654 static clib_error_t *
656  unformat_input_t * input, vlib_cli_command_t * cmd)
657 {
658  unformat_input_t _line_input, *line_input = &_line_input;
659  u32 num_m_args = 0;
660  u32 map_domain_index;
661  clib_error_t *error = NULL;
662 
663  /* Get a line of input. */
664  if (!unformat_user (input, unformat_line_input, line_input))
665  return 0;
666 
667  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
668  {
669  if (unformat (line_input, "index %d", &map_domain_index))
670  num_m_args++;
671  else
672  {
673  error = clib_error_return (0, "unknown input `%U'",
674  format_unformat_error, line_input);
675  goto done;
676  }
677  }
678 
679  if (num_m_args != 1)
680  {
681  error = clib_error_return (0, "mandatory argument(s) missing");
682  goto done;
683  }
684 
685  map_delete_domain (map_domain_index);
686 
687 done:
688  unformat_free (line_input);
689 
690  return error;
691 }
692 
693 static clib_error_t *
695  unformat_input_t * input, vlib_cli_command_t * cmd)
696 {
697  unformat_input_t _line_input, *line_input = &_line_input;
698  ip6_address_t tep;
699  u32 num_m_args = 0;
700  u32 psid = 0, map_domain_index;
701  clib_error_t *error = NULL;
702 
703  /* Get a line of input. */
704  if (!unformat_user (input, unformat_line_input, line_input))
705  return 0;
706 
707  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
708  {
709  if (unformat (line_input, "index %d", &map_domain_index))
710  num_m_args++;
711  else if (unformat (line_input, "psid %d", &psid))
712  num_m_args++;
713  else
714  if (unformat (line_input, "ip6-dst %U", unformat_ip6_address, &tep))
715  num_m_args++;
716  else
717  {
718  error = clib_error_return (0, "unknown input `%U'",
719  format_unformat_error, line_input);
720  goto done;
721  }
722  }
723 
724  if (num_m_args != 3)
725  {
726  error = clib_error_return (0, "mandatory argument(s) missing");
727  goto done;
728  }
729 
730  if (map_add_del_psid (map_domain_index, psid, &tep, 1) != 0)
731  {
732  error = clib_error_return (0, "Failing to add Mapping Rule");
733  goto done;
734  }
735 
736 done:
737  unformat_free (line_input);
738 
739  return error;
740 }
741 
742 #if MAP_SKIP_IP6_LOOKUP
743 static clib_error_t *
745  unformat_input_t * input,
746  vlib_cli_command_t * cmd)
747 {
748  unformat_input_t _line_input, *line_input = &_line_input;
749  ip4_address_t ip4nh, *p_v4 = NULL;
750  ip6_address_t ip6nh, *p_v6 = NULL;
751  clib_error_t *error = NULL;
752  int is_del = 0;
753 
754  memset (&ip4nh, 0, sizeof (ip4nh));
755  memset (&ip6nh, 0, sizeof (ip6nh));
756 
757  /* Get a line of input. */
758  if (!unformat_user (input, unformat_line_input, line_input))
759  return 0;
760 
761  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
762  {
763  if (unformat (line_input, "ip4-nh %U", unformat_ip4_address, &ip4nh))
764  p_v4 = &ip4nh;
765  else
766  if (unformat (line_input, "ip6-nh %U", unformat_ip6_address, &ip6nh))
767  p_v6 = &ip6nh;
768  else if (unformat (line_input, "del"))
769  is_del = 1;
770  else
771  {
772  error = clib_error_return (0, "unknown input `%U'",
773  format_unformat_error, line_input);
774  goto done;
775  }
776  }
777 
778  map_pre_resolve (p_v4, p_v6, is_del);
779 
780 done:
781  unformat_free (line_input);
782 
783  return error;
784 }
785 #endif
786 
787 static clib_error_t *
789  unformat_input_t * input,
790  vlib_cli_command_t * cmd)
791 {
792  unformat_input_t _line_input, *line_input = &_line_input;
793  ip4_address_t icmp_src_address;
794  map_main_t *mm = &map_main;
795  clib_error_t *error = NULL;
796 
797  mm->icmp4_src_address.as_u32 = 0;
798 
799  /* Get a line of input. */
800  if (!unformat_user (input, unformat_line_input, line_input))
801  return 0;
802 
803  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
804  {
805  if (unformat
806  (line_input, "%U", unformat_ip4_address, &icmp_src_address))
807  mm->icmp4_src_address = icmp_src_address;
808  else
809  {
810  error = clib_error_return (0, "unknown input `%U'",
811  format_unformat_error, line_input);
812  goto done;
813  }
814  }
815 
816 done:
817  unformat_free (line_input);
818 
819  return error;
820 }
821 
822 static clib_error_t *
824  unformat_input_t * input,
825  vlib_cli_command_t * cmd)
826 {
827  unformat_input_t _line_input, *line_input = &_line_input;
828  map_main_t *mm = &map_main;
829  int num_m_args = 0;
830  clib_error_t *error = NULL;
831 
832  /* Get a line of input. */
833  if (!unformat_user (input, unformat_line_input, line_input))
834  return 0;
835 
836  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
837  {
838  num_m_args++;
839  if (unformat (line_input, "on"))
840  mm->icmp6_enabled = true;
841  else if (unformat (line_input, "off"))
842  mm->icmp6_enabled = false;
843  else
844  {
845  error = clib_error_return (0, "unknown input `%U'",
846  format_unformat_error, line_input);
847  goto done;
848  }
849  }
850 
851 
852  if (num_m_args != 1)
853  error = clib_error_return (0, "mandatory argument(s) missing");
854 
855 done:
856  unformat_free (line_input);
857 
858  return error;
859 }
860 
861 static clib_error_t *
863  unformat_input_t * input, vlib_cli_command_t * cmd)
864 {
865  unformat_input_t _line_input, *line_input = &_line_input;
866  map_main_t *mm = &map_main;
867  clib_error_t *error = NULL;
868 
869  /* Get a line of input. */
870  if (!unformat_user (input, unformat_line_input, line_input))
871  return 0;
872 
873  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
874  {
875  if (unformat (line_input, "inner"))
876  mm->frag_inner = true;
877  else if (unformat (line_input, "outer"))
878  mm->frag_inner = false;
879  else
880  {
881  error = clib_error_return (0, "unknown input `%U'",
882  format_unformat_error, line_input);
883  goto done;
884  }
885  }
886 
887 done:
888  unformat_free (line_input);
889 
890  return error;
891 }
892 
893 static clib_error_t *
895  unformat_input_t * input,
896  vlib_cli_command_t * cmd)
897 {
898  unformat_input_t _line_input, *line_input = &_line_input;
899  map_main_t *mm = &map_main;
900  clib_error_t *error = NULL;
901 
902  /* Get a line of input. */
903  if (!unformat_user (input, unformat_line_input, line_input))
904  return 0;
905 
906  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
907  {
908  if (unformat (line_input, "on"))
909  mm->frag_ignore_df = true;
910  else if (unformat (line_input, "off"))
911  mm->frag_ignore_df = false;
912  else
913  {
914  error = clib_error_return (0, "unknown input `%U'",
915  format_unformat_error, line_input);
916  goto done;
917  }
918  }
919 
920 done:
921  unformat_free (line_input);
922 
923  return error;
924 }
925 
926 static clib_error_t *
928  unformat_input_t * input,
929  vlib_cli_command_t * cmd)
930 {
931  unformat_input_t _line_input, *line_input = &_line_input;
932  map_main_t *mm = &map_main;
933  u32 tc = 0;
934  clib_error_t *error = NULL;
935 
936  mm->tc_copy = false;
937 
938  /* Get a line of input. */
939  if (!unformat_user (input, unformat_line_input, line_input))
940  return 0;
941 
942  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
943  {
944  if (unformat (line_input, "copy"))
945  mm->tc_copy = true;
946  else if (unformat (line_input, "%x", &tc))
947  mm->tc = tc & 0xff;
948  else
949  {
950  error = clib_error_return (0, "unknown input `%U'",
951  format_unformat_error, line_input);
952  goto done;
953  }
954  }
955 
956 done:
957  unformat_free (line_input);
958 
959  return error;
960 }
961 
962 static char *
964 {
965  if (flags & MAP_DOMAIN_RFC6052)
966  return "rfc6052";
967  if (flags & MAP_DOMAIN_PREFIX)
968  return "prefix";
969  if (flags & MAP_DOMAIN_TRANSLATION)
970  return "map-t";
971  return "";
972 }
973 
974 static u8 *
975 format_map_domain (u8 * s, va_list * args)
976 {
977  map_domain_t *d = va_arg (*args, map_domain_t *);
978  bool counters = va_arg (*args, int);
979  map_main_t *mm = &map_main;
980  ip6_address_t ip6_prefix;
981 
982  if (d->rules)
983  memset (&ip6_prefix, 0, sizeof (ip6_prefix));
984  else
985  ip6_prefix = d->ip6_prefix;
986 
987  s = format (s,
988  "[%d] ip4-pfx %U/%d ip6-pfx %U/%d ip6-src %U/%d ea_bits_len %d "
989  "psid-offset %d psid-len %d mtu %d %s",
990  d - mm->domains,
992  format_ip6_address, &ip6_prefix, d->ip6_prefix_len,
994  d->ea_bits_len, d->psid_offset, d->psid_length, d->mtu,
996 
997  if (counters)
998  {
1000  vlib_counter_t v;
1002  d - mm->domains, &v);
1003  s = format (s, " TX: %lld/%lld", v.packets, v.bytes);
1005  d - mm->domains, &v);
1006  s = format (s, " RX: %lld/%lld", v.packets, v.bytes);
1008  }
1009  s = format (s, "\n");
1010 
1011  if (d->rules)
1012  {
1013  int i;
1014  ip6_address_t dst;
1015  for (i = 0; i < (0x1 << d->psid_length); i++)
1016  {
1017  dst = d->rules[i];
1018  if (dst.as_u64[0] == 0 && dst.as_u64[1] == 0)
1019  continue;
1020  s = format (s,
1021  " rule psid: %d ip6-dst %U\n", i, format_ip6_address,
1022  &dst);
1023  }
1024  }
1025  return s;
1026 }
1027 
1028 static u8 *
1029 format_map_ip4_reass (u8 * s, va_list * args)
1030 {
1031  map_main_t *mm = &map_main;
1032  map_ip4_reass_t *r = va_arg (*args, map_ip4_reass_t *);
1033  map_ip4_reass_key_t *k = &r->key;
1034  f64 now = vlib_time_now (mm->vlib_main);
1035  f64 lifetime = (((f64) mm->ip4_reass_conf_lifetime_ms) / 1000);
1036  f64 dt = (r->ts + lifetime > now) ? (r->ts + lifetime - now) : -1;
1037  s = format (s,
1038  "ip4-reass src=%U dst=%U protocol=%d identifier=%d port=%d lifetime=%.3lf\n",
1039  format_ip4_address, &k->src.as_u8, format_ip4_address,
1040  &k->dst.as_u8, k->protocol,
1041  clib_net_to_host_u16 (k->fragment_id),
1042  (r->port >= 0) ? clib_net_to_host_u16 (r->port) : -1, dt);
1043  return s;
1044 }
1045 
1046 static u8 *
1047 format_map_ip6_reass (u8 * s, va_list * args)
1048 {
1049  map_main_t *mm = &map_main;
1050  map_ip6_reass_t *r = va_arg (*args, map_ip6_reass_t *);
1051  map_ip6_reass_key_t *k = &r->key;
1052  f64 now = vlib_time_now (mm->vlib_main);
1053  f64 lifetime = (((f64) mm->ip6_reass_conf_lifetime_ms) / 1000);
1054  f64 dt = (r->ts + lifetime > now) ? (r->ts + lifetime - now) : -1;
1055  s = format (s,
1056  "ip6-reass src=%U dst=%U protocol=%d identifier=%d lifetime=%.3lf\n",
1057  format_ip6_address, &k->src.as_u8, format_ip6_address,
1058  &k->dst.as_u8, k->protocol,
1059  clib_net_to_host_u32 (k->fragment_id), dt);
1060  return s;
1061 }
1062 
1063 static clib_error_t *
1065  vlib_cli_command_t * cmd)
1066 {
1067  unformat_input_t _line_input, *line_input = &_line_input;
1068  map_main_t *mm = &map_main;
1069  map_domain_t *d;
1070  bool counters = false;
1071  u32 map_domain_index = ~0;
1072  clib_error_t *error = NULL;
1073 
1074  /* Get a line of input. */
1075  if (!unformat_user (input, unformat_line_input, line_input))
1076  return 0;
1077 
1078  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1079  {
1080  if (unformat (line_input, "counters"))
1081  counters = true;
1082  else if (unformat (line_input, "index %d", &map_domain_index))
1083  ;
1084  else
1085  {
1086  error = clib_error_return (0, "unknown input `%U'",
1087  format_unformat_error, line_input);
1088  goto done;
1089  }
1090  }
1091 
1092  if (pool_elts (mm->domains) == 0)
1093  vlib_cli_output (vm, "No MAP domains are configured...");
1094 
1095  if (map_domain_index == ~0)
1096  {
1097  /* *INDENT-OFF* */
1098  pool_foreach(d, mm->domains, ({vlib_cli_output(vm, "%U", format_map_domain, d, counters);}));
1099  /* *INDENT-ON* */
1100  }
1101  else
1102  {
1103  if (pool_is_free_index (mm->domains, map_domain_index))
1104  {
1105  error = clib_error_return (0, "MAP domain does not exists %d",
1106  map_domain_index);
1107  goto done;
1108  }
1109 
1110  d = pool_elt_at_index (mm->domains, map_domain_index);
1111  vlib_cli_output (vm, "%U", format_map_domain, d, counters);
1112  }
1113 
1114 done:
1115  unformat_free (line_input);
1116 
1117  return error;
1118 }
1119 
1120 static clib_error_t *
1122  vlib_cli_command_t * cmd)
1123 {
1124  map_main_t *mm = &map_main;
1125  map_ip4_reass_t *f4;
1126  map_ip6_reass_t *f6;
1127 
1128  /* *INDENT-OFF* */
1129  pool_foreach(f4, mm->ip4_reass_pool, ({vlib_cli_output (vm, "%U", format_map_ip4_reass, f4);}));
1130  /* *INDENT-ON* */
1131  /* *INDENT-OFF* */
1132  pool_foreach(f6, mm->ip6_reass_pool, ({vlib_cli_output (vm, "%U", format_map_ip6_reass, f6);}));
1133  /* *INDENT-ON* */
1134  return (0);
1135 }
1136 
1137 u64
1138 map_error_counter_get (u32 node_index, map_error_t map_error)
1139 {
1141  vlib_node_runtime_t *error_node = vlib_node_get_runtime (vm, node_index);
1142  vlib_error_main_t *em = &vm->error_main;
1143  vlib_error_t e = error_node->errors[map_error];
1144  vlib_node_t *n = vlib_get_node (vm, node_index);
1145  u32 ci;
1146 
1147  ci = vlib_error_get_code (e);
1148  ASSERT (ci < n->n_errors);
1149  ci += n->error_heap_index;
1150 
1151  return (em->counters[ci]);
1152 }
1153 
1154 static clib_error_t *
1156  vlib_cli_command_t * cmd)
1157 {
1158  map_main_t *mm = &map_main;
1159  map_domain_t *d;
1160  int domains = 0, rules = 0, domaincount = 0, rulecount = 0;
1161  if (pool_elts (mm->domains) == 0)
1162  {
1163  vlib_cli_output (vm, "No MAP domains are configured...");
1164  return 0;
1165  }
1166 
1167  /* *INDENT-OFF* */
1168  pool_foreach(d, mm->domains, ({
1169  if (d->rules) {
1170  rulecount+= 0x1 << d->psid_length;
1171  rules += sizeof(ip6_address_t) * 0x1 << d->psid_length;
1172  }
1173  domains += sizeof(*d);
1174  domaincount++;
1175  }));
1176  /* *INDENT-ON* */
1177 
1178  vlib_cli_output (vm, "MAP domains structure: %d\n", sizeof (map_domain_t));
1179  vlib_cli_output (vm, "MAP domains: %d (%d bytes)\n", domaincount, domains);
1180  vlib_cli_output (vm, "MAP rules: %d (%d bytes)\n", rulecount, rules);
1181  vlib_cli_output (vm, "Total: %d bytes)\n", rules + domains);
1182 
1183 #if MAP_SKIP_IP6_LOOKUP
1185  "MAP pre-resolve: IP6 next-hop: %U, IP4 next-hop: %U\n",
1186  format_map_pre_resolve, &pre_resolved[FIB_PROTOCOL_IP6],
1187  format_map_pre_resolve, &pre_resolved[FIB_PROTOCOL_IP4]);
1188 
1189 #endif
1190 
1191  if (mm->tc_copy)
1192  vlib_cli_output (vm, "MAP traffic-class: copy");
1193  else
1194  vlib_cli_output (vm, "MAP traffic-class: %x", mm->tc);
1195 
1197  "MAP IPv6 inbound security check: %s, fragmented packet security check: %s",
1198  mm->sec_check ? "enabled" : "disabled",
1199  mm->sec_check_frag ? "enabled" : "disabled");
1200 
1201  vlib_cli_output (vm, "ICMP-relay IPv4 source address: %U\n",
1202  format_ip4_address, &mm->icmp4_src_address);
1203  vlib_cli_output (vm, "ICMP6 unreachables sent for unmatched packets: %s\n",
1204  mm->icmp6_enabled ? "enabled" : "disabled");
1205  vlib_cli_output (vm, "Inner fragmentation: %s\n",
1206  mm->frag_inner ? "enabled" : "disabled");
1207  vlib_cli_output (vm, "Fragment packets regardless of DF flag: %s\n",
1208  mm->frag_ignore_df ? "enabled" : "disabled");
1209 
1210  /*
1211  * Counters
1212  */
1213  vlib_combined_counter_main_t *cm = mm->domain_counters;
1214  u64 total_pkts[MAP_N_DOMAIN_COUNTER];
1215  u64 total_bytes[MAP_N_DOMAIN_COUNTER];
1216  int which, i;
1217  vlib_counter_t v;
1218 
1219  memset (total_pkts, 0, sizeof (total_pkts));
1220  memset (total_bytes, 0, sizeof (total_bytes));
1221 
1223  vec_foreach (cm, mm->domain_counters)
1224  {
1225  which = cm - mm->domain_counters;
1226 
1227  for (i = 0; i < vlib_combined_counter_n_counters (cm); i++)
1228  {
1229  vlib_get_combined_counter (cm, i, &v);
1230  total_pkts[which] += v.packets;
1231  total_bytes[which] += v.bytes;
1232  }
1233  }
1235 
1236  vlib_cli_output (vm, "Encapsulated packets: %lld bytes: %lld\n",
1237  total_pkts[MAP_DOMAIN_COUNTER_TX],
1238  total_bytes[MAP_DOMAIN_COUNTER_TX]);
1239  vlib_cli_output (vm, "Decapsulated packets: %lld bytes: %lld\n",
1240  total_pkts[MAP_DOMAIN_COUNTER_RX],
1241  total_bytes[MAP_DOMAIN_COUNTER_RX]);
1242 
1243  vlib_cli_output (vm, "ICMP relayed packets: %d\n",
1244  vlib_get_simple_counter (&mm->icmp_relayed, 0));
1245 
1246  return 0;
1247 }
1248 
1249 static clib_error_t *
1251  vlib_cli_command_t * cmd)
1252 {
1253  unformat_input_t _line_input, *line_input = &_line_input;
1254  u32 lifetime = ~0;
1255  f64 ht_ratio = (MAP_IP4_REASS_CONF_HT_RATIO_MAX + 1);
1256  u32 pool_size = ~0;
1257  u64 buffers = ~(0ull);
1258  u8 ip4 = 0, ip6 = 0;
1259 
1260  if (!unformat_user (input, unformat_line_input, line_input))
1261  return 0;
1262 
1263  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1264  {
1265  if (unformat (line_input, "lifetime %u", &lifetime))
1266  ;
1267  else if (unformat (line_input, "ht-ratio %lf", &ht_ratio))
1268  ;
1269  else if (unformat (line_input, "pool-size %u", &pool_size))
1270  ;
1271  else if (unformat (line_input, "buffers %llu", &buffers))
1272  ;
1273  else if (unformat (line_input, "ip4"))
1274  ip4 = 1;
1275  else if (unformat (line_input, "ip6"))
1276  ip6 = 1;
1277  else
1278  {
1279  unformat_free (line_input);
1280  return clib_error_return (0, "invalid input");
1281  }
1282  }
1283  unformat_free (line_input);
1284 
1285  if (!ip4 && !ip6)
1286  return clib_error_return (0, "must specify ip4 and/or ip6");
1287 
1288  if (ip4)
1289  {
1290  if (pool_size != ~0 && pool_size > MAP_IP4_REASS_CONF_POOL_SIZE_MAX)
1291  return clib_error_return (0, "invalid ip4-reass pool-size ( > %d)",
1293  if (ht_ratio != (MAP_IP4_REASS_CONF_HT_RATIO_MAX + 1)
1294  && ht_ratio > MAP_IP4_REASS_CONF_HT_RATIO_MAX)
1295  return clib_error_return (0, "invalid ip4-reass ht-ratio ( > %d)",
1297  if (lifetime != ~0 && lifetime > MAP_IP4_REASS_CONF_LIFETIME_MAX)
1298  return clib_error_return (0, "invalid ip4-reass lifetime ( > %d)",
1300  if (buffers != ~(0ull) && buffers > MAP_IP4_REASS_CONF_BUFFERS_MAX)
1301  return clib_error_return (0, "invalid ip4-reass buffers ( > %ld)",
1303  }
1304 
1305  if (ip6)
1306  {
1307  if (pool_size != ~0 && pool_size > MAP_IP6_REASS_CONF_POOL_SIZE_MAX)
1308  return clib_error_return (0, "invalid ip6-reass pool-size ( > %d)",
1310  if (ht_ratio != (MAP_IP4_REASS_CONF_HT_RATIO_MAX + 1)
1311  && ht_ratio > MAP_IP6_REASS_CONF_HT_RATIO_MAX)
1312  return clib_error_return (0, "invalid ip6-reass ht-log2len ( > %d)",
1314  if (lifetime != ~0 && lifetime > MAP_IP6_REASS_CONF_LIFETIME_MAX)
1315  return clib_error_return (0, "invalid ip6-reass lifetime ( > %d)",
1317  if (buffers != ~(0ull) && buffers > MAP_IP6_REASS_CONF_BUFFERS_MAX)
1318  return clib_error_return (0, "invalid ip6-reass buffers ( > %ld)",
1320  }
1321 
1322  if (ip4)
1323  {
1324  u32 reass = 0, packets = 0;
1325  if (pool_size != ~0)
1326  {
1327  if (map_ip4_reass_conf_pool_size (pool_size, &reass, &packets))
1328  {
1329  vlib_cli_output (vm, "Could not set ip4-reass pool-size");
1330  }
1331  else
1332  {
1333  vlib_cli_output (vm,
1334  "Setting ip4-reass pool-size (destroyed-reassembly=%u , dropped-fragments=%u)",
1335  reass, packets);
1336  }
1337  }
1338  if (ht_ratio != (MAP_IP4_REASS_CONF_HT_RATIO_MAX + 1))
1339  {
1340  if (map_ip4_reass_conf_ht_ratio (ht_ratio, &reass, &packets))
1341  {
1342  vlib_cli_output (vm, "Could not set ip4-reass ht-log2len");
1343  }
1344  else
1345  {
1346  vlib_cli_output (vm,
1347  "Setting ip4-reass ht-log2len (destroyed-reassembly=%u , dropped-fragments=%u)",
1348  reass, packets);
1349  }
1350  }
1351  if (lifetime != ~0)
1352  {
1353  if (map_ip4_reass_conf_lifetime (lifetime))
1354  vlib_cli_output (vm, "Could not set ip4-reass lifetime");
1355  else
1356  vlib_cli_output (vm, "Setting ip4-reass lifetime");
1357  }
1358  if (buffers != ~(0ull))
1359  {
1360  if (map_ip4_reass_conf_buffers (buffers))
1361  vlib_cli_output (vm, "Could not set ip4-reass buffers");
1362  else
1363  vlib_cli_output (vm, "Setting ip4-reass buffers");
1364  }
1365 
1366  if (map_main.ip4_reass_conf_buffers >
1367  map_main.ip4_reass_conf_pool_size *
1369  {
1370  vlib_cli_output (vm,
1371  "Note: 'ip4-reass buffers' > pool-size * max-fragments-per-reassembly.");
1372  }
1373  }
1374 
1375  if (ip6)
1376  {
1377  u32 reass = 0, packets = 0;
1378  if (pool_size != ~0)
1379  {
1380  if (map_ip6_reass_conf_pool_size (pool_size, &reass, &packets))
1381  {
1382  vlib_cli_output (vm, "Could not set ip6-reass pool-size");
1383  }
1384  else
1385  {
1386  vlib_cli_output (vm,
1387  "Setting ip6-reass pool-size (destroyed-reassembly=%u , dropped-fragments=%u)",
1388  reass, packets);
1389  }
1390  }
1391  if (ht_ratio != (MAP_IP4_REASS_CONF_HT_RATIO_MAX + 1))
1392  {
1393  if (map_ip6_reass_conf_ht_ratio (ht_ratio, &reass, &packets))
1394  {
1395  vlib_cli_output (vm, "Could not set ip6-reass ht-log2len");
1396  }
1397  else
1398  {
1399  vlib_cli_output (vm,
1400  "Setting ip6-reass ht-log2len (destroyed-reassembly=%u , dropped-fragments=%u)",
1401  reass, packets);
1402  }
1403  }
1404  if (lifetime != ~0)
1405  {
1406  if (map_ip6_reass_conf_lifetime (lifetime))
1407  vlib_cli_output (vm, "Could not set ip6-reass lifetime");
1408  else
1409  vlib_cli_output (vm, "Setting ip6-reass lifetime");
1410  }
1411  if (buffers != ~(0ull))
1412  {
1413  if (map_ip6_reass_conf_buffers (buffers))
1414  vlib_cli_output (vm, "Could not set ip6-reass buffers");
1415  else
1416  vlib_cli_output (vm, "Setting ip6-reass buffers");
1417  }
1418 
1419  if (map_main.ip6_reass_conf_buffers >
1420  map_main.ip6_reass_conf_pool_size *
1422  {
1423  vlib_cli_output (vm,
1424  "Note: 'ip6-reass buffers' > pool-size * max-fragments-per-reassembly.");
1425  }
1426  }
1427 
1428  return 0;
1429 }
1430 
1431 
1432 /*
1433  * packet trace format function
1434  */
1435 u8 *
1436 format_map_trace (u8 * s, va_list * args)
1437 {
1438  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1439  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1440  map_trace_t *t = va_arg (*args, map_trace_t *);
1441  u32 map_domain_index = t->map_domain_index;
1442  u16 port = t->port;
1443 
1444  s =
1445  format (s, "MAP domain index: %d L4 port: %u", map_domain_index,
1446  clib_net_to_host_u16 (port));
1447 
1448  return s;
1449 }
1450 
1453 {
1454  map_main_t *mm = &map_main;
1455  u32 ri = mm->ip4_reass_hash_table[bucket];
1456  while (ri != MAP_REASS_INDEX_NONE)
1457  {
1459  if (r->key.as_u64[0] == k->as_u64[0] &&
1460  r->key.as_u64[1] == k->as_u64[1] &&
1461  now < r->ts + (((f64) mm->ip4_reass_conf_lifetime_ms) / 1000))
1462  {
1463  return r;
1464  }
1465  ri = r->bucket_next;
1466  }
1467  return NULL;
1468 }
1469 
1470 #define map_ip4_reass_pool_index(r) (r - map_main.ip4_reass_pool)
1471 
1472 void
1474 {
1475  map_main_t *mm = &map_main;
1476  map_ip4_reass_get_fragments (r, pi_to_drop);
1477 
1478  // Unlink in hash bucket
1479  map_ip4_reass_t *r2 = NULL;
1480  u32 r2i = mm->ip4_reass_hash_table[r->bucket];
1481  while (r2i != map_ip4_reass_pool_index (r))
1482  {
1483  ASSERT (r2i != MAP_REASS_INDEX_NONE);
1484  r2 = pool_elt_at_index (mm->ip4_reass_pool, r2i);
1485  r2i = r2->bucket_next;
1486  }
1487  if (r2)
1488  {
1489  r2->bucket_next = r->bucket_next;
1490  }
1491  else
1492  {
1494  }
1495 
1496  // Unlink in list
1497  if (r->fifo_next == map_ip4_reass_pool_index (r))
1498  {
1500  }
1501  else
1502  {
1504  mm->ip4_reass_fifo_last = r->fifo_prev;
1505  pool_elt_at_index (mm->ip4_reass_pool, r->fifo_prev)->fifo_next =
1506  r->fifo_next;
1507  pool_elt_at_index (mm->ip4_reass_pool, r->fifo_next)->fifo_prev =
1508  r->fifo_prev;
1509  }
1510 
1511  pool_put (mm->ip4_reass_pool, r);
1512  mm->ip4_reass_allocated--;
1513 }
1514 
1516 map_ip4_reass_get (u32 src, u32 dst, u16 fragment_id,
1517  u8 protocol, u32 ** pi_to_drop)
1518 {
1519  map_ip4_reass_t *r;
1520  map_main_t *mm = &map_main;
1521  map_ip4_reass_key_t k = {.src.data_u32 = src,
1522  .dst.data_u32 = dst,
1523  .fragment_id = fragment_id,
1524  .protocol = protocol
1525  };
1526 
1527  u32 h = 0;
1528 #ifdef clib_crc32c_uses_intrinsics
1529  h = clib_crc32c ((u8 *) k.as_u32, 16);
1530 #else
1531  u64 tmp = k.as_u32[0] ^ k.as_u32[1] ^ k.as_u32[2] ^ k.as_u32[3];
1532  h = clib_xxhash (tmp);
1533 #endif
1534  h = h >> (32 - mm->ip4_reass_ht_log2len);
1535 
1536  f64 now = vlib_time_now (mm->vlib_main);
1537 
1538  //Cache garbage collection
1540  {
1543  if (last->ts + (((f64) mm->ip4_reass_conf_lifetime_ms) / 1000) < now)
1544  map_ip4_reass_free (last, pi_to_drop);
1545  else
1546  break;
1547  }
1548 
1549  if ((r = map_ip4_reass_lookup (&k, h, now)))
1550  return r;
1551 
1553  return NULL;
1554 
1555  pool_get (mm->ip4_reass_pool, r);
1556  mm->ip4_reass_allocated++;
1557  int i;
1558  for (i = 0; i < MAP_IP4_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++)
1559  r->fragments[i] = ~0;
1560 
1561  u32 ri = map_ip4_reass_pool_index (r);
1562 
1563  //Link in new bucket
1564  r->bucket = h;
1566  mm->ip4_reass_hash_table[h] = ri;
1567 
1568  //Link in fifo
1570  {
1571  r->fifo_next =
1573  mm->ip4_reass_fifo_last)->fifo_next;
1574  r->fifo_prev = mm->ip4_reass_fifo_last;
1575  pool_elt_at_index (mm->ip4_reass_pool, r->fifo_prev)->fifo_next = ri;
1576  pool_elt_at_index (mm->ip4_reass_pool, r->fifo_next)->fifo_prev = ri;
1577  }
1578  else
1579  {
1580  r->fifo_next = r->fifo_prev = ri;
1581  mm->ip4_reass_fifo_last = ri;
1582  }
1583 
1584  //Set other fields
1585  r->ts = now;
1586  r->key = k;
1587  r->port = -1;
1588 #ifdef MAP_IP4_REASS_COUNT_BYTES
1589  r->expected_total = 0xffff;
1590  r->forwarded = 0;
1591 #endif
1592 
1593  return r;
1594 }
1595 
1596 int
1598 {
1599  if (map_main.ip4_reass_buffered_counter >= map_main.ip4_reass_conf_buffers)
1600  return -1;
1601 
1602  int i;
1603  for (i = 0; i < MAP_IP4_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++)
1604  if (r->fragments[i] == ~0)
1605  {
1606  r->fragments[i] = pi;
1607  map_main.ip4_reass_buffered_counter++;
1608  return 0;
1609  }
1610  return -1;
1611 }
1612 
1615 {
1616  map_main_t *mm = &map_main;
1617  u32 ri = mm->ip6_reass_hash_table[bucket];
1618  while (ri != MAP_REASS_INDEX_NONE)
1619  {
1621  if (now < r->ts + (((f64) mm->ip6_reass_conf_lifetime_ms) / 1000) &&
1622  r->key.as_u64[0] == k->as_u64[0] &&
1623  r->key.as_u64[1] == k->as_u64[1] &&
1624  r->key.as_u64[2] == k->as_u64[2] &&
1625  r->key.as_u64[3] == k->as_u64[3] &&
1626  r->key.as_u64[4] == k->as_u64[4])
1627  return r;
1628  ri = r->bucket_next;
1629  }
1630  return NULL;
1631 }
1632 
1633 #define map_ip6_reass_pool_index(r) (r - map_main.ip6_reass_pool)
1634 
1635 void
1637 {
1638  map_main_t *mm = &map_main;
1639  int i;
1640  for (i = 0; i < MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++)
1641  if (r->fragments[i].pi != ~0)
1642  {
1643  vec_add1 (*pi_to_drop, r->fragments[i].pi);
1644  r->fragments[i].pi = ~0;
1645  map_main.ip6_reass_buffered_counter--;
1646  }
1647 
1648  // Unlink in hash bucket
1649  map_ip6_reass_t *r2 = NULL;
1650  u32 r2i = mm->ip6_reass_hash_table[r->bucket];
1651  while (r2i != map_ip6_reass_pool_index (r))
1652  {
1653  ASSERT (r2i != MAP_REASS_INDEX_NONE);
1654  r2 = pool_elt_at_index (mm->ip6_reass_pool, r2i);
1655  r2i = r2->bucket_next;
1656  }
1657  if (r2)
1658  {
1659  r2->bucket_next = r->bucket_next;
1660  }
1661  else
1662  {
1664  }
1665 
1666  // Unlink in list
1667  if (r->fifo_next == map_ip6_reass_pool_index (r))
1668  {
1669  //Single element in the list, list is now empty
1671  }
1672  else
1673  {
1674  if (mm->ip6_reass_fifo_last == map_ip6_reass_pool_index (r)) //First element
1675  mm->ip6_reass_fifo_last = r->fifo_prev;
1676  pool_elt_at_index (mm->ip6_reass_pool, r->fifo_prev)->fifo_next =
1677  r->fifo_next;
1678  pool_elt_at_index (mm->ip6_reass_pool, r->fifo_next)->fifo_prev =
1679  r->fifo_prev;
1680  }
1681 
1682  // Free from pool if necessary
1683  pool_put (mm->ip6_reass_pool, r);
1684  mm->ip6_reass_allocated--;
1685 }
1686 
1689  u8 protocol, u32 ** pi_to_drop)
1690 {
1691  map_ip6_reass_t *r;
1692  map_main_t *mm = &map_main;
1693  map_ip6_reass_key_t k = {
1694  .src = *src,
1695  .dst = *dst,
1696  .fragment_id = fragment_id,
1697  .protocol = protocol
1698  };
1699 
1700  u32 h = 0;
1701  int i;
1702 
1703 #ifdef clib_crc32c_uses_intrinsics
1704  h = clib_crc32c ((u8 *) k.as_u32, 40);
1705 #else
1706  u64 tmp =
1707  k.as_u64[0] ^ k.as_u64[1] ^ k.as_u64[2] ^ k.as_u64[3] ^ k.as_u64[4];
1708  h = clib_xxhash (tmp);
1709 #endif
1710 
1711  h = h >> (32 - mm->ip6_reass_ht_log2len);
1712 
1713  f64 now = vlib_time_now (mm->vlib_main);
1714 
1715  //Cache garbage collection
1717  {
1720  if (last->ts + (((f64) mm->ip6_reass_conf_lifetime_ms) / 1000) < now)
1721  map_ip6_reass_free (last, pi_to_drop);
1722  else
1723  break;
1724  }
1725 
1726  if ((r = map_ip6_reass_lookup (&k, h, now)))
1727  return r;
1728 
1730  return NULL;
1731 
1732  pool_get (mm->ip6_reass_pool, r);
1733  mm->ip6_reass_allocated++;
1734  for (i = 0; i < MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++)
1735  {
1736  r->fragments[i].pi = ~0;
1737  r->fragments[i].next_data_len = 0;
1738  r->fragments[i].next_data_offset = 0;
1739  }
1740 
1741  u32 ri = map_ip6_reass_pool_index (r);
1742 
1743  //Link in new bucket
1744  r->bucket = h;
1746  mm->ip6_reass_hash_table[h] = ri;
1747 
1748  //Link in fifo
1750  {
1751  r->fifo_next =
1753  mm->ip6_reass_fifo_last)->fifo_next;
1754  r->fifo_prev = mm->ip6_reass_fifo_last;
1755  pool_elt_at_index (mm->ip6_reass_pool, r->fifo_prev)->fifo_next = ri;
1756  pool_elt_at_index (mm->ip6_reass_pool, r->fifo_next)->fifo_prev = ri;
1757  }
1758  else
1759  {
1760  r->fifo_next = r->fifo_prev = ri;
1761  mm->ip6_reass_fifo_last = ri;
1762  }
1763 
1764  //Set other fields
1765  r->ts = now;
1766  r->key = k;
1768 #ifdef MAP_IP6_REASS_COUNT_BYTES
1769  r->expected_total = 0xffff;
1770  r->forwarded = 0;
1771 #endif
1772  return r;
1773 }
1774 
1775 int
1777  u16 data_offset, u16 next_data_offset,
1778  u8 * data_start, u16 data_len)
1779 {
1780  map_ip6_fragment_t *f = NULL, *prev_f = NULL;
1781  u16 copied_len = (data_len > 20) ? 20 : data_len;
1782 
1783  if (map_main.ip6_reass_buffered_counter >= map_main.ip6_reass_conf_buffers)
1784  return -1;
1785 
1786  //Lookup for fragments for the current buffer
1787  //and the one before that
1788  int i;
1789  for (i = 0; i < MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++)
1790  {
1791  if (data_offset && r->fragments[i].next_data_offset == data_offset)
1792  {
1793  prev_f = &r->fragments[i]; // This is buffer for previous packet
1794  }
1795  else if (r->fragments[i].next_data_offset == next_data_offset)
1796  {
1797  f = &r->fragments[i]; // This is a buffer for the current packet
1798  }
1799  else if (r->fragments[i].next_data_offset == 0)
1800  { //Available
1801  if (f == NULL)
1802  f = &r->fragments[i];
1803  else if (prev_f == NULL)
1804  prev_f = &r->fragments[i];
1805  }
1806  }
1807 
1808  if (!f || f->pi != ~0)
1809  return -1;
1810 
1811  if (data_offset)
1812  {
1813  if (!prev_f)
1814  return -1;
1815 
1816  clib_memcpy (prev_f->next_data, data_start, copied_len);
1817  prev_f->next_data_len = copied_len;
1818  prev_f->next_data_offset = data_offset;
1819  }
1820  else
1821  {
1822  if (((ip4_header_t *) data_start)->ip_version_and_header_length != 0x45)
1823  return -1;
1824 
1826  clib_memcpy (&r->ip4_header, data_start, sizeof (ip4_header_t));
1827  }
1828 
1829  if (data_len > 20)
1830  {
1831  f->next_data_offset = next_data_offset;
1832  f->pi = pi;
1833  map_main.ip6_reass_buffered_counter++;
1834  }
1835  return 0;
1836 }
1837 
1838 void
1839 map_ip4_reass_reinit (u32 * trashed_reass, u32 * dropped_packets)
1840 {
1841  map_main_t *mm = &map_main;
1842  int i;
1843 
1844  if (dropped_packets)
1845  *dropped_packets = mm->ip4_reass_buffered_counter;
1846  if (trashed_reass)
1847  *trashed_reass = mm->ip4_reass_allocated;
1849  {
1850  u16 ri = mm->ip4_reass_fifo_last;
1851  do
1852  {
1854  for (i = 0; i < MAP_IP4_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++)
1855  if (r->fragments[i] != ~0)
1856  map_ip4_drop_pi (r->fragments[i]);
1857 
1858  ri = r->fifo_next;
1859  pool_put (mm->ip4_reass_pool, r);
1860  }
1861  while (ri != mm->ip4_reass_fifo_last);
1862  }
1863 
1866  for (i = 0; i < (1 << mm->ip4_reass_ht_log2len); i++)
1868  pool_free (mm->ip4_reass_pool);
1870 
1871  mm->ip4_reass_allocated = 0;
1874 }
1875 
1876 u8
1877 map_get_ht_log2len (f32 ht_ratio, u16 pool_size)
1878 {
1879  u32 desired_size = (u32) (pool_size * ht_ratio);
1880  u8 i;
1881  for (i = 1; i < 31; i++)
1882  if ((1 << i) >= desired_size)
1883  return i;
1884  return 4;
1885 }
1886 
1887 int
1888 map_ip4_reass_conf_ht_ratio (f32 ht_ratio, u32 * trashed_reass,
1889  u32 * dropped_packets)
1890 {
1891  map_main_t *mm = &map_main;
1892  if (ht_ratio > MAP_IP4_REASS_CONF_HT_RATIO_MAX)
1893  return -1;
1894 
1895  map_ip4_reass_lock ();
1896  mm->ip4_reass_conf_ht_ratio = ht_ratio;
1897  mm->ip4_reass_ht_log2len =
1899  map_ip4_reass_reinit (trashed_reass, dropped_packets);
1901  return 0;
1902 }
1903 
1904 int
1905 map_ip4_reass_conf_pool_size (u16 pool_size, u32 * trashed_reass,
1906  u32 * dropped_packets)
1907 {
1908  map_main_t *mm = &map_main;
1909  if (pool_size > MAP_IP4_REASS_CONF_POOL_SIZE_MAX)
1910  return -1;
1911 
1912  map_ip4_reass_lock ();
1913  mm->ip4_reass_conf_pool_size = pool_size;
1914  map_ip4_reass_reinit (trashed_reass, dropped_packets);
1916  return 0;
1917 }
1918 
1919 int
1921 {
1922  map_main.ip4_reass_conf_lifetime_ms = lifetime_ms;
1923  return 0;
1924 }
1925 
1926 int
1928 {
1929  map_main.ip4_reass_conf_buffers = buffers;
1930  return 0;
1931 }
1932 
1933 void
1934 map_ip6_reass_reinit (u32 * trashed_reass, u32 * dropped_packets)
1935 {
1936  map_main_t *mm = &map_main;
1937  if (dropped_packets)
1938  *dropped_packets = mm->ip6_reass_buffered_counter;
1939  if (trashed_reass)
1940  *trashed_reass = mm->ip6_reass_allocated;
1941  int i;
1943  {
1944  u16 ri = mm->ip6_reass_fifo_last;
1945  do
1946  {
1948  for (i = 0; i < MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++)
1949  if (r->fragments[i].pi != ~0)
1950  map_ip6_drop_pi (r->fragments[i].pi);
1951 
1952  ri = r->fifo_next;
1953  pool_put (mm->ip6_reass_pool, r);
1954  }
1955  while (ri != mm->ip6_reass_fifo_last);
1957  }
1958 
1961  for (i = 0; i < (1 << mm->ip6_reass_ht_log2len); i++)
1963  pool_free (mm->ip6_reass_pool);
1965 
1966  mm->ip6_reass_allocated = 0;
1968 }
1969 
1970 int
1971 map_ip6_reass_conf_ht_ratio (f32 ht_ratio, u32 * trashed_reass,
1972  u32 * dropped_packets)
1973 {
1974  map_main_t *mm = &map_main;
1975  if (ht_ratio > MAP_IP6_REASS_CONF_HT_RATIO_MAX)
1976  return -1;
1977 
1978  map_ip6_reass_lock ();
1979  mm->ip6_reass_conf_ht_ratio = ht_ratio;
1980  mm->ip6_reass_ht_log2len =
1982  map_ip6_reass_reinit (trashed_reass, dropped_packets);
1984  return 0;
1985 }
1986 
1987 int
1988 map_ip6_reass_conf_pool_size (u16 pool_size, u32 * trashed_reass,
1989  u32 * dropped_packets)
1990 {
1991  map_main_t *mm = &map_main;
1992  if (pool_size > MAP_IP6_REASS_CONF_POOL_SIZE_MAX)
1993  return -1;
1994 
1995  map_ip6_reass_lock ();
1996  mm->ip6_reass_conf_pool_size = pool_size;
1997  map_ip6_reass_reinit (trashed_reass, dropped_packets);
1999  return 0;
2000 }
2001 
2002 int
2004 {
2005  map_main.ip6_reass_conf_lifetime_ms = lifetime_ms;
2006  return 0;
2007 }
2008 
2009 int
2011 {
2012  map_main.ip6_reass_conf_buffers = buffers;
2013  return 0;
2014 }
2015 
2016 /* *INDENT-OFF* */
2017 
2018 /*?
2019  * Configure MAP reassembly behaviour
2020  *
2021  * @cliexpar
2022  * @cliexstart{map params reassembly}
2023  * @cliexend
2024  ?*/
2025 VLIB_CLI_COMMAND(map_ip4_reass_lifetime_command, static) = {
2026  .path = "map params reassembly",
2027  .short_help = "map params reassembly [ip4 | ip6] [lifetime <lifetime-ms>] "
2028  "[pool-size <pool-size>] [buffers <buffers>] "
2029  "[ht-ratio <ht-ratio>]",
2030  .function = map_params_reass_command_fn,
2031 };
2032 
2033 /*?
2034  * Set or copy the IP TOS/Traffic Class field
2035  *
2036  * @cliexpar
2037  * @cliexstart{map params traffic-class}
2038  *
2039  * This command is used to set the traffic-class field in translated
2040  * or encapsulated packets. If copy is specifed (the default) then the
2041  * traffic-class/TOS field is copied from the original packet to the
2042  * translated / encapsulating header.
2043  * @cliexend
2044  ?*/
2045 VLIB_CLI_COMMAND(map_traffic_class_command, static) = {
2046  .path = "map params traffic-class",
2047  .short_help = "map params traffic-class {0x0-0xff | copy}",
2048  .function = map_traffic_class_command_fn,
2049 };
2050 
2051 /*?
2052  * Bypass IP4/IP6 lookup
2053  *
2054  * @cliexpar
2055  * @cliexstart{map params pre-resolve}
2056  *
2057  * Bypass a second FIB lookup of the translated or encapsulated
2058  * packet, and forward the packet directly to the specified
2059  * next-hop. This optimization trades forwarding flexibility for
2060  * performance.
2061  * @cliexend
2062  ?*/
2063 VLIB_CLI_COMMAND(map_pre_resolve_command, static) = {
2064  .path = "map params pre-resolve",
2065  .short_help = " map params pre-resolve {ip4-nh <address>} "
2066  "| {ip6-nh <address>}",
2067  .function = map_pre_resolve_command_fn,
2068 };
2069 
2070 /*?
2071  * Enable or disable the MAP-E inbound security check
2072  *
2073  * @cliexpar
2074  * @cliexstart{map params security-check}
2075  *
2076  * By default, a decapsulated packet's IPv4 source address will be
2077  * verified against the outer header's IPv6 source address. Disabling
2078  * this feature will allow IPv4 source address spoofing.
2079  * @cliexend
2080  ?*/
2081 VLIB_CLI_COMMAND(map_security_check_command, static) = {
2082  .path = "map params security-check",
2083  .short_help = "map params security-check on|off",
2084  .function = map_security_check_command_fn,
2085 };
2086 
2087 /*?
2088  * Specifiy the IPv4 source address used for relayed ICMP error messages
2089  *
2090  * @cliexpar
2091  * @cliexstart{map params icmp source-address}
2092  *
2093  * This command specifies which IPv4 source address (must be local to
2094  * the system), that is used for relayed received IPv6 ICMP error
2095  * messages.
2096  * @cliexend
2097  ?*/
2098 VLIB_CLI_COMMAND(map_icmp_relay_source_address_command, static) = {
2099  .path = "map params icmp source-address",
2100  .short_help = "map params icmp source-address <ip4-address>",
2102 };
2103 
2104 /*?
2105  * Send IPv6 ICMP unreachables
2106  *
2107  * @cliexpar
2108  * @cliexstart{map params icmp6 unreachables}
2109  *
2110  * Send IPv6 ICMP unreachable messages back if security check fails or
2111  * no MAP domain exists.
2112  * @cliexend
2113  ?*/
2114 VLIB_CLI_COMMAND(map_icmp_unreachables_command, static) = {
2115  .path = "map params icmp6 unreachables",
2116  .short_help = "map params icmp6 unreachables {on|off}",
2118 };
2119 
2120 /*?
2121  * Configure MAP fragmentation behaviour
2122  *
2123  * @cliexpar
2124  * @cliexstart{map params fragment}
2125  * @cliexend
2126  ?*/
2127 VLIB_CLI_COMMAND(map_fragment_command, static) = {
2128  .path = "map params fragment",
2129  .short_help = "map params fragment inner|outer",
2130  .function = map_fragment_command_fn,
2131 };
2132 
2133 /*?
2134  * Ignore the IPv4 Don't fragment bit
2135  *
2136  * @cliexpar
2137  * @cliexstart{map params fragment ignore-df}
2138  *
2139  * Allows fragmentation of the IPv4 packet even if the DF bit is
2140  * set. The choice between inner or outer fragmentation of tunnel
2141  * packets is complicated. The benefit of inner fragmentation is that
2142  * the ultimate endpoint must reassemble, instead of the tunnel
2143  * endpoint.
2144  * @cliexend
2145  ?*/
2146 VLIB_CLI_COMMAND(map_fragment_df_command, static) = {
2147  .path = "map params fragment ignore-df",
2148  .short_help = "map params fragment ignore-df on|off",
2149  .function = map_fragment_df_command_fn,
2150 };
2151 
2152 /*?
2153  * Specifiy if the inbound security check should be done on fragments
2154  *
2155  * @cliexpar
2156  * @cliexstart{map params security-check fragments}
2157  *
2158  * Typically the inbound on-decapsulation security check is only done
2159  * on the first packet. The packet that contains the L4
2160  * information. While a security check on every fragment is possible,
2161  * it has a cost. State must be created on the first fragment.
2162  * @cliexend
2163  ?*/
2164 VLIB_CLI_COMMAND(map_security_check_frag_command, static) = {
2165  .path = "map params security-check fragments",
2166  .short_help = "map params security-check fragments on|off",
2168 };
2169 
2170 /*?
2171  * Add MAP domain
2172  *
2173  * @cliexpar
2174  * @cliexstart{map add domain}
2175  * @cliexend
2176  ?*/
2177 VLIB_CLI_COMMAND(map_add_domain_command, static) = {
2178  .path = "map add domain",
2179  .short_help = "map add domain ip4-pfx <ip4-pfx> ip6-pfx <ip6-pfx> "
2180  "ip6-src <ip6-pfx> ea-bits-len <n> psid-offset <n> psid-len <n> "
2181  "[map-t] [map-ce] [mtu <mtu>]",
2182  .function = map_add_domain_command_fn,
2183 };
2184 
2185 /*?
2186  * Add MAP rule to a domain
2187  *
2188  * @cliexpar
2189  * @cliexstart{map add rule}
2190  * @cliexend
2191  ?*/
2192 VLIB_CLI_COMMAND(map_add_rule_command, static) = {
2193  .path = "map add rule",
2194  .short_help = "map add rule index <domain> psid <psid> ip6-dst <ip6-addr>",
2195  .function = map_add_rule_command_fn,
2196 };
2197 
2198 /*?
2199  * Delete MAP domain
2200  *
2201  * @cliexpar
2202  * @cliexstart{map del domain}
2203  * @cliexend
2204  ?*/
2205 VLIB_CLI_COMMAND(map_del_command, static) = {
2206  .path = "map del domain",
2207  .short_help = "map del domain index <domain>",
2208  .function = map_del_domain_command_fn,
2209 };
2210 
2211 /*?
2212  * Show MAP domains
2213  *
2214  * @cliexpar
2215  * @cliexstart{show map domain}
2216  * @cliexend
2217  ?*/
2218 VLIB_CLI_COMMAND(show_map_domain_command, static) = {
2219  .path = "show map domain",
2220  .short_help = "show map domain index <n> [counters]",
2221  .function = show_map_domain_command_fn,
2222 };
2223 
2224 /*?
2225  * Show MAP statistics
2226  *
2227  * @cliexpar
2228  * @cliexstart{show map stats}
2229  * @cliexend
2230  ?*/
2231 VLIB_CLI_COMMAND(show_map_stats_command, static) = {
2232  .path = "show map stats",
2233  .short_help = "show map stats",
2234  .function = show_map_stats_command_fn,
2235 };
2236 
2237 /*?
2238  * Show MAP fragmentation information
2239  *
2240  * @cliexpar
2241  * @cliexstart{show map fragments}
2242  * @cliexend
2243  ?*/
2244 VLIB_CLI_COMMAND(show_map_fragments_command, static) = {
2245  .path = "show map fragments",
2246  .short_help = "show map fragments",
2247  .function = show_map_fragments_command_fn,
2248 };
2249 
2251  .version = VPP_BUILD_VER,
2252  .description = "Mapping of address and port (MAP)",
2253 };
2254 
2255 /* *INDENT-ON* */
2256 
2257 static clib_error_t *
2259 {
2260  map_main_t *mm = &map_main;
2261  u8 is_ce = false;
2262 
2263  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2264  {
2265  if (unformat (input, "customer edge"))
2266  is_ce = true;
2267  else
2268  return clib_error_return (0, "unknown input '%U'",
2269  format_unformat_error, input);
2270  }
2271 
2272  mm->is_ce = is_ce;
2273 
2274  return 0;
2275 }
2276 
2278 
2279 /*
2280  * map_init
2281  */
2282 clib_error_t *
2284 {
2285  map_main_t *mm = &map_main;
2286  clib_error_t *error = 0;
2287  mm->vnet_main = vnet_get_main ();
2288  mm->vlib_main = vm;
2289 
2290 #ifdef MAP_SKIP_IP6_LOOKUP
2291  fib_protocol_t proto;
2292 
2293  FOR_EACH_FIB_PROTOCOL (proto)
2294  {
2295  map_pre_resolve_init (&pre_resolved[proto]);
2296  }
2297 #endif
2298 
2299  /* traffic class */
2300  mm->tc = 0;
2301  mm->tc_copy = true;
2302 
2303  /* Inbound security check */
2304  mm->sec_check = true;
2305  mm->sec_check_frag = false;
2306 
2307  /* ICMP6 Type 1, Code 5 for security check failure */
2308  mm->icmp6_enabled = false;
2309 
2310  mm->is_ce = false;
2311 
2312  /* Inner or outer fragmentation */
2313  mm->frag_inner = false;
2314  mm->frag_ignore_df = false;
2315 
2319 
2322 
2323  /* IP4 virtual reassembly */
2324  mm->ip4_reass_hash_table = 0;
2325  mm->ip4_reass_pool = 0;
2326  mm->ip4_reass_lock =
2328  *mm->ip4_reass_lock = 0;
2333  mm->ip4_reass_ht_log2len =
2338 
2339  /* IP6 virtual reassembly */
2340  mm->ip6_reass_hash_table = 0;
2341  mm->ip6_reass_pool = 0;
2342  mm->ip6_reass_lock =
2344  *mm->ip6_reass_lock = 0;
2349  mm->ip6_reass_ht_log2len =
2354 
2355 #ifdef MAP_SKIP_IP6_LOOKUP
2357 #endif
2359 
2360  error = map_plugin_api_hookup (vm);
2361 
2362  return error;
2363 }
2364 
2366 
2367 /*
2368  * fd.io coding-style-patch-verification: ON
2369  *
2370  * Local Variables:
2371  * eval: (c-set-style "gnu")
2372  * End:
2373  */
u16 forwarded
Definition: map.h:186
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:437
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:202
#define map_ip4_reass_lock()
Definition: map.h:477
u8 psid_length
Definition: map.h:97
map_ip4_reass_t * ip4_reass_pool
Definition: map.h:270
Recursive resolution source.
Definition: fib_entry.h:125
u32 ip4_reass_conf_buffers
Definition: map.h:267
u32 error_heap_index
Definition: node.h:314
fib_node_t node
Linkage into the FIB graph.
Definition: map.h:205
static clib_error_t * map_fragment_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:862
#define CLIB_UNUSED(x)
Definition: clib.h:79
#define MAP_IP6_REASS_CONF_BUFFERS_MAX
Definition: map.h:531
u32 as_u32[4]
Definition: map.h:125
int map_delete_domain(u32 map_domain_index)
Definition: map.c:258
#define MAP_IP6_REASS_BUFFERS_DEFAULT
Definition: map.h:68
map_domain_flags_e flags
Definition: map.h:92
map_main_t map_main
Definition: map.c:27
u16 fifo_prev
Definition: map.h:190
void vlib_validate_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
validate a combined counter
Definition: counter.c:106
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:428
u16 ip4_reass_allocated
Definition: map.h:272
volatile u32 * ip6_reass_lock
Definition: map.h:298
u8 ip4_reass_ht_log2len
Definition: map.h:271
u32 fragments[MAP_IP4_REASS_MAX_FRAGMENTS_PER_REASSEMBLY]
Definition: map.h:142
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
#define MAP_IP6_REASS_LIFETIME_DEFAULT
Definition: map.h:65
static_always_inline map_ip6_reass_t * map_ip6_reass_lookup(map_ip6_reass_key_t *k, u32 bucket, f64 now)
Definition: map.c:1614
#define pool_alloc(P, N)
Allocate N more free elements to pool (unspecified alignment).
Definition: pool.h:329
u16 bucket_next
Definition: map.h:189
void fib_node_init(fib_node_t *node, fib_node_type_t type)
Definition: fib_node.c:185
u32 fib_entry_child_add(fib_node_index_t fib_entry_index, fib_node_type_t child_type, fib_node_index_t child_index)
Definition: fib_entry.c:527
u64 as_u64[2]
Definition: ip6_packet.h:51
void fib_entry_get_prefix(fib_node_index_t fib_entry_index, fib_prefix_t *pfx)
Definition: fib_entry.c:1616
unsigned long u64
Definition: types.h:89
map_error_t
Definition: map.h:327
dpo_id_t dpo
The Load-balance object index to use to forward.
Definition: map.h:220
#define NULL
Definition: clib.h:55
static u8 * format_map_domain(u8 *s, va_list *args)
Definition: map.c:975
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:228
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:1064
void map_ip4_reass_reinit(u32 *trashed_reass, u32 *dropped_packets)
Definition: map.c:1839
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:511
u64 map_error_counter_get(u32 node_index, map_error_t map_error)
Definition: map.c:1138
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:478
static clib_error_t * map_fragment_df_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:894
vlib_main_t * vlib_main
Definition: map.h:257
u8 tc
Definition: map.h:243
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:444
static clib_error_t * show_map_fragments_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:1121
void fib_entry_child_remove(fib_node_index_t fib_entry_index, u32 sibling_index)
Definition: fib_entry.c:538
A pre-resolved next-hop.
Definition: map.h:200
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:261
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:523
static void map_domain_counter_unlock(map_main_t *mm)
Definition: map.h:558
Combined counter to hold both packets and byte differences.
Definition: counter.h:140
static u64 clib_xxhash(u64 key)
Definition: xxhash.h:58
static heap_elt_t * last(heap_header_t *h)
Definition: heap.c:53
u16 vlib_error_t
Definition: error.h:44
int i
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
format_function_t format_ip46_address
Definition: format.h:61
u32 suffix_mask
Definition: map.h:88
bool sec_check_frag
Definition: map.h:247
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:62
u32 ip4_reass_buffered_counter
Definition: map.h:278
static u8 * format_map_ip4_reass(u8 *s, va_list *args)
Definition: map.c:1029
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:451
u16 ip4_reass_fifo_last
Definition: map.h:274
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:228
vhost_vring_addr_t addr
Definition: vhost_user.h:116
int map_ip6_reass_conf_ht_ratio(f32 ht_ratio, u32 *trashed_reass, u32 *dropped_packets)
Definition: map.c:1971
unsigned char u8
Definition: types.h:56
#define MAP_IP6_REASS_CONF_LIFETIME_MAX
Definition: map.h:529
u64 as_u64[5]
Definition: map.h:169
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
map_ip6_reass_t * ip6_reass_pool
Definition: map.h:293
map_ip6_fragment_t fragments[MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY]
Definition: map.h:193
u16 port
Definition: map.h:338
double f64
Definition: types.h:142
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
#define map_ip6_reass_unlock()
Definition: map.h:503
static void map_pre_resolve(ip4_address_t *ip4, ip6_address_t *ip6, int is_del)
Definition: map.c:481
IPv[46] Mapping.
Definition: fib_entry.h:90
void map_dpo_create(dpo_proto_t dproto, u32 domain_index, dpo_id_t *dpo)
A representation of a MAP DPO.
Definition: map_dpo.c:26
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:98
format_function_t format_ip4_address
Definition: format.h:81
#define MAP_IP4_REASS_MAX_FRAGMENTS_PER_REASSEMBLY
Definition: map.h:63
bool tc_copy
Definition: map.h:244
#define static_always_inline
Definition: clib.h:93
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:443
unformat_function_t unformat_ip4_address
Definition: format.h:76
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:744
#define MAP_REASS_INDEX_NONE
Definition: map.h:111
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:156
map_ip4_reass_key_t key
Definition: map.h:131
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:823
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a &#39;special&#39; entry from the FIB.
Definition: fib_table.c:407
u16 bucket
Definition: map.h:188
vlib_combined_counter_main_t * domain_counters
Definition: map.h:236
ip4_address_t icmp4_src_address
Definition: map.h:253
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:577
Aggregrate type for a prefix.
Definition: fib_types.h:193
u16 fifo_next
Definition: map.h:141
#define clib_error_return(e, args...)
Definition: error.h:99
vlib_simple_counter_main_t icmp_relayed
Definition: map.h:254
int map_ip4_reass_add_fragment(map_ip4_reass_t *r, u32 pi)
Definition: map.c:1597
ip6_address_t * rules
Definition: map.h:87
u8 map_get_ht_log2len(f32 ht_ratio, u16 pool_size)
Definition: map.c:1877
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
Definition: vec.h:240
u8 ea_bits_len
Definition: map.h:95
unsigned int u32
Definition: types.h:88
u8 ip6_prefix_len
Definition: map.h:93
#define MAP_IP4_REASS_CONF_LIFETIME_MAX
Definition: map.h:517
static_always_inline map_ip4_reass_t * map_ip4_reass_lookup(map_ip4_reass_key_t *k, u32 bucket, f64 now)
Definition: map.c:1452
u16 ip6_reass_allocated
Definition: map.h:295
int map_add_del_psid(u32 map_domain_index, u16 psid, ip6_address_t *tep, u8 is_add)
Definition: map.c:302
Definition: fib_entry.h:275
unformat_function_t unformat_line_input
Definition: format.h:282
#define MAP_IP6_REASS_CONF_POOL_SIZE_MAX
Definition: map.h:527
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:168
Definition: fib_entry.h:279
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:464
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:278
int map_ip6_reass_conf_buffers(u32 buffers)
Definition: map.c:2010
#define map_ip4_reass_pool_index(r)
Definition: map.c:1470
counter_t packets
packet counter
Definition: counter.h:142
bool is_ce
Definition: map.h:250
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:694
int map_ip4_reass_conf_lifetime(u16 lifetime_ms)
Definition: map.c:1920
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:216
vlib_error_main_t error_main
Definition: main.h:144
static map_main_pre_resolved_t * map_from_fib_node(fib_node_t *node)
Definition: map.c:395
#define MAP_IP4_REASS_BUFFERS_DEFAULT
Definition: map.h:61
#define MAP_IP4_REASS_CONF_HT_RATIO_MAX
Definition: map.h:513
static u8 * format_map_ip6_reass(u8 *s, va_list *args)
Definition: map.c:1047
bool frag_ignore_df
Definition: map.h:281
volatile u32 * ip4_reass_lock
Definition: map.h:275
#define v
Definition: acl.c:491
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:120
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
u16 ip4_reass_conf_pool_size
Definition: map.h:265
map_domain_t * domains
Definition: map.h:232
static clib_error_t * map_config(vlib_main_t *vm, unformat_input_t *input)
Definition: map.c:2258
u16 bucket
Definition: map.h:138
int map_ip4_reass_conf_buffers(u32 buffers)
Definition: map.c:1927
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:274
void map_t_dpo_create(dpo_proto_t dproto, u32 domain_index, dpo_id_t *dpo)
Definition: map_dpo.c:37
#define FOR_EACH_FIB_PROTOCOL(_item)
Definition: fib_types.h:65
void map_dpo_module_init(void)
Definition: map_dpo.c:126
int map_ip6_reass_conf_lifetime(u16 lifetime_ms)
Definition: map.c:2003
map_ip4_reass_t * map_ip4_reass_get(u32 src, u32 dst, u16 fragment_id, u8 protocol, u32 **pi_to_drop)
Definition: map.c:1516
int map_ip4_reass_conf_pool_size(u16 pool_size, u32 *trashed_reass, u32 *dropped_packets)
Definition: map.c:1905
u16 * ip6_reass_hash_table
Definition: map.h:296
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:164
u16 * ip4_reass_hash_table
Definition: map.h:273
fib_node_type_t fn_type
The node&#39;s type.
Definition: fib_node.h:291
An node in the FIB graph.
Definition: fib_node.h:287
#define MAP_IP4_REASS_HT_RATIO_DEFAULT
Definition: map.h:59
u8 ip6_src_len
Definition: map.h:94
u8 psid_shift
Definition: map.h:100
u16 expected_total
Definition: map.h:134
static u32 vlib_error_get_code(vlib_error_t e)
Definition: error.h:53
u8 suffix_shift
Definition: map.h:101
u32 flags
Definition: vhost_user.h:110
unformat_function_t unformat_ip6_address
Definition: format.h:97
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
Definition: pool.h:188
void map_ip4_drop_pi(u32 pi)
Definition: ip6_map.c:664
u8 ip6_reass_ht_log2len
Definition: map.h:294
u16 ip6_reass_fifo_last
Definition: map.h:297
#define pool_free(p)
Free a pool.
Definition: pool.h:357
void map_ip4_reass_free(map_ip4_reass_t *r, u32 **pi_to_drop)
Definition: map.c:1473
fib_node_index_t fib_table_entry_special_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags)
Add a &#39;special&#39; entry to the FIB.
Definition: fib_table.c:388
u64 * counters
Definition: error.h:78
static clib_error_t * map_params_reass_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:1250
u16 ip6_reass_conf_pool_size
Definition: map.h:288
u8 next_data_len
Definition: map.h:177
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
ip4_address_t ip4_prefix
Definition: map.h:89
u16 next_data_offset
Definition: map.h:176
static_always_inline void map_ip4_reass_get_fragments(map_ip4_reass_t *r, u32 **pi)
Definition: map.h:481
format_function_t format_ip6_address
Definition: format.h:99
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:252
vlib_main_t * vm
Definition: buffer.c:294
map_ip6_reass_t * map_ip6_reass_get(ip6_address_t *src, ip6_address_t *dst, u32 fragment_id, u8 protocol, u32 **pi_to_drop)
Definition: map.c:1688
#define MAP_IP6_REASS_POOL_SIZE_DEFAULT
Definition: map.h:67
u32 as_u32[10]
Definition: map.h:170
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
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)
Definition: map.c:65
u8 psid_offset
Definition: map.h:96
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:788
#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:275
u16 forwarded
Definition: map.h:135
#define clib_memcpy(a, b, c)
Definition: string.h:75
bool icmp6_enabled
Definition: map.h:248
u32 sibling
This object sibling index on the FIB entry&#39;s child dependency list.
Definition: map.h:215
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
map_ip6_reass_key_t key
Definition: map.h:182
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:271
static void map_pre_resolve_init(map_main_pre_resolved_t *pr)
Definition: map.c:353
ip6_address_t ip6_src
Definition: map.h:85
int map_ip4_reass_conf_ht_ratio(f32 ht_ratio, u32 *trashed_reass, u32 *dropped_packets)
Definition: map.c:1888
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:655
static void map_domain_counter_lock(map_main_t *mm)
Definition: map.h:551
f32 ip4_reass_conf_ht_ratio
Definition: map.h:264
Context passed between object during a back walk.
Definition: fib_node.h:200
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
fib_node_index_t fib_table_entry_special_dpo_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Add a &#39;special&#39; entry to the FIB that links to the DPO passed A special entry is an entry that the FI...
Definition: fib_table.c:307
void vlib_validate_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
validate a simple counter
Definition: counter.c:92
int map_ip6_reass_conf_pool_size(u16 pool_size, u32 *trashed_reass, u32 *dropped_packets)
Definition: map.c:1988
#define ASSERT(truth)
bool sec_check
Definition: map.h:246
long ctx[MAX_CONNS]
Definition: main.c:126
bool frag_inner
Definition: map.h:280
u16 psid_mask
Definition: map.h:90
void map_ip6_reass_reinit(u32 *trashed_reass, u32 *dropped_packets)
Definition: map.c:1934
static void clib_mem_free(void *p)
Definition: mem.h:179
ip4_header_t ip4_header
Definition: map.h:192
#define map_ip4_reass_unlock()
Definition: map.h:478
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:124
u8 * format_map_trace(u8 *s, va_list *args)
Definition: map.c:1436
#define MAP_IP6_REASS_HT_RATIO_DEFAULT
Definition: map.h:66
u8 ea_shift
Definition: map.h:102
static u8 * format_map_pre_resolve(u8 *s, va_list *ap)
Definition: map.c:360
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
ip6_address_t ip6_prefix
Definition: map.h:86
float f32
Definition: types.h:143
f32 ip6_reass_conf_ht_ratio
Definition: map.h:287
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:927
counter_t bytes
byte counter
Definition: counter.h:143
vnet_main_t * vnet_main
Definition: map.h:258
u16 mtu
Definition: map.h:91
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:184
#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:277
u16 ip6_reass_conf_lifetime_ms
Definition: map.h:289
fib_node_index_t fei
The FIB entry index of the next-hop.
Definition: map.h:210
#define map_ip6_reass_lock()
Definition: map.h:502
i32 port
Definition: map.h:137
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
#define MAP_IP4_REASS_POOL_SIZE_DEFAULT
Definition: map.h:60
#define MAP_IP6_REASS_CONF_HT_RATIO_MAX
Definition: map.h:525
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:195
char * name
The counter collection&#39;s name.
Definition: counter.h:186
A collection of combined counters.
Definition: counter.h:181
#define MAP_IP4_REASS_LIFETIME_DEFAULT
IP4 reassembly logic: One virtually reassembled flow requires a map_ip4_reass_t structure in order to...
Definition: map.h:58
u16 bucket_next
Definition: map.h:139
#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
#define MAP_IP4_REASS_CONF_POOL_SIZE_MAX
Definition: map.h:515
u8 ip4_prefix_len
Definition: map.h:105
A FIB graph nodes virtual function table.
Definition: fib_node.h:274
void map_ip6_reass_free(map_ip6_reass_t *r, u32 **pi_to_drop)
Definition: map.c:1636
vlib_simple_counter_main_t * simple_domain_counters
Definition: map.h:235
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:120
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
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:417
#define MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY
Definition: map.h:70
static void map_stack(map_main_pre_resolved_t *pr)
Definition: map.c:404
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:385
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:231
u16 ip4_reass_conf_lifetime_ms
Definition: map.h:266
#define vec_foreach(var, vec)
Vector iterator.
static clib_error_t * map_security_check_frag_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:544
u32 map_domain_index
Definition: map.h:337
#define MAP_IP4_REASS_CONF_BUFFERS_MAX
Definition: map.h:519
u64 as_u64[2]
Definition: map.h:124
u8 ip_version_and_header_length
Definition: ip4_packet.h:137
u16 fifo_prev
Definition: map.h:140
static char * map_flags_to_string(u32 flags)
Definition: map.c:963
u32 ip6_reass_buffered_counter
Definition: map.h:301
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:62
int map_ip6_reass_add_fragment(map_ip6_reass_t *r, u32 pi, u16 data_offset, u16 next_data_offset, u8 *data_start, u16 data_len)
Definition: map.c:1776
u16 expected_total
Definition: map.h:185
clib_error_t * map_init(vlib_main_t *vm)
Definition: map.c:2283
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:681
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:461
u16 fifo_next
Definition: map.h:191
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
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:1155
void map_ip6_drop_pi(u32 pi)
Definition: ip6_map.c:655
#define map_ip6_reass_pool_index(r)
Definition: map.c:1633
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
u32 ip6_reass_conf_buffers
Definition: map.h:290
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128