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