diff options
Diffstat (limited to 'yardstick/benchmark/contexts/standalone')
-rw-r--r-- | yardstick/benchmark/contexts/standalone/model.py | 124 | ||||
-rw-r--r-- | yardstick/benchmark/contexts/standalone/ovs_dpdk.py | 31 | ||||
-rw-r--r-- | yardstick/benchmark/contexts/standalone/sriov.py | 21 |
3 files changed, 119 insertions, 57 deletions
diff --git a/yardstick/benchmark/contexts/standalone/model.py b/yardstick/benchmark/contexts/standalone/model.py index ffd8858d9..30170832a 100644 --- a/yardstick/benchmark/contexts/standalone/model.py +++ b/yardstick/benchmark/contexts/standalone/model.py @@ -35,7 +35,7 @@ LOG = logging.getLogger(__name__) VM_TEMPLATE = """ <domain type="kvm"> - <name>{vm_name}</name> + <name>{vm_name}</name> <uuid>{random_uuid}</uuid> <memory unit="MB">{memory}</memory> <currentMemory unit="MB">{memory}</currentMemory> @@ -43,6 +43,7 @@ VM_TEMPLATE = """ <hugepages /> </memoryBacking> <vcpu cpuset='{cpuset}'>{vcpu}</vcpu> + {cputune} <os> <type arch="x86_64" machine="pc-i440fx-utopic">hvm</type> <boot dev="hd" /> @@ -79,7 +80,13 @@ VM_TEMPLATE = """ <source bridge="br-int" /> <model type='virtio'/> </interface> - </devices> + <serial type='pty'> + <target port='0'/> + </serial> + <console type='pty'> + <target type='serial' port='0'/> + </console> + </devices> </domain> """ WAIT_FOR_BOOT = 30 @@ -94,33 +101,63 @@ class Libvirt(object): cmd_template = "virsh list --name | grep -i %s" status = connection.execute(cmd_template % vm_name)[0] if status == 0: - LOG.info("VM '%s' is already present.. destroying" % vm_name) + LOG.info("VM '%s' is already present... destroying", vm_name) connection.execute("virsh destroy %s" % vm_name) @staticmethod def virsh_create_vm(connection, cfg): err = connection.execute("virsh create %s" % cfg)[0] - LOG.info("VM create status: %s" % (err)) + LOG.info("VM create status: %s", err) @staticmethod def virsh_destroy_vm(vm_name, connection): connection.execute("virsh destroy %s" % vm_name) @staticmethod - def add_interface_address(interface, pci_address): + def _add_interface_address(interface, pci_address): + """Add a PCI 'address' XML node + + <address type='pci' domain='0x0000' bus='0x00' slot='0x08' + function='0x0'/> + + Refence: https://software.intel.com/en-us/articles/ + configure-sr-iov-network-virtual-functions-in-linux-kvm + """ vm_pci = ET.SubElement(interface, 'address') vm_pci.set('type', 'pci') - vm_pci.set('domain', '0x%s' % pci_address.domain) - vm_pci.set('bus', '0x%s' % pci_address.bus) - vm_pci.set('slot', '0x%s' % pci_address.slot) - vm_pci.set('function', '0x%s' % pci_address.function) + vm_pci.set('domain', '0x{}'.format(pci_address.domain)) + vm_pci.set('bus', '0x{}'.format(pci_address.bus)) + vm_pci.set('slot', '0x{}'.format(pci_address.slot)) + vm_pci.set('function', '0x{}'.format(pci_address.function)) return vm_pci @classmethod def add_ovs_interface(cls, vpath, port_num, vpci, vports_mac, xml): - vhost_path = '{0}/var/run/openvswitch/dpdkvhostuser{1}' + """Add a DPDK OVS 'interface' XML node in 'devices' node + + <devices> + <interface type='vhostuser'> + <mac address='00:00:00:00:00:01'/> + <source type='unix' path='/usr/local/var/run/openvswitch/ + dpdkvhostuser0' mode='client'/> + <model type='virtio'/> + <driver queues='4'> + <host mrg_rxbuf='off'/> + </driver> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' + function='0x0'/> + </interface> + ... + </devices> + + Reference: http://docs.openvswitch.org/en/latest/topics/dpdk/ + vhost-user/ + """ + + vhost_path = ('{0}/var/run/openvswitch/dpdkvhostuser{1}'. + format(vpath, port_num)) root = ET.parse(xml) - pci_address = PciAddress.parse_address(vpci.strip(), multi_line=True) + pci_address = PciAddress(vpci.strip()) device = root.find('devices') interface = ET.SubElement(device, 'interface') @@ -130,7 +167,7 @@ class Libvirt(object): source = ET.SubElement(interface, 'source') source.set('type', 'unix') - source.set('path', vhost_path.format(vpath, port_num)) + source.set('path', vhost_path) source.set('mode', 'client') model = ET.SubElement(interface, 'model') @@ -142,14 +179,35 @@ class Libvirt(object): host = ET.SubElement(driver, 'host') host.set('mrg_rxbuf', 'off') - cls.add_interface_address(interface, pci_address) + cls._add_interface_address(interface, pci_address) root.write(xml) @classmethod - def add_sriov_interfaces(cls, vm_pci, vf_pci, vfmac, xml): + def add_sriov_interfaces(cls, vm_pci, vf_pci, vf_mac, xml): + """Add a SR-IOV 'interface' XML node in 'devices' node + + <devices> + <interface type='hostdev' managed='yes'> + <source> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' + function='0x0'/> + </source> + <mac address='52:54:00:6d:90:02'> + <address type='pci' domain='0x0000' bus='0x02' slot='0x04' + function='0x1'/> + </interface> + ... + </devices> + + Reference: https://access.redhat.com/documentation/en-us/ + red_hat_enterprise_linux/6/html/ + virtualization_host_configuration_and_guest_installation_guide/ + sect-virtualization_host_configuration_and_guest_installation_guide + -sr_iov-how_sr_iov_libvirt_works + """ + root = ET.parse(xml) - pci_address = PciAddress.parse_address(vf_pci.strip(), multi_line=True) device = root.find('devices') interface = ET.SubElement(device, 'interface') @@ -157,18 +215,14 @@ class Libvirt(object): interface.set('type', 'hostdev') mac = ET.SubElement(interface, 'mac') - mac.set('address', vfmac) - source = ET.SubElement(interface, 'source') + mac.set('address', vf_mac) - addr = ET.SubElement(source, "address") - addr.set('domain', "0x0") - addr.set('bus', "{0}".format(pci_address.bus)) - addr.set('function', "{0}".format(pci_address.function)) - addr.set('slot', "0x{0}".format(pci_address.slot)) - addr.set('type', "pci") + source = ET.SubElement(interface, 'source') + pci_address = PciAddress(vf_pci.strip()) + cls._add_interface_address(source, pci_address) - pci_vm_address = PciAddress.parse_address(vm_pci.strip(), multi_line=True) - cls.add_interface_address(interface, pci_vm_address) + pci_vm_address = PciAddress(vm_pci.strip()) + cls._add_interface_address(interface, pci_vm_address) root.write(xml) @@ -192,8 +246,9 @@ class Libvirt(object): vcpu = int(cpu) * int(threads) numa_cpus = '0-%s' % (vcpu - 1) hw_socket = flavor.get('hw_socket', '0') - cpuset = Libvirt.pin_vcpu_for_perf(connection, vm_name, vcpu, hw_socket) + cpuset = Libvirt.pin_vcpu_for_perf(connection, hw_socket) + cputune = extra_spec.get('cputune', '') mac = StandaloneContextHelper.get_mac_address(0x00) image = cls.create_snapshot_qemu(connection, index, flavor.get("images", None)) @@ -204,7 +259,7 @@ class Libvirt(object): memory=memory, vcpu=vcpu, cpu=cpu, numa_cpus=numa_cpus, socket=socket, threads=threads, - vm_image=image, cpuset=cpuset) + vm_image=image, cpuset=cpuset, cputune=cputune) write_file(cfg, vm_xml) @@ -216,13 +271,14 @@ class Libvirt(object): connection.execute("echo never > /sys/kernel/mm/transparent_hugepage/enabled") @classmethod - def pin_vcpu_for_perf(cls, connection, vm_name, cpu, socket="0"): + def pin_vcpu_for_perf(cls, connection, socket='0'): threads = "" sys_obj = CpuSysCores(connection) soc_cpu = sys_obj.get_core_socket() sys_cpu = int(soc_cpu["cores_per_socket"]) + socket = str(socket) cores = "%s-%s" % (soc_cpu[socket][0], soc_cpu[socket][sys_cpu - 1]) - if int(soc_cpu["thread_per_core"]): + if int(soc_cpu["thread_per_core"]) > 1: threads = "%s-%s" % (soc_cpu[socket][sys_cpu], soc_cpu[socket][-1]) cpuset = "%s,%s" % (cores, threads) return cpuset @@ -236,7 +292,8 @@ class StandaloneContextHelper(object): super(StandaloneContextHelper, self).__init__() @staticmethod - def install_req_libs(connection, extra_pkgs=[]): + def install_req_libs(connection, extra_pkgs=None): + extra_pkgs = extra_pkgs or [] pkgs = ["qemu-kvm", "libvirt-bin", "bridge-utils", "numactl", "fping"] pkgs.extend(extra_pkgs) cmd_template = "dpkg-query -W --showformat='${Status}\\n' \"%s\"|grep 'ok installed'" @@ -244,9 +301,6 @@ class StandaloneContextHelper(object): if connection.execute(cmd_template % pkg)[0]: connection.execute("apt-get update") connection.execute("apt-get -y install %s" % pkg) - else: - # all installed - return @staticmethod def get_kernel_module(connection, pci, driver): @@ -283,7 +337,7 @@ class StandaloneContextHelper(object): 'interface': str(interface), 'driver': driver }) - LOG.info("{0}".format(networks)) + LOG.info(networks) return networks @@ -352,7 +406,7 @@ class StandaloneContextHelper(object): while not mgmtip and times: connection.execute("fping -c 1 -g %s > /dev/null 2>&1" % cidr) out = connection.execute("ip neighbor | grep '%s'" % mac)[1] - LOG.info("fping -c 1 -g %s > /dev/null 2>&1" % cidr) + LOG.info("fping -c 1 -g %s > /dev/null 2>&1", cidr) if out.strip(): mgmtip = str(out.split(" ")[0]).strip() client = ssh.SSH.from_node(node, overrides={"ip": mgmtip}) diff --git a/yardstick/benchmark/contexts/standalone/ovs_dpdk.py b/yardstick/benchmark/contexts/standalone/ovs_dpdk.py index fcb7bb66c..3755b84e9 100644 --- a/yardstick/benchmark/contexts/standalone/ovs_dpdk.py +++ b/yardstick/benchmark/contexts/standalone/ovs_dpdk.py @@ -118,7 +118,7 @@ class OvsDpdkContext(Context): self.connection.execute(cmd) bind_cmd = "{dpdk_nic_bind} --force -b {driver} {port}" phy_driver = "vfio-pci" - for key, port in self.networks.items(): + for _, port in self.networks.items(): vpci = port.get("phy_port") self.connection.execute(bind_cmd.format(dpdk_nic_bind=self.dpdk_nic_bind, driver=phy_driver, port=vpci)) @@ -129,13 +129,21 @@ class OvsDpdkContext(Context): ovs_sock_path = '/var/run/openvswitch/db.sock' log_path = '/var/log/openvswitch/ovs-vswitchd.log' + pmd_cpu_mask = self.ovs_properties.get("pmd_cpu_mask", '') pmd_mask = hex(sum(2 ** num for num in range(pmd_nums)) << 1) + if pmd_cpu_mask: + pmd_mask = pmd_cpu_mask + socket0 = self.ovs_properties.get("ram", {}).get("socket_0", "2048") socket1 = self.ovs_properties.get("ram", {}).get("socket_1", "2048") ovs_other_config = "ovs-vsctl {0}set Open_vSwitch . other_config:{1}" detach_cmd = "ovs-vswitchd unix:{0}{1} --pidfile --detach --log-file={2}" + lcore_mask = self.ovs_properties.get("lcore_mask", '') + if lcore_mask: + lcore_mask = ovs_other_config.format("--no-wait ", "dpdk-lcore-mask='%s'" % lcore_mask) + cmd_list = [ "mkdir -p /usr/local/var/run/openvswitch", "mkdir -p {}".format(os.path.dirname(log_path)), @@ -143,6 +151,7 @@ class OvsDpdkContext(Context): ovs_sock_path), ovs_other_config.format("--no-wait ", "dpdk-init=true"), ovs_other_config.format("--no-wait ", "dpdk-socket-mem='%s,%s'" % (socket0, socket1)), + lcore_mask, detach_cmd.format(vpath, ovs_sock_path, log_path), ovs_other_config.format("", "pmd-cpu-mask=%s" % pmd_mask), ] @@ -170,7 +179,7 @@ class OvsDpdkContext(Context): ] ordered_network = OrderedDict(self.networks) - for index, (key, vnf) in enumerate(ordered_network.items()): + for index, vnf in enumerate(ordered_network.values()): if ovs_ver >= [2, 7, 0]: dpdk_args = " options:dpdk-devargs=%s" % vnf.get("phy_port") dpdk_list.append(ovs_add_port.format(br='br0', port='dpdk%s' % vnf.get("port_num", 0), @@ -263,7 +272,7 @@ class OvsDpdkContext(Context): # Bind nics back to kernel bind_cmd = "{dpdk_nic_bind} --force -b {driver} {port}" - for key, port in self.networks.items(): + for port in self.networks.values(): vpci = port.get("phy_port") phy_driver = port.get("driver") self.connection.execute(bind_cmd.format(dpdk_nic_bind=self.dpdk_nic_bind, @@ -296,8 +305,7 @@ class OvsDpdkContext(Context): except StopIteration: pass else: - raise ValueError("Duplicate nodes!!! Nodes: %s %s", - (node, duplicate)) + raise ValueError("Duplicate nodes!!! Nodes: %s %s" % (node, duplicate)) node["name"] = attr_name return node @@ -328,17 +336,17 @@ class OvsDpdkContext(Context): def configure_nics_for_ovs_dpdk(self): portlist = OrderedDict(self.networks) - for key, ports in portlist.items(): + for key in portlist: mac = StandaloneContextHelper.get_mac_address() portlist[key].update({'mac': mac}) self.networks = portlist - LOG.info("Ports %s" % self.networks) + LOG.info("Ports %s", self.networks) def _enable_interfaces(self, index, vfs, cfg): vpath = self.ovs_properties.get("vpath", "/usr/local") vf = self.networks[vfs[0]] port_num = vf.get('port_num', 0) - vpci = PciAddress.parse_address(vf['vpci'].strip(), multi_line=True) + vpci = PciAddress(vf['vpci'].strip()) # Generate the vpci for the interfaces slot = index + port_num + 10 vf['vpci'] = \ @@ -357,9 +365,10 @@ class OvsDpdkContext(Context): # 1. Check and delete VM if already exists Libvirt.check_if_vm_exists_and_delete(vm_name, self.connection) - vcpu, mac = Libvirt.build_vm_xml(self.connection, self.vm_flavor, cfg, vm_name, index) + _, mac = Libvirt.build_vm_xml(self.connection, self.vm_flavor, + cfg, vm_name, index) # 2: Cleanup already available VMs - for idx, (vkey, vfs) in enumerate(OrderedDict(vnf["network_ports"]).items()): + for vkey, vfs in OrderedDict(vnf["network_ports"]).items(): if vkey == "mgmt": continue self._enable_interfaces(index, vfs, cfg) @@ -367,7 +376,7 @@ class OvsDpdkContext(Context): # copy xml to target... self.connection.put(cfg, cfg) - # FIXME: launch through libvirt + # NOTE: launch through libvirt LOG.info("virsh create ...") Libvirt.virsh_create_vm(self.connection, cfg) diff --git a/yardstick/benchmark/contexts/standalone/sriov.py b/yardstick/benchmark/contexts/standalone/sriov.py index 69825fbbf..9d8423b5f 100644 --- a/yardstick/benchmark/contexts/standalone/sriov.py +++ b/yardstick/benchmark/contexts/standalone/sriov.py @@ -110,7 +110,7 @@ class SriovContext(Context): Libvirt.check_if_vm_exists_and_delete(vm, self.connection) # Bind nics back to kernel - for key, ports in self.networks.items(): + for ports in self.networks.values(): # enable VFs for given... build_vfs = "echo 0 > /sys/bus/pci/devices/{0}/sriov_numvfs" self.connection.execute(build_vfs.format(ports.get('phy_port'))) @@ -170,8 +170,7 @@ class SriovContext(Context): def configure_nics_for_sriov(self): vf_cmd = "ip link set {0} vf 0 mac {1}" - for key, ports in self.networks.items(): - vf_pci = [] + for ports in self.networks.values(): host_driver = ports.get('driver') if host_driver not in self.drivers: self.connection.execute("rmmod %svf" % host_driver) @@ -187,19 +186,19 @@ class SriovContext(Context): if interface is not None: self.connection.execute(vf_cmd.format(interface, mac)) - vf_pci = self.get_vf_data('vf_pci', ports.get('phy_port'), mac, interface) + vf_pci = self._get_vf_data(ports.get('phy_port'), mac, interface) ports.update({ 'vf_pci': vf_pci, 'mac': mac }) - LOG.info("Ports %s" % self.networks) + LOG.info('Ports %s', self.networks) def _enable_interfaces(self, index, idx, vfs, cfg): vf_spoofchk = "ip link set {0} vf 0 spoofchk off" vf = self.networks[vfs[0]] - vpci = PciAddress.parse_address(vf['vpci'].strip(), multi_line=True) + vpci = PciAddress(vf['vpci'].strip()) # Generate the vpci for the interfaces slot = index + idx + 10 vf['vpci'] = \ @@ -222,7 +221,7 @@ class SriovContext(Context): # 1. Check and delete VM if already exists Libvirt.check_if_vm_exists_and_delete(vm_name, self.connection) - vcpu, mac = Libvirt.build_vm_xml(self.connection, self.vm_flavor, cfg, vm_name, index) + _, mac = Libvirt.build_vm_xml(self.connection, self.vm_flavor, cfg, vm_name, index) # 2: Cleanup already available VMs for idx, (vkey, vfs) in enumerate(OrderedDict(vnf["network_ports"]).items()): if vkey == "mgmt": @@ -232,7 +231,7 @@ class SriovContext(Context): # copy xml to target... self.connection.put(cfg, cfg) - # FIXME: launch through libvirt + # NOTE: launch through libvirt LOG.info("virsh create ...") Libvirt.virsh_create_vm(self.connection, cfg) @@ -246,15 +245,15 @@ class SriovContext(Context): return nodes - def get_vf_data(self, key, value, vfmac, pfif): + def _get_vf_data(self, value, vfmac, pfif): vf_data = { "mac": vfmac, "pf_if": pfif } vfs = StandaloneContextHelper.get_virtual_devices(self.connection, value) for k, v in vfs.items(): - m = PciAddress.parse_address(k.strip(), multi_line=True) - m1 = PciAddress.parse_address(value.strip(), multi_line=True) + m = PciAddress(k.strip()) + m1 = PciAddress(value.strip()) if m.bus == m1.bus: vf_data.update({"vf_pci": str(v)}) break |