nat44_ei_main_t nat44_ei_main;
extern vlib_node_registration_t nat44_ei_hairpinning_node;
-extern vlib_node_registration_t nat44_ei_hairpin_dst_node;
extern vlib_node_registration_t
nat44_ei_in2out_hairpinning_finish_ip4_lookup_node;
extern vlib_node_registration_t
.runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa",
"ip4-sv-reassembly-output-feature"),
};
-VNET_FEATURE_INIT (ip4_nat44_ei_in2out_fast, static) = {
- .arc_name = "ip4-unicast",
- .node_name = "nat44-ei-in2out-fast",
- .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
- "ip4-sv-reassembly-feature"),
-};
-VNET_FEATURE_INIT (ip4_nat44_ei_out2in_fast, static) = {
- .arc_name = "ip4-unicast",
- .node_name = "nat44-ei-out2in-fast",
- .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
- "ip4-sv-reassembly-feature",
- "ip4-dhcp-client-detect"),
-};
-VNET_FEATURE_INIT (ip4_nat44_ei_hairpin_dst, static) = {
- .arc_name = "ip4-unicast",
- .node_name = "nat44-ei-hairpin-dst",
- .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa",
- "ip4-sv-reassembly-feature"),
-};
-VNET_FEATURE_INIT (ip4_nat44_ei_hairpin_src, static) = {
- .arc_name = "ip4-output",
- .node_name = "nat44-ei-hairpin-src",
- .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa",
- "ip4-sv-reassembly-output-feature"),
-};
VNET_FEATURE_INIT (ip4_nat44_ei_hairpinning, static) = {
.arc_name = "ip4-local",
.node_name = "nat44-ei-hairpinning",
void nat44_ei_add_del_addr_to_fib (ip4_address_t *addr, u8 p_len,
u32 sw_if_index, int is_add);
+static void nat44_ei_worker_db_free (nat44_ei_main_per_thread_data_t *tnm);
+
+static int nat44_ei_add_static_mapping_internal (
+ ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port,
+ nat_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags,
+ ip4_address_t pool_addr, u8 *tag);
+
+static int nat44_ei_del_static_mapping_internal (
+ ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port,
+ nat_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags);
+
static u8 *
format_nat44_ei_classify_trace (u8 *s, va_list *args)
{
return s;
}
-static void nat44_ei_db_free ();
-
static void nat44_ei_db_init (u32 translations, u32 translation_buckets,
u32 user_buckets);
nm->hairpinning_fq_index =
vlib_frame_queue_main_init (nat44_ei_hairpinning_node.index, 0);
- nm->hairpin_dst_fq_index =
- vlib_frame_queue_main_init (nat44_ei_hairpin_dst_node.index, 0);
nm->in2out_hairpinning_finish_ip4_lookup_node_fq_index =
vlib_frame_queue_main_init (
nat44_ei_in2out_hairpinning_finish_ip4_lookup_node.index, 0);
nm->user_buckets);
nat44_ei_set_alloc_default ();
- // TODO: zero simple counter for all counters missing
-
vlib_zero_simple_counter (&nm->total_users, 0);
vlib_zero_simple_counter (&nm->total_sessions, 0);
vlib_zero_simple_counter (&nm->user_limit_reached, 0);
return 0;
}
-void
-nat44_ei_addresses_free (nat44_ei_address_t **addresses)
-{
- nat44_ei_address_t *ap;
- vec_foreach (ap, *addresses)
- {
-#define _(N, i, n, s) vec_free (ap->busy_##n##_ports_per_thread);
- foreach_nat_protocol
-#undef _
- }
- vec_free (*addresses);
- *addresses = 0;
-}
-
static_always_inline nat44_ei_outside_fib_t *
nat44_ei_get_outside_fib (nat44_ei_outside_fib_t *outside_fibs, u32 fib_index)
{
return 0;
}
+static_always_inline int
+nat44_ei_hairpinning_enable (u32 sw_if_index, u8 is_enable)
+{
+ return vnet_feature_enable_disable ("ip4-local", "nat44-ei-hairpinning",
+ sw_if_index, is_enable, 0, 0);
+}
+
int
nat44_ei_add_interface (u32 sw_if_index, u8 is_inside)
{
}
if (!is_inside)
{
- rv = vnet_feature_enable_disable (
- "ip4-local", "nat44-ei-hairpinning", sw_if_index, 0, 0, 0);
+ rv = nat44_ei_hairpinning_enable (sw_if_index, 0);
if (rv)
{
return rv;
}
if (is_inside && !nm->out2in_dpo)
{
- rv = vnet_feature_enable_disable (
- "ip4-local", "nat44-ei-hairpinning", sw_if_index, 1, 0, 0);
+ rv = nat44_ei_hairpinning_enable (sw_if_index, 1);
if (rv)
{
return rv;
}
else
{
- rv = vnet_feature_enable_disable (
- "ip4-local", "nat44-ei-hairpinning", sw_if_index, 1, 0, 0);
+ rv = nat44_ei_hairpinning_enable (sw_if_index, 1);
if (rv)
{
return rv;
}
if (is_inside)
{
- rv = vnet_feature_enable_disable (
- "ip4-local", "nat44-ei-hairpinning", sw_if_index, 0, 0, 0);
+ rv = nat44_ei_hairpinning_enable (sw_if_index, 0);
if (rv)
{
return rv;
}
int
-nat44_ei_plugin_disable ()
+nat44_ei_add_del_output_interface (u32 sw_if_index, int is_del)
+{
+ if (is_del)
+ {
+ return nat44_ei_del_output_interface (sw_if_index);
+ }
+ else
+ {
+ return nat44_ei_add_output_interface (sw_if_index);
+ }
+}
+
+int
+nat44_ei_del_addresses ()
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ nat44_ei_address_t *a, *vec;
+ int error = 0;
+
+ vec = vec_dup (nm->addresses);
+ vec_foreach (a, vec)
+ {
+ error = nat44_ei_del_address (a->addr, 0);
+
+ if (error)
+ {
+ nat44_ei_log_err ("error occurred while removing adderess");
+ }
+ }
+ vec_free (vec);
+ vec_free (nm->addresses);
+ nm->addresses = 0;
+
+ vec_free (nm->auto_add_sw_if_indices);
+ nm->auto_add_sw_if_indices = 0;
+ return error;
+}
+
+int
+nat44_ei_del_interfaces ()
{
nat44_ei_main_t *nm = &nat44_ei_main;
nat44_ei_interface_t *i, *pool;
int error = 0;
- // first unregister all nodes from interfaces
pool = pool_dup (nm->interfaces);
pool_foreach (i, pool)
{
if (error)
{
- nat44_ei_log_err ("error occurred while removing interface %u",
- i->sw_if_index);
+ nat44_ei_log_err ("error occurred while removing interface");
}
}
pool_free (pool);
pool_free (nm->interfaces);
+ nm->interfaces = 0;
+ return error;
+}
+
+int
+nat44_ei_del_output_interfaces ()
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ nat44_ei_interface_t *i, *pool;
+ int error = 0;
pool = pool_dup (nm->output_feature_interfaces);
pool_foreach (i, pool)
error = nat44_ei_del_output_interface (i->sw_if_index);
if (error)
{
- nat44_ei_log_err ("error occurred while removing interface %u",
- i->sw_if_index);
+ nat44_ei_log_err ("error occurred while removing output interface");
}
}
pool_free (pool);
pool_free (nm->output_feature_interfaces);
+ nm->output_feature_interfaces = 0;
+ return error;
+}
- nat_ha_disable ();
- nat44_ei_db_free ();
+int
+nat44_ei_del_static_mappings ()
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ nat44_ei_static_mapping_t *m, *pool;
+ int error = 0;
- nat44_ei_addresses_free (&nm->addresses);
+ pool = pool_dup (nm->static_mappings);
+ pool_foreach (m, pool)
+ {
+ error = nat44_ei_del_static_mapping_internal (
+ m->local_addr, m->external_addr, m->local_port, m->external_port,
+ m->proto, m->vrf_id, ~0, m->flags);
+ if (error)
+ {
+ nat44_ei_log_err ("error occurred while removing mapping");
+ }
+ }
+ pool_free (pool);
+ pool_free (nm->static_mappings);
+ nm->static_mappings = 0;
vec_free (nm->to_resolve);
- vec_free (nm->auto_add_sw_if_indices);
-
nm->to_resolve = 0;
- nm->auto_add_sw_if_indices = 0;
- nm->forwarding_enabled = 0;
+ clib_bihash_free_8_8 (&nm->static_mapping_by_local);
+ clib_bihash_free_8_8 (&nm->static_mapping_by_external);
+
+ return error;
+}
+
+int
+nat44_ei_plugin_disable ()
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ nat44_ei_main_per_thread_data_t *tnm;
+ int rc, error = 0;
+
+ nat_ha_disable ();
+
+ rc = nat44_ei_del_static_mappings ();
+ if (rc)
+ error = 1;
+
+ rc = nat44_ei_del_addresses ();
+ if (rc)
+ error = 1;
+
+ rc = nat44_ei_del_interfaces ();
+ if (rc)
+ error = 1;
+
+ rc = nat44_ei_del_output_interfaces ();
+ if (rc)
+ error = 1;
+
+ if (nm->pat)
+ {
+ clib_bihash_free_8_8 (&nm->in2out);
+ clib_bihash_free_8_8 (&nm->out2in);
+
+ vec_foreach (tnm, nm->per_thread_data)
+ {
+ nat44_ei_worker_db_free (tnm);
+ }
+ }
- nm->enabled = 0;
clib_memset (&nm->rconfig, 0, sizeof (nm->rconfig));
- return 0;
+ nm->forwarding_enabled = 0;
+ nm->enabled = 0;
+
+ return error;
}
int
u16 l_port, u16 e_port, nat_protocol_t proto,
u32 vrf_id, u32 sw_if_index, u32 flags,
ip4_address_t pool_addr, u8 *tag)
+
{
nat44_ei_main_t *nm = &nat44_ei_main;
- clib_bihash_kv_8_8_t kv, value;
- nat44_ei_lb_addr_port_t *local;
- nat44_ei_static_mapping_t *m;
- u32 fib_index = ~0;
- u32 worker_index;
-
- fail_if_disabled ();
- if (is_sm_addr_only (flags))
+ if (is_sm_switch_address (flags))
{
- e_port = l_port = proto = 0;
- }
-
- if (sw_if_index != ~0)
- {
- // this mapping is interface bound
- ip4_address_t *first_int_addr;
-
- // check if this record isn't registered for resolve
if (!nat44_ei_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
sw_if_index, flags, 0))
{
return VNET_API_ERROR_VALUE_EXIST;
}
- // register record for resolve
+
nat44_ei_add_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
sw_if_index, flags, pool_addr, tag);
- first_int_addr =
+ ip4_address_t *first_int_addr =
ip4_interface_first_address (nm->ip4_main, sw_if_index, 0);
if (!first_int_addr)
{
e_addr.as_u32 = first_int_addr->as_u32;
}
+ return nat44_ei_add_static_mapping_internal (l_addr, e_addr, l_port, e_port,
+ proto, vrf_id, sw_if_index,
+ flags, pool_addr, tag);
+}
+
+int
+nat44_ei_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
+ u16 l_port, u16 e_port, nat_protocol_t proto,
+ u32 vrf_id, u32 sw_if_index, u32 flags)
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+
+ if (is_sm_switch_address (flags))
+ {
+
+ if (nat44_ei_del_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
+ sw_if_index, flags))
+ {
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+ }
+
+ ip4_address_t *first_int_addr =
+ ip4_interface_first_address (nm->ip4_main, sw_if_index, 0);
+ if (!first_int_addr)
+ {
+ // dhcp resolution required
+ return 0;
+ }
+
+ e_addr.as_u32 = first_int_addr->as_u32;
+ }
+
+ return nat44_ei_del_static_mapping_internal (
+ l_addr, e_addr, l_port, e_port, proto, vrf_id, sw_if_index, flags);
+}
+
+static int
+nat44_ei_add_static_mapping_internal (ip4_address_t l_addr,
+ ip4_address_t e_addr, u16 l_port,
+ u16 e_port, nat_protocol_t proto,
+ u32 vrf_id, u32 sw_if_index, u32 flags,
+ ip4_address_t pool_addr, u8 *tag)
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ clib_bihash_kv_8_8_t kv, value;
+ nat44_ei_lb_addr_port_t *local;
+ nat44_ei_static_mapping_t *m;
+ u32 fib_index = ~0;
+ u32 worker_index;
+
+ fail_if_disabled ();
+
+ if (is_sm_addr_only (flags))
+ {
+ e_port = l_port = proto = 0;
+ }
+
if (is_sm_identity_nat (flags))
{
l_port = e_port;
if (nat44_ei_reserve_port (e_addr, e_port, proto))
{
// remove resolve record
- if ((sw_if_index != ~0) && !is_sm_identity_nat (flags))
+ if ((is_sm_switch_address (flags)) && !is_sm_identity_nat (flags))
{
nat44_ei_del_resolve_record (l_addr, l_port, e_port, proto,
vrf_id, sw_if_index, flags);
return 0;
}
-int
-nat44_ei_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
- u16 l_port, u16 e_port, nat_protocol_t proto,
- u32 vrf_id, u32 sw_if_index, u32 flags)
+static int
+nat44_ei_del_static_mapping_internal (ip4_address_t l_addr,
+ ip4_address_t e_addr, u16 l_port,
+ u16 e_port, nat_protocol_t proto,
+ u32 vrf_id, u32 sw_if_index, u32 flags)
{
nat44_ei_main_per_thread_data_t *tnm;
nat44_ei_main_t *nm = &nat44_ei_main;
e_port = l_port = proto = 0;
}
- if (sw_if_index != ~0)
- {
- // this mapping is interface bound
- ip4_address_t *first_int_addr;
-
- // delete record registered for resolve
- if (nat44_ei_del_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
- sw_if_index, flags))
- {
- return VNET_API_ERROR_NO_SUCH_ENTRY;
- }
-
- first_int_addr =
- ip4_interface_first_address (nm->ip4_main, sw_if_index, 0);
- if (!first_int_addr)
- {
- // dhcp resolution required
- return 0;
- }
-
- e_addr.as_u32 = first_int_addr->as_u32;
- }
-
if (is_sm_identity_nat (flags))
{
l_port = e_port;
if (clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv, &value))
{
- if (sw_if_index != ~0)
+ if (is_sm_switch_address (flags))
{
return 0;
}
clib_dlist_init (tnm->lru_pool, tnm->unk_proto_lru_head_index);
}
-static void
-nat44_ei_db_free ()
-{
- nat44_ei_main_t *nm = &nat44_ei_main;
- nat44_ei_main_per_thread_data_t *tnm;
-
- pool_free (nm->static_mappings);
- clib_bihash_free_8_8 (&nm->static_mapping_by_local);
- clib_bihash_free_8_8 (&nm->static_mapping_by_external);
-
- if (nm->pat)
- {
- clib_bihash_free_8_8 (&nm->in2out);
- clib_bihash_free_8_8 (&nm->out2in);
- vec_foreach (tnm, nm->per_thread_data)
- {
- nat44_ei_worker_db_free (tnm);
- }
- }
-}
-
static void
nat44_ei_db_init (u32 translations, u32 translation_buckets, u32 user_buckets)
{
pool_foreach (m, nm->static_mappings)
{
if (m->external_addr.as_u32 == addr.as_u32)
- nat44_ei_del_static_mapping (m->local_addr, m->external_addr,
- m->local_port, m->external_port,
- m->proto, m->vrf_id, ~0, m->flags);
+ nat44_ei_del_static_mapping_internal (
+ m->local_addr, m->external_addr, m->local_port, m->external_port,
+ m->proto, m->vrf_id, ~0, m->flags);
}
}
else
}
}
- if (a->fib_index != ~0)
- {
- fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP4, nm->fib_src_low);
- }
-
/* Delete sessions using address */
if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
{
}
}
+ nat44_ei_add_del_addr_to_fib_foreach_out_if (&addr, 0);
+
+ if (a->fib_index != ~0)
+ {
+ fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP4, nm->fib_src_low);
+ }
+
#define _(N, i, n, s) vec_free (a->busy_##n##_ports_per_thread);
foreach_nat_protocol
#undef _
vec_del1 (nm->addresses, j);
-
- nat44_ei_add_del_addr_to_fib_foreach_out_if (&addr, 0);
-
return 0;
}
/* On this interface? */
if (rp->sw_if_index == sw_if_index)
{
- rv = nat44_ei_add_static_mapping (
+ rv = nat44_ei_add_static_mapping_internal (
rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto,
rp->vrf_id, ~0, rp->flags, rp->pool_addr, rp->tag);
if (rv)
{
- nat_elog_notice_X1 (nm, "add_static_mapping returned %d",
- "i4", rv);
+ nat_elog_notice_X1 (
+ nm, "add_static_mapping_internal returned %d", "i4", rv);
}
}
}
{
if (!m)
return;
- rv = nat44_ei_del_static_mapping (rp->l_addr, address[0], rp->l_port,
- rp->e_port, rp->proto, rp->vrf_id, ~0,
- rp->flags);
+ rv = nat44_ei_del_static_mapping_internal (
+ rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto, rp->vrf_id,
+ ~0, rp->flags);
if (rv)
{
nat_elog_notice_X1 (nm, "nat44_ei_del_static_mapping returned %d",
{
if (m)
return;
- rv = nat44_ei_add_static_mapping (rp->l_addr, address[0], rp->l_port,
- rp->e_port, rp->proto, rp->vrf_id, ~0,
- rp->flags, rp->pool_addr, rp->tag);
+ rv = nat44_ei_add_static_mapping_internal (
+ rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto, rp->vrf_id,
+ ~0, rp->flags, rp->pool_addr, rp->tag);
+
if (rv)
{
nat_elog_notice_X1 (nm, "nat44_ei_add_static_mapping returned %d",