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