FD.io VPP  v18.07.1-19-g511ce25
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  clib_warning ("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 
324  if (clib_bihash_add_del_16_8 (&srm->ip4_reass_hash, &kv, 1))
325  {
326  reass = 0;
327  goto unlock;
328  }
329 
330 unlock:
332  return reass;
333 }
334 
335 int
336 nat_ip4_reass_add_fragment (nat_reass_ip4_t * reass, u32 bi,
337  u32 ** bi_to_drop)
338 {
340  dlist_elt_t *elt;
341  u32 elt_index;
342 
343  if (reass->frag_n >= srm->ip4_max_frag)
344  {
346  &reass->key.src);
347  reass->flags |= NAT_REASS_FLAG_MAX_FRAG_DROP;
348  nat_ip4_reass_get_frags_inline (reass, bi_to_drop);
349  return -1;
350  }
351 
353 
354  pool_get (srm->ip4_frags_list_pool, elt);
355  elt_index = elt - srm->ip4_frags_list_pool;
356  clib_dlist_init (srm->ip4_frags_list_pool, elt_index);
357  elt->value = bi;
359  reass->frags_per_reass_list_head_index, elt_index);
360  reass->frag_n++;
361 
363 
364  return 0;
365 }
366 
367 void
368 nat_ip4_reass_get_frags (nat_reass_ip4_t * reass, u32 ** bi)
369 {
371 
373 
374  nat_ip4_reass_get_frags_inline (reass, bi);
375 
377 }
378 
379 void
381 {
382  nat_reass_ip4_t *reass;
384  f64 now = vlib_time_now (srm->vlib_main);
385 
386  /* *INDENT-OFF* */
387  pool_foreach (reass, srm->ip4_reass_pool,
388  ({
389  if (now < reass->last_heard + (f64) srm->ip4_timeout)
390  {
391  if (fn (reass, ctx))
392  return;
393  }
394  }));
395  /* *INDENT-ON* */
396 }
397 
398 static_always_inline nat_reass_ip6_t *
400 {
402  clib_bihash_kv_48_8_t kv, value;
403  nat_reass_ip6_t *reass;
404 
405  k->unused = 0;
406  kv.key[0] = k->as_u64[0];
407  kv.key[1] = k->as_u64[1];
408  kv.key[2] = k->as_u64[2];
409  kv.key[3] = k->as_u64[3];
410  kv.key[4] = k->as_u64[4];
411  kv.key[5] = k->as_u64[5];
412 
413  if (clib_bihash_search_48_8 (&srm->ip6_reass_hash, &kv, &value))
414  return 0;
415 
416  reass = pool_elt_at_index (srm->ip6_reass_pool, value.value);
417  if (now < reass->last_heard + (f64) srm->ip6_timeout)
418  return reass;
419 
420  return 0;
421 }
422 
423 nat_reass_ip6_t *
425  u32 frag_id, u8 proto, u8 reset_timeout,
426  u32 ** bi_to_drop)
427 {
429  nat_reass_ip6_t *reass = 0;
431  f64 now = vlib_time_now (srm->vlib_main);
432  dlist_elt_t *oldest_elt, *elt;
433  dlist_elt_t *per_reass_list_head_elt;
434  u32 oldest_index, elt_index;
436 
437  k.src.as_u64[0] = src.as_u64[0];
438  k.src.as_u64[1] = src.as_u64[1];
439  k.dst.as_u64[0] = dst.as_u64[0];
440  k.dst.as_u64[1] = dst.as_u64[1];
441  k.frag_id = frag_id;
442  k.proto = proto;
443  k.unused = 0;
444 
446 
447  reass = nat_ip6_reass_lookup (&k, now);
448  if (reass)
449  {
450  if (reset_timeout)
451  {
452  reass->last_heard = now;
454  reass->lru_list_index);
457  reass->lru_list_index);
458  }
459 
460  if (reass->flags && NAT_REASS_FLAG_MAX_FRAG_DROP)
461  {
462  reass = 0;
463  goto unlock;
464  }
465 
466  goto unlock;
467  }
468 
469  if (srm->ip6_reass_n >= srm->ip6_max_reass)
470  {
471  oldest_index =
473  srm->ip6_reass_head_index);
474  ASSERT (oldest_index != ~0);
475  oldest_elt =
476  pool_elt_at_index (srm->ip4_reass_lru_list_pool, oldest_index);
477  reass = pool_elt_at_index (srm->ip6_reass_pool, oldest_elt->value);
478  if (now < reass->last_heard + (f64) srm->ip6_timeout)
479  {
481  srm->ip6_reass_head_index, oldest_index);
482  clib_warning ("no free resassembly slot");
483  reass = 0;
484  goto unlock;
485  }
486 
488  srm->ip6_reass_head_index, oldest_index);
489 
490  kv.key[0] = k.as_u64[0];
491  kv.key[1] = k.as_u64[1];
492  kv.key[2] = k.as_u64[2];
493  kv.key[3] = k.as_u64[4];
494  kv.key[4] = k.as_u64[5];
495  if (clib_bihash_add_del_48_8 (&srm->ip6_reass_hash, &kv, 0))
496  {
497  reass = 0;
498  goto unlock;
499  }
500 
501  nat_ip6_reass_get_frags_inline (reass, bi_to_drop);
502  }
503  else
504  {
505  pool_get (srm->ip6_reass_pool, reass);
506  pool_get (srm->ip6_reass_lru_list_pool, elt);
507  reass->lru_list_index = elt_index = elt - srm->ip6_reass_lru_list_pool;
508  clib_dlist_init (srm->ip6_reass_lru_list_pool, elt_index);
509  elt->value = reass - srm->ip6_reass_pool;
511  srm->ip6_reass_head_index, elt_index);
512  pool_get (srm->ip6_frags_list_pool, per_reass_list_head_elt);
513  reass->frags_per_reass_list_head_index =
514  per_reass_list_head_elt - srm->ip6_frags_list_pool;
516  reass->frags_per_reass_list_head_index);
517  srm->ip6_reass_n++;
518  }
519 
520  reass->key.as_u64[0] = kv.key[0] = k.as_u64[0];
521  reass->key.as_u64[1] = kv.key[1] = k.as_u64[1];
522  reass->key.as_u64[2] = kv.key[2] = k.as_u64[2];
523  reass->key.as_u64[3] = kv.key[3] = k.as_u64[3];
524  reass->key.as_u64[4] = kv.key[4] = k.as_u64[4];
525  reass->key.as_u64[5] = kv.key[5] = k.as_u64[5];
526  kv.value = reass - srm->ip6_reass_pool;
527  reass->sess_index = (u32) ~ 0;
528  reass->last_heard = now;
529 
530  if (clib_bihash_add_del_48_8 (&srm->ip6_reass_hash, &kv, 1))
531  {
532  reass = 0;
533  goto unlock;
534  }
535 
536 unlock:
538  return reass;
539 }
540 
541 int
542 nat_ip6_reass_add_fragment (nat_reass_ip6_t * reass, u32 bi,
543  u32 ** bi_to_drop)
544 {
546  dlist_elt_t *elt;
547  u32 elt_index;
548 
549  if (reass->frag_n >= srm->ip6_max_frag)
550  {
552  &reass->key.src);
553  reass->flags |= NAT_REASS_FLAG_MAX_FRAG_DROP;
554  nat_ip6_reass_get_frags_inline (reass, bi_to_drop);
555  return -1;
556  }
557 
559 
560  pool_get (srm->ip6_frags_list_pool, elt);
561  elt_index = elt - srm->ip6_frags_list_pool;
562  clib_dlist_init (srm->ip6_frags_list_pool, elt_index);
563  elt->value = bi;
565  reass->frags_per_reass_list_head_index, elt_index);
566  reass->frag_n++;
567 
569 
570  return 0;
571 }
572 
573 void
574 nat_ip6_reass_get_frags (nat_reass_ip6_t * reass, u32 ** bi)
575 {
577 
579 
580  nat_ip6_reass_get_frags_inline (reass, bi);
581 
583 }
584 
585 void
587 {
588  nat_reass_ip6_t *reass;
590  f64 now = vlib_time_now (srm->vlib_main);
591 
592  /* *INDENT-OFF* */
593  pool_foreach (reass, srm->ip6_reass_pool,
594  ({
595  if (now < reass->last_heard + (f64) srm->ip4_timeout)
596  {
597  if (fn (reass, ctx))
598  return;
599  }
600  }));
601  /* *INDENT-ON* */
602 }
603 
604 clib_error_t *
606 {
609  clib_error_t *error = 0;
610  dlist_elt_t *head;
611  u32 nbuckets, head_index;
612 
613  srm->vlib_main = vm;
614  srm->vnet_main = vnet_get_main ();
615 
616  /* IPv4 */
620  srm->ip4_drop_frag = 0;
621  srm->ip4_reass_n = 0;
622 
623  if (tm->n_vlib_mains > 1)
625 
627 
628  nbuckets = nat_reass_get_nbuckets (0);
629  clib_bihash_init_16_8 (&srm->ip4_reass_hash, "nat-ip4-reass", nbuckets,
630  nbuckets * 1024);
631 
632  pool_get (srm->ip4_reass_lru_list_pool, head);
633  srm->ip4_reass_head_index = head_index =
634  head - srm->ip4_reass_lru_list_pool;
635  clib_dlist_init (srm->ip4_reass_lru_list_pool, head_index);
636 
637  /* IPv6 */
641  srm->ip6_drop_frag = 0;
642  srm->ip6_reass_n = 0;
643 
644  if (tm->n_vlib_mains > 1)
646 
648 
649  nbuckets = nat_reass_get_nbuckets (1);
650  clib_bihash_init_48_8 (&srm->ip6_reass_hash, "nat-ip6-reass", nbuckets,
651  nbuckets * 1024);
652 
653  pool_get (srm->ip6_reass_lru_list_pool, head);
654  srm->ip6_reass_head_index = head_index =
655  head - srm->ip6_reass_lru_list_pool;
656  clib_dlist_init (srm->ip6_reass_lru_list_pool, head_index);
657 
658  return error;
659 }
660 
661 static clib_error_t *
663  vlib_cli_command_t * cmd)
664 {
665  clib_error_t *error = 0;
666  unformat_input_t _line_input, *line_input = &_line_input;
667  u32 timeout = 0, max_reass = 0, max_frag = 0;
668  u8 drop_frag = (u8) ~ 0, is_ip6 = 0;
669  int rv;
670 
671  /* Get a line of input. */
672  if (!unformat_user (input, unformat_line_input, line_input))
673  return 0;
674 
675  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
676  {
677  if (unformat (line_input, "max-reassemblies %u", &max_reass))
678  ;
679  else if (unformat (line_input, "max-fragments %u", &max_frag))
680  ;
681  else if (unformat (line_input, "timeout %u", &timeout))
682  ;
683  else if (unformat (line_input, "enable"))
684  drop_frag = 0;
685  else if (unformat (line_input, "disable"))
686  drop_frag = 1;
687  else if (unformat (line_input, "ip4"))
688  is_ip6 = 0;
689  else if (unformat (line_input, "ip6"))
690  is_ip6 = 1;
691  else
692  {
693  error = clib_error_return (0, "unknown input '%U'",
694  format_unformat_error, line_input);
695  goto done;
696  }
697  }
698 
699  if (!timeout)
700  timeout = nat_reass_get_timeout (is_ip6);
701  if (!max_reass)
702  max_reass = nat_reass_get_max_reass (is_ip6);
703  if (!max_frag)
704  max_frag = nat_reass_get_max_frag (is_ip6);
705  if (drop_frag == (u8) ~ 0)
706  drop_frag = nat_reass_is_drop_frag (is_ip6);
707 
708  rv =
709  nat_reass_set (timeout, (u16) max_reass, (u8) max_frag, drop_frag,
710  is_ip6);
711  if (rv)
712  {
713  error = clib_error_return (0, "nat_set_reass return %d", rv);
714  goto done;
715  }
716 
717 done:
718  unformat_free (line_input);
719 
720  return error;
721 }
722 
723 static int
724 nat_ip4_reass_walk_cli (nat_reass_ip4_t * reass, void *ctx)
725 {
726  vlib_main_t *vm = ctx;
727 
728  vlib_cli_output (vm, " src %U dst %U proto %u id 0x%04x cached %u",
729  format_ip4_address, &reass->key.src,
730  format_ip4_address, &reass->key.dst,
731  reass->key.proto,
732  clib_net_to_host_u16 (reass->key.frag_id), reass->frag_n);
733 
734  return 0;
735 }
736 
737 static int
738 nat_ip6_reass_walk_cli (nat_reass_ip6_t * reass, void *ctx)
739 {
740  vlib_main_t *vm = ctx;
741 
742  vlib_cli_output (vm, " src %U dst %U proto %u id 0x%08x cached %u",
743  format_ip6_address, &reass->key.src,
744  format_ip6_address, &reass->key.dst,
745  reass->key.proto,
746  clib_net_to_host_u32 (reass->key.frag_id), reass->frag_n);
747 
748  return 0;
749 }
750 
751 static clib_error_t *
753  vlib_cli_command_t * cmd)
754 {
755  vlib_cli_output (vm, "NAT IPv4 virtual fragmentation reassembly is %s",
756  nat_reass_is_drop_frag (0) ? "DISABLED" : "ENABLED");
757  vlib_cli_output (vm, " max-reassemblies %u", nat_reass_get_max_reass (0));
758  vlib_cli_output (vm, " max-fragments %u", nat_reass_get_max_frag (0));
759  vlib_cli_output (vm, " timeout %usec", nat_reass_get_timeout (0));
760  vlib_cli_output (vm, " reassemblies:");
762 
763  vlib_cli_output (vm, "NAT IPv6 virtual fragmentation reassembly is %s",
764  nat_reass_is_drop_frag (1) ? "DISABLED" : "ENABLED");
765  vlib_cli_output (vm, " max-reassemblies %u", nat_reass_get_max_reass (1));
766  vlib_cli_output (vm, " max-fragments %u", nat_reass_get_max_frag (1));
767  vlib_cli_output (vm, " timeout %usec", nat_reass_get_timeout (1));
768  vlib_cli_output (vm, " reassemblies:");
770 
771  return 0;
772 }
773 
774 /* *INDENT-OFF* */
775 VLIB_CLI_COMMAND (nat_reass_command, static) =
776 {
777  .path = "nat virtual-reassembly",
778  .short_help = "nat virtual-reassembly ip4|ip6 [max-reassemblies <n>] "
779  "[max-fragments <n>] [timeout <sec>] [enable|disable]",
780  .function = nat_reass_command_fn,
781 };
782 
783 VLIB_CLI_COMMAND (show_nat_reass_command, static) =
784 {
785  .path = "show nat virtual-reassembly",
786  .short_help = "show nat virtual-reassembly",
787  .function = show_nat_reass_command_fn,
788 };
789 /* *INDENT-ON* */
790 
791 /*
792  * fd.io coding-style-patch-verification: ON
793  *
794  * Local Variables:
795  * eval: (c-set-style "gnu")
796  * End:
797  */
u32 nat_reass_get_timeout(u8 is_ip6)
Get reassembly timeout.
Definition: nat_reass.c:135
ip4_address_t src
Definition: nat_reass.h:41
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:605
#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:228
static int nat_ip6_reass_walk_cli(nat_reass_ip6_t *reass, void *ctx)
Definition: nat_reass.c:738
void nat_ip6_reass_get_frags(nat_reass_ip6_t *reass, u32 **bi)
Get cached fragments.
Definition: nat_reass.c:574
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
int i
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
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:299
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:380
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:662
double f64
Definition: types.h:142
u32 ip6_reass_head_index
Definition: nat_reass.h:124
format_function_t format_ip4_address
Definition: format.h:81
#define static_always_inline
Definition: clib.h:93
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:443
dlist_elt_t * ip4_frags_list_pool
Definition: nat_reass.h:114
dlist_elt_t * ip6_reass_lru_list_pool
Definition: nat_reass.h:122
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
unsigned int u32
Definition: types.h:88
nat_reass_ip6_t * ip6_reass_pool
Definition: nat_reass.h:120
vnet_main_t * vnet_main
Definition: nat_reass.h:130
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:129
#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:724
dlist_elt_t * ip4_reass_lru_list_pool
Definition: nat_reass.h:113
static_always_inline void nat_ip4_reass_get_frags_inline(nat_reass_ip4_t *reass, u32 **bi)
Definition: nat_reass.c:47
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:752
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:248
#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:115
#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:99
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
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:542
#define clib_warning(format, args...)
Definition: error.h:59
nat_reass_ip4_t * ip4_reass_pool
Definition: nat_reass.h:111
dlist_elt_t * ip6_frags_list_pool
Definition: nat_reass.h:123
ip6_address_t dst
Definition: nat_reass.h:73
clib_bihash_16_8_t ip4_reass_hash
Definition: nat_reass.h:112
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
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)
long ctx[MAX_CONNS]
Definition: main.c:126
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:399
ip6_address_t src
Definition: nat_reass.h:72
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:424
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:586
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:336
#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:368
NAT plugin virtual fragmentation reassembly.
clib_bihash_48_8_t ip6_reass_hash
Definition: nat_reass.h:121
ip4_address_t dst
Definition: nat_reass.h:42
clib_spinlock_t ip6_reass_lock
Definition: nat_reass.h:126
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:681
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:117
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