FD.io VPP  v18.10-32-g1161dda
Vector Packet Processing
nat_reass.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /**
16  * @file
17  * @brief NAT plugin virtual fragmentation reassembly
18  */
19 
20 #include <vnet/vnet.h>
21 #include <nat/nat_reass.h>
22 #include <nat/nat_ipfix_logging.h>
23 
25 
26 static u32
28 {
30  u32 nbuckets;
31  u8 i;
32 
33  if (is_ip6)
34  nbuckets = (u32) (srm->ip6_max_reass / NAT_REASS_HT_LOAD_FACTOR);
35  else
36  nbuckets = (u32) (srm->ip4_max_reass / NAT_REASS_HT_LOAD_FACTOR);
37 
38  for (i = 0; i < 31; i++)
39  if ((1 << i) >= nbuckets)
40  break;
41  nbuckets = 1 << i;
42 
43  return nbuckets;
44 }
45 
47 nat_ip4_reass_get_frags_inline (nat_reass_ip4_t * reass, u32 ** bi)
48 {
50  u32 elt_index;
51  dlist_elt_t *elt;
52 
53  while ((elt_index =
55  reass->frags_per_reass_list_head_index)) !=
56  ~0)
57  {
58  elt = pool_elt_at_index (srm->ip4_frags_list_pool, elt_index);
59  vec_add1 (*bi, elt->value);
60  reass->frag_n--;
61  pool_put_index (srm->ip4_frags_list_pool, elt_index);
62  }
63 }
64 
66 nat_ip6_reass_get_frags_inline (nat_reass_ip6_t * reass, u32 ** bi)
67 {
69  u32 elt_index;
70  dlist_elt_t *elt;
71 
72  while ((elt_index =
74  reass->frags_per_reass_list_head_index)) !=
75  ~0)
76  {
77  elt = pool_elt_at_index (srm->ip6_frags_list_pool, elt_index);
78  vec_add1 (*bi, elt->value);
79  reass->frag_n--;
80  pool_put_index (srm->ip6_frags_list_pool, elt_index);
81  }
82 }
83 
84 int
85 nat_reass_set (u32 timeout, u16 max_reass, u8 max_frag, u8 drop_frag,
86  u8 is_ip6)
87 {
89  u32 nbuckets;
90 
91  if (is_ip6)
92  {
93  if (srm->ip6_max_reass != max_reass)
94  {
96 
97  srm->ip6_max_reass = max_reass;
100  nbuckets = nat_reass_get_nbuckets (0);
101  clib_bihash_free_48_8 (&srm->ip6_reass_hash);
102  clib_bihash_init_48_8 (&srm->ip6_reass_hash, "nat-ip6-reass",
103  nbuckets, nbuckets * 1024);
104 
106  }
107  srm->ip6_timeout = timeout;
108  srm->ip6_max_frag = max_frag;
109  srm->ip6_drop_frag = drop_frag;
110  }
111  else
112  {
113  if (srm->ip4_max_reass != max_reass)
114  {
116 
117  srm->ip4_max_reass = max_reass;
118  pool_free (srm->ip4_reass_pool);
120  nbuckets = nat_reass_get_nbuckets (0);
121  clib_bihash_free_16_8 (&srm->ip4_reass_hash);
122  clib_bihash_init_16_8 (&srm->ip4_reass_hash, "nat-ip4-reass",
123  nbuckets, nbuckets * 1024);
125  }
126  srm->ip4_timeout = timeout;
127  srm->ip4_max_frag = max_frag;
128  srm->ip4_drop_frag = drop_frag;
129  }
130 
131  return 0;
132 }
133 
134 u32
136 {
138 
139  if (is_ip6)
140  return srm->ip6_timeout;
141 
142  return srm->ip4_timeout;
143 }
144 
145 u16
147 {
149 
150  if (is_ip6)
151  return srm->ip6_max_reass;
152 
153  return srm->ip4_max_reass;
154 }
155 
156 u8
158 {
160 
161  if (is_ip6)
162  return srm->ip6_max_frag;
163 
164  return srm->ip4_max_frag;
165 }
166 
167 u8
169 {
171 
172  if (is_ip6)
173  return srm->ip6_drop_frag;
174 
175  return srm->ip4_drop_frag;
176 }
177 
178 static_always_inline nat_reass_ip4_t *
180 {
182  clib_bihash_kv_16_8_t kv, value;
183  nat_reass_ip4_t *reass;
184 
185  kv.key[0] = k->as_u64[0];
186  kv.key[1] = k->as_u64[1];
187 
188  if (clib_bihash_search_16_8 (&srm->ip4_reass_hash, &kv, &value))
189  return 0;
190 
191  reass = pool_elt_at_index (srm->ip4_reass_pool, value.value);
192  if (now < reass->last_heard + (f64) srm->ip4_timeout)
193  return reass;
194 
195  return 0;
196 }
197 
198 nat_reass_ip4_t *
200  u8 proto)
201 {
203  nat_reass_ip4_t *reass = 0;
205  f64 now = vlib_time_now (srm->vlib_main);
206 
207  k.src.as_u32 = src.as_u32;
208  k.dst.as_u32 = dst.as_u32;
209  k.frag_id = frag_id;
210  k.proto = proto;
211 
213  reass = nat_ip4_reass_lookup (&k, now);
215 
216  return reass;
217 }
218 
219 nat_reass_ip4_t *
221  u16 frag_id, u8 proto, u8 reset_timeout,
222  u32 ** bi_to_drop)
223 {
225  nat_reass_ip4_t *reass = 0;
227  f64 now = vlib_time_now (srm->vlib_main);
228  dlist_elt_t *oldest_elt, *elt;
229  dlist_elt_t *per_reass_list_head_elt;
230  u32 oldest_index, elt_index;
231  clib_bihash_kv_16_8_t kv, value;
232 
233  k.src.as_u32 = src.as_u32;
234  k.dst.as_u32 = dst.as_u32;
235  k.frag_id = frag_id;
236  k.proto = proto;
237 
239 
240  reass = nat_ip4_reass_lookup (&k, now);
241  if (reass)
242  {
243  if (reset_timeout)
244  {
245  reass->last_heard = now;
247  reass->lru_list_index);
250  reass->lru_list_index);
251  }
252 
253  if (reass->flags & NAT_REASS_FLAG_MAX_FRAG_DROP)
254  {
255  reass = 0;
256  goto unlock;
257  }
258 
259  goto unlock;
260  }
261 
262  if (srm->ip4_reass_n >= srm->ip4_max_reass)
263  {
264  oldest_index =
266  srm->ip4_reass_head_index);
267  ASSERT (oldest_index != ~0);
268  oldest_elt =
269  pool_elt_at_index (srm->ip4_reass_lru_list_pool, oldest_index);
270  reass = pool_elt_at_index (srm->ip4_reass_pool, oldest_elt->value);
271  if (now < reass->last_heard + (f64) srm->ip4_timeout)
272  {
274  srm->ip4_reass_head_index, oldest_index);
275  nat_log_warn ("no free resassembly slot");
276  reass = 0;
277  goto unlock;
278  }
279 
281  srm->ip4_reass_head_index, oldest_index);
282 
283  kv.key[0] = reass->key.as_u64[0];
284  kv.key[1] = reass->key.as_u64[1];
285  if (!clib_bihash_search_16_8 (&srm->ip4_reass_hash, &kv, &value))
286  {
287  if (value.value == (reass - srm->ip4_reass_pool))
288  {
289  if (clib_bihash_add_del_16_8 (&srm->ip4_reass_hash, &kv, 0))
290  {
291  reass = 0;
292  goto unlock;
293  }
294  }
295  }
296 
297  nat_ip4_reass_get_frags_inline (reass, bi_to_drop);
298  }
299  else
300  {
301  pool_get (srm->ip4_reass_pool, reass);
302  pool_get (srm->ip4_reass_lru_list_pool, elt);
303  reass->lru_list_index = elt_index = elt - srm->ip4_reass_lru_list_pool;
304  clib_dlist_init (srm->ip4_reass_lru_list_pool, elt_index);
305  elt->value = reass - srm->ip4_reass_pool;
307  srm->ip4_reass_head_index, elt_index);
308  pool_get (srm->ip4_frags_list_pool, per_reass_list_head_elt);
309  reass->frags_per_reass_list_head_index =
310  per_reass_list_head_elt - srm->ip4_frags_list_pool;
312  reass->frags_per_reass_list_head_index);
313  srm->ip4_reass_n++;
314  }
315 
316  reass->key.as_u64[0] = kv.key[0] = k.as_u64[0];
317  reass->key.as_u64[1] = kv.key[1] = k.as_u64[1];
318  kv.value = reass - srm->ip4_reass_pool;
319  reass->sess_index = (u32) ~ 0;
320  reass->thread_index = (u32) ~ 0;
321  reass->last_heard = now;
322  reass->frag_n = 0;
323  reass->flags = 0;
324  reass->classify_next = NAT_REASS_IP4_CLASSIFY_NONE;
325 
326  if (clib_bihash_add_del_16_8 (&srm->ip4_reass_hash, &kv, 1))
327  {
328  reass = 0;
329  goto unlock;
330  }
331 
332 unlock:
334  return reass;
335 }
336 
337 int
338 nat_ip4_reass_add_fragment (nat_reass_ip4_t * reass, u32 bi,
339  u32 ** bi_to_drop)
340 {
342  dlist_elt_t *elt;
343  u32 elt_index;
344 
345  if (reass->frag_n >= srm->ip4_max_frag)
346  {
348  &reass->key.src);
349  reass->flags |= NAT_REASS_FLAG_MAX_FRAG_DROP;
350  nat_ip4_reass_get_frags_inline (reass, bi_to_drop);
351  return -1;
352  }
353 
355 
356  pool_get (srm->ip4_frags_list_pool, elt);
357  elt_index = elt - srm->ip4_frags_list_pool;
358  clib_dlist_init (srm->ip4_frags_list_pool, elt_index);
359  elt->value = bi;
361  reass->frags_per_reass_list_head_index, elt_index);
362  reass->frag_n++;
363 
365 
366  return 0;
367 }
368 
369 void
370 nat_ip4_reass_get_frags (nat_reass_ip4_t * reass, u32 ** bi)
371 {
373 
375 
376  nat_ip4_reass_get_frags_inline (reass, bi);
377 
379 }
380 
381 void
383 {
384  nat_reass_ip4_t *reass;
386  f64 now = vlib_time_now (srm->vlib_main);
387 
388  /* *INDENT-OFF* */
389  pool_foreach (reass, srm->ip4_reass_pool,
390  ({
391  if (now < reass->last_heard + (f64) srm->ip4_timeout)
392  {
393  if (fn (reass, ctx))
394  return;
395  }
396  }));
397  /* *INDENT-ON* */
398 }
399 
400 static_always_inline nat_reass_ip6_t *
402 {
404  clib_bihash_kv_48_8_t kv, value;
405  nat_reass_ip6_t *reass;
406 
407  k->unused = 0;
408  kv.key[0] = k->as_u64[0];
409  kv.key[1] = k->as_u64[1];
410  kv.key[2] = k->as_u64[2];
411  kv.key[3] = k->as_u64[3];
412  kv.key[4] = k->as_u64[4];
413  kv.key[5] = k->as_u64[5];
414 
415  if (clib_bihash_search_48_8 (&srm->ip6_reass_hash, &kv, &value))
416  return 0;
417 
418  reass = pool_elt_at_index (srm->ip6_reass_pool, value.value);
419  if (now < reass->last_heard + (f64) srm->ip6_timeout)
420  return reass;
421 
422  return 0;
423 }
424 
425 nat_reass_ip6_t *
427  u32 frag_id, u8 proto, u8 reset_timeout,
428  u32 ** bi_to_drop)
429 {
431  nat_reass_ip6_t *reass = 0;
433  f64 now = vlib_time_now (srm->vlib_main);
434  dlist_elt_t *oldest_elt, *elt;
435  dlist_elt_t *per_reass_list_head_elt;
436  u32 oldest_index, elt_index;
438 
439  k.src.as_u64[0] = src.as_u64[0];
440  k.src.as_u64[1] = src.as_u64[1];
441  k.dst.as_u64[0] = dst.as_u64[0];
442  k.dst.as_u64[1] = dst.as_u64[1];
443  k.frag_id = frag_id;
444  k.proto = proto;
445  k.unused = 0;
446 
448 
449  reass = nat_ip6_reass_lookup (&k, now);
450  if (reass)
451  {
452  if (reset_timeout)
453  {
454  reass->last_heard = now;
456  reass->lru_list_index);
459  reass->lru_list_index);
460  }
461 
462  if (reass->flags & NAT_REASS_FLAG_MAX_FRAG_DROP)
463  {
464  reass = 0;
465  goto unlock;
466  }
467 
468  goto unlock;
469  }
470 
471  if (srm->ip6_reass_n >= srm->ip6_max_reass)
472  {
473  oldest_index =
475  srm->ip6_reass_head_index);
476  ASSERT (oldest_index != ~0);
477  oldest_elt =
478  pool_elt_at_index (srm->ip4_reass_lru_list_pool, oldest_index);
479  reass = pool_elt_at_index (srm->ip6_reass_pool, oldest_elt->value);
480  if (now < reass->last_heard + (f64) srm->ip6_timeout)
481  {
483  srm->ip6_reass_head_index, oldest_index);
484  nat_log_warn ("no free resassembly slot");
485  reass = 0;
486  goto unlock;
487  }
488 
490  srm->ip6_reass_head_index, oldest_index);
491 
492  kv.key[0] = k.as_u64[0];
493  kv.key[1] = k.as_u64[1];
494  kv.key[2] = k.as_u64[2];
495  kv.key[3] = k.as_u64[4];
496  kv.key[4] = k.as_u64[5];
497  if (clib_bihash_add_del_48_8 (&srm->ip6_reass_hash, &kv, 0))
498  {
499  reass = 0;
500  goto unlock;
501  }
502 
503  nat_ip6_reass_get_frags_inline (reass, bi_to_drop);
504  }
505  else
506  {
507  pool_get (srm->ip6_reass_pool, reass);
508  pool_get (srm->ip6_reass_lru_list_pool, elt);
509  reass->lru_list_index = elt_index = elt - srm->ip6_reass_lru_list_pool;
510  clib_dlist_init (srm->ip6_reass_lru_list_pool, elt_index);
511  elt->value = reass - srm->ip6_reass_pool;
513  srm->ip6_reass_head_index, elt_index);
514  pool_get (srm->ip6_frags_list_pool, per_reass_list_head_elt);
515  reass->frags_per_reass_list_head_index =
516  per_reass_list_head_elt - srm->ip6_frags_list_pool;
518  reass->frags_per_reass_list_head_index);
519  srm->ip6_reass_n++;
520  }
521 
522  reass->key.as_u64[0] = kv.key[0] = k.as_u64[0];
523  reass->key.as_u64[1] = kv.key[1] = k.as_u64[1];
524  reass->key.as_u64[2] = kv.key[2] = k.as_u64[2];
525  reass->key.as_u64[3] = kv.key[3] = k.as_u64[3];
526  reass->key.as_u64[4] = kv.key[4] = k.as_u64[4];
527  reass->key.as_u64[5] = kv.key[5] = k.as_u64[5];
528  kv.value = reass - srm->ip6_reass_pool;
529  reass->sess_index = (u32) ~ 0;
530  reass->last_heard = now;
531 
532  if (clib_bihash_add_del_48_8 (&srm->ip6_reass_hash, &kv, 1))
533  {
534  reass = 0;
535  goto unlock;
536  }
537 
538 unlock:
540  return reass;
541 }
542 
543 int
544 nat_ip6_reass_add_fragment (nat_reass_ip6_t * reass, u32 bi,
545  u32 ** bi_to_drop)
546 {
548  dlist_elt_t *elt;
549  u32 elt_index;
550 
551  if (reass->frag_n >= srm->ip6_max_frag)
552  {
554  &reass->key.src);
555  reass->flags |= NAT_REASS_FLAG_MAX_FRAG_DROP;
556  nat_ip6_reass_get_frags_inline (reass, bi_to_drop);
557  return -1;
558  }
559 
561 
562  pool_get (srm->ip6_frags_list_pool, elt);
563  elt_index = elt - srm->ip6_frags_list_pool;
564  clib_dlist_init (srm->ip6_frags_list_pool, elt_index);
565  elt->value = bi;
567  reass->frags_per_reass_list_head_index, elt_index);
568  reass->frag_n++;
569 
571 
572  return 0;
573 }
574 
575 void
576 nat_ip6_reass_get_frags (nat_reass_ip6_t * reass, u32 ** bi)
577 {
579 
581 
582  nat_ip6_reass_get_frags_inline (reass, bi);
583 
585 }
586 
587 void
589 {
590  nat_reass_ip6_t *reass;
592  f64 now = vlib_time_now (srm->vlib_main);
593 
594  /* *INDENT-OFF* */
595  pool_foreach (reass, srm->ip6_reass_pool,
596  ({
597  if (now < reass->last_heard + (f64) srm->ip4_timeout)
598  {
599  if (fn (reass, ctx))
600  return;
601  }
602  }));
603  /* *INDENT-ON* */
604 }
605 
606 clib_error_t *
608 {
611  clib_error_t *error = 0;
612  dlist_elt_t *head;
613  u32 nbuckets, head_index;
614 
615  srm->vlib_main = vm;
616  srm->vnet_main = vnet_get_main ();
617 
618  /* IPv4 */
622  srm->ip4_drop_frag = 0;
623  srm->ip4_reass_n = 0;
624 
625  if (tm->n_vlib_mains > 1)
627 
629 
630  nbuckets = nat_reass_get_nbuckets (0);
631  clib_bihash_init_16_8 (&srm->ip4_reass_hash, "nat-ip4-reass", nbuckets,
632  nbuckets * 1024);
633 
634  pool_get (srm->ip4_reass_lru_list_pool, head);
635  srm->ip4_reass_head_index = head_index =
636  head - srm->ip4_reass_lru_list_pool;
637  clib_dlist_init (srm->ip4_reass_lru_list_pool, head_index);
638 
639  /* IPv6 */
643  srm->ip6_drop_frag = 0;
644  srm->ip6_reass_n = 0;
645 
646  if (tm->n_vlib_mains > 1)
648 
650 
651  nbuckets = nat_reass_get_nbuckets (1);
652  clib_bihash_init_48_8 (&srm->ip6_reass_hash, "nat-ip6-reass", nbuckets,
653  nbuckets * 1024);
654 
655  pool_get (srm->ip6_reass_lru_list_pool, head);
656  srm->ip6_reass_head_index = head_index =
657  head - srm->ip6_reass_lru_list_pool;
658  clib_dlist_init (srm->ip6_reass_lru_list_pool, head_index);
659 
660  return error;
661 }
662 
663 static clib_error_t *
665  vlib_cli_command_t * cmd)
666 {
667  clib_error_t *error = 0;
668  unformat_input_t _line_input, *line_input = &_line_input;
669  u32 timeout = 0, max_reass = 0, max_frag = 0;
670  u8 drop_frag = (u8) ~ 0, is_ip6 = 0;
671  int rv;
672 
673  /* Get a line of input. */
674  if (!unformat_user (input, unformat_line_input, line_input))
675  return 0;
676 
677  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
678  {
679  if (unformat (line_input, "max-reassemblies %u", &max_reass))
680  ;
681  else if (unformat (line_input, "max-fragments %u", &max_frag))
682  ;
683  else if (unformat (line_input, "timeout %u", &timeout))
684  ;
685  else if (unformat (line_input, "enable"))
686  drop_frag = 0;
687  else if (unformat (line_input, "disable"))
688  drop_frag = 1;
689  else if (unformat (line_input, "ip4"))
690  is_ip6 = 0;
691  else if (unformat (line_input, "ip6"))
692  is_ip6 = 1;
693  else
694  {
695  error = clib_error_return (0, "unknown input '%U'",
696  format_unformat_error, line_input);
697  goto done;
698  }
699  }
700 
701  if (!timeout)
702  timeout = nat_reass_get_timeout (is_ip6);
703  if (!max_reass)
704  max_reass = nat_reass_get_max_reass (is_ip6);
705  if (!max_frag)
706  max_frag = nat_reass_get_max_frag (is_ip6);
707  if (drop_frag == (u8) ~ 0)
708  drop_frag = nat_reass_is_drop_frag (is_ip6);
709 
710  rv =
711  nat_reass_set (timeout, (u16) max_reass, (u8) max_frag, drop_frag,
712  is_ip6);
713  if (rv)
714  {
715  error = clib_error_return (0, "nat_set_reass return %d", rv);
716  goto done;
717  }
718 
719 done:
720  unformat_free (line_input);
721 
722  return error;
723 }
724 
725 static int
726 nat_ip4_reass_walk_cli (nat_reass_ip4_t * reass, void *ctx)
727 {
728  vlib_main_t *vm = ctx;
729  u8 *flags_str = 0;
730  const char *classify_next_str;
731 
732  if (reass->flags & NAT_REASS_FLAG_MAX_FRAG_DROP)
733  flags_str = format (flags_str, "MAX_FRAG_DROP");
734  if (reass->flags & NAT_REASS_FLAG_CLASSIFY_ED_CONTINUE)
735  {
736  if (flags_str)
737  flags_str = format (flags_str, " | ");
738  flags_str = format (flags_str, "CLASSIFY_ED_CONTINUE");
739  }
740  if (reass->flags & NAT_REASS_FLAG_ED_DONT_TRANSLATE)
741  {
742  if (flags_str)
743  flags_str = format (flags_str, " | ");
744  flags_str = format (flags_str, "CLASSIFY_ED_DONT_TRANSLATE");
745  }
746  if (!flags_str)
747  flags_str = format (flags_str, "0");
748  flags_str = format (flags_str, "%c", 0);
749 
750  switch (reass->classify_next)
751  {
753  classify_next_str = "NONE";
754  break;
756  classify_next_str = "IN2OUT";
757  break;
759  classify_next_str = "OUT2IN";
760  break;
761  default:
762  classify_next_str = "invalid value";
763  }
764 
765  vlib_cli_output (vm, " src %U dst %U proto %u id 0x%04x cached %u "
766  "flags %s classify_next %s",
767  format_ip4_address, &reass->key.src,
768  format_ip4_address, &reass->key.dst,
769  reass->key.proto,
770  clib_net_to_host_u16 (reass->key.frag_id), reass->frag_n,
771  flags_str, classify_next_str);
772 
773  vec_free (flags_str);
774 
775  return 0;
776 }
777 
778 static int
779 nat_ip6_reass_walk_cli (nat_reass_ip6_t * reass, void *ctx)
780 {
781  vlib_main_t *vm = ctx;
782 
783  vlib_cli_output (vm, " src %U dst %U proto %u id 0x%08x cached %u",
784  format_ip6_address, &reass->key.src,
785  format_ip6_address, &reass->key.dst,
786  reass->key.proto,
787  clib_net_to_host_u32 (reass->key.frag_id), reass->frag_n);
788 
789  return 0;
790 }
791 
792 static clib_error_t *
794  vlib_cli_command_t * cmd)
795 {
796  vlib_cli_output (vm, "NAT IPv4 virtual fragmentation reassembly is %s",
797  nat_reass_is_drop_frag (0) ? "DISABLED" : "ENABLED");
798  vlib_cli_output (vm, " max-reassemblies %u", nat_reass_get_max_reass (0));
799  vlib_cli_output (vm, " max-fragments %u", nat_reass_get_max_frag (0));
800  vlib_cli_output (vm, " timeout %usec", nat_reass_get_timeout (0));
801  vlib_cli_output (vm, " reassemblies:");
803 
804  vlib_cli_output (vm, "NAT IPv6 virtual fragmentation reassembly is %s",
805  nat_reass_is_drop_frag (1) ? "DISABLED" : "ENABLED");
806  vlib_cli_output (vm, " max-reassemblies %u", nat_reass_get_max_reass (1));
807  vlib_cli_output (vm, " max-fragments %u", nat_reass_get_max_frag (1));
808  vlib_cli_output (vm, " timeout %usec", nat_reass_get_timeout (1));
809  vlib_cli_output (vm, " reassemblies:");
811 
812  return 0;
813 }
814 
815 /* *INDENT-OFF* */
816 VLIB_CLI_COMMAND (nat_reass_command, static) =
817 {
818  .path = "nat virtual-reassembly",
819  .short_help = "nat virtual-reassembly ip4|ip6 [max-reassemblies <n>] "
820  "[max-fragments <n>] [timeout <sec>] [enable|disable]",
821  .function = nat_reass_command_fn,
822 };
823 
824 VLIB_CLI_COMMAND (show_nat_reass_command, static) =
825 {
826  .path = "show nat virtual-reassembly",
827  .short_help = "show nat virtual-reassembly",
828  .function = show_nat_reass_command_fn,
829 };
830 /* *INDENT-ON* */
831 
832 /*
833  * fd.io coding-style-patch-verification: ON
834  *
835  * Local Variables:
836  * eval: (c-set-style "gnu")
837  * End:
838  */
u32 nat_reass_get_timeout(u8 is_ip6)
Get reassembly timeout.
Definition: nat_reass.c:135
ip4_address_t src
Definition: nat_reass.h:43
vl_api_address_t src
Definition: vxlan_gbp.api:33
static void clib_dlist_init(dlist_elt_t *pool, u32 index)
Definition: dlist.h:36
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
clib_error_t * nat_reass_init(vlib_main_t *vm)
Initialize NAT virtual fragmentation reassembly.
Definition: nat_reass.c:607
#define pool_alloc(P, N)
Allocate N more free elements to pool (unspecified alignment).
Definition: pool.h:329
u64 as_u64[2]
Definition: ip6_packet.h:51
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:227
static int nat_ip6_reass_walk_cli(nat_reass_ip6_t *reass, void *ctx)
Definition: nat_reass.c:779
void nat_ip6_reass_get_frags(nat_reass_ip6_t *reass, u32 **bi)
Get cached fragments.
Definition: nat_reass.c:576
static_always_inline void clib_spinlock_unlock_if_init(clib_spinlock_t *p)
Definition: lock.h:98
nat_reass_ip4_t * nat_ip4_reass_find(ip4_address_t src, ip4_address_t dst, u16 frag_id, u8 proto)
Find reassembly.
Definition: nat_reass.c:199
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:523
#define nat_log_warn(...)
Definition: nat.h:687
int i
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
int(* nat_ip6_reass_walk_fn_t)(nat_reass_ip6_t *reass, void *ctx)
Call back function when walking IPv6 reassemblies, non-zero return value stop walk.
Definition: nat_reass.h:309
void nat_ipfix_logging_max_fragments_ip6(u32 limit, ip6_address_t *src)
Generate maximum IPv6 fragments pending reassembly exceeded event.
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:228
unsigned char u8
Definition: types.h:56
void nat_ip4_reass_walk(nat_ip4_reass_walk_fn_t fn, void *ctx)
Walk IPv4 reassemblies.
Definition: nat_reass.c:382
static clib_error_t * nat_reass_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat_reass.c:664
double f64
Definition: types.h:142
u32 ip6_reass_head_index
Definition: nat_reass.h:134
format_function_t format_ip4_address
Definition: format.h:75
#define static_always_inline
Definition: clib.h:95
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:443
dlist_elt_t * ip4_frags_list_pool
Definition: nat_reass.h:124
dlist_elt_t * ip6_reass_lru_list_pool
Definition: nat_reass.h:132
static_always_inline void nat_ip6_reass_get_frags_inline(nat_reass_ip6_t *reass, u32 **bi)
Definition: nat_reass.c:66
#define NAT_MAX_REASS_DEAFULT
Definition: nat_reass.h:29
#define NAT_REASS_FLAG_MAX_FRAG_DROP
Definition: nat_reass.h:33
#define clib_error_return(e, args...)
Definition: error.h:99
#define NAT_REASS_FLAG_ED_DONT_TRANSLATE
Definition: nat_reass.h:35
unsigned int u32
Definition: types.h:88
#define NAT_REASS_FLAG_CLASSIFY_ED_CONTINUE
Definition: nat_reass.h:34
nat_reass_ip6_t * ip6_reass_pool
Definition: nat_reass.h:130
vnet_main_t * vnet_main
Definition: nat_reass.h:140
unformat_function_t unformat_line_input
Definition: format.h:282
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:57
#define NAT_MAX_FRAG_DEFAULT
Definition: nat_reass.h:30
u8 nat_reass_get_max_frag(u8 is_ip6)
Get maximum number of fragmets per reassembly.
Definition: nat_reass.c:157
vlib_main_t * vlib_main
Definition: nat_reass.h:139
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:464
static int nat_ip4_reass_walk_cli(nat_reass_ip4_t *reass, void *ctx)
Definition: nat_reass.c:726
dlist_elt_t * ip4_reass_lru_list_pool
Definition: nat_reass.h:123
static_always_inline void nat_ip4_reass_get_frags_inline(nat_reass_ip4_t *reass, u32 **bi)
Definition: nat_reass.c:47
long ctx[MAX_CONNS]
Definition: main.c:144
static void clib_dlist_addtail(dlist_elt_t *pool, u32 head_index, u32 new_index)
Definition: dlist.h:43
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
#define NAT_REASS_TIMEOUT_DEFAULT
Definition: nat_reass.h:28
static clib_error_t * show_nat_reass_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: nat_reass.c:793
int(* nat_ip4_reass_walk_fn_t)(nat_reass_ip4_t *reass, void *ctx)
Call back function when walking IPv4 reassemblies, non-zero return value stop walk.
Definition: nat_reass.h:258
#define pool_free(p)
Free a pool.
Definition: pool.h:357
u16 nat_reass_get_max_reass(u8 is_ip6)
Get maximum number of concurrent reassemblies.
Definition: nat_reass.c:146
u32 ip4_reass_head_index
Definition: nat_reass.h:125
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
static void clib_dlist_addhead(dlist_elt_t *pool, u32 head_index, u32 new_index)
Definition: dlist.h:71
int nat_reass_set(u32 timeout, u16 max_reass, u8 max_frag, u8 drop_frag, u8 is_ip6)
Set NAT virtual fragmentation reassembly configuration.
Definition: nat_reass.c:85
format_function_t format_ip6_address
Definition: format.h:93
u8 nat_reass_is_drop_frag(u8 is_ip6)
Get status of virtual fragmentation reassembly.
Definition: nat_reass.c:168
vlib_main_t * vm
Definition: buffer.c:294
vl_api_address_t dst
Definition: vxlan_gbp.api:34
static u32 nat_reass_get_nbuckets(u8 is_ip6)
Definition: nat_reass.c:27
int nat_ip6_reass_add_fragment(nat_reass_ip6_t *reass, u32 bi, u32 **bi_to_drop)
Cache fragment.
Definition: nat_reass.c:544
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
nat_reass_ip4_t * ip4_reass_pool
Definition: nat_reass.h:121
dlist_elt_t * ip6_frags_list_pool
Definition: nat_reass.h:133
ip6_address_t dst
Definition: nat_reass.h:83
clib_bihash_16_8_t ip4_reass_hash
Definition: nat_reass.h:122
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
static_always_inline nat_reass_ip4_t * nat_ip4_reass_lookup(nat_reass_ip4_key_t *k, f64 now)
Definition: nat_reass.c:179
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:299
void nat_ipfix_logging_max_fragments_ip4(u32 limit, ip4_address_t *src)
Generate maximum IPv4 fragments pending reassembly exceeded event.
#define ASSERT(truth)
nat_reass_main_t nat_reass_main
Definition: nat_reass.c:24
static void clib_dlist_remove(dlist_elt_t *pool, u32 index)
Definition: dlist.h:99
u32 value
Definition: dlist.h:32
static_always_inline nat_reass_ip6_t * nat_ip6_reass_lookup(nat_reass_ip6_key_t *k, f64 now)
Definition: nat_reass.c:401
ip6_address_t src
Definition: nat_reass.h:82
nat_reass_ip6_t * nat_ip6_reass_find_or_create(ip6_address_t src, ip6_address_t dst, u32 frag_id, u8 proto, u8 reset_timeout, u32 **bi_to_drop)
Find or create reassembly.
Definition: nat_reass.c:426
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
void nat_ip6_reass_walk(nat_ip6_reass_walk_fn_t fn, void *ctx)
Walk IPv6 reassemblies.
Definition: nat_reass.c:588
nat_reass_ip4_t * nat_ip4_reass_find_or_create(ip4_address_t src, ip4_address_t dst, u16 frag_id, u8 proto, u8 reset_timeout, u32 **bi_to_drop)
Find or create reassembly.
Definition: nat_reass.c:220
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
int nat_ip4_reass_add_fragment(nat_reass_ip4_t *reass, u32 bi, u32 **bi_to_drop)
Cache fragment.
Definition: nat_reass.c:338
#define NAT_REASS_HT_LOAD_FACTOR
Definition: nat_reass.h:31
void nat_ip4_reass_get_frags(nat_reass_ip4_t *reass, u32 **bi)
Get cached fragments.
Definition: nat_reass.c:370
NAT plugin virtual fragmentation reassembly.
clib_bihash_48_8_t ip6_reass_hash
Definition: nat_reass.h:131
ip4_address_t dst
Definition: nat_reass.h:44
clib_spinlock_t ip6_reass_lock
Definition: nat_reass.h:136
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:725
static_always_inline void clib_spinlock_lock_if_init(clib_spinlock_t *p)
Definition: lock.h:82
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
clib_spinlock_t ip4_reass_lock
Definition: nat_reass.h:127
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
static u32 clib_dlist_remove_head(dlist_elt_t *pool, u32 head_index)
Definition: dlist.h:117