diff options
author | Matus Fabian <matfabia@cisco.com> | 2017-07-19 08:06:01 -0700 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2017-07-20 06:56:07 +0000 |
commit | 93d84c9fc2a839cb4114dbe431a00a58f2a1b168 (patch) | |
tree | b34c57f212357fdb26a8eff74b2759513ba0a57e /test | |
parent | b12ac56c44f4f6d4d5e3bc37bba39b19bc6b2551 (diff) |
SNAT: in2out translation as an output feature (VPP-903)
in2out translation as an output feature on the outside interface (postrouting)
Change-Id: I32c0311be09bdf102b9a0885b8b89c7588cb558f
Signed-off-by: Matus Fabian <matfabia@cisco.com>
Diffstat (limited to 'test')
-rw-r--r-- | test/test_snat.py | 146 | ||||
-rw-r--r-- | test/vpp_papi_provider.py | 23 |
2 files changed, 169 insertions, 0 deletions
diff --git a/test/test_snat.py b/test/test_snat.py index df81fb56ab5..1db1546a1e7 100644 --- a/test/test_snat.py +++ b/test/test_snat.py @@ -615,6 +615,12 @@ class TestSNAT(MethodHolder): intf.is_inside, is_add=0) + interfaces = self.vapi.snat_interface_output_feature_dump() + for intf in interfaces: + self.vapi.snat_interface_add_del_output_feature(intf.sw_if_index, + intf.is_inside, + is_add=0) + static_mappings = self.vapi.snat_static_mapping_dump() for sm in static_mappings: self.vapi.snat_add_static_mapping(sm.local_ip_address, @@ -2108,6 +2114,146 @@ class TestSNAT(MethodHolder): self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise + def test_output_feature(self): + """ S-NAT interface output feature (in2out postrouting) """ + self.snat_add_address(self.snat_addr) + self.vapi.snat_interface_add_del_output_feature(self.pg0.sw_if_index) + self.vapi.snat_interface_add_del_output_feature(self.pg1.sw_if_index, + is_inside=0) + + # in2out + pkts = self.create_stream_in(self.pg0, self.pg1) + self.pg0.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg1.get_capture(len(pkts)) + self.verify_capture_out(capture) + + # out2in + pkts = self.create_stream_out(self.pg1) + self.pg1.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg0.get_capture(len(pkts)) + self.verify_capture_in(capture, self.pg0) + + def test_output_feature_vrf_aware(self): + """ S-NAT interface output feature VRF aware (in2out postrouting) """ + nat_ip_vrf10 = "10.0.0.10" + nat_ip_vrf20 = "10.0.0.20" + + self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n, + dst_address_length=32, + next_hop_address=self.pg3.remote_ip4n, + next_hop_sw_if_index=self.pg3.sw_if_index, + table_id=10) + self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n, + dst_address_length=32, + next_hop_address=self.pg3.remote_ip4n, + next_hop_sw_if_index=self.pg3.sw_if_index, + table_id=20) + + self.snat_add_address(nat_ip_vrf10, vrf_id=10) + self.snat_add_address(nat_ip_vrf20, vrf_id=20) + self.vapi.snat_interface_add_del_output_feature(self.pg4.sw_if_index) + self.vapi.snat_interface_add_del_output_feature(self.pg6.sw_if_index) + self.vapi.snat_interface_add_del_output_feature(self.pg3.sw_if_index, + is_inside=0) + + # in2out VRF 10 + pkts = self.create_stream_in(self.pg4, self.pg3) + self.pg4.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg3.get_capture(len(pkts)) + self.verify_capture_out(capture, nat_ip=nat_ip_vrf10) + + # out2in VRF 10 + pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10) + self.pg3.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg4.get_capture(len(pkts)) + self.verify_capture_in(capture, self.pg4) + + # in2out VRF 20 + pkts = self.create_stream_in(self.pg6, self.pg3) + self.pg6.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg3.get_capture(len(pkts)) + self.verify_capture_out(capture, nat_ip=nat_ip_vrf20) + + # out2in VRF 20 + pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20) + self.pg3.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg6.get_capture(len(pkts)) + self.verify_capture_in(capture, self.pg6) + + def _test_output_feature_hairpinning(self): + """ S-NAT interface output feature hairpinning (in2out postrouting) """ + 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 + + self.snat_add_address(self.snat_addr) + self.vapi.snat_interface_add_del_output_feature(self.pg0.sw_if_index) + self.vapi.snat_interface_add_del_output_feature(self.pg1.sw_if_index, + is_inside=0) + + # add static mapping for server + self.snat_add_static_mapping(server.ip4, self.snat_addr, + server_in_port, server_out_port, + proto=IP_PROTOS.tcp) + + # send packet from host to server + p = (Ether(src=host.mac, dst=self.pg0.local_mac) / + IP(src=host.ip4, dst=self.snat_addr) / + 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 = capture[0] + try: + ip = p[IP] + tcp = p[TCP] + self.assertEqual(ip.src, self.snat_addr) + self.assertEqual(ip.dst, server.ip4) + self.assertNotEqual(tcp.sport, host_in_port) + self.assertEqual(tcp.dport, server_in_port) + self.check_tcp_checksum(p) + host_out_port = tcp.sport + except: + self.logger.error(ppp("Unexpected or invalid packet:", p)) + raise + + # send reply from server to host + p = (Ether(src=server.mac, dst=self.pg0.local_mac) / + IP(src=server.ip4, dst=self.snat_addr) / + TCP(sport=server_in_port, dport=host_out_port)) + self.pg0.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg0.get_capture(1) + p = capture[0] + try: + ip = p[IP] + tcp = p[TCP] + self.assertEqual(ip.src, self.snat_addr) + self.assertEqual(ip.dst, host.ip4) + self.assertEqual(tcp.sport, server_out_port) + self.assertEqual(tcp.dport, host_in_port) + self.check_tcp_checksum(p) + except: + self.logger.error(ppp("Unexpected or invalid packet:"), p) + raise + def tearDown(self): super(TestSNAT, self).tearDown() if not self.vpp_dead: diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py index 2814ef97b9e..11e16e49b8f 100644 --- a/test/vpp_papi_provider.py +++ b/test/vpp_papi_provider.py @@ -1055,6 +1055,23 @@ class VppPapiProvider(object): 'is_inside': is_inside, 'sw_if_index': sw_if_index}) + def snat_interface_add_del_output_feature( + self, + sw_if_index, + is_inside=1, + is_add=1): + """Enable/disable S-NAT output feature on the interface + + :param sw_if_index: Software index of the interface + :param is_inside: 1 if inside, 0 if outside (Default value = 1) + :param is_add: 1 if add, 0 if delete (Default value = 1) + """ + return self.api( + self.papi.snat_interface_add_del_output_feature, + {'is_add': is_add, + 'is_inside': is_inside, + 'sw_if_index': sw_if_index}) + def snat_add_static_mapping( self, local_ip, @@ -1128,6 +1145,12 @@ class VppPapiProvider(object): """ return self.api(self.papi.snat_interface_dump, {}) + def snat_interface_output_feature_dump(self): + """Dump interfaces with S-NAT output feature + :return: Dictionary of interfaces with S-NAT output feature + """ + return self.api(self.papi.snat_interface_output_feature_dump, {}) + def snat_static_mapping_dump(self): """Dump S-NAT static mappings :return: Dictionary of S-NAT static mappings |