X-Git-Url: https://gerrit.fd.io/r/gitweb?p=csit.git;a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2FIPsecUtil.py;h=520cf7b932aa04b28283504411dd7a42b70f857b;hp=99a470d934e9ca07b396c71cc388ea3e411b88e1;hb=a275fa0062158d712152f542b7bc9ec40b5c5f31;hpb=6dc62d10b1e6a6b5eee09f6d42e750de273a464b diff --git a/resources/libraries/python/IPsecUtil.py b/resources/libraries/python/IPsecUtil.py index 99a470d934..520cf7b932 100644 --- a/resources/libraries/python/IPsecUtil.py +++ b/resources/libraries/python/IPsecUtil.py @@ -29,8 +29,9 @@ from resources.libraries.python.IPAddress import IPAddress from resources.libraries.python.IPUtil import IPUtil, IpDscp, MPLS_LABEL_INVALID from resources.libraries.python.PapiExecutor import PapiSocketExecutor from resources.libraries.python.ssh import scp_node -from resources.libraries.python.topology import Topology +from resources.libraries.python.topology import Topology, NodeType from resources.libraries.python.VatExecutor import VatExecutor +from resources.libraries.python.VPPUtil import VPPUtil IPSEC_UDP_PORT_NONE = 0xffff @@ -94,18 +95,18 @@ class IPsecProto(IntEnum): class IPsecSadFlags(IntEnum): """IPsec Security Association Database flags.""" - IPSEC_API_SAD_FLAG_NONE = 0, + IPSEC_API_SAD_FLAG_NONE = 0 # Enable extended sequence numbers - IPSEC_API_SAD_FLAG_USE_ESN = 0x01, + IPSEC_API_SAD_FLAG_USE_ESN = 0x01 # Enable Anti - replay - IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY = 0x02, + IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY = 0x02 # IPsec tunnel mode if non-zero, else transport mode - IPSEC_API_SAD_FLAG_IS_TUNNEL = 0x04, + IPSEC_API_SAD_FLAG_IS_TUNNEL = 0x04 # IPsec tunnel mode is IPv6 if non-zero, else IPv4 tunnel # only valid if is_tunnel is non-zero - IPSEC_API_SAD_FLAG_IS_TUNNEL_V6 = 0x08, + IPSEC_API_SAD_FLAG_IS_TUNNEL_V6 = 0x08 # Enable UDP encapsulation for NAT traversal - IPSEC_API_SAD_FLAG_UDP_ENCAP = 0x10, + IPSEC_API_SAD_FLAG_UDP_ENCAP = 0x10 # IPsec SA is or inbound traffic IPSEC_API_SAD_FLAG_IS_INBOUND = 0x40 @@ -243,12 +244,14 @@ class IPsecUtil: def get_integ_alg_key_len(integ_alg): """Return integrity algorithm key length. + None argument is accepted, returning zero. + :param integ_alg: Integrity algorithm. - :type integ_alg: IntegAlg + :type integ_alg: Optional[IntegAlg] :returns: Key length. :rtype: int """ - return integ_alg.key_len + return 0 if integ_alg is None else integ_alg.key_len @staticmethod def get_integ_alg_scapy_name(integ_alg): @@ -320,6 +323,60 @@ class IPsecUtil: with PapiSocketExecutor(node) as papi_exec: papi_exec.add(cmd, **args).get_reply(err_msg) + @staticmethod + def vpp_ipsec_crypto_sw_scheduler_set_worker( + node, workers, crypto_enable=False): + """Enable or disable crypto on specific vpp worker threads. + + :param node: VPP node to enable or disable crypto for worker threads. + :param workers: List of VPP thread numbers. + :param crypto_enable: Disable or enable crypto work. + :type node: dict + :type workers: Iterable[int] + :type crypto_enable: bool + :raises RuntimeError: If failed to enable or disable crypto for worker + thread or if no API reply received. + """ + for worker in workers: + cmd = u"crypto_sw_scheduler_set_worker" + err_msg = f"Failed to disable/enable crypto for worker thread " \ + f"on host {node[u'host']}" + args = dict( + worker_index=worker - 1, + crypto_enable=crypto_enable + ) + with PapiSocketExecutor(node) as papi_exec: + papi_exec.add(cmd, **args).get_reply(err_msg) + + @staticmethod + def vpp_ipsec_crypto_sw_scheduler_set_worker_on_all_duts( + nodes, workers, crypto_enable=False): + """Enable or disable crypto on specific vpp worker threads. + + :param node: VPP node to enable or disable crypto for worker threads. + :param workers: List of VPP thread numbers. + :param crypto_enable: Disable or enable crypto work. + :type node: dict + :type workers: Iterable[int] + :type crypto_enable: bool + :raises RuntimeError: If failed to enable or disable crypto for worker + thread or if no API reply received. + """ + for node in nodes.values(): + if node[u"type"] == NodeType.DUT: + thread_data = VPPUtil.vpp_show_threads(node) + worker_cnt = len(thread_data) - 1 + if not worker_cnt: + return None + worker_ids = list() + for item in thread_data: + if str(item.cpu_id) in workers.split(u","): + worker_ids.append(item.id) + + IPsecUtil.vpp_ipsec_crypto_sw_scheduler_set_worker( + node, workers=worker_ids, crypto_enable=crypto_enable + ) + @staticmethod def vpp_ipsec_add_sad_entry( node, sad_id, spi, crypto_alg, crypto_key, integ_alg=None, @@ -342,7 +399,7 @@ class IPsecUtil: :type spi: int :type crypto_alg: CryptoAlg :type crypto_key: str - :type integ_alg: IntegAlg + :type integ_alg: Optional[IntegAlg] :type integ_key: str :type tunnel_src: str :type tunnel_dst: str @@ -426,7 +483,7 @@ class IPsecUtil: :type spi: int :type crypto_alg: CryptoAlg :type crypto_key: str - :type integ_alg: IntegAlg + :type integ_alg: Optional[IntegAlg] :type integ_key: str :type tunnel_src: str :type tunnel_dst: str @@ -453,8 +510,8 @@ class IPsecUtil: integ = f"integ-alg {integ_alg.alg_name} " \ f"integ-key {integ_key.hex()}" \ if integ_alg else u"" - tunnel = f"tunnel-src {src_addr + i * addr_incr} " \ - f"tunnel-dst {dst_addr + i * addr_incr}" \ + tunnel = f"tunnel src {src_addr + i * addr_incr} " \ + f"tunnel dst {dst_addr + i * addr_incr}" \ if tunnel_src and tunnel_dst else u"" conf = f"exec ipsec sa add {sad_id + i} esp spi {spi + i} "\ f"crypto-alg {crypto_alg.alg_name} " \ @@ -527,7 +584,7 @@ class IPsecUtil: @staticmethod def vpp_ipsec_set_ip_route( node, n_tunnels, tunnel_src, traffic_addr, tunnel_dst, interface, - raddr_range): + raddr_range, dst_mac=None): """Set IP address and route on interface. :param node: VPP node to add config on. @@ -539,6 +596,7 @@ class IPsecUtil: :param raddr_range: Mask specifying range of Policy selector Remote IP addresses. Valid values are from 1 to 32 in case of IPv4 and to 128 in case of IPv6. + :param dst_mac: The MAC address of destination tunnels. :type node: dict :type n_tunnels: int :type tunnel_src: str @@ -546,6 +604,7 @@ class IPsecUtil: :type tunnel_dst: str :type interface: str :type raddr_range: int + :type dst_mac: str """ tunnel_src = ip_address(tunnel_src) tunnel_dst = ip_address(tunnel_dst) @@ -564,7 +623,11 @@ class IPsecUtil: f"exec ip route add {traffic_addr + i}/" \ f"{128 if traffic_addr.version == 6 else 32} " \ f"via {tunnel_dst + i * addr_incr} {if_name}\n" + if dst_mac: + conf = f"{conf}exec set ip neighbor {if_name} " \ + f"{tunnel_dst + i * addr_incr} {dst_mac}\n" tmp_file.write(conf) + VatExecutor().execute_script( tmp_filename, node, timeout=300, json_out=False, copy_on_execute=True @@ -585,8 +648,21 @@ class IPsecUtil: is_multipath=0, route=None ) - err_msg = f"Failed to configure IP addresses and IP routes " \ - f"on interface {interface} on host {node[u'host']}" + cmd3 = u"ip_neighbor_add_del" + args3 = dict( + is_add=True, + neighbor=dict( + sw_if_index=Topology.get_interface_sw_index(node, interface), + flags=0, + mac_address=str(dst_mac), + ip_address=None + ) + ) + err_msg = f"Failed to configure IP addresses, IP routes and " \ + f"IP neighbor on interface {interface} on host {node[u'host']}" \ + if dst_mac \ + else f"Failed to configure IP addresses and IP routes " \ + f"on interface {interface} on host {node[u'host']}" with PapiSocketExecutor(node) as papi_exec: for i in range(n_tunnels): @@ -601,6 +677,11 @@ class IPsecUtil: history = bool(not 1 < i < n_tunnels - 2) papi_exec.add(cmd1, history=history, **args1).\ add(cmd2, history=history, **args2) + if dst_mac: + args3[u"neighbor"][u"ip_address"] = ip_address( + tunnel_dst + i * addr_incr + ) + papi_exec.add(cmd3, history=history, **args3) papi_exec.get_replies(err_msg) @staticmethod @@ -825,6 +906,8 @@ class IPsecUtil: raddr_ip2, addr_incr, spi_d, existing_tunnels=0): """Create multiple IPsec tunnel interfaces on DUT1 node using VAT. + Generate random keys and return them (so DUT2 or TG can decrypt). + :param nodes: VPP nodes to create tunnel interfaces. :param tun_ips: Dictionary with VPP node 1 ipsec tunnel interface IPv4/IPv6 address (ip1) and VPP node 2 ipsec tunnel interface @@ -847,11 +930,13 @@ class IPsecUtil: :type if2_key: str :type n_tunnels: int :type crypto_alg: CryptoAlg - :type integ_alg: IntegAlg + :type integ_alg: Optional[IntegAlg] :type raddr_ip2: IPv4Address or IPv6Address :type addr_incr: int :type spi_d: dict :type existing_tunnels: int + :returns: Generated ckeys and ikeys. + :rtype: List[bytes], List[bytes] """ tmp_fn1 = u"/tmp/ipsec_create_tunnel_dut1.config" if1_n = Topology.get_interface_name(nodes[u"DUT1"], if1_key) @@ -878,10 +963,10 @@ class IPsecUtil: ckeys.append( gen_key(IPsecUtil.get_crypto_alg_key_len(crypto_alg)) ) + ikeys.append( + gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg)) + ) if integ_alg: - ikeys.append( - gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg)) - ) integ = f"integ-alg {integ_alg.alg_name} " \ f"integ-key {ikeys[i].hex()} " else: @@ -941,6 +1026,9 @@ class IPsecUtil: ikeys, raddr_ip1, addr_incr, spi_d, existing_tunnels=0): """Create multiple IPsec tunnel interfaces on DUT2 node using VAT. + This method accesses keys generated by DUT1 method + and does not return anything. + :param nodes: VPP nodes to create tunnel interfaces. :param tun_ips: Dictionary with VPP node 1 ipsec tunnel interface IPv4/IPv6 address (ip1) and VPP node 2 ipsec tunnel interface @@ -961,9 +1049,9 @@ class IPsecUtil: :type if2_key: str :type n_tunnels: int :type crypto_alg: CryptoAlg - :type ckeys: list - :type integ_alg: IntegAlg - :type ikeys: list + :type ckeys: Sequence[bytes] + :type integ_alg: Optional[IntegAlg] + :type ikeys: Sequence[bytes] :type addr_incr: int :type spi_d: dict :type existing_tunnels: int @@ -1116,6 +1204,8 @@ class IPsecUtil: raddr_ip2, addr_incr, spi_d, existing_tunnels=0): """Create multiple IPsec tunnel interfaces on DUT1 node using PAPI. + Generate random keys and return them (so DUT2 or TG can decrypt). + :param nodes: VPP nodes to create tunnel interfaces. :param tun_ips: Dictionary with VPP node 1 ipsec tunnel interface IPv4/IPv6 address (ip1) and VPP node 2 ipsec tunnel interface @@ -1138,11 +1228,13 @@ class IPsecUtil: :type if2_key: str :type n_tunnels: int :type crypto_alg: CryptoAlg - :type integ_alg: IntegAlg + :type integ_alg: Optional[IntegAlg] :type raddr_ip2: IPv4Address or IPv6Address :type addr_incr: int :type spi_d: dict :type existing_tunnels: int + :returns: Generated ckeys and ikeys. + :rtype: List[bytes], List[bytes] """ if not existing_tunnels: loop_sw_if_idx = IPsecUtil._ipsec_create_loopback_dut1_papi( @@ -1245,10 +1337,9 @@ class IPsecUtil: ckeys.append( gen_key(IPsecUtil.get_crypto_alg_key_len(crypto_alg)) ) - if integ_alg: - ikeys.append( - gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg)) - ) + ikeys.append( + gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg)) + ) # SAD entry for outband / tx path args[u"entry"][u"sad_id"] = i args[u"entry"][u"spi"] = spi_d[u"spi_1"] + i @@ -1364,6 +1455,9 @@ class IPsecUtil: ikeys, raddr_ip1, addr_incr, spi_d, existing_tunnels=0): """Create multiple IPsec tunnel interfaces on DUT2 node using PAPI. + This method accesses keys generated by DUT1 method + and does not return anything. + :param nodes: VPP nodes to create tunnel interfaces. :param tun_ips: Dictionary with VPP node 1 ipsec tunnel interface IPv4/IPv6 address (ip1) and VPP node 2 ipsec tunnel interface @@ -1384,9 +1478,9 @@ class IPsecUtil: :type if2_key: str :type n_tunnels: int :type crypto_alg: CryptoAlg - :type ckeys: list - :type integ_alg: IntegAlg - :type ikeys: list + :type ckeys: Sequence[bytes] + :type integ_alg: Optional[IntegAlg] + :type ikeys: Sequence[bytes] :type addr_incr: int :type spi_d: dict :type existing_tunnels: int @@ -1485,10 +1579,9 @@ class IPsecUtil: ckeys.append( gen_key(IPsecUtil.get_crypto_alg_key_len(crypto_alg)) ) - if integ_alg: - ikeys.append( - gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg)) - ) + ikeys.append( + gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg)) + ) # SAD entry for outband / tx path args[u"entry"][u"sad_id"] = 100000 + i args[u"entry"][u"spi"] = spi_d[u"spi_2"] + i @@ -1615,9 +1708,13 @@ class IPsecUtil: def vpp_ipsec_create_tunnel_interfaces( nodes, tun_if1_ip_addr, tun_if2_ip_addr, if1_key, if2_key, n_tunnels, crypto_alg, integ_alg, raddr_ip1, raddr_ip2, raddr_range, - existing_tunnels=0): + existing_tunnels=0, return_keys=False): """Create multiple IPsec tunnel interfaces between two VPP nodes. + Some deployments (e.g. devicetest) need to know the generated keys. + But other deployments (e.g. scale perf test) would get spammed + if we returned keys every time. + :param nodes: VPP nodes to create tunnel interfaces. :param tun_if1_ip_addr: VPP node 1 ipsec tunnel interface IPv4/IPv6 address. @@ -1638,6 +1735,7 @@ class IPsecUtil: and to 128 in case of IPv6. :param existing_tunnels: Number of tunnel interfaces before creation. Useful mainly for reconf tests. Default 0. + :param return_keys: Whether generated keys should be returned. :type nodes: dict :type tun_if1_ip_addr: str :type tun_if2_ip_addr: str @@ -1645,11 +1743,14 @@ class IPsecUtil: :type if2_key: str :type n_tunnels: int :type crypto_alg: CryptoAlg - :type integ_alg: IntegAlg + :type integ_alg: Optonal[IntegAlg] :type raddr_ip1: string :type raddr_ip2: string :type raddr_range: int :type existing_tunnels: int + :type return_keys: bool + :returns: Ckeys, ikeys, spi_1, spi_2. + :rtype: Optional[List[bytes], List[bytes], int, int] """ n_tunnels = int(n_tunnels) existing_tunnels = int(existing_tunnels) @@ -1671,25 +1772,27 @@ class IPsecUtil: nodes, tun_ips, if1_key, if2_key, n_tunnels, crypto_alg, integ_alg, raddr_ip2, addr_incr, spi_d, existing_tunnels ) - if u"DUT2" not in nodes.keys(): - return ckeys[0], ikeys[0], spi_d[u"spi_1"], spi_d[u"spi_2"] - IPsecUtil._ipsec_create_tunnel_interfaces_dut2_vat( - nodes, tun_ips, if2_key, n_tunnels, crypto_alg, ckeys, - integ_alg, ikeys, raddr_ip1, addr_incr, spi_d, existing_tunnels - ) + if u"DUT2" in nodes.keys(): + IPsecUtil._ipsec_create_tunnel_interfaces_dut2_vat( + nodes, tun_ips, if2_key, n_tunnels, crypto_alg, ckeys, + integ_alg, ikeys, raddr_ip1, addr_incr, spi_d, + existing_tunnels + ) else: ckeys, ikeys = IPsecUtil._ipsec_create_tunnel_interfaces_dut1_papi( nodes, tun_ips, if1_key, if2_key, n_tunnels, crypto_alg, integ_alg, raddr_ip2, addr_incr, spi_d, existing_tunnels ) - if u"DUT2" not in nodes.keys(): - return ckeys[0], ikeys[0], spi_d[u"spi_1"], spi_d[u"spi_2"] - IPsecUtil._ipsec_create_tunnel_interfaces_dut2_papi( - nodes, tun_ips, if2_key, n_tunnels, crypto_alg, ckeys, - integ_alg, ikeys, raddr_ip1, addr_incr, spi_d, existing_tunnels - ) + if u"DUT2" in nodes.keys(): + IPsecUtil._ipsec_create_tunnel_interfaces_dut2_papi( + nodes, tun_ips, if2_key, n_tunnels, crypto_alg, ckeys, + integ_alg, ikeys, raddr_ip1, addr_incr, spi_d, + existing_tunnels + ) - return None, None, None, None + if return_keys: + return ckeys, ikeys, spi_d[u"spi_1"], spi_d[u"spi_2"] + return None @staticmethod def _create_ipsec_script_files(dut, instances): @@ -1754,7 +1857,7 @@ class IPsecUtil: :type if2_ip_addr: str :type n_tunnels: int :type crypto_alg: CryptoAlg - :type integ_alg: IntegAlg + :type integ_alg: Optional[IntegAlg] :type raddr_ip1: string :type raddr_ip2: string :type raddr_range: int @@ -1787,10 +1890,10 @@ class IPsecUtil: gen_key(IPsecUtil.get_crypto_alg_key_len(crypto_alg)), u"hex" ) integ = u"" + ikey = getattr( + gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg)), u"hex" + ) if integ_alg: - ikey = getattr( - gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg)), u"hex" - ) integ = ( f"integ-alg {integ_alg.alg_name} " f"local-integ-key {ikey} " @@ -1868,7 +1971,7 @@ class IPsecUtil: :type interface2: str or int :type n_tunnels: int :type crypto_alg: CryptoAlg - :type integ_alg: IntegAlg + :type integ_alg: Optional[IntegAlg] :type tunnel_ip1: str :type tunnel_ip2: str :type raddr_ip1: string @@ -1890,12 +1993,12 @@ class IPsecUtil: IPsecUtil.get_integ_alg_key_len(integ_alg) ).decode() if integ_alg else u"" + rmac = Topology.get_interface_mac(nodes[u"DUT2"], interface2) \ + if u"DUT2" in nodes.keys() \ + else Topology.get_interface_mac(nodes[u"TG"], interface2) IPsecUtil.vpp_ipsec_set_ip_route( nodes[u"DUT1"], n_tunnels, tunnel_ip1, raddr_ip2, tunnel_ip2, - interface1, raddr_range) - IPsecUtil.vpp_ipsec_set_ip_route( - nodes[u"DUT2"], n_tunnels, tunnel_ip2, raddr_ip1, tunnel_ip1, - interface2, raddr_range) + interface1, raddr_range, rmac) IPsecUtil.vpp_ipsec_add_spd(nodes[u"DUT1"], spd_id) IPsecUtil.vpp_ipsec_spd_add_if(nodes[u"DUT1"], spd_id, interface1) @@ -1908,17 +2011,6 @@ class IPsecUtil: proto=50, laddr_range=u"100.0.0.0/8", raddr_range=u"100.0.0.0/8" ) - IPsecUtil.vpp_ipsec_add_spd(nodes[u"DUT2"], spd_id) - IPsecUtil.vpp_ipsec_spd_add_if(nodes[u"DUT2"], spd_id, interface2) - IPsecUtil.vpp_ipsec_policy_add( - nodes[u"DUT2"], spd_id, p_hi, PolicyAction.BYPASS, inbound=False, - proto=50, laddr_range=u"100.0.0.0/8", raddr_range=u"100.0.0.0/8" - ) - IPsecUtil.vpp_ipsec_policy_add( - nodes[u"DUT2"], spd_id, p_hi, PolicyAction.BYPASS, inbound=True, - proto=50, laddr_range=u"100.0.0.0/8", raddr_range=u"100.0.0.0/8" - ) - IPsecUtil.vpp_ipsec_add_sad_entries( nodes[u"DUT1"], n_tunnels, sa_id_1, spi_1, crypto_alg, crypto_key, integ_alg, integ_key, tunnel_ip1, tunnel_ip2 @@ -1928,30 +2020,49 @@ class IPsecUtil: ) IPsecUtil.vpp_ipsec_add_sad_entries( - nodes[u"DUT2"], n_tunnels, sa_id_1, spi_1, crypto_alg, crypto_key, - integ_alg, integ_key, tunnel_ip1, tunnel_ip2 + nodes[u"DUT1"], n_tunnels, sa_id_2, spi_2, crypto_alg, crypto_key, + integ_alg, integ_key, tunnel_ip2, tunnel_ip1 ) IPsecUtil.vpp_ipsec_spd_add_entries( - nodes[u"DUT2"], n_tunnels, spd_id, p_lo, True, sa_id_1, raddr_ip2 + nodes[u"DUT1"], n_tunnels, spd_id, p_lo, True, sa_id_2, raddr_ip1 ) - IPsecUtil.vpp_ipsec_add_sad_entries( - nodes[u"DUT2"], n_tunnels, sa_id_2, spi_2, crypto_alg, crypto_key, - integ_alg, integ_key, tunnel_ip2, tunnel_ip1 - ) + if u"DUT2" in nodes.keys(): + IPsecUtil.vpp_ipsec_set_ip_route( + nodes[u"DUT2"], n_tunnels, tunnel_ip2, raddr_ip1, tunnel_ip1, + interface2, raddr_range) + + IPsecUtil.vpp_ipsec_add_spd(nodes[u"DUT2"], spd_id) + IPsecUtil.vpp_ipsec_spd_add_if(nodes[u"DUT2"], spd_id, interface2) + IPsecUtil.vpp_ipsec_policy_add( + nodes[u"DUT2"], spd_id, p_hi, PolicyAction.BYPASS, + inbound=False, proto=50, laddr_range=u"100.0.0.0/8", + raddr_range=u"100.0.0.0/8" + ) + IPsecUtil.vpp_ipsec_policy_add( + nodes[u"DUT2"], spd_id, p_hi, PolicyAction.BYPASS, + inbound=True, proto=50, laddr_range=u"100.0.0.0/8", + raddr_range=u"100.0.0.0/8" + ) - IPsecUtil.vpp_ipsec_spd_add_entries( - nodes[u"DUT2"], n_tunnels, spd_id, p_lo, False, sa_id_2, raddr_ip1 - ) + IPsecUtil.vpp_ipsec_add_sad_entries( + nodes[u"DUT2"], n_tunnels, sa_id_1, spi_1, crypto_alg, + crypto_key, integ_alg, integ_key, tunnel_ip1, tunnel_ip2 + ) + IPsecUtil.vpp_ipsec_spd_add_entries( + nodes[u"DUT2"], n_tunnels, spd_id, p_lo, True, sa_id_1, + raddr_ip2 + ) - IPsecUtil.vpp_ipsec_add_sad_entries( - nodes[u"DUT1"], n_tunnels, sa_id_2, spi_2, crypto_alg, crypto_key, - integ_alg, integ_key, tunnel_ip2, tunnel_ip1 - ) + IPsecUtil.vpp_ipsec_add_sad_entries( + nodes[u"DUT2"], n_tunnels, sa_id_2, spi_2, crypto_alg, + crypto_key, integ_alg, integ_key, tunnel_ip2, tunnel_ip1 + ) + IPsecUtil.vpp_ipsec_spd_add_entries( + nodes[u"DUT2"], n_tunnels, spd_id, p_lo, False, sa_id_2, + raddr_ip1 + ) - IPsecUtil.vpp_ipsec_spd_add_entries( - nodes[u"DUT1"], n_tunnels, spd_id, p_lo, True, sa_id_2, raddr_ip1 - ) @staticmethod def vpp_ipsec_show(node):