summaryrefslogtreecommitdiffstats
path: root/src/plugins/nat
diff options
context:
space:
mode:
authorFilip Varga <fivarga@cisco.com>2022-02-23 15:45:48 -0800
committerOle Tr�an <otroan@employees.org>2022-04-01 13:26:04 +0000
commit691c630b79ec2230b67944c8a9f77f95b49d95ad (patch)
treec27778fb111ef4d85d3c712ee0b68b0574f26d82 /src/plugins/nat
parentb68108203a59e12f4b4435caba164072e234f0aa (diff)
nat: VRF routing & FIB improvements
This patch affects how destination fib is choosen during session creation. Default behavior of choosing fib based on output interfaces is kept. Configuration gives you the ability to change default behavior to direct or restrict traffic between different FIB tables. NAT specific VRF routing options: a) keeping communication in the same VRF b) option to add multiple destination VRFs c) option to control the resolution order of destination VRFs TX FIB resolution is based on looking up RX FIB entry in NATs VRF table and picking the first FIB that resolves destination address. Ticket: VPP-2009 Type: improvement Change-Id: If500c48d7ce3466533ad9581c0847870788fc4fb Signed-off-by: Filip Varga <fivarga@cisco.com>
Diffstat (limited to 'src/plugins/nat')
-rw-r--r--src/plugins/nat/nat44-ed/nat44_ed.api52
-rw-r--r--src/plugins/nat/nat44-ed/nat44_ed.c189
-rw-r--r--src/plugins/nat/nat44-ed/nat44_ed.h95
-rw-r--r--src/plugins/nat/nat44-ed/nat44_ed_api.c73
-rw-r--r--src/plugins/nat/nat44-ed/nat44_ed_cfg.c0
-rw-r--r--src/plugins/nat/nat44-ed/nat44_ed_cli.c234
-rw-r--r--src/plugins/nat/nat44-ed/nat44_ed_in2out.c356
-rw-r--r--src/plugins/nat/nat44-ed/nat44_ed_out2in.c9
8 files changed, 727 insertions, 281 deletions
diff --git a/src/plugins/nat/nat44-ed/nat44_ed.api b/src/plugins/nat/nat44-ed/nat44_ed.api
index afb55021bec..88496a3f16e 100644
--- a/src/plugins/nat/nat44-ed/nat44_ed.api
+++ b/src/plugins/nat/nat44-ed/nat44_ed.api
@@ -198,6 +198,58 @@ define nat_worker_details {
string name[64];
};
+/** \brief Add/delete inter VRF NAT44-ED routing table
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param table_vrf_id - id of (rx) VRF used for resolving
+ destination (tx) VRF during dynamic
+ session creation
+ @param is_add - if true add else del
+*/
+autoreply define nat44_ed_add_del_vrf_table {
+ u32 client_index;
+ u32 context;
+ u32 table_vrf_id;
+ bool is_add;
+};
+
+/** \brief Add/del inter VRF NAT44-ED route record
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param table_vrf_id - id of the VRF NAT routing table
+ @param vrf_id - id of resolving destination (tx) VRF table
+ @param is_add - if true add else del
+*/
+autoreply define nat44_ed_add_del_vrf_route {
+ u32 client_index;
+ u32 context;
+ u32 table_vrf_id;
+ u32 vrf_id;
+ bool is_add;
+};
+
+/** \brief Dump NAT44-ED inter VRF NAT routing tables
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+*/
+define nat44_ed_vrf_tables_dump {
+ u32 client_index;
+ u32 context;
+};
+
+/** \brief NAT44-ED inter VRF NAT routing table details response
+ @param context - sender context, to match reply w/ request
+ @param table_vrf_id - id of the VRF NAT routing table
+ @param n_vrf_ids - number of vrf_ids
+ @param vrf_ids - ids of resolving destination (tx) VRFs
+*/
+define nat44_ed_vrf_tables_details {
+ u32 context;
+ u32 table_vrf_id;
+ u32 n_vrf_ids;
+ u32 vrf_ids[n_vrf_ids];
+};
+
/** \brief Set TCP MSS rewriting configuration
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
diff --git a/src/plugins/nat/nat44-ed/nat44_ed.c b/src/plugins/nat/nat44-ed/nat44_ed.c
index bf802f59323..3b1c9a2c89f 100644
--- a/src/plugins/nat/nat44-ed/nat44_ed.c
+++ b/src/plugins/nat/nat44-ed/nat44_ed.c
@@ -626,6 +626,134 @@ nat44_ed_del_address (ip4_address_t addr, u8 twice_nat)
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)
{
@@ -1555,10 +1683,10 @@ update_per_vrf_sessions_vec (u32 fib_index, int is_del)
}
}
-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)
@@ -1589,7 +1717,7 @@ nat44_ed_add_interface (u32 sw_if_index, u8 is_inside)
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;
@@ -1671,13 +1799,13 @@ nat44_ed_add_interface (u32 sw_if_index, u8 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);
@@ -1699,7 +1827,7 @@ nat44_ed_del_interface (u32 sw_if_index, u8 is_inside)
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;
@@ -1784,8 +1912,8 @@ nat44_ed_del_interface (u32 sw_if_index, u8 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);
}
@@ -1803,7 +1931,7 @@ nat44_ed_add_output_interface (u32 sw_if_index)
{
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;
@@ -1881,13 +2009,13 @@ nat44_ed_add_output_interface (u32 sw_if_index)
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);
@@ -1903,7 +2031,7 @@ nat44_ed_del_output_interface (u32 sw_if_index)
{
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;
@@ -1971,8 +2099,8 @@ nat44_ed_del_output_interface (u32 sw_if_index)
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);
}
@@ -2036,7 +2164,7 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index,
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;
@@ -2074,8 +2202,8 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index,
{
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;
}
@@ -2085,7 +2213,7 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index,
{
if (outside_fib->fib_index == new_fib_index)
{
- outside_fib->refcount++;
+ outside_fib->ref_count++;
is_add = 0;
break;
}
@@ -2094,7 +2222,7 @@ nat44_ed_update_outside_fib_cb (ip4_main_t *im, uword opaque, u32 sw_if_index,
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;
}
}
@@ -2518,6 +2646,8 @@ nat44_plugin_disable ()
if (rc)
error = 1;
+ nat44_ed_del_vrf_tables ();
+
vec_free (sm->max_translations_per_fib);
sm->max_translations_per_fib = 0;
@@ -2587,11 +2717,12 @@ nat44_ed_sm_match (snat_main_t *sm, ip4_address_t match_addr, u16 match_port,
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,
@@ -2599,12 +2730,13 @@ nat44_ed_sm_match (snat_main_t *sm, ip4_address_t match_addr, u16 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,
@@ -2612,7 +2744,7 @@ nat44_ed_sm_match (snat_main_t *sm, ip4_address_t match_addr, u16 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)
@@ -2626,7 +2758,7 @@ nat44_ed_sm_match (snat_main_t *sm, ip4_address_t match_addr, u16 match_port,
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;
@@ -2635,15 +2767,16 @@ nat44_ed_sm_match (snat_main_t *sm, ip4_address_t match_addr, u16 match_port,
}
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;
@@ -2787,7 +2920,7 @@ nat44_ed_get_in2out_worker_index (vlib_buffer_t *b, ip4_header_t *ip,
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,
diff --git a/src/plugins/nat/nat44-ed/nat44_ed.h b/src/plugins/nat/nat44-ed/nat44_ed.h
index e2047fe12ac..1ca71187ac7 100644
--- a/src/plugins/nat/nat44-ed/nat44_ed.h
+++ b/src/plugins/nat/nat44-ed/nat44_ed.h
@@ -355,18 +355,6 @@ typedef struct
typedef struct
{
- u32 fib_index;
- u32 ref_count;
-} nat_fib_t;
-
-typedef struct
-{
- u32 fib_index;
- u32 refcount;
-} nat_outside_fib_t;
-
-typedef struct
-{
/* backend IP address */
ip4_address_t addr;
/* backend port number */
@@ -504,6 +492,25 @@ typedef int (nat_alloc_out_addr_and_port_function_t) (
ip_protocol_t proto, ip4_address_t *addr, u16 *port, u16 port_per_thread,
u32 snat_thread_index);
+typedef struct nat_fib_s
+{
+ u32 fib_index;
+ u32 ref_count;
+} nat_fib_t;
+
+typedef struct vrf_route_s
+{
+ u32 vrf_id;
+ u32 fib_index;
+} vrf_route_t;
+
+typedef struct vrf_table_s
+{
+ u32 table_vrf_id;
+ u32 table_fib_index;
+ vrf_route_t *routes;
+} vrf_table_t;
+
typedef struct snat_main_s
{
/* Thread settings */
@@ -525,6 +532,21 @@ typedef struct snat_main_s
/* Endpoint dependent lookup table */
clib_bihash_16_8_t flow_hash;
+ // vector of fibs
+ nat_fib_t *fibs;
+
+ u32 inside_vrf_id;
+ u32 inside_fib_index;
+
+ u32 outside_vrf_id;
+ u32 outside_fib_index;
+
+ // vector of outside fibs
+ nat_fib_t *outside_fibs;
+
+ // VRF routing table for dynamic sessions
+ vrf_table_t *vrf_tables;
+
/* Interface pool */
snat_interface_t *interfaces;
snat_interface_t *output_feature_interfaces;
@@ -539,12 +561,6 @@ typedef struct snat_main_s
/* first interface address should be auto-added */
snat_address_resolve_t *addr_to_resolve;
- /* vector of fibs */
- nat_fib_t *fibs;
-
- /* vector of outside fibs */
- nat_outside_fib_t *outside_fibs;
-
/* vector of fib entries */
snat_fib_entry_reg_t *fib_entry_reg;
@@ -571,11 +587,6 @@ typedef struct snat_main_s
u32 max_translations_per_thread;
u32 *max_translations_per_fib;
- u32 outside_vrf_id;
- u32 outside_fib_index;
- u32 inside_vrf_id;
- u32 inside_fib_index;
-
nat_timeouts_t timeouts;
/* TCP MSS clamping */
@@ -849,6 +860,10 @@ int nat44_ed_del_address (ip4_address_t addr, u8 twice_nat);
int nat44_ed_add_interface_address (u32 sw_if_index, u8 twice_nat);
int nat44_ed_del_interface_address (u32 sw_if_index, u8 twice_nat);
+int nat44_ed_add_del_vrf_table (u32 table_vrf_id, bool is_add);
+int nat44_ed_add_del_vrf_route (u32 table_vrf_id, u32 vrf_id, bool is_add);
+void nat44_ed_del_vrf_tables ();
+
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,
@@ -910,31 +925,15 @@ int nat44_update_session_limit (u32 session_limit, u32 vrf_id);
void expire_per_vrf_sessions (u32 fib_index);
-/**
- * @brief Match NAT44 static mapping.
- *
- * @param key address and port to match
- * @param addr external/local address of the matched mapping
- * @param port port of the matched mapping
- * @param fib_index fib index of the matched mapping
- * @param by_external if 0 match by local address otherwise match by external
- * address
- * @param is_addr_only 1 if matched mapping is address only
- * @param twice_nat matched mapping is twice NAT type
- * @param lb 1 if matched mapping is load-balanced
- * @param ext_host_addr external host address
- * @param is_identity_nat 1 if indentity mapping
- * @param out if !=0 set to pointer of the mapping structure
- *
- * @returns 0 if match found otherwise 1.
- */
-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,
- 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);
+int 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);
u32 get_thread_idx_by_port (u16 e_port);
diff --git a/src/plugins/nat/nat44-ed/nat44_ed_api.c b/src/plugins/nat/nat44-ed/nat44_ed_api.c
index f4ba2bc9e8e..19e497e00c2 100644
--- a/src/plugins/nat/nat44-ed/nat44_ed_api.c
+++ b/src/plugins/nat/nat44-ed/nat44_ed_api.c
@@ -1194,6 +1194,79 @@ vl_api_nat44_show_running_config_t_handler (
}));
}
+static void
+vl_api_nat44_ed_add_del_vrf_table_t_handler (
+ vl_api_nat44_ed_add_del_vrf_table_t *mp)
+{
+ snat_main_t *sm = &snat_main;
+ vl_api_nat44_ed_add_del_vrf_table_reply_t *rmp;
+ int rv = nat44_ed_add_del_vrf_table (clib_net_to_host_u32 (mp->table_vrf_id),
+ mp->is_add);
+ REPLY_MACRO (VL_API_NAT44_ED_ADD_DEL_VRF_TABLE);
+}
+
+static void
+vl_api_nat44_ed_add_del_vrf_route_t_handler (
+ vl_api_nat44_ed_add_del_vrf_route_t *mp)
+{
+ snat_main_t *sm = &snat_main;
+ vl_api_nat44_ed_add_del_vrf_route_reply_t *rmp;
+ int rv =
+ nat44_ed_add_del_vrf_route (clib_net_to_host_u32 (mp->table_vrf_id),
+ clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
+ REPLY_MACRO (VL_API_NAT44_ED_ADD_DEL_VRF_ROUTE);
+}
+
+static void
+nat44_ed_vrf_tables_send_details (vl_api_registration_t *rp, u32 context,
+ vrf_table_t *t)
+{
+ snat_main_t *sm = &snat_main;
+ vl_api_nat44_ed_vrf_tables_details_t *mp;
+
+ u32 *vrf_ids = 0;
+ vrf_route_t *r;
+
+ mp = vl_msg_api_alloc_zero (sizeof (*mp) +
+ sizeof (mp->vrf_ids[0]) * vec_len (t->routes));
+ mp->_vl_msg_id =
+ ntohs (VL_API_NAT44_ED_VRF_TABLES_DETAILS + sm->msg_id_base);
+ mp->context = context;
+ mp->n_vrf_ids = clib_host_to_net_u32 (vec_len (t->routes));
+
+ pool_foreach (r, t->routes)
+ {
+ vec_add1 (vrf_ids, r->vrf_id);
+ }
+
+ // copy the records
+ clib_memcpy (mp->vrf_ids, vrf_ids,
+ sizeof (mp->vrf_ids[0]) * vec_len (t->routes));
+
+ vec_free (vrf_ids);
+
+ // send the message
+ vl_api_send_msg (rp, (u8 *) mp);
+}
+
+static void
+vl_api_nat44_ed_vrf_tables_dump_t_handler (
+ vl_api_nat44_ed_vrf_tables_dump_t *mp)
+{
+ snat_main_t *sm = &snat_main;
+ vl_api_registration_t *rp;
+ vrf_table_t *t;
+
+ rp = vl_api_client_index_to_registration (mp->client_index);
+ if (rp == 0)
+ return;
+
+ pool_foreach (t, sm->vrf_tables)
+ {
+ nat44_ed_vrf_tables_send_details (rp, mp->context, t);
+ }
+}
+
/* user (internal host) key */
typedef struct
{
diff --git a/src/plugins/nat/nat44-ed/nat44_ed_cfg.c b/src/plugins/nat/nat44-ed/nat44_ed_cfg.c
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/src/plugins/nat/nat44-ed/nat44_ed_cfg.c
+++ /dev/null
diff --git a/src/plugins/nat/nat44-ed/nat44_ed_cli.c b/src/plugins/nat/nat44-ed/nat44_ed_cli.c
index 7693063b8d8..bddd635272c 100644
--- a/src/plugins/nat/nat44-ed/nat44_ed_cli.c
+++ b/src/plugins/nat/nat44-ed/nat44_ed_cli.c
@@ -916,8 +916,6 @@ add_static_mapping_command_fn (vlib_main_t * vm,
e_port = clib_host_to_net_u16 (e_port);
}
- // TODO: specific pool_addr for both pool & twice nat pool ?
-
if (is_add)
{
rv =
@@ -930,25 +928,17 @@ add_static_mapping_command_fn (vlib_main_t * vm,
vrf_id, sw_if_index, flags);
}
- // TODO: fix returns
-
switch (rv)
{
- case VNET_API_ERROR_INVALID_VALUE:
- error = clib_error_return (0, "External port already in use.");
- goto done;
+ case VNET_API_ERROR_UNSUPPORTED:
+ error = clib_error_return (0, "Plugin disabled.");
+ break;
case VNET_API_ERROR_NO_SUCH_ENTRY:
- if (is_add)
- error = clib_error_return (0, "External address must be allocated.");
- else
- error = clib_error_return (0, "Mapping not exist.");
- goto done;
- case VNET_API_ERROR_NO_SUCH_FIB:
- error = clib_error_return (0, "No such VRF id.");
- goto done;
+ error = clib_error_return (0, "Mapping not exist.");
+ break;
case VNET_API_ERROR_VALUE_EXIST:
error = clib_error_return (0, "Mapping already exist.");
- goto done;
+ break;
default:
break;
}
@@ -959,7 +949,6 @@ done:
return error;
}
-// TODO: either delete this bullshit or update it
static clib_error_t *
add_identity_mapping_command_fn (vlib_main_t * vm,
unformat_input_t * input,
@@ -976,7 +965,6 @@ add_identity_mapping_command_fn (vlib_main_t * vm,
flags = NAT_SM_FLAG_IDENTITY_NAT;
- /* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
@@ -1029,25 +1017,17 @@ add_identity_mapping_command_fn (vlib_main_t * vm,
sw_if_index, flags);
}
- // TODO: fix returns
-
switch (rv)
{
- case VNET_API_ERROR_INVALID_VALUE:
- error = clib_error_return (0, "External port already in use.");
- goto done;
+ case VNET_API_ERROR_UNSUPPORTED:
+ error = clib_error_return (0, "Plugin disabled.");
+ break;
case VNET_API_ERROR_NO_SUCH_ENTRY:
- if (is_add)
- error = clib_error_return (0, "External address must be allocated.");
- else
- error = clib_error_return (0, "Mapping not exist.");
- goto done;
- case VNET_API_ERROR_NO_SUCH_FIB:
- error = clib_error_return (0, "No such VRF id.");
- goto done;
+ error = clib_error_return (0, "Mapping not exist.");
+ break;
case VNET_API_ERROR_VALUE_EXIST:
error = clib_error_return (0, "Mapping already exist.");
- goto done;
+ break;
default:
break;
}
@@ -1073,7 +1053,6 @@ add_lb_static_mapping_command_fn (vlib_main_t * vm,
int rv, is_add = 1;
u32 flags = 0;
- /* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
@@ -1342,6 +1321,156 @@ done:
}
static clib_error_t *
+nat44_ed_add_del_vrf_table_command_fn (vlib_main_t *vm,
+ unformat_input_t *input,
+ vlib_cli_command_t *cmd)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ clib_error_t *error = 0;
+ bool is_add = true, not_set = true;
+ u32 vrf_id = ~0;
+ int rv;
+
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "%u", &vrf_id))
+ ;
+ else if (not_set)
+ {
+ if (unformat (line_input, "add"))
+ {
+ is_add = true;
+ }
+ else if (unformat (line_input, "del"))
+ {
+ is_add = false;
+ }
+ not_set = false;
+ }
+ else
+ {
+ error = clib_error_return (0, "unknown input '%U'",
+ format_unformat_error, line_input);
+ goto done;
+ }
+ }
+
+ if (not_set)
+ {
+ error = clib_error_return (0, "missing required parameter");
+ goto done;
+ }
+
+ if (~0 == vrf_id)
+ {
+ error = clib_error_return (0, "missing vrf id");
+ goto done;
+ }
+
+ rv = nat44_ed_add_del_vrf_table (vrf_id, is_add);
+ if (rv)
+ {
+ error = clib_error_return (0, "%s vrf table returned %d",
+ is_add ? "add" : "del", rv);
+ }
+
+done:
+ unformat_free (line_input);
+
+ return error;
+}
+
+static clib_error_t *
+nat44_ed_add_del_vrf_route_command_fn (vlib_main_t *vm,
+ unformat_input_t *input,
+ vlib_cli_command_t *cmd)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ clib_error_t *error = 0;
+ bool is_add = true, not_set = true;
+ u32 vrf_id = ~0, table_vrf_id = ~0;
+ int rv;
+
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "table %u", &table_vrf_id))
+ ;
+ else if (unformat (line_input, "%u", &vrf_id))
+ ;
+ else if (not_set)
+ {
+ if (unformat (line_input, "add"))
+ {
+ is_add = true;
+ }
+ else if (unformat (line_input, "del"))
+ {
+ is_add = false;
+ }
+ not_set = false;
+ }
+ else
+ {
+ error = clib_error_return (0, "unknown input '%U'",
+ format_unformat_error, line_input);
+ goto done;
+ }
+ }
+
+ if (not_set)
+ {
+ error = clib_error_return (0, "missing required parameter");
+ goto done;
+ }
+
+ if ((~0 == vrf_id) || (~0 == table_vrf_id))
+ {
+ error = clib_error_return (0, "missing vrf id");
+ goto done;
+ }
+
+ rv = nat44_ed_add_del_vrf_route (table_vrf_id, vrf_id, is_add);
+ if (rv)
+ {
+ error = clib_error_return (0, "%s vrf table returned %d",
+ is_add ? "add" : "del", rv);
+ }
+
+done:
+ unformat_free (line_input);
+
+ return error;
+}
+
+static clib_error_t *
+nat44_ed_show_vrf_tables_command_fn (vlib_main_t *vm, unformat_input_t *input,
+ vlib_cli_command_t *cmd)
+{
+ snat_main_t *sm = &snat_main;
+ vrf_table_t *t;
+ vrf_route_t *r;
+ int i = 0;
+
+ pool_foreach (t, sm->vrf_tables)
+ {
+ vlib_cli_output (vm, "table %u:", t->table_vrf_id);
+ pool_foreach (r, t->routes)
+ {
+ vlib_cli_output (vm, "[%u] vrf-id %u", i, r->vrf_id);
+ i++;
+ }
+ }
+
+ return 0;
+}
+
+static clib_error_t *
nat44_show_interface_address_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd)
@@ -2093,6 +2222,45 @@ VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
/*?
* @cliexpar
+ * @cliexstart{nat44 vrf table}
+ * Add empty inter VRF routing table
+ * vpp# nat44 vrf table add 10
+ * @cliexend
+?*/
+VLIB_CLI_COMMAND (nat44_ed_add_del_vrf_table_command, static) = {
+ .path = "nat44 vrf table",
+ .short_help = "nat44 vrf table [add|del] <vrf-id>",
+ .function = nat44_ed_add_del_vrf_table_command_fn,
+};
+
+/*?
+ * @cliexpar
+ * @cliexstart{nat44 vrf route}
+ * Add inter VRF route record to VRF routing table
+ * vpp# nat44 vrf route add table 10 20
+ * @cliexend
+?*/
+VLIB_CLI_COMMAND (nat44_ed_add_del_vrf_route_command, static) = {
+ .path = "nat44 vrf route",
+ .short_help = "nat44 vrf route [add|del] table <vrf-id> <vrf-id>",
+ .function = nat44_ed_add_del_vrf_route_command_fn,
+};
+
+/*?
+ * @cliexpar
+ * @cliexstart{show nat44 vrf tables}
+ * Show inter VRF route tables
+ * vpp# show nat44 vrf tables
+ * @cliexend
+?*/
+VLIB_CLI_COMMAND (nat44_ed_show_vrf_tables_command, static) = {
+ .path = "show nat44 vrf tables",
+ .short_help = "show nat44 vrf tables",
+ .function = nat44_ed_show_vrf_tables_command_fn,
+};
+
+/*?
+ * @cliexpar
* @cliexstart{show nat44 interface address}
* Show NAT44 pool address interfaces
* vpp# show nat44 interface address
diff --git a/src/plugins/nat/nat44-ed/nat44_ed_in2out.c b/src/plugins/nat/nat44-ed/nat44_ed_in2out.c
index 6e0a21d890a..179405e72b7 100644
--- a/src/plugins/nat/nat44-ed/nat44_ed_in2out.c
+++ b/src/plugins/nat/nat44-ed/nat44_ed_in2out.c
@@ -96,74 +96,6 @@ format_nat_in2out_ed_trace (u8 * s, va_list * args)
return s;
}
-/**
- * @brief Check if packet should be translated
- *
- * Packets aimed at outside interface and external address with active session
- * should be translated.
- *
- * @param sm NAT main
- * @param rt NAT runtime data
- * @param sw_if_index0 index of the inside interface
- * @param ip0 IPv4 header
- * @param rx_fib_index0 RX FIB index
- *
- * @returns 0 if packet should be translated otherwise 1
- */
-static inline int
-snat_not_translate_fast (snat_main_t *sm, vlib_node_runtime_t *node,
- u32 sw_if_index0, ip4_header_t *ip0,
- u32 rx_fib_index0)
-{
- fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
- nat_outside_fib_t *outside_fib;
- fib_prefix_t pfx = {
- .fp_proto = FIB_PROTOCOL_IP4,
- .fp_len = 32,
- .fp_addr = {
- .ip4.as_u32 = ip0->dst_address.as_u32,
- }
- ,
- };
-
- /* Don't NAT packet aimed at the intfc address */
- if (PREDICT_FALSE (
- is_interface_addr (sm, node, sw_if_index0, ip0->dst_address.as_u32)))
- return 1;
-
- fei = fib_table_lookup (rx_fib_index0, &pfx);
- if (FIB_NODE_INDEX_INVALID != fei)
- {
- u32 sw_if_index = fib_entry_get_resolving_interface (fei);
- if (sw_if_index == ~0)
- {
- vec_foreach (outside_fib, sm->outside_fibs)
- {
- fei = fib_table_lookup (outside_fib->fib_index, &pfx);
- if (FIB_NODE_INDEX_INVALID != fei)
- {
- sw_if_index = fib_entry_get_resolving_interface (fei);
- if (sw_if_index != ~0)
- break;
- }
- }
- }
- if (sw_if_index == ~0)
- return 1;
-
- snat_interface_t *i;
- pool_foreach (i, sm->interfaces)
- {
- /* NAT packet aimed at outside interface */
- if ((nat44_ed_is_interface_outside (i)) &&
- (sw_if_index == i->sw_if_index))
- return 0;
- }
- }
-
- return 1;
-}
-
static int
nat_ed_alloc_addr_and_port_with_snat_address (
snat_main_t *sm, u8 proto, u32 thread_index, snat_address_t *a,
@@ -340,31 +272,6 @@ nat_ed_alloc_addr_and_port (snat_main_t *sm, u32 rx_fib_index,
return 1;
}
-static_always_inline u32
-nat_outside_fib_index_lookup (snat_main_t * sm, ip4_address_t addr)
-{
- fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
- nat_outside_fib_t *outside_fib;
- fib_prefix_t pfx = {
- .fp_proto = FIB_PROTOCOL_IP4,
- .fp_len = 32,
- .fp_addr = {.ip4.as_u32 = addr.as_u32,}
- ,
- };
- vec_foreach (outside_fib, sm->outside_fibs)
- {
- fei = fib_table_lookup (outside_fib->fib_index, &pfx);
- if (FIB_NODE_INDEX_INVALID != fei)
- {
- if (fib_entry_get_resolving_interface (fei) != ~0)
- {
- return outside_fib->fib_index;
- }
- }
- }
- return ~0;
-}
-
static_always_inline int
nat44_ed_external_sm_lookup (snat_main_t *sm, ip4_address_t match_addr,
u16 match_port, ip_protocol_t match_protocol,
@@ -388,6 +295,131 @@ nat44_ed_external_sm_lookup (snat_main_t *sm, ip4_address_t match_addr,
return 1;
}
+static_always_inline vrf_table_t *
+get_vrf_table_by_fib (u32 fib_index)
+{
+ snat_main_t *sm = &snat_main;
+ vrf_table_t *t;
+
+ pool_foreach (t, sm->vrf_tables)
+ {
+ if (fib_index == t->table_fib_index)
+ {
+ return t;
+ }
+ }
+
+ return 0;
+}
+
+static_always_inline u32
+get_tx_fib_index (u32 rx_fib_index, ip4_address_t addr)
+{
+ fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
+ fib_prefix_t pfx = {
+ .fp_proto = FIB_PROTOCOL_IP4,
+ .fp_len = 32,
+ .fp_addr = {.ip4.as_u32 = addr.as_u32,}
+ ,
+ };
+
+ snat_main_t *sm = &snat_main;
+ vrf_table_t *t = get_vrf_table_by_fib (rx_fib_index);
+ // default to rx fib
+ u32 tx_fib_index = rx_fib_index;
+
+ if (0 != t)
+ {
+ // managed routes to other fibs
+ vrf_route_t *r;
+ pool_foreach (r, t->routes)
+ {
+ fei = fib_table_lookup (r->fib_index, &pfx);
+ if ((FIB_NODE_INDEX_INVALID != fei) &&
+ (~0 != fib_entry_get_resolving_interface (fei)))
+ {
+ tx_fib_index = r->fib_index;
+ break;
+ }
+ }
+ }
+ else
+ {
+ // default to configured fib
+ tx_fib_index = sm->outside_fib_index;
+
+ // default routes to other fibs
+ nat_fib_t *f;
+ vec_foreach (f, sm->outside_fibs)
+ {
+ fei = fib_table_lookup (f->fib_index, &pfx);
+ if ((FIB_NODE_INDEX_INVALID != fei) &&
+ (~0 != fib_entry_get_resolving_interface (fei)))
+ {
+ tx_fib_index = f->fib_index;
+ break;
+ }
+ }
+ }
+
+ return tx_fib_index;
+}
+
+static_always_inline int
+is_destination_resolvable (u32 rx_fib_index, ip4_address_t addr)
+{
+ fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
+ fib_prefix_t pfx = {
+ .fp_proto = FIB_PROTOCOL_IP4,
+ .fp_len = 32,
+ .fp_addr = {.ip4.as_u32 = addr.as_u32,}
+ ,
+ };
+
+ snat_main_t *sm = &snat_main;
+ vrf_table_t *t = get_vrf_table_by_fib (rx_fib_index);
+ u32 ii;
+
+ if (0 != t)
+ {
+ // managed routes to other fibs
+ vrf_route_t *r;
+ pool_foreach (r, t->routes)
+ {
+ fei = fib_table_lookup (r->fib_index, &pfx);
+ if ((FIB_NODE_INDEX_INVALID != fei) &&
+ (~0 != (ii = fib_entry_get_resolving_interface (fei))))
+ {
+ return 1;
+ }
+ }
+ }
+ else
+ {
+ // default routes to other fibs
+ nat_fib_t *f;
+ vec_foreach (f, sm->outside_fibs)
+ {
+ fei = fib_table_lookup (f->fib_index, &pfx);
+ if ((FIB_NODE_INDEX_INVALID != fei) &&
+ (~0 != (ii = fib_entry_get_resolving_interface (fei))))
+ {
+ snat_interface_t *i;
+ pool_foreach (i, sm->interfaces)
+ {
+ if ((nat44_ed_is_interface_outside (i)) &&
+ (ii == i->sw_if_index))
+ {
+ return 1;
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
static u32
slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b,
ip4_address_t l_addr, ip4_address_t r_addr, u16 l_port,
@@ -398,7 +430,7 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b,
snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
ip4_address_t outside_addr;
u16 outside_port;
- u32 outside_fib_index;
+ u32 tx_fib_index;
u8 is_identity_nat = 0;
snat_session_t *s = NULL;
@@ -419,33 +451,14 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b,
}
}
- outside_fib_index = sm->outside_fib_index;
-
- switch (vec_len (sm->outside_fibs))
- {
- case 0:
- outside_fib_index = sm->outside_fib_index;
- break;
- case 1:
- outside_fib_index = sm->outside_fibs[0].fib_index;
- break;
- default:
- outside_fib_index = nat_outside_fib_index_lookup (sm, r_addr);
- break;
- }
-
ip4_address_t sm_addr;
u16 sm_port;
u32 sm_fib_index;
- /* First try to match static mapping by local address and port */
- int is_sm;
- if (snat_static_mapping_match (vm, sm, l_addr, l_port, rx_fib_index, proto,
- &sm_addr, &sm_port, &sm_fib_index, 0, 0, 0,
- &lb, 0, &is_identity_nat, 0))
- {
- is_sm = 0;
- }
- else
+ int is_sm = 0;
+ // First try to match static mapping by local address and port
+ if (!snat_static_mapping_match (vm, l_addr, l_port, rx_fib_index, proto,
+ &sm_addr, &sm_port, &sm_fib_index, 0, 0, 0,
+ &lb, 0, &is_identity_nat, 0))
{
if (PREDICT_FALSE (is_identity_nat))
{
@@ -468,21 +481,24 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b,
s = nat_ed_session_alloc (sm, thread_index, now, proto);
ASSERT (s);
+ tx_fib_index = get_tx_fib_index (rx_fib_index, r_addr);
+
if (!is_sm)
{
s->in2out.addr = l_addr;
s->in2out.port = l_port;
s->proto = proto;
s->in2out.fib_index = rx_fib_index;
- s->out2in.fib_index = outside_fib_index;
+ s->out2in.fib_index = tx_fib_index;
// suggest using local port to allocation function
outside_port = l_port;
- // hairpinning?
- int is_hairpinning = nat44_ed_external_sm_lookup (sm, r_addr, r_port,
- proto, &daddr, &dport);
- s->flags |= is_hairpinning * SNAT_SESSION_FLAG_HAIRPINNING;
+ if (PREDICT_FALSE (nat44_ed_external_sm_lookup (sm, r_addr, r_port,
+ proto, &daddr, &dport)))
+ {
+ s->flags |= SNAT_SESSION_FLAG_HAIRPINNING;
+ }
// destination addr/port updated with real values in
// nat_ed_alloc_addr_and_port
@@ -520,7 +536,7 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b,
s->in2out.port = l_port;
s->proto = proto;
s->in2out.fib_index = rx_fib_index;
- s->out2in.fib_index = outside_fib_index;
+ s->out2in.fib_index = tx_fib_index;
s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
// hairpinning?
@@ -568,7 +584,7 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b,
nat_6t_flow_sport_rewrite_set (&s->i2o, outside_port);
nat_6t_flow_dport_rewrite_set (&s->i2o, dport);
}
- nat_6t_flow_txfib_rewrite_set (&s->i2o, outside_fib_index);
+ nat_6t_flow_txfib_rewrite_set (&s->i2o, tx_fib_index);
if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s, 1))
{
@@ -600,38 +616,55 @@ error:
}
static_always_inline int
-nat44_ed_not_translate (vlib_main_t *vm, snat_main_t *sm,
- vlib_node_runtime_t *node, u32 sw_if_index,
- vlib_buffer_t *b, ip4_header_t *ip, u32 proto,
- u32 rx_fib_index)
+nat44_ed_not_translate (vlib_main_t *vm, vlib_node_runtime_t *node,
+ u32 sw_if_index, vlib_buffer_t *b, ip4_header_t *ip,
+ u32 proto, u32 rx_fib_index)
{
+ snat_main_t *sm = &snat_main;
+
clib_bihash_kv_16_8_t kv, value;
+ ip4_address_t placeholder_addr;
+ u32 placeholder_fib_index;
+ u16 placeholder_port;
init_ed_k (&kv, ip->dst_address.as_u32,
vnet_buffer (b)->ip.reass.l4_dst_port, ip->src_address.as_u32,
vnet_buffer (b)->ip.reass.l4_src_port, sm->outside_fib_index,
ip->protocol);
- /* NAT packet aimed at external address if has active sessions */
- if (clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value))
+ // do nat if active session or is static mapping
+ if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value) ||
+ !snat_static_mapping_match (
+ vm, ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port,
+ sm->outside_fib_index, proto, &placeholder_addr, &placeholder_port,
+ &placeholder_fib_index, 1, 0, 0, 0, 0, 0, 0))
{
- /* or is static mappings */
- ip4_address_t placeholder_addr;
- u16 placeholder_port;
- u32 placeholder_fib_index;
- if (!snat_static_mapping_match (
- vm, sm, ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port,
- sm->outside_fib_index, proto, &placeholder_addr, &placeholder_port,
- &placeholder_fib_index, 1, 0, 0, 0, 0, 0, 0))
- return 0;
+ return 0;
}
- else
- return 0;
+ // do not nat if forwarding enabled
if (sm->forwarding_enabled)
- return 1;
+ {
+ return 1;
+ }
- return snat_not_translate_fast (sm, node, sw_if_index, ip, rx_fib_index);
+ // do not nat packet aimed at the interface address
+ if (PREDICT_FALSE (
+ is_interface_addr (sm, node, sw_if_index, ip->dst_address.as_u32)))
+ {
+ return 1;
+ }
+
+ // do nat packets with resolvable destination
+ // destination can be resolved either by:
+ // a) vrf routing table entry
+ // b) (non output feature) outside interface fib
+ if (is_destination_resolvable (rx_fib_index, ip->dst_address))
+ {
+ return 0;
+ }
+
+ return 1;
}
static_always_inline int
@@ -810,7 +843,7 @@ icmp_in2out_ed_slow_path (snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip,
else
{
if (PREDICT_FALSE (nat44_ed_not_translate (
- vm, sm, node, sw_if_index, b, ip, IP_PROTOCOL_ICMP, rx_fib_index)))
+ vm, node, sw_if_index, b, ip, IP_PROTOCOL_ICMP, rx_fib_index)))
{
return next;
}
@@ -868,7 +901,7 @@ nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b,
snat_static_mapping_t *m = NULL;
snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
snat_session_t *s = NULL;
- u32 outside_fib_index = sm->outside_fib_index;
+ u32 tx_fib_index;
int i;
ip4_address_t new_src_addr = { 0 };
ip4_address_t new_dst_addr = ip->dst_address;
@@ -883,20 +916,9 @@ nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b,
return 0;
}
- switch (vec_len (sm->outside_fibs))
- {
- case 0:
- outside_fib_index = sm->outside_fib_index;
- break;
- case 1:
- outside_fib_index = sm->outside_fibs[0].fib_index;
- break;
- default:
- outside_fib_index = nat_outside_fib_index_lookup (sm, ip->dst_address);
- break;
- }
+ tx_fib_index = get_tx_fib_index (rx_fib_index, ip->dst_address);
- /* Try to find static mapping first */
+ // Try to find static mapping first
m = nat44_ed_sm_i2o_lookup (sm, ip->src_address, 0, rx_fib_index,
ip->protocol);
if (m)
@@ -910,7 +932,7 @@ nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b,
if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32)
{
init_ed_k (&s_kv, s->out2in.addr.as_u32, 0,
- ip->dst_address.as_u32, 0, outside_fib_index,
+ ip->dst_address.as_u32, 0, tx_fib_index,
ip->protocol);
if (clib_bihash_search_16_8 (&sm->flow_hash, &s_kv, &s_value))
{
@@ -925,7 +947,7 @@ nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b,
for (i = 0; i < vec_len (sm->addresses); i++)
{
init_ed_k (&s_kv, sm->addresses[i].addr.as_u32, 0,
- ip->dst_address.as_u32, 0, outside_fib_index,
+ ip->dst_address.as_u32, 0, tx_fib_index,
ip->protocol);
if (clib_bihash_search_16_8 (&sm->flow_hash, &s_kv, &s_value))
{
@@ -952,7 +974,7 @@ nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b,
nat_6t_i2o_flow_init (sm, thread_index, s, ip->src_address, 0,
ip->dst_address, 0, rx_fib_index, ip->protocol);
nat_6t_flow_saddr_rewrite_set (&s->i2o, new_src_addr.as_u32);
- nat_6t_flow_txfib_rewrite_set (&s->i2o, outside_fib_index);
+ nat_6t_flow_txfib_rewrite_set (&s->i2o, tx_fib_index);
// hairpinning?
int is_hairpinning = nat44_ed_external_sm_lookup (
@@ -960,17 +982,17 @@ nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b,
s->flags |= is_hairpinning * SNAT_SESSION_FLAG_HAIRPINNING;
nat_6t_flow_daddr_rewrite_set (&s->i2o, new_dst_addr.as_u32);
- nat_6t_flow_txfib_rewrite_set (&s->i2o, outside_fib_index);
+ nat_6t_flow_txfib_rewrite_set (&s->i2o, tx_fib_index);
nat_6t_o2i_flow_init (sm, thread_index, s, new_dst_addr, 0, new_src_addr, 0,
- outside_fib_index, ip->protocol);
+ tx_fib_index, ip->protocol);
nat_6t_flow_saddr_rewrite_set (&s->o2i, ip->dst_address.as_u32);
nat_6t_flow_daddr_rewrite_set (&s->o2i, ip->src_address.as_u32);
nat_6t_flow_txfib_rewrite_set (&s->o2i, rx_fib_index);
s->ext_host_addr.as_u32 = ip->dst_address.as_u32;
s->out2in.addr.as_u32 = new_src_addr.as_u32;
- s->out2in.fib_index = outside_fib_index;
+ s->out2in.fib_index = tx_fib_index;
s->in2out.addr.as_u32 = ip->src_address.as_u32;
s->in2out.fib_index = rx_fib_index;
s->in2out.port = s->out2in.port = ip->protocol;
@@ -1445,8 +1467,8 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t *vm,
else
{
if (PREDICT_FALSE (
- nat44_ed_not_translate (vm, sm, node, rx_sw_if_index0, b0,
- ip0, proto0, rx_fib_index0)))
+ nat44_ed_not_translate (vm, node, rx_sw_if_index0, b0, ip0,
+ proto0, rx_fib_index0)))
goto trace0;
}
diff --git a/src/plugins/nat/nat44-ed/nat44_ed_out2in.c b/src/plugins/nat/nat44-ed/nat44_ed_out2in.c
index aa0cc508f08..e53d9c5a2de 100644
--- a/src/plugins/nat/nat44-ed/nat44_ed_out2in.c
+++ b/src/plugins/nat/nat44-ed/nat44_ed_out2in.c
@@ -182,7 +182,7 @@ icmp_out2in_ed_slow_path (snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip,
goto out;
}
- if (snat_static_mapping_match (vm, sm, ip->dst_address, lookup_sport,
+ if (snat_static_mapping_match (vm, ip->dst_address, lookup_sport,
rx_fib_index, ip->protocol, &sm_addr,
&sm_port, &sm_fib_index, 1, &is_addr_only, 0,
0, 0, &identity_nat, &m))
@@ -1164,10 +1164,9 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm,
destination address and port in packet */
if (snat_static_mapping_match (
- vm, sm, ip0->dst_address,
- vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0, proto0,
- &sm_addr, &sm_port, &sm_fib_index, 1, 0, &twice_nat0, &lb_nat0,
- &ip0->src_address, &identity_nat0, &m))
+ vm, ip0->dst_address, vnet_buffer (b0)->ip.reass.l4_dst_port,
+ rx_fib_index0, proto0, &sm_addr, &sm_port, &sm_fib_index, 1, 0,
+ &twice_nat0, &lb_nat0, &ip0->src_address, &identity_nat0, &m))
{
/*
* Send DHCP packets to the ipv4 stack, or we won't