From d7603d97e046d59aba6864b208c181b39fc72b52 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Thu, 28 Mar 2019 08:56:10 +0000 Subject: [PATCH] IPSEC: tunnel fragmentation Change-Id: I63741a22bc82f5f861e1c0f26a93b5569cc52061 Signed-off-by: Neale Ranns --- src/vnet/ipsec/esp_encrypt.c | 10 ++++++++++ src/vnet/ipsec/ipsec_if.c | 3 +++ test/framework.py | 6 ++++-- test/template_ipsec.py | 40 +++++++++++++++++++++++++--------------- test/test_ipsec_tun_if_esp.py | 34 +++++++++++++++++++++++----------- 5 files changed, 65 insertions(+), 28 deletions(-) diff --git a/src/vnet/ipsec/esp_encrypt.c b/src/vnet/ipsec/esp_encrypt.c index c2069e52b33..82247697cba 100644 --- a/src/vnet/ipsec/esp_encrypt.c +++ b/src/vnet/ipsec/esp_encrypt.c @@ -563,6 +563,11 @@ VLIB_REGISTER_NODE (esp4_encrypt_tun_node) = { .n_errors = ARRAY_LEN(esp_encrypt_error_strings), .error_strings = esp_encrypt_error_strings, + + .n_next_nodes = 1, + .next_nodes = { + [ESP_ENCRYPT_NEXT_DROP] = "ip4-drop", + }, }; VNET_FEATURE_INIT (esp4_encrypt_tun_feat_node, static) = @@ -590,6 +595,11 @@ VLIB_REGISTER_NODE (esp6_encrypt_tun_node) = { .n_errors = ARRAY_LEN(esp_encrypt_error_strings), .error_strings = esp_encrypt_error_strings, + + .n_next_nodes = 1, + .next_nodes = { + [ESP_ENCRYPT_NEXT_DROP] = "ip6-drop", + }, }; VNET_FEATURE_INIT (esp6_encrypt_tun_feat_node, static) = diff --git a/src/vnet/ipsec/ipsec_if.c b/src/vnet/ipsec/ipsec_if.c index 7d6c725e539..17f28a09ac8 100644 --- a/src/vnet/ipsec/ipsec_if.c +++ b/src/vnet/ipsec/ipsec_if.c @@ -352,6 +352,9 @@ ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm, t->hw_if_index = hw_if_index; t->sw_if_index = hi->sw_if_index; + /* Standard default jumbo MTU. */ + vnet_sw_interface_set_mtu (vnm, t->sw_if_index, 9000); + /* Add the new tunnel to the DB of tunnels per sw_if_index ... */ vec_validate_init_empty (im->ipsec_if_by_sw_if_index, t->sw_if_index, ~0); diff --git a/test/framework.py b/test/framework.py index dce477d16d2..004d2f62f49 100644 --- a/test/framework.py +++ b/test/framework.py @@ -1017,9 +1017,11 @@ class VppTestCase(unittest.TestCase): i.assert_nothing_captured(remark=remark) timeout = 0.1 - def send_and_expect(self, intf, pkts, output): + def send_and_expect(self, intf, pkts, output, n_rx=None): + if not n_rx: + n_rx = len(pkts) self.pg_send(intf, pkts) - rx = output.get_capture(len(pkts)) + rx = output.get_capture(n_rx) return rx def send_and_expect_only(self, intf, pkts, output, timeout=None): diff --git a/test/template_ipsec.py b/test/template_ipsec.py index 40e787eebb7..333a6685b8e 100644 --- a/test/template_ipsec.py +++ b/test/template_ipsec.py @@ -7,7 +7,7 @@ from scapy.layers.l2 import Ether, Raw from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest from framework import VppTestCase, VppTestRunner -from util import ppp +from util import ppp, reassemble4 from vpp_papi import VppEnum @@ -161,8 +161,6 @@ class TemplateIpsec(VppTestCase): super(TemplateIpsec, self).setUp() self.setup_params() - self.payload = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"\ - "XXXXXXXXXXXXXXXXXXXXX" self.tun_spd_id = 1 self.tra_spd_id = 2 @@ -193,26 +191,30 @@ class TemplateIpsec(VppTestCase): if not self.vpp_dead: self.vapi.cli("show hardware") - def gen_encrypt_pkts(self, sa, sw_intf, src, dst, count=1): + def gen_encrypt_pkts(self, sa, sw_intf, src, dst, count=1, + payload_size=54): return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) / - sa.encrypt(IP(src=src, dst=dst) / ICMP() / self.payload) + sa.encrypt(IP(src=src, dst=dst) / + ICMP() / Raw('X' * payload_size)) for i in range(count)] - def gen_encrypt_pkts6(self, sa, sw_intf, src, dst, count=1): + def gen_encrypt_pkts6(self, sa, sw_intf, src, dst, count=1, + payload_size=54): return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) / sa.encrypt(IPv6(src=src, dst=dst) / - ICMPv6EchoRequest(id=0, seq=1, data=self.payload)) + ICMPv6EchoRequest(id=0, seq=1, + data='X' * payload_size)) for i in range(count)] - def gen_pkts(self, sw_intf, src, dst, count=1): + def gen_pkts(self, sw_intf, src, dst, count=1, payload_size=54): return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) / - IP(src=src, dst=dst) / ICMP() / self.payload + IP(src=src, dst=dst) / ICMP() / Raw('X' * payload_size) for i in range(count)] - def gen_pkts6(self, sw_intf, src, dst, count=1): + def gen_pkts6(self, sw_intf, src, dst, count=1, payload_size=54): return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) / IPv6(src=src, dst=dst) / - ICMPv6EchoRequest(id=0, seq=1, data=self.payload) + ICMPv6EchoRequest(id=0, seq=1, data='X' * payload_size) for i in range(count)] @@ -470,8 +472,10 @@ class IpsecTun4(object): self.assert_packet_counter_equal(self.tun4_encrypt_node_name, count) self.assert_packet_counter_equal(self.tun4_decrypt_node_name, count) - def verify_tun_44(self, p, count=1): + def verify_tun_44(self, p, count=1, payload_size=64, n_rx=None): self.vapi.cli("clear errors") + if not n_rx: + n_rx = count try: config_tun_params(p, self.encryption_type, self.tun_if) send_pkts = self.gen_encrypt_pkts(p.scapy_tun_sa, self.tun_if, @@ -484,16 +488,19 @@ class IpsecTun4(object): self.assert_equal(recv_pkt[IP].dst, self.pg1.remote_ip4) self.assert_packet_checksums_valid(recv_pkt) send_pkts = self.gen_pkts(self.pg1, src=self.pg1.remote_ip4, - dst=p.remote_tun_if_host, count=count) - recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if) + dst=p.remote_tun_if_host, count=count, + payload_size=payload_size) + recv_pkts = self.send_and_expect(self.pg1, send_pkts, + self.tun_if, n_rx) + decrypt_pkts = [] for recv_pkt in recv_pkts: try: decrypt_pkt = p.vpp_tun_sa.decrypt(recv_pkt[IP]) if not decrypt_pkt.haslayer(IP): decrypt_pkt = IP(decrypt_pkt[Raw].load) + decrypt_pkts.append(decrypt_pkt) self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip4) self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host) - self.assert_packet_checksums_valid(decrypt_pkt) except: self.logger.debug(ppp("Unexpected packet:", recv_pkt)) try: @@ -502,6 +509,9 @@ class IpsecTun4(object): except: pass raise + pkts = reassemble4(decrypt_pkts) + for pkt in pkts: + self.assert_packet_checksums_valid(pkt) finally: self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec")) diff --git a/test/test_ipsec_tun_if_esp.py b/test/test_ipsec_tun_if_esp.py index e9894a9f340..5af37bfac73 100644 --- a/test/test_ipsec_tun_if_esp.py +++ b/test/test_ipsec_tun_if_esp.py @@ -20,21 +20,22 @@ class TemplateIpsec4TunIfEsp(TemplateIpsec): self.tun_if = self.pg0 p = self.ipv4_params - tun_if = VppIpsecTunInterface(self, self.pg0, p.vpp_tun_spi, - p.scapy_tun_spi, p.crypt_algo_vpp_id, - p.crypt_key, p.crypt_key, - p.auth_algo_vpp_id, p.auth_key, - p.auth_key) - tun_if.add_vpp_config() - tun_if.admin_up() - tun_if.config_ip4() - tun_if.config_ip6() + + p.tun_if = VppIpsecTunInterface(self, self.pg0, p.vpp_tun_spi, + p.scapy_tun_spi, p.crypt_algo_vpp_id, + p.crypt_key, p.crypt_key, + p.auth_algo_vpp_id, p.auth_key, + p.auth_key) + p.tun_if.add_vpp_config() + p.tun_if.admin_up() + p.tun_if.config_ip4() + p.tun_if.config_ip6() VppIpRoute(self, p.remote_tun_if_host, 32, - [VppRoutePath(tun_if.remote_ip4, + [VppRoutePath(p.tun_if.remote_ip4, 0xffffffff)]).add_vpp_config() VppIpRoute(self, p.remote_tun_if_host6, 128, - [VppRoutePath(tun_if.remote_ip6, + [VppRoutePath(p.tun_if.remote_ip6, 0xffffffff, proto=DpoProto.DPO_PROTO_IP6)], is_ip6=1).add_vpp_config() @@ -58,6 +59,17 @@ class TestIpsec4TunIfEsp1(TemplateIpsec4TunIfEsp, IpsecTun4Tests): """ ipsec 6o4 tunnel basic test """ self.verify_tun_64(self.params[socket.AF_INET], count=257) + def test_tun_basic_frag44(self): + """ ipsec 4o4 tunnel frag basic test """ + p = self.ipv4_params + + self.vapi.sw_interface_set_mtu(p.tun_if.sw_if_index, + [1500, 0, 0, 0]) + self.verify_tun_44(self.params[socket.AF_INET], + count=1, payload_size=1800, n_rx=2) + self.vapi.sw_interface_set_mtu(p.tun_if.sw_if_index, + [9000, 0, 0, 0]) + class TestIpsec4TunIfEsp2(TemplateIpsec4TunIfEsp, IpsecTcpTests): """ Ipsec ESP - TCP tests """ -- 2.16.6