FD.io VPP  v16.06
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 "map.h"
19 
20 #ifndef __SSE4_2__
21 #include <vppinfra/xxhash.h>
22 
23 static inline u32
24 crc_u32(u32 data, u32 value)
25 {
26  u64 tmp = ((u64)data<<32) | (u64) value;
27  return (u32) clib_xxhash(tmp);
28 }
29 #endif
30 
31 /*
32  * This code supports the following MAP modes:
33  *
34  * Algorithmic Shared 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 Full IPv4 address (ea_bits_len > 0):
38  * ea_bits_len + ip4_prefix = 32
39  * psid_length = 0, ip6_prefix < 64, ip4_prefix <= 32
40  * Algorithmic IPv4 prefix (ea_bits_len > 0):
41  * ea_bits_len + ip4_prefix < 32
42  * psid_length = 0, ip6_prefix < 64, ip4_prefix <= 32
43  *
44  * Independent Shared IPv4 address (ea_bits_len = 0):
45  * ip4_prefix = 32
46  * psid_length > 0
47  * Rule IPv6 address = 128, Rule PSID Set
48  * Independent Full IPv4 address (ea_bits_len = 0):
49  * ip4_prefix = 32
50  * psid_length = 0, ip6_prefix = 128
51  * Independent IPv4 prefix (ea_bits_len = 0):
52  * ip4_prefix < 32
53  * psid_length = 0, ip6_prefix = 128
54  *
55  */
56 
57 /*
58  * This code supports MAP-T:
59  *
60  * With DMR prefix length equal to 96.
61  *
62  */
63 
64 
65 i32
66 ip4_get_port (ip4_header_t *ip, map_dir_e dir, u16 buffer_len)
67 {
68  //TODO: use buffer length
69  if (ip->ip_version_and_header_length != 0x45 ||
71  return -1;
72 
73  if (PREDICT_TRUE((ip->protocol == IP_PROTOCOL_TCP) ||
74  (ip->protocol == IP_PROTOCOL_UDP))) {
75  udp_header_t *udp = (void *)(ip + 1);
76  return (dir == MAP_SENDER) ? udp->src_port : udp->dst_port;
77  } else if (ip->protocol == IP_PROTOCOL_ICMP) {
78  icmp46_header_t *icmp = (void *)(ip + 1);
79  if (icmp->type == ICMP4_echo_request ||
80  icmp->type == ICMP4_echo_reply) {
81  return *((u16 *)(icmp + 1));
82  } else if (clib_net_to_host_u16(ip->length) >= 64) {
83  ip = (ip4_header_t *)(icmp + 2);
84  if (PREDICT_TRUE((ip->protocol == IP_PROTOCOL_TCP) ||
85  (ip->protocol == IP_PROTOCOL_UDP))) {
86  udp_header_t *udp = (void *)(ip + 1);
87  return (dir == MAP_SENDER) ? udp->dst_port : udp->src_port;
88  } else if (ip->protocol == IP_PROTOCOL_ICMP) {
89  icmp46_header_t *icmp = (void *)(ip + 1);
90  if (icmp->type == ICMP4_echo_request ||
91  icmp->type == ICMP4_echo_reply) {
92  return *((u16 *)(icmp + 1));
93  }
94  }
95  }
96  }
97  return -1;
98 }
99 
100 i32
101 ip6_get_port (ip6_header_t *ip6, map_dir_e dir, u16 buffer_len)
102 {
103  u8 l4_protocol;
104  u16 l4_offset;
105  u16 frag_offset;
106  u8 *l4;
107 
108  if (ip6_parse(ip6, buffer_len, &l4_protocol, &l4_offset, &frag_offset))
109  return -1;
110 
111  //TODO: Use buffer length
112 
113  if (frag_offset &&
114  ip6_frag_hdr_offset(((ip6_frag_hdr_t *)u8_ptr_add(ip6, frag_offset))))
115  return -1; //Can't deal with non-first fragment for now
116 
117  l4 = u8_ptr_add(ip6, l4_offset);
118  if (l4_protocol == IP_PROTOCOL_TCP ||
119  l4_protocol == IP_PROTOCOL_UDP) {
120  return (dir == MAP_SENDER) ? ((udp_header_t *)(l4))->src_port : ((udp_header_t *)(l4))->dst_port;
121  } else if (l4_protocol == IP_PROTOCOL_ICMP6) {
122  icmp46_header_t *icmp = (icmp46_header_t *)(l4);
123  if (icmp->type == ICMP6_echo_request) {
124  return (dir == MAP_SENDER) ? ((u16*)(icmp))[2] : -1;
125  } else if (icmp->type == ICMP6_echo_reply) {
126  return (dir == MAP_SENDER) ? -1 : ((u16*)(icmp))[2];
127  }
128  }
129  return -1;
130 }
131 
132 
133 int
135  u8 ip4_prefix_len,
136  ip6_address_t *ip6_prefix,
137  u8 ip6_prefix_len,
138  ip6_address_t *ip6_src,
139  u8 ip6_src_len,
140  u8 ea_bits_len,
141  u8 psid_offset,
142  u8 psid_length,
143  u32 *map_domain_index,
144  u16 mtu,
145  u8 flags)
146 {
147  map_main_t *mm = &map_main;
148  ip4_main_t *im4 = &ip4_main;
149  ip6_main_t *im6 = &ip6_main;
150  map_domain_t *d;
151  ip_adjacency_t adj;
154  u8 suffix_len;
155  uword *p;
156 
157  /* EA bits must be within the first 64 bits */
158  if (ea_bits_len > 0 && (ip6_prefix_len + ea_bits_len) > 64)
159  return -1;
160 
161  /* Sanity check on the src prefix length */
162  if (flags & MAP_DOMAIN_TRANSLATION) {
163  if (ip6_src_len != 96) {
164  clib_warning("MAP-T only supports ip6_src_len = 96 for now.");
165  return -1;
166  }
167  } else {
168  if (ip6_src_len != 128) {
169  clib_warning("MAP-E requires a BR address, not a prefix (ip6_src_len should be 128).");
170  return -1;
171  }
172  }
173 
174  /* Get domain index */
176  memset(d, 0, sizeof (*d));
177  *map_domain_index = d - mm->domains;
178 
179  /* Init domain struct */
180  d->ip4_prefix.as_u32 = ip4_prefix->as_u32;
181  d->ip4_prefix_len = ip4_prefix_len;
182  d->ip6_prefix = *ip6_prefix;
183  d->ip6_prefix_len = ip6_prefix_len;
184  d->ip6_src = *ip6_src;
185  d->ip6_src_len = ip6_src_len;
186  d->ea_bits_len = ea_bits_len;
187  d->psid_offset = psid_offset;
188  d->psid_length = psid_length;
189  d->mtu = mtu;
190  d->flags = flags;
191 
192  /* How many, and which bits to grab from the IPv4 DA */
193  if (ip4_prefix_len + ea_bits_len < 32) {
194  d->flags |= MAP_DOMAIN_PREFIX;
195  suffix_len = d->suffix_shift = 32 - ip4_prefix_len - ea_bits_len;
196  } else {
197  d->suffix_shift = 0;
198  suffix_len = 32 - ip4_prefix_len;
199  }
200  d->suffix_mask = (1<<suffix_len) - 1;
201 
202  d->psid_shift = 16 - psid_length - psid_offset;
203  d->psid_mask = (1 << d->psid_length) - 1;
204  d->ea_shift = 64 - ip6_prefix_len - suffix_len - d->psid_length;
205 
206  /* Init IP adjacency */
207  memset(&adj, 0, sizeof(adj));
208  adj.explicit_fib_index = ~0;
210  p = (uword *)&adj.rewrite_data[0];
211  *p = (uword) (*map_domain_index);
212 
213  if (ip4_get_route(im4, 0, 0, (u8 *)ip4_prefix, ip4_prefix_len)) {
214  clib_warning("IPv4 route already defined: %U/%d", format_ip4_address, ip4_prefix, ip4_prefix_len);
215  pool_put(mm->domains, d);
216  return -1;
217  }
218 
219  /* Create ip4 adjacency */
220  memset(&args4, 0, sizeof(args4));
221  args4.table_index_or_table_id = 0;
222  args4.flags = IP4_ROUTE_FLAG_ADD;
223  args4.dst_address.as_u32 = ip4_prefix->as_u32;
224  args4.dst_address_length = ip4_prefix_len;
225 
226  args4.adj_index = ~0;
227  args4.add_adj = &adj;
228  args4.n_add_adj = 1;
229  ip4_add_del_route(im4, &args4);
230 
231  /* Multiple MAP domains may share same source IPv6 TEP */
232  u32 ai = ip6_get_route(im6, 0, 0, ip6_src, ip6_src_len);
233  if (ai > 0) {
235  ip_adjacency_t *adj6 = ip_get_adjacency(lm6, ai);
236  if (adj6->lookup_next_index != IP_LOOKUP_NEXT_MAP &&
238  clib_warning("BR source address already assigned: %U", format_ip6_address, ip6_src);
239  pool_put(mm->domains, d);
240  return -1;
241  }
242  /* Shared source */
243  p = (uword *)&adj6->rewrite_data[0];
244  p[0] = ~0;
245 
246  /* Add refcount, so we don't accidentially delete the route underneath someone */
247  p[1]++;
248  } else {
249  /* Create ip6 adjacency. */
250  memset(&args6, 0, sizeof(args6));
251  args6.table_index_or_table_id = 0;
252  args6.flags = IP6_ROUTE_FLAG_ADD;
253  args6.dst_address.as_u64[0] = ip6_src->as_u64[0];
254  args6.dst_address.as_u64[1] = ip6_src->as_u64[1];
255  args6.dst_address_length = ip6_src_len;
256  args6.adj_index = ~0;
257  args6.add_adj = &adj;
258  args6.n_add_adj = 1;
259  ip6_add_del_route(im6, &args6);
260  }
261 
262  /* Validate packet/byte counters */
264  int i;
265  for (i = 0; i < vec_len(mm->simple_domain_counters); i++) {
266  vlib_validate_simple_counter(&mm->simple_domain_counters[i], *map_domain_index);
267  vlib_zero_simple_counter(&mm->simple_domain_counters[i], *map_domain_index);
268  }
269  for (i = 0; i < vec_len(mm->domain_counters); i++) {
270  vlib_validate_combined_counter(&mm->domain_counters[i], *map_domain_index);
271  vlib_zero_combined_counter(&mm->domain_counters[i], *map_domain_index);
272  }
274 
275  return 0;
276 }
277 
278 /*
279  * map_delete_domain
280  */
281 int
282 map_delete_domain (u32 map_domain_index)
283 {
284  map_main_t *mm = &map_main;
285  ip4_main_t *im4 = &ip4_main;
286  ip6_main_t *im6 = &ip6_main;
287  map_domain_t *d;
288  ip_adjacency_t adj;
291 
292  if (pool_is_free_index(mm->domains, map_domain_index)) {
293  clib_warning("MAP domain delete: domain does not exist: %d", map_domain_index);
294  return -1;
295  }
296 
297  d = pool_elt_at_index(mm->domains, map_domain_index);
298 
299  memset(&adj, 0, sizeof(adj));
300  adj.explicit_fib_index = ~0;
302 
303  /* Delete ip4 adjacency */
304  memset(&args4, 0, sizeof(args4));
305  args4.table_index_or_table_id = 0;
306  args4.flags = IP4_ROUTE_FLAG_DEL;
307  args4.dst_address.as_u32 = d->ip4_prefix.as_u32;
309  args4.adj_index = 0;
310  args4.add_adj = &adj;
311  args4.n_add_adj = 0;
312  ip4_add_del_route(im4, &args4);
313 
314  /* Delete ip6 adjacency */
315  u32 ai = ip6_get_route(im6, 0, 0, &d->ip6_src, d->ip6_src_len);
316  if (ai > 0) {
318  ip_adjacency_t *adj6 = ip_get_adjacency(lm6, ai);
319 
320  uword *p = (uword *)&adj6->rewrite_data[0];
321  /* Delete route when no other domains use this source */
322  if (p[1] == 0) {
323  memset(&args6, 0, sizeof (args6));
324  args6.table_index_or_table_id = 0;
325  args6.flags = IP6_ROUTE_FLAG_DEL;
326  args6.dst_address.as_u64[0] = d->ip6_src.as_u64[0];
327  args6.dst_address.as_u64[1] = d->ip6_src.as_u64[1];
328  args6.dst_address_length = d->ip6_src_len;
329  args6.adj_index = 0;
330  args6.add_adj = &adj;
331  args6.n_add_adj = 0;
332  ip6_add_del_route(im6, &args6);
333  }
334  p[1]--;
335  }
336  /* Deleting rules */
337  if (d->rules)
338  clib_mem_free(d->rules);
339 
340  pool_put(mm->domains, d);
341 
342  return 0;
343 }
344 
345 int
346 map_add_del_psid (u32 map_domain_index, u16 psid, ip6_address_t *tep,
347  u8 is_add)
348 {
349  map_domain_t *d;
350  map_main_t *mm = &map_main;
351 
352  if (pool_is_free_index(mm->domains, map_domain_index)) {
353  clib_warning("MAP rule: domain does not exist: %d", map_domain_index);
354  return -1;
355  }
356  d = pool_elt_at_index(mm->domains, map_domain_index);
357 
358  /* Rules are only used in 1:1 independent case */
359  if (d->ea_bits_len > 0)
360  return (-1);
361 
362  if (!d->rules) {
363  u32 l = (0x1 << d->psid_length) * sizeof(ip6_address_t);
365  if (!d->rules) return -1;
366  memset(d->rules, 0, l);
367  }
368 
369  if (psid >= (0x1 << d->psid_length)) {
370  clib_warning("MAP rule: PSID outside bounds: %d [%d]", psid, 0x1 << d->psid_length);
371  return -1;
372  }
373 
374  if (is_add) {
375  d->rules[psid] = *tep;
376  } else {
377  memset(&d->rules[psid], 0, sizeof(ip6_address_t));
378  }
379  return 0;
380 }
381 
382 #ifdef MAP_SKIP_IP6_LOOKUP
383 static void
385 {
386  map_main_t *mm = &map_main;
387  ip4_main_t *im4 = &ip4_main;
388  ip6_main_t *im6 = &ip6_main;
389 
390  if (ip6->as_u64[0] != 0 || ip6->as_u64[1] != 0) {
391  mm->adj6_index = ip6_fib_lookup_with_table(im6, 0, ip6);
392  clib_warning("FIB lookup results in: %u", mm->adj6_index);
393  }
394  if (ip4->as_u32 != 0) {
395  mm->adj4_index = ip4_fib_lookup_with_table(im4, 0, ip4, 0);
396  clib_warning("FIB lookup results in: %u", mm->adj4_index);
397  }
398 }
399 #endif
400 
401 static clib_error_t *
403  unformat_input_t *input,
404  vlib_cli_command_t *cmd)
405 {
406  unformat_input_t _line_input, *line_input = &_line_input;
407  map_main_t *mm = &map_main;
408  /* Get a line of input. */
409  if (!unformat_user(input, unformat_line_input, line_input))
410  return 0;
411 
412  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
413  if (unformat(line_input, "off"))
414  mm->sec_check = false;
415  else if (unformat(line_input, "on"))
416  mm->sec_check = true;
417  else
418  return clib_error_return(0, "unknown input `%U'",
419  format_unformat_error, input);
420  }
421  unformat_free(line_input);
422  return 0;
423 }
424 
425 static clib_error_t *
427  unformat_input_t *input,
428  vlib_cli_command_t *cmd)
429 {
430  unformat_input_t _line_input, *line_input = &_line_input;
431  map_main_t *mm = &map_main;
432  /* Get a line of input. */
433  if (!unformat_user(input, unformat_line_input, line_input))
434  return 0;
435 
436  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
437  if (unformat(line_input, "off"))
438  mm->sec_check_frag = false;
439  else if (unformat(line_input, "on"))
440  mm->sec_check_frag = true;
441  else
442  return clib_error_return(0, "unknown input `%U'",
443  format_unformat_error, input);
444  }
445  unformat_free(line_input);
446  return 0;
447 }
448 
449 static clib_error_t *
451  unformat_input_t *input,
452  vlib_cli_command_t *cmd)
453 {
454  unformat_input_t _line_input, *line_input = &_line_input;
455  ip4_address_t ip4_prefix;
456  ip6_address_t ip6_prefix;
457  ip6_address_t ip6_src;
458  u32 ip6_prefix_len, ip4_prefix_len, map_domain_index, ip6_src_len;
459  u32 num_m_args = 0;
460  /* Optional arguments */
461  u32 ea_bits_len, psid_offset = 0, psid_length = 0;
462  u32 mtu = 0;
463  u8 flags = 0;
464  ip6_src_len = 128;
465 
466  /* Get a line of input. */
467  if (!unformat_user(input, unformat_line_input, line_input))
468  return 0;
469 
470  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
471  if (unformat(line_input, "ip4-pfx %U/%d", unformat_ip4_address, &ip4_prefix, &ip4_prefix_len))
472  num_m_args++;
473  else if (unformat(line_input, "ip6-pfx %U/%d", unformat_ip6_address, &ip6_prefix, &ip6_prefix_len))
474  num_m_args++;
475  else if (unformat(line_input, "ip6-src %U/%d", unformat_ip6_address, &ip6_src, &ip6_src_len))
476  num_m_args++;
477  else if (unformat(line_input, "ip6-src %U", unformat_ip6_address, &ip6_src))
478  num_m_args++;
479  else if (unformat(line_input, "ea-bits-len %d", &ea_bits_len))
480  num_m_args++;
481  else if (unformat(line_input, "psid-offset %d", &psid_offset))
482  num_m_args++;
483  else if (unformat(line_input, "psid-len %d", &psid_length))
484  num_m_args++;
485  else if (unformat(line_input, "mtu %d", &mtu))
486  num_m_args++;
487  else if (unformat(line_input, "map-t"))
488  flags |= MAP_DOMAIN_TRANSLATION;
489  else
490  return clib_error_return(0, "unknown input `%U'",
491  format_unformat_error, input);
492  }
493  unformat_free(line_input);
494 
495  if (num_m_args < 3)
496  return clib_error_return(0, "mandatory argument(s) missing");
497 
498  map_create_domain(&ip4_prefix, ip4_prefix_len,
499  &ip6_prefix, ip6_prefix_len, &ip6_src, ip6_src_len,
500  ea_bits_len, psid_offset, psid_length, &map_domain_index,
501  mtu, flags);
502 
503  return 0;
504 }
505 
506 static clib_error_t *
508  unformat_input_t *input,
509  vlib_cli_command_t *cmd)
510 {
511  unformat_input_t _line_input, *line_input = &_line_input;
512  u32 num_m_args = 0;
513  u32 map_domain_index;
514 
515  /* Get a line of input. */
516  if (! unformat_user(input, unformat_line_input, line_input))
517  return 0;
518 
519  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
520  if (unformat(line_input, "index %d", &map_domain_index))
521  num_m_args++;
522  else
523  return clib_error_return(0, "unknown input `%U'",
524  format_unformat_error, input);
525  }
526  unformat_free(line_input);
527 
528  if (num_m_args != 1)
529  return clib_error_return(0, "mandatory argument(s) missing");
530 
531  map_delete_domain(map_domain_index);
532 
533  return 0;
534 }
535 
536 static clib_error_t *
538  unformat_input_t *input,
539  vlib_cli_command_t *cmd)
540 {
541  unformat_input_t _line_input, *line_input = &_line_input;
542  ip6_address_t tep;
543  u32 num_m_args = 0;
544  u32 psid, map_domain_index;
545 
546  /* Get a line of input. */
547  if (! unformat_user(input, unformat_line_input, line_input))
548  return 0;
549 
550  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
551  if (unformat(line_input, "index %d", &map_domain_index))
552  num_m_args++;
553  else if (unformat(line_input, "psid %d", &psid))
554  num_m_args++;
555  else if (unformat(line_input, "ip6-dst %U", unformat_ip6_address, &tep))
556  num_m_args++;
557  else
558  return clib_error_return(0, "unknown input `%U'",
559  format_unformat_error, input);
560  }
561  unformat_free(line_input);
562 
563  if (num_m_args != 3)
564  return clib_error_return(0, "mandatory argument(s) missing");
565 
566  if (map_add_del_psid(map_domain_index, psid, &tep, 1) != 0) {
567  return clib_error_return(0, "Failing to add Mapping Rule");
568  }
569  return 0;
570 }
571 
572 #if MAP_SKIP_IP6_LOOKUP
573 static clib_error_t *
575  unformat_input_t *input,
576  vlib_cli_command_t *cmd)
577 {
578  unformat_input_t _line_input, *line_input = &_line_input;
579  ip4_address_t ip4nh;
580  ip6_address_t ip6nh;
581  map_main_t *mm = &map_main;
582 
583  memset(&ip4nh, 0, sizeof(ip4nh));
584  memset(&ip6nh, 0, sizeof(ip6nh));
585 
586  /* Get a line of input. */
587  if (!unformat_user(input, unformat_line_input, line_input))
588  return 0;
589 
590  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
591  if (unformat(line_input, "ip4-nh %U", unformat_ip4_address, &ip4nh))
592  mm->preresolve_ip4 = ip4nh;
593  else if (unformat(line_input, "ip6-nh %U", unformat_ip6_address, &ip6nh))
594  mm->preresolve_ip6 = ip6nh;
595  else
596  return clib_error_return(0, "unknown input `%U'",
597  format_unformat_error, input);
598  }
599  unformat_free(line_input);
600 
601  map_pre_resolve(&ip4nh, &ip6nh);
602 
603  return 0;
604 }
605 #endif
606 
607 static clib_error_t *
609  unformat_input_t *input,
610  vlib_cli_command_t *cmd)
611 {
612  unformat_input_t _line_input, *line_input = &_line_input;
613  ip4_address_t icmp_src_address;
614  map_main_t *mm = &map_main;
615 
616  mm->icmp4_src_address.as_u32 = 0;
617 
618  /* Get a line of input. */
619  if (!unformat_user(input, unformat_line_input, line_input))
620  return 0;
621 
622  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
623  if (unformat(line_input, "%U", unformat_ip4_address, &icmp_src_address))
624  mm->icmp4_src_address = icmp_src_address;
625  else
626  return clib_error_return(0, "unknown input `%U'",
627  format_unformat_error, input);
628  }
629  unformat_free(line_input);
630 
631  return 0;
632 }
633 
634 static clib_error_t *
636  unformat_input_t *input,
637  vlib_cli_command_t *cmd)
638 {
639  unformat_input_t _line_input, *line_input = &_line_input;
640  map_main_t *mm = &map_main;
641  int num_m_args = 0;
642 
643  /* Get a line of input. */
644  if (!unformat_user(input, unformat_line_input, line_input))
645  return 0;
646 
647  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
648  num_m_args++;
649  if (unformat(line_input, "on"))
650  mm->icmp6_enabled = true;
651  else if (unformat(line_input, "off"))
652  mm->icmp6_enabled = false;
653  else
654  return clib_error_return(0, "unknown input `%U'",
655  format_unformat_error, input);
656  }
657  unformat_free(line_input);
658 
659 
660  if (num_m_args != 1)
661  return clib_error_return(0, "mandatory argument(s) missing");
662 
663  return 0;
664 }
665 
666 static clib_error_t *
668  unformat_input_t *input,
669  vlib_cli_command_t *cmd)
670 {
671  unformat_input_t _line_input, *line_input = &_line_input;
672  map_main_t *mm = &map_main;
673 
674  /* Get a line of input. */
675  if (!unformat_user(input, unformat_line_input, line_input))
676  return 0;
677 
678  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
679  if (unformat(line_input, "inner"))
680  mm->frag_inner = true;
681  else if (unformat(line_input, "outer"))
682  mm->frag_inner = false;
683  else
684  return clib_error_return(0, "unknown input `%U'",
685  format_unformat_error, input);
686  }
687  unformat_free(line_input);
688 
689  return 0;
690 }
691 
692 static clib_error_t *
694  unformat_input_t *input,
695  vlib_cli_command_t *cmd)
696 {
697  unformat_input_t _line_input, *line_input = &_line_input;
698  map_main_t *mm = &map_main;
699 
700  /* Get a line of input. */
701  if (!unformat_user(input, unformat_line_input, line_input))
702  return 0;
703 
704  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
705  if (unformat(line_input, "on"))
706  mm->frag_ignore_df = true;
707  else if (unformat(line_input, "off"))
708  mm->frag_ignore_df = false;
709  else
710  return clib_error_return(0, "unknown input `%U'",
711  format_unformat_error, input);
712  }
713  unformat_free(line_input);
714 
715  return 0;
716 }
717 
718 static clib_error_t *
720  unformat_input_t *input,
721  vlib_cli_command_t *cmd)
722 {
723  unformat_input_t _line_input, *line_input = &_line_input;
724  map_main_t *mm = &map_main;
725  u32 tc = 0;
726 
727  mm->tc_copy = false;
728 
729  /* Get a line of input. */
730  if (!unformat_user(input, unformat_line_input, line_input))
731  return 0;
732 
733  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
734  if (unformat(line_input, "copy"))
735  mm->tc_copy = true;
736  else if (unformat(line_input, "%x", &tc))
737  mm->tc = tc & 0xff;
738  else
739  return clib_error_return(0, "unknown input `%U'",
740  format_unformat_error, input);
741  }
742  unformat_free(line_input);
743 
744  return 0;
745 }
746 
747 static u8 *
748 format_map_domain (u8 *s, va_list *args)
749 {
750  map_domain_t *d = va_arg(*args, map_domain_t *);
751  bool counters = va_arg(*args, int);
752  map_main_t *mm = &map_main;
753  ip6_address_t ip6_prefix;
754 
755  if (d->rules)
756  memset(&ip6_prefix, 0, sizeof(ip6_prefix));
757  else
758  ip6_prefix = d->ip6_prefix;
759 
760  s = format(s,
761  "[%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",
762  d - mm->domains,
764  format_ip6_address, &ip6_prefix, d->ip6_prefix_len,
766  d->ea_bits_len, d->psid_offset, d->psid_length, d->mtu,
767  (d->flags & MAP_DOMAIN_TRANSLATION) ? "map-t" : "");
768 
769  if (counters) {
771  vlib_counter_t v;
773  s = format(s, " TX: %lld/%lld", v.packets, v.bytes);
775  s = format(s, " RX: %lld/%lld", v.packets, v.bytes);
777  }
778  s = format(s, "\n");
779 
780  if (d->rules) {
781  int i;
782  ip6_address_t dst;
783  for (i = 0; i < (0x1 << d->psid_length); i++) {
784  dst = d->rules[i];
785  if (dst.as_u64[0] == 0 && dst.as_u64[1] == 0 )
786  continue;
787  s = format(s,
788  " rule psid: %d ip6-dst %U\n", i, format_ip6_address, &dst);
789  }
790  }
791  return s;
792 }
793 
794 static u8 *
795 format_map_ip4_reass (u8 *s, va_list *args)
796 {
797  map_main_t *mm = &map_main;
798  map_ip4_reass_t *r = va_arg(*args, map_ip4_reass_t *);
799  map_ip4_reass_key_t *k = &r->key;
800  f64 now = vlib_time_now(mm->vlib_main);
801  f64 lifetime = (((f64)mm->ip4_reass_conf_lifetime_ms) / 1000);
802  f64 dt = (r->ts + lifetime > now) ? (r->ts + lifetime - now) : -1;
803  s = format(s,
804  "ip4-reass src=%U dst=%U protocol=%d identifier=%d port=%d lifetime=%.3lf\n",
805  format_ip4_address, &k->src.as_u8, format_ip4_address, &k->dst.as_u8,
806  k->protocol, clib_net_to_host_u16(k->fragment_id), (r->port >= 0)?clib_net_to_host_u16(r->port):-1, dt);
807  return s;
808 }
809 
810 static u8 *
811 format_map_ip6_reass (u8 *s, va_list *args)
812 {
813  map_main_t *mm = &map_main;
814  map_ip6_reass_t *r = va_arg(*args, map_ip6_reass_t *);
815  map_ip6_reass_key_t *k = &r->key;
816  f64 now = vlib_time_now(mm->vlib_main);
817  f64 lifetime = (((f64)mm->ip6_reass_conf_lifetime_ms) / 1000);
818  f64 dt = (r->ts + lifetime > now) ? (r->ts + lifetime - now) : -1;
819  s = format(s,
820  "ip6-reass src=%U dst=%U protocol=%d identifier=%d lifetime=%.3lf\n",
821  format_ip6_address, &k->src.as_u8, format_ip6_address, &k->dst.as_u8,
822  k->protocol, clib_net_to_host_u32(k->fragment_id), dt);
823  return s;
824 }
825 
826 static clib_error_t *
828 {
829  unformat_input_t _line_input, *line_input = &_line_input;
830  map_main_t *mm = &map_main;
831  map_domain_t *d;
832  bool counters = false;
833  u32 map_domain_index = ~0;
834 
835  /* Get a line of input. */
836  if (!unformat_user(input, unformat_line_input, line_input))
837  return 0;
838 
839  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
840  if (unformat(line_input, "counters"))
841  counters = true;
842  else if (unformat(line_input, "index %d", &map_domain_index))
843  ;
844  else
845  return clib_error_return(0, "unknown input `%U'",
846  format_unformat_error, input);
847  }
848  unformat_free(line_input);
849 
850  if (pool_elts(mm->domains) == 0)
851  vlib_cli_output(vm, "No MAP domains are configured...");
852 
853  if (map_domain_index == ~0) {
854  pool_foreach(d, mm->domains, ({vlib_cli_output(vm, "%U", format_map_domain, d, counters);}));
855  } else {
856  if (pool_is_free_index(mm->domains, map_domain_index)) {
857  return clib_error_return(0, "MAP domain does not exists %d", map_domain_index);
858  }
859 
860  d = pool_elt_at_index(mm->domains, map_domain_index);
861  vlib_cli_output(vm, "%U", format_map_domain, d, counters);
862  }
863 
864  return 0;
865 }
866 
867 static clib_error_t *
869 {
870  map_main_t *mm = &map_main;
871  map_ip4_reass_t *f4;
872  map_ip6_reass_t *f6;
873 
874  pool_foreach(f4, mm->ip4_reass_pool, ({vlib_cli_output (vm, "%U", format_map_ip4_reass, f4);}));
875  pool_foreach(f6, mm->ip6_reass_pool, ({vlib_cli_output (vm, "%U", format_map_ip6_reass, f6);}));
876  return (0);
877 }
878 
879 u64
880 map_error_counter_get (u32 node_index, map_error_t map_error)
881 {
882  vlib_main_t *vm = vlib_get_main();
883  vlib_node_runtime_t *error_node = vlib_node_get_runtime(vm, node_index);
884  vlib_error_main_t *em = &vm->error_main;
885  vlib_error_t e = error_node->errors[map_error];
886  vlib_node_t *n = vlib_get_node(vm, node_index);
887  u32 ci;
888 
889  ci = vlib_error_get_code(e);
890  ASSERT (ci < n->n_errors);
891  ci += n->error_heap_index;
892 
893  return (em->counters[ci]);
894 }
895 
896 static clib_error_t *
898 {
899  map_main_t *mm = &map_main;
900  map_domain_t *d;
901  int domains = 0, rules = 0, domaincount = 0, rulecount = 0;
902  if (pool_elts (mm->domains) == 0)
903  vlib_cli_output(vm, "No MAP domains are configured...");
904 
905  pool_foreach(d, mm->domains, ({
906  if (d->rules) {
907  rulecount+= 0x1 << d->psid_length;
908  rules += sizeof(ip6_address_t) * 0x1 << d->psid_length;
909  }
910  domains += sizeof(*d);
911  domaincount++;
912  }));
913 
914  vlib_cli_output(vm, "MAP domains structure: %d\n", sizeof (map_domain_t));
915  vlib_cli_output(vm, "MAP domains: %d (%d bytes)\n", domaincount, domains);
916  vlib_cli_output(vm, "MAP rules: %d (%d bytes)\n", rulecount, rules);
917  vlib_cli_output(vm, "Total: %d bytes)\n", rules + domains);
918 
919 #if MAP_SKIP_IP6_LOOKUP
920  vlib_cli_output(vm, "MAP pre-resolve: IP6 next-hop: %U (%u), IP4 next-hop: %U (%u)\n",
921  format_ip6_address, &mm->preresolve_ip6, mm->adj6_index,
922  format_ip4_address, &mm->preresolve_ip4, mm->adj4_index);
923 #endif
924 
925  if (mm->tc_copy)
926  vlib_cli_output(vm, "MAP traffic-class: copy");
927  else
928  vlib_cli_output(vm, "MAP traffic-class: %x", mm->tc);
929 
930  vlib_cli_output(vm, "MAP IPv6 inbound security check: %s, fragmented packet security check: %s", mm->sec_check ? "enabled" : "disabled",
931  mm->sec_check_frag ? "enabled" : "disabled");
932 
933  vlib_cli_output(vm, "ICMP-relay IPv4 source address: %U\n", format_ip4_address, &mm->icmp4_src_address);
934  vlib_cli_output(vm, "ICMP6 unreachables sent for unmatched packets: %s\n", mm->icmp6_enabled ? "enabled" : "disabled");
935  vlib_cli_output(vm, "Inner fragmentation: %s\n", mm->frag_inner ? "enabled" : "disabled");
936  vlib_cli_output(vm, "Fragment packets regardless of DF flag: %s\n", mm->frag_ignore_df ? "enabled" : "disabled");
937 
938  /*
939  * Counters
940  */
941  vlib_combined_counter_main_t *cm = mm->domain_counters;
942  u64 total_pkts[MAP_N_DOMAIN_COUNTER];
943  u64 total_bytes[MAP_N_DOMAIN_COUNTER];
944  int which, i;
945  vlib_counter_t v;
946 
947  memset (total_pkts, 0, sizeof (total_pkts));
948  memset (total_bytes, 0, sizeof (total_bytes));
949 
951  vec_foreach (cm, mm->domain_counters) {
952  which = cm - mm->domain_counters;
953 
954  for (i = 0; i < vec_len (cm->maxi); i++) {
955  vlib_get_combined_counter (cm, i, &v);
956  total_pkts[which] += v.packets;
957  total_bytes[which] += v.bytes;
958  }
959  }
961 
962  vlib_cli_output(vm, "Encapsulated packets: %lld bytes: %lld\n", total_pkts[MAP_DOMAIN_COUNTER_TX],
963  total_bytes[MAP_DOMAIN_COUNTER_TX]);
964  vlib_cli_output(vm, "Decapsulated packets: %lld bytes: %lld\n", total_pkts[MAP_DOMAIN_COUNTER_RX],
965  total_bytes[MAP_DOMAIN_COUNTER_RX]);
966 
967  vlib_cli_output(vm, "ICMP relayed packets: %d\n", vlib_get_simple_counter(&mm->icmp_relayed, 0));
968 
969  return 0;
970 }
971 
972 static clib_error_t *
974 {
975  unformat_input_t _line_input, *line_input = &_line_input;
976  u32 lifetime = ~0;
977  f64 ht_ratio = (MAP_IP4_REASS_CONF_HT_RATIO_MAX+1);
978  u32 pool_size = ~0;
979  u64 buffers = ~(0ull);
980  u8 ip4 = 0, ip6 = 0;
981 
982  if (!unformat_user(input, unformat_line_input, line_input))
983  return 0;
984 
985  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
986  if (!unformat(line_input, "lifetime %u", &lifetime) &&
987  !unformat(line_input, "ht-ratio %lf", &ht_ratio) &&
988  !unformat(line_input, "pool-size %u", &pool_size) &&
989  !unformat(line_input, "buffers %llu", &buffers) &&
990  !((unformat(line_input, "ip4")) && (ip4 = 1)) &&
991  !((unformat(line_input, "ip6")) && (ip6 = 1))) {
992  unformat_free(line_input);
993  return clib_error_return(0, "invalid input");
994  }
995  }
996  unformat_free(line_input);
997 
998  if (!ip4 && !ip6)
999  return clib_error_return(0, "must specify ip4 and/or ip6");
1000 
1001  if (ip4) {
1002  if (pool_size != ~0 && pool_size > MAP_IP4_REASS_CONF_POOL_SIZE_MAX)
1003  return clib_error_return(0, "invalid ip4-reass pool-size ( > %d)", MAP_IP4_REASS_CONF_POOL_SIZE_MAX);
1004  if (ht_ratio != (MAP_IP4_REASS_CONF_HT_RATIO_MAX+1) && ht_ratio > MAP_IP4_REASS_CONF_HT_RATIO_MAX)
1005  return clib_error_return(0, "invalid ip4-reass ht-ratio ( > %d)", MAP_IP4_REASS_CONF_HT_RATIO_MAX);
1006  if (lifetime != ~0 && lifetime > MAP_IP4_REASS_CONF_LIFETIME_MAX)
1007  return clib_error_return(0, "invalid ip4-reass lifetime ( > %d)", MAP_IP4_REASS_CONF_LIFETIME_MAX);
1008  if (buffers != ~(0ull) && buffers > MAP_IP4_REASS_CONF_BUFFERS_MAX)
1009  return clib_error_return(0, "invalid ip4-reass buffers ( > %ld)", MAP_IP4_REASS_CONF_BUFFERS_MAX);
1010  }
1011 
1012  if (ip6) {
1013  if (pool_size != ~0 && pool_size > MAP_IP6_REASS_CONF_POOL_SIZE_MAX)
1014  return clib_error_return(0, "invalid ip6-reass pool-size ( > %d)", MAP_IP6_REASS_CONF_POOL_SIZE_MAX);
1015  if (ht_ratio != (MAP_IP4_REASS_CONF_HT_RATIO_MAX+1) && ht_ratio > MAP_IP6_REASS_CONF_HT_RATIO_MAX)
1016  return clib_error_return(0, "invalid ip6-reass ht-log2len ( > %d)", MAP_IP6_REASS_CONF_HT_RATIO_MAX);
1017  if (lifetime != ~0 && lifetime > MAP_IP6_REASS_CONF_LIFETIME_MAX)
1018  return clib_error_return(0, "invalid ip6-reass lifetime ( > %d)", MAP_IP6_REASS_CONF_LIFETIME_MAX);
1019  if (buffers != ~(0ull) && buffers > MAP_IP6_REASS_CONF_BUFFERS_MAX)
1020  return clib_error_return(0, "invalid ip6-reass buffers ( > %ld)", MAP_IP6_REASS_CONF_BUFFERS_MAX);
1021  }
1022 
1023  if (ip4) {
1024  u32 reass = 0, packets = 0;
1025  if (pool_size != ~0) {
1026  if (map_ip4_reass_conf_pool_size(pool_size, &reass, &packets)) {
1027  vlib_cli_output(vm, "Could not set ip4-reass pool-size");
1028  } else {
1029  vlib_cli_output(vm, "Setting ip4-reass pool-size (destroyed-reassembly=%u , dropped-fragments=%u)", reass, packets);
1030  }
1031  }
1032  if (ht_ratio != (MAP_IP4_REASS_CONF_HT_RATIO_MAX+1)) {
1033  if (map_ip4_reass_conf_ht_ratio(ht_ratio, &reass, &packets)) {
1034  vlib_cli_output(vm, "Could not set ip4-reass ht-log2len");
1035  } else {
1036  vlib_cli_output(vm, "Setting ip4-reass ht-log2len (destroyed-reassembly=%u , dropped-fragments=%u)", reass, packets);
1037  }
1038  }
1039  if (lifetime != ~0) {
1040  if (map_ip4_reass_conf_lifetime(lifetime))
1041  vlib_cli_output(vm, "Could not set ip4-reass lifetime");
1042  else
1043  vlib_cli_output(vm, "Setting ip4-reass lifetime");
1044  }
1045  if (buffers != ~(0ull)) {
1046  if (map_ip4_reass_conf_buffers(buffers))
1047  vlib_cli_output(vm, "Could not set ip4-reass buffers");
1048  else
1049  vlib_cli_output(vm, "Setting ip4-reass buffers");
1050  }
1051 
1054  vlib_cli_output(vm, "Note: 'ip4-reass buffers' > pool-size * max-fragments-per-reassembly.");
1055  }
1056  }
1057 
1058  if (ip6) {
1059  u32 reass = 0, packets = 0;
1060  if (pool_size != ~0) {
1061  if (map_ip6_reass_conf_pool_size(pool_size, &reass, &packets)) {
1062  vlib_cli_output(vm, "Could not set ip6-reass pool-size");
1063  } else {
1064  vlib_cli_output(vm, "Setting ip6-reass pool-size (destroyed-reassembly=%u , dropped-fragments=%u)", reass, packets);
1065  }
1066  }
1067  if (ht_ratio != (MAP_IP4_REASS_CONF_HT_RATIO_MAX+1)) {
1068  if (map_ip6_reass_conf_ht_ratio(ht_ratio, &reass, &packets)) {
1069  vlib_cli_output(vm, "Could not set ip6-reass ht-log2len");
1070  } else {
1071  vlib_cli_output(vm, "Setting ip6-reass ht-log2len (destroyed-reassembly=%u , dropped-fragments=%u)", reass, packets);
1072  }
1073  }
1074  if (lifetime != ~0) {
1075  if (map_ip6_reass_conf_lifetime(lifetime))
1076  vlib_cli_output(vm, "Could not set ip6-reass lifetime");
1077  else
1078  vlib_cli_output(vm, "Setting ip6-reass lifetime");
1079  }
1080  if (buffers != ~(0ull)) {
1081  if (map_ip6_reass_conf_buffers(buffers))
1082  vlib_cli_output(vm, "Could not set ip6-reass buffers");
1083  else
1084  vlib_cli_output(vm, "Setting ip6-reass buffers");
1085  }
1086 
1089  vlib_cli_output(vm, "Note: 'ip6-reass buffers' > pool-size * max-fragments-per-reassembly.");
1090  }
1091  }
1092 
1093  return 0;
1094 }
1095 
1096 
1097 /*
1098  * packet trace format function
1099  */
1100 u8 *
1101 format_map_trace (u8 *s, va_list *args)
1102 {
1103  CLIB_UNUSED(vlib_main_t *vm) = va_arg (*args, vlib_main_t *);
1104  CLIB_UNUSED(vlib_node_t *node) = va_arg (*args, vlib_node_t *);
1105  map_trace_t *t = va_arg (*args, map_trace_t *);
1106  u32 map_domain_index = t->map_domain_index;
1107  u16 port = t->port;
1108 
1109  s = format(s, "MAP domain index: %d L4 port: %u", map_domain_index, clib_net_to_host_u16(port));
1110 
1111  return s;
1112 }
1113 
1116 {
1117  map_main_t *mm = &map_main;
1118  u32 ri = mm->ip4_reass_hash_table[bucket];
1119  while(ri != MAP_REASS_INDEX_NONE) {
1121  if (r->key.as_u64[0] == k->as_u64[0] &&
1122  r->key.as_u64[1] == k->as_u64[1] &&
1123  now < r->ts + (((f64)mm->ip4_reass_conf_lifetime_ms) / 1000)) {
1124  return r;
1125  }
1126  ri = r->bucket_next;
1127  }
1128  return NULL;
1129 }
1130 
1131 #define map_ip4_reass_pool_index(r) (r - map_main.ip4_reass_pool)
1132 
1133 void
1135 {
1136  map_main_t *mm = &map_main;
1137  map_ip4_reass_get_fragments(r, pi_to_drop);
1138 
1139  // Unlink in hash bucket
1140  map_ip4_reass_t *r2 = NULL;
1141  u32 r2i = mm->ip4_reass_hash_table[r->bucket];
1142  while (r2i != map_ip4_reass_pool_index(r)) {
1143  ASSERT(r2i != MAP_REASS_INDEX_NONE);
1144  r2 = pool_elt_at_index(mm->ip4_reass_pool, r2i);
1145  r2i = r2->bucket_next;
1146  }
1147  if (r2) {
1148  r2->bucket_next = r->bucket_next;
1149  } else {
1151  }
1152 
1153  // Unlink in list
1154  if (r->fifo_next == map_ip4_reass_pool_index(r)) {
1156  } else {
1158  mm->ip4_reass_fifo_last = r->fifo_prev;
1159  pool_elt_at_index(mm->ip4_reass_pool, r->fifo_prev)->fifo_next = r->fifo_next;
1160  pool_elt_at_index(mm->ip4_reass_pool, r->fifo_next)->fifo_prev = r->fifo_prev;
1161  }
1162 
1163  pool_put(mm->ip4_reass_pool, r);
1164  mm->ip4_reass_allocated--;
1165 }
1166 
1168 map_ip4_reass_get(u32 src, u32 dst, u16 fragment_id,
1169  u8 protocol, u32 **pi_to_drop)
1170 {
1171  map_ip4_reass_t * r;
1172  map_main_t *mm = &map_main;
1173  map_ip4_reass_key_t k = {.src.data_u32 = src,
1174  .dst.data_u32 = dst,
1175  .fragment_id = fragment_id,
1176  .protocol = protocol };
1177 
1178  u32 h = 0;
1179  h = crc_u32(k.as_u32[0], h);
1180  h = crc_u32(k.as_u32[1], h);
1181  h = crc_u32(k.as_u32[2], h);
1182  h = crc_u32(k.as_u32[3], h);
1183  h = h >> (32 - mm->ip4_reass_ht_log2len);
1184 
1185  f64 now = vlib_time_now(mm->vlib_main);
1186 
1187  //Cache garbage collection
1188  while (mm->ip4_reass_fifo_last != MAP_REASS_INDEX_NONE) {
1190  if (last->ts + (((f64)mm->ip4_reass_conf_lifetime_ms) / 1000) < now)
1191  map_ip4_reass_free(last, pi_to_drop);
1192  else
1193  break;
1194  }
1195 
1196  if ((r = map_ip4_reass_lookup(&k, h, now)))
1197  return r;
1198 
1200  return NULL;
1201 
1202  pool_get(mm->ip4_reass_pool, r);
1203  mm->ip4_reass_allocated++;
1204  int i;
1206  r->fragments[i] = ~0;
1207 
1208  u32 ri = map_ip4_reass_pool_index(r);
1209 
1210  //Link in new bucket
1211  r->bucket = h;
1212  r->bucket_next = mm->ip4_reass_hash_table[h];
1213  mm->ip4_reass_hash_table[h] = ri;
1214 
1215  //Link in fifo
1218  r->fifo_prev = mm->ip4_reass_fifo_last;
1219  pool_elt_at_index(mm->ip4_reass_pool, r->fifo_prev)->fifo_next = ri;
1220  pool_elt_at_index(mm->ip4_reass_pool, r->fifo_next)->fifo_prev = ri;
1221  } else {
1222  r->fifo_next = r->fifo_prev = ri;
1223  mm->ip4_reass_fifo_last = ri;
1224  }
1225 
1226  //Set other fields
1227  r->ts = now;
1228  r->key = k;
1229  r->port = -1;
1230 #ifdef MAP_IP4_REASS_COUNT_BYTES
1231  r->expected_total = 0xffff;
1232  r->forwarded = 0;
1233 #endif
1234 
1235  return r;
1236 }
1237 
1238 int
1240 {
1242  return -1;
1243 
1244  int i;
1246  if(r->fragments[i] == ~0) {
1247  r->fragments[i] = pi;
1249  return 0;
1250  }
1251  return -1;
1252 }
1253 
1256 {
1257  map_main_t *mm = &map_main;
1258  u32 ri = mm->ip6_reass_hash_table[bucket];
1259  while(ri != MAP_REASS_INDEX_NONE) {
1261  if(now < r->ts + (((f64)mm->ip6_reass_conf_lifetime_ms) / 1000) &&
1262  r->key.as_u64[0] == k->as_u64[0] &&
1263  r->key.as_u64[1] == k->as_u64[1] &&
1264  r->key.as_u64[2] == k->as_u64[2] &&
1265  r->key.as_u64[3] == k->as_u64[3] &&
1266  r->key.as_u64[4] == k->as_u64[4])
1267  return r;
1268  ri = r->bucket_next;
1269  }
1270  return NULL;
1271 }
1272 
1273 #define map_ip6_reass_pool_index(r) (r - map_main.ip6_reass_pool)
1274 
1275 void
1277 {
1278  map_main_t *mm = &map_main;
1279  int i;
1281  if(r->fragments[i].pi != ~0) {
1282  vec_add1(*pi_to_drop, r->fragments[i].pi);
1283  r->fragments[i].pi = ~0;
1285  }
1286 
1287  // Unlink in hash bucket
1288  map_ip6_reass_t *r2 = NULL;
1289  u32 r2i = mm->ip6_reass_hash_table[r->bucket];
1290  while (r2i != map_ip6_reass_pool_index(r)) {
1291  ASSERT(r2i != MAP_REASS_INDEX_NONE);
1292  r2 = pool_elt_at_index(mm->ip6_reass_pool, r2i);
1293  r2i = r2->bucket_next;
1294  }
1295  if (r2) {
1296  r2->bucket_next = r->bucket_next;
1297  } else {
1299  }
1300 
1301  // Unlink in list
1302  if (r->fifo_next == map_ip6_reass_pool_index(r)) {
1303  //Single element in the list, list is now empty
1305  } else {
1306  if (mm->ip6_reass_fifo_last == map_ip6_reass_pool_index(r)) //First element
1307  mm->ip6_reass_fifo_last = r->fifo_prev;
1308  pool_elt_at_index(mm->ip6_reass_pool, r->fifo_prev)->fifo_next = r->fifo_next;
1309  pool_elt_at_index(mm->ip6_reass_pool, r->fifo_next)->fifo_prev = r->fifo_prev;
1310  }
1311 
1312  // Free from pool if necessary
1313  pool_put(mm->ip6_reass_pool, r);
1314  mm->ip6_reass_allocated--;
1315 }
1316 
1319  u8 protocol, u32 **pi_to_drop)
1320 {
1321  map_ip6_reass_t * r;
1322  map_main_t *mm = &map_main;
1323  map_ip6_reass_key_t k = {
1324  .src = *src,
1325  .dst = *dst,
1326  .fragment_id = fragment_id,
1327  .protocol = protocol };
1328 
1329  u32 h = 0;
1330  int i;
1331  for (i=0; i<10; i++)
1332  h = crc_u32(k.as_u32[i], h);
1333  h = h >> (32 - mm->ip6_reass_ht_log2len);
1334 
1335  f64 now = vlib_time_now(mm->vlib_main);
1336 
1337  //Cache garbage collection
1338  while (mm->ip6_reass_fifo_last != MAP_REASS_INDEX_NONE) {
1340  if (last->ts + (((f64)mm->ip6_reass_conf_lifetime_ms) / 1000) < now)
1341  map_ip6_reass_free(last, pi_to_drop);
1342  else
1343  break;
1344  }
1345 
1346  if ((r = map_ip6_reass_lookup(&k, h, now)))
1347  return r;
1348 
1350  return NULL;
1351 
1352  pool_get(mm->ip6_reass_pool, r);
1353  mm->ip6_reass_allocated++;
1354  for (i=0; i<MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++) {
1355  r->fragments[i].pi = ~0;
1356  r->fragments[i].next_data_len = 0;
1357  r->fragments[i].next_data_offset = 0;
1358  }
1359 
1360  u32 ri = map_ip6_reass_pool_index(r);
1361 
1362  //Link in new bucket
1363  r->bucket = h;
1364  r->bucket_next = mm->ip6_reass_hash_table[h];
1365  mm->ip6_reass_hash_table[h] = ri;
1366 
1367  //Link in fifo
1370  r->fifo_prev = mm->ip6_reass_fifo_last;
1371  pool_elt_at_index(mm->ip6_reass_pool, r->fifo_prev)->fifo_next = ri;
1372  pool_elt_at_index(mm->ip6_reass_pool, r->fifo_next)->fifo_prev = ri;
1373  } else {
1374  r->fifo_next = r->fifo_prev = ri;
1375  mm->ip6_reass_fifo_last = ri;
1376  }
1377 
1378  //Set other fields
1379  r->ts = now;
1380  r->key = k;
1382 #ifdef MAP_IP6_REASS_COUNT_BYTES
1383  r->expected_total = 0xffff;
1384  r->forwarded = 0;
1385 #endif
1386  return r;
1387 }
1388 
1389 int
1391  u16 data_offset, u16 next_data_offset,
1392  u8 *data_start, u16 data_len)
1393 {
1394  map_ip6_fragment_t *f = NULL, *prev_f = NULL;
1395  u16 copied_len = (data_len > 20) ? 20 : data_len;
1396 
1398  return -1;
1399 
1400  //Lookup for fragments for the current buffer
1401  //and the one before that
1402  int i;
1403  for (i=0; i<MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY; i++) {
1404  if (data_offset && r->fragments[i].next_data_offset == data_offset) {
1405  prev_f = &r->fragments[i]; // This is buffer for previous packet
1406  } else if (r->fragments[i].next_data_offset == next_data_offset) {
1407  f = &r->fragments[i]; // This is a buffer for the current packet
1408  } else if (r->fragments[i].next_data_offset == 0) { //Available
1409  if (f == NULL)
1410  f = &r->fragments[i];
1411  else if (prev_f == NULL)
1412  prev_f = &r->fragments[i];
1413  }
1414  }
1415 
1416  if (!f || f->pi != ~0)
1417  return -1;
1418 
1419  if (data_offset) {
1420  if (!prev_f)
1421  return -1;
1422 
1423  clib_memcpy(prev_f->next_data, data_start, copied_len);
1424  prev_f->next_data_len = copied_len;
1425  prev_f->next_data_offset = data_offset;
1426  } else {
1427  if (((ip4_header_t *)data_start)->ip_version_and_header_length != 0x45)
1428  return -1;
1429 
1431  clib_memcpy(&r->ip4_header, data_start, sizeof(ip4_header_t));
1432  }
1433 
1434  if(data_len > 20) {
1435  f->next_data_offset = next_data_offset;
1436  f->pi = pi;
1438  }
1439  return 0;
1440 }
1441 
1442 void map_ip4_reass_reinit(u32 *trashed_reass, u32 *dropped_packets)
1443 {
1444  map_main_t *mm = &map_main;
1445  int i;
1446 
1447  if(dropped_packets)
1448  *dropped_packets = mm->ip4_reass_buffered_counter;
1449  if(trashed_reass)
1450  *trashed_reass = mm->ip4_reass_allocated;
1452  u16 ri = mm->ip4_reass_fifo_last;
1453  do {
1456  if (r->fragments[i] != ~0)
1457  map_ip4_drop_pi(r->fragments[i]);
1458 
1459  ri = r->fifo_next;
1460  pool_put(mm->ip4_reass_pool, r);
1461  } while (ri != mm->ip4_reass_fifo_last);
1462  }
1463 
1466  for (i=0; i<(1 << mm->ip4_reass_ht_log2len); i++)
1470 
1471  mm->ip4_reass_allocated = 0;
1474 }
1475 
1476 u8 map_get_ht_log2len(f32 ht_ratio, u16 pool_size)
1477 {
1478  u32 desired_size = (u32)(pool_size * ht_ratio);
1479  u8 i;
1480  for (i=1; i<31; i++)
1481  if ((1 << i) >= desired_size)
1482  return i;
1483  return 4;
1484 }
1485 
1486 int map_ip4_reass_conf_ht_ratio(f32 ht_ratio, u32 *trashed_reass, u32 *dropped_packets)
1487 {
1488  map_main_t *mm = &map_main;
1489  if (ht_ratio > MAP_IP4_REASS_CONF_HT_RATIO_MAX)
1490  return -1;
1491 
1493  mm->ip4_reass_conf_ht_ratio = ht_ratio;
1495  map_ip4_reass_reinit(trashed_reass, dropped_packets);
1497  return 0;
1498 }
1499 
1500 int map_ip4_reass_conf_pool_size(u16 pool_size, u32 *trashed_reass, u32 *dropped_packets)
1501 {
1502  map_main_t *mm = &map_main;
1503  if (pool_size > MAP_IP4_REASS_CONF_POOL_SIZE_MAX)
1504  return -1;
1505 
1507  mm->ip4_reass_conf_pool_size = pool_size;
1508  map_ip4_reass_reinit(trashed_reass, dropped_packets);
1510  return 0;
1511 }
1512 
1514 {
1515  map_main.ip4_reass_conf_lifetime_ms = lifetime_ms;
1516  return 0;
1517 }
1518 
1520 {
1521  map_main.ip4_reass_conf_buffers = buffers;
1522  return 0;
1523 }
1524 
1525 void map_ip6_reass_reinit(u32 *trashed_reass, u32 *dropped_packets)
1526 {
1527  map_main_t *mm = &map_main;
1528  if(dropped_packets)
1529  *dropped_packets = mm->ip6_reass_buffered_counter;
1530  if(trashed_reass)
1531  *trashed_reass = mm->ip6_reass_allocated;
1532  int i;
1534  u16 ri = mm->ip6_reass_fifo_last;
1535  do {
1538  if (r->fragments[i].pi != ~0)
1539  map_ip6_drop_pi(r->fragments[i].pi);
1540 
1541  ri = r->fifo_next;
1542  pool_put(mm->ip6_reass_pool, r);
1543  } while (ri != mm->ip6_reass_fifo_last);
1545  }
1546 
1549  for(i=0; i<(1 << mm->ip6_reass_ht_log2len); i++)
1553 
1554  mm->ip6_reass_allocated = 0;
1556 }
1557 
1558 int map_ip6_reass_conf_ht_ratio(f32 ht_ratio, u32 *trashed_reass, u32 *dropped_packets)
1559 {
1560  map_main_t *mm = &map_main;
1561  if (ht_ratio > MAP_IP6_REASS_CONF_HT_RATIO_MAX)
1562  return -1;
1563 
1565  mm->ip6_reass_conf_ht_ratio = ht_ratio;
1567  map_ip6_reass_reinit(trashed_reass, dropped_packets);
1569  return 0;
1570 }
1571 
1572 int map_ip6_reass_conf_pool_size(u16 pool_size, u32 *trashed_reass, u32 *dropped_packets)
1573 {
1574  map_main_t *mm = &map_main;
1575  if (pool_size > MAP_IP6_REASS_CONF_POOL_SIZE_MAX)
1576  return -1;
1577 
1579  mm->ip6_reass_conf_pool_size = pool_size;
1580  map_ip6_reass_reinit(trashed_reass, dropped_packets);
1582  return 0;
1583 }
1584 
1586 {
1587  map_main.ip6_reass_conf_lifetime_ms = lifetime_ms;
1588  return 0;
1589 }
1590 
1592 {
1593  map_main.ip6_reass_conf_buffers = buffers;
1594  return 0;
1595 }
1596 
1598  .path = "map params reassembly",
1599  .short_help = "[ip4 | ip6] [lifetime <lifetime-ms>] [pool-size <pool-size>] [buffers <buffers>] [ht-ratio <ht-ratio>]",
1600  .function = map_params_reass_command_fn,
1601 };
1602 
1604  .path = "map params traffic-class",
1605  .short_help =
1606  "traffic-class {0x0-0xff | copy}",
1607  .function = map_traffic_class_command_fn,
1608 };
1609 
1611  .path = "map params pre-resolve",
1612  .short_help =
1613  "pre-resolve {ip4-nh <address>} | {ip6-nh <address>}",
1614  .function = map_pre_resolve_command_fn,
1615 };
1616 
1618  .path = "map params security-check",
1619  .short_help =
1620  "security-check on|off",
1621  .function = map_security_check_command_fn,
1622 };
1623 
1625  .path = "map params icmp source-address",
1626  .short_help = "source-address <ip4-address>",
1628 };
1629 
1631  .path = "map params icmp6 unreachables",
1632  .short_help = "unreachables {on|off}",
1634 };
1635 
1637  .path = "map params fragment",
1638  .short_help = "[inner|outer] [ignore-df [on|off]]",
1639  .function = map_fragment_command_fn,
1640 };
1641 
1643  .path = "map params fragment ignore-df",
1644  .short_help = "on|off",
1645  .function = map_fragment_df_command_fn,
1646 };
1647 
1649  .path = "map params security-check fragments",
1650  .short_help =
1651  "fragments on|off",
1653 };
1654 
1656  .path = "map add domain",
1657  .short_help =
1658  "map add domain ip4-pfx <ip4-pfx> ip6-pfx <ip6-pfx> ip6-src <ip6-pfx> "
1659  "ea-bits-len <n> psid-offset <n> psid-len <n> [map-t] [mtu <mtu>]",
1660  .function = map_add_domain_command_fn,
1661 };
1662 
1664  .path = "map add rule",
1665  .short_help =
1666  "map add rule index <domain> psid <psid> ip6-dst <ip6-addr>",
1667  .function = map_add_rule_command_fn,
1668 };
1669 
1671  .path = "map del domain",
1672  .short_help =
1673  "map del domain index <domain>",
1674  .function = map_del_domain_command_fn,
1675 };
1676 
1678  .path = "show map domain",
1679  .function = show_map_domain_command_fn,
1680 };
1681 
1683  .path = "show map stats",
1684  .function = show_map_stats_command_fn,
1685 };
1686 
1688  .path = "show map fragments",
1689  .function = show_map_fragments_command_fn,
1690 };
1691 
1692 /*
1693  * map_init
1694  */
1696 {
1697  map_main_t *mm = &map_main;
1698  mm->vnet_main = vnet_get_main();
1699  mm->vlib_main = vm;
1700 
1701 #ifdef MAP_SKIP_IP6_LOOKUP
1702  memset(&mm->preresolve_ip4, 0, sizeof(mm->preresolve_ip4));
1703  memset(&mm->preresolve_ip6, 0, sizeof(mm->preresolve_ip6));
1704  mm->adj4_index = 0;
1705  mm->adj6_index = 0;
1706 #endif
1707 
1708  /* traffic class */
1709  mm->tc = 0;
1710  mm->tc_copy = true;
1711 
1712  /* Inbound security check */
1713  mm->sec_check = true;
1714  mm->sec_check_frag = false;
1715 
1716  /* ICMP6 Type 1, Code 5 for security check failure */
1717  mm->icmp6_enabled = false;
1718 
1719  /* Inner or outer fragmentation */
1720  mm->frag_inner = false;
1721  mm->frag_ignore_df = false;
1722 
1726 
1729 
1730  /* IP4 virtual reassembly */
1731  mm->ip4_reass_hash_table = 0;
1732  mm->ip4_reass_pool = 0;
1741 
1742  /* IP6 virtual reassembly */
1743  mm->ip6_reass_hash_table = 0;
1744  mm->ip6_reass_pool = 0;
1753 
1754  return 0;
1755 }
1756 
u16 forwarded
Definition: map.h:174
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:394
#define map_ip4_reass_lock()
Definition: map.h:433
u8 psid_length
Definition: map.h:94
vlib_cli_command_t map_ip4_reass_lifetime_command
(constructor) VLIB_CLI_COMMAND (map_ip4_reass_lifetime_command)
Definition: map.c:1597
map_ip4_reass_t * ip4_reass_pool
Definition: map.h:226
u32 ip4_reass_conf_buffers
Definition: map.h:223
vlib_cli_command_t map_icmp_relay_source_address_command
(constructor) VLIB_CLI_COMMAND (map_icmp_relay_source_address_command)
Definition: map.c:1624
u32 error_heap_index
Definition: node.h:244
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
static clib_error_t * map_fragment_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: map.c:667
#define CLIB_UNUSED(x)
Definition: clib.h:79
#define MAP_IP6_REASS_CONF_BUFFERS_MAX
Definition: map.h:485
u32 as_u32[4]
Definition: map.h:118
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:942
int map_delete_domain(u32 map_domain_index)
Definition: map.c:282
#define MAP_IP6_REASS_BUFFERS_DEFAULT
Definition: map.h:68
map_domain_flags_e flags
Definition: map.h:89
u16 fifo_prev
Definition: map.h:178
void vlib_validate_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
Definition: counter.c:106
u16 ip4_reass_allocated
Definition: map.h:228
volatile u32 * ip6_reass_lock
Definition: map.h:254
format_function_t format_ip6_address
Definition: format.h:87
u8 ip4_reass_ht_log2len
Definition: map.h:227
u32 fragments[MAP_IP4_REASS_MAX_FRAGMENTS_PER_REASSEMBLY]
Definition: map.h:133
always_inline vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Definition: node_funcs.h:46
#define MAP_IP6_REASS_LIFETIME_DEFAULT
Definition: map.h:65
static_always_inline map_ip6_reass_t * map_ip6_reass_lookup(map_ip6_reass_key_t *k, u32 bucket, f64 now)
Definition: map.c:1255
#define pool_alloc(P, N)
Definition: pool.h:233
u16 bucket_next
Definition: map.h:177
ip_lookup_next_t lookup_next_index
Definition: lookup.h:163
#define PREDICT_TRUE(x)
Definition: clib.h:98
always_inline int ip4_get_fragment_offset(ip4_header_t *i)
Definition: ip4_packet.h:162
u64 as_u64[2]
Definition: ip6_packet.h:50
always_inline void clib_mem_free(void *p)
Definition: mem.h:149
map_error_t
Definition: map.h:283
always_inline void unformat_free(unformat_input_t *i)
Definition: format.h:160
#define UNFORMAT_END_OF_INPUT
Definition: format.h:142
#define NULL
Definition: clib.h:55
vlib_counter_t * maxi
Definition: counter.h:181
static u8 * format_map_domain(u8 *s, va_list *args)
Definition: map.c:748
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:827
void map_ip4_reass_reinit(u32 *trashed_reass, u32 *dropped_packets)
Definition: map.c:1442
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:402
u64 map_error_counter_get(u32 node_index, map_error_t map_error)
Definition: map.c:880
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:488
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:693
vlib_main_t * vlib_main
Definition: map.h:213
u8 tc
Definition: map.h:201
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:868
i32 ip6_get_port(ip6_header_t *ip6, map_dir_e dir, u16 buffer_len)
Definition: map.c:101
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:480
static void map_domain_counter_unlock(map_main_t *mm)
Definition: map.h:536
static u64 clib_xxhash(u64 key)
Definition: xxhash.h:57
always_inline u64 vlib_get_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Definition: counter.h:93
u32 suffix_mask
Definition: map.h:85
bool sec_check_frag
Definition: map.h:205
u32 ip4_reass_buffered_counter
Definition: map.h:234
static u8 * format_map_ip4_reass(u8 *s, va_list *args)
Definition: map.c:795
ip6_address_t preresolve_ip6
Definition: map.h:197
static u32 crc_u32(u32 data, u32 value)
Definition: map.c:24
vlib_error_t * errors
Definition: node.h:378
u16 ip4_reass_fifo_last
Definition: map.h:230
#define pool_get(P, E)
Definition: pool.h:186
format_function_t format_ip4_address
Definition: format.h:71
vlib_cli_command_t show_map_domain_command
(constructor) VLIB_CLI_COMMAND (show_map_domain_command)
Definition: map.c:1677
int map_ip6_reass_conf_ht_ratio(f32 ht_ratio, u32 *trashed_reass, u32 *dropped_packets)
Definition: map.c:1558
always_inline vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
#define MAP_IP6_REASS_CONF_LIFETIME_MAX
Definition: map.h:483
u64 as_u64[5]
Definition: map.h:158
map_ip6_reass_t * ip6_reass_pool
Definition: map.h:249
map_ip6_fragment_t fragments[MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY]
Definition: map.h:181
u16 port
Definition: map.h:294
ip4_address_t preresolve_ip4
Definition: map.h:196
#define map_ip6_reass_unlock()
Definition: map.h:457
always_inline uword unformat_check_input(unformat_input_t *i)
Definition: format.h:168
float f32
Definition: types.h:141
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
#define MAP_IP4_REASS_MAX_FRAGMENTS_PER_REASSEMBLY
Definition: map.h:63
bool tc_copy
Definition: map.h:202
#define static_always_inline
Definition: clib.h:85
#define pool_foreach(VAR, POOL, BODY)
Definition: pool.h:328
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:574
#define MAP_REASS_INDEX_NONE
Definition: map.h:105
always_inline heap_elt_t * last(heap_header_t *h)
Definition: heap.c:51
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:109
map_ip4_reass_key_t key
Definition: map.h:122
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:635
always_inline u32 vlib_error_get_code(vlib_error_t e)
Definition: error.h:51
u16 bucket
Definition: map.h:176
vlib_combined_counter_main_t * domain_counters
Definition: map.h:190
vlib_cli_command_t show_map_fragments_command
(constructor) VLIB_CLI_COMMAND (show_map_fragments_command)
Definition: map.c:1687
ip4_address_t icmp4_src_address
Definition: map.h:209
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:450
int i32
Definition: types.h:81
vlib_cli_command_t map_del_command
(constructor) VLIB_CLI_COMMAND (map_del_command)
Definition: map.c:1670
u16 fifo_next
Definition: map.h:132
u32 ip4_fib_lookup_with_table(ip4_main_t *im, u32 fib_index, ip4_address_t *dst, u32 disable_default_route)
Definition: ip4_forward.c:50
always_inline uword pool_elts(void *v)
Definition: pool.h:97
vlib_simple_counter_main_t icmp_relayed
Definition: map.h:210
int map_ip4_reass_add_fragment(map_ip4_reass_t *r, u32 pi)
Definition: map.c:1239
ip6_address_t * rules
Definition: map.h:84
#define clib_warning(format, args...)
Definition: error.h:59
u32 table_index_or_table_id
Definition: ip6.h:343
unsigned long u64
Definition: types.h:89
u8 map_get_ht_log2len(f32 ht_ratio, u16 pool_size)
Definition: map.c:1476
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
Definition: vec.h:199
u8 ea_bits_len
Definition: map.h:92
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:953
u8 ip6_prefix_len
Definition: map.h:90
#define MAP_IP4_REASS_CONF_LIFETIME_MAX
Definition: map.h:471
void ip6_add_del_route(ip6_main_t *im, ip6_add_del_route_args_t *args)
Definition: ip6_forward.c:208
static_always_inline map_ip4_reass_t * map_ip4_reass_lookup(map_ip4_reass_key_t *k, u32 bucket, f64 now)
Definition: map.c:1115
u16 ip6_reass_allocated
Definition: map.h:251
int map_add_del_psid(u32 map_domain_index, u16 psid, ip6_address_t *tep, u8 is_add)
Definition: map.c:346
unformat_function_t unformat_ip4_address
Definition: format.h:68
always_inline void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:113
#define MAP_IP6_REASS_CONF_POOL_SIZE_MAX
Definition: map.h:481
ip6_address_t dst_address
Definition: ip6.h:346
#define pool_elt_at_index(p, i)
Definition: pool.h:346
int map_ip6_reass_conf_buffers(u32 buffers)
Definition: map.c:1591
u32 vlib_error_t
Definition: error.h:44
#define map_ip4_reass_pool_index(r)
Definition: map.c:1131
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:537
int map_ip4_reass_conf_lifetime(u16 lifetime_ms)
Definition: map.c:1513
vlib_error_main_t error_main
Definition: main.h:124
#define MAP_IP4_REASS_BUFFERS_DEFAULT
Definition: map.h:61
void * ip4_get_route(ip4_main_t *im, u32 fib_index_or_table_id, u32 flags, u8 *address, u32 address_length)
Definition: ip4_forward.c:469
#define MAP_IP4_REASS_CONF_HT_RATIO_MAX
Definition: map.h:467
static u8 * format_map_ip6_reass(u8 *s, va_list *args)
Definition: map.c:811
bool frag_ignore_df
Definition: map.h:237
volatile u32 * ip4_reass_lock
Definition: map.h:231
u16 ip4_reass_conf_pool_size
Definition: map.h:221
map_domain_t * domains
Definition: map.h:186
u16 bucket
Definition: map.h:129
ip_adjacency_t * add_adj
Definition: ip6.h:355
vlib_cli_command_t map_add_domain_command
(constructor) VLIB_CLI_COMMAND (map_add_domain_command)
Definition: map.c:1655
int map_ip4_reass_conf_buffers(u32 buffers)
Definition: map.c:1519
#define pool_put(P, E)
Definition: pool.h:200
int map_ip6_reass_conf_lifetime(u16 lifetime_ms)
Definition: map.c:1585
map_ip4_reass_t * map_ip4_reass_get(u32 src, u32 dst, u16 fragment_id, u8 protocol, u32 **pi_to_drop)
Definition: map.c:1168
static void vlib_get_combined_counter(vlib_combined_counter_main_t *cm, u32 index, vlib_counter_t *result)
Definition: counter.h:248
int map_ip4_reass_conf_pool_size(u16 pool_size, u32 *trashed_reass, u32 *dropped_packets)
Definition: map.c:1500
u16 * ip6_reass_hash_table
Definition: map.h:252
u16 * ip4_reass_hash_table
Definition: map.h:229
u32 ip6_get_route(ip6_main_t *im, u32 fib_index_or_table_id, u32 flags, ip6_address_t *address, u32 address_length)
Definition: ip6_forward.c:523
vlib_cli_command_t map_fragment_command
(constructor) VLIB_CLI_COMMAND (map_fragment_command)
Definition: map.c:1636
map_main_t map_main
Definition: map.h:297
i32 ip4_get_port(ip4_header_t *ip, map_dir_e dir, u16 buffer_len)
Definition: map.c:66
#define MAP_IP4_REASS_HT_RATIO_DEFAULT
Definition: map.h:59
u8 ip6_src_len
Definition: map.h:91
u8 psid_shift
Definition: map.h:97
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:538
u16 expected_total
Definition: map.h:125
unformat_function_t unformat_ip6_address
Definition: format.h:86
ip_adjacency_t * add_adj
Definition: ip4.h:293
u8 suffix_shift
Definition: map.h:98
#define pool_get_aligned(P, E, A)
Definition: pool.h:155
void map_ip4_drop_pi(u32 pi)
Definition: ip6_map.c:515
u8 ip6_reass_ht_log2len
Definition: map.h:250
u16 ip6_reass_fifo_last
Definition: map.h:253
#define pool_free(p)
Definition: pool.h:248
void map_ip4_reass_free(map_ip4_reass_t *r, u32 **pi_to_drop)
Definition: map.c:1134
u64 * counters
Definition: error.h:73
vlib_cli_command_t map_icmp_unreachables_command
(constructor) VLIB_CLI_COMMAND (map_icmp_unreachables_command)
Definition: map.c:1630
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:973
vlib_cli_command_t map_pre_resolve_command
(constructor) VLIB_CLI_COMMAND (map_pre_resolve_command)
Definition: map.c:1610
u16 ip6_reass_conf_pool_size
Definition: map.h:244
map_dir_e
Definition: map.h:23
u8 next_data_len
Definition: map.h:165
ip4_address_t ip4_prefix
Definition: map.h:86
u16 next_data_offset
Definition: map.h:164
static_always_inline void map_ip4_reass_get_fragments(map_ip4_reass_t *r, u32 **pi)
Definition: map.h:437
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:1318
#define MAP_IP6_REASS_POOL_SIZE_DEFAULT
Definition: map.h:67
u32 as_u32[10]
Definition: map.h:159
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
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:134
u8 psid_offset
Definition: map.h:93
vlib_cli_command_t map_security_check_frag_command
(constructor) VLIB_CLI_COMMAND (map_security_check_frag_command)
Definition: map.c:1648
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:608
u16 forwarded
Definition: map.h:126
vlib_cli_command_t map_fragment_df_command
(constructor) VLIB_CLI_COMMAND (map_fragment_df_command)
Definition: map.c:1642
#define clib_memcpy(a, b, c)
Definition: string.h:63
bool icmp6_enabled
Definition: map.h:206
u32 ip6_fib_lookup_with_table(ip6_main_t *im, u32 fib_index, ip6_address_t *dst)
Definition: ip6_forward.c:61
#define IP6_ROUTE_FLAG_DEL
Definition: ip6.h:328
map_ip6_reass_key_t key
Definition: map.h:170
#define pool_is_free_index(P, I)
Definition: pool.h:197
ip6_address_t ip6_src
Definition: map.h:82
u32 adj4_index
Definition: map.h:195
#define IP4_ROUTE_FLAG_DEL
Definition: ip4.h:265
int map_ip4_reass_conf_ht_ratio(f32 ht_ratio, u32 *trashed_reass, u32 *dropped_packets)
Definition: map.c:1486
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:507
static void map_domain_counter_lock(map_main_t *mm)
Definition: map.h:529
f32 ip4_reass_conf_ht_ratio
Definition: map.h:220
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:150
vlib_cli_command_t map_security_check_command
(constructor) VLIB_CLI_COMMAND (map_security_check_command)
Definition: map.c:1617
void vlib_validate_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Definition: counter.c:95
#define ip6_frag_hdr_offset(hdr)
Definition: ip6_packet.h:385
int map_ip6_reass_conf_pool_size(u16 pool_size, u32 *trashed_reass, u32 *dropped_packets)
Definition: map.c:1572
#define ASSERT(truth)
#define u8_ptr_add(ptr, index)
Definition: map.h:506
unsigned int u32
Definition: types.h:88
bool sec_check
Definition: map.h:204
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:87
ip4_address_t dst_address
Definition: ip4.h:284
#define IP4_ROUTE_FLAG_ADD
Definition: ip4.h:264
ip6_main_t ip6_main
Definition: ip6_forward.c:2490
ip_lookup_main_t lookup_main
Definition: ip6.h:135
bool frag_inner
Definition: map.h:236
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
u16 psid_mask
Definition: map.h:87
void map_ip6_reass_reinit(u32 *trashed_reass, u32 *dropped_packets)
Definition: map.c:1525
ip4_header_t ip4_header
Definition: map.h:180
#define map_ip4_reass_unlock()
Definition: map.h:434
u8 * format_map_trace(u8 *s, va_list *args)
Definition: map.c:1101
#define MAP_IP6_REASS_HT_RATIO_DEFAULT
Definition: map.h:66
u8 ea_shift
Definition: map.h:99
always_inline void vlib_zero_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
Definition: counter.h:277
always_inline ip_adjacency_t * ip_get_adjacency(ip_lookup_main_t *lm, u32 adj_index)
Definition: lookup.h:423
ip6_address_t ip6_prefix
Definition: map.h:83
u64 uword
Definition: types.h:112
f32 ip6_reass_conf_ht_ratio
Definition: map.h:243
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:719
vnet_main_t * vnet_main
Definition: map.h:214
unsigned short u16
Definition: types.h:57
u16 mtu
Definition: map.h:88
vlib_cli_command_t show_map_stats_command
(constructor) VLIB_CLI_COMMAND (show_map_stats_command)
Definition: map.c:1682
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:140
u16 ip6_reass_conf_lifetime_ms
Definition: map.h:245
unsigned char u8
Definition: types.h:56
#define map_ip6_reass_lock()
Definition: map.h:456
u32 adj6_index
Definition: map.h:195
vlib_cli_command_t map_traffic_class_command
(constructor) VLIB_CLI_COMMAND (map_traffic_class_command)
Definition: map.c:1603
i32 port
Definition: map.h:128
#define MAP_IP4_REASS_POOL_SIZE_DEFAULT
Definition: map.h:60
#define MAP_IP6_REASS_CONF_HT_RATIO_MAX
Definition: map.h:479
u32 table_index_or_table_id
Definition: ip4.h:281
#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:58
u16 bucket_next
Definition: map.h:130
#define MAP_IP4_REASS_CONF_POOL_SIZE_MAX
Definition: map.h:469
u8 ip4_prefix_len
Definition: map.h:102
void map_ip6_reass_free(map_ip6_reass_t *r, u32 **pi_to_drop)
Definition: map.c:1276
vlib_simple_counter_main_t * simple_domain_counters
Definition: map.h:189
always_inline void vlib_zero_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Definition: counter.h:122
ip4_main_t ip4_main
Definition: ip4_forward.c:1394
always_inline vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Definition: node_funcs.h:61
#define MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY
Definition: map.h:70
#define IP6_ROUTE_FLAG_ADD
Definition: ip6.h:327
u16 ip4_reass_conf_lifetime_ms
Definition: map.h:222
#define vec_foreach(var, vec)
Vector iterator.
i16 explicit_fib_index
Definition: lookup.h:168
always_inline f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:182
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:426
u32 map_domain_index
Definition: map.h:293
#define MAP_IP4_REASS_CONF_BUFFERS_MAX
Definition: map.h:473
u64 as_u64[2]
Definition: map.h:117
#define clib_error_return(e, args...)
Definition: error.h:112
u8 ip_version_and_header_length
Definition: ip4_packet.h:108
u16 fifo_prev
Definition: map.h:131
struct _unformat_input_t unformat_input_t
Definition: map.h:24
void ip4_add_del_route(ip4_main_t *im, ip4_add_del_route_args_t *args)
Definition: ip4_forward.c:196
u32 flags
Definition: vhost-user.h:73
u32 ip6_reass_buffered_counter
Definition: map.h:257
#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:1390
static void map_pre_resolve(ip4_address_t *ip4, ip6_address_t *ip6)
Definition: map.c:384
u16 expected_total
Definition: map.h:173
clib_error_t * map_init(vlib_main_t *vm)
Definition: map.c:1695
unformat_function_t unformat_line_input
Definition: format.h:279
u16 fifo_next
Definition: map.h:179
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:897
void map_ip6_drop_pi(u32 pi)
Definition: ip6_map.c:507
#define map_ip6_reass_pool_index(r)
Definition: map.c:1273
vlib_cli_command_t map_add_rule_command
(constructor) VLIB_CLI_COMMAND (map_add_rule_command)
Definition: map.c:1663
u32 ip6_reass_conf_buffers
Definition: map.h:246