aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatus Fabian <matfabia@cisco.com>2018-10-07 21:28:23 -0700
committerOle Trøan <otroan@employees.org>2018-10-08 11:46:23 +0000
commite2f4e2f175beb6d6490d275049199db7dd61c783 (patch)
tree3b8a5997a835d15aec3b58af5e9bfc7195d12f7c
parent2fd4b56aea5833a4752525d58cac335909190e9c (diff)
NAT44: do not create session record for identity mapping (VPP-1439)
Change-Id: I39a3146a4e4ba8eadf50af7113b9ae6b1c1d688f Signed-off-by: Matus Fabian <matfabia@cisco.com>
-rwxr-xr-xsrc/plugins/nat/in2out.c41
-rw-r--r--src/plugins/nat/in2out_ed.c39
-rwxr-xr-xsrc/plugins/nat/nat.c74
-rw-r--r--src/plugins/nat/nat.h62
-rw-r--r--src/plugins/nat/nat44_cli.c4
-rw-r--r--src/plugins/nat/nat44_hairpinning.c4
-rw-r--r--src/plugins/nat/nat_api.c25
-rw-r--r--src/plugins/nat/nat_format.c8
-rwxr-xr-xsrc/plugins/nat/out2in.c39
-rw-r--r--src/plugins/nat/out2in_ed.c40
-rw-r--r--test/test_nat.py3
11 files changed, 236 insertions, 103 deletions
diff --git a/src/plugins/nat/in2out.c b/src/plugins/nat/in2out.c
index b6106505331..b99aef3944d 100755
--- a/src/plugins/nat/in2out.c
+++ b/src/plugins/nat/in2out.c
@@ -135,7 +135,7 @@ snat_not_translate (snat_main_t * sm, vlib_node_runtime_t * node,
&value0))
{
/* or is static mappings */
- if (!snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0))
+ if (!snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0, 0))
return 0;
}
else
@@ -236,13 +236,14 @@ slow_path (snat_main_t * sm, vlib_buffer_t * b0,
vlib_node_runtime_t * node, u32 next0, u32 thread_index, f64 now)
{
snat_user_t *u;
- snat_session_t *s;
+ snat_session_t *s = 0;
clib_bihash_kv_8_8_t kv0;
snat_session_key_t key1;
udp_header_t *udp0 = ip4_next_header (ip0);
u8 is_sm = 0;
nat_outside_fib_t *outside_fib;
fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
+ u8 identity_nat;
fib_prefix_t pfx = {
.fp_proto = FIB_PROTOCOL_IP4,
.fp_len = 32,
@@ -263,7 +264,8 @@ slow_path (snat_main_t * sm, vlib_buffer_t * b0,
key1.protocol = key0->protocol;
/* First try to match static mapping by local address and port */
- if (snat_static_mapping_match (sm, *key0, &key1, 0, 0, 0, 0, 0))
+ if (snat_static_mapping_match
+ (sm, *key0, &key1, 0, 0, 0, 0, 0, &identity_nat))
{
/* Try to create dynamic translation */
if (snat_alloc_outside_address_and_port (sm->addresses, rx_fib_index0,
@@ -277,7 +279,15 @@ slow_path (snat_main_t * sm, vlib_buffer_t * b0,
}
}
else
- is_sm = 1;
+ {
+ if (PREDICT_FALSE (identity_nat))
+ {
+ *sessionp = s;
+ return next0;
+ }
+
+ is_sm = 1;
+ }
u = nat_user_get_or_create (sm, &ip0->src_address, rx_fib_index0,
thread_index);
@@ -489,6 +499,12 @@ icmp_match_in2out_slow (snat_main_t * sm, vlib_node_runtime_t * node,
if (PREDICT_FALSE (next0 == SNAT_IN2OUT_NEXT_DROP))
goto out;
+
+ if (!s0)
+ {
+ dont_translate = 1;
+ goto out;
+ }
}
else
{
@@ -558,7 +574,8 @@ icmp_match_in2out_fast (snat_main_t * sm, vlib_node_runtime_t * node,
}
key0.fib_index = rx_fib_index0;
- if (snat_static_mapping_match (sm, key0, &sm0, 0, &is_addr_only, 0, 0, 0))
+ if (snat_static_mapping_match
+ (sm, key0, &sm0, 0, &is_addr_only, 0, 0, 0, 0))
{
if (PREDICT_FALSE (snat_not_translate_fast (sm, node, sw_if_index0, ip0,
IP_PROTOCOL_ICMP,
@@ -987,6 +1004,9 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
&s0, node, next0, thread_index, now);
if (PREDICT_FALSE (next0 == SNAT_IN2OUT_NEXT_DROP))
goto trace00;
+
+ if (PREDICT_FALSE (!s0))
+ goto trace00;
}
else
{
@@ -1163,6 +1183,9 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
&s1, node, next1, thread_index, now);
if (PREDICT_FALSE (next1 == SNAT_IN2OUT_NEXT_DROP))
goto trace01;
+
+ if (PREDICT_FALSE (!s1))
+ goto trace01;
}
else
{
@@ -1374,6 +1397,9 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
if (PREDICT_FALSE (next0 == SNAT_IN2OUT_NEXT_DROP))
goto trace0;
+
+ if (PREDICT_FALSE (!s0))
+ goto trace0;
}
else
{
@@ -1717,6 +1743,9 @@ nat44_in2out_reass_node_fn (vlib_main_t * vm,
if (PREDICT_FALSE (next0 == SNAT_IN2OUT_NEXT_DROP))
goto trace0;
+ if (PREDICT_FALSE (!s0))
+ goto trace0;
+
reass0->sess_index = s0 - per_thread_data->sessions;
}
else
@@ -1971,7 +2000,7 @@ snat_in2out_fast_static_map_fn (vlib_main_t * vm,
key0.port = udp0->src_port;
key0.fib_index = rx_fib_index0;
- if (snat_static_mapping_match (sm, key0, &sm0, 0, 0, 0, 0, 0))
+ if (snat_static_mapping_match (sm, key0, &sm0, 0, 0, 0, 0, 0, 0))
{
b0->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
next0 = SNAT_IN2OUT_NEXT_DROP;
diff --git a/src/plugins/nat/in2out_ed.c b/src/plugins/nat/in2out_ed.c
index adf0ff30948..8db53c08142 100644
--- a/src/plugins/nat/in2out_ed.c
+++ b/src/plugins/nat/in2out_ed.c
@@ -256,7 +256,7 @@ slow_path_ed (snat_main_t * sm,
snat_session_t ** sessionp,
vlib_node_runtime_t * node, u32 next, u32 thread_index, f64 now)
{
- snat_session_t *s;
+ snat_session_t *s = 0;
snat_user_t *u;
snat_session_key_t key0, key1;
lb_nat_type_t lb = 0, is_sm = 0;
@@ -265,6 +265,7 @@ slow_path_ed (snat_main_t * sm,
u32 proto = ip_proto_to_snat_proto (key->proto);
nat_outside_fib_t *outside_fib;
fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
+ u8 identity_nat;
fib_prefix_t pfx = {
.fp_proto = FIB_PROTOCOL_IP4,
.fp_len = 32,
@@ -288,7 +289,8 @@ slow_path_ed (snat_main_t * sm,
key0.fib_index = rx_fib_index;
key1.fib_index = sm->outside_fib_index;
/* First try to match static mapping by local address and port */
- if (snat_static_mapping_match (sm, key0, &key1, 0, 0, 0, &lb, 0))
+ if (snat_static_mapping_match
+ (sm, key0, &key1, 0, 0, 0, &lb, 0, &identity_nat))
{
/* Try to create dynamic translation */
if (snat_alloc_outside_address_and_port (sm->addresses, rx_fib_index,
@@ -302,7 +304,15 @@ slow_path_ed (snat_main_t * sm,
}
}
else
- is_sm = 1;
+ {
+ if (PREDICT_FALSE (identity_nat))
+ {
+ *sessionp = s;
+ return next;
+ }
+
+ is_sm = 1;
+ }
u = nat_user_get_or_create (sm, &key->l_addr, rx_fib_index, thread_index);
if (!u)
@@ -413,7 +423,7 @@ nat44_ed_not_translate (snat_main_t * sm, vlib_node_runtime_t * node,
key0.protocol = proto;
key0.fib_index = sm->outside_fib_index;
/* or is static mappings */
- if (!snat_static_mapping_match (sm, key0, &key1, 1, 0, 0, 0, 0))
+ if (!snat_static_mapping_match (sm, key0, &key1, 1, 0, 0, 0, 0, 0))
return 0;
}
else
@@ -607,6 +617,12 @@ icmp_match_in2out_ed (snat_main_t * sm, vlib_node_runtime_t * node,
if (PREDICT_FALSE (next == NAT_IN2OUT_ED_NEXT_DROP))
goto out;
+
+ if (!s)
+ {
+ dont_translate = 1;
+ goto out;
+ }
}
else
{
@@ -1011,6 +1027,9 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
if (PREDICT_FALSE (next0 == NAT_IN2OUT_ED_NEXT_DROP))
goto trace00;
+
+ if (PREDICT_FALSE (!s0))
+ goto trace00;
}
else
{
@@ -1212,6 +1231,9 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
if (PREDICT_FALSE (next1 == NAT_IN2OUT_ED_NEXT_DROP))
goto trace01;
+
+ if (PREDICT_FALSE (!s1))
+ goto trace01;
}
else
{
@@ -1442,6 +1464,9 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
if (PREDICT_FALSE (next0 == NAT_IN2OUT_ED_NEXT_DROP))
goto trace0;
+
+ if (PREDICT_FALSE (!s0))
+ goto trace0;
}
else
{
@@ -1839,6 +1864,12 @@ nat44_ed_in2out_reass_node_fn_inline (vlib_main_t * vm,
if (PREDICT_FALSE (next0 == NAT_IN2OUT_ED_NEXT_DROP))
goto trace0;
+ if (PREDICT_FALSE (!s0))
+ {
+ reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
+ goto trace0;
+ }
+
reass0->sess_index = s0 - per_thread_data->sessions;
}
else
diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c
index 0818332eeb3..ae2e64e1f82 100755
--- a/src/plugins/nat/nat.c
+++ b/src/plugins/nat/nat.c
@@ -583,7 +583,9 @@ snat_add_static_mapping_when_resolved (snat_main_t * sm,
u16 e_port,
u32 vrf_id,
snat_protocol_t proto,
- int addr_only, int is_add, u8 * tag)
+ int addr_only, int is_add, u8 * tag,
+ int twice_nat, int out2in_only,
+ int identity_nat)
{
snat_static_map_resolve_t *rp;
@@ -596,6 +598,9 @@ snat_add_static_mapping_when_resolved (snat_main_t * sm,
rp->proto = proto;
rp->addr_only = addr_only;
rp->is_add = is_add;
+ rp->twice_nat = twice_nat;
+ rp->out2in_only = out2in_only;
+ rp->identity_nat = identity_nat;
rp->tag = vec_dup (tag);
}
@@ -613,34 +618,12 @@ get_thread_idx_by_port (u16 e_port)
return thread_idx;
}
-/**
- * @brief Add static mapping.
- *
- * Create static mapping between local addr+port and external addr+port.
- *
- * @param l_addr Local IPv4 address.
- * @param e_addr External IPv4 address.
- * @param l_port Local port number.
- * @param e_port External port number.
- * @param vrf_id VRF ID.
- * @param addr_only If 0 address port and pair mapping, otherwise address only.
- * @param sw_if_index External port instead of specific IP address.
- * @param is_add If 0 delete static mapping, otherwise add.
- * @param twice_nat If value is TWICE_NAT then translate external host address
- * and port.
- * If value is TWICE_NAT_SELF then translate external host
- * address and port whenever external host address equals
- * local address of internal host.
- * @param out2in_only If 1 rule match only out2in direction
- * @param tag - opaque string tag
- *
- * @returns
- */
int
snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
u32 sw_if_index, snat_protocol_t proto, int is_add,
- twice_nat_type_t twice_nat, u8 out2in_only, u8 * tag)
+ twice_nat_type_t twice_nat, u8 out2in_only, u8 * tag,
+ u8 identity_nat)
{
snat_main_t *sm = &snat_main;
snat_static_mapping_t *m;
@@ -702,7 +685,7 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
snat_add_static_mapping_when_resolved
(sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
- addr_only, is_add, tag);
+ addr_only, is_add, tag, twice_nat, out2in_only, identity_nat);
/* DHCP resolution required? */
if (first_int_addr == 0)
@@ -842,11 +825,15 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
m->tag = vec_dup (tag);
m->local_addr = l_addr;
m->external_addr = e_addr;
- m->addr_only = addr_only;
m->vrf_id = vrf_id;
m->fib_index = fib_index;
m->twice_nat = twice_nat;
- m->out2in_only = out2in_only;
+ if (out2in_only)
+ m->flags |= NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY;
+ if (addr_only)
+ m->flags |= NAT_STATIC_MAPPING_FLAG_ADDR_ONLY;
+ if (identity_nat)
+ m->flags |= NAT_STATIC_MAPPING_FLAG_IDENTITY_NAT;
if (!addr_only)
{
m->local_port = l_port;
@@ -1147,11 +1134,11 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
memset (m, 0, sizeof (*m));
m->tag = vec_dup (tag);
m->external_addr = e_addr;
- m->addr_only = 0;
m->external_port = e_port;
m->proto = proto;
m->twice_nat = twice_nat;
- m->out2in_only = out2in_only;
+ if (out2in_only)
+ m->flags |= NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY;
m->affinity = affinity;
if (affinity)
@@ -1368,9 +1355,9 @@ snat_del_address (snat_main_t * sm, ip4_address_t addr, u8 delete_sm,
if (m->external_addr.as_u32 == addr.as_u32)
(void) snat_add_static_mapping (m->local_addr, m->external_addr,
m->local_port, m->external_port,
- m->vrf_id, m->addr_only, ~0,
+ m->vrf_id, is_addr_only_static_mapping(m), ~0,
m->proto, 0, m->twice_nat,
- m->out2in_only, m->tag);
+ is_out2in_only_static_mapping(m), m->tag, is_identity_static_mapping(m));
}));
/* *INDENT-ON* */
}
@@ -1682,7 +1669,7 @@ fib:
pool_foreach (m, sm->static_mappings,
({
- if (!(m->addr_only) || (m->local_addr.as_u32 == m->external_addr.as_u32))
+ if (!(is_addr_only_static_mapping(m)) || (m->local_addr.as_u32 == m->external_addr.as_u32))
continue;
snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
@@ -1810,7 +1797,7 @@ fib:
pool_foreach (m, sm->static_mappings,
({
- if (!(m->addr_only) || (m->local_addr.as_u32 == m->external_addr.as_u32))
+ if (!((is_addr_only_static_mapping(m))) || (m->local_addr.as_u32 == m->external_addr.as_u32))
continue;
snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
@@ -2017,7 +2004,8 @@ snat_static_mapping_match (snat_main_t * sm,
u8 by_external,
u8 * is_addr_only,
twice_nat_type_t * twice_nat,
- lb_nat_type_t * lb, ip4_address_t * ext_host_addr)
+ lb_nat_type_t * lb, ip4_address_t * ext_host_addr,
+ u8 * is_identity_nat)
{
clib_bihash_kv_8_8_t kv, value;
snat_static_mapping_t *m;
@@ -2108,7 +2096,7 @@ snat_static_mapping_match (snat_main_t * sm,
mapping->fib_index = m->fib_index;
mapping->addr = m->local_addr;
/* Address only mapping doesn't change port */
- mapping->port = m->addr_only ? match.port
+ mapping->port = is_addr_only_static_mapping (m) ? match.port
: clib_host_to_net_u16 (m->local_port);
}
mapping->protocol = m->proto;
@@ -2117,18 +2105,21 @@ snat_static_mapping_match (snat_main_t * sm,
{
mapping->addr = m->external_addr;
/* Address only mapping doesn't change port */
- mapping->port = m->addr_only ? match.port
+ mapping->port = is_addr_only_static_mapping (m) ? match.port
: clib_host_to_net_u16 (m->external_port);
mapping->fib_index = sm->outside_fib_index;
}
end:
if (PREDICT_FALSE (is_addr_only != 0))
- *is_addr_only = m->addr_only;
+ *is_addr_only = is_addr_only_static_mapping (m);
if (PREDICT_FALSE (twice_nat != 0))
*twice_nat = m->twice_nat;
+ if (PREDICT_FALSE (is_identity_nat != 0))
+ *is_identity_nat = is_identity_static_mapping (m);
+
return 0;
}
@@ -2919,7 +2910,8 @@ match:
rp->e_port,
rp->vrf_id,
rp->addr_only, ~0 /* sw_if_index */ ,
- rp->proto, !is_delete, 0, 0, rp->tag);
+ rp->proto, !is_delete, rp->twice_nat,
+ rp->out2in_only, rp->tag, rp->identity_nat);
if (rv)
nat_log_notice ("snat_add_static_mapping returned %d", rv);
}
@@ -2988,7 +2980,9 @@ match:
rp->addr_only,
~0 /* sw_if_index */ ,
rp->proto,
- rp->is_add, 0, 0, rp->tag);
+ rp->is_add, rp->twice_nat,
+ rp->out2in_only, rp->tag,
+ rp->identity_nat);
if (rv)
nat_log_notice ("snat_add_static_mapping returned %d", rv);
}
diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h
index 1baf10ff43c..0549acdba3a 100644
--- a/src/plugins/nat/nat.h
+++ b/src/plugins/nat/nat.h
@@ -179,6 +179,11 @@ typedef enum
#define NAT_INTERFACE_FLAG_IS_INSIDE 1
#define NAT_INTERFACE_FLAG_IS_OUTSIDE 2
+/* Static mapping flags */
+#define NAT_STATIC_MAPPING_FLAG_ADDR_ONLY 1
+#define NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY 2
+#define NAT_STATIC_MAPPING_FLAG_IDENTITY_NAT 4
+
/* *INDENT-OFF* */
typedef CLIB_PACKED(struct
{
@@ -321,12 +326,8 @@ typedef struct
u16 local_port;
/* external port */
u16 external_port;
- /* 1 = 1:1NAT, 0 = 1:1NAPT */
- u8 addr_only;
/* is twice-nat */
twice_nat_type_t twice_nat;
- /* 1 = rule match only out2in direction */
- u8 out2in_only;
/* local FIB table */
u32 vrf_id;
u32 fib_index;
@@ -342,6 +343,8 @@ typedef struct
nat44_lb_addr_port_t *locals;
/* affinity per service lis */
u32 affinity_per_service_list_head_index;
+ /* flags */
+ u32 flags;
} snat_static_mapping_t;
typedef struct
@@ -358,9 +361,12 @@ typedef struct
u32 sw_if_index;
u32 vrf_id;
snat_protocol_t proto;
+ u32 flags;
int addr_only;
int twice_nat;
int is_add;
+ int out2in_only;
+ int identity_nat;
u8 *tag;
} snat_static_map_resolve_t;
@@ -642,6 +648,24 @@ unformat_function_t unformat_snat_protocol;
*/
#define nat44_is_ses_closed(s) s->state == 0xf
+/** \brief Check if NAT static mapping is address only (1:1NAT).
+ @param sm NAT static mapping
+ @return 1 if 1:1NAT, 0 if 1:1NAPT
+*/
+#define is_addr_only_static_mapping(sm) (sm->flags & NAT_STATIC_MAPPING_FLAG_ADDR_ONLY)
+
+/** \brief Check if NAT static mapping match only out2in direction.
+ @param sm NAT static mapping
+ @return 1 if rule match only out2in direction
+*/
+#define is_out2in_only_static_mapping(sm) (sm->flags & NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY)
+
+/** \brief Check if NAT static mapping is identity NAT.
+ @param sm NAT static mapping
+ @return 1 if identity NAT
+*/
+#define is_identity_static_mapping(sm) (sm->flags & NAT_STATIC_MAPPING_FLAG_IDENTITY_NAT)
+
/* logging */
#define nat_log_err(...) \
vlib_log(VLIB_LOG_LEVEL_ERR, snat_main.log_class, __VA_ARGS__)
@@ -773,18 +797,19 @@ void nat44_add_del_address_dpo (ip4_address_t addr, u8 is_add);
/**
* @brief Add/delete NAT44 static mapping
*
- * @param l_addr local IPv4 address
- * @param e_addr external IPv4 address
- * @param l_port local port number
- * @param e_port external port number
- * @param vrf_id local VRF ID
- * @param addr_only 1 = 1:1NAT, 0 = 1:1NAPT
- * @param sw_if_index use interface address as external IPv4 address
- * @param proto L4 protocol
- * @param is_add 1 = add, 0 = delete
- * @param twice_nat twice-nat mode
- * @param out2in_only if 1 rule match only out2in direction
- * @param tagi opaque string tag
+ * @param l_addr local IPv4 address
+ * @param e_addr external IPv4 address
+ * @param l_port local port number
+ * @param e_port external port number
+ * @param vrf_id local VRF ID
+ * @param addr_only 1 = 1:1NAT, 0 = 1:1NAPT
+ * @param sw_if_index use interface address as external IPv4 address
+ * @param proto L4 protocol
+ * @param is_add 1 = add, 0 = delete
+ * @param twice_nat twice-nat mode
+ * @param out2in_only if 1 rule match only out2in direction
+ * @param tag opaque string tag
+ * @param identity_nat identity NAT
*
* @return 0 on success, non-zero value otherwise
*/
@@ -793,7 +818,7 @@ int snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
int addr_only, u32 sw_if_index,
snat_protocol_t proto, int is_add,
twice_nat_type_t twice_nat, u8 out2in_only,
- u8 * tag);
+ u8 * tag, u8 identity_nat);
/**
* @brief Add/delete static mapping with load-balancing (multiple backends)
@@ -1009,7 +1034,8 @@ int snat_static_mapping_match (snat_main_t * sm,
u8 * is_addr_only,
twice_nat_type_t * twice_nat,
lb_nat_type_t * lb,
- ip4_address_t * ext_host_addr);
+ ip4_address_t * ext_host_addr,
+ u8 * is_identity_nat);
/**
* @brief Add/del NAT address to FIB.
diff --git a/src/plugins/nat/nat44_cli.c b/src/plugins/nat/nat44_cli.c
index bebc6a0b2dc..0a3379acb32 100644
--- a/src/plugins/nat/nat44_cli.c
+++ b/src/plugins/nat/nat44_cli.c
@@ -718,7 +718,7 @@ add_static_mapping_command_fn (vlib_main_t * vm,
rv = snat_add_static_mapping (l_addr, e_addr, (u16) l_port, (u16) e_port,
vrf_id, addr_only, sw_if_index, proto, is_add,
- twice_nat, out2in_only, 0);
+ twice_nat, out2in_only, 0, 0);
switch (rv)
{
@@ -802,7 +802,7 @@ add_identity_mapping_command_fn (vlib_main_t * vm,
rv = snat_add_static_mapping (addr, addr, (u16) port, (u16) port,
vrf_id, addr_only, sw_if_index, proto, is_add,
- 0, 0, 0);
+ 0, 0, 0, 1);
switch (rv)
{
diff --git a/src/plugins/nat/nat44_hairpinning.c b/src/plugins/nat/nat44_hairpinning.c
index 9d49dc2300e..c07427d6bcb 100644
--- a/src/plugins/nat/nat44_hairpinning.c
+++ b/src/plugins/nat/nat44_hairpinning.c
@@ -114,7 +114,7 @@ snat_hairpinning (snat_main_t * sm,
kv0.key = key0.as_u64;
/* Check if destination is static mappings */
- if (!snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0))
+ if (!snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0, 0))
{
new_dst_addr0 = sm0.addr.as_u32;
new_dst_port0 = sm0.port;
@@ -444,7 +444,7 @@ nat44_reass_hairpinning (snat_main_t * sm,
udp0 = ip4_next_header (ip0);
/* Check if destination is static mappings */
- if (!snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0))
+ if (!snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0, 0))
{
new_dst_addr0 = sm0.addr.as_u32;
new_dst_port0 = sm0.port;
diff --git a/src/plugins/nat/nat_api.c b/src/plugins/nat/nat_api.c
index e642eddb95a..8ad5c6652ca 100644
--- a/src/plugins/nat/nat_api.c
+++ b/src/plugins/nat/nat_api.c
@@ -980,7 +980,7 @@ static void
rv = snat_add_static_mapping (local_addr, external_addr, local_port,
external_port, vrf_id, mp->addr_only,
external_sw_if_index, proto, mp->is_add,
- twice_nat, mp->out2in_only, tag);
+ twice_nat, mp->out2in_only, tag, 0);
vec_free (tag);
@@ -1027,7 +1027,7 @@ send_nat44_static_mapping_details (snat_static_mapping_t * m,
memset (rmp, 0, sizeof (*rmp));
rmp->_vl_msg_id =
ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
- rmp->addr_only = m->addr_only;
+ rmp->addr_only = is_addr_only_static_mapping (m);
clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
rmp->external_sw_if_index = ~0;
@@ -1037,8 +1037,8 @@ send_nat44_static_mapping_details (snat_static_mapping_t * m,
rmp->twice_nat = 1;
else if (m->twice_nat == TWICE_NAT_SELF)
rmp->self_twice_nat = 1;
- rmp->out2in_only = m->out2in_only;
- if (m->addr_only == 0)
+ rmp->out2in_only = is_out2in_only_static_mapping (m);
+ if (rmp->addr_only == 0)
{
rmp->protocol = snat_proto_to_ip_proto (m->proto);
rmp->external_port = htons (m->external_port);
@@ -1100,9 +1100,7 @@ vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t
/* *INDENT-OFF* */
pool_foreach (m, sm->static_mappings,
({
- if (!vec_len (m->locals) &&
- ((m->local_port != m->external_port)
- || (m->local_addr.as_u32 != m->external_addr.as_u32)))
+ if (!is_identity_static_mapping(m) && !vec_len (m->locals))
send_nat44_static_mapping_details (m, reg, mp->context);
}));
/* *INDENT-ON* */
@@ -1110,7 +1108,7 @@ vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t
for (j = 0; j < vec_len (sm->to_resolve); j++)
{
rp = sm->to_resolve + j;
- if (rp->l_addr.as_u32 != 0)
+ if (!rp->identity_nat)
send_nat44_static_map_resolve_details (rp, reg, mp->context);
}
}
@@ -1162,7 +1160,7 @@ static void
rv =
snat_add_static_mapping (addr, addr, port, port, vrf_id, mp->addr_only,
- sw_if_index, proto, mp->is_add, 0, 0, tag);
+ sw_if_index, proto, mp->is_add, 0, 0, tag, 1);
vec_free (tag);
@@ -1203,7 +1201,7 @@ send_nat44_identity_mapping_details (snat_static_mapping_t * m,
memset (rmp, 0, sizeof (*rmp));
rmp->_vl_msg_id =
ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
- rmp->addr_only = m->addr_only;
+ rmp->addr_only = is_addr_only_static_mapping (m);
clib_memcpy (rmp->ip_address, &(m->local_addr), 4);
rmp->port = htons (m->local_port);
rmp->sw_if_index = ~0;
@@ -1260,8 +1258,7 @@ static void
/* *INDENT-OFF* */
pool_foreach (m, sm->static_mappings,
({
- if (!vec_len (m->locals) && (m->local_port == m->external_port)
- && (m->local_addr.as_u32 == m->external_addr.as_u32))
+ if (is_identity_static_mapping(m) && !vec_len (m->locals))
send_nat44_identity_mapping_details (m, reg, mp->context);
}));
/* *INDENT-ON* */
@@ -1269,7 +1266,7 @@ static void
for (j = 0; j < vec_len (sm->to_resolve); j++)
{
rp = sm->to_resolve + j;
- if (rp->l_addr.as_u32 == 0)
+ if (rp->identity_nat)
send_nat44_identity_map_resolve_details (rp, reg, mp->context);
}
}
@@ -1656,7 +1653,7 @@ send_nat44_lb_static_mapping_details (snat_static_mapping_t * m,
rmp->twice_nat = 1;
else if (m->twice_nat == TWICE_NAT_SELF)
rmp->self_twice_nat = 1;
- rmp->out2in_only = m->out2in_only;
+ rmp->out2in_only = is_out2in_only_static_mapping (m);
if (m->tag)
strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
diff --git a/src/plugins/nat/nat_format.c b/src/plugins/nat/nat_format.c
index 279d6664933..a4b62b6e977 100644
--- a/src/plugins/nat/nat_format.c
+++ b/src/plugins/nat/nat_format.c
@@ -220,14 +220,14 @@ format_snat_static_mapping (u8 * s, va_list * args)
snat_static_mapping_t *m = va_arg (*args, snat_static_mapping_t *);
nat44_lb_addr_port_t *local;
- if (m->addr_only)
+ if (is_addr_only_static_mapping (m))
s = format (s, "local %U external %U vrf %d %s %s",
format_ip4_address, &m->local_addr,
format_ip4_address, &m->external_addr,
m->vrf_id,
m->twice_nat == TWICE_NAT ? "twice-nat" :
m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
- m->out2in_only ? "out2in-only" : "");
+ is_out2in_only_static_mapping (m) ? "out2in-only" : "");
else
{
if (vec_len (m->locals))
@@ -237,7 +237,7 @@ format_snat_static_mapping (u8 * s, va_list * args)
format_ip4_address, &m->external_addr, m->external_port,
m->twice_nat == TWICE_NAT ? "twice-nat" :
m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
- m->out2in_only ? "out2in-only" : "");
+ is_out2in_only_static_mapping (m) ? "out2in-only" : "");
vec_foreach (local, m->locals)
s = format (s, "\n local %U:%d vrf %d probability %d\%",
format_ip4_address, &local->addr, local->port,
@@ -251,7 +251,7 @@ format_snat_static_mapping (u8 * s, va_list * args)
m->vrf_id,
m->twice_nat == TWICE_NAT ? "twice-nat" :
m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
- m->out2in_only ? "out2in-only" : "");
+ is_out2in_only_static_mapping (m) ? "out2in-only" : "");
}
return s;
}
diff --git a/src/plugins/nat/out2in.c b/src/plugins/nat/out2in.c
index 67d831a850c..eeecf165264 100755
--- a/src/plugins/nat/out2in.c
+++ b/src/plugins/nat/out2in.c
@@ -309,6 +309,7 @@ icmp_match_out2in_slow (snat_main_t * sm, vlib_node_runtime_t * node,
u8 is_addr_only;
u32 next0 = ~0;
int err;
+ u8 identity_nat;
icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
@@ -333,7 +334,7 @@ icmp_match_out2in_slow (snat_main_t * sm, vlib_node_runtime_t * node,
/* Try to match static mapping by external address and port,
destination address and port in packet */
if (snat_static_mapping_match
- (sm, key0, &sm0, 1, &is_addr_only, 0, 0, 0))
+ (sm, key0, &sm0, 1, &is_addr_only, 0, 0, 0, &identity_nat))
{
if (!sm->forwarding_enabled)
{
@@ -364,6 +365,11 @@ icmp_match_out2in_slow (snat_main_t * sm, vlib_node_runtime_t * node,
goto out;
}
+ if (PREDICT_FALSE (identity_nat))
+ {
+ dont_translate = 1;
+ goto out;
+ }
/* Create session initiated by host from external network */
s0 = create_session_for_static_mapping (sm, b0, sm0, key0,
node, thread_index,
@@ -443,7 +449,8 @@ icmp_match_out2in_fast (snat_main_t * sm, vlib_node_runtime_t * node,
}
key0.fib_index = rx_fib_index0;
- if (snat_static_mapping_match (sm, key0, &sm0, 1, &is_addr_only, 0, 0, 0))
+ if (snat_static_mapping_match
+ (sm, key0, &sm0, 1, &is_addr_only, 0, 0, 0, 0))
{
/* Don't NAT packet aimed at the intfc address */
if (is_interface_addr (sm, node, sw_if_index0, ip0->dst_address.as_u32))
@@ -703,6 +710,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
u32 proto0, proto1;
snat_session_t *s0 = 0, *s1 = 0;
clib_bihash_kv_8_8_t kv0, kv1, value0, value1;
+ u8 identity_nat0, identity_nat1;
/* Prefetch next iteration. */
{
@@ -793,7 +801,8 @@ snat_out2in_node_fn (vlib_main_t * vm,
{
/* Try to match static mapping by external address and port,
destination address and port in packet */
- if (snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0))
+ if (snat_static_mapping_match
+ (sm, key0, &sm0, 1, 0, 0, 0, 0, &identity_nat0))
{
/*
* Send DHCP packets to the ipv4 stack, or we won't
@@ -817,6 +826,9 @@ snat_out2in_node_fn (vlib_main_t * vm,
goto trace0;
}
+ if (PREDICT_FALSE (identity_nat0))
+ goto trace0;
+
/* Create session initiated by host from external network */
s0 = create_session_for_static_mapping (sm, b0, sm0, key0, node,
thread_index, now);
@@ -950,7 +962,8 @@ snat_out2in_node_fn (vlib_main_t * vm,
{
/* Try to match static mapping by external address and port,
destination address and port in packet */
- if (snat_static_mapping_match (sm, key1, &sm1, 1, 0, 0, 0, 0))
+ if (snat_static_mapping_match
+ (sm, key1, &sm1, 1, 0, 0, 0, 0, &identity_nat1))
{
/*
* Send DHCP packets to the ipv4 stack, or we won't
@@ -974,6 +987,9 @@ snat_out2in_node_fn (vlib_main_t * vm,
goto trace1;
}
+ if (PREDICT_FALSE (identity_nat1))
+ goto trace1;
+
/* Create session initiated by host from external network */
s1 = create_session_for_static_mapping (sm, b1, sm1, key1, node,
thread_index, now);
@@ -1069,6 +1085,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
u32 proto0;
snat_session_t *s0 = 0;
clib_bihash_kv_8_8_t kv0, value0;
+ u8 identity_nat0;
/* speculatively enqueue b0 to the current next frame */
bi0 = from[0];
@@ -1143,7 +1160,8 @@ snat_out2in_node_fn (vlib_main_t * vm,
{
/* Try to match static mapping by external address and port,
destination address and port in packet */
- if (snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0))
+ if (snat_static_mapping_match
+ (sm, key0, &sm0, 1, 0, 0, 0, 0, &identity_nat0))
{
/*
* Send DHCP packets to the ipv4 stack, or we won't
@@ -1167,6 +1185,9 @@ snat_out2in_node_fn (vlib_main_t * vm,
goto trace00;
}
+ if (PREDICT_FALSE (identity_nat0))
+ goto trace00;
+
/* Create session initiated by host from external network */
s0 = create_session_for_static_mapping (sm, b0, sm0, key0, node,
thread_index, now);
@@ -1320,6 +1341,7 @@ nat44_out2in_reass_node_fn (vlib_main_t * vm,
snat_session_t *s0 = 0;
u16 old_port0, new_port0;
ip_csum_t sum0;
+ u8 identity_nat0;
/* speculatively enqueue b0 to the current next frame */
bi0 = from[0];
@@ -1377,7 +1399,7 @@ nat44_out2in_reass_node_fn (vlib_main_t * vm,
/* Try to match static mapping by external address and port,
destination address and port in packet */
if (snat_static_mapping_match
- (sm, key0, &sm0, 1, 0, 0, 0, 0))
+ (sm, key0, &sm0, 1, 0, 0, 0, 0, &identity_nat0))
{
/*
* Send DHCP packets to the ipv4 stack, or we won't
@@ -1402,6 +1424,9 @@ nat44_out2in_reass_node_fn (vlib_main_t * vm,
goto trace0;
}
+ if (PREDICT_FALSE (identity_nat0))
+ goto trace0;
+
/* Create session initiated by host from external network */
s0 =
create_session_for_static_mapping (sm, b0, sm0, key0,
@@ -1663,7 +1688,7 @@ snat_out2in_fast_node_fn (vlib_main_t * vm,
key0.port = udp0->dst_port;
key0.fib_index = rx_fib_index0;
- if (snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0))
+ if (snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0, 0))
{
b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
goto trace00;
diff --git a/src/plugins/nat/out2in_ed.c b/src/plugins/nat/out2in_ed.c
index dce6c5616c5..b2dbc513df6 100644
--- a/src/plugins/nat/out2in_ed.c
+++ b/src/plugins/nat/out2in_ed.c
@@ -471,7 +471,7 @@ icmp_match_out2in_ed (snat_main_t * sm, vlib_node_runtime_t * node,
clib_bihash_kv_16_8_t kv, value;
snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
snat_session_t *s = 0;
- u8 dont_translate = 0, is_addr_only;
+ u8 dont_translate = 0, is_addr_only, identity_nat;
snat_session_key_t e_key, l_key;
icmp = (icmp46_header_t *) ip4_next_header (ip);
@@ -496,7 +496,7 @@ icmp_match_out2in_ed (snat_main_t * sm, vlib_node_runtime_t * node,
e_key.protocol = ip_proto_to_snat_proto (key.proto);
e_key.fib_index = rx_fib_index;
if (snat_static_mapping_match
- (sm, e_key, &l_key, 1, &is_addr_only, 0, 0, 0))
+ (sm, e_key, &l_key, 1, &is_addr_only, 0, 0, 0, &identity_nat))
{
if (!sm->forwarding_enabled)
{
@@ -533,6 +533,12 @@ icmp_match_out2in_ed (snat_main_t * sm, vlib_node_runtime_t * node,
goto out;
}
+ if (PREDICT_FALSE (identity_nat))
+ {
+ dont_translate = 1;
+ goto out;
+ }
+
/* Create session initiated by host from external network */
s = create_session_for_static_mapping_ed (sm, b, l_key, e_key, node,
thread_index, 0, 0,
@@ -717,6 +723,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
snat_session_key_t e_key0, l_key0, e_key1, l_key1;
lb_nat_type_t lb_nat0, lb_nat1;
twice_nat_type_t twice_nat0, twice_nat1;
+ u8 identity_nat0, identity_nat1;
/* Prefetch next iteration. */
{
@@ -828,7 +835,8 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
e_key0.fib_index = rx_fib_index0;
if (snat_static_mapping_match (sm, e_key0, &l_key0, 1, 0,
&twice_nat0, &lb_nat0,
- &ip0->src_address))
+ &ip0->src_address,
+ &identity_nat0))
{
/*
* Send DHCP packets to the ipv4 stack, or we won't
@@ -864,6 +872,9 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
goto trace00;
}
+ if (PREDICT_FALSE (identity_nat0))
+ goto trace00;
+
/* Create session initiated by host from external network */
s0 = create_session_for_static_mapping_ed (sm, b0, l_key0,
e_key0, node,
@@ -1046,7 +1057,8 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
e_key1.fib_index = rx_fib_index1;
if (snat_static_mapping_match (sm, e_key1, &l_key1, 1, 0,
&twice_nat1, &lb_nat1,
- &ip1->src_address))
+ &ip1->src_address,
+ &identity_nat1))
{
/*
* Send DHCP packets to the ipv4 stack, or we won't
@@ -1082,6 +1094,9 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
goto trace01;
}
+ if (PREDICT_FALSE (identity_nat1))
+ goto trace01;
+
/* Create session initiated by host from external network */
s1 = create_session_for_static_mapping_ed (sm, b1, l_key1,
e_key1, node,
@@ -1202,6 +1217,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
snat_session_key_t e_key0, l_key0;
lb_nat_type_t lb_nat0;
twice_nat_type_t twice_nat0;
+ u8 identity_nat0;
/* speculatively enqueue b0 to the current next frame */
bi0 = from[0];
@@ -1297,7 +1313,8 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
e_key0.fib_index = rx_fib_index0;
if (snat_static_mapping_match (sm, e_key0, &l_key0, 1, 0,
&twice_nat0, &lb_nat0,
- &ip0->src_address))
+ &ip0->src_address,
+ &identity_nat0))
{
/*
* Send DHCP packets to the ipv4 stack, or we won't
@@ -1333,6 +1350,9 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
goto trace0;
}
+ if (PREDICT_FALSE (identity_nat0))
+ goto trace0;
+
/* Create session initiated by host from external network */
s0 = create_session_for_static_mapping_ed (sm, b0, l_key0,
e_key0, node,
@@ -1554,6 +1574,7 @@ nat44_ed_out2in_reass_node_fn (vlib_main_t * vm,
snat_session_key_t e_key0, l_key0;
lb_nat_type_t lb0;
twice_nat_type_t twice_nat0;
+ u8 identity_nat0;
/* speculatively enqueue b0 to the current next frame */
bi0 = from[0];
@@ -1634,7 +1655,8 @@ nat44_ed_out2in_reass_node_fn (vlib_main_t * vm,
e_key0.protocol = proto0;
e_key0.fib_index = rx_fib_index0;
if (snat_static_mapping_match (sm, e_key0, &l_key0, 1, 0,
- &twice_nat0, &lb0, 0))
+ &twice_nat0, &lb0, 0,
+ &identity_nat0))
{
/*
* Send DHCP packets to the ipv4 stack, or we won't
@@ -1674,6 +1696,12 @@ nat44_ed_out2in_reass_node_fn (vlib_main_t * vm,
goto trace0;
}
+ if (PREDICT_FALSE (identity_nat0))
+ {
+ reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
+ goto trace0;
+ }
+
/* Create session initiated by host from external network */
s0 = create_session_for_static_mapping_ed (sm, b0, l_key0,
e_key0, node,
diff --git a/test/test_nat.py b/test/test_nat.py
index 9092b4796bb..3b9007f6e93 100644
--- a/test/test_nat.py
+++ b/test/test_nat.py
@@ -1935,6 +1935,9 @@ class TestNAT44(MethodHolder):
self.logger.error(ppp("Unexpected or invalid packet:", p))
raise
+ sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
+ self.assertEqual(len(sessions), 0)
+
def test_multiple_inside_interfaces(self):
""" NAT44 multiple non-overlapping address space inside interfaces """