From 9ec846c2684b69f47505d73ea9f873b793a11558 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Tue, 9 Feb 2021 14:04:02 +0000 Subject: ipsec: Use the new tunnel API types to add flow label and TTL copy support Type: feature attmpet 2. this includes changes in ah_encrypt that don't use uninitialised memory when doing tunnel mode fixups. Signed-off-by: Neale Ranns Change-Id: Ie3cb776f5c415c93b8a5ee22f22586fd0181110d --- test/template_ipsec.py | 32 +++++++++++++++++++++++++------- test/test_ipsec_ah.py | 6 ++++-- test/test_ipsec_esp.py | 17 +++++++++-------- test/test_ipsec_tun_if_esp.py | 34 ++++++++++++++++++++++++++++------ test/vpp_ipsec.py | 30 +++++++++++++++++++----------- 5 files changed, 85 insertions(+), 34 deletions(-) (limited to 'test') diff --git a/test/template_ipsec.py b/test/template_ipsec.py index 918c99383af..0c1f5a19298 100644 --- a/test/template_ipsec.py +++ b/test/template_ipsec.py @@ -37,6 +37,11 @@ class IPsecIPv4Params: self.vpp_tra_sa_id = 400 self.vpp_tra_spi = 4000 + self.outer_hop_limit = 64 + self.inner_hop_limit = 255 + self.outer_flow_label = 0 + self.inner_flow_label = 0x12345 + self.auth_algo_vpp_id = (VppEnum.vl_api_ipsec_integ_alg_t. IPSEC_API_INTEG_ALG_SHA1_96) self.auth_algo = 'HMAC-SHA1-96' # scapy name @@ -76,6 +81,11 @@ class IPsecIPv6Params: self.vpp_tra_sa_id = 800 self.vpp_tra_spi = 4000 + self.outer_hop_limit = 64 + self.inner_hop_limit = 255 + self.outer_flow_label = 0 + self.inner_flow_label = 0x12345 + self.auth_algo_vpp_id = (VppEnum.vl_api_ipsec_integ_alg_t. IPSEC_API_INTEG_ALG_SHA1_96) self.auth_algo = 'HMAC-SHA1-96' # scapy name @@ -242,7 +252,9 @@ class TemplateIpsec(VppTestCase): def gen_encrypt_pkts6(self, p, 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) / + sa.encrypt(IPv6(src=src, dst=dst, + hlim=p.inner_hop_limit, + fl=p.inner_flow_label) / ICMPv6EchoRequest(id=0, seq=1, data='X' * payload_size)) for i in range(count)] @@ -252,9 +264,10 @@ class TemplateIpsec(VppTestCase): IP(src=src, dst=dst) / ICMP() / Raw(b'X' * payload_size) for i in range(count)] - def gen_pkts6(self, sw_intf, src, dst, count=1, payload_size=54): + def gen_pkts6(self, p, 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) / + IPv6(src=src, dst=dst, + hlim=p.inner_hop_limit, fl=p.inner_flow_label) / ICMPv6EchoRequest(id=0, seq=1, data='X' * payload_size) for i in range(count)] @@ -945,7 +958,7 @@ class IpsecTun4(object): self.assert_equal(recv_pkt[IPv6].src, p.remote_tun_if_host6) self.assert_equal(recv_pkt[IPv6].dst, self.pg1.remote_ip6) self.assert_packet_checksums_valid(recv_pkt) - send_pkts = self.gen_pkts6(self.pg1, src=self.pg1.remote_ip6, + send_pkts = self.gen_pkts6(p, self.pg1, src=self.pg1.remote_ip6, dst=p.remote_tun_if_host6, count=count) recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if) for recv_pkt in recv_pkts: @@ -1034,6 +1047,9 @@ class IpsecTun6(object): self.assert_packet_checksums_valid(rx) self.assertEqual(len(rx) - len(Ether()) - len(IPv6()), rx[IPv6].plen) + self.assert_equal(rx[IPv6].hlim, p.outer_hop_limit) + if p.outer_flow_label: + self.assert_equal(rx[IPv6].fl, p.outer_flow_label) try: decrypt_pkt = p.vpp_tun_sa.decrypt(rx[IPv6]) if not decrypt_pkt.haslayer(IPv6): @@ -1041,6 +1057,8 @@ class IpsecTun6(object): self.assert_packet_checksums_valid(decrypt_pkt) self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip6) self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host) + self.assert_equal(decrypt_pkt.hlim, p.inner_hop_limit - 1) + self.assert_equal(decrypt_pkt.fl, p.inner_flow_label) except: self.logger.debug(ppp("Unexpected packet:", rx)) try: @@ -1076,7 +1094,7 @@ class IpsecTun6(object): recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1) self.verify_decrypted6(p_in, recv_pkts) - send_pkts = self.gen_pkts6(self.pg1, src=self.pg1.remote_ip6, + send_pkts = self.gen_pkts6(p_in, self.pg1, src=self.pg1.remote_ip6, dst=p_out.remote_tun_if_host, count=count, payload_size=payload_size) @@ -1108,7 +1126,7 @@ class IpsecTun6(object): self.pg1, n_rx=1) self.verify_decrypted6(p, recv_pkts) - send_pkts = self.gen_pkts6(self.pg1, src=self.pg1.remote_ip6, + send_pkts = self.gen_pkts6(p, self.pg1, src=self.pg1.remote_ip6, dst=p.remote_tun_if_host, count=1, payload_size=64) @@ -1198,7 +1216,7 @@ class IpsecTun6HandoffTests(IpsecTun6): self.pg1, worker=worker) self.verify_decrypted6(p, recv_pkts) - send_pkts = self.gen_pkts6(self.pg1, src=self.pg1.remote_ip6, + send_pkts = self.gen_pkts6(p, self.pg1, src=self.pg1.remote_ip6, dst=p.remote_tun_if_host, count=N_PKTS) recv_pkts = self.send_and_expect(self.pg1, send_pkts, diff --git a/test/test_ipsec_ah.py b/test/test_ipsec_ah.py index d44492ddd26..ef6725e6a10 100644 --- a/test/test_ipsec_ah.py +++ b/test/test_ipsec_ah.py @@ -126,6 +126,8 @@ class ConfigIpsecAH(TemplateIpsec): tun_flags = params.tun_flags e = VppEnum.vl_api_ipsec_spd_action_t objs = [] + params.outer_hop_limit = 253 + params.outer_flow_label = 0x12345 params.tun_sa_in = VppIpsecSA(self, scapy_tun_sa_id, scapy_tun_spi, auth_algo_vpp_id, auth_key, @@ -336,7 +338,7 @@ class TestIpsecAhTun(TemplateIpsecAh, IpsecTun46Tests): Raw(b'X' * payload_size) for i in range(count)] - def gen_pkts6(self, sw_intf, src, dst, count=1, payload_size=54): + def gen_pkts6(self, p, sw_intf, src, dst, count=1, payload_size=54): # set the DSCP + ECN - flags are set to copy both return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) / IPv6(src=src, dst=dst, tc=5) / @@ -375,7 +377,7 @@ class TestIpsecAhTun2(TemplateIpsecAh, IpsecTun46Tests): Raw(b'X' * payload_size) for i in range(count)] - def gen_pkts6(self, sw_intf, src, dst, count=1, payload_size=54): + def gen_pkts6(self, p, sw_intf, src, dst, count=1, payload_size=54): # set the DSCP + ECN - flags are set to copy both return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) / IPv6(src=src, dst=dst, tc=0) / diff --git a/test/test_ipsec_esp.py b/test/test_ipsec_esp.py index 178b1d248bf..11d44049aeb 100644 --- a/test/test_ipsec_esp.py +++ b/test/test_ipsec_esp.py @@ -123,7 +123,8 @@ class ConfigIpsecESP(TemplateIpsec): tun_flags=tun_flags, dscp=params.dscp, flags=flags, - salt=salt) + salt=salt, + hop_limit=params.outer_hop_limit) params.tun_sa_out = VppIpsecSA(self, vpp_tun_sa_id, vpp_tun_spi, auth_algo_vpp_id, auth_key, crypt_algo_vpp_id, crypt_key, @@ -133,7 +134,8 @@ class ConfigIpsecESP(TemplateIpsec): tun_flags=tun_flags, dscp=params.dscp, flags=flags, - salt=salt) + salt=salt, + hop_limit=params.outer_hop_limit) objs.append(params.tun_sa_in) objs.append(params.tun_sa_out) @@ -401,7 +403,7 @@ class TestIpsecEspTun(TemplateIpsecEsp, IpsecTun46Tests): Raw(b'X' * payload_size) for i in range(count)] - def gen_pkts6(self, sw_intf, src, dst, count=1, payload_size=54): + def gen_pkts6(self, p, sw_intf, src, dst, count=1, payload_size=54): # set the DSCP + ECN - flags are set to copy both return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) / IPv6(src=src, dst=dst, tc=5) / @@ -433,15 +435,13 @@ class TestIpsecEspTun2(TemplateIpsecEsp, IpsecTun46Tests): super(TestIpsecEspTun2, self).setUp() def gen_pkts(self, sw_intf, src, dst, count=1, payload_size=54): - # set the DSCP + ECN - flags are set to copy only DSCP return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) / IP(src=src, dst=dst) / UDP(sport=4444, dport=4444) / Raw(b'X' * payload_size) for i in range(count)] - def gen_pkts6(self, sw_intf, src, dst, count=1, payload_size=54): - # set the DSCP + ECN - flags are set to copy both + def gen_pkts6(self, p, 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) / UDP(sport=4444, dport=4444) / @@ -449,13 +449,13 @@ class TestIpsecEspTun2(TemplateIpsecEsp, IpsecTun46Tests): for i in range(count)] def verify_encrypted(self, p, sa, rxs): - # just check that only the DSCP is copied + # just check that only the DSCP is set for rx in rxs: self.assertEqual(rx[IP].tos, VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_EF << 2) def verify_encrypted6(self, p, sa, rxs): - # just check that the DSCP & ECN are copied + # just check that the DSCP is set for rx in rxs: self.assertEqual(rx[IPv6].tc, VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_AF11 << 2) @@ -684,6 +684,7 @@ class RunTestIpsecEspAll(ConfigIpsecESP, p.crypt_key = algo['key'] p.salt = algo['salt'] p.flags = p.flags | flag + p.outer_flow_label = 243224 self.reporter.send_keep_alive(self) diff --git a/test/test_ipsec_tun_if_esp.py b/test/test_ipsec_tun_if_esp.py index 5bcd9ddfae0..2ef1351ae7f 100644 --- a/test/test_ipsec_tun_if_esp.py +++ b/test/test_ipsec_tun_if_esp.py @@ -1494,7 +1494,7 @@ class TestIpsecGre6IfEspTra(TemplateIpsec, Raw(b'X' * payload_size)) for i in range(count)] - def gen_pkts6(self, sw_intf, src, dst, count=1, + def gen_pkts6(self, p, sw_intf, src, dst, count=1, payload_size=100): return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) / IPv6(src="1::1", dst="1::2") / @@ -1724,7 +1724,7 @@ class TestIpsecMGreIfEspTra6(TemplateIpsec, IpsecTun6): Raw(b'X' * payload_size)) for i in range(count)] - def gen_pkts6(self, sw_intf, src, dst, count=1, + def gen_pkts6(self, p, sw_intf, src, dst, count=1, payload_size=100): return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) / IPv6(src="1::1", dst=dst) / @@ -2263,7 +2263,7 @@ class TestIpsec6TunProtectTun(TemplateIpsec, Raw(b'X' * payload_size)) for i in range(count)] - def gen_pkts6(self, sw_intf, src, dst, count=1, + def gen_pkts6(self, p, sw_intf, src, dst, count=1, payload_size=100): return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) / IPv6(src=src, dst=dst) / @@ -2659,12 +2659,19 @@ class TemplateIpsecItf6(object): def config_sa_tun(self, p, src, dst): config_tun_params(p, self.encryption_type, None, src, dst) + if not hasattr(p, 'tun_flags'): + p.tun_flags = None + if not hasattr(p, 'hop_limit'): + p.hop_limit = 255 + p.tun_sa_out = VppIpsecSA(self, p.scapy_tun_sa_id, p.scapy_tun_spi, p.auth_algo_vpp_id, p.auth_key, p.crypt_algo_vpp_id, p.crypt_key, self.vpp_esp_protocol, src, dst, - flags=p.flags) + flags=p.flags, + tun_flags=p.tun_flags, + hop_limit=p.hop_limit) p.tun_sa_out.add_vpp_config() p.tun_sa_in = VppIpsecSA(self, p.vpp_tun_sa_id, p.vpp_tun_spi, @@ -2729,8 +2736,13 @@ class TestIpsecItf6(TemplateIpsec, def test_tun_44(self): """IPSEC interface IPv6""" + tf = VppEnum.vl_api_tunnel_encap_decap_flags_t n_pkts = 127 p = self.ipv6_params + p.inner_hop_limit = 24 + p.outer_hop_limit = 23 + p.outer_flow_label = 243224 + p.tun_flags = tf.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_HOP_LIMIT self.config_network(p) self.config_sa_tun(p, @@ -2776,6 +2788,12 @@ class TestIpsecItf6(TemplateIpsec, np.vpp_tun_sa_id += 1 np.tun_if.local_spi = p.vpp_tun_spi np.tun_if.remote_spi = p.scapy_tun_spi + np.inner_hop_limit = 24 + np.outer_hop_limit = 128 + np.inner_flow_label = 0xabcde + np.outer_flow_label = 0xabcde + np.hop_limit = 128 + np.tun_flags = tf.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_FLOW_LABEL self.config_sa_tun(np, self.pg0.local_ip6, @@ -2828,6 +2846,7 @@ class TestIpsecMIfEsp4(TemplateIpsec, IpsecTun4): try: self.assertEqual(rx[IP].tos, VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_EF << 2) + self.assertEqual(rx[IP].ttl, p.hop_limit) pkt = sa.decrypt(rx[IP]) if not pkt.haslayer(IP): pkt = IP(pkt[Raw].load) @@ -2876,6 +2895,7 @@ class TestIpsecMIfEsp4(TemplateIpsec, IpsecTun4): p.scapy_tra_spi = p.scapy_tra_spi + ii p.vpp_tra_sa_id = p.vpp_tra_sa_id + ii p.vpp_tra_spi = p.vpp_tra_spi + ii + p.hop_limit = ii+10 p.tun_sa_out = VppIpsecSA( self, p.scapy_tun_sa_id, p.scapy_tun_spi, p.auth_algo_vpp_id, p.auth_key, @@ -2883,7 +2903,8 @@ class TestIpsecMIfEsp4(TemplateIpsec, IpsecTun4): self.vpp_esp_protocol, self.pg0.local_ip4, self.pg0.remote_hosts[ii].ip4, - dscp=VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_EF) + dscp=VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_EF, + hop_limit=p.hop_limit) p.tun_sa_out.add_vpp_config() p.tun_sa_in = VppIpsecSA( @@ -2893,7 +2914,8 @@ class TestIpsecMIfEsp4(TemplateIpsec, IpsecTun4): self.vpp_esp_protocol, self.pg0.remote_hosts[ii].ip4, self.pg0.local_ip4, - dscp=VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_EF) + dscp=VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_EF, + hop_limit=p.hop_limit) p.tun_sa_in.add_vpp_config() p.tun_protect = VppIpsecTunProtect( diff --git a/test/vpp_ipsec.py b/test/vpp_ipsec.py index 013e3d7310b..d0ceeae2e4d 100644 --- a/test/vpp_ipsec.py +++ b/test/vpp_ipsec.py @@ -194,7 +194,7 @@ class VppIpsecSA(VppObject): tun_src=None, tun_dst=None, flags=None, salt=0, tun_flags=None, dscp=None, - udp_src=None, udp_dst=None): + udp_src=None, udp_dst=None, hop_limit=None): e = VppEnum.vl_api_ipsec_sad_flags_t self.test = test self.id = id @@ -206,6 +206,7 @@ class VppIpsecSA(VppObject): self.proto = proto self.salt = salt + self.table_id = 0 self.tun_src = tun_src self.tun_dst = tun_dst if not flags: @@ -228,6 +229,18 @@ class VppIpsecSA(VppObject): self.dscp = VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_CS0 if dscp: self.dscp = dscp + self.hop_limit = 255 + if hop_limit: + self.hop_limit = hop_limit + + def tunnel_encode(self): + return {'src': (self.tun_src if self.tun_src else []), + 'dst': (self.tun_dst if self.tun_dst else []), + 'encap_decap_flags': self.tun_flags, + 'dscp': self.dscp, + 'hop_limit': self.hop_limit, + 'table_id': self.table_id + } def add_vpp_config(self): entry = { @@ -244,10 +257,7 @@ class VppIpsecSA(VppObject): 'length': len(self.crypto_key), }, 'protocol': self.proto, - 'tunnel_src': (self.tun_src if self.tun_src else []), - 'tunnel_dst': (self.tun_dst if self.tun_dst else []), - 'tunnel_flags': self.tun_flags, - 'dscp': self.dscp, + 'tunnel': self.tunnel_encode(), 'flags': self.flags, 'salt': self.salt } @@ -256,13 +266,13 @@ class VppIpsecSA(VppObject): entry['udp_src_port'] = self.udp_src if self.udp_dst: entry['udp_dst_port'] = self.udp_dst - r = self.test.vapi.ipsec_sad_entry_add_del_v2(is_add=1, entry=entry) + r = self.test.vapi.ipsec_sad_entry_add_del_v3(is_add=1, entry=entry) self.stat_index = r.stat_index self.test.registry.register(self, self.test.logger) return self def remove_vpp_config(self): - r = self.test.vapi.ipsec_sad_entry_add_del_v2( + r = self.test.vapi.ipsec_sad_entry_add_del_v3( is_add=0, entry={ 'sad_id': self.id, @@ -278,9 +288,7 @@ class VppIpsecSA(VppObject): 'length': len(self.crypto_key), }, 'protocol': self.proto, - 'tunnel_src': (self.tun_src if self.tun_src else []), - 'tunnel_dst': (self.tun_dst if self.tun_dst else []), - 'flags': self.flags, + 'tunnel': self.tunnel_encode(), 'salt': self.salt }) @@ -290,7 +298,7 @@ class VppIpsecSA(VppObject): def query_vpp_config(self): e = VppEnum.vl_api_ipsec_sad_flags_t - bs = self.test.vapi.ipsec_sa_v2_dump() + bs = self.test.vapi.ipsec_sa_v3_dump() for b in bs: if b.entry.sad_id == self.id: # if udp encap is configured then the ports should match -- cgit 1.2.3-korg