FD.io VPP  v19.08-27-gf4dcae4
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 {
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  u8 proto)
222 {
224  nat_reass_ip4_t *reass = 0;
225  dlist_elt_t *elt, *per_reass_list_head_elt;
226  u32 elt_index;
227  f64 now = vlib_time_now (srm->vlib_main);
230 
232 
233  if (srm->ip4_reass_n >= srm->ip4_max_reass)
234  {
235  nat_elog_warn ("no free resassembly slot");
236  goto unlock;
237  }
238 
239  pool_get (srm->ip4_reass_pool, reass);
240  pool_get (srm->ip4_reass_lru_list_pool, elt);
241  reass->lru_list_index = elt_index = elt - srm->ip4_reass_lru_list_pool;
242  clib_dlist_init (srm->ip4_reass_lru_list_pool, elt_index);
243  elt->value = reass - srm->ip4_reass_pool;
245  srm->ip4_reass_head_index, elt_index);
246  pool_get (srm->ip4_frags_list_pool, per_reass_list_head_elt);
247  reass->frags_per_reass_list_head_index =
248  per_reass_list_head_elt - srm->ip4_frags_list_pool;
250  reass->frags_per_reass_list_head_index);
251  srm->ip4_reass_n++;
252  k.src.as_u32 = src.as_u32;
253  k.dst.as_u32 = dst.as_u32;
254  k.frag_id = frag_id;
255  k.proto = proto;
256  reass->key.as_u64[0] = kv.key[0] = k.as_u64[0];
257  reass->key.as_u64[1] = kv.key[1] = k.as_u64[1];
258  kv.value = reass - srm->ip4_reass_pool;
259  reass->sess_index = (u32) ~ 0;
260  reass->thread_index = (u32) ~ 0;
261  reass->last_heard = now;
262  reass->frag_n = 0;
263  reass->flags = 0;
264  reass->classify_next = NAT_REASS_IP4_CLASSIFY_NONE;
265  if (clib_bihash_add_del_16_8 (&srm->ip4_reass_hash, &kv, 1))
266  nat_elog_warn ("ip4_reass_hash add key failed");
267 
268 unlock:
270  return reass;
271 }
272 
273 nat_reass_ip4_t *
275  u16 frag_id, u8 proto, u8 reset_timeout,
276  u32 ** bi_to_drop)
277 {
279  nat_reass_ip4_t *reass = 0;
281  f64 now = vlib_time_now (srm->vlib_main);
282  dlist_elt_t *oldest_elt, *elt;
283  dlist_elt_t *per_reass_list_head_elt;
284  u32 oldest_index, elt_index;
286 
287  k.src.as_u32 = src.as_u32;
288  k.dst.as_u32 = dst.as_u32;
289  k.frag_id = frag_id;
290  k.proto = proto;
291 
293 
294  reass = nat_ip4_reass_lookup (&k, now);
295  if (reass)
296  {
297  if (reset_timeout)
298  {
299  reass->last_heard = now;
301  reass->lru_list_index);
304  reass->lru_list_index);
305  }
306 
307  if (reass->flags & NAT_REASS_FLAG_MAX_FRAG_DROP)
308  {
309  reass = 0;
310  goto unlock;
311  }
312 
313  goto unlock;
314  }
315 
316  if (srm->ip4_reass_n >= srm->ip4_max_reass)
317  {
318  oldest_index =
320  srm->ip4_reass_head_index);
321  ASSERT (oldest_index != ~0);
322  oldest_elt =
323  pool_elt_at_index (srm->ip4_reass_lru_list_pool, oldest_index);
324  reass = pool_elt_at_index (srm->ip4_reass_pool, oldest_elt->value);
325  if (now < reass->last_heard + (f64) srm->ip4_timeout)
326  {
328  srm->ip4_reass_head_index, oldest_index);
329  nat_elog_warn ("no free resassembly slot");
330  reass = 0;
331  goto unlock;
332  }
333 
335  srm->ip4_reass_head_index, oldest_index);
336 
337  kv.key[0] = reass->key.as_u64[0];
338  kv.key[1] = reass->key.as_u64[1];
339  if (!clib_bihash_search_16_8 (&srm->ip4_reass_hash, &kv, &value))
340  {
341  if (value.value == (reass - srm->ip4_reass_pool))
342  {
343  if (clib_bihash_add_del_16_8 (&srm->ip4_reass_hash, &kv, 0))
344  {
345  reass = 0;
346  goto unlock;
347  }
348  }
349  }
350 
351  nat_ip4_reass_get_frags_inline (reass, bi_to_drop);
352  }
353  else
354  {
355  pool_get (srm->ip4_reass_pool, reass);
356  pool_get (srm->ip4_reass_lru_list_pool, elt);
357  reass->lru_list_index = elt_index = elt - srm->ip4_reass_lru_list_pool;
358  clib_dlist_init (srm->ip4_reass_lru_list_pool, elt_index);
359  elt->value = reass - srm->ip4_reass_pool;
361  srm->ip4_reass_head_index, elt_index);
362  pool_get (srm->ip4_frags_list_pool, per_reass_list_head_elt);
363  reass->frags_per_reass_list_head_index =
364  per_reass_list_head_elt - srm->ip4_frags_list_pool;
366  reass->frags_per_reass_list_head_index);
367  srm->ip4_reass_n++;
368  }
369 
370  reass->key.as_u64[0] = kv.key[0] = k.as_u64[0];
371  reass->key.as_u64[1] = kv.key[1] = k.as_u64[1];
372  kv.value = reass - srm->ip4_reass_pool;
373  reass->sess_index = (u32) ~ 0;
374  reass->thread_index = (u32) ~ 0;
375  reass->last_heard = now;
376  reass->frag_n = 0;
377  reass->flags = 0;
378  reass->classify_next = NAT_REASS_IP4_CLASSIFY_NONE;
379 
380  if (clib_bihash_add_del_16_8 (&srm->ip4_reass_hash, &kv, 1))
381  {
382  reass = 0;
383  goto unlock;
384  }
385 
386 unlock:
388  return reass;
389 }
390 
391 int
392 nat_ip4_reass_add_fragment (u32 thread_index, nat_reass_ip4_t * reass,
393  u32 bi, u32 ** bi_to_drop)
394 {
396  dlist_elt_t *elt;
397  u32 elt_index;
398 
399  if (reass->frag_n >= srm->ip4_max_frag)
400  {
402  &reass->key.src);
403  reass->flags |= NAT_REASS_FLAG_MAX_FRAG_DROP;
404  nat_ip4_reass_get_frags_inline (reass, bi_to_drop);
405  return -1;
406  }
407 
409 
410  pool_get (srm->ip4_frags_list_pool, elt);
411  elt_index = elt - srm->ip4_frags_list_pool;
412  clib_dlist_init (srm->ip4_frags_list_pool, elt_index);
413  elt->value = bi;
415  reass->frags_per_reass_list_head_index, elt_index);
416  reass->frag_n++;
417 
419 
420  return 0;
421 }
422 
423 void
424 nat_ip4_reass_get_frags (nat_reass_ip4_t * reass, u32 ** bi)
425 {
427 
429 
430  nat_ip4_reass_get_frags_inline (reass, bi);
431 
433 }
434 
435 void
437 {
438  nat_reass_ip4_t *reass;
440  f64 now = vlib_time_now (srm->vlib_main);
441 
442  /* *INDENT-OFF* */
443  pool_foreach (reass, srm->ip4_reass_pool,
444  ({
445  if (now < reass->last_heard + (f64) srm->ip4_timeout)
446  {
447  if (fn (reass, ctx))
448  return;
449  }
450  }));
451  /* *INDENT-ON* */
452 }
453 
454 static_always_inline nat_reass_ip6_t *
456 {
459  nat_reass_ip6_t *reass;
460 
461  k->unused = 0;
462  kv.key[0] = k->as_u64[0];
463  kv.key[1] = k->as_u64[1];
464  kv.key[2] = k->as_u64[2];
465  kv.key[3] = k->as_u64[3];
466  kv.key[4] = k->as_u64[4];
467  kv.key[5] = k->as_u64[5];
468 
469  if (clib_bihash_search_48_8 (&srm->ip6_reass_hash, &kv, &value))
470  return 0;
471 
472  reass = pool_elt_at_index (srm->ip6_reass_pool, value.value);
473  if (now < reass->last_heard + (f64) srm->ip6_timeout)
474  return reass;
475 
476  return 0;
477 }
478 
479 nat_reass_ip6_t *
481  u32 frag_id, u8 proto, u8 reset_timeout,
482  u32 ** bi_to_drop)
483 {
485  nat_reass_ip6_t *reass = 0;
487  f64 now = vlib_time_now (srm->vlib_main);
488  dlist_elt_t *oldest_elt, *elt;
489  dlist_elt_t *per_reass_list_head_elt;
490  u32 oldest_index, elt_index;
492 
493  k.src.as_u64[0] = src.as_u64[0];
494  k.src.as_u64[1] = src.as_u64[1];
495  k.dst.as_u64[0] = dst.as_u64[0];
496  k.dst.as_u64[1] = dst.as_u64[1];
497  k.frag_id = frag_id;
498  k.proto = proto;
499  k.unused = 0;
500 
502 
503  reass = nat_ip6_reass_lookup (&k, now);
504  if (reass)
505  {
506  if (reset_timeout)
507  {
508  reass->last_heard = now;
510  reass->lru_list_index);
513  reass->lru_list_index);
514  }
515 
516  if (reass->flags & NAT_REASS_FLAG_MAX_FRAG_DROP)
517  {
518  reass = 0;
519  goto unlock;
520  }
521 
522  goto unlock;
523  }
524 
525  if (srm->ip6_reass_n >= srm->ip6_max_reass)
526  {
527  oldest_index =
529  srm->ip6_reass_head_index);
530  ASSERT (oldest_index != ~0);
531  oldest_elt =
532  pool_elt_at_index (srm->ip4_reass_lru_list_pool, oldest_index);
533  reass = pool_elt_at_index (srm->ip6_reass_pool, oldest_elt->value);
534  if (now < reass->last_heard + (f64) srm->ip6_timeout)
535  {
537  srm->ip6_reass_head_index, oldest_index);
538  nat_elog_warn ("no free resassembly slot");
539  reass = 0;
540  goto unlock;
541  }
542 
544  srm->ip6_reass_head_index, oldest_index);
545 
546  kv.key[0] = k.as_u64[0];
547  kv.key[1] = k.as_u64[1];
548  kv.key[2] = k.as_u64[2];
549  kv.key[3] = k.as_u64[3];
550  kv.key[4] = k.as_u64[4];
551  kv.key[5] = k.as_u64[5];
552  if (clib_bihash_add_del_48_8 (&srm->ip6_reass_hash, &kv, 0))
553  {
554  reass = 0;
555  goto unlock;
556  }
557 
558  nat_ip6_reass_get_frags_inline (reass, bi_to_drop);
559  }
560  else
561  {
562  pool_get (srm->ip6_reass_pool, reass);
563  pool_get (srm->ip6_reass_lru_list_pool, elt);
564  reass->lru_list_index = elt_index = elt - srm->ip6_reass_lru_list_pool;
565  clib_dlist_init (srm->ip6_reass_lru_list_pool, elt_index);
566  elt->value = reass - srm->ip6_reass_pool;
568  srm->ip6_reass_head_index, elt_index);
569  pool_get (srm->ip6_frags_list_pool, per_reass_list_head_elt);
570  reass->frags_per_reass_list_head_index =
571  per_reass_list_head_elt - srm->ip6_frags_list_pool;
573  reass->frags_per_reass_list_head_index);
574  srm->ip6_reass_n++;
575  }
576 
577  reass->key.as_u64[0] = kv.key[0] = k.as_u64[0];
578  reass->key.as_u64[1] = kv.key[1] = k.as_u64[1];
579  reass->key.as_u64[2] = kv.key[2] = k.as_u64[2];
580  reass->key.as_u64[3] = kv.key[3] = k.as_u64[3];
581  reass->key.as_u64[4] = kv.key[4] = k.as_u64[4];
582  reass->key.as_u64[5] = kv.key[5] = k.as_u64[5];
583  kv.value = reass - srm->ip6_reass_pool;
584  reass->sess_index = (u32) ~ 0;
585  reass->last_heard = now;
586 
587  if (clib_bihash_add_del_48_8 (&srm->ip6_reass_hash, &kv, 1))
588  {
589  reass = 0;
590  goto unlock;
591  }
592 
593 unlock:
595  return reass;
596 }
597 
598 int
599 nat_ip6_reass_add_fragment (u32 thread_index, nat_reass_ip6_t * reass,
600  u32 bi, u32 ** bi_to_drop)
601 {
603  dlist_elt_t *elt;
604  u32 elt_index;
605 
606  if (reass->frag_n >= srm->ip6_max_frag)
607  {
609  &reass->key.src);
610  reass->flags |= NAT_REASS_FLAG_MAX_FRAG_DROP;
611  nat_ip6_reass_get_frags_inline (reass, bi_to_drop);
612  return -1;
613  }
614 
616 
617  pool_get (srm->ip6_frags_list_pool, elt);
618  elt_index = elt - srm->ip6_frags_list_pool;
619  clib_dlist_init (srm->ip6_frags_list_pool, elt_index);
620  elt->value = bi;
622  reass->frags_per_reass_list_head_index, elt_index);
623  reass->frag_n++;
624 
626 
627  return 0;
628 }
629 
630 void
631 nat_ip6_reass_get_frags (nat_reass_ip6_t * reass, u32 ** bi)
632 {
634 
636 
637  nat_ip6_reass_get_frags_inline (reass, bi);
638 
640 }
641 
642 void
644 {
645  nat_reass_ip6_t *reass;
647  f64 now = vlib_time_now (srm->vlib_main);
648 
649  /* *INDENT-OFF* */
650  pool_foreach (reass, srm->ip6_reass_pool,
651  ({
652  if (now < reass->last_heard + (f64) srm->ip4_timeout)
653  {
654  if (fn (reass, ctx))
655  return;
656  }
657  }));
658  /* *INDENT-ON* */
659 }
660 
661 clib_error_t *
663 {
666  clib_error_t *error = 0;
667  dlist_elt_t *head;
668  u32 nbuckets, head_index;
669 
670  srm->vlib_main = vm;
671  srm->vnet_main = vnet_get_main ();
672 
673  /* IPv4 */
677  srm->ip4_drop_frag = 0;
678  srm->ip4_reass_n = 0;
679 
680  if (tm->n_vlib_mains > 1)
682 
684 
685  nbuckets = nat_reass_get_nbuckets (0);
686  clib_bihash_init_16_8 (&srm->ip4_reass_hash, "nat-ip4-reass", nbuckets,
687  nbuckets * 1024);
688 
689  pool_get (srm->ip4_reass_lru_list_pool, head);
690  srm->ip4_reass_head_index = head_index =
691  head - srm->ip4_reass_lru_list_pool;
692  clib_dlist_init (srm->ip4_reass_lru_list_pool, head_index);
693 
694  /* IPv6 */
698  srm->ip6_drop_frag = 0;
699  srm->ip6_reass_n = 0;
700 
701  if (tm->n_vlib_mains > 1)
703 
705 
706  nbuckets = nat_reass_get_nbuckets (1);
707  clib_bihash_init_48_8 (&srm->ip6_reass_hash, "nat-ip6-reass", nbuckets,
708  nbuckets * 1024);
709 
710  pool_get (srm->ip6_reass_lru_list_pool, head);
711  srm->ip6_reass_head_index = head_index =
712  head - srm->ip6_reass_lru_list_pool;
713  clib_dlist_init (srm->ip6_reass_lru_list_pool, head_index);
714 
715  return error;
716 }
717 
718 static clib_error_t *
720  vlib_cli_command_t * cmd)
721 {
722  clib_error_t *error = 0;
723  unformat_input_t _line_input, *line_input = &_line_input;
724  u32 timeout = 0, max_reass = 0, max_frag = 0;
725  u8 drop_frag = (u8) ~ 0, is_ip6 = 0;
726  int rv;
727 
728  /* Get a line of input. */
729  if (!unformat_user (input, unformat_line_input, line_input))
730  return 0;
731 
732  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
733  {
734  if (unformat (line_input, "max-reassemblies %u", &max_reass))
735  ;
736  else if (unformat (line_input, "max-fragments %u", &max_frag))
737  ;
738  else if (unformat (line_input, "timeout %u", &timeout))
739  ;
740  else if (unformat (line_input, "enable"))
741  drop_frag = 0;
742  else if (unformat (line_input, "disable"))
743  drop_frag = 1;
744  else if (unformat (line_input, "ip4"))
745  is_ip6 = 0;
746  else if (unformat (line_input, "ip6"))
747  is_ip6 = 1;
748  else
749  {
750  error = clib_error_return (0, "unknown input '%U'",
751  format_unformat_error, line_input);
752  goto done;
753  }
754  }
755 
756  if (!timeout)
757  timeout = nat_reass_get_timeout (is_ip6);
758  if (!max_reass)
759  max_reass = nat_reass_get_max_reass (is_ip6);
760  if (!max_frag)
761  max_frag = nat_reass_get_max_frag (is_ip6);
762  if (drop_frag == (u8) ~ 0)
763  drop_frag = nat_reass_is_drop_frag (is_ip6);
764 
765  rv =
766  nat_reass_set (timeout, (u16) max_reass, (u8) max_frag, drop_frag,
767  is_ip6);
768  if (rv)
769  {
770  error = clib_error_return (0, "nat_set_reass return %d", rv);
771  goto done;
772  }
773 
774 done:
775  unformat_free (line_input);
776 
777  return error;
778 }
779 
780 static int
781 nat_ip4_reass_walk_cli (nat_reass_ip4_t * reass, void *ctx)
782 {
783  vlib_main_t *vm = ctx;
784  u8 *flags_str = 0;
785  const char *classify_next_str;
786 
787  if (reass->flags & NAT_REASS_FLAG_MAX_FRAG_DROP)
788  flags_str = format (flags_str, "MAX_FRAG_DROP");
789  if (reass->flags & NAT_REASS_FLAG_CLASSIFY_ED_CONTINUE)
790  {
791  if (flags_str)
792  flags_str = format (flags_str, " | ");
793  flags_str = format (flags_str, "CLASSIFY_ED_CONTINUE");
794  }
795  if (reass->flags & NAT_REASS_FLAG_ED_DONT_TRANSLATE)
796  {
797  if (flags_str)
798  flags_str = format (flags_str, " | ");
799  flags_str = format (flags_str, "CLASSIFY_ED_DONT_TRANSLATE");
800  }
801  if (!flags_str)
802  flags_str = format (flags_str, "0");
803  flags_str = format (flags_str, "%c", 0);
804 
805  switch (reass->classify_next)
806  {
808  classify_next_str = "NONE";
809  break;
811  classify_next_str = "IN2OUT";
812  break;
814  classify_next_str = "OUT2IN";
815  break;
816  default:
817  classify_next_str = "invalid value";
818  }
819 
820  vlib_cli_output (vm, " src %U dst %U proto %u id 0x%04x cached %u "
821  "flags %s classify_next %s",
822  format_ip4_address, &reass->key.src,
823  format_ip4_address, &reass->key.dst,
824  reass->key.proto,
825  clib_net_to_host_u16 (reass->key.frag_id), reass->frag_n,
826  flags_str, classify_next_str);
827 
828  vec_free (flags_str);
829 
830  return 0;
831 }
832 
833 static int
834 nat_ip6_reass_walk_cli (nat_reass_ip6_t * reass, void *ctx)
835 {
836  vlib_main_t *vm = ctx;
837 
838  vlib_cli_output (vm, " src %U dst %U proto %u id 0x%08x cached %u",
839  format_ip6_address, &reass->key.src,
840  format_ip6_address, &reass->key.dst,
841  reass->key.proto,
842  clib_net_to_host_u32 (reass->key.frag_id), reass->frag_n);
843 
844  return 0;
845 }
846 
847 static clib_error_t *
849  vlib_cli_command_t * cmd)
850 {
851  vlib_cli_output (vm, "NAT IPv4 virtual fragmentation reassembly is %s",
852  nat_reass_is_drop_frag (0) ? "DISABLED" : "ENABLED");
853  vlib_cli_output (vm, " max-reassemblies %u", nat_reass_get_max_reass (0));
854  vlib_cli_output (vm, " max-fragments %u", nat_reass_get_max_frag (0));
855  vlib_cli_output (vm, " timeout %usec", nat_reass_get_timeout (0));
856  vlib_cli_output (vm, " reassemblies:");
858 
859  vlib_cli_output (vm, "NAT IPv6 virtual fragmentation reassembly is %s",
860  nat_reass_is_drop_frag (1) ? "DISABLED" : "ENABLED");
861  vlib_cli_output (vm, " max-reassemblies %u", nat_reass_get_max_reass (1));
862  vlib_cli_output (vm, " max-fragments %u", nat_reass_get_max_frag (1));
863  vlib_cli_output (vm, " timeout %usec", nat_reass_get_timeout (1));
864  vlib_cli_output (vm, " reassemblies:");
866 
867  return 0;
868 }
869 
870 /* *INDENT-OFF* */
871 VLIB_CLI_COMMAND (nat_reass_command, static) =
872 {
873  .path = "nat virtual-reassembly",
874  .short_help = "nat virtual-reassembly ip4|ip6 [max-reassemblies <n>] "
875  "[max-fragments <n>] [timeout <sec>] [enable|disable]",
876  .function = nat_reass_command_fn,
877 };
878 
879 VLIB_CLI_COMMAND (show_nat_reass_command, static) =
880 {
881  .path = "show nat virtual-reassembly",
882  .short_help = "show nat virtual-reassembly",
883  .function = show_nat_reass_command_fn,
884 };
885 /* *INDENT-ON* */
886 
887 /*
888  * fd.io coding-style-patch-verification: ON
889  *
890  * Local Variables:
891  * eval: (c-set-style "gnu")
892  * End:
893  */
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
int nat_ip4_reass_add_fragment(u32 thread_index, nat_reass_ip4_t *reass, u32 bi, u32 **bi_to_drop)
Cache fragment.
Definition: nat_reass.c:392
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:46
clib_error_t * nat_reass_init(vlib_main_t *vm)
Initialize NAT virtual fragmentation reassembly.
Definition: nat_reass.c:662
#define pool_alloc(P, N)
Allocate N more free elements to pool (unspecified alignment).
Definition: pool.h:341
u64 as_u64[2]
Definition: ip6_packet.h:51
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:258
static int nat_ip6_reass_walk_cli(nat_reass_ip6_t *reass, void *ctx)
Definition: nat_reass.c:834
void nat_ip6_reass_get_frags(nat_reass_ip6_t *reass, u32 **bi)
Get cached fragments.
Definition: nat_reass.c:631
static_always_inline void clib_spinlock_unlock_if_init(clib_spinlock_t *p)
Definition: lock.h:108
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:522
vl_api_address_t src
Definition: gre.api:51
int i
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
#define nat_elog_warn(nat_elog_str)
Definition: nat.h:965
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
int nat_ip6_reass_add_fragment(u32 thread_index, nat_reass_ip6_t *reass, u32 bi, u32 **bi_to_drop)
Cache fragment.
Definition: nat_reass.c:599
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:322
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:236
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:436
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:719
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:99
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:493
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
void nat_ipfix_logging_max_fragments_ip4(u32 thread_index, u32 limit, ip4_address_t *src)
Generate maximum IPv4 fragments pending reassembly exceeded event.
#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:283
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:61
#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:514
static int nat_ip4_reass_walk_cli(nat_reass_ip4_t *reass, void *ctx)
Definition: nat_reass.c:781
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
void nat_ipfix_logging_max_fragments_ip6(u32 thread_index, u32 limit, ip6_address_t *src)
Generate maximum IPv6 fragments pending reassembly exceeded event.
#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:848
vl_api_address_t dst
Definition: gre.api:52
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:271
#define pool_free(p)
Free a pool.
Definition: pool.h:407
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:145
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:312
static u32 nat_reass_get_nbuckets(u8 is_ip6)
Definition: nat_reass.c:27
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
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
u8 value
Definition: qos.api:53
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:311
#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:455
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:480
static void unformat_free(unformat_input_t *i)
Definition: format.h:163
void nat_ip6_reass_walk(nat_ip6_reass_walk_fn_t fn, void *ctx)
Walk IPv6 reassemblies.
Definition: nat_reass.c:643
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:274
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
#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:424
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:768
static_always_inline void clib_spinlock_lock_if_init(clib_spinlock_t *p)
Definition: lock.h:93
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
clib_spinlock_t ip4_reass_lock
Definition: nat_reass.h:127
vl_api_fib_path_nh_proto_t proto
Definition: fib_types.api:125
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
nat_reass_ip4_t * nat_ip4_reass_create(ip4_address_t src, ip4_address_t dst, u16 frag_id, u8 proto)
Create reassembly.
Definition: nat_reass.c:220
static u32 clib_dlist_remove_head(dlist_elt_t *pool, u32 head_index)
Definition: dlist.h:117