aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatus Fabian <matfabia@cisco.com>2018-03-20 04:31:42 -0700
committerOle Trøan <otroan@employees.org>2018-03-23 10:49:54 +0000
commit265640ce768d76920f4bc79016cdc90bb35d714c (patch)
tree9f2f864f3811e41d8a90c321a1c27c3c02f3b207
parentf8fda2a98a699b1dbe399fe80cd9c6c765648aed (diff)
NAT44: fix removal of LB static mappings with same local address and port pair (VPP-1199)
Change-Id: Iad8c626e83bbc58d5c85b6736f5a3dd5bc9ceafb Signed-off-by: Matus Fabian <matfabia@cisco.com> (cherry picked from commit e877d68407d316adb64baa855985b746dcb2e102)
-rw-r--r--src/plugins/nat/nat.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c
index a3a104f6ae7..acd167163c2 100644
--- a/src/plugins/nat/nat.c
+++ b/src/plugins/nat/nat.c
@@ -969,6 +969,33 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
return 0;
}
+static int lb_local_exists (nat44_lb_addr_port_t * local,
+ ip4_address_t * e_addr, u16 e_port)
+{
+ snat_main_t *sm = &snat_main;
+ snat_static_mapping_t *m;
+ nat44_lb_addr_port_t *ap;
+
+ /* *INDENT-OFF* */
+ pool_foreach (m, sm->static_mappings,
+ ({
+ if (vec_len(m->locals))
+ {
+ if (m->external_port == e_port && m->external_addr.as_u32 == e_addr->as_u32)
+ continue;
+
+ vec_foreach (ap, m->locals)
+ {
+ if (ap->port == local->port && ap->addr.as_u32 == local->addr.as_u32)
+ return 1;
+ }
+ }
+ }));
+ /* *INDENT-ON* */
+
+ return 0;
+}
+
int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
snat_protocol_t proto, u32 vrf_id,
nat44_lb_addr_port_t *locals, u8 is_add,
@@ -1181,12 +1208,15 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
return VNET_API_ERROR_UNSPECIFIED;
}
- m_key.port = clib_host_to_net_u16 (local->port);
- kv.key = m_key.as_u64;
- if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 0))
+ if (!lb_local_exists(local, &e_addr, e_port))
{
- clib_warning ("in2out key del failed");
- return VNET_API_ERROR_UNSPECIFIED;
+ m_key.port = clib_host_to_net_u16 (local->port);
+ kv.key = m_key.as_u64;
+ if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 0))
+ {
+ clib_warning ("in2out key del failed");
+ return VNET_API_ERROR_UNSPECIFIED;
+ }
}
/* Delete sessions */
u_key.addr = local->addr;