summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorMatus Fabian <matfabia@cisco.com>2017-07-06 05:37:49 -0700
committerOle Trøan <otroan@employees.org>2017-07-07 07:04:42 +0000
commit7968e6cad5fac28568162945e2e57556740013fd (patch)
treee379568214b125982ff3348d4943c1ac5cab8832 /test
parent7b749fe890a4acb23431148859c25643a3597d2a (diff)
SNAT: Fallback to 3-tuple key for non TCP/UDP sessions (VPP-884)
Change-Id: I4868ff6e81c579b29d3ea066976ae145f8b83e9e Signed-off-by: Matus Fabian <matfabia@cisco.com>
Diffstat (limited to 'test')
-rw-r--r--test/test_snat.py247
1 files changed, 246 insertions, 1 deletions
diff --git a/test/test_snat.py b/test/test_snat.py
index f876c5f0ab7..df81fb56ab5 100644
--- a/test/test_snat.py
+++ b/test/test_snat.py
@@ -1932,7 +1932,7 @@ class TestSNAT(MethodHolder):
self.logger.error(ppp("Unexpected or invalid packet:", packet))
raise
- def test_hairpinning_unknown_proto(self):
+ def test_hairpinning_static_unknown_proto(self):
""" 1:1 NAT translate packet with unknown protocol - hairpinning """
host = self.pg0.remote_hosts[0]
@@ -1987,6 +1987,127 @@ class TestSNAT(MethodHolder):
self.logger.error(ppp("Unexpected or invalid packet:", packet))
raise
+ def test_unknown_proto(self):
+ """ SNAT translate packet with unknown protocol """
+ self.snat_add_address(self.snat_addr)
+ self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
+ self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index,
+ is_inside=0)
+
+ # in2out
+ p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
+ IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
+ TCP(sport=self.tcp_port_in, dport=20))
+ self.pg0.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ p = self.pg1.get_capture(1)
+
+ p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
+ IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
+ GRE() /
+ IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
+ TCP(sport=1234, dport=1234))
+ self.pg0.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ p = self.pg1.get_capture(1)
+ packet = p[0]
+ try:
+ self.assertEqual(packet[IP].src, self.snat_addr)
+ self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
+ self.assertTrue(packet.haslayer(GRE))
+ self.check_ip_checksum(packet)
+ except:
+ self.logger.error(ppp("Unexpected or invalid packet:", packet))
+ raise
+
+ # out2in
+ p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
+ IP(src=self.pg1.remote_ip4, dst=self.snat_addr) /
+ GRE() /
+ IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
+ TCP(sport=1234, dport=1234))
+ self.pg1.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ p = self.pg0.get_capture(1)
+ packet = p[0]
+ try:
+ self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
+ self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
+ self.assertTrue(packet.haslayer(GRE))
+ self.check_ip_checksum(packet)
+ except:
+ self.logger.error(ppp("Unexpected or invalid packet:", packet))
+ raise
+
+ def test_hairpinning_unknown_proto(self):
+ """ SNAT translate packet with unknown protocol - hairpinning """
+ host = self.pg0.remote_hosts[0]
+ server = self.pg0.remote_hosts[1]
+ host_in_port = 1234
+ host_out_port = 0
+ server_in_port = 5678
+ server_out_port = 8765
+ server_nat_ip = "10.0.0.11"
+
+ self.snat_add_address(self.snat_addr)
+ self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
+ self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index,
+ is_inside=0)
+
+ # add static mapping for server
+ self.snat_add_static_mapping(server.ip4, server_nat_ip)
+
+ # host to server
+ p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
+ IP(src=host.ip4, dst=server_nat_ip) /
+ TCP(sport=host_in_port, dport=server_out_port))
+ self.pg0.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ capture = self.pg0.get_capture(1)
+
+ p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
+ IP(src=host.ip4, dst=server_nat_ip) /
+ GRE() /
+ IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
+ TCP(sport=1234, dport=1234))
+ self.pg0.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ p = self.pg0.get_capture(1)
+ packet = p[0]
+ try:
+ self.assertEqual(packet[IP].src, self.snat_addr)
+ self.assertEqual(packet[IP].dst, server.ip4)
+ self.assertTrue(packet.haslayer(GRE))
+ self.check_ip_checksum(packet)
+ except:
+ self.logger.error(ppp("Unexpected or invalid packet:", packet))
+ raise
+
+ # server to host
+ p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
+ IP(src=server.ip4, dst=self.snat_addr) /
+ GRE() /
+ IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
+ TCP(sport=1234, dport=1234))
+ self.pg0.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ p = self.pg0.get_capture(1)
+ packet = p[0]
+ try:
+ self.assertEqual(packet[IP].src, server_nat_ip)
+ self.assertEqual(packet[IP].dst, host.ip4)
+ self.assertTrue(packet.haslayer(GRE))
+ self.check_ip_checksum(packet)
+ except:
+ self.logger.error(ppp("Unexpected or invalid packet:", packet))
+ raise
+
def tearDown(self):
super(TestSNAT, self).tearDown()
if not self.vpp_dead:
@@ -3230,6 +3351,130 @@ class TestNAT64(MethodHolder):
vrf1_pref64_len)
self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
+ def _test_unknown_proto(self):
+ """ NAT64 translate packet with unknown protocol """
+
+ self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
+ self.nat_addr_n)
+ self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
+ self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
+ remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
+
+ # in2out
+ p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
+ IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
+ TCP(sport=self.tcp_port_in, dport=20))
+ self.pg0.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ p = self.pg1.get_capture(1)
+
+ p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
+ IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
+ GRE() /
+ IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
+ TCP(sport=1234, dport=1234))
+ self.pg0.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ p = self.pg1.get_capture(1)
+ packet = p[0]
+ try:
+ self.assertEqual(packet[IP].src, self.nat_addr)
+ self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
+ self.assertTrue(packet.haslayer(GRE))
+ self.check_ip_checksum(packet)
+ except:
+ self.logger.error(ppp("Unexpected or invalid packet:", packet))
+ raise
+
+ # out2in
+ p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
+ IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
+ GRE() /
+ IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
+ TCP(sport=1234, dport=1234))
+ self.pg1.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ p = self.pg0.get_capture(1)
+ packet = p[0]
+ try:
+ self.assertEqual(packet[IPv6].src, remote_ip6)
+ self.assertEqual(packet[IPv6].dst, self.pgi0.remote_ip6)
+ self.assertTrue(packet.haslayer(GRE))
+ except:
+ self.logger.error(ppp("Unexpected or invalid packet:", packet))
+ raise
+
+ def _test_hairpinning_unknown_proto(self):
+ """ NAT64 translate packet with unknown protocol - hairpinning """
+
+ client = self.pg0.remote_hosts[0]
+ server = self.pg0.remote_hosts[1]
+ server_tcp_in_port = 22
+ server_tcp_out_port = 4022
+ client_tcp_in_port = 1234
+ client_udp_in_port = 1235
+ nat_addr_ip6 = self.compose_ip6(self.nat_addr, '64:ff9b::', 96)
+
+ self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
+ self.nat_addr_n)
+ self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
+ self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
+
+ self.vapi.nat64_add_del_static_bib(server.ip6n,
+ self.nat_addr_n,
+ server_tcp_in_port,
+ server_tcp_out_port,
+ IP_PROTOS.tcp)
+
+ # client to server
+ p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
+ IPv6(src=client.ip6, dst=nat_addr_ip6) /
+ TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
+ self.pg0.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ p = self.pg0.get_capture(1)
+
+ p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
+ IPv6(src=client.ip6, dst=nat_addr_ip6) /
+ GRE() /
+ IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
+ TCP(sport=1234, dport=1234))
+ self.pg0.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ p = self.pg0.get_capture(1)
+ packet = p[0]
+ try:
+ self.assertEqual(packet[IPv6].src, nat_addr_ip6)
+ self.assertEqual(packet[IPv6].dst, server.ip6)
+ self.assertTrue(packet.haslayer(GRE))
+ except:
+ self.logger.error(ppp("Unexpected or invalid packet:", packet))
+ raise
+
+ # server to client
+ p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
+ IPv6(src=server.ip6, dst=nat_addr_ip6) /
+ GRE() /
+ IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
+ TCP(sport=1234, dport=1234))
+ self.pg0.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ p = self.pg0.get_capture(1)
+ packet = p[0]
+ try:
+ self.assertEqual(packet[IPv6].src, nat_addr_ip6)
+ self.assertEqual(packet[IPv6].dst, client.ip6)
+ self.assertTrue(packet.haslayer(GRE))
+ except:
+ self.logger.error(ppp("Unexpected or invalid packet:", packet))
+ raise
+
def nat64_get_ses_num(self):
"""
Return number of active NAT64 sessions.
n">pi0); p1 = vlib_get_buffer (vm, pi1); n_packets -= 2; packets += 2; ip0 = (void *) (p0->data + ip_header_offset); ip1 = (void *) (p1->data + ip_header_offset); ip0->payload_length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, p0) - ip_header_offset - sizeof (ip0[0])); ip1->payload_length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, p1) - ip_header_offset - sizeof (ip1[0])); } while (n_packets >= 1) { u32 pi0; vlib_buffer_t *p0; ip6_header_t *ip0; pi0 = packets[0]; p0 = vlib_get_buffer (vm, pi0); n_packets -= 1; packets += 1; ip0 = (void *) (p0->data + ip_header_offset); ip0->payload_length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, p0) - ip_header_offset - sizeof (ip0[0])); } } typedef struct { pg_edit_t ip_version; pg_edit_t traffic_class; pg_edit_t flow_label; pg_edit_t payload_length; pg_edit_t protocol; pg_edit_t hop_limit; pg_edit_t src_address, dst_address; } pg_ip6_header_t; static inline void pg_ip6_header_init (pg_ip6_header_t * p) { /* Initialize fields that are not bit fields in the IP header. */ #define _(f) pg_edit_init (&p->f, ip6_header_t, f); _(payload_length); _(hop_limit); _(protocol); _(src_address); _(dst_address); #undef _ /* Initialize bit fields. */ pg_edit_init_bitfield (&p->ip_version, ip6_header_t, ip_version_traffic_class_and_flow_label, 28, 4); pg_edit_init_bitfield (&p->traffic_class, ip6_header_t, ip_version_traffic_class_and_flow_label, 20, 8); pg_edit_init_bitfield (&p->flow_label, ip6_header_t, ip_version_traffic_class_and_flow_label, 0, 20); } uword unformat_pg_ip6_header (unformat_input_t * input, va_list * args) { pg_stream_t *s = va_arg (*args, pg_stream_t *); pg_ip6_header_t *p; u32 group_index; p = pg_create_edit_group (s, sizeof (p[0]), sizeof (ip6_header_t), &group_index); pg_ip6_header_init (p); /* Defaults. */ pg_edit_set_fixed (&p->ip_version, 6); pg_edit_set_fixed (&p->traffic_class, 0); pg_edit_set_fixed (&p->flow_label, 0); pg_edit_set_fixed (&p->hop_limit, 64); p->payload_length.type = PG_EDIT_UNSPECIFIED; if (!unformat (input, "%U: %U -> %U", unformat_pg_edit, unformat_ip_protocol, &p->protocol, unformat_pg_edit, unformat_ip6_address, &p->src_address, unformat_pg_edit, unformat_ip6_address, &p->dst_address)) goto error; /* Parse options. */ while (1) { if (unformat (input, "version %U", unformat_pg_edit, unformat_pg_number, &p->ip_version)) ; else if (unformat (input, "traffic-class %U", unformat_pg_edit, unformat_pg_number, &p->traffic_class)) ; else if (unformat (input, "length %U", unformat_pg_edit, unformat_pg_number, &p->payload_length)) ; else if (unformat (input, "hop-limit %U", unformat_pg_edit, unformat_pg_number, &p->hop_limit)) ; /* Can't parse input: try next protocol level. */ else break; } { ip_main_t *im = &ip_main; ip_protocol_t protocol; ip_protocol_info_t *pi; pi = 0; if (p->protocol.type == PG_EDIT_FIXED) { protocol = pg_edit_get_value (&p->protocol, PG_EDIT_LO); pi = ip_get_protocol_info (im, protocol); } if (pi && pi->unformat_pg_edit && unformat_user (input, pi->unformat_pg_edit, s)) ; else if (!unformat_user (input, unformat_pg_payload, s)) goto error; if (p->payload_length.type == PG_EDIT_UNSPECIFIED && s->min_packet_bytes == s->max_packet_bytes && group_index + 1 < vec_len (s->edit_groups)) { pg_edit_set_fixed (&p->payload_length, pg_edit_group_n_bytes (s, group_index) - sizeof (ip6_header_t)); } p = pg_get_edit_group (s, group_index); if (p->payload_length.type == PG_EDIT_UNSPECIFIED) { pg_edit_group_t *g = pg_stream_get_group (s, group_index); g->edit_function = ip6_pg_edit_function; } return 1; } error: /* Free up any edits we may have added. */ pg_free_edit_group (s); return 0; } /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */