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