diff options
Diffstat (limited to 'resources/libraries/python/IPsecUtil.py')
-rw-r--r-- | resources/libraries/python/IPsecUtil.py | 157 |
1 files changed, 155 insertions, 2 deletions
diff --git a/resources/libraries/python/IPsecUtil.py b/resources/libraries/python/IPsecUtil.py index 8f464d5a05..9c3e5c712e 100644 --- a/resources/libraries/python/IPsecUtil.py +++ b/resources/libraries/python/IPsecUtil.py @@ -26,6 +26,7 @@ from resources.libraries.python.IPUtil import IPUtil from resources.libraries.python.InterfaceUtil import InterfaceUtil, \ InterfaceStatusFlags 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.VatExecutor import VatExecutor @@ -1149,6 +1150,158 @@ class IPsecUtil: papi_exec.get_replies(err_msg) @staticmethod + def _create_ipsec_script_files(dut, instances): + """Create script files for configuring IPsec in containers + + :param dut: DUT node on which to create the script files + :param instances: number of containers on DUT node + :type dut: string + :type instances: int + """ + scripts = [] + for cnf in range(0, instances): + script_filename = ( + f"/tmp/ipsec_create_tunnel_cnf_{dut}_{cnf + 1}.config" + ) + scripts.append(open(script_filename, 'w')) + return scripts + + @staticmethod + def _close_and_copy_ipsec_script_files( + dut, nodes, instances, scripts): + """Close created scripts and copy them to containers + + :param dut: DUT node on which to create the script files + :param nodes: VPP nodes + :param instances: number of containers on DUT node + :param scripts: dictionary holding the script files + :type dut: string + :type nodes: dict + :type instances: int + :type scripts: dict + """ + for cnf in range(0, instances): + scripts[cnf].close() + script_filename = ( + f"/tmp/ipsec_create_tunnel_cnf_{dut}_{cnf + 1}.config" + ) + scp_node(nodes[dut], script_filename, script_filename) + + + @staticmethod + def vpp_ipsec_create_tunnel_interfaces_in_containers( + nodes, if1_ip_addr, if2_ip_addr, if1_key, if2_key, n_tunnels, + crypto_alg, integ_alg, raddr_ip1, raddr_ip2, raddr_range, + n_instances): + """Create multiple IPsec tunnel interfaces between two VPP nodes. + + :param nodes: VPP nodes to create tunnel interfaces. + :param if1_ip_addr: VPP node 1 interface IP4 address. + :param if2_ip_addr: VPP node 2 interface IP4 address. + :param if1_key: VPP node 1 interface key from topology file. + :param if2_key: VPP node 2 interface key from topology file. + :param n_tunnels: Number of tunnell interfaces to create. + :param crypto_alg: The encryption algorithm name. + :param integ_alg: The integrity algorithm name. + :param raddr_ip1: Policy selector remote IPv4 start address for the + first tunnel in direction node1->node2. + :param raddr_ip2: Policy selector remote IPv4 start address for the + first tunnel in direction node2->node1. + :param raddr_range: Mask specifying range of Policy selector Remote + IPv4 addresses. Valid values are from 1 to 32. + :param n_instances: Number of containers. + :type nodes: dict + :type if1_ip_addr: str + :type if2_ip_addr: str + :type if1_key: str + :type if2_key: str + :type n_tunnels: int + :type crypto_alg: CryptoAlg + :type integ_alg: IntegAlg + :type raddr_ip1: string + :type raddr_ip2: string + :type raddr_range: int + :type n_instances: int + """ + spi_1 = 100000 + spi_2 = 200000 + addr_incr = 1 << (32 - raddr_range) + + dut1_scripts = IPsecUtil._create_ipsec_script_files( + u"DUT1", n_instances) + dut2_scripts = IPsecUtil._create_ipsec_script_files( + u"DUT2", n_instances) + + for cnf in range(0, n_instances): + dut1_scripts[cnf].write( + u"create loopback interface\n" + u"set interface state loop0 up\n\n" + ) + dut2_scripts[cnf].write( + f"ip route add {if1_ip_addr}/8 via " + f"{ip_address(if2_ip_addr) + cnf + 100} memif1/{cnf + 1}\n\n" + ) + + for tnl in range(0, n_tunnels): + tnl_incr = tnl * addr_incr + cnf = tnl % n_instances + i = tnl // n_instances + ckey = gen_key(IPsecUtil.get_crypto_alg_key_len(crypto_alg)).hex() + integ = u"" + if integ_alg: + ikey = gen_key(IPsecUtil.get_integ_alg_key_len(integ_alg)).hex() + integ = ( + f"integ-alg {integ_alg.alg_name} " + f"local-integ-key {ikey} " + f"remote-integ-key {ikey} " + ) + + # Configure tunnel end point(s) on left side + dut1_scripts[cnf].write( + u"set interface ip address loop0 " + f"{ip_address(if1_ip_addr) + tnl_incr}/32\n" + f"create ipsec tunnel " + f"local-ip {ip_address(if1_ip_addr) + tnl_incr} " + f"local-spi {spi_1 + tnl} " + f"remote-ip {ip_address(if2_ip_addr) + cnf} " + f"remote-spi {spi_2 + tnl} " + f"crypto-alg {crypto_alg.alg_name} " + f"local-crypto-key {ckey} " + f"remote-crypto-key {ckey} " + f"instance {i} " + f"salt 0x0 " + f"{integ} \n" + f"set interface unnumbered ipip{i} use loop0\n" + f"set interface state ipip{i} up\n" + f"ip route add {ip_address(raddr_ip2)+tnl}/32 via ipip{i}\n\n" + ) + + # Configure tunnel end point(s) on right side + dut2_scripts[cnf].write( + f"set ip arp memif1/{cnf + 1} " + f"{ip_address(if1_ip_addr) + tnl_incr} " + f"02:02:00:00:{17:02X}:{cnf:02X} static\n" + f"create ipsec tunnel local-ip {ip_address(if2_ip_addr) + cnf} " + f"local-spi {spi_2 + tnl} " + f"remote-ip {ip_address(if1_ip_addr) + tnl_incr} " + f"remote-spi {spi_1 + tnl} " + f"crypto-alg {crypto_alg.alg_name} " + f"local-crypto-key {ckey} " + f"remote-crypto-key {ckey} " + f"instance {i} " + f"salt 0x0 " + f"{integ}\n" + f"set interface unnumbered ipip{i} use memif1/{cnf + 1}\n" + f"set interface state ipip{i} up\n" + f"ip route add {ip_address(raddr_ip1) + tnl}/32 via ipip{i}\n\n" + ) + + IPsecUtil._close_and_copy_ipsec_script_files( + u"DUT1", nodes, n_instances, dut1_scripts) + IPsecUtil._close_and_copy_ipsec_script_files( + u"DUT2", nodes, n_instances, dut2_scripts) + + @staticmethod def vpp_ipsec_add_multiple_tunnels( nodes, interface1, interface2, n_tunnels, crypto_alg, integ_alg, tunnel_ip1, tunnel_ip2, raddr_ip1, raddr_ip2, raddr_range): @@ -1166,8 +1319,8 @@ class IPsecUtil: first tunnel in direction node1->node2. :param raddr_ip2: Policy selector remote IPv4 start address for the first tunnel in direction node2->node1. - :param raddr_range: Mask specifying range of Policy selector Remote IPv4 - addresses. Valid values are from 1 to 32. + :param raddr_range: Mask specifying range of Policy selector Remote + IPv4 addresses. Valid values are from 1 to 32. :type nodes: dict :type interface1: str or int :type interface2: str or int |