19 #include <vpp/app/version.h> 49 #define skip_if_disabled() \ 52 nat44_ei_main_t *nm = &nat44_ei_main; \ 53 if (PREDICT_FALSE (!nm->enabled)) \ 58 #define fail_if_enabled() \ 61 nat44_ei_main_t *nm = &nat44_ei_main; \ 62 if (PREDICT_FALSE (nm->enabled)) \ 64 nat44_ei_log_err ("plugin enabled"); \ 70 #define fail_if_disabled() \ 73 nat44_ei_main_t *nm = &nat44_ei_main; \ 74 if (PREDICT_FALSE (!nm->enabled)) \ 76 nat44_ei_log_err ("plugin disabled"); \ 84 .arc_name =
"ip4-unicast",
85 .node_name =
"nat44-ei-classify",
87 "ip4-sv-reassembly-feature"),
90 .arc_name =
"ip4-unicast",
91 .node_name =
"nat44-ei-handoff-classify",
93 "ip4-sv-reassembly-feature"),
96 .arc_name =
"ip4-unicast",
97 .node_name =
"nat44-ei-in2out",
99 "ip4-sv-reassembly-feature"),
102 .arc_name =
"ip4-unicast",
103 .node_name =
"nat44-ei-out2in",
105 "ip4-sv-reassembly-feature",
106 "ip4-dhcp-client-detect"),
109 .arc_name =
"ip4-output",
110 .node_name =
"nat44-ei-in2out-output",
112 "ip4-sv-reassembly-output-feature"),
115 .arc_name =
"ip4-unicast",
116 .node_name =
"nat44-ei-in2out-fast",
118 "ip4-sv-reassembly-feature"),
121 .arc_name =
"ip4-unicast",
122 .node_name =
"nat44-ei-out2in-fast",
124 "ip4-sv-reassembly-feature",
125 "ip4-dhcp-client-detect"),
128 .arc_name =
"ip4-unicast",
129 .node_name =
"nat44-ei-hairpin-dst",
131 "ip4-sv-reassembly-feature"),
134 .arc_name =
"ip4-output",
135 .node_name =
"nat44-ei-hairpin-src",
137 "ip4-sv-reassembly-output-feature"),
140 .arc_name =
"ip4-local",
141 .node_name =
"nat44-ei-hairpinning",
145 .arc_name =
"ip4-unicast",
146 .node_name =
"nat44-ei-in2out-worker-handoff",
150 .arc_name =
"ip4-unicast",
151 .node_name =
"nat44-ei-out2in-worker-handoff",
153 "ip4-dhcp-client-detect"),
156 .arc_name =
"ip4-output",
157 .node_name =
"nat44-ei-in2out-output-worker-handoff",
159 "ip4-sv-reassembly-output-feature"),
163 .version = VPP_BUILD_VER,
164 .description =
"IPv4 Endpoint-Independent NAT (NAT44 EI)",
167 #define foreach_nat44_ei_classify_error \ 168 _ (NEXT_IN2OUT, "next in2out") \ 169 _ (NEXT_OUT2IN, "next out2in") \ 170 _ (FRAG_CACHED, "fragment cached") 174 #define _(sym, str) NAT44_EI_CLASSIFY_ERROR_##sym, 181 #define _(sym, string) string, 212 s =
format (s,
"nat44-ei-classify: fragment cached");
215 next = t->
next_in2out ?
"nat44-ei-in2out" :
"nat44-ei-out2in";
216 s =
format (s,
"nat44-ei-classify: next %s", next);
229 u32 address_length,
u32 if_address_index,
u32 is_delete);
233 u32 address_length,
u32 if_address_index,
u32 is_delete);
258 return VNET_API_ERROR_FEATURE_DISABLED;
261 return VNET_API_ERROR_INVALID_WORKER;
277 #define nat_validate_simple_counter(c, i) \ 280 vlib_validate_simple_counter (&c, i); \ 281 vlib_zero_simple_counter (&c, i); \ 285 #define nat_init_simple_counter(c, n, sn) \ 289 c.stat_segment_name = sn; \ 290 nat_validate_simple_counter (c, 0); \ 298 nat_validate_simple_counter (nm->counters.fastpath.in2out.x, sw_if_index); \ 299 nat_validate_simple_counter (nm->counters.fastpath.out2in.x, sw_if_index); \ 300 nat_validate_simple_counter (nm->counters.slowpath.in2out.x, sw_if_index); \ 301 nat_validate_simple_counter (nm->counters.slowpath.out2in.x, sw_if_index); 315 u32 i, num_threads = 0;
316 uword *p, *bitmap = 0;
338 "/nat44-ei/total-users");
340 "/nat44-ei/total-sessions");
342 "/nat44-ei/user-limit-reached");
345 nat_init_simple_counter (nm->counters.fastpath.in2out.x, #x, \ 346 "/nat44-ei/in2out/fastpath/" #x); \ 347 nat_init_simple_counter (nm->counters.fastpath.out2in.x, #x, \ 348 "/nat44-ei/out2in/fastpath/" #x); \ 349 nat_init_simple_counter (nm->counters.slowpath.in2out.x, #x, \ 350 "/nat44-ei/in2out/slowpath/" #x); \ 351 nat_init_simple_counter (nm->counters.slowpath.out2in.x, #x, \ 352 "/nat44-ei/out2in/slowpath/" #x); 356 "/nat44-ei/hairpinning");
487 #define _(N, i, n, s) vec_free (ap->busy_##n##_ports_per_thread); 498 const char *feature_name, *del_feature_name;
512 return VNET_API_ERROR_UNSUPPORTED;
520 return VNET_API_ERROR_VALUE_EXIST;
525 feature_name = is_inside ?
"nat44-ei-in2out-fast" :
"nat44-ei-out2in-fast";
529 feature_name = is_inside ?
"nat44-ei-in2out-worker-handoff" :
530 "nat44-ei-out2in-worker-handoff";
532 feature_name = is_inside ?
"nat44-ei-in2out" :
"nat44-ei-out2in";
586 del_feature_name =
"nat44-ei-handoff-classify";
588 "del_feature_name = nat44-ei-handoff-classify");
589 feature_name = !is_inside ?
590 "nat44-ei-in2out-worker-handoff" :
591 "nat44-ei-out2in-worker-handoff";
595 del_feature_name =
"nat44-ei-classify";
598 !is_inside ?
"nat44-ei-in2out" :
"nat44-ei-out2in";
606 "ip4-unicast", del_feature_name, sw_if_index, 0, 0, 0);
610 "ip4-unicast", feature_name, sw_if_index, 1, 0, 0);
616 "nat44-ei-hairpinning",
617 sw_if_index, 1, 0, 0);
629 "ip4-unicast", feature_name, sw_if_index, 0, 0, 0);
636 "nat44-ei-hairpinning",
637 sw_if_index, 0, 0, 0);
651 del_feature_name = !is_inside ?
652 "nat44-ei-in2out-worker-handoff" :
653 "nat44-ei-out2in-worker-handoff";
654 feature_name =
"nat44-ei-handoff-classify";
655 clib_warning (
"feature_name = nat44-ei-handoff-classify");
660 !is_inside ?
"nat44-ei-in2out" :
"nat44-ei-out2in";
661 feature_name =
"nat44-ei-classify";
670 "ip4-unicast", del_feature_name, sw_if_index, 0, 0, 0);
674 sw_if_index, 1, 0, 0);
680 "ip4-local",
"nat44-ei-hairpinning", sw_if_index, 0, 0, 0);
694 return VNET_API_ERROR_NO_SUCH_ENTRY;
703 sw_if_index, 1, 0, 0);
714 sw_if_index, 1, 0, 0);
763 return VNET_API_ERROR_UNSUPPORTED;
771 return VNET_API_ERROR_VALUE_EXIST;
812 sw_if_index, !is_del, 0, 0);
816 sw_if_index, !is_del, 0, 0);
832 "nat44-ei-out2in-worker-handoff",
833 sw_if_index, !is_del, 0, 0);
837 "ip4-output",
"nat44-ei-in2out-output-worker-handoff", sw_if_index,
852 sw_if_index, !is_del, 0, 0);
856 sw_if_index, !is_del, 0, 0);
877 return VNET_API_ERROR_VALUE_EXIST;
886 return VNET_API_ERROR_NO_SUCH_ENTRY;
990 u16 port_host_byte_order = clib_net_to_host_u16 (port);
992 for (address_index = 0; address_index <
vec_len (addresses); address_index++)
994 if (addresses[address_index].addr.
as_u32 != addr.
as_u32)
997 a = addresses + address_index;
1000 #define _(N, j, n, s) \ 1001 case NAT_PROTOCOL_##N: \ 1002 if (a->busy_##n##_port_refcounts[port_host_byte_order]) \ 1003 return VNET_API_ERROR_INSTANCE_IN_USE; \ 1004 ++a->busy_##n##_port_refcounts[port_host_byte_order]; \ 1005 a->busy_##n##_ports_per_thread[thread_index]++; \ 1006 a->busy_##n##_ports++; \ 1015 return VNET_API_ERROR_NO_SUCH_ENTRY;
1026 .fp_addr.ip4.as_u32 = addr.
as_u32,
1050 u16 port_host_byte_order = clib_net_to_host_u16 (port);
1052 for (address_index = 0; address_index <
vec_len (addresses); address_index++)
1054 if (addresses[address_index].addr.
as_u32 == addr->
as_u32)
1058 ASSERT (address_index < vec_len (addresses));
1060 a = addresses + address_index;
1064 #define _(N, i, n, s) \ 1065 case NAT_PROTOCOL_##N: \ 1066 ASSERT (a->busy_##n##_port_refcounts[port_host_byte_order] >= 1); \ 1067 --a->busy_##n##_port_refcounts[port_host_byte_order]; \ 1068 a->busy_##n##_ports--; \ 1069 a->busy_##n##_ports_per_thread[thread_index]--; \ 1086 if (clib_bihash_add_del_8_8 (&nm->
in2out, &kv, 0))
1089 if (clib_bihash_add_del_8_8 (&nm->
out2in, &kv, 0))
1094 &s->in2out.addr, s->in2out.port, &s->out2in.addr,
1095 s->out2in.port, s->nat_proto);
1104 thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32,
1105 s->nat_proto, s->in2out.port, s->out2in.port, s->in2out.fib_index);
1107 nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
1108 s->ext_host_port, s->nat_proto, s->out2in.fib_index,
1116 &s->out2in.
addr, s->out2in.port,
1124 nat44_ei_user_t *u = 0;
1135 if (clib_bihash_search_8_8 (&tnm->
user_hash, &kv, &value))
1148 u->addr.as_u32 = addr->
as_u32;
1149 u->fib_index = fib_index;
1153 u->sessions_per_user_list_head_index =
1154 per_user_list_head_elt - tnm->
list_pool;
1161 if (clib_bihash_add_del_8_8 (&tnm->
user_hash, &kv, 1))
1179 nat44_ei_session_t *
1183 nat44_ei_session_t *s;
1185 u32 oldest_per_user_translation_list_index, session_index;
1186 dlist_elt_t *oldest_per_user_translation_list_elt;
1193 tnm->
list_pool, u->sessions_per_user_list_head_index);
1195 ASSERT (oldest_per_user_translation_list_index != ~0);
1199 oldest_per_user_translation_list_index);
1202 tnm->
list_pool, oldest_per_user_translation_list_index);
1205 session_index = oldest_per_user_translation_list_elt->
value;
1212 u->nstaticsessions--;
1219 s->ext_host_addr.as_u32 = 0;
1220 s->ext_host_port = 0;
1221 s->ext_host_nat_addr.as_u32 = 0;
1222 s->ext_host_nat_port = 0;
1232 per_user_translation_list_elt - tnm->
list_pool);
1235 s->per_user_index = per_user_translation_list_elt - tnm->
list_pool;
1236 s->per_user_list_head_index = u->sessions_per_user_list_head_index;
1239 per_user_translation_list_elt - tnm->
list_pool);
1241 s->user_index = u - tnm->
users;
1246 s->ha_last_refreshed =
now;
1258 if (clib_bihash_add_del_8_8 (&nm->
in2out, &kv, 0))
1262 if (clib_bihash_add_del_8_8 (&nm->
out2in, &kv, 0))
1268 &s->in2out.addr, s->in2out.port,
1269 &s->out2in.addr, s->out2in.port, s->nat_proto);
1272 thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32,
1273 s->nat_proto, s->in2out.port, s->out2in.port, s->in2out.fib_index);
1275 nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
1276 s->ext_host_port, s->nat_proto, s->out2in.fib_index,
1284 &s->out2in.
addr, s->out2in.port,
1292 nat44_ei_session_t *s;
1303 while (elt->
value != ~0)
1332 if (!clib_bihash_search_8_8 (&tnm->
user_hash, &kv, &value))
1345 if (!clib_bihash_search_8_8 (&tnm->
user_hash, &kv, &value))
1366 nat44_ei_session_t *s;
1367 u32 elt_index, head_index, ses_index;
1369 if (!clib_bihash_search_8_8 (&tnm->
user_hash, &kv, &value))
1371 user_index = value.
value;
1373 if (u->nstaticsessions)
1375 head_index = u->sessions_per_user_list_head_index;
1377 elt_index = head->
next;
1379 ses_index = elt->
value;
1380 while (ses_index != ~0)
1384 ses_index = elt->
value;
1388 if ((s->out2in.addr.as_u32 != e_addr.
as_u32) ||
1389 (s->out2in.port != e_port))
1412 u32 next_worker_index = 0;
1420 next_worker_index += nm->
workers[hash & (_vec_len (nm->
workers) - 1)];
1424 return next_worker_index;
1429 u32 rx_fib_index0,
u8 is_output)
1437 u32 next_worker_index = 0;
1464 icmp46_header_t *
icmp = (icmp46_header_t *) udp;
1467 vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
1477 case NAT_PROTOCOL_ICMP:
1478 icmp = (icmp46_header_t *) l4_header;
1482 case NAT_PROTOCOL_UDP:
1483 case NAT_PROTOCOL_TCP:
1506 next_worker_index +=
1508 return next_worker_index;
1516 u32 snat_thread_index)
1528 for (i = s_addr_offset; i <
vec_len (addresses); ++
i)
1533 #define _(N, j, n, s) \ 1534 case NAT_PROTOCOL_##N: \ 1535 if (a->busy_##n##_ports_per_thread[thread_index] < port_per_thread) \ 1537 if (a->fib_index == fib_index) \ 1541 portnum = (port_per_thread * snat_thread_index) + \ 1542 nat_random_port (&nm->random_seed, 0, \ 1543 port_per_thread - 1) + \ 1545 if (a->busy_##n##_port_refcounts[portnum]) \ 1547 --a->busy_##n##_port_refcounts[portnum]; \ 1548 a->busy_##n##_ports_per_thread[thread_index]++; \ 1549 a->busy_##n##_ports++; \ 1551 *port = clib_host_to_net_u16 (portnum); \ 1555 else if (a->fib_index == ~0) \ 1568 for (i = 0; i < s_addr_offset; ++
i)
1604 u16 port_per_thread,
u32 snat_thread_index)
1617 #define _(N, i, n, s) \ 1618 case NAT_PROTOCOL_##N: \ 1619 if (a->busy_##n##_ports < ports) \ 1623 portnum = nat_random_port (&nm->random_seed, nm->start_port, \ 1625 if (a->busy_##n##_port_refcounts[portnum]) \ 1627 ++a->busy_##n##_port_refcounts[portnum]; \ 1628 a->busy_##n##_ports++; \ 1630 *port = clib_host_to_net_u16 (portnum); \ 1651 u16 port_per_thread,
u32 snat_thread_index)
1655 u16 m, ports, portnum,
A, j;
1664 #define _(N, i, n, s) \ 1665 case NAT_PROTOCOL_##N: \ 1666 if (a->busy_##n##_ports < ports) \ 1670 A = nat_random_port (&nm->random_seed, 1, \ 1671 pow2_mask (nm->psid_offset)); \ 1672 j = nat_random_port (&nm->random_seed, 0, pow2_mask (m)); \ 1673 portnum = A | (nm->psid << nm->psid_offset) | (j << (16 - m)); \ 1674 if (a->busy_##n##_port_refcounts[portnum]) \ 1676 ++a->busy_##n##_port_refcounts[portnum]; \ 1677 a->busy_##n##_ports++; \ 1679 *port = clib_host_to_net_u16 (portnum); \ 1732 int addr_only,
int identity_nat,
1761 .fib_index = ses->in2out.fib_index };
1772 if (!clib_bihash_search_8_8 (&tnm->
user_hash, &kv, &value))
1776 u->nstaticsessions--;
1791 nat44_ei_session_t *s;
1792 clib_bihash_8_8_t *t;
1794 init_nat_k (&kv, *addr, port, fib_index, proto);
1796 if (!clib_bihash_search_8_8 (t, &kv, &value))
1804 return VNET_API_ERROR_UNSPECIFIED;
1812 return VNET_API_ERROR_NO_SUCH_ENTRY;
1837 .ip4.as_u32 = addr->
as_u32,
1856 u8 identity_nat,
u8 *tag,
u8 is_add)
1868 u32 elt_index, head_index;
1871 nat44_ei_session_t *s;
1877 if (sw_if_index != ~0)
1907 return VNET_API_ERROR_VALUE_EXIST;
1910 l_addr, l_port, e_port, proto, sw_if_index, vrf_id, addr_only,
1914 if (!first_int_addr)
1925 return VNET_API_ERROR_NO_SUCH_ENTRY;
1929 if (!first_int_addr)
1939 init_nat_k (&kv, e_addr, addr_only ? 0 : e_port, 0, addr_only ? 0 : proto);
1952 if (local->
vrf_id == vrf_id)
1953 return VNET_API_ERROR_VALUE_EXIST;
1964 return VNET_API_ERROR_VALUE_EXIST;
1983 init_nat_k (&kv, l_addr, addr_only ? 0 : l_port, fib_index,
1984 addr_only ? 0 : proto);
1987 return VNET_API_ERROR_VALUE_EXIST;
2002 #define _(N, j, n, s) \ 2003 case NAT_PROTOCOL_##N: \ 2004 if (a->busy_##n##_port_refcounts[e_port]) \ 2005 return VNET_API_ERROR_INVALID_VALUE; \ 2006 ++a->busy_##n##_port_refcounts[e_port]; \ 2007 if (e_port > 1024) \ 2009 a->busy_##n##_ports++; \ 2010 a->busy_##n##_ports_per_thread[nat44_ei_get_thread_idx_by_port ( \ 2017 return VNET_API_ERROR_INVALID_VALUE_2;
2025 if (sw_if_index != ~0)
2042 return VNET_API_ERROR_NO_SUCH_ENTRY;
2101 if (!clib_bihash_search_8_8 (&tnm->
user_hash, &kv, &value))
2103 user_index = value.
value;
2107 head_index = u->sessions_per_user_list_head_index;
2109 elt_index = head->
next;
2111 ses_index = elt->
value;
2112 while (ses_index != ~0)
2116 ses_index = elt->
value;
2121 if (!addr_only && s->in2out.port != m->
local_port)
2140 if (sw_if_index != ~0)
2143 return VNET_API_ERROR_NO_SUCH_ENTRY;
2153 if (local->
vrf_id == vrf_id)
2154 find = local - m->
locals;
2157 return VNET_API_ERROR_NO_SUCH_ENTRY;
2176 #define _(N, j, n, s) \ 2177 case NAT_PROTOCOL_##N: \ 2178 --a->busy_##n##_port_refcounts[e_port]; \ 2179 if (e_port > 1024) \ 2181 a->busy_##n##_ports--; \ 2182 a->busy_##n##_ports_per_thread[nat44_ei_get_thread_idx_by_port ( \ 2188 default :
return VNET_API_ERROR_INVALID_VALUE_2;
2254 u32 match_fib_index,
2257 u32 *mapping_fib_index,
u8 by_external,
2258 u8 *is_addr_only,
u8 *is_identity_nat)
2267 init_nat_k (&kv, match_addr, match_port, 0, match_protocol);
2285 init_nat_k (&kv, match_addr, match_port, match_fib_index,
2290 init_nat_k (&kv, match_addr, 0, match_fib_index, 0);
2304 *mapping_port = match_port;
2306 *mapping_port =
port;
2365 s =
format (s,
"%U thread-index %llu session-index %llu",
2385 u32 translations,
u32 translation_buckets,
2394 clib_bihash_init_8_8 (&tnm->
user_hash,
"users", user_buckets, 0);
2396 clib_bihash_set_kvp_format_fn_8_8 (&tnm->
user_hash,
2432 clib_bihash_free_8_8 (&nm->
in2out);
2433 clib_bihash_free_8_8 (&nm->
out2in);
2447 u32 static_mapping_buckets = 1024;
2448 u32 static_mapping_memory_size = 64 << 20;
2451 "static_mapping_by_local", static_mapping_buckets,
2452 static_mapping_memory_size);
2454 "static_mapping_by_external", static_mapping_buckets,
2455 static_mapping_memory_size);
2463 clib_bihash_init_8_8 (&nm->
in2out,
"in2out", translation_buckets, 0);
2464 clib_bihash_init_8_8 (&nm->
out2in,
"out2in", translation_buckets, 0);
2465 clib_bihash_set_kvp_format_fn_8_8 (&nm->
in2out,
2467 clib_bihash_set_kvp_format_fn_8_8 (&nm->
out2in,
2485 clib_bihash_free_8_8 (&nm->
in2out);
2486 clib_bihash_free_8_8 (&nm->
out2in);
2489 clib_bihash_set_kvp_format_fn_8_8 (&nm->
in2out,
2491 clib_bihash_set_kvp_format_fn_8_8 (&nm->
out2in,
2508 u32 new_fib_index,
u32 old_fib_index)
2516 if (!nm->
enabled || (new_fib_index == old_fib_index) ||
2547 if (outside_fib->
fib_index == old_fib_index)
2558 if (outside_fib->
fib_index == new_fib_index)
2587 return VNET_API_ERROR_VALUE_EXIST;
2600 #define _(N, i, n, s) \ 2601 clib_memset (ap->busy_##n##_port_refcounts, 0, \ 2602 sizeof (ap->busy_##n##_port_refcounts)); \ 2603 ap->busy_##n##_ports = 0; \ 2604 ap->busy_##n##_ports_per_thread = 0; \ 2605 vec_validate_init_empty (ap->busy_##n##_ports_per_thread, \ 2606 tm->n_vlib_mains - 1, 0); 2638 u32 *indices_to_delete = 0;
2645 for (i = 0; i <
vec_len (auto_add_sw_if_indices); i++)
2647 if (auto_add_sw_if_indices[i] == sw_if_index)
2662 if (vec_len (indices_to_delete))
2664 for (j = vec_len (indices_to_delete) - 1; j >= 0; j--)
2672 return VNET_API_ERROR_VALUE_EXIST;
2679 return VNET_API_ERROR_NO_SUCH_ENTRY;
2711 nat44_ei_session_t *ses;
2712 u32 *ses_to_be_removed = 0, *ses_index;
2730 return VNET_API_ERROR_NO_SUCH_ENTRY;
2751 return VNET_API_ERROR_UNSPECIFIED;
2759 if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
2765 if (ses->out2in.addr.as_u32 == addr.
as_u32)
2781 #define _(N, i, n, s) vec_free (a->busy_##n##_ports_per_thread); 2811 u32 if_address_index,
u32 is_delete)
2835 for (j = 0; j <
vec_len (addresses); j++)
2836 if (addresses[j].
addr.as_u32 == address->
as_u32)
2861 nm,
"nat44_ei_add_del_static_mapping returned %d",
"i4", rv);
2885 u32 address_length,
u32 if_address_index,
2953 u32 next_in2out = 0, next_out2in = 0;
2959 while (n_left_from > 0)
2965 while (n_left_from > 0 && n_left_to_next > 0)
2980 n_left_to_next -= 1;
3020 (b0->
flags & VLIB_BUFFER_IS_TRACED)))
3033 n_left_to_next, bi0, next0);
3040 vm, node->
node_index, NAT44_EI_CLASSIFY_ERROR_NEXT_IN2OUT, next_in2out);
3042 vm, node->
node_index, NAT44_EI_CLASSIFY_ERROR_NEXT_OUT2IN, next_out2in);
3053 .name =
"nat44-ei-classify",
3054 .vector_size =
sizeof (
u32),
3074 .name =
"nat44-ei-handoff-classify",
3075 .vector_size =
sizeof (
u32),
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
static u8 * format_nat44_ei_classify_trace(u8 *s, va_list *args)
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
fib_protocol_t fp_proto
protocol type
vlib_node_registration_t nat44_ei_in2out_hairpinning_finish_interface_output_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_in2out_hairpinning_finish_interface_output_node) ...
static void nat44_ei_delete_user_with_no_session(nat44_ei_main_t *nm, nat44_ei_user_t *u, u32 thread_index)
u8 * format_nat44_ei_key(u8 *s, va_list *args)
int nat44_ei_add_interface_address(nat44_ei_main_t *nm, u32 sw_if_index, int is_del)
int ip4_sv_reass_output_enable_disable_with_refcnt(u32 sw_if_index, int is_enable)
ip4_table_bind_function_t * function
void nat44_ei_free_session_data_v2(nat44_ei_main_t *nm, nat44_ei_session_t *s, u32 thread_index, u8 is_ha)
#define nat_elog_info(_pm, nat_elog_str)
static int nat44_ei_alloc_range_cb(nat44_ei_address_t *addresses, u32 fib_index, u32 thread_index, nat_protocol_t proto, ip4_address_t s_addr, ip4_address_t *addr, u16 *port, u16 port_per_thread, u32 snat_thread_index)
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Functions to call when interface address changes.
static void clib_dlist_init(dlist_elt_t *pool, u32 index)
static void nat44_ei_db_free()
nat44_ei_config_t rconfig
u32 fq_in2out_output_index
#define fail_if_disabled()
void nat_ipfix_logging_addresses_exhausted(u32 thread_index, u32 pool_id)
Generate NAT addresses exhausted event.
nat44_ei_interface_t * interfaces
#define pool_foreach(VAR, POOL)
Iterate through pool.
#define pool_alloc(P, N)
Allocate N more free elements to pool (unspecified alignment).
vl_api_ip_proto_t protocol
nat44_ei_lb_addr_port_t * locals
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
ip4_address_t * ip4_interface_first_address(ip4_main_t *im, u32 sw_if_index, ip_interface_address_t **result_ia)
int nat44_ei_add_del_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, nat_protocol_t proto, u32 sw_if_index, u32 vrf_id, u8 addr_only, u8 identity_nat, u8 *tag, u8 is_add)
Add/delete NAT44-EI static mapping.
u32 fib_table_get_index_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the index of the FIB bound to the interface.
u32 nat44_ei_get_thread_idx_by_port(u16 e_port)
#define clib_bitmap_foreach(i, ai)
Macro to iterate across set bits in a bitmap.
u32 vlib_frame_queue_main_init(u32 node_index, u32 frame_queue_nelts)
add paths without path extensions
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
NAT44 endpoint independent plugin declarations.
nat44_ei_session_t * sessions
#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. ...
ip_lookup_main_t lookup_main
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 increment)
Increment a simple counter.
static_always_inline void nat44_ei_user_del_sessions(nat44_ei_user_t *u, u32 thread_index)
void nat_dpo_create(dpo_proto_t dproto, u32 aftr_index, dpo_id_t *dpo)
static u32 nat_value_get_thread_index(clib_bihash_kv_8_8_t *value)
static void init_nat_i2o_k(clib_bihash_kv_8_8_t *kv, nat44_ei_session_t *s)
#define VLIB_NODE_FN(node)
int nat44_ei_plugin_disable()
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
clib_bihash_8_8_t static_mapping_by_external
static void split_nat_key(u64 key, ip4_address_t *addr, u16 *port, u32 *fib_index, nat_protocol_t *proto)
int nat44_ei_set_outside_address_and_port(nat44_ei_address_t *addresses, u32 thread_index, ip4_address_t addr, u16 port, nat_protocol_t protocol)
int nat44_ei_user_del(ip4_address_t *addr, u32 fib_index)
Delete specific NAT44 EI user and his sessions.
static_always_inline void nat_reset_timeouts(nat_timeouts_t *timeouts)
#define nat44_ei_is_addr_only_static_mapping(mp)
int nat44_ei_interface_add_del(u32 sw_if_index, u8 is_inside, int is_del)
static_always_inline u8 icmp_type_is_error_message(u8 icmp_type)
nat44_ei_static_mapping_t * static_mappings
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, fib_mpls_label_t *next_hop_labels, fib_route_path_flags_t path_flags)
Update the entry to have just one path.
void nat44_ei_free_session_data(nat44_ei_main_t *nm, nat44_ei_session_t *s, u32 thread_index, u8 is_ha)
void nat44_ei_set_alloc_range(u16 start_port, u16 end_port)
Set address and port assignment algorithm for port range.
u32 nat44_ei_get_in2out_worker_index(ip4_header_t *ip0, u32 rx_fib_index0, u8 is_output)
#define static_always_inline
int nat44_ei_set_workers(uword *bitmap)
#define nat_init_simple_counter(c, n, sn)
nat44_ei_main_per_thread_data_t * tnm
#define VLIB_INIT_FUNCTION(x)
static nat_protocol_t ip_proto_to_nat_proto(u8 ip_proto)
Common NAT inline functions.
void nat_syslog_nat44_apmdel(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *xsaddr, u16 xsport, nat_protocol_t proto)
nat44_ei_address_t * addresses
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a 'special' entry from the FIB.
#define nat_elog_notice_X1(_pm, nat_elog_fmt_str, nat_elog_fmt_arg, nat_elog_val1)
#define nat_validate_simple_counter(c, i)
void nat_dpo_module_init(void)
#define NAT44_EI_INTERFACE_FLAG_IS_OUTSIDE
description fragment has unexpected format
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Aggregate type for a prefix.
#define nat_elog_warn(_pm, nat_elog_str)
static void init_nat_kv(clib_bihash_kv_8_8_t *kv, ip4_address_t addr, u16 port, u32 fib_index, nat_protocol_t proto, u32 thread_index, u32 session_index)
vlib_simple_counter_main_t hairpinning
vnet_main_t * vnet_get_main(void)
static u32 nat_value_get_session_index(clib_bihash_kv_8_8_t *value)
int nat44_ei_del_session(nat44_ei_main_t *nm, ip4_address_t *addr, u16 port, nat_protocol_t proto, u32 vrf_id, int is_in)
Delete NAT44-EI session.
static void * ip4_next_header(ip4_header_t *i)
vlib_node_registration_t nat44_ei_handoff_classify_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_handoff_classify_node)
int ip4_sv_reass_enable_disable_with_refcnt(u32 sw_if_index, int is_enable)
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
#define nat44_ei_is_session_static(sp)
struct nat44_ei_main_s::@81 counters
int nat44_ei_del_address(nat44_ei_main_t *nm, ip4_address_t addr, u8 delete_sm)
nat44_ei_classify_error_t
static int nat44_ei_alloc_mape_cb(nat44_ei_address_t *addresses, u32 fib_index, u32 thread_index, nat_protocol_t proto, ip4_address_t s_addr, ip4_address_t *addr, u16 *port, u16 port_per_thread, u32 snat_thread_index)
vlib_node_registration_t nat44_ei_hairpin_dst_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_hairpin_dst_node)
int nat44_ei_add_address(nat44_ei_main_t *nm, ip4_address_t *addr, u32 vrf_id)
fib_source_t fib_source_allocate(const char *name, fib_source_priority_t prio, fib_source_behaviour_t bh)
vl_api_fib_path_type_t type
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
vl_api_interface_index_t sw_if_index
vlib_node_registration_t nat44_ei_classify_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_classify_node)
nat44_ei_static_map_resolve_t * to_resolve
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
static void nat44_ei_add_static_mapping_when_resolved(ip4_address_t l_addr, u16 l_port, u16 e_port, nat_protocol_t proto, u32 sw_if_index, u32 vrf_id, int addr_only, int identity_nat, u8 *tag)
#define FIB_SOURCE_PRIORITY_HI
Some priority values that plugins might use when they are not to concerned where in the list they'll ...
void nat44_ei_static_mapping_del_sessions(nat44_ei_main_t *nm, nat44_ei_main_per_thread_data_t *tnm, nat44_ei_user_key_t u_key, int addr_only, ip4_address_t e_addr, u16 e_port)
Delete session for static mapping.
static uword clib_bitmap_last_set(uword *ai)
Return the higest numbered set bit in a bitmap.
IPv4 shallow virtual reassembly.
nat44_ei_interface_t * output_feature_interfaces
static void clib_dlist_addtail(dlist_elt_t *pool, u32 head_index, u32 new_index)
format_function_t format_nat_protocol
void nat44_ei_free_outside_address_and_port(nat44_ei_address_t *addresses, u32 thread_index, ip4_address_t *addr, u16 port, nat_protocol_t protocol)
#define NAT44_EI_STATIC_MAPPING_FLAG_IDENTITY_NAT
static void nat44_ei_worker_db_init(nat44_ei_main_per_thread_data_t *tnm, u32 translations, u32 translation_buckets, u32 user_buckets)
int nat44_ei_interface_add_del_output_feature(u32 sw_if_index, u8 is_inside, int is_del)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
static_always_inline uword nat44_ei_classify_inline_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define pool_put(P, E)
Free an object E in pool P.
clib_error_t * nat44_ei_api_hookup(vlib_main_t *vm)
#define vec_dup(V)
Return copy of vector (no header, no alignment)
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)
#define vec_del1(v, i)
Delete the element at index I.
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
u32 node_index
Node index.
static void vlib_set_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 value)
Set a simple counter.
u32 max_translations_per_user
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
void nat_ha_enable()
Enable NAT HA.
static char * nat44_ei_classify_error_strings[]
#define NAT_FQ_NELTS_DEFAULT
void fib_table_unlock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Take a reference counting lock on the table.
u32 nat44_ei_get_out2in_worker_index(vlib_buffer_t *b, ip4_header_t *ip0, u32 rx_fib_index0, u8 is_output)
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
static void nat44_ei_update_outside_fib(ip4_main_t *im, uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
clib_bihash_8_8_t static_mapping_by_local
u32 * auto_add_sw_if_indices
#define pool_free(p)
Free a pool.
void nat_ha_init(vlib_main_t *vm, u32 num_workers, u32 num_threads)
Initialize NAT HA.
void nat44_ei_set_alloc_default()
Set address and port assignment algorithm to default/standard.
static void nat44_ei_db_init(u32 translations, u32 translation_buckets, u32 user_buckets)
#define VLIB_REGISTER_NODE(x,...)
nat44_ei_main_per_thread_data_t * per_thread_data
int nat44_ei_plugin_enable(nat44_ei_config_t c)
static_always_inline uword vlib_get_thread_index(void)
u8 static_mapping_connection_tracking
sll srl srl sll sra u16x4 i
#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
#define clib_warning(format, args...)
u32 in2out_hairpinning_finish_interface_output_node_fq_index
#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
#define nat44_ei_is_identity_static_mapping(mp)
void fib_table_lock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Release a reference counting lock on the table.
#define NAT44_EI_STATIC_MAPPING_FLAG_ADDR_ONLY
#define nat44_ei_log_err(...)
clib_error_t * nat44_ei_init(vlib_main_t *vm)
fib_node_index_t fib_table_entry_special_dpo_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Add a 'special' entry to the FIB that links to the DPO passed A special entry is an entry that the FI...
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
#define pool_put_index(p, i)
Free pool element with given index.
u32 in2out_hairpinning_finish_ip4_lookup_node_fq_index
vlib_simple_counter_main_t user_limit_reached
VNET_FEATURE_INIT(ip4_nat_classify, static)
u32 unk_proto_lru_head_index
ip4_address_t external_addr
#define foreach_nat_counter
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.
vlib_put_next_frame(vm, node, next_index, 0)
u32 tcp_trans_lru_head_index
#define clib_bitmap_free(v)
Free a bitmap.
static void vlib_zero_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Clear a simple counter Clears the set of per-thread u16 counters, and the u64 counter.
uword * thread_registrations_by_name
static void clib_dlist_remove(dlist_elt_t *pool, u32 index)
nat44_ei_hairpin_src_next_t next_index
void nat44_ei_set_alloc_mape(u16 psid, u16 psid_offset, u16 psid_length)
Set address and port assignment algorithm for MAP-E CE.
ip_lookup_main_t * ip4_lookup_main
#define FIB_SOURCE_PRIORITY_LOW
void nat44_ei_add_del_address_dpo(ip4_address_t addr, u8 is_add)
#define VNET_FEATURES(...)
u8 * format_nat44_ei_user_kvp(u8 *s, va_list *args)
static int nat44_ei_alloc_default_cb(nat44_ei_address_t *addresses, u32 fib_index, u32 thread_index, nat_protocol_t proto, ip4_address_t s_addr, ip4_address_t *addr, u16 *port, u16 port_per_thread, u32 snat_thread_index)
static uword is_pow2(uword x)
vlib_simple_counter_main_t total_sessions
#define foreach_nat44_ei_classify_error
ip4_table_bind_callback_t * table_bind_callbacks
Functions to call when interface to table biding changes.
struct _vlib_node_registration vlib_node_registration_t
void nat44_ei_delete_session(nat44_ei_main_t *nm, nat44_ei_session_t *ses, u32 thread_index)
void nat44_ei_set_node_indexes(nat44_ei_main_t *nm, vlib_main_t *vm)
vlib_log_class_t log_class
#define NAT44_EI_INTERFACE_FLAG_IS_INSIDE
static_always_inline void nat_validate_interface_counters(nat44_ei_main_t *nm, u32 sw_if_index)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vlib_main_t vlib_node_runtime_t * node
void nat44_ei_sessions_clear()
Clear all active NAT44-EI sessions.
#define nat44_ei_is_unk_proto_session(sp)
VLIB buffer representation.
nat44_ei_outside_fib_t * outside_fibs
static void nat44_ei_ip4_add_del_addr_only_sm_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 void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
nat44_ei_main_t nat44_ei_main
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
static void init_nat_o2i_k(clib_bihash_kv_8_8_t *kv, nat44_ei_session_t *s)
static void nat44_ei_worker_db_free(nat44_ei_main_per_thread_data_t *tnm)
#define fail_if_enabled()
nat44_ei_session_t * nat44_ei_session_alloc_or_recycle(nat44_ei_main_t *nm, nat44_ei_user_t *u, u32 thread_index, f64 now)
#define hash_get_mem(h, key)
static api_main_t * vlibapi_get_main(void)
u32 in2out_output_node_index
ip4_main_t ip4_main
Global ip4 main structure.
NAT port/address allocation lib.
int nat44_ei_set_frame_queue_nelts(u32 frame_queue_nelts)
static vlib_thread_main_t * vlib_get_thread_main()
u8 * format_nat44_ei_session_kvp(u8 *s, va_list *args)
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
#define vec_foreach(var, vec)
Vector iterator.
void nat44_ei_add_del_addr_to_fib(ip4_address_t *addr, u8 p_len, u32 sw_if_index, int is_add)
u16 flags
Copy of main node flags.
void nat_ha_sdel(ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 fib_index, u32 session_thread_index)
Create session delete HA event.
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
u32 tcp_estab_lru_head_index
nat44_ei_alloc_out_addr_and_port_function_t * alloc_addr_and_port
static_always_inline u32 nat_calc_bihash_buckets(u32 n_elts)
#define VLIB_NODE_FLAG_TRACE
nat44_ei_addr_and_port_alloc_alg_t addr_and_port_alloc_alg
u8 * format_nat44_ei_static_mapping_kvp(u8 *s, va_list *args)
u32 max_translations_per_thread
int nat44_ei_static_mapping_match(ip4_address_t match_addr, u16 match_port, u32 match_fib_index, nat_protocol_t match_protocol, ip4_address_t *mapping_addr, u16 *mapping_port, u32 *mapping_fib_index, u8 by_external, u8 *is_addr_only, u8 *is_identity_nat)
Match NAT44-EI static mapping.
#define nat44_ei_interface_is_inside(ip)
static void init_nat_k(clib_bihash_kv_8_8_t *kv, ip4_address_t addr, u16 port, u32 fib_index, nat_protocol_t proto)
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
static void nat44_ei_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)
void nat_ha_disable()
Disable NAT HA.
void nat44_ei_addresses_free(nat44_ei_address_t **addresses)
nat44_ei_user_t * nat44_ei_user_get_or_create(nat44_ei_main_t *nm, ip4_address_t *addr, u32 fib_index, u32 thread_index)
clib_bihash_8_8_t user_hash
vlib_node_registration_t nat44_ei_hairpinning_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_hairpinning_node)
#define nat44_ei_interface_is_outside(ip)
void nat_ipfix_logging_nat44_ses_delete(u32 thread_index, u32 src_ip, u32 nat_src_ip, nat_protocol_t nat_proto, u16 src_port, u16 nat_src_port, u32 fib_index)
Generate NAT44 session delete event.
vlib_node_registration_t nat44_ei_in2out_hairpinning_finish_ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_in2out_hairpinning_finish_ip4_lookup_node) ...
static int nat44_ei_is_address_used_in_static_mapping(ip4_address_t addr)
static u32 clib_dlist_remove_head(dlist_elt_t *pool, u32 head_index)
vlib_simple_counter_main_t total_users
static uword pool_elts(void *v)
Number of active elements in a pool.