FD.io VPP  v19.04-6-g6f05f72
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  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_log_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_log_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;
285  clib_bihash_kv_16_8_t kv, value;
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_log_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 {
458  clib_bihash_kv_48_8_t kv, value;
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_log_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[4];
550  kv.key[4] = k.as_u64[5];
551  if (clib_bihash_add_del_48_8 (&srm->ip6_reass_hash, &kv, 0))
552  {
553  reass = 0;
554  goto unlock;
555  }
556 
557  nat_ip6_reass_get_frags_inline (reass, bi_to_drop);
558  }
559  else
560  {
561  pool_get (srm->ip6_reass_pool, reass);
562  pool_get (srm->ip6_reass_lru_list_pool, elt);
563  reass->lru_list_index = elt_index = elt - srm->ip6_reass_lru_list_pool;
564  clib_dlist_init (srm->ip6_reass_lru_list_pool, elt_index);
565  elt->value = reass - srm->ip6_reass_pool;
567  srm->ip6_reass_head_index, elt_index);
568  pool_get (srm->ip6_frags_list_pool, per_reass_list_head_elt);
569  reass->frags_per_reass_list_head_index =
570  per_reass_list_head_elt - srm->ip6_frags_list_pool;
572  reass->frags_per_reass_list_head_index);
573  srm->ip6_reass_n++;
574  }
575 
576  reass->key.as_u64[0] = kv.key[0] = k.as_u64[0];
577  reass->key.as_u64[1] = kv.key[1] = k.as_u64[1];
578  reass->key.as_u64[2] = kv.key[2] = k.as_u64[2];
579  reass->key.as_u64[3] = kv.key[3] = k.as_u64[3];
580  reass->key.as_u64[4] = kv.key[4] = k.as_u64[4];
581  reass->key.as_u64[5] = kv.key[5] = k.as_u64[5];
582  kv.value = reass - srm->ip6_reass_pool;
583  reass->sess_index = (u32) ~ 0;
584  reass->last_heard = now;
585 
586  if (clib_bihash_add_del_48_8 (&srm->ip6_reass_hash, &kv, 1))
587  {
588  reass = 0;
589  goto unlock;
590  }
591 
592 unlock:
594  return reass;
595 }
596 
597 int
598 nat_ip6_reass_add_fragment (u32 thread_index, nat_reass_ip6_t * reass,
599  u32 bi, u32 ** bi_to_drop)
600 {
602  dlist_elt_t *elt;
603  u32 elt_index;
604 
605  if (reass->frag_n >= srm->ip6_max_frag)
606  {
608  &reass->key.src);
609  reass->flags |= NAT_REASS_FLAG_MAX_FRAG_DROP;
610  nat_ip6_reass_get_frags_inline (reass, bi_to_drop);
611  return -1;
612  }
613 
615 
616  pool_get (srm->ip6_frags_list_pool, elt);
617  elt_index = elt - srm->ip6_frags_list_pool;
618  clib_dlist_init (srm->ip6_frags_list_pool, elt_index);
619  elt->value = bi;
621  reass->frags_per_reass_list_head_index, elt_index);
622  reass->frag_n++;
623 
625 
626  return 0;
627 }
628 
629 void
630 nat_ip6_reass_get_frags (nat_reass_ip6_t * reass, u32 ** bi)
631 {
633 
635 
636  nat_ip6_reass_get_frags_inline (reass, bi);
637 
639 }
640 
641 void
643 {
644  nat_reass_ip6_t *reass;
646  f64 now = vlib_time_now (srm->vlib_main);
647 
648  /* *INDENT-OFF* */
649  pool_foreach (reass, srm->ip6_reass_pool,
650  ({
651  if (now < reass->last_heard + (f64) srm->ip4_timeout)
652  {
653  if (fn (reass, ctx))
654  return;
655  }
656  }));
657  /* *INDENT-ON* */
658 }
659 
660 clib_error_t *
662 {
665  clib_error_t *error = 0;
666  dlist_elt_t *head;
667  u32 nbuckets, head_index;
668 
669  srm->vlib_main = vm;
670  srm->vnet_main = vnet_get_main ();
671 
672  /* IPv4 */
676  srm->ip4_drop_frag = 0;
677  srm->ip4_reass_n = 0;
678 
679  if (tm->n_vlib_mains > 1)
681 
683 
684  nbuckets = nat_reass_get_nbuckets (0);
685  clib_bihash_init_16_8 (&srm->ip4_reass_hash, "nat-ip4-reass", nbuckets,
686  nbuckets * 1024);
687 
688  pool_get (srm->ip4_reass_lru_list_pool, head);
689  srm->ip4_reass_head_index = head_index =
690  head - srm->ip4_reass_lru_list_pool;
691  clib_dlist_init (srm->ip4_reass_lru_list_pool, head_index);
692 
693  /* IPv6 */
697  srm->ip6_drop_frag = 0;
698  srm->ip6_reass_n = 0;
699 
700  if (tm->n_vlib_mains > 1)
702 
704 
705  nbuckets = nat_reass_get_nbuckets (1);
706  clib_bihash_init_48_8 (&srm->ip6_reass_hash, "nat-ip6-reass", nbuckets,
707  nbuckets * 1024);
708 
709  pool_get (srm->ip6_reass_lru_list_pool, head);
710  srm->ip6_reass_head_index = head_index =
711  head - srm->ip6_reass_lru_list_pool;
712  clib_dlist_init (srm->ip6_reass_lru_list_pool, head_index);
713 
714  return error;
715 }
716 
717 static clib_error_t *
719  vlib_cli_command_t * cmd)
720 {
721  clib_error_t *error = 0;
722  unformat_input_t _line_input, *line_input = &_line_input;
723  u32 timeout = 0, max_reass = 0, max_frag = 0;
724  u8 drop_frag = (u8) ~ 0, is_ip6 = 0;
725  int rv;
726 
727  /* Get a line of input. */
728  if (!unformat_user (input, unformat_line_input, line_input))
729  return 0;
730 
731  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
732  {
733  if (unformat (line_input, "max-reassemblies %u", &max_reass))
734  ;
735  else if (unformat (line_input, "max-fragments %u", &max_frag))
736  ;
737  else if (unformat (line_input, "timeout %u", &timeout))
738  ;
739  else if (unformat (line_input, "enable"))
740  drop_frag = 0;
741  else if (unformat (line_input, "disable"))
742  drop_frag = 1;
743  else if (unformat (line_input, "ip4"))
744  is_ip6 = 0;
745  else if (unformat (line_input, "ip6"))
746  is_ip6 = 1;
747  else
748  {
749  error = clib_error_return (0, "unknown input '%U'",
750  format_unformat_error, line_input);
751  goto done;
752  }
753  }
754 
755  if (!timeout)
756  timeout = nat_reass_get_timeout (is_ip6);
757  if (!max_reass)
758  max_reass = nat_reass_get_max_reass (is_ip6);
759  if (!max_frag)
760  max_frag = nat_reass_get_max_frag (is_ip6);
761  if (drop_frag == (u8) ~ 0)
762  drop_frag = nat_reass_is_drop_frag (is_ip6);
763 
764  rv =
765  nat_reass_set (timeout, (u16) max_reass, (u8) max_frag, drop_frag,
766  is_ip6);
767  if (rv)
768  {
769  error = clib_error_return (0, "nat_set_reass return %d", rv);
770  goto done;
771  }
772 
773 done:
774  unformat_free (line_input);
775 
776  return error;
777 }
778 
779 static int
780 nat_ip4_reass_walk_cli (nat_reass_ip4_t * reass, void *ctx)
781 {
782  vlib_main_t *vm = ctx;
783  u8 *flags_str = 0;
784  const char *classify_next_str;
785 
786  if (reass->flags & NAT_REASS_FLAG_MAX_FRAG_DROP)
787  flags_str = format (flags_str, "MAX_FRAG_DROP");
788  if (reass->flags & NAT_REASS_FLAG_CLASSIFY_ED_CONTINUE)
789  {
790  if (flags_str)
791  flags_str = format (flags_str, " | ");
792  flags_str = format (flags_str, "CLASSIFY_ED_CONTINUE");
793  }
794  if (reass->flags & NAT_REASS_FLAG_ED_DONT_TRANSLATE)
795  {
796  if (flags_str)
797  flags_str = format (flags_str, " | ");
798  flags_str = format (flags_str, "CLASSIFY_ED_DONT_TRANSLATE");
799  }
800  if (!flags_str)
801  flags_str = format (flags_str, "0");
802  flags_str = format (flags_str, "%c", 0);
803 
804  switch (reass->classify_next)
805  {
807  classify_next_str = "NONE";
808  break;
810  classify_next_str = "IN2OUT";
811  break;
813  classify_next_str = "OUT2IN";
814  break;
815  default:
816  classify_next_str = "invalid value";
817  }
818 
819  vlib_cli_output (vm, " src %U dst %U proto %u id 0x%04x cached %u "
820  "flags %s classify_next %s",
821  format_ip4_address, &reass->key.src,
822  format_ip4_address, &reass->key.dst,
823  reass->key.proto,
824  clib_net_to_host_u16 (reass->key.frag_id), reass->frag_n,
825  flags_str, classify_next_str);
826 
827  vec_free (flags_str);
828 
829  return 0;
830 }
831 
832 static int
833 nat_ip6_reass_walk_cli (nat_reass_ip6_t * reass, void *ctx)
834 {
835  vlib_main_t *vm = ctx;
836 
837  vlib_cli_output (vm, " src %U dst %U proto %u id 0x%08x cached %u",
838  format_ip6_address, &reass->key.src,
839  format_ip6_address, &reass->key.dst,
840  reass->key.proto,
841  clib_net_to_host_u32 (reass->key.frag_id), reass->frag_n);
842 
843  return 0;
844 }
845 
846 static clib_error_t *
848  vlib_cli_command_t * cmd)
849 {
850  vlib_cli_output (vm, "NAT IPv4 virtual fragmentation reassembly is %s",
851  nat_reass_is_drop_frag (0) ? "DISABLED" : "ENABLED");
852  vlib_cli_output (vm, " max-reassemblies %u", nat_reass_get_max_reass (0));
853  vlib_cli_output (vm, " max-fragments %u", nat_reass_get_max_frag (0));
854  vlib_cli_output (vm, " timeout %usec", nat_reass_get_timeout (0));
855  vlib_cli_output (vm, " reassemblies:");
857 
858  vlib_cli_output (vm, "NAT IPv6 virtual fragmentation reassembly is %s",
859  nat_reass_is_drop_frag (1) ? "DISABLED" : "ENABLED");
860  vlib_cli_output (vm, " max-reassemblies %u", nat_reass_get_max_reass (1));
861  vlib_cli_output (vm, " max-fragments %u", nat_reass_get_max_frag (1));
862  vlib_cli_output (vm, " timeout %usec", nat_reass_get_timeout (1));
863  vlib_cli_output (vm, " reassemblies:");
865 
866  return 0;
867 }
868 
869 /* *INDENT-OFF* */
870 VLIB_CLI_COMMAND (nat_reass_command, static) =
871 {
872  .path = "nat virtual-reassembly",
873  .short_help = "nat virtual-reassembly ip4|ip6 [max-reassemblies <n>] "
874  "[max-fragments <n>] [timeout <sec>] [enable|disable]",
875  .function = nat_reass_command_fn,
876 };
877 
878 VLIB_CLI_COMMAND (show_nat_reass_command, static) =
879 {
880  .path = "show nat virtual-reassembly",
881  .short_help = "show nat virtual-reassembly",
882  .function = show_nat_reass_command_fn,
883 };
884 /* *INDENT-ON* */
885 
886 /*
887  * fd.io coding-style-patch-verification: ON
888  *
889  * Local Variables:
890  * eval: (c-set-style "gnu")
891  * End:
892  */
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:47
clib_error_t * nat_reass_init(vlib_main_t *vm)
Initialize NAT virtual fragmentation reassembly.
Definition: nat_reass.c:661
#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:255
static int nat_ip6_reass_walk_cli(nat_reass_ip6_t *reass, void *ctx)
Definition: nat_reass.c:833
void nat_ip6_reass_get_frags(nat_reass_ip6_t *reass, u32 **bi)
Get cached fragments.
Definition: nat_reass.c:630
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:522
#define nat_log_warn(...)
Definition: nat.h:720
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:424
vl_api_ip4_address_t dst
Definition: ipsec_gre.api:39
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:598
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:718
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: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:514
static int nat_ip4_reass_walk_cli(nat_reass_ip4_t *reass, void *ctx)
Definition: nat_reass.c:780
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:847
vl_api_ip4_address_t src
Definition: ipsec_gre.api:38
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: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: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
#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:162
void nat_ip6_reass_walk(nat_ip6_reass_walk_fn_t fn, void *ctx)
Walk IPv6 reassemblies.
Definition: nat_reass.c:642
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: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
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