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