if (PREDICT_FALSE (sm->enabled)) \
{ \
nat_log_err ("plugin enabled"); \
- return 1; \
+ return VNET_API_ERROR_FEATURE_ALREADY_ENABLED; \
} \
} \
while (0)
if (PREDICT_FALSE (!sm->enabled)) \
{ \
nat_log_err ("plugin disabled"); \
- return 1; \
+ return VNET_API_ERROR_FEATURE_ALREADY_DISABLED; \
} \
} \
while (0)
{
ap->addr_len = ia->address_length;
ap->sw_if_index = i->sw_if_index;
- ap->net.as_u32 = (ap->addr.as_u32 >> (32 - ap->addr_len))
- << (32 - ap->addr_len);
+ ap->net.as_u32 = ap->addr.as_u32 & ip4_main.fib_masks[ap->addr_len];
nat_log_debug ("pool addr %U binds to -> sw_if_idx: %u net: %U/%u",
format_ip4_address, &ap->addr, ap->sw_if_index,
{
ap->addr_len = ia->address_length;
ap->sw_if_index = sw_if_index;
- ap->net.as_u32 = (ap->addr.as_u32 >> (32 - ap->addr_len))
- << (32 - ap->addr_len);
+ ap->net.as_u32 = ap->addr.as_u32 & ip4_main.fib_masks[ap->addr_len];
nat_log_debug ("pool addr %U binds to -> sw_if_idx: %u net: %U/%u",
format_ip4_address, &ap->addr, ap->sw_if_index,
return 0;
}
+vrf_table_t *
+nat44_ed_get_vrf_table (u32 table_vrf_id)
+{
+ snat_main_t *sm = &snat_main;
+ vrf_table_t *t;
+
+ pool_foreach (t, sm->vrf_tables)
+ {
+ if (table_vrf_id == t->table_vrf_id)
+ {
+ return t;
+ }
+ }
+ return NULL;
+}
+
+vrf_route_t *
+nat44_ed_get_vrf_route (vrf_table_t *t, u32 vrf_id)
+{
+ vrf_route_t *r;
+
+ pool_foreach (r, t->routes)
+ {
+ if (vrf_id == r->vrf_id)
+ {
+ return r;
+ }
+ }
+ return NULL;
+}
+
+int
+nat44_ed_add_del_vrf_table (u32 table_vrf_id, bool is_add)
+{
+ snat_main_t *sm = &snat_main;
+ vrf_table_t *t;
+ vrf_route_t *r;
+
+ t = nat44_ed_get_vrf_table (table_vrf_id);
+ if (t)
+ {
+ if (is_add)
+ {
+ return VNET_API_ERROR_VALUE_EXIST;
+ }
+ pool_foreach (r, t->routes)
+ {
+ fib_table_unlock (r->fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low);
+ }
+ fib_table_unlock (t->table_fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low);
+
+ pool_free (t->routes);
+ pool_put (sm->vrf_tables, t);
+ }
+ else
+ {
+ if (!is_add)
+ {
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+ }
+ pool_get (sm->vrf_tables, t);
+ clib_memset (t, 0, sizeof (*t));
+ t->table_vrf_id = table_vrf_id;
+ t->table_fib_index = fib_table_find_or_create_and_lock (
+ FIB_PROTOCOL_IP4, table_vrf_id, sm->fib_src_low);
+ }
+
+ return 0;
+}
+
+void
+nat44_ed_del_vrf_tables ()
+{
+ snat_main_t *sm = &snat_main;
+ vrf_table_t *t;
+ vrf_route_t *r;
+
+ pool_foreach (t, sm->vrf_tables)
+ {
+ pool_foreach (r, t->routes)
+ {
+ fib_table_unlock (r->fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low);
+ }
+ fib_table_unlock (t->table_fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low);
+ pool_free (t->routes);
+ }
+ pool_free (sm->vrf_tables);
+}
+
+int
+nat44_ed_add_del_vrf_route (u32 table_vrf_id, u32 vrf_id, bool is_add)
+{
+ snat_main_t *sm = &snat_main;
+ vrf_table_t *t;
+ vrf_route_t *r;
+
+ t = nat44_ed_get_vrf_table (table_vrf_id);
+ if (!t)
+ {
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+ }
+
+ r = nat44_ed_get_vrf_route (t, vrf_id);
+ if (r)
+ {
+ if (is_add)
+ {
+ return VNET_API_ERROR_VALUE_EXIST;
+ }
+ fib_table_unlock (r->fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low);
+ pool_put (t->routes, r);
+ }
+ else
+ {
+ if (!is_add)
+ {
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+ }
+ pool_get (t->routes, r);
+ clib_memset (r, 0, sizeof (*r));
+ r->vrf_id = vrf_id;
+ r->fib_index = fib_table_find_or_create_and_lock (
+ FIB_PROTOCOL_IP4, vrf_id, sm->fib_src_low);
+ }
+
+ return 0;
+}
+
u32
get_thread_idx_by_port (u16 e_port)
{
u32 thread_idx = sm->num_workers;
if (sm->num_workers > 1)
{
- thread_idx =
- sm->first_worker_index +
- sm->workers[(e_port - 1024) / sm->port_per_thread];
+ thread_idx = sm->first_worker_index +
+ sm->workers[(e_port - ED_USER_PORT_OFFSET) /
+ sm->port_per_thread % _vec_len (sm->workers)];
}
return thread_idx;
}
vec_foreach (tsm, sm->per_thread_data)
{
- vec_foreach (per_vrf_sessions, tsm->per_vrf_sessions_vec)
- {
- if ((per_vrf_sessions->rx_fib_index == fib_index) ||
- (per_vrf_sessions->tx_fib_index == fib_index))
- {
- per_vrf_sessions->expired = 1;
- }
- }
+ pool_foreach (per_vrf_sessions, tsm->per_vrf_sessions_pool)
+ {
+ if ((per_vrf_sessions->rx_fib_index == fib_index) ||
+ (per_vrf_sessions->tx_fib_index == fib_index))
+ {
+ per_vrf_sessions->expired = 1;
+ }
+ }
}
}
void
-update_per_vrf_sessions_vec (u32 fib_index, int is_del)
+update_per_vrf_sessions_pool (u32 fib_index, int is_del)
{
snat_main_t *sm = &snat_main;
nat_fib_t *fib;
}
}
-static_always_inline nat_outside_fib_t *
-nat44_ed_get_outside_fib (nat_outside_fib_t *outside_fibs, u32 fib_index)
+static_always_inline nat_fib_t *
+nat44_ed_get_outside_fib (nat_fib_t *outside_fibs, u32 fib_index)
{
- nat_outside_fib_t *f;
+ nat_fib_t *f;
vec_foreach (f, outside_fibs)
{
if (f->fib_index == fib_index)
const char *del_feature_name, *feature_name;
snat_main_t *sm = &snat_main;
- nat_outside_fib_t *outside_fib;
+ nat_fib_t *outside_fib;
snat_interface_t *i;
u32 fib_index;
int rv;
fib_index =
fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index);
- update_per_vrf_sessions_vec (fib_index, 0 /*is_del*/);
+ update_per_vrf_sessions_pool (fib_index, 0 /*is_del*/);
if (!is_inside)
{
outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index);
if (outside_fib)
{
- outside_fib->refcount++;
+ outside_fib->ref_count++;
}
else
{
vec_add2 (sm->outside_fibs, outside_fib, 1);
outside_fib->fib_index = fib_index;
- outside_fib->refcount = 1;
+ outside_fib->ref_count = 1;
}
nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 1);
const char *del_feature_name, *feature_name;
snat_main_t *sm = &snat_main;
- nat_outside_fib_t *outside_fib;
+ nat_fib_t *outside_fib;
snat_interface_t *i;
u32 fib_index;
int rv;
fib_index =
fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index);
- update_per_vrf_sessions_vec (fib_index, 1 /*is_del*/);
+ update_per_vrf_sessions_pool (fib_index, 1 /*is_del*/);
if (!is_inside)
{
outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index);
if (outside_fib)
{
- outside_fib->refcount--;
- if (!outside_fib->refcount)
+ outside_fib->ref_count--;
+ if (!outside_fib->ref_count)
{
vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
}
{
snat_main_t *sm = &snat_main;
- nat_outside_fib_t *outside_fib;
+ nat_fib_t *outside_fib;
snat_interface_t *i;
u32 fib_index;
int rv;
fib_index =
fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index);
- update_per_vrf_sessions_vec (fib_index, 0 /*is_del*/);
+ update_per_vrf_sessions_pool (fib_index, 0 /*is_del*/);
outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index);
if (outside_fib)
{
- outside_fib->refcount++;
+ outside_fib->ref_count++;
}
else
{
vec_add2 (sm->outside_fibs, outside_fib, 1);
outside_fib->fib_index = fib_index;
- outside_fib->refcount = 1;
+ outside_fib->ref_count = 1;
}
nat44_ed_add_del_nat_addr_fib_reg_entries (sw_if_index, 1);
{
snat_main_t *sm = &snat_main;
- nat_outside_fib_t *outside_fib;
+ nat_fib_t *outside_fib;
snat_interface_t *i;
u32 fib_index;
int rv;
fib_index =
fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index);
- update_per_vrf_sessions_vec (fib_index, 1 /*is_del*/);
+ update_per_vrf_sessions_pool (fib_index, 1 /*is_del*/);
outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index);
if (outside_fib)
{
- outside_fib->refcount--;
- if (!outside_fib->refcount)
+ outside_fib->ref_count--;
+ if (!outside_fib->ref_count)
{
vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
}
j++;
}
- sm->port_per_thread = (0xffff - 1024) / _vec_len (sm->workers);
+ sm->port_per_thread = (65536 - ED_USER_PORT_OFFSET) / _vec_len (sm->workers);
return 0;
}
u32 new_fib_index, u32 old_fib_index)
{
snat_main_t *sm = &snat_main;
- nat_outside_fib_t *outside_fib;
+ nat_fib_t *outside_fib;
snat_interface_t *i;
u8 is_add = 1;
u8 match = 0;
{
if (outside_fib->fib_index == old_fib_index)
{
- outside_fib->refcount--;
- if (!outside_fib->refcount)
+ outside_fib->ref_count--;
+ if (!outside_fib->ref_count)
vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
break;
}
{
if (outside_fib->fib_index == new_fib_index)
{
- outside_fib->refcount++;
+ outside_fib->ref_count++;
is_add = 0;
break;
}
if (is_add)
{
vec_add2 (sm->outside_fibs, outside_fib, 1);
- outside_fib->refcount = 1;
+ outside_fib->ref_count = 1;
outside_fib->fib_index = new_fib_index;
}
}
clib_memset (sm, 0, sizeof (*sm));
- // required
- sm->vnet_main = vnet_get_main ();
// convenience
sm->ip4_main = &ip4_main;
}
}
num_threads = tm->n_vlib_mains - 1;
- sm->port_per_thread = 0xffff - 1024;
+ sm->port_per_thread = 65536 - ED_USER_PORT_OFFSET;
vec_validate (sm->per_thread_data, num_threads);
/* Use all available workers by default */
nat44_ed_db_init (sm->max_translations_per_thread, sm->translation_buckets);
- nat44_ed_init_tcp_state_stable (sm);
-
nat_affinity_enable ();
nat_reset_timeouts (&sm->timeouts);
rc = nat44_ed_del_static_mappings ();
if (rc)
- error = 1;
+ error = VNET_API_ERROR_BUG;
rc = nat44_ed_del_addresses ();
if (rc)
- error = 1;
+ error = VNET_API_ERROR_BUG;
rc = nat44_ed_del_interfaces ();
if (rc)
- error = 1;
+ error = VNET_API_ERROR_BUG;
rc = nat44_ed_del_output_interfaces ();
if (rc)
- error = 1;
+ error = VNET_API_ERROR_BUG;
+
+ nat44_ed_del_vrf_tables ();
vec_free (sm->max_translations_per_fib);
sm->max_translations_per_fib = 0;
if (m)
return m;
- /* Try address only mapping */
+ // try address only mapping
m = nat44_ed_sm_i2o_lookup (sm, match_addr, 0, match_fib_index, 0);
if (m)
return m;
+ // default static mapping fib index (based on configuration)
if (sm->inside_fib_index != match_fib_index)
{
m = nat44_ed_sm_i2o_lookup (sm, match_addr, match_port,
if (m)
return m;
- /* Try address only mapping */
+ // try address only mapping
m = nat44_ed_sm_i2o_lookup (sm, match_addr, 0, sm->inside_fib_index,
0);
if (m)
return m;
}
+ // TODO: this specific use case may be deprecated (needs testing)
if (sm->outside_fib_index != match_fib_index)
{
m = nat44_ed_sm_i2o_lookup (sm, match_addr, match_port,
if (m)
return m;
- /* Try address only mapping */
+ // try address only mapping
m = nat44_ed_sm_i2o_lookup (sm, match_addr, 0, sm->outside_fib_index,
0);
if (m)
if (m)
return m;
- /* Try address only mapping */
+ // try address only mapping
m = nat44_ed_sm_o2i_lookup (sm, match_addr, 0, 0, 0);
if (m)
return m;
}
int
-snat_static_mapping_match (vlib_main_t *vm, snat_main_t *sm,
- ip4_address_t match_addr, u16 match_port,
- u32 match_fib_index, ip_protocol_t match_protocol,
+snat_static_mapping_match (vlib_main_t *vm, ip4_address_t match_addr,
+ u16 match_port, u32 match_fib_index,
+ ip_protocol_t match_protocol,
ip4_address_t *mapping_addr, u16 *mapping_port,
u32 *mapping_fib_index, int by_external,
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, snat_static_mapping_t **out)
{
+ snat_main_t *sm = &snat_main;
snat_static_mapping_t *m;
u32 rand, lo = 0, hi, mid, *tmp = 0, i;
nat44_lb_addr_port_t *local;
if (PREDICT_FALSE (is_output))
{
fib_index = sm->outside_fib_index;
- nat_outside_fib_t *outside_fib;
+ nat_fib_t *outside_fib;
fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
fib_prefix_t pfx = {
.fp_proto = FIB_PROTOCOL_IP4,
}
/* worker by outside port */
- next_worker_index = sm->first_worker_index;
- next_worker_index +=
- sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread];
+ next_worker_index = get_thread_idx_by_port (clib_net_to_host_u16 (port));
done:
nat_elog_debug_handoff (sm, "HANDOFF OUT2IN", next_worker_index,
{
pool_free (tsm->lru_pool);
pool_free (tsm->sessions);
- vec_free (tsm->per_vrf_sessions_vec);
+ pool_free (tsm->per_vrf_sessions_pool);
}
void
{
ap->addr_len = address_length;
ap->sw_if_index = sw_if_index;
- ap->net.as_u32 = (ap->addr.as_u32 >> (32 - ap->addr_len))
- << (32 - ap->addr_len);
+ ap->net.as_u32 =
+ ap->addr.as_u32 & ip4_main.fib_masks[ap->addr_len];
nat_log_debug (
"pool addr %U binds to -> sw_if_idx: %u net: %U/%u",
if (!sm->enabled)
{
+ nat_log_err ("nat44 is disabled");
return VNET_API_ERROR_UNSUPPORTED;
}
if (!sm->enabled)
{
+ nat_log_err ("nat44 is disabled");
return VNET_API_ERROR_UNSUPPORTED;
}