summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/nat/nat.c11
-rw-r--r--test/test_nat.py64
2 files changed, 74 insertions, 1 deletions
diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c
index bedf4e5d386..56904ef7e04 100644
--- a/src/plugins/nat/nat.c
+++ b/src/plugins/nat/nat.c
@@ -387,7 +387,7 @@ nat44_classify_node_fn_inline (vlib_main_t * vm,
if (ip0->dst_address.as_u32 == ap->addr.as_u32)
{
next0 = NAT44_CLASSIFY_NEXT_OUT2IN;
- break;
+ goto enqueue0;
}
}
@@ -401,8 +401,17 @@ nat44_classify_node_fn_inline (vlib_main_t * vm,
if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv0, &value0))
{
next0 = NAT44_CLASSIFY_NEXT_OUT2IN;
+ goto enqueue0;
}
+ udp_header_t * udp0 = ip4_next_header (ip0);
+ m_key0.port = clib_net_to_host_u16 (udp0->dst_port);
+ m_key0.protocol = ip_proto_to_snat_proto (ip0->protocol);
+ kv0.key = m_key0.as_u64;
+ if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv0, &value0))
+ next0 = NAT44_CLASSIFY_NEXT_OUT2IN;
}
+
+ enqueue0:
/* verify speculative enqueue, maybe switch current next frame */
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
to_next, n_left_to_next,
diff --git a/test/test_nat.py b/test/test_nat.py
index d2bc4569af0..298863833fa 100644
--- a/test/test_nat.py
+++ b/test/test_nat.py
@@ -3240,6 +3240,70 @@ class TestNAT44(MethodHolder):
self.logger.error(ppp("Unexpected or invalid packet:", p))
raise
+ def test_one_armed_nat44_static(self):
+ """ One armed NAT44 and 1:1 NAPT symmetrical rule """
+ remote_host = self.pg9.remote_hosts[0]
+ local_host = self.pg9.remote_hosts[1]
+ external_port = 80
+ local_port = 8080
+ eh_port_in = 0
+
+ self.vapi.nat44_forwarding_enable_disable(1)
+ self.nat44_add_address(self.nat_addr, twice_nat=1)
+ self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
+ local_port, external_port,
+ proto=IP_PROTOS.tcp, out2in_only=1,
+ twice_nat=1)
+ self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
+ self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
+ is_inside=0)
+
+ # from client to service
+ p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
+ IP(src=remote_host.ip4, dst=self.nat_addr) /
+ TCP(sport=12345, dport=external_port))
+ self.pg9.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ capture = self.pg9.get_capture(1)
+ p = capture[0]
+ server = None
+ try:
+ ip = p[IP]
+ tcp = p[TCP]
+ self.assertEqual(ip.dst, local_host.ip4)
+ self.assertEqual(ip.src, self.nat_addr)
+ self.assertEqual(tcp.dport, local_port)
+ self.assertNotEqual(tcp.sport, 12345)
+ eh_port_in = tcp.sport
+ self.check_tcp_checksum(p)
+ self.check_ip_checksum(p)
+ except:
+ self.logger.error(ppp("Unexpected or invalid packet:", p))
+ raise
+
+ # from service back to client
+ p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
+ IP(src=local_host.ip4, dst=self.nat_addr) /
+ TCP(sport=local_port, dport=eh_port_in))
+ self.pg9.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ capture = self.pg9.get_capture(1)
+ p = capture[0]
+ try:
+ ip = p[IP]
+ tcp = p[TCP]
+ self.assertEqual(ip.src, self.nat_addr)
+ self.assertEqual(ip.dst, remote_host.ip4)
+ self.assertEqual(tcp.sport, external_port)
+ self.assertEqual(tcp.dport, 12345)
+ self.check_tcp_checksum(p)
+ self.check_ip_checksum(p)
+ except:
+ self.logger.error(ppp("Unexpected or invalid packet:", p))
+ raise
+
def test_del_session(self):
""" Delete NAT44 session """
self.nat44_add_address(self.nat_addr)