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