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