29 #include <vpp/app/version.h> 36 .arc_name =
"ip4-unicast",
37 .node_name =
"nat44-in2out",
41 .arc_name =
"ip4-unicast",
42 .node_name =
"nat44-out2in",
46 .arc_name =
"ip4-unicast",
47 .node_name =
"nat44-det-in2out",
51 .arc_name =
"ip4-unicast",
52 .node_name =
"nat44-det-out2in",
56 .arc_name =
"ip4-unicast",
57 .node_name =
"nat44-in2out-worker-handoff",
61 .arc_name =
"ip4-unicast",
62 .node_name =
"nat44-out2in-worker-handoff",
66 .arc_name =
"ip4-unicast",
67 .node_name =
"nat44-in2out-fast",
71 .arc_name =
"ip4-unicast",
72 .node_name =
"nat44-out2in-fast",
76 .arc_name =
"ip4-unicast",
77 .node_name =
"nat44-hairpin-dst",
83 .arc_name =
"ip4-output",
84 .node_name =
"nat44-in2out-output",
88 .arc_name =
"ip4-output",
89 .node_name =
"nat44-in2out-output-worker-handoff",
93 .arc_name =
"ip4-output",
94 .node_name =
"nat44-hairpin-src",
101 .version = VPP_BUILD_VER,
102 .description =
"Network Address Translation",
126 .ip4.as_u32 = addr->
as_u32,
175 #define _(N, i, n, s) \ 176 clib_bitmap_alloc (ap->busy_##n##_port_bitmap, 65535); \ 177 ap->busy_##n##_ports = 0; \ 178 vec_validate_init_empty (ap->busy_##n##_ports_per_thread, tm->n_vlib_mains - 1, 0); 188 snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1);
196 snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1);
207 if (m->external_addr.as_u32 == addr.as_u32)
218 v = clib_net_to_host_u32(a->
as_u32) + 1;
219 a->
as_u32 = clib_host_to_net_u32(v);
263 u16 l_port,
u16 e_port,
u32 vrf_id,
int addr_only,
277 if (sw_if_index != ~0)
286 if (first_int_addr == 0)
289 (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
298 m_key.
port = addr_only ? 0 : e_port;
299 m_key.
protocol = addr_only ? 0 : proto;
310 return VNET_API_ERROR_VALUE_EXIST;
317 return VNET_API_ERROR_NO_SUCH_FIB;
339 #define _(N, j, n, s) \ 340 case SNAT_PROTOCOL_##N: \ 341 if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \ 342 return VNET_API_ERROR_INVALID_VALUE; \ 343 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \ 346 a->busy_##n##_ports++; \ 347 a->busy_##n##_ports_per_thread[(e_port - 1024) / sm->port_per_thread]++; \ 354 return VNET_API_ERROR_INVALID_VALUE_2;
361 return VNET_API_ERROR_NO_SUCH_ENTRY;
365 memset (m, 0,
sizeof (*m));
404 return VNET_API_ERROR_NO_SUCH_ENTRY;
416 #define _(N, j, n, s) \ 417 case SNAT_PROTOCOL_##N: \ 418 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \ 421 a->busy_##n##_ports--; \ 422 a->busy_##n##_ports_per_thread[(e_port - 1024) / sm->port_per_thread]--; \ 429 return VNET_API_ERROR_INVALID_VALUE_2;
456 u32 elt_index, head_index, del_elt_index;
469 if (!clib_bihash_search_8_8 (&tsm->
user_hash, &kv, &value))
471 user_index = value.
value;
477 elt_index = head->
next;
479 ses_index = elt->
value;
480 while (ses_index != ~0)
483 del_elt_index = elt_index;
484 elt_index = elt->
next;
486 ses_index = elt->
value;
490 if ((s->out2in.addr.as_u32 != e_addr.
as_u32) &&
491 (clib_net_to_host_u16 (s->out2in.port) != e_port))
499 up_key.
l_addr = s->in2out.addr;
500 up_key.
r_addr = s->ext_host_addr;
502 up_key.
proto = s->in2out.port;
507 if (clib_bihash_add_del_16_8 (&sm->
in2out_ed,
511 up_key.
l_addr = s->out2in.addr;
515 if (clib_bihash_add_del_16_8 (&sm->
out2in_ed,
523 s->out2in.addr.as_u32,
527 s->in2out.fib_index);
529 value.
key = s->in2out.as_u64;
530 if (clib_bihash_add_del_8_8 (&tsm->
in2out, &value, 0))
532 value.
key = s->out2in.as_u64;
533 if (clib_bihash_add_del_8_8 (&tsm->
out2in, &value, 0))
548 clib_bihash_add_del_8_8 (&tsm->
user_hash, &kv, 0);
564 if (interface->is_inside)
567 snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
572 if (interface->is_inside)
575 snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
594 u32 worker_index = 0;
610 return VNET_API_ERROR_VALUE_EXIST;
613 return VNET_API_ERROR_INVALID_VALUE;
631 #define _(N, j, n, s) \ 632 case SNAT_PROTOCOL_##N: \ 633 if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \ 634 return VNET_API_ERROR_INVALID_VALUE; \ 635 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \ 638 a->busy_##n##_ports++; \ 639 a->busy_##n##_ports_per_thread[(e_port - 1024) / sm->port_per_thread]++; \ 646 return VNET_API_ERROR_INVALID_VALUE_2;
653 return VNET_API_ERROR_NO_SUCH_ENTRY;
657 memset (m, 0,
sizeof (*m));
673 clib_warning (
"static_mapping_by_external key add failed");
674 return VNET_API_ERROR_UNSPECIFIED;
691 if (clib_bihash_add_del_8_8(&tsm->
out2in, &kv, 1))
693 clib_warning (
"static_mapping_by_local key add failed");
694 return VNET_API_ERROR_UNSPECIFIED;
698 for (i = 0; i <
vec_len (locals); i++)
705 locals[
i].
prefix = (i == 0) ? locals[i].probability :\
706 (locals[i - 1].prefix + locals[i].probability);
709 m_key.
port = clib_host_to_net_u16 (locals[i].port);
712 if (clib_bihash_add_del_8_8(&tsm->
in2out, &kv, 1))
715 return VNET_API_ERROR_UNSPECIFIED;
722 return VNET_API_ERROR_NO_SUCH_ENTRY;
736 #define _(N, j, n, s) \ 737 case SNAT_PROTOCOL_##N: \ 738 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \ 741 a->busy_##n##_ports--; \ 742 a->busy_##n##_ports_per_thread[(e_port - 1024) / sm->port_per_thread]--; \ 749 return VNET_API_ERROR_INVALID_VALUE_2;
764 clib_warning (
"static_mapping_by_external key del failed");
765 return VNET_API_ERROR_UNSPECIFIED;
770 if (clib_bihash_add_del_8_8(&tsm->
out2in, &kv, 0))
773 return VNET_API_ERROR_UNSPECIFIED;
784 clib_warning (
"static_mapping_by_local key del failed");
785 return VNET_API_ERROR_UNSPECIFIED;
788 m_key.
port = clib_host_to_net_u16 (local->
port);
790 if (clib_bihash_add_del_8_8(&tsm->
in2out, &kv, 0))
793 return VNET_API_ERROR_UNSPECIFIED;
808 u32 *ses_to_be_removed = 0, *ses_index;
827 return VNET_API_ERROR_NO_SUCH_ENTRY;
833 if (m->external_addr.as_u32 == addr.as_u32)
834 (void) snat_add_static_mapping (m->local_addr, m->external_addr,
835 m->local_port, m->external_port,
836 m->vrf_id, m->addr_only, ~0,
846 return VNET_API_ERROR_UNSPECIFIED;
855 if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
860 if (ses->out2in.addr.as_u32 == addr.as_u32)
862 if (snat_is_unk_proto_session (ses))
864 clib_bihash_kv_16_8_t up_kv;
865 nat_ed_ses_key_t up_key;
866 up_key.l_addr = ses->in2out.addr;
867 up_key.r_addr = ses->ext_host_addr;
868 up_key.fib_index = ses->in2out.fib_index;
869 up_key.proto = ses->in2out.port;
872 up_kv.key[0] = up_key.as_u64[0];
873 up_kv.key[1] = up_key.as_u64[1];
874 if (clib_bihash_add_del_16_8 (&sm->in2out_ed,
876 clib_warning (
"in2out key del failed");
878 up_key.l_addr = ses->out2in.addr;
879 up_key.fib_index = ses->out2in.fib_index;
880 up_kv.key[0] = up_key.as_u64[0];
881 up_kv.key[1] = up_key.as_u64[1];
882 if (clib_bihash_add_del_16_8 (&sm->out2in_ed,
884 clib_warning (
"out2in key del failed");
889 snat_ipfix_logging_nat44_ses_delete(ses->in2out.addr.as_u32,
890 ses->out2in.addr.as_u32,
891 ses->in2out.protocol,
894 ses->in2out.fib_index);
895 kv.key = ses->in2out.as_u64;
896 clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 0);
897 kv.key = ses->out2in.as_u64;
898 clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 0);
900 vec_add1 (ses_to_be_removed, ses - tsm->sessions);
901 clib_dlist_remove (tsm->list_pool, ses->per_user_index);
902 user_key.addr = ses->in2out.addr;
903 user_key.fib_index = ses->in2out.fib_index;
904 kv.key = user_key.as_u64;
905 if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
907 u = pool_elt_at_index (tsm->users, value.value);
925 if (interface->is_inside)
928 snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
933 if (interface->is_inside)
936 snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
947 const char * feature_name;
953 feature_name = is_inside ?
"nat44-in2out-fast" :
"nat44-out2in-fast";
957 feature_name = is_inside ?
"nat44-in2out-worker-handoff" :
"nat44-out2in-worker-handoff";
959 feature_name = is_inside ?
"nat44-det-in2out" :
"nat44-det-out2in";
961 feature_name = is_inside ?
"nat44-in2out" :
"nat44-out2in";
975 if (i->sw_if_index == sw_if_index)
978 pool_put (sm->interfaces, i);
980 return VNET_API_ERROR_VALUE_EXIST;
987 return VNET_API_ERROR_NO_SUCH_ENTRY;
990 i->sw_if_index = sw_if_index;
991 i->is_inside = is_inside;
1003 if (!(m->addr_only))
1006 snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
1011 snat_add_del_addr_to_fib(&dm->out_addr, dm->out_plen, sw_if_index, !is_del);
1028 return VNET_API_ERROR_UNSUPPORTED;
1033 sw_if_index, !is_del, 0, 0);
1035 sw_if_index, !is_del, 0, 0);
1042 sw_if_index, !is_del, 0, 0);
1044 "nat44-in2out-output-worker-handoff",
1045 sw_if_index, !is_del, 0, 0);
1052 sw_if_index, !is_del, 0, 0);
1065 if (i->sw_if_index == sw_if_index)
1068 pool_put (sm->output_feature_interfaces, i);
1070 return VNET_API_ERROR_VALUE_EXIST;
1077 return VNET_API_ERROR_NO_SUCH_ENTRY;
1079 pool_get (sm->output_feature_interfaces,
i);
1080 i->sw_if_index = sw_if_index;
1081 i->is_inside = is_inside;
1093 if (!(m->addr_only))
1096 snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
1108 return VNET_API_ERROR_FEATURE_DISABLED;
1111 return VNET_API_ERROR_INVALID_WORKER;
1134 u32 if_address_index,
1220 u16 port_host_byte_order = clib_net_to_host_u16 (k->
port);
1228 #define _(N, i, n, s) \ 1229 case SNAT_PROTOCOL_##N: \ 1230 ASSERT (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \ 1231 port_host_byte_order) == 1); \ 1232 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \ 1233 port_host_byte_order, 0); \ 1234 a->busy_##n##_ports--; \ 1235 a->busy_##n##_ports_per_thread[thread_index]--; \ 1273 m_key.
port = clib_net_to_host_u16 (match.
port);
1279 if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
1285 if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
1299 mid = ((
hi -
lo) >> 1) +
lo;
1343 u32 * address_indexp)
1356 #define _(N, j, n, s) \ 1357 case SNAT_PROTOCOL_##N: \ 1358 if (a->busy_##n##_ports_per_thread[thread_index] < sm->port_per_thread) \ 1362 portnum = (sm->port_per_thread * \ 1363 sm->per_thread_data[thread_index].snat_thread_index) + \ 1364 snat_random_port(sm, 1, sm->port_per_thread) + 1024; \ 1365 if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \ 1367 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \ 1368 a->busy_##n##_ports_per_thread[thread_index]++; \ 1369 a->busy_##n##_ports++; \ 1370 k->addr = a->addr; \ 1371 k->port = clib_host_to_net_u16(portnum); \ 1372 *address_indexp = i; \ 1399 u32 start_host_order, end_host_order;
1412 if (
unformat (line_input,
"%U - %U",
1416 else if (
unformat (line_input,
"tenant-vrf %u", &vrf_id))
1419 end_addr = start_addr;
1420 else if (
unformat (line_input,
"del"))
1436 start_host_order = clib_host_to_net_u32 (start_addr.
as_u32);
1437 end_host_order = clib_host_to_net_u32 (end_addr.
as_u32);
1439 if (end_host_order < start_host_order)
1445 count = (end_host_order - start_host_order) + 1;
1453 this_addr = start_addr;
1455 for (i = 0; i <
count; i++)
1464 case VNET_API_ERROR_NO_SUCH_ENTRY:
1467 case VNET_API_ERROR_UNSPECIFIED:
1484 .path =
"nat44 add address",
1485 .short_help =
"nat44 add address <ip4-range-start> [- <ip4-range-end>] " 1486 "[tenant-vrf <vrf-id>] [del]",
1499 u32 * inside_sw_if_indices = 0;
1500 u32 * outside_sw_if_indices = 0;
1501 u8 is_output_feature = 0;
1515 vec_add1 (inside_sw_if_indices, sw_if_index);
1518 vec_add1 (outside_sw_if_indices, sw_if_index);
1519 else if (
unformat (line_input,
"output-feature"))
1520 is_output_feature = 1;
1521 else if (
unformat (line_input,
"del"))
1531 if (
vec_len (inside_sw_if_indices))
1533 for (i = 0; i <
vec_len(inside_sw_if_indices); i++)
1535 sw_if_index = inside_sw_if_indices[
i];
1536 if (is_output_feature)
1541 is_del ?
"del" :
"add",
1553 is_del ?
"del" :
"add",
1563 if (
vec_len (outside_sw_if_indices))
1565 for (i = 0; i <
vec_len(outside_sw_if_indices); i++)
1567 sw_if_index = outside_sw_if_indices[
i];
1568 if (is_output_feature)
1573 is_del ?
"del" :
"add",
1585 is_del ?
"del" :
"add",
1604 .path =
"set interface nat44",
1606 .short_help =
"set interface nat44 in <intfc> out <intfc> [output-feature] " 1613 u32 *r = va_arg (*args,
u32 *);
1616 #define _(N, i, n, s) else if (unformat (input, s)) *r = SNAT_PROTOCOL_##N; 1632 #define _(N, j, n, str) case SNAT_PROTOCOL_##N: t = (u8 *) str; break; 1636 s =
format (s,
"unknown");
1651 u32 l_port = 0, e_port = 0, vrf_id = ~0;
1654 u32 sw_if_index = ~0;
1677 else if (
unformat (line_input,
"external %U %u",
1682 else if (
unformat (line_input,
"external %U",
1685 else if (
unformat (line_input,
"vrf %u", &vrf_id))
1689 else if (
unformat (line_input,
"del"))
1699 if (!addr_only && !proto_set)
1706 vrf_id, addr_only, sw_if_index, proto, is_add);
1710 case VNET_API_ERROR_INVALID_VALUE:
1713 case VNET_API_ERROR_NO_SUCH_ENTRY:
1719 case VNET_API_ERROR_NO_SUCH_FIB:
1722 case VNET_API_ERROR_VALUE_EXIST:
1750 .path =
"nat44 add static mapping",
1753 "nat44 add static mapping tcp|udp|icmp local <addr> [<port>] external <addr> [<port>] [vrf <table-id>] [del]",
1764 u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0;
1777 if (
unformat (line_input,
"local %U:%u probability %u",
1780 memset (&local, 0,
sizeof (local));
1781 local.addr = l_addr;
1782 local.port = (
u16) l_port;
1783 local.probability = (
u8) probability;
1789 else if (
unformat (line_input,
"vrf %u", &vrf_id))
1794 else if (
unformat (line_input,
"del"))
1821 case VNET_API_ERROR_INVALID_VALUE:
1824 case VNET_API_ERROR_NO_SUCH_ENTRY:
1830 case VNET_API_ERROR_VALUE_EXIST:
1845 .path =
"nat44 add load-balancing static mapping",
1848 "nat44 add load-balancing static mapping protocol tcp|udp external <addr>:<port> local <addr>:<port> probability <n> [vrf <table-id>] [del]",
1889 case VNET_API_ERROR_INVALID_WORKER:
1892 case VNET_API_ERROR_FEATURE_DISABLED:
1894 "Supported only if 2 or more workes available.");
1914 .path =
"set nat workers",
1917 "set nat workers <workers-list>",
1938 if (
unformat (line_input,
"domain %d", &domain_id))
1940 else if (
unformat (line_input,
"src-port %d", &src_port))
1942 else if (
unformat (line_input,
"disable"))
1976 .path =
"nat ipfix logging",
1978 .short_help =
"nat ipfix logging [domain <domain-id>] [src-port <port>] [disable]",
1985 u32 next_worker_index = 0;
1993 next_worker_index += sm->
workers[hash & (_vec_len (sm->
workers) - 1)];
1997 return next_worker_index;
2047 if (!clib_bihash_search_16_8 (&sm->
out2in_ed, &s_kv, &s_value))
2069 icmp46_header_t * icmp = (icmp46_header_t *) udp;
2080 case SNAT_PROTOCOL_ICMP:
2081 icmp = (icmp46_header_t*)l4_header;
2085 case SNAT_PROTOCOL_UDP:
2086 case SNAT_PROTOCOL_TCP:
2098 m_key.addr = ip0->dst_address;
2099 m_key.port = clib_net_to_host_u16 (port);
2100 m_key.protocol = proto;
2101 m_key.fib_index = rx_fib_index0;
2102 kv.key = m_key.as_u64;
2103 if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
2106 return m->worker_index;
2111 return (
u32) ((clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread);
2118 u32 translation_buckets = 1024;
2119 u32 translation_memory_size = 128<<20;
2120 u32 user_buckets = 128;
2121 u32 user_memory_size = 64<<20;
2122 u32 max_translations_per_user = 100;
2123 u32 outside_vrf_id = 0;
2124 u32 inside_vrf_id = 0;
2125 u32 static_mapping_buckets = 1024;
2126 u32 static_mapping_memory_size = 64<<20;
2127 u8 static_mapping_only = 0;
2128 u8 static_mapping_connection_tracking = 0;
2135 if (
unformat (input,
"translation hash buckets %d", &translation_buckets))
2137 else if (
unformat (input,
"translation hash memory %d",
2138 &translation_memory_size));
2139 else if (
unformat (input,
"user hash buckets %d", &user_buckets))
2141 else if (
unformat (input,
"user hash memory %d",
2144 else if (
unformat (input,
"max translations per user %d",
2145 &max_translations_per_user))
2147 else if (
unformat (input,
"outside VRF id %d",
2150 else if (
unformat (input,
"inside VRF id %d",
2153 else if (
unformat (input,
"static mapping only"))
2155 static_mapping_only = 1;
2156 if (
unformat (input,
"connection tracking"))
2157 static_mapping_connection_tracking = 1;
2159 else if (
unformat (input,
"deterministic"))
2200 if (!static_mapping_only ||
2201 (static_mapping_only && static_mapping_connection_tracking))
2208 clib_bihash_init_8_8 (&tsm->
in2out,
"in2out", translation_buckets,
2209 translation_memory_size);
2211 clib_bihash_init_8_8 (&tsm->
out2in,
"out2in", translation_buckets,
2212 translation_memory_size);
2214 clib_bihash_init_8_8 (&tsm->
user_hash,
"users", user_buckets,
2218 clib_bihash_init_16_8 (&sm->
in2out_ed,
"in2out-ed",
2219 translation_buckets, translation_memory_size);
2221 clib_bihash_init_16_8 (&sm->
out2in_ed,
"out2in-ed",
2222 translation_buckets, translation_memory_size);
2230 "static_mapping_by_local", static_mapping_buckets,
2231 static_mapping_memory_size);
2234 "static_mapping_by_external", static_mapping_buckets,
2235 static_mapping_memory_size);
2250 #define _(v, N, str) case SNAT_SESSION_##N: t = (u8 *) str; break; 2254 t =
format (t,
"unknown");
2264 s =
format (s,
"%U proto %U port %d fib %d",
2274 snat_session_t * sess = va_arg (*args, snat_session_t *);
2278 s =
format (s,
" i2o %U proto %u fib %u\n",
2280 sess->in2out.fib_index);
2281 s =
format (s,
" o2i %U proto %u fib %u\n",
2283 sess->out2in.fib_index);
2290 if (sess->ext_host_addr.as_u32)
2291 s =
format (s,
" external host %U\n",
2293 s =
format (s,
" last heard %.2f\n", sess->last_heard);
2294 s =
format (s,
" total pkts %d, total bytes %lld\n",
2295 sess->total_pkts, sess->total_bytes);
2297 s =
format (s,
" static translation\n");
2299 s =
format (s,
" dynamic translation\n");
2301 s =
format (s,
" load-balancing\n");
2310 int verbose = va_arg (*args,
int);
2312 u32 elt_index, head_index;
2314 snat_session_t * sess;
2316 s =
format (s,
"%U: %d dynamic translations, %d static translations\n",
2327 elt_index = head->
next;
2329 session_index = elt->
value;
2331 while (session_index != ~0)
2337 elt_index = elt->
next;
2339 session_index = elt->
value;
2352 s =
format (s,
"local %U external %U vrf %d",
2360 s =
format (s,
"%U vrf %d external %U:%d",
2365 s =
format (s,
"\n local %U:%d probability %d\%",
2370 s =
format (s,
"%U local %U:%d external %U:%d vrf %d",
2385 s =
format (s,
"local %U external %U vrf %d",
2391 s =
format (s,
"%U local %U:%d external %U:%d vrf %d",
2405 u32 in_offset, out_offset;
2407 u32 *
i = va_arg (*args,
u32 *);
2410 in_addr.
as_u32 = clib_host_to_net_u32 (
2411 clib_net_to_host_u32(det_map->
in_addr.
as_u32) + user_index);
2412 in_offset = clib_net_to_host_u32(in_addr.
as_u32) -
2415 out_addr.
as_u32 = clib_host_to_net_u32(
2417 s =
format (s,
"in %U:%d out %U:%d external host %U:%d state: %U expire: %d\n",
2419 clib_net_to_host_u16 (ses->
in_port),
2443 u32 users_num = 0, sessions_num = 0, *worker, *sw_if_index;
2451 else if (
unformat (input,
"verbose"))
2457 vlib_cli_output (vm,
"NAT plugin mode: static mapping only connection " 2468 vlib_cli_output (vm,
"NAT plugin mode: dynamic translations enabled");
2475 vlib_cli_output (vm,
"%U %s", format_vnet_sw_interface_name, vnm,
2476 vnet_get_sw_interface (vnm, i->sw_if_index),
2477 i->is_inside ?
"in" :
"out");
2482 vlib_cli_output (vm,
"%U output-feature %s",
2483 format_vnet_sw_interface_name, vnm,
2484 vnet_get_sw_interface (vnm, i->sw_if_index),
2485 i->is_inside ?
"in" :
"out");
2506 #define _(N, i, n, s) \ 2507 vlib_cli_output (vm, " %d busy %s ports", ap->busy_##n##_ports, s); 2541 vlib_cli_output (vm,
"in %U/%d out %U/%d\n",
2542 format_ip4_address, &dm->in_addr, dm->in_plen,
2543 format_ip4_address, &dm->out_addr, dm->out_plen);
2544 vlib_cli_output (vm,
" outside address sharing ratio: %d\n",
2546 vlib_cli_output (vm,
" number of ports per inside host: %d\n",
2547 dm->ports_per_host);
2548 vlib_cli_output (vm,
" sessions number: %d\n", dm->ses_num);
2551 vec_foreach_index (j, dm->sessions)
2553 ses = vec_elt_at_index (dm->sessions, j);
2555 vlib_cli_output (vm,
" %U", format_det_map_ses, dm, ses,
2564 if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking))
2573 vlib_cli_output (vm,
"%U", format_snat_static_mapping, m);
2582 sessions_num +=
pool_elts (tsm->sessions);
2586 " %d static mappings",
2617 vlib_cli_output (vm,
" %U", format_snat_user, tsm, u,
2627 vlib_cli_output (vm,
"%U", format_snat_static_mapping, m);
2629 for (j = 0; j <
vec_len (sm->to_resolve); j++)
2631 rp = sm->to_resolve + j;
2643 .path =
"show nat44",
2644 .short_help =
"show nat44",
2655 u32 if_address_index,
2660 u32 *indices_to_delete = 0;
2700 if (
vec_len(indices_to_delete))
2703 for (j =
vec_len(indices_to_delete)-1; j >= 0; j--)
2724 u32 *indices_to_delete = 0;
2747 if (
vec_len(indices_to_delete))
2749 for (j =
vec_len(indices_to_delete)-1; j >= 0; j--)
2757 return VNET_API_ERROR_VALUE_EXIST;
2764 return VNET_API_ERROR_NO_SUCH_ENTRY;
2797 else if (
unformat (line_input,
"del"))
2827 .path =
"nat44 add interface address",
2828 .short_help =
"nat44 add interface address <interface> [del]",
2840 u32 in_plen, out_plen;
2854 else if (
unformat (line_input,
"del"))
2893 .path =
"nat44 deterministic add",
2894 .short_help =
"nat44 deterministic add in <addr>/<plen> out <addr>/<plen> [del]",
2955 .path =
"nat44 deterministic forward",
2956 .short_help =
"nat44 deterministic forward <addr>",
2989 if (out_port < 1024 || out_port > 65535)
3020 .path =
"nat44 deterministic reverse",
3021 .short_help =
"nat44 deterministic reverse <addr>:<port>",
3042 else if (
unformat (line_input,
"tcp-established %u",
3045 else if (
unformat (line_input,
"tcp-transitory %u",
3050 else if (
unformat (line_input,
"reset"))
3084 .path =
"set nat44 deterministic timeout",
3087 "set nat44 deterministic timeout [udp <sec> | tcp-established <sec> " 3088 "tcp-transitory <sec> | icmp <sec> | reset]",
3099 u32 out_port, ext_port;
3111 if (
unformat (line_input,
"%U:%d %U:%d",
3156 .path =
"nat44 deterministic close session out",
3157 .short_help =
"nat44 deterministic close session out " 3158 "<out_addr>:<out_port> <ext_addr>:<ext_port>",
3170 u32 in_port, ext_port;
3182 if (
unformat (line_input,
"%U:%d %U:%d",
3225 .path =
"nat44 deterministic close session in",
3226 .short_help =
"nat44 deterministic close session in " 3227 "<in_addr>:<in_port> <ext_addr>:<ext_port>",
ip4_address_t external_addr
int snat_add_interface_address(snat_main_t *sm, u32 sw_if_index, int is_del)
u8 * format_snat_user(u8 *s, va_list *args)
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
clib_error_t * snat_api_init(vlib_main_t *vm, snat_main_t *sm)
#define vec_foreach_index(var, v)
Iterate over vector indices.
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
u32 sessions_per_user_list_head_index
clib_bihash_16_8_t out2in_ed
sll srl srl sll sra u16x4 i
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Functions to call when interface address changes.
u8 * format_snat_protocol(u8 *s, va_list *args)
vnet_main_t * vnet_get_main(void)
u32 fq_in2out_output_index
#define SNAT_TCP_ESTABLISHED_TIMEOUT
ip4_address_t * ip4_interface_first_address(ip4_main_t *im, u32 sw_if_index, ip_interface_address_t **result_ia)
void snat_free_outside_address_and_port(snat_main_t *sm, u32 thread_index, snat_session_key_t *k, u32 address_index)
u32 vlib_frame_queue_main_init(u32 node_index, u32 frame_queue_nelts)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
static clib_error_t * snat_det_map_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static void snat_det_ses_close(snat_det_map_t *dm, snat_det_session_t *ses)
u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
static snat_det_session_t * snat_det_find_ses_by_in(snat_det_map_t *dm, ip4_address_t *in_addr, u16 in_port, snat_det_out_key_t out_key)
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
fib_node_index_t fib_table_entry_update_one_path(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, dpo_proto_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, mpls_label_t *next_hop_labels, fib_route_path_flags_t path_flags)
Update the entry to have just one path.
static void snat_det_forward(snat_det_map_t *dm, ip4_address_t *in_addr, ip4_address_t *out_addr, u16 *lo_port)
ip_lookup_main_t lookup_main
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
vlib_node_registration_t snat_det_out2in_node
(constructor) VLIB_REGISTER_NODE (snat_det_out2in_node)
unformat_function_t unformat_vnet_sw_interface
static_always_inline u16 snat_random_port(snat_main_t *sm, u16 min, u16 max)
clib_bihash_16_8_t in2out_ed
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.
snat_det_map_t * det_maps
static clib_error_t * snat_add_interface_address_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static void snat_ip4_add_del_interface_address_cb(ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 if_address_index, u32 is_delete)
static clib_error_t * snat_det_close_session_in_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
int snat_static_mapping_match(snat_main_t *sm, snat_session_key_t match, snat_session_key_t *mapping, u8 by_external, u8 *is_addr_only)
Match NAT44 static mapping.
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
static void snat_det_reverse(snat_det_map_t *dm, ip4_address_t *out_addr, u16 out_port, ip4_address_t *in_addr)
#define snat_is_unk_proto_session(s)
Check if SNAT session for unknown protocol.
u8 * format_snat_static_mapping(u8 *s, va_list *args)
u32 icmp_match_in2out_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation.
int snat_interface_add_del(u32 sw_if_index, u8 is_inside, int is_del)
nat44_lb_addr_port_t * locals
clib_bihash_8_8_t user_hash
u32 max_translations_per_user
static clib_error_t * snat_feature_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u32 in2out_output_node_index
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
#define static_always_inline
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
#define VLIB_INIT_FUNCTION(x)
vlib_node_registration_t snat_out2in_node
(constructor) VLIB_REGISTER_NODE (snat_out2in_node)
ip4_address_t ext_host_addr
static u32 snat_get_worker_in2out_cb(ip4_header_t *ip0, u32 rx_fib_index0)
#define SNAT_DET_SES_PER_USER
A high priority source a plugin can use.
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Aggregrate type for a prefix.
#define clib_error_return(e, args...)
int snat_ipfix_logging_enable_disable(int enable, u32 domain_id, u16 src_port)
Enable/disable NAT plugin IPFIX logging.
void snat_ipfix_logging_init(vlib_main_t *vm)
Initialize NAT plugin IPFIX logging.
u8 * format_snat_key(u8 *s, va_list *args)
static void * ip4_next_header(ip4_header_t *i)
static clib_error_t * add_address_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u16 fp_len
The mask length.
u32 icmp_match_out2in_det(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
VNET_FEATURE_INIT(ip4_snat_in2out, static)
vlib_worker_thread_t * vlib_worker_threads
format_function_t format_vnet_sw_interface_name
#define clib_bitmap_foreach(i, ai, body)
Macro to iterate across set bits in a bitmap.
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
static clib_error_t * snat_det_forward_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
uword * fib_index_by_table_id
Hash table mapping table id to fib index.
static uword clib_bitmap_last_set(uword *ai)
Return the higest numbered set bit in a bitmap.
static snat_det_map_t * snat_det_map_by_out(snat_main_t *sm, ip4_address_t *out_addr)
static clib_error_t * show_snat_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
snat_static_mapping_t * static_mappings
void snat_ipfix_logging_nat44_ses_delete(u32 src_ip, u32 nat_src_ip, snat_protocol_t snat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session delete event.
#define pool_put(P, E)
Free an object E in pool P.
#define VLIB_CONFIG_FUNCTION(x, n,...)
static clib_error_t * set_workers_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define vec_del1(v, i)
Delete the element at index I.
clib_bihash_8_8_t static_mapping_by_external
void fib_table_unlock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Take a reference counting lock on the table.
static clib_error_t * add_lb_static_mapping_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
snat_interface_t * output_feature_interfaces
static u32 random_u32_max(void)
Maximum value returned by random_u32()
static_always_inline uword vlib_get_thread_index(void)
vlib_node_registration_t snat_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_node)
u8 static_mapping_connection_tracking
snat_get_worker_function_t * worker_in2out_cb
#define vec_free(V)
Free vector's memory (no header).
void fib_table_entry_delete(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Delete a FIB entry.
ip4_add_del_interface_address_function_t * function
static ip4_fib_t * ip4_fib_get(u32 index)
Get the FIB at the given index.
deterministic NAT definitions
#define clib_warning(format, args...)
int snat_interface_add_del_output_feature(u32 sw_if_index, u8 is_inside, int is_del)
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
8 octet key, 8 octet key value pair
int snat_del_address(snat_main_t *sm, ip4_address_t addr, u8 delete_sm)
u32 icmp_match_in2out_slow(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
u32 tcp_transitory_timeout
int snat_det_add_map(snat_main_t *sm, ip4_address_t *in_addr, u8 in_plen, ip4_address_t *out_addr, u8 out_plen, int is_add)
Add/delete deterministic NAT mapping.
#define VLIB_CLI_COMMAND(x,...)
u32 * auto_add_sw_if_indices
int nat44_add_del_lb_static_mapping(ip4_address_t e_addr, u16 e_port, snat_protocol_t proto, u32 vrf_id, nat44_lb_addr_port_t *locals, u8 is_add)
static snat_det_map_t * snat_det_map_by_user(snat_main_t *sm, ip4_address_t *user_addr)
#define pool_put_index(p, i)
Free pool element with given index.
u8 * format_snat_static_map_to_resolve(u8 *s, va_list *args)
#define vec_delete(V, N, M)
Delete N elements starting at element M.
snat_get_worker_function_t * worker_out2in_cb
static u32 ip_proto_to_snat_proto(u8 ip_proto)
snat_icmp_match_function_t * icmp_match_out2in_cb
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.
#define clib_bitmap_free(v)
Free a bitmap.
uword * thread_registrations_by_name
static void clib_dlist_remove(dlist_elt_t *pool, u32 index)
#define VNET_FEATURES(...)
static clib_error_t * snat_init(vlib_main_t *vm)
static uword is_pow2(uword x)
vlib_node_registration_t snat_det_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_det_in2out_node)
u32 icmp_match_out2in_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation.
clib_error_t * nat64_init(vlib_main_t *vm)
Initialize NAT64.
NAT64 global declarations.
void increment_v4_address(ip4_address_t *a)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static clib_error_t * set_timeout_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static void snat_add_static_mapping_when_resolved(snat_main_t *sm, ip4_address_t l_addr, u16 l_port, u32 sw_if_index, u16 e_port, u32 vrf_id, snat_protocol_t proto, int addr_only, int is_add)
static uword unformat_bitmap_list(unformat_input_t *input, va_list *va)
unformat a list of bit ranges into a bitmap (eg "0-3,5-7,11" )
void snat_ipfix_logging_addresses_exhausted(u32 pool_id)
Generate NAT addresses exhausted event.
snat_main_per_thread_data_t * per_thread_data
static clib_error_t * snat_det_reverse_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
snat_address_t * addresses
u32 icmp_match_in2out_det(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
u8 * format_snat_session(u8 *s, va_list *args)
#define hash_get_mem(h, key)
u8 * format_det_map_ses(u8 *s, va_list *args)
#define SNAT_ICMP_TIMEOUT
uword unformat_snat_protocol(unformat_input_t *input, va_list *args)
static snat_det_session_t * snat_det_get_ses_by_out(snat_det_map_t *dm, ip4_address_t *in_addr, u64 out_key)
snat_static_map_resolve_t * to_resolve
static u32 random_u32(u32 *seed)
32-bit random number generator
ip4_main_t ip4_main
Global ip4 main structure.
static clib_error_t * snat_ipfix_logging_enable_disable_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static vlib_thread_main_t * vlib_get_thread_main()
u32 translation_memory_size
#define vec_foreach(var, vec)
Vector iterator.
vlib_node_registration_t snat_in2out_output_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_output_node)
static clib_error_t * snat_det_close_session_out_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
int snat_set_workers(uword *bitmap)
static clib_error_t * add_static_mapping_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
int snat_alloc_outside_address_and_port(snat_main_t *sm, u32 fib_index, u32 thread_index, snat_session_key_t *k, u32 *address_indexp)
static clib_error_t * snat_config(vlib_main_t *vm, unformat_input_t *input)
void snat_add_address(snat_main_t *sm, ip4_address_t *addr, u32 vrf_id)
int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, u32 vrf_id, int addr_only, u32 sw_if_index, snat_protocol_t proto, int is_add)
Add static mapping.
#define SNAT_TCP_TRANSITORY_TIMEOUT
ip_lookup_main_t * ip4_lookup_main
static int is_snat_address_used_in_static_mapping(snat_main_t *sm, ip4_address_t addr)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
snat_session_t * sessions
u8 * format_snat_session_state(u8 *s, va_list *args)
snat_icmp_match_function_t * icmp_match_in2out_cb
#define SNAT_SESSION_FLAG_LOAD_BALANCING
clib_bihash_8_8_t static_mapping_by_local
static u32 snat_get_worker_out2in_cb(ip4_header_t *ip0, u32 rx_fib_index0)
snat_interface_t * interfaces
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)
static_always_inline u8 icmp_is_error_message(icmp46_header_t *icmp)
u32 tcp_established_timeout
static uword pool_elts(void *v)
Number of active elements in a pool.