summaryrefslogtreecommitdiffstats
path: root/src/plugins/nat/nat44-ed/nat44_ed.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/nat/nat44-ed/nat44_ed.c')
-rw-r--r--src/plugins/nat/nat44-ed/nat44_ed.c806
1 files changed, 363 insertions, 443 deletions
diff --git a/src/plugins/nat/nat44-ed/nat44_ed.c b/src/plugins/nat/nat44-ed/nat44_ed.c
index 7907d8ffa6b..d3ef3d54f89 100644
--- a/src/plugins/nat/nat44-ed/nat44_ed.c
+++ b/src/plugins/nat/nat44-ed/nat44_ed.c
@@ -185,9 +185,11 @@ static int nat44_ed_add_static_mapping_internal (
ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port,
ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags,
ip4_address_t pool_addr, u8 *tag);
-static int nat44_ed_del_static_mapping_internal (
- ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port,
- ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags);
+static int nat44_ed_del_static_mapping_internal (ip4_address_t l_addr,
+ ip4_address_t e_addr,
+ u16 l_port, u16 e_port,
+ ip_protocol_t proto,
+ u32 vrf_id, u32 flags);
u32 nat_calc_bihash_buckets (u32 n_elts);
@@ -290,25 +292,6 @@ nat44_ed_free_session_data (snat_main_t *sm, snat_session_t *s,
}
}
-static int
-is_snat_address_used_in_static_mapping (snat_main_t *sm, ip4_address_t addr)
-{
- snat_static_mapping_t *m;
- pool_foreach (m, sm->static_mappings)
- {
- if (is_sm_addr_only (m->flags) || is_sm_out2in_only (m->flags) ||
- is_sm_identity_nat (m->flags))
- {
- continue;
- }
- if (m->external_addr.as_u32 == addr.as_u32)
- {
- return 1;
- }
- }
- return 0;
-}
-
static ip_interface_address_t *
nat44_ed_get_ip_interface_address (u32 sw_if_index, ip4_address_t addr)
{
@@ -415,41 +398,91 @@ nat44_ed_bind_if_addr_to_nat_addr (u32 sw_if_index)
}
}
+static_always_inline snat_fib_entry_reg_t *
+nat44_ed_get_fib_entry_reg (ip4_address_t addr, u32 sw_if_index, int *out_idx)
+{
+ snat_main_t *sm = &snat_main;
+ snat_fib_entry_reg_t *fe;
+ int i;
+
+ for (i = 0; i < vec_len (sm->fib_entry_reg); i++)
+ {
+ fe = sm->fib_entry_reg + i;
+ if ((addr.as_u32 == fe->addr.as_u32) && (sw_if_index == fe->sw_if_index))
+ {
+ if (out_idx)
+ {
+ *out_idx = i;
+ }
+ return fe;
+ }
+ }
+ return NULL;
+}
+
static void
-nat44_ed_add_del_addr_to_fib (ip4_address_t *addr, u8 p_len, u32 sw_if_index,
- int is_add)
+nat44_ed_add_fib_entry_reg (ip4_address_t addr, u32 sw_if_index)
{
// Add the external NAT address to the FIB as receive entries. This ensures
// that VPP will reply to ARP for this address and we don't need to enable
// proxy ARP on the outside interface.
-
snat_main_t *sm = &snat_main;
- fib_prefix_t prefix = {
- .fp_len = p_len,
- .fp_proto = FIB_PROTOCOL_IP4,
- .fp_addr = {
- .ip4.as_u32 = addr->as_u32,
- },
- };
- u32 fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
+ snat_fib_entry_reg_t *fe;
- if (is_add)
+ if (!(fe = nat44_ed_get_fib_entry_reg (addr, sw_if_index, 0)))
{
+ fib_prefix_t prefix = {
+ .fp_len = 32,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ .fp_addr = {
+ .ip4.as_u32 = addr.as_u32,
+ },
+ };
+ u32 fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
fib_table_entry_update_one_path (fib_index, &prefix, sm->fib_src_low,
(FIB_ENTRY_FLAG_CONNECTED |
FIB_ENTRY_FLAG_LOCAL |
FIB_ENTRY_FLAG_EXCLUSIVE),
DPO_PROTO_IP4, NULL, sw_if_index, ~0, 1,
NULL, FIB_ROUTE_PATH_FLAG_NONE);
+
+ vec_add2 (sm->fib_entry_reg, fe, 1);
+ clib_memset (fe, 0, sizeof (*fe));
+ fe->addr.as_u32 = addr.as_u32;
+ fe->sw_if_index = sw_if_index;
}
- else
+ fe->count++;
+}
+
+static void
+nat44_ed_del_fib_entry_reg (ip4_address_t addr, u32 sw_if_index)
+{
+ snat_main_t *sm = &snat_main;
+ snat_fib_entry_reg_t *fe;
+ int i;
+
+ if ((fe = nat44_ed_get_fib_entry_reg (addr, sw_if_index, &i)))
{
- fib_table_entry_delete (fib_index, &prefix, sm->fib_src_low);
+ fe->count--;
+ if (0 == fe->count)
+ {
+ fib_prefix_t prefix = {
+ .fp_len = 32,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ .fp_addr = {
+ .ip4.as_u32 = addr.as_u32,
+ },
+ };
+ u32 fib_index =
+ ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
+ fib_table_entry_delete (fib_index, &prefix, sm->fib_src_low);
+ vec_del1 (sm->fib_entry_reg, i);
+ }
}
}
static void
-nat44_ed_add_del_addr_to_fib_foreach_out_if (ip4_address_t *addr, u8 is_add)
+nat44_ed_add_del_interface_fib_reg_entries (ip4_address_t addr, u8 is_add)
{
snat_main_t *sm = &snat_main;
snat_interface_t *i;
@@ -458,42 +491,66 @@ nat44_ed_add_del_addr_to_fib_foreach_out_if (ip4_address_t *addr, u8 is_add)
{
if (nat44_ed_is_interface_outside (i))
{
- nat44_ed_add_del_addr_to_fib (addr, 32, i->sw_if_index, is_add);
+ if (is_add)
+ {
+ nat44_ed_add_fib_entry_reg (addr, i->sw_if_index);
+ }
+ else
+ {
+ nat44_ed_del_fib_entry_reg (addr, i->sw_if_index);
+ }
}
}
pool_foreach (i, sm->output_feature_interfaces)
{
if (nat44_ed_is_interface_outside (i))
{
- nat44_ed_add_del_addr_to_fib (addr, 32, i->sw_if_index, is_add);
+ if (is_add)
+ {
+ nat44_ed_add_fib_entry_reg (addr, i->sw_if_index);
+ }
+ else
+ {
+ nat44_ed_del_fib_entry_reg (addr, i->sw_if_index);
+ }
}
}
}
static_always_inline void
-nat44_ed_add_del_addr_to_fib_foreach_addr (u32 sw_if_index, u8 is_add)
+nat44_ed_add_del_nat_addr_fib_reg_entries (u32 sw_if_index, u8 is_add)
{
snat_main_t *sm = &snat_main;
snat_address_t *ap;
vec_foreach (ap, sm->addresses)
{
- nat44_ed_add_del_addr_to_fib (&ap->addr, 32, sw_if_index, is_add);
+ if (is_add)
+ {
+ nat44_ed_add_fib_entry_reg (ap->addr, sw_if_index);
+ }
+ else
+ {
+ nat44_ed_del_fib_entry_reg (ap->addr, sw_if_index);
+ }
}
}
static_always_inline void
-nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (u32 sw_if_index, u8 is_add)
+nat44_ed_add_del_sm_fib_reg_entries (u32 sw_if_index, u8 is_add)
{
snat_main_t *sm = &snat_main;
snat_static_mapping_t *m;
pool_foreach (m, sm->static_mappings)
{
- if (is_sm_addr_only (m->flags) && !is_sm_identity_nat (m->flags))
+ if (is_add)
{
- nat44_ed_add_del_addr_to_fib (&m->external_addr, 32, sw_if_index,
- is_add);
+ nat44_ed_add_fib_entry_reg (m->external_addr, sw_if_index);
+ }
+ else
+ {
+ nat44_ed_del_fib_entry_reg (m->external_addr, sw_if_index);
}
}
}
@@ -544,21 +601,20 @@ nat44_ed_add_address (ip4_address_t *addr, u32 vrf_id, u8 twice_nat)
{
// if we don't have enabled interface we don't add address
// to fib
- nat44_ed_add_del_addr_to_fib_foreach_out_if (addr, 1);
+ nat44_ed_add_del_interface_fib_reg_entries (*addr, 1);
nat44_ed_update_outside_if_addresses (ap);
}
return 0;
}
int
-nat44_ed_del_address (ip4_address_t addr, u8 delete_sm, u8 twice_nat)
+nat44_ed_del_address (ip4_address_t addr, u8 twice_nat)
{
snat_main_t *sm = &snat_main;
snat_address_t *a = 0, *addresses;
snat_session_t *ses;
u32 *ses_to_be_removed = 0, *ses_index;
snat_main_per_thread_data_t *tsm;
- snat_static_mapping_t *m;
int j;
addresses = twice_nat ? sm->twice_nat_addresses : sm->addresses;
@@ -577,33 +633,15 @@ nat44_ed_del_address (ip4_address_t addr, u8 delete_sm, u8 twice_nat)
return VNET_API_ERROR_NO_SUCH_ENTRY;
}
- if (delete_sm)
- {
- pool_foreach (m, sm->static_mappings)
- {
- if (m->external_addr.as_u32 == addr.as_u32)
- {
- nat44_ed_del_static_mapping_internal (
- m->local_addr, m->external_addr, m->local_port,
- m->external_port, ip_proto_to_nat_proto (m->proto), m->vrf_id,
- ~0, m->flags);
- }
- }
- }
- else
- {
- if (is_snat_address_used_in_static_mapping (sm, addr))
- {
- nat_log_err ("address used in static mapping");
- return VNET_API_ERROR_UNSPECIFIED;
- }
- }
-
- // delete sessions using address
+ // delete dynamic sessions only
vec_foreach (tsm, sm->per_thread_data)
{
pool_foreach (ses, tsm->sessions)
{
+ if (ses->flags & SNAT_SESSION_FLAG_STATIC_MAPPING)
+ {
+ continue;
+ }
if (ses->out2in.addr.as_u32 == addr.as_u32)
{
nat44_ed_free_session_data (sm, ses, tsm - sm->per_thread_data,
@@ -621,7 +659,7 @@ nat44_ed_del_address (ip4_address_t addr, u8 delete_sm, u8 twice_nat)
if (!twice_nat)
{
- nat44_ed_add_del_addr_to_fib_foreach_out_if (&addr, 0);
+ nat44_ed_add_del_interface_fib_reg_entries (addr, 0);
}
if (a->fib_index != ~0)
@@ -730,38 +768,18 @@ nat44_ed_sm_i2o_lookup (snat_main_t *sm, ip4_address_t addr, u16 port,
return nat44_ed_sm_lookup (sm, &kv);
}
-void
-nat44_ed_add_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port,
- ip_protocol_t proto, u32 vrf_id, u32 sw_if_index,
- u32 flags, ip4_address_t pool_addr, u8 *tag)
-{
- snat_static_map_resolve_t *rp;
- snat_main_t *sm = &snat_main;
-
- vec_add2 (sm->to_resolve, rp, 1);
- rp->l_addr.as_u32 = l_addr.as_u32;
- rp->l_port = l_port;
- rp->e_port = e_port;
- rp->sw_if_index = sw_if_index;
- rp->vrf_id = vrf_id;
- rp->proto = proto;
- rp->flags = flags;
- rp->pool_addr = pool_addr;
- rp->tag = vec_dup (tag);
-}
-
-int
+static snat_static_mapping_resolve_t *
nat44_ed_get_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port,
ip_protocol_t proto, u32 vrf_id, u32 sw_if_index,
- u32 flags, int *out)
+ u32 flags, int *out_idx)
{
- snat_static_map_resolve_t *rp;
+ snat_static_mapping_resolve_t *rp;
snat_main_t *sm = &snat_main;
int i;
- for (i = 0; i < vec_len (sm->to_resolve); i++)
+ for (i = 0; i < vec_len (sm->sm_to_resolve); i++)
{
- rp = sm->to_resolve + i;
+ rp = sm->sm_to_resolve + i;
if (rp->sw_if_index == sw_if_index && rp->vrf_id == vrf_id)
{
@@ -790,27 +808,27 @@ nat44_ed_get_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port,
{
continue;
}
- if (out)
+ if (out_idx)
{
- *out = i;
+ *out_idx = i;
}
- return 0;
+ return rp;
}
}
- return 1;
+ return NULL;
}
-int
+static int
nat44_ed_del_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port,
ip_protocol_t proto, u32 vrf_id, u32 sw_if_index,
u32 flags)
{
snat_main_t *sm = &snat_main;
int i;
- if (!nat44_ed_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
- sw_if_index, flags, &i))
+ if (nat44_ed_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
+ sw_if_index, flags, &i))
{
- vec_del1 (sm->to_resolve, i);
+ vec_del1 (sm->sm_to_resolve, i);
return 0;
}
return 1;
@@ -835,50 +853,69 @@ nat44_ed_validate_sm_input (u32 flags)
return 0;
}
-snat_address_t *
-nat44_ed_addr_lookup (snat_main_t *sm, u32 addr)
-{
- for (int i = 0; i < vec_len (sm->addresses); ++i)
- {
- if (sm->addresses[i].addr.as_u32 == addr)
- return &sm->addresses[i];
- }
- return NULL;
-}
-
int
nat44_ed_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
u16 l_port, u16 e_port, ip_protocol_t proto,
u32 vrf_id, u32 sw_if_index, u32 flags,
ip4_address_t pool_addr, u8 *tag)
{
+ snat_static_mapping_resolve_t *rp;
snat_main_t *sm = &snat_main;
+ int rv;
+
+ if (!sm->enabled)
+ {
+ return VNET_API_ERROR_UNSUPPORTED;
+ }
+
+ rv = nat44_ed_validate_sm_input (flags);
+ if (rv != 0)
+ {
+ return rv;
+ }
// interface bound mapping
if (is_sm_switch_address (flags))
{
- if (!nat44_ed_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
- sw_if_index, flags, 0))
+ if (nat44_ed_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
+ sw_if_index, flags, 0))
{
return VNET_API_ERROR_VALUE_EXIST;
}
- nat44_ed_add_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
- sw_if_index, flags, pool_addr, tag);
+ vec_add2 (sm->sm_to_resolve, rp, 1);
+ rp->l_addr.as_u32 = l_addr.as_u32;
+ rp->l_port = l_port;
+ rp->e_port = e_port;
+ rp->sw_if_index = sw_if_index;
+ rp->vrf_id = vrf_id;
+ rp->proto = proto;
+ rp->flags = flags;
+ rp->pool_addr = pool_addr;
+ rp->tag = vec_dup (tag);
+ rp->is_resolved = 0;
+
ip4_address_t *first_int_addr =
ip4_interface_first_address (sm->ip4_main, sw_if_index, 0);
if (!first_int_addr)
{
- // dhcp resolution required
return 0;
}
e_addr.as_u32 = first_int_addr->as_u32;
+ rp->is_resolved = 1;
+ }
+
+ rv = nat44_ed_add_static_mapping_internal (l_addr, e_addr, l_port, e_port,
+ proto, vrf_id, sw_if_index, flags,
+ pool_addr, tag);
+ if ((0 != rv) && is_sm_switch_address (flags))
+ {
+ nat44_ed_del_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
+ sw_if_index, flags);
}
- return nat44_ed_add_static_mapping_internal (l_addr, e_addr, l_port, e_port,
- proto, vrf_id, sw_if_index,
- flags, pool_addr, tag);
+ return rv;
}
int
@@ -886,8 +923,19 @@ nat44_ed_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
u16 l_port, u16 e_port, ip_protocol_t proto,
u32 vrf_id, u32 sw_if_index, u32 flags)
{
-
snat_main_t *sm = &snat_main;
+ int rv;
+
+ if (!sm->enabled)
+ {
+ return VNET_API_ERROR_UNSUPPORTED;
+ }
+
+ rv = nat44_ed_validate_sm_input (flags);
+ if (rv != 0)
+ {
+ return rv;
+ }
// interface bound mapping
if (is_sm_switch_address (flags))
@@ -909,8 +957,8 @@ nat44_ed_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
e_addr.as_u32 = first_int_addr->as_u32;
}
- return nat44_ed_del_static_mapping_internal (
- l_addr, e_addr, l_port, e_port, proto, vrf_id, sw_if_index, flags);
+ return nat44_ed_del_static_mapping_internal (l_addr, e_addr, l_port, e_port,
+ proto, vrf_id, flags);
}
static int
@@ -924,18 +972,6 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr,
nat44_lb_addr_port_t *local;
snat_static_mapping_t *m;
u32 fib_index = ~0;
- int rv;
-
- if (!sm->enabled)
- {
- return VNET_API_ERROR_UNSUPPORTED;
- }
-
- rv = nat44_ed_validate_sm_input (flags);
- if (rv != 0)
- {
- return rv;
- }
if (is_sm_addr_only (flags))
{
@@ -951,13 +987,14 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr,
m = nat44_ed_sm_o2i_lookup (sm, e_addr, e_port, 0, proto);
if (m)
{
+ // case:
+ // adding local identity nat record for different vrf table
+
if (!is_sm_identity_nat (m->flags))
{
return VNET_API_ERROR_VALUE_EXIST;
}
- // case:
- // adding local identity nat record for different vrf table
pool_foreach (local, m->locals)
{
if (local->vrf_id == vrf_id)
@@ -1001,21 +1038,6 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr,
}
}
- if (!(is_sm_out2in_only (flags) || is_sm_addr_only (flags) ||
- sm->static_mapping_only))
- {
- if (!nat44_ed_addr_lookup (sm, e_addr.as_u32))
- {
- // remove resolve record
- if (is_sm_switch_address (flags) && !is_sm_identity_nat (flags))
- {
- nat44_ed_del_resolve_record (l_addr, l_port, e_port, proto,
- vrf_id, sw_if_index, flags);
- }
- return VNET_API_ERROR_NO_SUCH_ENTRY;
- }
- }
-
pool_get (sm->static_mappings, m);
clib_memset (m, 0, sizeof (*m));
@@ -1023,13 +1045,9 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr,
m->local_addr = l_addr;
m->external_addr = e_addr;
+ m->pool_addr = pool_addr;
m->tag = vec_dup (tag);
- if (is_sm_exact_address (flags) && is_sm_twice_nat (flags))
- {
- m->pool_addr = pool_addr;
- }
-
if (!is_sm_addr_only (flags))
{
m->local_port = l_port;
@@ -1048,12 +1066,6 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr,
{
m->vrf_id = vrf_id;
m->fib_index = fib_index;
-
- // not identity && addr only
- if (is_sm_addr_only (flags))
- {
- nat44_ed_add_del_addr_to_fib_foreach_out_if (&e_addr, 1);
- }
}
if (!is_sm_out2in_only (flags))
@@ -1076,6 +1088,8 @@ nat44_ed_add_static_mapping_internal (ip4_address_t l_addr,
vec_add1 (m->workers, worker_index);
}
+ nat44_ed_add_del_interface_fib_reg_entries (e_addr, 1);
+
return 0;
}
@@ -1083,7 +1097,7 @@ static int
nat44_ed_del_static_mapping_internal (ip4_address_t l_addr,
ip4_address_t e_addr, u16 l_port,
u16 e_port, ip_protocol_t proto,
- u32 vrf_id, u32 sw_if_index, u32 flags)
+ u32 vrf_id, u32 flags)
{
snat_main_per_thread_data_t *tsm;
snat_main_t *sm = &snat_main;
@@ -1091,18 +1105,6 @@ nat44_ed_del_static_mapping_internal (ip4_address_t l_addr,
nat44_lb_addr_port_t *local;
snat_static_mapping_t *m;
u32 fib_index = ~0;
- int rv;
-
- if (!sm->enabled)
- {
- return VNET_API_ERROR_UNSUPPORTED;
- }
-
- rv = nat44_ed_validate_sm_input (flags);
- if (rv != 0)
- {
- return rv;
- }
if (is_sm_addr_only (flags))
{
@@ -1117,13 +1119,8 @@ nat44_ed_del_static_mapping_internal (ip4_address_t l_addr,
// fib index 0
m = nat44_ed_sm_o2i_lookup (sm, e_addr, e_port, 0, proto);
-
if (!m)
{
- if (is_sm_switch_address (flags))
- {
- return 0;
- }
return VNET_API_ERROR_NO_SUCH_ENTRY;
}
@@ -1157,33 +1154,25 @@ nat44_ed_del_static_mapping_internal (ip4_address_t l_addr,
fib_index = m->fib_index;
}
- if (!(is_sm_out2in_only (flags) || is_sm_addr_only (flags) ||
- sm->static_mapping_only))
- {
- if (!nat44_ed_addr_lookup (sm, e_addr.as_u32))
- {
- return VNET_API_ERROR_INVALID_VALUE;
- }
- }
-
if (!is_sm_out2in_only (flags))
{
nat44_ed_sm_i2o_del (sm, l_addr, l_port, fib_index, proto);
}
- if (!sm->static_mapping_only || sm->static_mapping_connection_tracking)
+ // delete sessions for static mapping
+ if (sm->num_workers > 1)
{
- // delete sessions for static mapping
- if (sm->num_workers > 1)
- tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]);
- else
- tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
-
- nat_ed_static_mapping_del_sessions (
- sm, tsm, m->local_addr, m->local_port, m->proto, fib_index,
- is_sm_addr_only (flags), e_addr, e_port);
+ tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]);
+ }
+ else
+ {
+ tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
}
+ nat_ed_static_mapping_del_sessions (sm, tsm, m->local_addr, m->local_port,
+ m->proto, fib_index,
+ is_sm_addr_only (flags), e_addr, e_port);
+
fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low);
if (!pool_elts (m->locals))
@@ -1196,10 +1185,7 @@ nat44_ed_del_static_mapping_internal (ip4_address_t l_addr,
vec_free (m->workers);
pool_put (sm->static_mappings, m);
- if (is_sm_addr_only (flags) && !is_sm_identity_nat (flags))
- {
- nat44_ed_add_del_addr_to_fib_foreach_out_if (&e_addr, 0);
- }
+ nat44_ed_add_del_interface_fib_reg_entries (e_addr, 0);
}
return 0;
@@ -1238,7 +1224,7 @@ nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
return VNET_API_ERROR_INVALID_VALUE;
}
- if (!(sm->static_mapping_only || is_sm_out2in_only (flags)))
+ if (!is_sm_out2in_only (flags))
{
/* Find external address in allocated addresses and reserve port for
address and port pair mapping when dynamic translations enabled */
@@ -1282,7 +1268,7 @@ nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
if (nat44_ed_sm_o2i_add (sm, m, m->external_addr, m->external_port, 0,
m->proto))
{
- nat_elog_err (sm, "sm o2i key add failed");
+ nat_log_err ("sm o2i key add failed");
return VNET_API_ERROR_UNSPECIFIED;
}
@@ -1294,7 +1280,7 @@ nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
{
if (nat44_ed_sm_o2i_add (sm, m, e_addr, e_port, 0, proto))
{
- nat_elog_err (sm, "sm o2i key add failed");
+ nat_log_err ("sm o2i key add failed");
rc = VNET_API_ERROR_UNSPECIFIED;
// here we continue with add operation so that it can be safely
// reversed in delete path - otherwise we'd have to track what
@@ -1357,7 +1343,7 @@ nat44_ed_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
if (nat44_ed_sm_o2i_del (sm, m->external_addr, m->external_port, 0,
m->proto))
{
- nat_elog_err (sm, "sm o2i key del failed");
+ nat_log_err ("sm o2i key del failed");
return VNET_API_ERROR_UNSPECIFIED;
}
@@ -1369,7 +1355,7 @@ nat44_ed_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
if (nat44_ed_sm_i2o_del (sm, local->addr, local->port,
local->fib_index, m->proto))
{
- nat_elog_err (sm, "sm i2o key del failed");
+ nat_log_err ("sm i2o key del failed");
return VNET_API_ERROR_UNSPECIFIED;
}
}
@@ -1478,7 +1464,7 @@ nat44_ed_add_del_lb_static_mapping_local (ip4_address_t e_addr, u16 e_port,
if (nat44_ed_sm_i2o_add (sm, m, l_addr, l_port, local->fib_index,
proto))
{
- nat_elog_err (sm, "sm i2o key add failed");
+ nat_log_err ("sm i2o key add failed");
pool_put (m->locals, local);
return VNET_API_ERROR_UNSPECIFIED;
}
@@ -1499,7 +1485,7 @@ nat44_ed_add_del_lb_static_mapping_local (ip4_address_t e_addr, u16 e_port,
{
if (nat44_ed_sm_i2o_del (sm, l_addr, l_port, match_local->fib_index,
proto))
- nat_elog_err (sm, "sm i2o key del failed");
+ nat_log_err ("sm i2o key del failed");
}
if (sm->num_workers > 1)
@@ -1747,8 +1733,8 @@ nat44_ed_add_interface (u32 sw_if_index, u8 is_inside)
outside_fib->refcount = 1;
}
- nat44_ed_add_del_addr_to_fib_foreach_addr (sw_if_index, 1);
- nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 1);
+ nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 1);
+ nat44_ed_add_del_sm_fib_reg_entries (sw_if_index, 1);
nat44_ed_bind_if_addr_to_nat_addr (sw_if_index);
}
@@ -1858,8 +1844,8 @@ nat44_ed_del_interface (u32 sw_if_index, u8 is_inside)
}
}
- nat44_ed_add_del_addr_to_fib_foreach_addr (sw_if_index, 0);
- nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 0);
+ nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 0);
+ nat44_ed_add_del_sm_fib_reg_entries (sw_if_index, 0);
}
return 0;
@@ -1957,8 +1943,8 @@ nat44_ed_add_output_interface (u32 sw_if_index)
outside_fib->refcount = 1;
}
- nat44_ed_add_del_addr_to_fib_foreach_addr (sw_if_index, 1);
- nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 1);
+ nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 1);
+ nat44_ed_add_del_sm_fib_reg_entries (sw_if_index, 1);
nat44_ed_bind_if_addr_to_nat_addr (sw_if_index);
@@ -2045,8 +2031,8 @@ nat44_ed_del_output_interface (u32 sw_if_index)
}
}
- nat44_ed_add_del_addr_to_fib_foreach_addr (sw_if_index, 0);
- nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 0);
+ nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 0);
+ nat44_ed_add_del_sm_fib_reg_entries (sw_if_index, 0);
return 0;
}
@@ -2103,7 +2089,7 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index,
}
pool_foreach (i, sm->interfaces)
- {
+ {
if (i->sw_if_index == sw_if_index)
{
if (!(nat44_ed_is_interface_outside (i)))
@@ -2113,7 +2099,7 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index,
}
pool_foreach (i, sm->output_feature_interfaces)
- {
+ {
if (i->sw_if_index == sw_if_index)
{
if (!(nat44_ed_is_interface_outside (i)))
@@ -2126,25 +2112,25 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index,
return;
vec_foreach (outside_fib, sm->outside_fibs)
- {
- if (outside_fib->fib_index == old_fib_index)
- {
- outside_fib->refcount--;
- if (!outside_fib->refcount)
- vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
- break;
- }
- }
+ {
+ if (outside_fib->fib_index == old_fib_index)
+ {
+ outside_fib->refcount--;
+ if (!outside_fib->refcount)
+ vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
+ break;
+ }
+ }
vec_foreach (outside_fib, sm->outside_fibs)
- {
- if (outside_fib->fib_index == new_fib_index)
- {
- outside_fib->refcount++;
- is_add = 0;
- break;
- }
- }
+ {
+ if (outside_fib->fib_index == new_fib_index)
+ {
+ outside_fib->refcount++;
+ is_add = 0;
+ break;
+ }
+ }
if (is_add)
{
@@ -2162,7 +2148,7 @@ static void nat44_ed_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 void nat44_ed_add_del_static_mapping_addr_only_cb (
+static void nat44_ed_add_del_static_mapping_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);
@@ -2351,7 +2337,7 @@ nat_init (vlib_main_t * vm)
/* callbacks to call when interface address changes. */
cbi.function = nat44_ed_add_del_interface_address_cb;
vec_add1 (sm->ip4_main->add_del_interface_address_callbacks, cbi);
- cbi.function = nat44_ed_add_del_static_mapping_addr_only_cb;
+ cbi.function = nat44_ed_add_del_static_mapping_cb;
vec_add1 (sm->ip4_main->add_del_interface_address_callbacks, cbi);
/* callbacks to call when interface to table biding changes */
@@ -2380,19 +2366,8 @@ nat44_plugin_enable (nat44_config_t c)
fail_if_enabled ();
- if (c.static_mapping_only && !c.connection_tracking)
- {
- nat_log_err ("unsupported combination of configuration");
- return 1;
- }
-
- sm->static_mapping_only = c.static_mapping_only;
- sm->static_mapping_connection_tracking = c.connection_tracking;
-
sm->forwarding_enabled = 0;
sm->mss_clamping = 0;
- sm->pat = (!c.static_mapping_only ||
- (c.static_mapping_only && c.connection_tracking));
if (!c.sessions)
c.sessions = 63 * 1024;
@@ -2461,7 +2436,7 @@ nat44_ed_del_addresses ()
vec = vec_dup (sm->addresses);
vec_foreach (a, vec)
{
- error = nat44_ed_del_address (a->addr, 0, 0);
+ error = nat44_ed_del_address (a->addr, 0);
if (error)
{
nat_log_err ("error occurred while removing adderess");
@@ -2474,7 +2449,7 @@ nat44_ed_del_addresses ()
vec = vec_dup (sm->twice_nat_addresses);
vec_foreach (a, vec)
{
- error = nat44_ed_del_address (a->addr, 0, 1);
+ error = nat44_ed_del_address (a->addr, 1);
if (error)
{
nat_log_err ("error occurred while removing adderess");
@@ -2484,11 +2459,8 @@ nat44_ed_del_addresses ()
vec_free (sm->twice_nat_addresses);
sm->twice_nat_addresses = 0;
- vec_free (sm->auto_add_sw_if_indices_twice_nat);
- sm->auto_add_sw_if_indices_twice_nat = 0;
-
- vec_free (sm->auto_add_sw_if_indices);
- sm->auto_add_sw_if_indices = 0;
+ vec_free (sm->addr_to_resolve);
+ sm->addr_to_resolve = 0;
return error;
}
@@ -2557,7 +2529,7 @@ nat44_ed_del_static_mappings ()
{
error = nat44_ed_del_static_mapping_internal (
m->local_addr, m->external_addr, m->local_port, m->external_port,
- m->proto, m->vrf_id, ~0, m->flags);
+ m->proto, m->vrf_id, m->flags);
if (error)
{
nat_log_err ("error occurred while removing mapping");
@@ -2567,8 +2539,8 @@ nat44_ed_del_static_mappings ()
pool_free (sm->static_mappings);
sm->static_mappings = 0;
- vec_free (sm->to_resolve);
- sm->to_resolve = 0;
+ vec_free (sm->sm_to_resolve);
+ sm->sm_to_resolve = 0;
return error;
}
@@ -2603,12 +2575,9 @@ nat44_plugin_disable ()
clib_bihash_free_16_8 (&sm->flow_hash);
- if (sm->pat)
+ vec_foreach (tsm, sm->per_thread_data)
{
- vec_foreach (tsm, sm->per_thread_data)
- {
- nat44_ed_worker_db_free (tsm);
- }
+ nat44_ed_worker_db_free (tsm);
}
clib_memset (&sm->rconfig, 0, sizeof (sm->rconfig));
@@ -3231,13 +3200,10 @@ nat44_ed_db_init (u32 translations, u32 translation_buckets)
reinit_ed_flow_hash ();
- if (sm->pat)
+ vec_foreach (tsm, sm->per_thread_data)
{
- vec_foreach (tsm, sm->per_thread_data)
- {
- nat44_ed_worker_db_init (tsm, sm->max_translations_per_thread,
- sm->translation_buckets);
- }
+ nat44_ed_worker_db_init (tsm, sm->max_translations_per_thread,
+ sm->translation_buckets);
}
}
@@ -3257,95 +3223,105 @@ nat44_ed_sessions_clear ()
reinit_ed_flow_hash ();
- if (sm->pat)
+ vec_foreach (tsm, sm->per_thread_data)
{
- vec_foreach (tsm, sm->per_thread_data)
- {
-
- nat44_ed_worker_db_free (tsm);
- nat44_ed_worker_db_init (tsm, sm->max_translations_per_thread,
- sm->translation_buckets);
- }
+ nat44_ed_worker_db_free (tsm);
+ nat44_ed_worker_db_init (tsm, sm->max_translations_per_thread,
+ sm->translation_buckets);
}
vlib_zero_simple_counter (&sm->total_sessions, 0);
}
static void
-nat44_ed_add_del_static_mapping_addr_only_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)
+nat44_ed_add_del_static_mapping_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)
{
- snat_static_map_resolve_t *rp;
+ snat_static_mapping_resolve_t *rp;
snat_main_t *sm = &snat_main;
- snat_static_mapping_t *m;
- int i, rv = 0, match = 0;
+ int rv = 0;
if (!sm->enabled)
{
return;
}
- // find first addr_only resolve record by sw_if_index
- for (i = 0; i < vec_len (sm->to_resolve); i++)
+ vec_foreach (rp, sm->sm_to_resolve)
{
- rp = sm->to_resolve + i;
- if (is_sm_addr_only (rp->flags) && rp->sw_if_index == sw_if_index)
+ if (sw_if_index == rp->sw_if_index)
{
- match = 1;
- break;
+ if (is_delete)
+ {
+ if (rp->is_resolved)
+ {
+ rv = nat44_ed_del_static_mapping_internal (
+ rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto,
+ rp->vrf_id, rp->flags);
+ if (rv)
+ {
+ nat_log_err ("ed del static mapping failed");
+ }
+ else
+ {
+ rp->is_resolved = 0;
+ }
+ }
+ }
+ else
+ {
+ if (!rp->is_resolved)
+ {
+ rv = nat44_ed_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_log_err ("ed add static mapping failed");
+ }
+ else
+ {
+ rp->is_resolved = 1;
+ }
+ }
+ }
}
}
- if (!match)
- {
- return;
- }
+}
- m = nat44_ed_sm_o2i_lookup (
- sm, *address, is_sm_addr_only (rp->flags) ? 0 : rp->e_port, 0, rp->proto);
+static int
+nat44_ed_get_addr_resolve_record (u32 sw_if_index, u8 twice_nat, int *out)
+{
+ snat_main_t *sm = &snat_main;
+ snat_address_resolve_t *rp;
+ int i;
- if (is_delete)
- {
- if (m)
- {
- rv = nat44_ed_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 (sm, "nat44_ed_del_static_mapping returned %d",
- "i4", rv);
- }
- }
- else
+ for (i = 0; i < vec_len (sm->addr_to_resolve); i++)
{
- if (!m)
- {
- rv = nat44_ed_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);
- }
- // else: don't trip over lease renewal, static config
- if (rv)
+ rp = sm->addr_to_resolve + i;
+
+ if ((rp->sw_if_index == sw_if_index) && (rp->is_twice_nat == twice_nat))
{
- nat_elog_notice_X1 (sm, "nat44_ed_add_static_mapping returned %d",
- "i4", rv);
+ if (out)
+ {
+ *out = i;
+ }
+ return 0;
}
}
+ return 1;
}
-
-static_always_inline int
-is_sw_if_index_reg_for_auto_resolve (u32 *sw_if_indices, u32 sw_if_index)
+static int
+nat44_ed_del_addr_resolve_record (u32 sw_if_index, u8 twice_nat)
{
- u32 *i;
- vec_foreach (i, sw_if_indices)
+ snat_main_t *sm = &snat_main;
+ int i;
+ if (!nat44_ed_get_addr_resolve_record (sw_if_index, twice_nat, &i))
{
- if (*i == sw_if_index)
- {
- return 1;
- }
+ vec_del1 (sm->addr_to_resolve, i);
+ return 0;
}
- return 0;
+ return 1;
}
static void
@@ -3355,23 +3331,21 @@ nat44_ed_add_del_interface_address_cb (ip4_main_t *im, uword opaque,
u32 if_address_index, u32 is_delete)
{
snat_main_t *sm = &snat_main;
- snat_static_map_resolve_t *rp;
- snat_address_t *ap, *addresses = sm->addresses;
+ snat_address_resolve_t *arp;
+ snat_address_t *ap;
u8 twice_nat = 0;
- int rv, i;
+ int i, rv;
if (!sm->enabled)
{
return;
}
- if (!is_sw_if_index_reg_for_auto_resolve (sm->auto_add_sw_if_indices,
- sw_if_index))
+ if (nat44_ed_get_addr_resolve_record (sw_if_index, twice_nat, &i))
{
- if (!is_sw_if_index_reg_for_auto_resolve (
- sm->auto_add_sw_if_indices_twice_nat, sw_if_index))
+ twice_nat = 1;
+ if (nat44_ed_get_addr_resolve_record (sw_if_index, twice_nat, &i))
{
- // interface resolve
u32 fib_index =
ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
vec_foreach (ap, sm->addresses)
@@ -3400,51 +3374,35 @@ nat44_ed_add_del_interface_address_cb (ip4_main_t *im, uword opaque,
}
return;
}
- else
- {
- addresses = sm->twice_nat_addresses;
- twice_nat = 1;
- }
}
+ arp = sm->addr_to_resolve + i;
+
if (!is_delete)
{
- // don't trip over lease renewal, static config
- for (i = 0; i < vec_len (addresses); i++)
+ if (arp->is_resolved)
{
- if (addresses[i].addr.as_u32 == address->as_u32)
- {
- return;
- }
+ return;
}
- (void) nat44_ed_add_address (address, ~0, twice_nat);
-
- // scan static mapping switch address resolution record vector
- for (i = 0; i < vec_len (sm->to_resolve); i++)
+ rv = nat44_ed_add_address (address, ~0, arp->is_twice_nat);
+ if (0 == rv)
{
- rp = sm->to_resolve + i;
- if (is_sm_addr_only (rp->flags))
- {
- continue;
- }
- if (rp->sw_if_index == sw_if_index)
- {
- rv = nat44_ed_add_static_mapping_internal (
- rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto,
- rp->vrf_id, sw_if_index, rp->flags, rp->pool_addr, rp->tag);
- if (rv)
- {
- nat_elog_notice_X1 (
- sm, "add_static_mapping_internal returned %d", "i4", rv);
- }
- }
+ arp->is_resolved = 1;
}
}
else
{
- // remove all static mapping records
- (void) nat44_ed_del_address (address[0], 1, twice_nat);
+ if (!arp->is_resolved)
+ {
+ return;
+ }
+
+ rv = nat44_ed_del_address (address[0], arp->is_twice_nat);
+ if (0 == rv)
+ {
+ arp->is_resolved = 0;
+ }
}
}
@@ -3454,34 +3412,34 @@ nat44_ed_add_interface_address (u32 sw_if_index, u8 twice_nat)
snat_main_t *sm = &snat_main;
ip4_main_t *ip4_main = sm->ip4_main;
ip4_address_t *first_int_addr;
- u32 *auto_add_sw_if_indices = twice_nat ?
- sm->auto_add_sw_if_indices_twice_nat :
- sm->auto_add_sw_if_indices;
- int i;
+ snat_address_resolve_t *ap;
+ int rv;
- for (i = 0; i < vec_len (auto_add_sw_if_indices); i++)
+ if (!sm->enabled)
{
- if (auto_add_sw_if_indices[i] == sw_if_index)
- {
- return VNET_API_ERROR_VALUE_EXIST;
- }
+ return VNET_API_ERROR_UNSUPPORTED;
}
- // add to the auto-address list
- if (twice_nat)
- {
- vec_add1 (sm->auto_add_sw_if_indices_twice_nat, sw_if_index);
- }
- else
+ if (!nat44_ed_get_addr_resolve_record (sw_if_index, twice_nat, 0))
{
- vec_add1 (sm->auto_add_sw_if_indices, sw_if_index);
+ return VNET_API_ERROR_VALUE_EXIST;
}
- // if the address is already bound - or static - add it now
+ vec_add2 (sm->addr_to_resolve, ap, 1);
+ ap->sw_if_index = sw_if_index;
+ ap->is_twice_nat = twice_nat;
+ ap->is_resolved = 0;
+
first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0);
if (first_int_addr)
{
- (void) nat44_ed_add_address (first_int_addr, ~0, twice_nat);
+ rv = nat44_ed_add_address (first_int_addr, ~0, twice_nat);
+ if (0 != rv)
+ {
+ nat44_ed_del_addr_resolve_record (sw_if_index, twice_nat);
+ return rv;
+ }
+ ap->is_resolved = 1;
}
return 0;
@@ -3493,62 +3451,24 @@ nat44_ed_del_interface_address (u32 sw_if_index, u8 twice_nat)
snat_main_t *sm = &snat_main;
ip4_main_t *ip4_main = sm->ip4_main;
ip4_address_t *first_int_addr;
- snat_static_map_resolve_t *rp;
- u32 *indices_to_delete = 0;
- int i, j;
- u32 *auto_add_sw_if_indices;
if (!sm->enabled)
{
return VNET_API_ERROR_UNSUPPORTED;
}
- auto_add_sw_if_indices = twice_nat ? sm->auto_add_sw_if_indices_twice_nat :
- sm->auto_add_sw_if_indices;
-
- for (i = 0; i < vec_len (auto_add_sw_if_indices); i++)
+ if (nat44_ed_del_addr_resolve_record (sw_if_index, twice_nat))
{
- if (auto_add_sw_if_indices[i] == sw_if_index)
- {
- first_int_addr =
- ip4_interface_first_address (ip4_main, sw_if_index, 0);
- if (first_int_addr)
- {
- // remove all static mapping records
- (void) nat44_ed_del_address (first_int_addr[0], 1, twice_nat);
- }
- else
- {
- for (j = 0; j < vec_len (sm->to_resolve); j++)
- {
- rp = sm->to_resolve + j;
- if (rp->sw_if_index == sw_if_index)
- {
- vec_add1 (indices_to_delete, j);
- }
- }
- if (vec_len (indices_to_delete))
- {
- for (j = vec_len (indices_to_delete) - 1; j >= 0; j--)
- {
- vec_del1 (sm->to_resolve, j);
- }
- vec_free (indices_to_delete);
- }
- }
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+ }
- if (twice_nat)
- {
- vec_del1 (sm->auto_add_sw_if_indices_twice_nat, i);
- }
- else
- {
- vec_del1 (sm->auto_add_sw_if_indices, i);
- }
- return 0;
- }
+ first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0);
+ if (first_int_addr)
+ {
+ return nat44_ed_del_address (first_int_addr[0], twice_nat);
}
- return VNET_API_ERROR_NO_SUCH_ENTRY;
+
+ return 0;
}
int