.node_name = "nat44-hairpin-src",
.runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa","ip4-sv-reassembly-output-feature"),
};
+VNET_FEATURE_INIT (nat_pre_in2out_output, static) = {
+ .arc_name = "ip4-output",
+ .node_name = "nat-pre-in2out-output",
+ .runs_after = VNET_FEATURES ("ip4-sv-reassembly-output-feature"),
+ .runs_before = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
+};
VNET_FEATURE_INIT (ip4_nat44_ed_in2out_output, static) = {
.arc_name = "ip4-output",
.node_name = "nat44-ed-in2out-output",
s->nat_proto);
}
-int
-nat44_set_session_limit (u32 session_limit, u32 vrf_id)
-{
- snat_main_t *sm = &snat_main;
- u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
- u32 len = vec_len (sm->max_translations_per_fib);
-
- if (len <= fib_index)
- {
- vec_validate (sm->max_translations_per_fib, fib_index + 1);
-
- for (; len < vec_len (sm->max_translations_per_fib); len++)
- sm->max_translations_per_fib[len] = sm->max_translations_per_thread;
- }
-
- sm->max_translations_per_fib[fib_index] = session_limit;
- return 0;
-}
-
void
nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
u32 thread_index, u8 is_ha)
nat_protocol_t proto,
int addr_only, int is_add, u8 * tag,
int twice_nat, int out2in_only,
- int identity_nat)
+ int identity_nat,
+ ip4_address_t pool_addr, int exact)
{
snat_static_map_resolve_t *rp;
rp->out2in_only = out2in_only;
rp->identity_nat = identity_nat;
rp->tag = vec_dup (tag);
+ rp->pool_addr = pool_addr;
+ rp->exact = exact;
}
static u32
u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
u32 sw_if_index, nat_protocol_t proto, int is_add,
twice_nat_type_t twice_nat, u8 out2in_only, u8 * tag,
- u8 identity_nat)
+ u8 identity_nat, ip4_address_t pool_addr, int exact)
{
snat_main_t *sm = &snat_main;
snat_static_mapping_t *m;
snat_add_static_mapping_when_resolved
(sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
- addr_only, is_add, tag, twice_nat, out2in_only, identity_nat);
+ addr_only, is_add, tag, twice_nat, out2in_only,
+ identity_nat, pool_addr, exact);
/* DHCP resolution required? */
if (first_int_addr == 0)
m->local_addr = l_addr;
m->external_addr = e_addr;
m->twice_nat = twice_nat;
+
+ if (twice_nat == TWICE_NAT && exact)
+ {
+ m->flags |= NAT_STATIC_MAPPING_FLAG_EXACT_ADDRESS;
+ m->pool_addr = pool_addr;
+ }
+
if (out2in_only)
m->flags |= NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY;
if (addr_only)
if (delete_sm)
{
+ ip4_address_t pool_addr = { 0 };
/* *INDENT-OFF* */
pool_foreach (m, sm->static_mappings,
({
if (m->external_addr.as_u32 == addr.as_u32)
(void) snat_add_static_mapping (m->local_addr, m->external_addr,
m->local_port, m->external_port,
- m->vrf_id, is_addr_only_static_mapping(m), ~0,
- m->proto, 0, m->twice_nat,
- is_out2in_only_static_mapping(m), m->tag, is_identity_static_mapping(m));
+ m->vrf_id,
+ is_addr_only_static_mapping(m), ~0,
+ m->proto, 0 /* is_add */,
+ m->twice_nat,
+ is_out2in_only_static_mapping(m),
+ m->tag,
+ is_identity_static_mapping(m),
+ pool_addr, 0);
}));
/* *INDENT-ON* */
}
return rv;
vnet_feature_enable_disable ("ip4-unicast", "nat-pre-out2in",
sw_if_index, !is_del, 0, 0);
- vnet_feature_enable_disable ("ip4-output", "nat44-ed-in2out-output",
+ vnet_feature_enable_disable ("ip4-output", "nat-pre-in2out-output",
sw_if_index, !is_del, 0, 0);
}
else
u8 * is_addr_only,
twice_nat_type_t * twice_nat,
lb_nat_type_t * lb, ip4_address_t * ext_host_addr,
- u8 * is_identity_nat)
+ u8 * is_identity_nat, snat_static_mapping_t ** out)
{
clib_bihash_kv_8_8_t kv, value;
+ clib_bihash_8_8_t *mapping_hash;
snat_static_mapping_t *m;
- clib_bihash_8_8_t *mapping_hash = &sm->static_mapping_by_local;
u32 rand, lo = 0, hi, mid, *tmp = 0, i;
- u8 backend_index;
nat44_lb_addr_port_t *local;
+ u8 backend_index;
- if (by_external)
+ if (!by_external)
{
- mapping_hash = &sm->static_mapping_by_external;
- init_nat_k (&kv, match_addr, match_port, 0, match_protocol);
+ mapping_hash = &sm->static_mapping_by_local;
+ init_nat_k (&kv, match_addr, match_port, match_fib_index,
+ match_protocol);
if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
{
/* Try address only mapping */
- init_nat_k (&kv, match_addr, 0, 0, 0);
+ init_nat_k (&kv, match_addr, 0, match_fib_index, 0);
if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
return 1;
}
-
}
else
{
- init_nat_k (&kv, match_addr, match_port, match_fib_index,
- match_protocol);
+ mapping_hash = &sm->static_mapping_by_external;
+ init_nat_k (&kv, match_addr, match_port, 0, match_protocol);
if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
{
/* Try address only mapping */
- init_nat_k (&kv, match_addr, 0, match_fib_index, 0);
+ init_nat_k (&kv, match_addr, 0, 0, 0);
if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
return 1;
}
-
}
m = pool_elt_at_index (sm->static_mappings, value.value);
if (PREDICT_FALSE (is_identity_nat != 0))
*is_identity_nat = is_identity_static_mapping (m);
+ if (out != 0)
+ *out = m;
+
return 0;
}
return n_buckets * (8 + kv_size * 4);
}
+u32
+nat44_get_max_session_limit ()
+{
+ snat_main_t *sm = &snat_main;
+ u32 max_limit = 0, len = 0;
+
+ for (; len < vec_len (sm->max_translations_per_fib); len++)
+ {
+ if (max_limit < sm->max_translations_per_fib[len])
+ max_limit = sm->max_translations_per_fib[len];
+ }
+ return max_limit;
+}
+
+int
+nat44_set_session_limit (u32 session_limit, u32 vrf_id)
+{
+ snat_main_t *sm = &snat_main;
+ u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
+ u32 len = vec_len (sm->max_translations_per_fib);
+
+ if (len <= fib_index)
+ {
+ vec_validate (sm->max_translations_per_fib, fib_index + 1);
+
+ for (; len < vec_len (sm->max_translations_per_fib); len++)
+ sm->max_translations_per_fib[len] = sm->max_translations_per_thread;
+ }
+
+ sm->max_translations_per_fib[fib_index] = session_limit;
+ return 0;
+}
+
+int
+nat44_update_session_limit (u32 session_limit, u32 vrf_id)
+{
+ snat_main_t *sm = &snat_main;
+
+ if (nat44_set_session_limit (session_limit, vrf_id))
+ return 1;
+ sm->max_translations_per_thread = nat44_get_max_session_limit ();
+
+ sm->translation_buckets =
+ nat_calc_bihash_buckets (sm->max_translations_per_thread);
+
+ if (!sm->translation_memory_size_set)
+ {
+ sm->translation_memory_size =
+ nat_calc_bihash_memory (sm->translation_buckets,
+ sizeof (clib_bihash_16_8_t));
+ }
+
+ nat44_sessions_clear ();
+ return 0;
+}
+
void
nat44_db_init (snat_main_per_thread_data_t * tsm)
{
// translation buckets 1024
max_translations_per_thread = 10 * 1024;
}
+ sm->translation_memory_size_set = translation_memory_size != 0;
+
sm->max_translations_per_thread = max_translations_per_thread;
sm->translation_buckets =
nat_calc_bihash_buckets (sm->max_translations_per_thread);
rp->vrf_id,
rp->addr_only, ~0 /* sw_if_index */ ,
rp->proto, !is_delete, rp->twice_nat,
- rp->out2in_only, rp->tag, rp->identity_nat);
+ rp->out2in_only, rp->tag, rp->identity_nat,
+ rp->pool_addr, rp->exact);
if (rv)
nat_elog_notice_X1 ("snat_add_static_mapping returned %d", "i4", rv);
}
rp->proto,
rp->is_add, rp->twice_nat,
rp->out2in_only, rp->tag,
- rp->identity_nat);
+ rp->identity_nat,
+ rp->pool_addr, rp->exact);
if (rv)
nat_elog_notice_X1 ("snat_add_static_mapping returned %d",
"i4", rv);
[NAT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
[NAT_NEXT_IN2OUT_ED_FAST_PATH] = "nat44-ed-in2out",
[NAT_NEXT_IN2OUT_ED_SLOW_PATH] = "nat44-ed-in2out-slowpath",
+ [NAT_NEXT_IN2OUT_ED_OUTPUT_FAST_PATH] = "nat44-ed-in2out-output",
[NAT_NEXT_IN2OUT_ED_OUTPUT_SLOW_PATH] = "nat44-ed-in2out-output-slowpath",
[NAT_NEXT_OUT2IN_ED_FAST_PATH] = "nat44-ed-out2in",
[NAT_NEXT_OUT2IN_ED_SLOW_PATH] = "nat44-ed-out2in-slowpath",