X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=test%2Ftemplate_ipsec.py;h=7bd0b9ec81f7fb6d1c8ba5f60436e4e6c7752dd7;hb=041add7d1;hp=034bc8ecf45ed631029ab3772d38a6b160ee7868;hpb=5d4b8912d2fe186b4fb920a72b3a2f7b556f4e7d;p=vpp.git diff --git a/test/template_ipsec.py b/test/template_ipsec.py index 034bc8ecf45..7bd0b9ec81f 100644 --- a/test/template_ipsec.py +++ b/test/template_ipsec.py @@ -5,8 +5,10 @@ import struct from scapy.layers.inet import IP, ICMP, TCP, UDP from scapy.layers.ipsec import SecurityAssociation, ESP from scapy.layers.l2 import Ether -from scapy.packet import Raw -from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest +from scapy.packet import raw, Raw +from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, IPv6ExtHdrHopByHop, \ + IPv6ExtHdrFragment, IPv6ExtHdrDestOpt + from framework import VppTestCase, VppTestRunner from util import ppp, reassemble4, fragment_rfc791, fragment_rfc8200 @@ -25,14 +27,14 @@ class IPsecIPv4Params(object): self.remote_tun_if_host = '1.1.1.1' self.remote_tun_if_host6 = '1111::1' - self.scapy_tun_sa_id = 10 + self.scapy_tun_sa_id = 100 self.scapy_tun_spi = 1001 - self.vpp_tun_sa_id = 20 + self.vpp_tun_sa_id = 200 self.vpp_tun_spi = 1000 - self.scapy_tra_sa_id = 30 + self.scapy_tra_sa_id = 300 self.scapy_tra_spi = 2001 - self.vpp_tra_sa_id = 40 + self.vpp_tra_sa_id = 400 self.vpp_tra_spi = 2000 self.auth_algo_vpp_id = (VppEnum.vl_api_ipsec_integ_alg_t. @@ -47,6 +49,9 @@ class IPsecIPv4Params(object): self.salt = 0 self.flags = 0 self.nat_header = None + self.tun_flags = (VppEnum.vl_api_tunnel_encap_decap_flags_t. + TUNNEL_API_ENCAP_DECAP_FLAG_NONE) + self.dscp = 0 class IPsecIPv6Params(object): @@ -61,14 +66,14 @@ class IPsecIPv6Params(object): self.remote_tun_if_host = '1111:1111:1111:1111:1111:1111:1111:1111' self.remote_tun_if_host4 = '1.1.1.1' - self.scapy_tun_sa_id = 50 + self.scapy_tun_sa_id = 500 self.scapy_tun_spi = 3001 - self.vpp_tun_sa_id = 60 + self.vpp_tun_sa_id = 600 self.vpp_tun_spi = 3000 - self.scapy_tra_sa_id = 70 + self.scapy_tra_sa_id = 700 self.scapy_tra_spi = 4001 - self.vpp_tra_sa_id = 80 + self.vpp_tra_sa_id = 800 self.vpp_tra_spi = 4000 self.auth_algo_vpp_id = (VppEnum.vl_api_ipsec_integ_alg_t. @@ -83,6 +88,9 @@ class IPsecIPv6Params(object): self.salt = 0 self.flags = 0 self.nat_header = None + self.tun_flags = (VppEnum.vl_api_tunnel_encap_decap_flags_t. + TUNNEL_API_ENCAP_DECAP_FLAG_NONE) + self.dscp = 0 def mk_scapy_crypt_key(p): @@ -96,6 +104,8 @@ def config_tun_params(p, encryption_type, tun_if): ip_class_by_addr_type = {socket.AF_INET: IP, socket.AF_INET6: IPv6} esn_en = bool(p.flags & (VppEnum.vl_api_ipsec_sad_flags_t. IPSEC_API_SAD_FLAG_USE_ESN)) + p.tun_dst = tun_if.remote_addr[p.addr_type] + p.tun_src = tun_if.local_addr[p.addr_type] crypt_key = mk_scapy_crypt_key(p) p.scapy_tun_sa = SecurityAssociation( encryption_type, spi=p.vpp_tun_spi, @@ -103,8 +113,8 @@ def config_tun_params(p, encryption_type, tun_if): crypt_key=crypt_key, auth_algo=p.auth_algo, auth_key=p.auth_key, tunnel_header=ip_class_by_addr_type[p.addr_type]( - src=tun_if.remote_addr[p.addr_type], - dst=tun_if.local_addr[p.addr_type]), + src=p.tun_dst, + dst=p.tun_src), nat_t_header=p.nat_header, esn_en=esn_en) p.vpp_tun_sa = SecurityAssociation( @@ -113,8 +123,8 @@ def config_tun_params(p, encryption_type, tun_if): crypt_key=crypt_key, auth_algo=p.auth_algo, auth_key=p.auth_key, tunnel_header=ip_class_by_addr_type[p.addr_type]( - dst=tun_if.remote_addr[p.addr_type], - src=tun_if.local_addr[p.addr_type]), + dst=p.tun_dst, + src=p.tun_src), nat_t_header=p.nat_header, esn_en=esn_en) @@ -177,8 +187,10 @@ class TemplateIpsec(VppTestCase): super(TemplateIpsec, cls).tearDownClass() def setup_params(self): - self.ipv4_params = IPsecIPv4Params() - self.ipv6_params = IPsecIPv6Params() + if not hasattr(self, 'ipv4_params'): + self.ipv4_params = IPsecIPv4Params() + if not hasattr(self, 'ipv6_params'): + self.ipv6_params = IPsecIPv6Params() self.params = {self.ipv4_params.addr_type: self.ipv4_params, self.ipv6_params.addr_type: self.ipv6_params} @@ -220,14 +232,14 @@ class TemplateIpsec(VppTestCase): def show_commands_at_teardown(self): self.logger.info(self.vapi.cli("show hardware")) - def gen_encrypt_pkts(self, sa, sw_intf, src, dst, count=1, + def gen_encrypt_pkts(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(IP(src=src, dst=dst) / ICMP() / Raw(b'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, 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) / @@ -552,16 +564,17 @@ class IpsecTra4(object): p.scapy_tra_sa.seq_num = 351 p.vpp_tra_sa.seq_num = 351 - def verify_tra_basic4(self, count=1): + def verify_tra_basic4(self, count=1, payload_size=54): """ ipsec v4 transport basic test """ self.vapi.cli("clear errors") self.vapi.cli("clear ipsec sa") try: p = self.params[socket.AF_INET] - send_pkts = self.gen_encrypt_pkts(p.scapy_tra_sa, self.tra_if, + send_pkts = self.gen_encrypt_pkts(p, p.scapy_tra_sa, self.tra_if, src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4, - count=count) + count=count, + payload_size=payload_size) recv_pkts = self.send_and_expect(self.tra_if, send_pkts, self.tra_if) for rx in recv_pkts: @@ -593,7 +606,7 @@ class IpsecTra4(object): class IpsecTra4Tests(IpsecTra4): """ UT test methods for Transport v4 """ def test_tra_anti_replay(self): - """ ipsec v4 transport anti-reply test """ + """ ipsec v4 transport anti-replay test """ self.verify_tra_anti_replay() def test_tra_basic(self, count=1): @@ -607,14 +620,16 @@ class IpsecTra4Tests(IpsecTra4): class IpsecTra6(object): """ verify methods for Transport v6 """ - def verify_tra_basic6(self, count=1): + def verify_tra_basic6(self, count=1, payload_size=54): self.vapi.cli("clear errors") + self.vapi.cli("clear ipsec sa") try: p = self.params[socket.AF_INET6] - send_pkts = self.gen_encrypt_pkts6(p.scapy_tra_sa, self.tra_if, + send_pkts = self.gen_encrypt_pkts6(p, p.scapy_tra_sa, self.tra_if, src=self.tra_if.remote_ip6, dst=self.tra_if.local_ip6, - count=count) + count=count, + payload_size=payload_size) recv_pkts = self.send_and_expect(self.tra_if, send_pkts, self.tra_if) for rx in recv_pkts: @@ -641,6 +656,108 @@ class IpsecTra6(object): self.assert_packet_counter_equal(self.tra6_encrypt_node_name, count) self.assert_packet_counter_equal(self.tra6_decrypt_node_name, count) + def gen_encrypt_pkts_ext_hdrs6(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='X' * payload_size)) + for i in range(count)] + + def gen_pkts_ext_hdrs6(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) / + IPv6ExtHdrHopByHop() / + IPv6ExtHdrFragment(id=2, offset=200) / + Raw(b'\xff' * 200) + for i in range(count)] + + def verify_tra_encrypted6(self, p, sa, rxs): + decrypted = [] + for rx in rxs: + self.assert_packet_checksums_valid(rx) + try: + decrypt_pkt = p.vpp_tra_sa.decrypt(rx[IPv6]) + decrypted.append(decrypt_pkt) + self.assert_equal(decrypt_pkt.src, self.tra_if.local_ip6) + self.assert_equal(decrypt_pkt.dst, self.tra_if.remote_ip6) + except: + self.logger.debug(ppp("Unexpected packet:", rx)) + try: + self.logger.debug(ppp("Decrypted packet:", decrypt_pkt)) + except: + pass + raise + return decrypted + + def verify_tra_66_ext_hdrs(self, p): + count = 63 + + # + # check we can decrypt with options + # + tx = self.gen_encrypt_pkts_ext_hdrs6(p.scapy_tra_sa, self.tra_if, + src=self.tra_if.remote_ip6, + dst=self.tra_if.local_ip6, + count=count) + self.send_and_expect(self.tra_if, tx, self.tra_if) + + # + # injecting a packet from ourselves to be routed of box is a hack + # but it matches an outbout policy, alors je ne regrette rien + # + + # one extension before ESP + tx = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / + IPv6(src=self.tra_if.local_ip6, + dst=self.tra_if.remote_ip6) / + IPv6ExtHdrFragment(id=2, offset=200) / + Raw(b'\xff' * 200)) + + rxs = self.send_and_expect(self.pg2, [tx], self.tra_if) + dcs = self.verify_tra_encrypted6(p, p.vpp_tra_sa, rxs) + + for dc in dcs: + # for reasons i'm not going to investigate scapy does not + # created the correct headers after decrypt. but reparsing + # the ipv6 packet fixes it + dc = IPv6(raw(dc[IPv6])) + self.assert_equal(dc[IPv6ExtHdrFragment].id, 2) + + # two extensions before ESP + tx = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / + IPv6(src=self.tra_if.local_ip6, + dst=self.tra_if.remote_ip6) / + IPv6ExtHdrHopByHop() / + IPv6ExtHdrFragment(id=2, offset=200) / + Raw(b'\xff' * 200)) + + rxs = self.send_and_expect(self.pg2, [tx], self.tra_if) + dcs = self.verify_tra_encrypted6(p, p.vpp_tra_sa, rxs) + + for dc in dcs: + dc = IPv6(raw(dc[IPv6])) + self.assertTrue(dc[IPv6ExtHdrHopByHop]) + self.assert_equal(dc[IPv6ExtHdrFragment].id, 2) + + # two extensions before ESP, one after + tx = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / + IPv6(src=self.tra_if.local_ip6, + dst=self.tra_if.remote_ip6) / + IPv6ExtHdrHopByHop() / + IPv6ExtHdrFragment(id=2, offset=200) / + IPv6ExtHdrDestOpt() / + Raw(b'\xff' * 200)) + + rxs = self.send_and_expect(self.pg2, [tx], self.tra_if) + dcs = self.verify_tra_encrypted6(p, p.vpp_tra_sa, rxs) + + for dc in dcs: + dc = IPv6(raw(dc[IPv6])) + self.assertTrue(dc[IPv6ExtHdrDestOpt]) + self.assertTrue(dc[IPv6ExtHdrHopByHop]) + self.assert_equal(dc[IPv6ExtHdrFragment].id, 2) + class IpsecTra6Tests(IpsecTra6): """ UT test methods for Transport v6 """ @@ -653,6 +770,12 @@ class IpsecTra6Tests(IpsecTra6): self.verify_tra_basic6(count=257) +class IpsecTra6ExtTests(IpsecTra6): + def test_tra_ext_hdrs_66(self): + """ ipsec 6o6 tra extension headers test """ + self.verify_tra_66_ext_hdrs(self.params[socket.AF_INET6]) + + class IpsecTra46Tests(IpsecTra4Tests, IpsecTra6Tests): """ UT test methods for Transport v6 and v4""" pass @@ -660,21 +783,21 @@ class IpsecTra46Tests(IpsecTra4Tests, IpsecTra6Tests): class IpsecTun4(object): """ verify methods for Tunnel v4 """ - def verify_counters4(self, p, count, n_frags=None): + def verify_counters4(self, p, count, n_frags=None, worker=None): if not n_frags: n_frags = count if (hasattr(p, "spd_policy_in_any")): - pkts = p.spd_policy_in_any.get_stats()['packets'] + pkts = p.spd_policy_in_any.get_stats(worker)['packets'] self.assertEqual(pkts, count, "incorrect SPD any policy: expected %d != %d" % (count, pkts)) if (hasattr(p, "tun_sa_in")): - pkts = p.tun_sa_in.get_stats()['packets'] + pkts = p.tun_sa_in.get_stats(worker)['packets'] self.assertEqual(pkts, count, "incorrect SA in counts: expected %d != %d" % (count, pkts)) - pkts = p.tun_sa_out.get_stats()['packets'] + pkts = p.tun_sa_out.get_stats(worker)['packets'] self.assertEqual(pkts, count, "incorrect SA out counts: expected %d != %d" % (count, pkts)) @@ -688,6 +811,15 @@ class IpsecTun4(object): self.assert_equal(rx[IP].dst, self.pg1.remote_ip4) self.assert_packet_checksums_valid(rx) + def verify_esp_padding(self, sa, esp_payload, decrypt_pkt): + align = sa.crypt_algo.block_size + if align < 4: + align = 4 + exp_len = (len(decrypt_pkt) + 2 + (align - 1)) & ~(align - 1) + exp_len += sa.crypt_algo.iv_size + exp_len += sa.crypt_algo.icv_size or sa.auth_algo.icv_size + self.assertEqual(exp_len, len(esp_payload)) + def verify_encrypted(self, p, sa, rxs): decrypt_pkts = [] for rx in rxs: @@ -696,9 +828,12 @@ class IpsecTun4(object): self.assert_packet_checksums_valid(rx) self.assertEqual(len(rx) - len(Ether()), rx[IP].len) try: - decrypt_pkt = p.vpp_tun_sa.decrypt(rx[IP]) + rx_ip = rx[IP] + decrypt_pkt = p.vpp_tun_sa.decrypt(rx_ip) if not decrypt_pkt.haslayer(IP): decrypt_pkt = IP(decrypt_pkt[Raw].load) + if rx_ip.proto == socket.IPPROTO_ESP: + self.verify_esp_padding(sa, rx_ip[ESP].data, decrypt_pkt) 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) @@ -715,13 +850,16 @@ class IpsecTun4(object): def verify_tun_44(self, p, count=1, payload_size=64, n_rx=None): self.vapi.cli("clear errors") + self.vapi.cli("clear ipsec counters") + self.vapi.cli("clear ipsec sa") if not n_rx: n_rx = count try: - send_pkts = self.gen_encrypt_pkts(p.scapy_tun_sa, self.tun_if, + send_pkts = self.gen_encrypt_pkts(p, p.scapy_tun_sa, self.tun_if, src=p.remote_tun_if_host, dst=self.pg1.remote_ip4, - count=count) + count=count, + payload_size=payload_size) recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1) self.verify_decrypted(p, recv_pkts) @@ -732,19 +870,45 @@ class IpsecTun4(object): self.tun_if, n_rx) self.verify_encrypted(p, p.vpp_tun_sa, recv_pkts) + for rx in recv_pkts: + self.assertEqual(rx[IP].src, p.tun_src) + self.assertEqual(rx[IP].dst, p.tun_dst) + finally: self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec all")) + self.logger.info(self.vapi.ppcli("show ipsec sa 0")) + self.logger.info(self.vapi.ppcli("show ipsec sa 4")) self.verify_counters4(p, count, n_rx) + def verify_tun_dropped_44(self, p, count=1, payload_size=64, n_rx=None): + self.vapi.cli("clear errors") + if not n_rx: + n_rx = count + try: + send_pkts = self.gen_encrypt_pkts(p, p.scapy_tun_sa, self.tun_if, + src=p.remote_tun_if_host, + dst=self.pg1.remote_ip4, + count=count) + self.send_and_assert_no_replies(self.tun_if, send_pkts) + + send_pkts = self.gen_pkts(self.pg1, src=self.pg1.remote_ip4, + dst=p.remote_tun_if_host, count=count, + payload_size=payload_size) + self.send_and_assert_no_replies(self.pg1, send_pkts) + + finally: + self.logger.info(self.vapi.ppcli("show error")) + self.logger.info(self.vapi.ppcli("show ipsec all")) + def verify_tun_reass_44(self, p): self.vapi.cli("clear errors") self.vapi.ip_reassembly_enable_disable( sw_if_index=self.tun_if.sw_if_index, enable_ip4=True) try: - send_pkts = self.gen_encrypt_pkts(p.scapy_tun_sa, self.tun_if, + send_pkts = self.gen_encrypt_pkts(p, p.scapy_tun_sa, self.tun_if, src=p.remote_tun_if_host, dst=self.pg1.remote_ip4, payload_size=1900, @@ -770,8 +934,9 @@ class IpsecTun4(object): def verify_tun_64(self, p, count=1): self.vapi.cli("clear errors") + self.vapi.cli("clear ipsec sa") try: - send_pkts = self.gen_encrypt_pkts6(p.scapy_tun_sa, self.tun_if, + send_pkts = self.gen_encrypt_pkts6(p, p.scapy_tun_sa, self.tun_if, src=p.remote_tun_if_host6, dst=self.pg1.remote_ip6, count=count) @@ -828,6 +993,10 @@ class IpsecTun4Tests(IpsecTun4): def test_tun_basic44(self): """ ipsec 4o4 tunnel basic test """ self.verify_tun_44(self.params[socket.AF_INET], count=1) + self.tun_if.admin_down() + self.tun_if.resolve_arp() + self.tun_if.admin_up() + self.verify_tun_44(self.params[socket.AF_INET], count=1) def test_tun_reass_basic44(self): """ ipsec 4o4 tunnel basic reassembly test """ @@ -835,19 +1004,19 @@ class IpsecTun4Tests(IpsecTun4): def test_tun_burst44(self): """ ipsec 4o4 tunnel burst test """ - self.verify_tun_44(self.params[socket.AF_INET], count=257) + self.verify_tun_44(self.params[socket.AF_INET], count=127) class IpsecTun6(object): """ verify methods for Tunnel v6 """ - def verify_counters6(self, p_in, p_out, count): + def verify_counters6(self, p_in, p_out, count, worker=None): if (hasattr(p_in, "tun_sa_in")): - pkts = p_in.tun_sa_in.get_stats()['packets'] + pkts = p_in.tun_sa_in.get_stats(worker)['packets'] self.assertEqual(pkts, count, "incorrect SA in counts: expected %d != %d" % (count, pkts)) if (hasattr(p_out, "tun_sa_out")): - pkts = p_out.tun_sa_out.get_stats()['packets'] + pkts = p_out.tun_sa_out.get_stats(worker)['packets'] self.assertEqual(pkts, count, "incorrect SA out counts: expected %d != %d" % (count, pkts)) @@ -884,7 +1053,8 @@ class IpsecTun6(object): self.vapi.cli("clear errors") self.vapi.cli("clear ipsec sa") - send_pkts = self.gen_encrypt_pkts6(p_in.scapy_tun_sa, self.tun_if, + send_pkts = self.gen_encrypt_pkts6(p_in, p_in.scapy_tun_sa, + self.tun_if, src=p_in.remote_tun_if_host, dst=self.pg1.remote_ip6, count=count) @@ -897,10 +1067,12 @@ class IpsecTun6(object): if not p_out: p_out = p_in try: - send_pkts = self.gen_encrypt_pkts6(p_in.scapy_tun_sa, self.tun_if, + send_pkts = self.gen_encrypt_pkts6(p_in, p_in.scapy_tun_sa, + self.tun_if, src=p_in.remote_tun_if_host, dst=self.pg1.remote_ip6, - count=count) + count=count, + payload_size=payload_size) recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1) self.verify_decrypted6(p_in, recv_pkts) @@ -908,10 +1080,13 @@ class IpsecTun6(object): dst=p_out.remote_tun_if_host, count=count, payload_size=payload_size) - recv_pkts = self.send_and_expect(self.pg1, send_pkts, - self.tun_if) + recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if) self.verify_encrypted6(p_out, p_out.vpp_tun_sa, recv_pkts) + for rx in recv_pkts: + self.assertEqual(rx[IPv6].src, p_out.tun_src) + self.assertEqual(rx[IPv6].dst, p_out.tun_dst) + finally: self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec all")) @@ -923,11 +1098,11 @@ class IpsecTun6(object): sw_if_index=self.tun_if.sw_if_index, enable_ip6=True) try: - send_pkts = self.gen_encrypt_pkts6(p.scapy_tun_sa, self.tun_if, + send_pkts = self.gen_encrypt_pkts6(p, p.scapy_tun_sa, self.tun_if, src=p.remote_tun_if_host, dst=self.pg1.remote_ip6, count=1, - payload_size=1900) + payload_size=1850) send_pkts = fragment_rfc8200(send_pkts[0], 1, 1400, self.logger) recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1, n_rx=1) @@ -950,8 +1125,9 @@ class IpsecTun6(object): def verify_tun_46(self, p, count=1): """ ipsec 4o6 tunnel basic test """ self.vapi.cli("clear errors") + self.vapi.cli("clear ipsec sa") try: - send_pkts = self.gen_encrypt_pkts(p.scapy_tun_sa, self.tun_if, + send_pkts = self.gen_encrypt_pkts(p, p.scapy_tun_sa, self.tun_if, src=p.remote_tun_if_host4, dst=self.pg1.remote_ip4, count=count) @@ -1002,6 +1178,68 @@ class IpsecTun6Tests(IpsecTun6): self.verify_tun_66(self.params[socket.AF_INET6], count=257) +class IpsecTun6HandoffTests(IpsecTun6): + """ UT test methods for Tunnel v6 with multiple workers """ + worker_config = "workers 2" + + def test_tun_handoff_66(self): + """ ipsec 6o6 tunnel worker hand-off test """ + N_PKTS = 15 + p = self.params[socket.AF_INET6] + + # inject alternately on worker 0 and 1. all counts on the SA + # should be against worker 0 + for worker in [0, 1, 0, 1]: + send_pkts = self.gen_encrypt_pkts6(p, p.scapy_tun_sa, self.tun_if, + src=p.remote_tun_if_host, + dst=self.pg1.remote_ip6, + count=N_PKTS) + recv_pkts = self.send_and_expect(self.tun_if, send_pkts, + self.pg1, worker=worker) + self.verify_decrypted6(p, recv_pkts) + + send_pkts = self.gen_pkts6(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, + self.tun_if, worker=worker) + self.verify_encrypted6(p, p.vpp_tun_sa, recv_pkts) + + # all counts against the first worker that was used + self.verify_counters6(p, p, 4*N_PKTS, worker=0) + + +class IpsecTun4HandoffTests(IpsecTun4): + """ UT test methods for Tunnel v4 with multiple workers """ + worker_config = "workers 2" + + def test_tun_handooff_44(self): + """ ipsec 4o4 tunnel worker hand-off test """ + N_PKTS = 15 + p = self.params[socket.AF_INET] + + # inject alternately on worker 0 and 1. all counts on the SA + # should be against worker 0 + for worker in [0, 1, 0, 1]: + send_pkts = self.gen_encrypt_pkts(p, p.scapy_tun_sa, self.tun_if, + src=p.remote_tun_if_host, + dst=self.pg1.remote_ip4, + count=N_PKTS) + recv_pkts = self.send_and_expect(self.tun_if, send_pkts, + self.pg1, worker=worker) + self.verify_decrypted(p, recv_pkts) + + send_pkts = self.gen_pkts(self.pg1, src=self.pg1.remote_ip4, + dst=p.remote_tun_if_host, + count=N_PKTS) + recv_pkts = self.send_and_expect(self.pg1, send_pkts, + self.tun_if, worker=worker) + self.verify_encrypted(p, p.vpp_tun_sa, recv_pkts) + + # all counts against the first worker that was used + self.verify_counters4(p, 4*N_PKTS, worker=0) + + class IpsecTun46Tests(IpsecTun4Tests, IpsecTun6Tests): """ UT test methods for Tunnel v6 & v4 """ pass