X-Git-Url: https://gerrit.fd.io/r/gitweb?p=csit.git;a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2FContainerUtils.py;fp=resources%2Flibraries%2Fpython%2FContainerUtils.py;h=d10360f79e883aadb7947119bf3aa33bd72ff7a3;hp=74add983596bfd690704bf1a5443de8914720557;hb=3d5a75be5a88931690898e0fe52e4f48bc67c5ed;hpb=f99c79a4035787aff0db70498d022095caa44043 diff --git a/resources/libraries/python/ContainerUtils.py b/resources/libraries/python/ContainerUtils.py index 74add98359..d10360f79e 100644 --- a/resources/libraries/python/ContainerUtils.py +++ b/resources/libraries/python/ContainerUtils.py @@ -15,11 +15,14 @@ from collections import OrderedDict, Counter from io import open +from re import search from string import Template +from time import sleep from robot.libraries.BuiltIn import BuiltIn from resources.libraries.python.Constants import Constants +from resources.libraries.python.CpuUtils import CpuUtils from resources.libraries.python.ssh import SSH from resources.libraries.python.topology import Topology, SocketType from resources.libraries.python.VppConfigGenerator import VppConfigGenerator @@ -153,6 +156,12 @@ class ContainerManager: self.engine.container = self.containers[container] self.engine.restart_vpp() + def verify_vpp_in_all_containers(self): + """Verify that VPP is installed and running in all containers.""" + for container in self.containers: + self.engine.container = self.containers[container] + self.engine.verify_vpp() + def configure_vpp_in_all_containers(self, chain_topology, **kwargs): """Configure VPP in all containers. @@ -208,6 +217,17 @@ class ContainerManager: mid1=mid1, mid2=mid2, sid1=sid1, sid2=sid2, guest_dir=guest_dir, **kwargs ) + elif chain_topology == u"chain_vswitch": + self._configure_vpp_chain_vswitch( + mid1=mid1, mid2=mid2, sid1=sid1, sid2=sid2, + guest_dir=guest_dir, **kwargs) + elif chain_topology == u"chain_ipsec": + idx_match = search(r"\d+$", self.engine.container.name) + if idx_match: + idx = int(idx_match.group()) + self._configure_vpp_chain_ipsec( + mid1=mid1, mid2=mid2, sid1=sid1, sid2=sid2, + guest_dir=guest_dir, nf_instance=idx, **kwargs) else: raise RuntimeError( f"Container topology {chain_topology} not implemented" @@ -299,6 +319,134 @@ class ContainerManager: vif1_mac=vif1_mac, vif2_mac=vif2_mac ) + def _configure_vpp_chain_vswitch(self, **kwargs): + """Configure VPP as vswitch in container. + + :param kwargs: Named parameters. + :param kwargs: dict + """ + dut = self.engine.container.name.split(u"_")[0] + if dut == u"DUT1": + if1_pci = Topology.get_interface_pci_addr( + self.engine.container.node, kwargs[u"dut1_if2"]) + if2_pci = Topology.get_interface_pci_addr( + self.engine.container.node, kwargs[u"dut1_if1"]) + if_red_name = Topology.get_interface_name( + self.engine.container.node, kwargs[u"dut1_if2"]) + if_black_name = Topology.get_interface_name( + self.engine.container.node, kwargs[u"dut1_if1"]) + tg_if_ip4 = kwargs[u"tg_if2_ip4"] + tg_if_mac = kwargs[u"tg_if2_mac"] + else: + tg_if_ip4 = kwargs[u"tg_if1_ip4"] + tg_if_mac = kwargs[u"tg_if1_mac"] + if1_pci = Topology.get_interface_pci_addr( + self.engine.container.node, kwargs[u"dut2_if1"]) + if2_pci = Topology.get_interface_pci_addr( + self.engine.container.node, kwargs[u"dut2_if2"]) + if_red_name = Topology.get_interface_name( + self.engine.container.node, kwargs[u"dut2_if1"]) + if_black_name = Topology.get_interface_name( + self.engine.container.node, kwargs[u"dut2_if2"]) + + n_instances = int(kwargs[u"n_instances"]) + rxq = 1 + if u"rxq" in kwargs: + rxq = int(kwargs[u"rxq"]) + buffers = 215040 + if u"buffers" in kwargs: + buffers = int(kwargs[u"buffers"]) + nodes = kwargs[u"nodes"] + cpuset_cpus = CpuUtils.get_affinity_nf( + nodes, dut, nf_chains=1, nf_nodes=1, nf_chain=1, + nf_node=1, vs_dtc=0, nf_dtc=8, nf_mtcr=1, nf_dtcr=1 + ) + self.engine.create_vpp_startup_config_vswitch( + cpuset_cpus, rxq, buffers, if1_pci, if2_pci + ) + + instances = [] + for i in range(1, n_instances + 1): + instances.append( + f"create interface memif id {i} socket-id 1 master\n" + f"set interface state memif1/{i} up\n" + f"set interface l2 bridge memif1/{i} 1\n" + f"create interface memif id {i} socket-id 2 master\n" + f"set interface state memif2/{i} up\n" + f"set interface l2 bridge memif2/{i} 2\n" + f"set ip arp memif2/{i} {tg_if_ip4} {tg_if_mac} " + f"static\n\n" + ) + + self.engine.create_vpp_exec_config( + u"memif_create_chain_vswitch_ipsec.exec", + socket1=f"{kwargs[u'guest_dir']}/{dut}_memif-vswitch-1", + socket2=f"{kwargs[u'guest_dir']}/{dut}_memif-vswitch-2", + if_red_name=if_red_name, + if_black_name=if_black_name, + instances=u"\n\n".join(instances)) + + + def _configure_vpp_chain_ipsec(self, **kwargs): + """Configure VPP in container with memifs. + + :param kwargs: Named parameters. + :param kwargs: dict + """ + nf_nodes = int(kwargs[u"nf_nodes"]) + nf_instance = int(kwargs[u"nf_instance"]) + nodes = kwargs[u"nodes"] + dut = self.engine.container.name.split(u"_")[0] + cpuset_cpus = CpuUtils.get_affinity_nf( + nodes, dut, nf_chains=1, nf_nodes=nf_nodes, nf_chain=1, + nf_node=nf_instance, vs_dtc=10, nf_dtc=1, nf_mtcr=1, nf_dtcr=1) + self.engine.create_vpp_startup_config_ipsec(cpuset_cpus) + local_ip_base = kwargs[u"dut2_if1_ip4"].rsplit(u".", 1)[0] + + if dut == u"DUT1": + tnl_local_ip = f"{local_ip_base}.{nf_instance + 100}" + tnl_remote_ip = f"{local_ip_base}.{nf_instance}" + remote_ip_base = kwargs[u"dut1_if1_ip4"].rsplit(u".", 1)[0] + tg_if_ip4 = kwargs[u"tg_if1_ip4"] + tg_if_mac = kwargs[u"tg_if1_mac"] + raddr_ip4 = kwargs[u"laddr_ip4"] + l_mac1 = 17 + l_mac2 = 18 + r_mac = 1 + else: + tnl_local_ip = f"{local_ip_base}.{nf_instance}" + tnl_remote_ip = f"{local_ip_base}.{nf_instance + 100}" + remote_ip_base = kwargs[u"dut2_if2_ip4"].rsplit(u".", 1)[0] + tg_if_ip4 = kwargs[u"tg_if2_ip4"] + tg_if_mac = kwargs[u"tg_if2_mac"] + raddr_ip4 = kwargs[u"raddr_ip4"] + l_mac1 = 1 + l_mac2 = 2 + r_mac = 17 + + self.engine.create_vpp_exec_config( + u"memif_create_chain_ipsec.exec", + socket1=f"{kwargs['guest_dir']}/{dut}_memif-vswitch-1", + socket2=f"{kwargs['guest_dir']}/{dut}_memif-vswitch-2", + mid1=nf_instance, + mid2=nf_instance, + sid1=u"1", + sid2=u"2", + mac1=f"02:02:00:00:{l_mac1:02X}:{(nf_instance - 1):02X}", + mac2=f"02:02:00:00:{l_mac2:02X}:{(nf_instance - 1):02X}", + tg_if2_ip4=tg_if_ip4, + tg_if2_mac=tg_if_mac, + raddr_ip4=raddr_ip4, + tnl_local_ip=tnl_local_ip, + tnl_remote_ip=tnl_remote_ip, + tnl_remote_mac=f"02:02:00:00:{r_mac:02X}:{(nf_instance - 1):02X}", + remote_ip=f"{remote_ip_base}.{nf_instance}" + ) + self.engine.execute( + f"cat {kwargs['guest_dir']}/ipsec_create_tunnel_cnf_" + f"{dut}_{nf_instance}.config >> /tmp/running.exec" + ) + def _configure_vpp_pipeline_ip4(self, **kwargs): """Configure VPP in pipeline topology with ip4. @@ -448,15 +596,13 @@ class ContainerEngine: self.container.node, SocketType.PAPI, self.container.name, - f"{self.container.root}/tmp/vpp_sockets/{self.container.name}/" - f"api.sock" + f"/tmp/vpp_sockets/{self.container.name}/api.sock" ) topo_instance.add_new_socket( self.container.node, SocketType.STATS, self.container.name, - f"{self.container.root}/tmp/vpp_sockets/{self.container.name}/" - f"stats.sock" + f"/tmp/vpp_sockets/{self.container.name}/stats.sock" ) def restart_vpp(self): @@ -464,13 +610,37 @@ class ContainerEngine: self.execute(u"supervisorctl restart vpp") self.execute(u"cat /tmp/supervisord.log") - def create_base_vpp_startup_config(self): + # TODO Rewrite .execute to accept retries parameter and get rid of this + # function. + def verify_vpp(self, retries=120, retry_wait=1): + """Verify that VPP is installed and running inside container. + + :param retries: Check for VPP for this number of times Default: 120 + :param retry_wait: Wait for this number of seconds between retries. + + """ + cmd = (u"vppctl show pci 2>&1 | " + u"fgrep -v 'Connection refused' | " + u"fgrep -v 'No such file or directory'") + + for _ in range(retries + 1): + try: + self.execute(cmd) + break + except RuntimeError: + sleep(retry_wait) + else: + msg = f"VPP did not come up in container: {self.container.name}" + raise RuntimeError(msg) + + def create_base_vpp_startup_config(self, cpuset_cpus=None): """Create base startup configuration of VPP on container. :returns: Base VPP startup configuration. :rtype: VppConfigGenerator """ - cpuset_cpus = self.container.cpuset_cpus + if cpuset_cpus is None: + cpuset_cpus = self.container.cpuset_cpus # Create config instance vpp_config = VppConfigGenerator() @@ -519,8 +689,7 @@ class ContainerEngine: # Apply configuration self.execute(u"mkdir -p /etc/vpp/") self.execute( - f'echo "{vpp_config.get_config_str()}" | ' - f'tee /etc/vpp/startup.conf' + f'echo "{vpp_config.get_config_str()}" | tee /etc/vpp/startup.conf' ) def create_vpp_startup_config_func_dev(self): @@ -540,8 +709,58 @@ class ContainerEngine: # Apply configuration self.execute(u"mkdir -p /etc/vpp/") self.execute( - f'echo "{vpp_config.get_config_str()}" | ' - f'tee /etc/vpp/startup.conf' + f'echo "{vpp_config.get_config_str()}" | tee /etc/vpp/startup.conf' + ) + + def create_vpp_startup_config_vswitch(self, cpuset_cpus, rxq, buffers, + *devices): + """Create startup configuration of VPP vswitch. + + :param cpuset_cpus: CPU list to run on. + :param rxq: Number of interface RX queues. + :param buffers: Number of buffers per numa. + :param devices: List of PCI devices to add. + :type cpuset_cpus: list + :type rxq: int + :type buffers: int + :type devices: list + """ + vpp_config = self.create_base_vpp_startup_config(cpuset_cpus) + vpp_config.add_dpdk_dev(*devices) + vpp_config.add_dpdk_log_level(u"debug") + vpp_config.add_plugin(u"disable", u"default") + vpp_config.add_plugin(u"enable", u"dpdk_plugin.so") + vpp_config.add_plugin(u"enable", u"memif_plugin.so") + vpp_config.add_dpdk_no_tx_checksum_offload() + vpp_config.add_buffers_per_numa(buffers) + vpp_config.add_dpdk_dev_default_rxq(rxq) + + # Apply configuration + self.execute(u"mkdir -p /etc/vpp/") + self.execute( + f'echo "{vpp_config.get_config_str()}" | tee /etc/vpp/startup.conf' + ) + + def create_vpp_startup_config_ipsec(self, cpuset_cpus): + """Create startup configuration of VPP with IPsec on container. + + :param cpuset_cpus: CPU list to run on. + :type cpuset_cpus: list + """ + vpp_config = self.create_base_vpp_startup_config(cpuset_cpus) + vpp_config.add_plugin(u"disable", u"default") + vpp_config.add_plugin(u"enable", u"memif_plugin.so") + vpp_config.add_plugin(u"enable", u"crypto_ia32_plugin.so") + vpp_config.add_plugin(u"enable", u"crypto_ipsecmb_plugin.so") + vpp_config.add_plugin(u"enable", u"crypto_openssl_plugin.so") + vpp_config.add_heapsize(u"4G") + vpp_config.add_ip_heap_size(u"4G") + vpp_config.add_statseg_size(u"4G") + + # Apply configuration + self.execute(u"mkdir -p /etc/vpp/") + self.execute( + f'echo "{vpp_config.get_config_str()}" | tee /etc/vpp/startup.conf' ) def create_vpp_exec_config(self, template_file, **kwargs):