FD.io VPP  v17.10-9-gd594711
Vector Packet Processing
nat64.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 NAT64 implementation
18  */
19 
20 #include <nat/nat64.h>
21 #include <nat/nat64_db.h>
22 #include <vnet/fib/ip4_fib.h>
23 
24 
26 
27 /* *INDENT-OFF* */
28 
29 /* Hook up input features */
30 VNET_FEATURE_INIT (nat64_in2out, static) = {
31  .arc_name = "ip6-unicast",
32  .node_name = "nat64-in2out",
33  .runs_before = VNET_FEATURES ("ip6-lookup"),
34 };
35 VNET_FEATURE_INIT (nat64_out2in, static) = {
36  .arc_name = "ip4-unicast",
37  .node_name = "nat64-out2in",
38  .runs_before = VNET_FEATURES ("ip4-lookup"),
39 };
40 
41 static u8 well_known_prefix[] = {
42  0x00, 0x64, 0xff, 0x9b,
43  0x00, 0x00, 0x00, 0x00,
44  0x00, 0x00, 0x00, 0x00,
45  0x00, 0x00, 0x00, 0x00
46 };
47 
48 /* *INDENT-ON* */
49 
52 {
53  nat64_main_t *nm = &nat64_main;
54  clib_error_t *error = 0;
56 
57  nm->is_disabled = 0;
58 
59  if (tm->n_vlib_mains > 1)
60  {
61  nm->is_disabled = 1;
62  goto error;
63  }
64 
65  if (nat64_db_init (&nm->db))
66  {
67  error = clib_error_return (0, "NAT64 DB init failed");
68  goto error;
69  }
70 
71  /* set session timeouts to default values */
77 
78 error:
79  return error;
80 }
81 
82 int
84 {
85  nat64_main_t *nm = &nat64_main;
86  snat_address_t *a = 0;
87  snat_interface_t *interface;
88  int i;
89 
90  /* Check if address already exists */
91  for (i = 0; i < vec_len (nm->addr_pool); i++)
92  {
93  if (nm->addr_pool[i].addr.as_u32 == addr->as_u32)
94  {
95  a = nm->addr_pool + i;
96  break;
97  }
98  }
99 
100  if (is_add)
101  {
102  if (a)
103  return VNET_API_ERROR_VALUE_EXIST;
104 
105  vec_add2 (nm->addr_pool, a, 1);
106  a->addr = *addr;
107  a->fib_index = 0;
108  if (vrf_id != ~0)
109  a->fib_index =
112 #define _(N, i, n, s) \
113  clib_bitmap_alloc (a->busy_##n##_port_bitmap, 65535);
115 #undef _
116  }
117  else
118  {
119  if (!a)
120  return VNET_API_ERROR_NO_SUCH_ENTRY;
121 
122  if (a->fib_index)
125 
126 #define _(N, id, n, s) \
127  clib_bitmap_free (a->busy_##n##_port_bitmap);
129 #undef _
130  /* Delete sessions using address */
131  nat64_db_free_out_addr (&nm->db, &a->addr);
132  vec_del1 (nm->addr_pool, i);
133  }
134 
135  /* Add/del external address to FIB */
136  /* *INDENT-OFF* */
137  pool_foreach (interface, nm->interfaces,
138  ({
139  if (interface->is_inside)
140  continue;
141 
142  snat_add_del_addr_to_fib (addr, 32, interface->sw_if_index, is_add);
143  break;
144  }));
145  /* *INDENT-ON* */
146 
147  return 0;
148 }
149 
150 void
152 {
153  nat64_main_t *nm = &nat64_main;
154  snat_address_t *a = 0;
155 
156  /* *INDENT-OFF* */
157  vec_foreach (a, nm->addr_pool)
158  {
159  if (fn (a, ctx))
160  break;
161  };
162  /* *INDENT-ON* */
163 }
164 
165 int
166 nat64_add_del_interface (u32 sw_if_index, u8 is_inside, u8 is_add)
167 {
168  nat64_main_t *nm = &nat64_main;
169  snat_interface_t *interface = 0, *i;
170  snat_address_t *ap;
171  const char *feature_name, *arc_name;
172 
173  /* Check if address already exists */
174  /* *INDENT-OFF* */
175  pool_foreach (i, nm->interfaces,
176  ({
177  if (i->sw_if_index == sw_if_index)
178  {
179  interface = i;
180  break;
181  }
182  }));
183  /* *INDENT-ON* */
184 
185  if (is_add)
186  {
187  if (interface)
188  return VNET_API_ERROR_VALUE_EXIST;
189 
190  pool_get (nm->interfaces, interface);
191  interface->sw_if_index = sw_if_index;
192  interface->is_inside = is_inside;
193 
194  }
195  else
196  {
197  if (!interface)
198  return VNET_API_ERROR_NO_SUCH_ENTRY;
199 
200  pool_put (nm->interfaces, interface);
201  }
202 
203  if (!is_inside)
204  {
205  /* *INDENT-OFF* */
206  vec_foreach (ap, nm->addr_pool)
207  snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, is_add);
208  /* *INDENT-ON* */
209  }
210 
211  arc_name = is_inside ? "ip6-unicast" : "ip4-unicast";
212  feature_name = is_inside ? "nat64-in2out" : "nat64-out2in";
213 
214  return vnet_feature_enable_disable (arc_name, feature_name, sw_if_index,
215  is_add, 0, 0);
216 }
217 
218 void
220 {
221  nat64_main_t *nm = &nat64_main;
222  snat_interface_t *i = 0;
223 
224  /* *INDENT-OFF* */
225  pool_foreach (i, nm->interfaces,
226  ({
227  if (fn (i, ctx))
228  break;
229  }));
230  /* *INDENT-ON* */
231 }
232 
233 int
235  ip4_address_t * addr, u16 * port)
236 {
237  nat64_main_t *nm = &nat64_main;
238  snat_main_t *sm = &snat_main;
239  int i;
240  snat_address_t *a, *ga = 0;
241  u32 portnum;
242 
243  for (i = 0; i < vec_len (nm->addr_pool); i++)
244  {
245  a = nm->addr_pool + i;
246  switch (proto)
247  {
248 #define _(N, j, n, s) \
249  case SNAT_PROTOCOL_##N: \
250  if (a->busy_##n##_ports < (65535-1024)) \
251  { \
252  if (a->fib_index == fib_index) \
253  { \
254  while (1) \
255  { \
256  portnum = random_u32 (&sm->random_seed); \
257  portnum &= 0xFFFF; \
258  if (portnum < 1024) \
259  continue; \
260  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
261  portnum)) \
262  continue; \
263  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
264  portnum, 1); \
265  a->busy_##n##_ports++; \
266  *port = portnum; \
267  addr->as_u32 = a->addr.as_u32; \
268  return 0; \
269  } \
270  } \
271  else if (a->fib_index == 0) \
272  ga = a; \
273  } \
274  break;
276 #undef _
277  default:
278  clib_warning ("unknown protocol");
279  return 1;
280  }
281  }
282 
283  if (ga)
284  {
285  switch (proto)
286  {
287 #define _(N, j, n, s) \
288  case SNAT_PROTOCOL_##N: \
289  while (1) \
290  { \
291  portnum = random_u32 (&sm->random_seed); \
292  portnum &= 0xFFFF; \
293  if (portnum < 1024) \
294  continue; \
295  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
296  portnum)) \
297  continue; \
298  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
299  portnum, 1); \
300  a->busy_##n##_ports++; \
301  *port = portnum; \
302  addr->as_u32 = a->addr.as_u32; \
303  return 0; \
304  }
305  break;
307 #undef _
308  default:
309  clib_warning ("unknown protocol");
310  return 1;
311  }
312  }
313 
314  /* Totally out of translations to use... */
315  //TODO: IPFix
316  return 1;
317 }
318 
319 void
321  snat_protocol_t proto)
322 {
323  nat64_main_t *nm = &nat64_main;
324  int i;
325  snat_address_t *a;
326 
327  for (i = 0; i < vec_len (nm->addr_pool); i++)
328  {
329  a = nm->addr_pool + i;
330  if (addr->as_u32 != a->addr.as_u32)
331  continue;
332  switch (proto)
333  {
334 #define _(N, j, n, s) \
335  case SNAT_PROTOCOL_##N: \
336  ASSERT (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
337  port) == 1); \
338  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, port, 0); \
339  a->busy_##n##_ports--; \
340  break;
342 #undef _
343  default:
344  clib_warning ("unknown protocol");
345  return;
346  }
347  break;
348  }
349 }
350 
351 int
353  ip4_address_t * out_addr, u16 in_port,
354  u16 out_port, u8 proto, u32 vrf_id, u8 is_add)
355 {
356  nat64_main_t *nm = &nat64_main;
357  nat64_db_bib_entry_t *bibe;
361  ip46_address_t addr;
362  int i;
363  snat_address_t *a;
364 
365  addr.as_u64[0] = in_addr->as_u64[0];
366  addr.as_u64[1] = in_addr->as_u64[1];
367  bibe =
368  nat64_db_bib_entry_find (&nm->db, &addr, clib_host_to_net_u16 (in_port),
369  proto, fib_index, 1);
370 
371  if (is_add)
372  {
373  if (bibe)
374  return VNET_API_ERROR_VALUE_EXIST;
375 
376  for (i = 0; i < vec_len (nm->addr_pool); i++)
377  {
378  a = nm->addr_pool + i;
379  if (out_addr->as_u32 != a->addr.as_u32)
380  continue;
381  switch (p)
382  {
383 #define _(N, j, n, s) \
384  case SNAT_PROTOCOL_##N: \
385  if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
386  out_port)) \
387  return VNET_API_ERROR_INVALID_VALUE; \
388  clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
389  out_port, 1); \
390  if (out_port > 1024) \
391  a->busy_##n##_ports++; \
392  break;
394 #undef _
395  default:
396  memset (&addr, 0, sizeof (addr));
397  addr.ip4.as_u32 = out_addr->as_u32;
399  (&nm->db, &addr, 0, proto, fib_index, 0))
400  return VNET_API_ERROR_INVALID_VALUE;
401  }
402  break;
403  }
404  bibe =
405  nat64_db_bib_entry_create (&nm->db, in_addr, out_addr,
406  clib_host_to_net_u16 (in_port),
407  clib_host_to_net_u16 (out_port), fib_index,
408  proto, 1);
409  if (!bibe)
410  return VNET_API_ERROR_UNSPECIFIED;
411  }
412  else
413  {
414  if (!bibe)
415  return VNET_API_ERROR_NO_SUCH_ENTRY;
416 
417  nat64_free_out_addr_and_port (out_addr, out_port, p);
418  nat64_db_bib_entry_free (&nm->db, bibe);
419  }
420 
421  return 0;
422 }
423 
424 int
426 {
427  nat64_main_t *nm = &nat64_main;
428 
429  if (timeout == 0)
431  else if (timeout < SNAT_UDP_TIMEOUT_MIN)
432  return VNET_API_ERROR_INVALID_VALUE;
433  else
434  nm->udp_timeout = timeout;
435 
436  return 0;
437 }
438 
439 u32
441 {
442  nat64_main_t *nm = &nat64_main;
443 
444  return nm->udp_timeout;
445 }
446 
447 int
449 {
450  nat64_main_t *nm = &nat64_main;
451 
452  if (timeout == 0)
454  else
455  nm->icmp_timeout = timeout;
456 
457  return 0;
458 }
459 
460 u32
462 {
463  nat64_main_t *nm = &nat64_main;
464 
465  return nm->icmp_timeout;
466 }
467 
468 int
469 nat64_set_tcp_timeouts (u32 trans, u32 est, u32 incoming_syn)
470 {
471  nat64_main_t *nm = &nat64_main;
472 
473  if (trans == 0)
475  else
476  nm->tcp_trans_timeout = trans;
477 
478  if (est == 0)
480  else
481  nm->tcp_est_timeout = est;
482 
483  if (incoming_syn == 0)
485  else
486  nm->tcp_incoming_syn_timeout = incoming_syn;
487 
488  return 0;
489 }
490 
491 u32
493 {
494  nat64_main_t *nm = &nat64_main;
495 
496  return nm->tcp_trans_timeout;
497 }
498 
499 u32
501 {
502  nat64_main_t *nm = &nat64_main;
503 
504  return nm->tcp_est_timeout;
505 }
506 
507 u32
509 {
510  nat64_main_t *nm = &nat64_main;
511 
512  return nm->tcp_incoming_syn_timeout;
513 }
514 
515 void
516 nat64_session_reset_timeout (nat64_db_st_entry_t * ste, vlib_main_t * vm)
517 {
518  nat64_main_t *nm = &nat64_main;
519  u32 now = (u32) vlib_time_now (vm);
520 
521  switch (ip_proto_to_snat_proto (ste->proto))
522  {
523  case SNAT_PROTOCOL_ICMP:
524  ste->expire = now + nm->icmp_timeout;
525  return;
526  case SNAT_PROTOCOL_TCP:
527  {
528  switch (ste->tcp_state)
529  {
530  case NAT64_TCP_STATE_V4_INIT:
531  case NAT64_TCP_STATE_V6_INIT:
532  case NAT64_TCP_STATE_V4_FIN_RCV:
533  case NAT64_TCP_STATE_V6_FIN_RCV:
534  case NAT64_TCP_STATE_V6_FIN_V4_FIN_RCV:
535  case NAT64_TCP_STATE_TRANS:
536  ste->expire = now + nm->tcp_trans_timeout;
537  return;
538  case NAT64_TCP_STATE_ESTABLISHED:
539  ste->expire = now + nm->tcp_est_timeout;
540  return;
541  default:
542  return;
543  }
544  }
545  case SNAT_PROTOCOL_UDP:
546  ste->expire = now + nm->udp_timeout;
547  return;
548  default:
549  ste->expire = now + nm->udp_timeout;
550  return;
551  }
552 }
553 
554 void
555 nat64_tcp_session_set_state (nat64_db_st_entry_t * ste, tcp_header_t * tcp,
556  u8 is_ip6)
557 {
558  switch (ste->tcp_state)
559  {
560  case NAT64_TCP_STATE_CLOSED:
561  {
562  if (tcp->flags & TCP_FLAG_SYN)
563  {
564  if (is_ip6)
565  ste->tcp_state = NAT64_TCP_STATE_V6_INIT;
566  else
567  ste->tcp_state = NAT64_TCP_STATE_V4_INIT;
568  }
569  return;
570  }
571  case NAT64_TCP_STATE_V4_INIT:
572  {
573  if (is_ip6 && (tcp->flags & TCP_FLAG_SYN))
574  ste->tcp_state = NAT64_TCP_STATE_ESTABLISHED;
575  return;
576  }
577  case NAT64_TCP_STATE_V6_INIT:
578  {
579  if (!is_ip6 && (tcp->flags & TCP_FLAG_SYN))
580  ste->tcp_state = NAT64_TCP_STATE_ESTABLISHED;
581  return;
582  }
583  case NAT64_TCP_STATE_ESTABLISHED:
584  {
585  if (tcp->flags & TCP_FLAG_FIN)
586  {
587  if (is_ip6)
588  ste->tcp_state = NAT64_TCP_STATE_V6_FIN_RCV;
589  else
590  ste->tcp_state = NAT64_TCP_STATE_V4_FIN_RCV;
591  }
592  else if (tcp->flags & TCP_FLAG_RST)
593  {
594  ste->tcp_state = NAT64_TCP_STATE_TRANS;
595  }
596  return;
597  }
598  case NAT64_TCP_STATE_V4_FIN_RCV:
599  {
600  if (is_ip6 && (tcp->flags & TCP_FLAG_FIN))
601  ste->tcp_state = NAT64_TCP_STATE_V6_FIN_V4_FIN_RCV;
602  return;
603  }
604  case NAT64_TCP_STATE_V6_FIN_RCV:
605  {
606  if (!is_ip6 && (tcp->flags & TCP_FLAG_FIN))
607  ste->tcp_state = NAT64_TCP_STATE_V6_FIN_V4_FIN_RCV;
608  return;
609  }
610  case NAT64_TCP_STATE_TRANS:
611  {
612  if (!(tcp->flags & TCP_FLAG_RST))
613  ste->tcp_state = NAT64_TCP_STATE_ESTABLISHED;
614  return;
615  }
616  default:
617  return;
618  }
619 }
620 
621 int
622 nat64_add_del_prefix (ip6_address_t * prefix, u8 plen, u32 vrf_id, u8 is_add)
623 {
624  nat64_main_t *nm = &nat64_main;
625  nat64_prefix_t *p = 0;
626  int i;
627 
628  /* Verify prefix length */
629  if (plen != 32 && plen != 40 && plen != 48 && plen != 56 && plen != 64
630  && plen != 96)
631  return VNET_API_ERROR_INVALID_VALUE;
632 
633  /* Check if tenant already have prefix */
634  for (i = 0; i < vec_len (nm->pref64); i++)
635  {
636  if (nm->pref64[i].vrf_id == vrf_id)
637  {
638  p = nm->pref64 + i;
639  break;
640  }
641  }
642 
643  if (is_add)
644  {
645  if (!p)
646  {
647  vec_add2 (nm->pref64, p, 1);
648  p->fib_index =
651  p->vrf_id = vrf_id;
652  }
653 
654  p->prefix.as_u64[0] = prefix->as_u64[0];
655  p->prefix.as_u64[1] = prefix->as_u64[1];
656  p->plen = plen;
657  }
658  else
659  {
660  if (!p)
661  return VNET_API_ERROR_NO_SUCH_ENTRY;
662 
663  vec_del1 (nm->pref64, i);
664  }
665 
666  return 0;
667 }
668 
669 void
671 {
672  nat64_main_t *nm = &nat64_main;
673  nat64_prefix_t *p = 0;
674 
675  /* *INDENT-OFF* */
676  vec_foreach (p, nm->pref64)
677  {
678  if (fn (p, ctx))
679  break;
680  };
681  /* *INDENT-ON* */
682 }
683 
684 void
686 {
687  nat64_main_t *nm = &nat64_main;
688  nat64_prefix_t *p, *gp = 0, *prefix = 0;
689 
690  /* *INDENT-OFF* */
691  vec_foreach (p, nm->pref64)
692  {
693  if (p->fib_index == fib_index)
694  {
695  prefix = p;
696  break;
697  }
698 
699  if (p->fib_index == 0)
700  gp = p;
701  };
702  /* *INDENT-ON* */
703 
704  if (!prefix)
705  prefix = gp;
706 
707  if (prefix)
708  {
709  memset (ip6, 0, 16);
710  memcpy (ip6, &p->prefix, p->plen);
711  switch (p->plen)
712  {
713  case 32:
714  ip6->as_u32[1] = ip4->as_u32;
715  break;
716  case 40:
717  ip6->as_u8[5] = ip4->as_u8[0];
718  ip6->as_u8[6] = ip4->as_u8[1];
719  ip6->as_u8[7] = ip4->as_u8[2];
720  ip6->as_u8[9] = ip4->as_u8[3];
721  break;
722  case 48:
723  ip6->as_u8[6] = ip4->as_u8[0];
724  ip6->as_u8[7] = ip4->as_u8[1];
725  ip6->as_u8[9] = ip4->as_u8[2];
726  ip6->as_u8[10] = ip4->as_u8[3];
727  break;
728  case 56:
729  ip6->as_u8[7] = ip4->as_u8[0];
730  ip6->as_u8[9] = ip4->as_u8[1];
731  ip6->as_u8[10] = ip4->as_u8[2];
732  ip6->as_u8[11] = ip4->as_u8[3];
733  break;
734  case 64:
735  ip6->as_u8[9] = ip4->as_u8[0];
736  ip6->as_u8[10] = ip4->as_u8[1];
737  ip6->as_u8[11] = ip4->as_u8[2];
738  ip6->as_u8[12] = ip4->as_u8[3];
739  break;
740  case 96:
741  ip6->as_u32[3] = ip4->as_u32;
742  break;
743  default:
744  clib_warning ("invalid prefix length");
745  break;
746  }
747  }
748  else
749  {
750  memcpy (ip6, well_known_prefix, 16);
751  ip6->as_u32[3] = ip4->as_u32;
752  }
753 }
754 
755 void
757 {
758  nat64_main_t *nm = &nat64_main;
759  nat64_prefix_t *p, *gp = 0;
760  u8 plen = 0;
761 
762  /* *INDENT-OFF* */
763  vec_foreach (p, nm->pref64)
764  {
765  if (p->fib_index == fib_index)
766  {
767  plen = p->plen;
768  break;
769  }
770 
771  if (p->vrf_id == 0)
772  gp = p;
773  };
774  /* *INDENT-ON* */
775 
776  if (!plen)
777  {
778  if (gp)
779  plen = gp->plen;
780  else
781  plen = 96;
782  }
783 
784  switch (plen)
785  {
786  case 32:
787  ip4->as_u32 = ip6->as_u32[1];
788  break;
789  case 40:
790  ip4->as_u8[0] = ip6->as_u8[5];
791  ip4->as_u8[1] = ip6->as_u8[6];
792  ip4->as_u8[2] = ip6->as_u8[7];
793  ip4->as_u8[3] = ip6->as_u8[9];
794  break;
795  case 48:
796  ip4->as_u8[0] = ip6->as_u8[6];
797  ip4->as_u8[1] = ip6->as_u8[7];
798  ip4->as_u8[2] = ip6->as_u8[9];
799  ip4->as_u8[3] = ip6->as_u8[10];
800  break;
801  case 56:
802  ip4->as_u8[0] = ip6->as_u8[7];
803  ip4->as_u8[1] = ip6->as_u8[9];
804  ip4->as_u8[2] = ip6->as_u8[10];
805  ip4->as_u8[3] = ip6->as_u8[11];
806  break;
807  case 64:
808  ip4->as_u8[0] = ip6->as_u8[9];
809  ip4->as_u8[1] = ip6->as_u8[10];
810  ip4->as_u8[2] = ip6->as_u8[11];
811  ip4->as_u8[3] = ip6->as_u8[12];
812  break;
813  case 96:
814  ip4->as_u32 = ip6->as_u32[3];
815  break;
816  default:
817  clib_warning ("invalid prefix length");
818  break;
819  }
820 }
821 
822 /**
823  * @brief The 'nat64-expire-walk' process's main loop.
824  *
825  * Check expire time for NAT64 sessions.
826  */
827 static uword
829  vlib_frame_t * f)
830 {
831  nat64_main_t *nm = &nat64_main;
832 
833  while (!nm->is_disabled)
834  {
837  u32 now = (u32) vlib_time_now (vm);
838 
839  nad64_db_st_free_expired (&nm->db, now);
840  }
841 
842  return 0;
843 }
844 
846 
847 /* *INDENT-OFF* */
848 VLIB_REGISTER_NODE (nat64_expire_walk_node, static) = {
849  .function = nat64_expire_walk_fn,
850  .type = VLIB_NODE_TYPE_PROCESS,
851  .name = "nat64-expire-walk",
852 };
853 /* *INDENT-ON* */
854 
855 /*
856  * fd.io coding-style-patch-verification: ON
857  *
858  * Local Variables:
859  * eval: (c-set-style "gnu")
860  * End:
861  */
u32 nat64_get_icmp_timeout(void)
Get ICMP session timeout.
Definition: nat64.c:461
u32 icmp_timeout
Definition: nat64.h:66
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
int nat64_set_udp_timeout(u32 timeout)
Set UDP session timeout.
Definition: nat64.c:425
int nat64_alloc_out_addr_and_port(u32 fib_index, snat_protocol_t proto, ip4_address_t *addr, u16 *port)
Alloce IPv4 address and port pair from NAT64 pool.
Definition: nat64.c:234
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
Definition: node_funcs.h:699
a
Definition: bitmap.h:516
ip6_address_t prefix
Definition: nat64.h:44
snat_address_t * addr_pool
Address pool vector.
Definition: nat64.h:56
#define TCP_FLAG_SYN
Definition: fa_node.h:8
void nat64_extract_ip4(ip6_address_t *ip6, ip4_address_t *ip4, u32 fib_index)
Extract IPv4 address from the IPv4-embedded IPv6 addresses.
Definition: nat64.c:756
#define SNAT_TCP_ESTABLISHED_TIMEOUT
Definition: nat.h:36
u8 as_u8[16]
Definition: ip6_packet.h:48
u64 as_u64[2]
Definition: ip6_packet.h:51
int nat64_add_del_interface(u32 sw_if_index, u8 is_inside, u8 is_add)
Enable/disable NAT64 feature on the interface.
Definition: nat64.c:166
#define NULL
Definition: clib.h:55
u8 is_disabled
Definition: nat64.h:71
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:221
nat64_db_bib_entry_t * nat64_db_bib_entry_create(nat64_db_t *db, ip6_address_t *in_addr, ip4_address_t *out_addr, u16 in_port, u16 out_port, u32 fib_index, u8 proto, u8 is_static)
Create new NAT64 BIB entry.
Definition: nat64_db.c:45
int nat64_add_del_pool_addr(ip4_address_t *addr, u32 vrf_id, u8 is_add)
Add/delete address to NAT64 pool.
Definition: nat64.c:83
nat64_db_bib_entry_t * nat64_db_bib_entry_find(nat64_db_t *db, ip46_address_t *addr, u16 port, u8 proto, u32 fib_index, u8 is_ip6)
Find NAT64 BIB entry.
Definition: nat64_db.c:173
struct _vlib_node_registration vlib_node_registration_t
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:557
u32 tcp_trans_timeout
Definition: nat64.h:67
void snat_add_del_addr_to_fib(ip4_address_t *addr, u8 p_len, u32 sw_if_index, int is_add)
Add/del NAT address to FIB.
Definition: nat.c:119
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:225
struct _tcp_header tcp_header_t
int nat64_set_tcp_timeouts(u32 trans, u32 est, u32 incoming_syn)
Set TCP session timeouts.
Definition: nat64.c:469
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:437
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
Definition: node_funcs.h:542
int nat64_set_icmp_timeout(u32 timeout)
Set ICMP session timeout.
Definition: nat64.c:448
A high priority source a plugin can use.
Definition: fib_entry.h:58
#define clib_error_return(e, args...)
Definition: error.h:99
u32 tcp_est_timeout
Definition: nat64.h:68
void nat64_tcp_session_set_state(nat64_db_st_entry_t *ste, tcp_header_t *tcp, u8 is_ip6)
Set NAT64 TCP session state.
Definition: nat64.c:555
snat_interface_t * interfaces
Interface pool.
Definition: nat64.h:53
u32 tcp_incoming_syn_timeout
Definition: nat64.h:69
nat64_db_t db
BIB and session DB.
Definition: nat64.h:62
u32 fib_index
Definition: nat64.h:47
u32 udp_timeout
Definition: nat64.h:65
nat64_prefix_t * pref64
Pref64 vector.
Definition: nat64.h:59
void nat64_session_reset_timeout(nat64_db_st_entry_t *ste, vlib_main_t *vm)
Reset NAT64 session timeout.
Definition: nat64.c:516
void nad64_db_st_free_expired(nat64_db_t *db, u32 now)
Free expired session entries in session tables.
Definition: nat64_db.c:533
u32 nat64_get_udp_timeout(void)
Get UDP session timeout.
Definition: nat64.c:440
#define SNAT_UDP_TIMEOUT
Definition: nat.h:33
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:270
void nat64_db_bib_entry_free(nat64_db_t *db, nat64_db_bib_entry_t *bibe)
Free NAT64 BIB entry.
Definition: nat64_db.c:106
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:801
static uword nat64_expire_walk_fn(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
The &#39;nat64-expire-walk&#39; process&#39;s main loop.
Definition: nat64.c:828
#define TCP_FLAG_FIN
Definition: fa_node.h:7
void fib_table_unlock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Take a reference counting lock on the table.
Definition: fib_table.c:1177
void nat64_compose_ip6(ip6_address_t *ip6, ip4_address_t *ip4, u32 fib_index)
Compose IPv4-embedded IPv6 addresses.
Definition: nat64.c:685
#define TCP_FLAG_RST
Definition: fa_node.h:9
static u8 well_known_prefix[]
Definition: nat64.c:41
snat_main_t snat_main
Definition: nat.c:31
u32 as_u32[4]
Definition: ip6_packet.h:50
u32 nat64_get_tcp_est_timeout(void)
Get TCP established timeout.
Definition: nat64.c:500
void nat64_pool_addr_walk(nat64_pool_addr_walk_fn_t fn, void *ctx)
Walk NAT64 pool.
Definition: nat64.c:151
vlib_main_t * vm
Definition: buffer.c:283
int nat64_add_del_prefix(ip6_address_t *prefix, u8 plen, u32 vrf_id, u8 is_add)
Add/delete NAT64 prefix.
Definition: nat64.c:622
#define clib_warning(format, args...)
Definition: error.h:59
nat64_main_t nat64_main
Definition: nat64.c:25
u32 vrf_id
Definition: nat64.h:46
unsigned int u32
Definition: types.h:88
u32 nat64_get_tcp_incoming_syn_timeout(void)
Get TCP incoming SYN timeout.
Definition: nat64.c:508
long ctx[MAX_CONNS]
Definition: main.c:95
static u32 ip_proto_to_snat_proto(u8 ip_proto)
Definition: nat.h:429
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id, fib_source_t src)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1084
ip4_address_t addr
Definition: nat.h:169
#define VNET_FEATURES(...)
Definition: feature.h:368
void nat64_prefix_walk(nat64_prefix_walk_fn_t fn, void *ctx)
Walk NAT64 prefixes.
Definition: nat64.c:670
u64 uword
Definition: types.h:112
void nat64_interfaces_walk(nat64_interface_walk_fn_t fn, void *ctx)
Walk NAT64 interfaces.
Definition: nat64.c:219
void nat64_db_free_out_addr(nat64_db_t *db, ip4_address_t *out_addr)
Free sessions using specific outside address.
Definition: nat64_db.c:565
clib_error_t * nat64_init(vlib_main_t *vm)
Initialize NAT64.
Definition: nat64.c:51
NAT64 global declarations.
static vlib_node_registration_t nat64_expire_walk_node
(constructor) VLIB_REGISTER_NODE (nat64_expire_walk_node)
Definition: nat64.c:845
unsigned short u16
Definition: types.h:57
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
snat_protocol_t
Definition: nat.h:104
#define SNAT_ICMP_TIMEOUT
Definition: nat.h:38
NAT64 DB.
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
#define SNAT_UDP_TIMEOUT_MIN
Definition: nat.h:34
#define vec_foreach(var, vec)
Vector iterator.
vhost_vring_addr_t addr
Definition: vhost-user.h:83
int nat64_db_init(nat64_db_t *db)
Initialize NAT64 DB.
Definition: nat64_db.c:22
#define SNAT_TCP_INCOMING_SYN
Definition: nat.h:37
VNET_FEATURE_INIT(nat64_in2out, static)
void nat64_free_out_addr_and_port(ip4_address_t *addr, u16 port, snat_protocol_t proto)
Free IPv4 address and port pair from NAT64 pool.
Definition: nat64.c:320
#define SNAT_TCP_TRANSITORY_TIMEOUT
Definition: nat.h:35
int nat64_add_del_static_bib_entry(ip6_address_t *in_addr, ip4_address_t *out_addr, u16 in_port, u16 out_port, u8 proto, u32 vrf_id, u8 is_add)
Add/delete static NAT64 BIB entry.
Definition: nat64.c:352
int(* nat64_prefix_walk_fn_t)(nat64_prefix_t *pref64, void *ctx)
Call back function when walking addresses in NAT64 prefixes, non-zero return value stop walk...
Definition: nat64.h:282
u32 fib_index
Definition: nat.h:170
u32 nat64_get_tcp_trans_timeout(void)
Get TCP transitory timeout.
Definition: nat64.c:492
int(* nat64_interface_walk_fn_t)(snat_interface_t *i, void *ctx)
Call back function when walking interfaces with NAT64 feature, non-zero return value stop walk...
Definition: nat64.h:120
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:229
int(* nat64_pool_addr_walk_fn_t)(snat_address_t *addr, void *ctx)
Call back function when walking addresses in NAT64 pool, non-zero return value stop walk...
Definition: nat64.h:95