From e2f4e2f175beb6d6490d275049199db7dd61c783 Mon Sep 17 00:00:00 2001 From: Matus Fabian Date: Sun, 7 Oct 2018 21:28:23 -0700 Subject: [PATCH] NAT44: do not create session record for identity mapping (VPP-1439) Change-Id: I39a3146a4e4ba8eadf50af7113b9ae6b1c1d688f Signed-off-by: Matus Fabian --- src/plugins/nat/in2out.c | 41 +++++++++++++++++--- src/plugins/nat/in2out_ed.c | 39 +++++++++++++++++-- src/plugins/nat/nat.c | 74 +++++++++++++++++-------------------- src/plugins/nat/nat.h | 62 ++++++++++++++++++++++--------- src/plugins/nat/nat44_cli.c | 4 +- src/plugins/nat/nat44_hairpinning.c | 4 +- src/plugins/nat/nat_api.c | 25 ++++++------- src/plugins/nat/nat_format.c | 8 ++-- src/plugins/nat/out2in.c | 39 +++++++++++++++---- src/plugins/nat/out2in_ed.c | 40 +++++++++++++++++--- test/test_nat.py | 3 ++ 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 """ -- 2.16.6