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