29 #include <vpp/app/version.h> 36 .arc_name =
"ip4-unicast",
37 .node_name =
"snat-in2out",
41 .arc_name =
"ip4-unicast",
42 .node_name =
"snat-out2in",
46 .arc_name =
"ip4-unicast",
47 .node_name =
"snat-det-in2out",
51 .arc_name =
"ip4-unicast",
52 .node_name =
"snat-det-out2in",
56 .arc_name =
"ip4-unicast",
57 .node_name =
"snat-in2out-worker-handoff",
61 .arc_name =
"ip4-unicast",
62 .node_name =
"snat-out2in-worker-handoff",
66 .arc_name =
"ip4-unicast",
67 .node_name =
"snat-in2out-fast",
71 .arc_name =
"ip4-unicast",
72 .node_name =
"snat-out2in-fast",
78 .version = VPP_BUILD_VER,
79 .description =
"Network Address Translation",
103 .ip4.as_u32 = addr->
as_u32,
146 #define _(N, i, n, s) \ 147 clib_bitmap_alloc (ap->busy_##n##_port_bitmap, 65535); 157 snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1);
168 if (m->external_addr.as_u32 == addr.as_u32)
179 v = clib_net_to_host_u32(a->
as_u32) + 1;
180 a->
as_u32 = clib_host_to_net_u32(v);
224 u16 l_port,
u16 e_port,
u32 vrf_id,
int addr_only,
238 if (sw_if_index != ~0)
244 (sm->ip4_main, sw_if_index, 0 );
247 if (first_int_addr == 0)
250 (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
259 m_key.
port = addr_only ? 0 : e_port;
260 m_key.
protocol = addr_only ? 0 : proto;
263 if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
271 return VNET_API_ERROR_VALUE_EXIST;
276 p =
hash_get (sm->ip4_main->fib_index_by_table_id, vrf_id);
278 return VNET_API_ERROR_NO_SUCH_FIB;
284 fib_index = sm->inside_fib_index;
285 vrf_id = sm->inside_vrf_id;
290 if (!addr_only && !(sm->static_mapping_only))
292 for (i = 0; i <
vec_len (sm->addresses); i++)
294 if (sm->addresses[i].addr.as_u32 == e_addr.
as_u32)
296 a = sm->addresses +
i;
300 #define _(N, j, n, s) \ 301 case SNAT_PROTOCOL_##N: \ 302 if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \ 303 return VNET_API_ERROR_INVALID_VALUE; \ 304 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \ 306 a->busy_##n##_ports++; \ 312 return VNET_API_ERROR_INVALID_VALUE_2;
319 return VNET_API_ERROR_NO_SUCH_ENTRY;
323 memset (m, 0,
sizeof (*m));
341 kv.
value = m - sm->static_mappings;
342 clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 1);
348 kv.
value = m - sm->static_mappings;
349 clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 1);
361 if (clib_bihash_search_8_8 (&sm->worker_by_in, &kv, &value))
363 kv.
value = sm->first_worker_index +
364 sm->workers[sm->next_worker++ %
vec_len (sm->workers)];
366 clib_bihash_add_del_8_8 (&sm->worker_by_in, &kv, 1);
375 w_key1.
fib_index = sm->outside_fib_index;
377 clib_bihash_add_del_8_8 (&sm->worker_by_out, &kv, 1);
383 return VNET_API_ERROR_NO_SUCH_ENTRY;
386 if (!addr_only && !(sm->static_mapping_only))
388 for (i = 0; i <
vec_len (sm->addresses); i++)
390 if (sm->addresses[i].addr.as_u32 == e_addr.
as_u32)
392 a = sm->addresses +
i;
395 #define _(N, j, n, s) \ 396 case SNAT_PROTOCOL_##N: \ 397 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \ 399 a->busy_##n##_ports--; \ 405 return VNET_API_ERROR_INVALID_VALUE_2;
417 clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0);
423 clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 0);
426 if (!(sm->static_mapping_only) ||
427 (sm->static_mapping_only && sm->static_mapping_connection_tracking))
432 u32 elt_index, head_index, del_elt_index;
441 if (!clib_bihash_search_8_8 (&sm->user_hash, &kv, &value))
443 user_index = value.
value;
444 if (!clib_bihash_search_8_8 (&sm->worker_by_in, &kv, &value))
453 elt_index = head->
next;
455 ses_index = elt->
value;
456 while (ses_index != ~0)
459 del_elt_index = elt_index;
460 elt_index = elt->
next;
462 ses_index = elt->
value;
466 if ((s->out2in.addr.as_u32 != e_addr.
as_u32) &&
467 (clib_net_to_host_u16 (s->out2in.port) != e_port))
473 s->out2in.addr.as_u32,
477 s->in2out.fib_index);
479 value.
key = s->in2out.as_u64;
480 clib_bihash_add_del_8_8 (&sm->in2out, &value, 0);
481 value.
key = s->out2in.as_u64;
482 clib_bihash_add_del_8_8 (&sm->out2in, &value, 0);
495 clib_bihash_add_del_8_8 (&sm->user_hash, &kv, 0);
511 if (interface->is_inside)
514 snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
525 u32 *ses_to_be_removed = 0, *ses_index;
535 for (i=0; i <
vec_len (sm->addresses); i++)
537 if (sm->addresses[i].addr.as_u32 == addr.
as_u32)
539 a = sm->addresses +
i;
544 return VNET_API_ERROR_NO_SUCH_ENTRY;
550 if (m->external_addr.as_u32 == addr.as_u32)
551 (void) snat_add_static_mapping (m->local_addr, m->external_addr,
552 m->local_port, m->external_port,
553 m->vrf_id, m->addr_only, ~0,
563 return VNET_API_ERROR_UNSPECIFIED;
568 if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
573 if (ses->out2in.addr.as_u32 == addr.as_u32)
576 snat_ipfix_logging_nat44_ses_delete(ses->in2out.addr.as_u32,
577 ses->out2in.addr.as_u32,
578 ses->in2out.protocol,
581 ses->in2out.fib_index);
582 vec_add1 (ses_to_be_removed, ses - tsm->sessions);
583 kv.key = ses->in2out.as_u64;
584 clib_bihash_add_del_8_8 (&sm->in2out, &kv, 0);
585 kv.key = ses->out2in.as_u64;
586 clib_bihash_add_del_8_8 (&sm->out2in, &kv, 0);
587 clib_dlist_remove (tsm->list_pool, ses->per_user_index);
588 user_key.addr = ses->in2out.addr;
589 user_key.fib_index = ses->in2out.fib_index;
590 kv.key = user_key.as_u64;
591 if (!clib_bihash_search_8_8 (&sm->user_hash, &kv, &value))
593 u = pool_elt_at_index (tsm->users, value.value);
611 if (interface->is_inside)
614 snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
625 const char * feature_name;
630 if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking))
631 feature_name = is_inside ?
"snat-in2out-fast" :
"snat-out2in-fast";
634 if (sm->num_workers > 1 && !sm->deterministic)
635 feature_name = is_inside ?
"snat-in2out-worker-handoff" :
"snat-out2in-worker-handoff";
636 else if (sm->deterministic)
637 feature_name = is_inside ?
"snat-det-in2out" :
"snat-det-out2in";
639 feature_name = is_inside ?
"snat-in2out" :
"snat-out2in";
645 if (sm->fq_in2out_index == ~0 && !sm->deterministic && sm->num_workers > 1)
648 if (sm->fq_out2in_index == ~0 && !sm->deterministic && sm->num_workers > 1)
653 if (i->sw_if_index == sw_if_index)
656 pool_put (sm->interfaces, i);
658 return VNET_API_ERROR_VALUE_EXIST;
665 return VNET_API_ERROR_NO_SUCH_ENTRY;
668 i->sw_if_index = sw_if_index;
669 i->is_inside = is_inside;
684 snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
689 snat_add_del_addr_to_fib(&dm->out_addr, dm->out_plen, sw_if_index, !is_del);
700 if (sm->num_workers < 2)
701 return VNET_API_ERROR_FEATURE_DISABLED;
704 return VNET_API_ERROR_INVALID_WORKER;
722 u32 if_address_index,
741 sm->ip4_lookup_main = lm;
743 sm->first_worker_index = 0;
747 sm->fq_in2out_index = ~0;
748 sm->fq_out2in_index = ~0;
760 sm->num_workers = tr->
count;
766 if (sm->num_workers > 1)
768 for (i=0; i < sm->num_workers; i++)
799 u16 port_host_byte_order = clib_net_to_host_u16 (k->
port);
803 a = sm->addresses + address_index;
807 #define _(N, i, n, s) \ 808 case SNAT_PROTOCOL_##N: \ 809 ASSERT (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \ 810 port_host_byte_order) == 1); \ 811 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \ 812 port_host_byte_order, 0); \ 813 a->busy_##n##_ports--; \ 844 clib_bihash_8_8_t *mapping_hash = &sm->static_mapping_by_local;
847 mapping_hash = &sm->static_mapping_by_external;
850 m_key.
port = clib_net_to_host_u16 (match.
port);
856 if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
862 if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
882 mapping->
fib_index = sm->outside_fib_index;
894 u32 * address_indexp)
900 for (i = 0; i <
vec_len (sm->addresses); i++)
902 a = sm->addresses +
i;
907 #define _(N, j, n, s) \ 908 case SNAT_PROTOCOL_##N: \ 909 if (a->busy_##n##_ports < (65535-1024)) \ 913 portnum = random_u32 (&sm->random_seed); \ 915 if (portnum < 1024) \ 917 if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \ 919 clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \ 920 a->busy_##n##_ports++; \ 922 k->port = clib_host_to_net_u16(portnum); \ 923 *address_indexp = i; \ 950 u32 start_host_order, end_host_order;
963 if (
unformat (line_input,
"%U - %U",
967 else if (
unformat (line_input,
"tenant-vrf %u", &vrf_id))
970 end_addr = start_addr;
971 else if (
unformat (line_input,
"del"))
981 if (sm->static_mapping_only)
987 start_host_order = clib_host_to_net_u32 (start_addr.
as_u32);
988 end_host_order = clib_host_to_net_u32 (end_addr.
as_u32);
990 if (end_host_order < start_host_order)
996 count = (end_host_order - start_host_order) + 1;
1004 this_addr = start_addr;
1006 for (i = 0; i < count; i++)
1015 case VNET_API_ERROR_NO_SUCH_ENTRY:
1018 case VNET_API_ERROR_UNSPECIFIED:
1035 .path =
"snat add address",
1036 .short_help =
"snat add addresses <ip4-range-start> [- <ip4-range-end>] " 1037 "[tenant-vrf <vrf-id>] [del]",
1050 u32 * inside_sw_if_indices = 0;
1051 u32 * outside_sw_if_indices = 0;
1065 vec_add1 (inside_sw_if_indices, sw_if_index);
1068 vec_add1 (outside_sw_if_indices, sw_if_index);
1069 else if (
unformat (line_input,
"del"))
1079 if (
vec_len (inside_sw_if_indices))
1081 for (i = 0; i <
vec_len(inside_sw_if_indices); i++)
1083 sw_if_index = inside_sw_if_indices[
i];
1088 if (
vec_len (outside_sw_if_indices))
1090 for (i = 0; i <
vec_len(outside_sw_if_indices); i++)
1092 sw_if_index = outside_sw_if_indices[
i];
1106 .path =
"set interface snat",
1108 .short_help =
"set interface snat in <intfc> out <intfc> [del]",
1114 u32 *r = va_arg (*args,
u32 *);
1117 #define _(N, i, n, s) else if (unformat (input, s)) *r = SNAT_PROTOCOL_##N; 1133 #define _(N, j, n, str) case SNAT_PROTOCOL_##N: t = (u8 *) str; break; 1137 s =
format (s,
"unknown");
1151 u32 l_port = 0, e_port = 0, vrf_id = ~0;
1154 u32 sw_if_index = ~0;
1177 else if (
unformat (line_input,
"external %U %u",
1182 else if (
unformat (line_input,
"external %U",
1185 else if (
unformat (line_input,
"vrf %u", &vrf_id))
1189 else if (
unformat (line_input,
"del"))
1199 if (!addr_only && !proto_set)
1206 vrf_id, addr_only, sw_if_index, proto, is_add);
1210 case VNET_API_ERROR_INVALID_VALUE:
1213 case VNET_API_ERROR_NO_SUCH_ENTRY:
1219 case VNET_API_ERROR_NO_SUCH_FIB:
1222 case VNET_API_ERROR_VALUE_EXIST:
1250 .path =
"snat add static mapping",
1253 "snat add static mapping local tcp|udp|icmp <addr> [<port>] external <addr> [<port>] [vrf <table-id>] [del]",
1294 case VNET_API_ERROR_INVALID_WORKER:
1297 case VNET_API_ERROR_FEATURE_DISABLED:
1299 "Supported only if 2 or more workes available.");
1319 .path =
"set snat workers",
1322 "set snat workers <workers-list>",
1343 if (
unformat (line_input,
"domain %d", &domain_id))
1345 else if (
unformat (line_input,
"src-port %d", &src_port))
1347 else if (
unformat (line_input,
"disable"))
1381 .path =
"snat ipfix logging",
1383 .short_help =
"snat ipfix logging [domain <domain-id>] [src-port <port>] [disable]",
1392 u32 next_worker_index = 0;
1400 if (clib_bihash_search_8_8 (&sm->worker_by_in, &kv0, &value0))
1403 next_worker_index = sm->first_worker_index;
1406 next_worker_index +=
1407 sm->workers[sm->next_worker++ % _vec_len (sm->workers)];
1411 kv0.
value = next_worker_index;
1412 clib_bihash_add_del_8_8 (&sm->worker_by_in, &kv0, 1);
1415 next_worker_index = value0.
value;
1417 return next_worker_index;
1427 u32 next_worker_index = 0;
1437 icmp46_header_t * icmp0 = (icmp46_header_t *) udp0;
1445 if (clib_bihash_search_8_8 (&sm->worker_by_out, &kv0, &value0))
1450 if (clib_bihash_search_8_8 (&sm->worker_by_out, &kv0, &value0))
1453 next_worker_index = sm->first_worker_index;
1456 next_worker_index +=
1457 sm->workers[sm->next_worker++ % _vec_len (sm->workers)];
1463 next_worker_index = value0.
value;
1467 kv0.
value = next_worker_index;
1468 clib_bihash_add_del_8_8 (&sm->worker_by_out, &kv0, 1);
1471 next_worker_index = value0.
value;
1473 return next_worker_index;
1480 u32 translation_buckets = 1024;
1481 u32 translation_memory_size = 128<<20;
1482 u32 user_buckets = 128;
1483 u32 user_memory_size = 64<<20;
1484 u32 max_translations_per_user = 100;
1485 u32 outside_vrf_id = 0;
1486 u32 inside_vrf_id = 0;
1487 u32 static_mapping_buckets = 1024;
1488 u32 static_mapping_memory_size = 64<<20;
1489 u8 static_mapping_only = 0;
1490 u8 static_mapping_connection_tracking = 0;
1493 sm->deterministic = 0;
1497 if (
unformat (input,
"translation hash buckets %d", &translation_buckets))
1499 else if (
unformat (input,
"translation hash memory %d",
1500 &translation_memory_size));
1501 else if (
unformat (input,
"user hash buckets %d", &user_buckets))
1503 else if (
unformat (input,
"user hash memory %d",
1506 else if (
unformat (input,
"max translations per user %d",
1507 &max_translations_per_user))
1509 else if (
unformat (input,
"outside VRF id %d",
1512 else if (
unformat (input,
"inside VRF id %d",
1515 else if (
unformat (input,
"static mapping only"))
1517 static_mapping_only = 1;
1518 if (
unformat (input,
"connection tracking"))
1519 static_mapping_connection_tracking = 1;
1521 else if (
unformat (input,
"deterministic"))
1522 sm->deterministic = 1;
1529 sm->translation_buckets = translation_buckets;
1530 sm->translation_memory_size = translation_memory_size;
1531 sm->user_buckets = user_buckets;
1532 sm->user_memory_size = user_memory_size;
1533 sm->max_translations_per_user = max_translations_per_user;
1534 sm->outside_vrf_id = outside_vrf_id;
1537 sm->inside_vrf_id = inside_vrf_id;
1540 sm->static_mapping_only = static_mapping_only;
1541 sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
1543 if (sm->deterministic)
1556 if (!static_mapping_only ||
1557 (static_mapping_only && static_mapping_connection_tracking))
1562 clib_bihash_init_8_8 (&sm->worker_by_in,
"worker-by-in", user_buckets,
1565 clib_bihash_init_8_8 (&sm->worker_by_out,
"worker-by-out", user_buckets,
1570 clib_bihash_init_8_8 (&sm->in2out,
"in2out", translation_buckets,
1571 translation_memory_size);
1573 clib_bihash_init_8_8 (&sm->out2in,
"out2in", translation_buckets,
1574 translation_memory_size);
1576 clib_bihash_init_8_8 (&sm->user_hash,
"users", user_buckets,
1584 clib_bihash_init_8_8 (&sm->static_mapping_by_local,
1585 "static_mapping_by_local", static_mapping_buckets,
1586 static_mapping_memory_size);
1588 clib_bihash_init_8_8 (&sm->static_mapping_by_external,
1589 "static_mapping_by_external", static_mapping_buckets,
1590 static_mapping_memory_size);
1605 #define _(v, N, str) case SNAT_SESSION_##N: t = (u8 *) str; break; 1609 t =
format (t,
"unknown");
1618 char * protocol_string =
"unknown";
1619 static char *protocol_strings[] = {
1626 protocol_string = protocol_strings[key->
protocol];
1628 s =
format (s,
"%U proto %s port %d fib %d",
1637 snat_session_t * sess = va_arg (*args, snat_session_t *);
1641 s =
format (s,
" last heard %.2f\n", sess->last_heard);
1642 s =
format (s,
" total pkts %d, total bytes %lld\n",
1643 sess->total_pkts, sess->total_bytes);
1645 s =
format (s,
" static translation\n");
1647 s =
format (s,
" dynamic translation\n");
1656 int verbose = va_arg (*args,
int);
1658 u32 elt_index, head_index;
1660 snat_session_t * sess;
1662 s =
format (s,
"%U: %d dynamic translations, %d static translations\n",
1673 elt_index = head->
next;
1675 session_index = elt->
value;
1677 while (session_index != ~0)
1683 elt_index = elt->
next;
1685 session_index = elt->
value;
1697 s =
format (s,
"local %U external %U vrf %d",
1702 s =
format (s,
"%U local %U:%d external %U:%d vrf %d",
1717 s =
format (s,
"local %U external %U vrf %d",
1723 s =
format (s,
"%U local %U:%d external %U:%d vrf %d",
1737 u32 in_offset, out_offset;
1739 u32 *
i = va_arg (*args,
u32 *);
1742 in_addr.
as_u32 = clib_host_to_net_u32 (
1743 clib_net_to_host_u32(det_map->
in_addr.
as_u32) + user_index);
1744 in_offset = clib_net_to_host_u32(in_addr.
as_u32) -
1747 out_addr.
as_u32 = clib_host_to_net_u32(
1749 s =
format (s,
"in %U:%d out %U:%d external host %U:%d state: %U expire: %d\n",
1751 clib_net_to_host_u16 (ses->
in_port),
1775 u32 users_num = 0, sessions_num = 0, *worker, *sw_if_index;
1783 else if (
unformat (input,
"verbose"))
1786 if (sm->static_mapping_only)
1788 if (sm->static_mapping_connection_tracking)
1794 else if (sm->deterministic)
1807 vlib_cli_output (vm,
"%U %s", format_vnet_sw_interface_name, vnm,
1808 vnet_get_sw_interface (vnm, i->sw_if_index),
1809 i->is_inside ?
"in" :
"out");
1812 if (
vec_len (sm->auto_add_sw_if_indices))
1815 vec_foreach (sw_if_index, sm->auto_add_sw_if_indices)
1830 #define _(N, i, n, s) \ 1831 vlib_cli_output (vm, " %d busy %s ports", ap->busy_##n##_ports, s); 1837 if (sm->num_workers > 1)
1851 if (sm->deterministic)
1855 sm->tcp_established_timeout);
1857 sm->tcp_transitory_timeout);
1865 vlib_cli_output (vm,
"in %U/%d out %U/%d\n",
1866 format_ip4_address, &dm->in_addr, dm->in_plen,
1867 format_ip4_address, &dm->out_addr, dm->out_plen);
1868 vlib_cli_output (vm,
" outside address sharing ratio: %d\n",
1870 vlib_cli_output (vm,
" number of ports per inside host: %d\n",
1871 dm->ports_per_host);
1872 vlib_cli_output (vm,
" sessions number: %d\n", dm->ses_num);
1875 vec_foreach_index (j, dm->sessions)
1877 ses = vec_elt_at_index (dm->sessions, j);
1879 vlib_cli_output (vm,
" %U", format_det_map_ses, dm, ses,
1888 if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking))
1897 vlib_cli_output (vm,
"%U", format_snat_static_mapping, m);
1906 sessions_num +=
pool_elts (tsm->sessions);
1909 vlib_cli_output (vm,
"%d users, %d outside addresses, %d active sessions," 1910 " %d static mappings",
1941 vlib_cli_output (vm,
" %U", format_snat_user, tsm, u,
1951 vlib_cli_output (vm,
"%U", format_snat_static_mapping, m);
1953 for (j = 0; j <
vec_len (sm->to_resolve); j++)
1955 rp = sm->to_resolve + j;
1967 .path =
"show snat",
1968 .short_help =
"show snat",
1979 u32 if_address_index,
1984 u32 *indices_to_delete = 0;
1988 for (i = 0; i <
vec_len(sm->auto_add_sw_if_indices); i++)
1990 if (sw_if_index == sm->auto_add_sw_if_indices[i])
1995 for (j = 0; j <
vec_len(sm->addresses); j++)
1996 if (sm->addresses[j].addr.as_u32 == address->
as_u32)
2001 for (j = 0; j <
vec_len (sm->to_resolve); j++)
2003 rp = sm->to_resolve + j;
2024 if (
vec_len(indices_to_delete))
2027 for (j =
vec_len(indices_to_delete)-1; j >= 0; j--)
2048 u32 *indices_to_delete = 0;
2054 for (i = 0; i <
vec_len(sm->auto_add_sw_if_indices); i++)
2056 if (sm->auto_add_sw_if_indices[i] == sw_if_index)
2065 for (j = 0; j <
vec_len (sm->to_resolve); j++)
2067 rp = sm->to_resolve + j;
2071 if (
vec_len(indices_to_delete))
2073 for (j =
vec_len(indices_to_delete)-1; j >= 0; j--)
2078 vec_del1(sm->auto_add_sw_if_indices, i);
2081 return VNET_API_ERROR_VALUE_EXIST;
2088 return VNET_API_ERROR_NO_SUCH_ENTRY;
2091 vec_add1(sm->auto_add_sw_if_indices, sw_if_index);
2119 sm->vnet_main, &sw_if_index))
2121 else if (
unformat (line_input,
"del"))
2151 .path =
"snat add interface address",
2152 .short_help =
"snat add interface address <interface> [del]",
2164 u32 in_plen, out_plen;
2178 else if (
unformat (line_input,
"del"))
2217 .path =
"snat deterministic add",
2218 .short_help =
"snat deterministic add in <addr>/<plen> out <addr>/<plen> [del]",
2279 .path =
"snat deterministic forward",
2280 .short_help =
"snat deterministic forward <addr>",
2313 if (out_port < 1024 || out_port > 65535)
2344 .path =
"snat deterministic reverse",
2345 .short_help =
"snat deterministic reverse <addr>:<port>",
2364 if (
unformat (line_input,
"udp %u", &sm->udp_timeout))
2366 else if (
unformat (line_input,
"tcp-established %u",
2367 &sm->tcp_established_timeout))
2369 else if (
unformat (line_input,
"tcp-transitory %u",
2370 &sm->tcp_transitory_timeout))
2372 else if (
unformat (line_input,
"icmp %u", &sm->icmp_timeout))
2374 else if (
unformat (line_input,
"reset"))
2408 .path =
"set snat deterministic timeout",
2411 "set snat deterministic timeout [udp <sec> | tcp-established <sec> " 2412 "tcp-transitory <sec> | icmp <sec> | reset]",
2423 u16 out_port, ext_port;
2435 if (
unformat (line_input,
"%U:%d %U:%d",
2480 .path =
"snat deterministic close session out",
2481 .short_help =
"snat deterministic close session out " 2482 "<out_addr>:<out_port> <ext_addr>:<ext_port>",
2494 u16 in_port, ext_port;
2506 if (
unformat (line_input,
"%U:%d %U:%d",
2549 .path =
"snat deterministic close session in",
2550 .short_help =
"snat deterministic close session in " 2551 "<in_addr>:<in_port> <ext_addr>:<ext_port>",
ip4_address_t external_addr
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
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, fib_protocol_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.
#define vec_foreach_index(var, v)
Iterate over vector indices.
u32 sessions_per_user_list_head_index
void snat_add_address(snat_main_t *sm, ip4_address_t *addr, u32 vrf_id)
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_session_state(u8 *s, va_list *args)
vnet_main_t * vnet_get_main(void)
u32 icmp_match_in2out_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, 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 packet SNAT translation.
int snat_alloc_outside_address_and_port(snat_main_t *sm, u32 fib_index, snat_session_key_t *k, u32 *address_indexp)
ip4_address_t * ip4_interface_first_address(ip4_main_t *im, u32 sw_if_index, ip_interface_address_t **result_ia)
static void snat_det_reverse(snat_det_map_t *dm, ip4_address_t *out_addr, u16 out_port, ip4_address_t *in_addr)
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 snat_det_map_t * snat_det_map_by_out(snat_main_t *sm, ip4_address_t *out_addr)
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
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. ...
u8 * format_snat_static_map_to_resolve(u8 *s, va_list *args)
ip_lookup_main_t lookup_main
static void snat_det_forward(snat_det_map_t *dm, ip4_address_t *in_addr, ip4_address_t *out_addr, u16 *lo_port)
void snat_ipfix_logging_init(vlib_main_t *vm)
Initialize SNAT IPFIX logging.
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
int snat_ipfix_logging_enable_disable(int enable, u32 domain_id, u16 src_port)
Enable/disable SNAT IPFIX logging.
unformat_function_t unformat_vnet_sw_interface
static u32 snat_get_worker_in2out_cb(ip4_header_t *ip0, u32 rx_fib_index0)
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_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
static clib_error_t * snat_init(vlib_main_t *vm)
static clib_error_t * add_address_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static clib_error_t * set_timeout_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u8 * format_snat_key(u8 *s, va_list *args)
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
void increment_v4_address(ip4_address_t *a)
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)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
vlib_node_registration_t snat_det_out2in_node
(constructor) VLIB_REGISTER_NODE (snat_det_out2in_node)
#define VLIB_INIT_FUNCTION(x)
ip4_address_t ext_host_addr
#define SNAT_ICMP_TIMEOUT
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)
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)
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...)
static void * ip4_next_header(ip4_header_t *i)
static clib_error_t * snat_det_forward_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static clib_error_t * snat_ipfix_logging_enable_disable_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u16 fp_len
The mask length.
uword unformat_snat_protocol(unformat_input_t *input, va_list *args)
#define SNAT_TCP_TRANSITORY_TIMEOUT
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.
deterministic NAT definitions
static uword clib_bitmap_last_set(uword *ai)
Return the higest numbered set bit in a bitmap.
static u32 snat_get_worker_out2in_cb(ip4_header_t *ip0, u32 rx_fib_index0)
static int is_snat_address_used_in_static_mapping(snat_main_t *sm, ip4_address_t addr)
#define pool_put(P, E)
Free an object E in pool P.
#define VLIB_CONFIG_FUNCTION(x, n,...)
#define vec_del1(v, i)
Delete the element at index I.
int snat_del_address(snat_main_t *sm, ip4_address_t addr, u8 delete_sm)
vlib_node_registration_t snat_out2in_node
(constructor) VLIB_REGISTER_NODE (snat_out2in_node)
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 SNAT static mapping.
static clib_error_t * snat_add_interface_address_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u8 * format_snat_session(u8 *s, va_list *args)
#define SNAT_DET_SES_PER_USER
VNET_FEATURE_INIT(ip4_snat_in2out, static)
u32 icmp_match_in2out_slow(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, 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 packet SNAT translation and create session if needed...
static clib_error_t * show_snat_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
vlib_node_registration_t snat_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_node)
#define vec_free(V)
Free vector's memory (no header).
static clib_error_t * add_static_mapping_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
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.
u8 * format_snat_protocol(u8 *s, va_list *args)
#define clib_warning(format, args...)
int snat_set_workers(uword *bitmap)
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.
static clib_error_t * snat_config(vlib_main_t *vm, unformat_input_t *input)
static u32 ip4_fib_index_from_table_id(u32 table_id)
8 octet key, 8 octet key value pair
u32 icmp_match_out2in_det(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, 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 packet SNAT translation and create session if needed...
clib_error_t * snat_api_init(vlib_main_t *vm, snat_main_t *sm)
#define VLIB_CLI_COMMAND(x,...)
void snat_ipfix_logging_addresses_exhausted(u32 pool_id)
Generate NAT addresses exhausted event.
#define pool_put_index(p, i)
Free pool element with given index.
static clib_error_t * snat_det_map_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define vec_delete(V, N, M)
Delete N elements starting at element M.
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.
u8 * format_snat_static_mapping(u8 *s, va_list *args)
u32 icmp_match_in2out_det(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, 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 packet SNAT translation and create session if needed...
u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, 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 packet SNAT translation and create session if needed...
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id)
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)
u8 * format_det_map_ses(u8 *s, va_list *args)
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 snat_det_session_t * snat_det_get_ses_by_out(snat_det_map_t *dm, ip4_address_t *in_addr, u64 out_key)
#define VNET_FEATURES(...)
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.
vlib_node_registration_t snat_det_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_det_in2out_node)
clib_error_t * nat64_init(vlib_main_t *vm)
Initialize NAT64.
NAT64 global declarations.
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static snat_det_map_t * snat_det_map_by_user(snat_main_t *sm, ip4_address_t *user_addr)
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" )
static clib_error_t * snat_det_close_session_out_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
void snat_free_outside_address_and_port(snat_main_t *sm, snat_session_key_t *k, u32 address_index)
#define hash_get_mem(h, key)
static void snat_det_ses_close(snat_det_map_t *dm, snat_det_session_t *ses)
ip4_main_t ip4_main
Global ip4 main structure.
u32 icmp_match_out2in_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, 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 packet SNAT translation.
static vlib_thread_main_t * vlib_get_thread_main()
#define vec_foreach(var, vec)
Vector iterator.
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_interface_add_del(u32 sw_if_index, u8 is_inside, int is_del)
static clib_error_t * snat_det_reverse_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
snat_session_t * sessions
static clib_error_t * snat_feature_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
static clib_error_t * set_workers_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define SNAT_TCP_ESTABLISHED_TIMEOUT
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 uword pool_elts(void *v)
Number of active elements in a pool.