* [dts] [PATCH v2 01/19] Abstract the NIC device as the single class NetDevice
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
@ 2015-05-22 9:03 ` Jiajia, Sun
2015-05-22 9:03 ` [dts] [PATCH v2 02/19] Add a base module for virtual test Jiajia, Sun
` (17 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:03 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Added module: framework/net_device.py
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/net_device.py | 634 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 634 insertions(+)
create mode 100644 framework/net_device.py
diff --git a/framework/net_device.py b/framework/net_device.py
new file mode 100644
index 0000000..0e6614f
--- /dev/null
+++ b/framework/net_device.py
@@ -0,0 +1,634 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+import os
+import re
+from functools import wraps
+import time
+
+
+import settings
+from crb import Crb
+from settings import TIMEOUT
+
+
+class NetDevice(object):
+
+ """
+ Abstract the device which is PF or VF.
+ """
+
+ def __init__(self, crb, bus_id, devfun_id):
+ if not isinstance(crb, Crb):
+ raise Exception(" Please input the instance of Crb!!!")
+ self.crb = crb
+ self.bus_id = bus_id
+ self.devfun_id = devfun_id
+ self.pci = bus_id + ':' + devfun_id
+ self.pci_id = self.get_pci_id(bus_id, devfun_id)
+ self.default_driver = settings.get_nic_driver(self.pci_id)
+
+ if self.nic_is_pf():
+ self.default_vf_driver = ''
+ self.intf_name = self.get_interface_name()
+
+ def __send_expect(self, cmds, expected, timeout=TIMEOUT, alt_session=True):
+ """
+ Wrap the crb`s session as private session for sending expect.
+ """
+ return self.crb.send_expect(cmds, expected, timeout=timeout, alt_session=alt_session)
+
+ def __get_os_type(self):
+ """
+ Get OS type.
+ """
+ return self.crb.get_os_type()
+
+ def nic_is_pf(self):
+ """
+ It is the method that you can check if the nic is PF.
+ """
+ return True
+
+ def nic_has_driver(func):
+ """
+ Check if the NIC has a driver.
+ """
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ nic_instance = args[0]
+ nic_instance.current_driver = nic_instance.get_nic_driver()
+ if not nic_instance.current_driver:
+ return ''
+ return func(*args, **kwargs)
+ return wrapper
+
+ def get_nic_driver(self):
+ """
+ Get the NIC driver.
+ """
+ return self.crb.get_pci_dev_driver(self.bus_id, self.devfun_id)
+
+ @nic_has_driver
+ def get_interface_name(self):
+ """
+ Get interface name of specified pci device.
+ """
+ get_interface_name = getattr(
+ self, 'get_interface_name_%s' %
+ self.__get_os_type())
+ return get_interface_name(self.bus_id, self.devfun_id, self.current_driver)
+
+ def get_interface_name_linux(self, bus_id, devfun_id, driver):
+ """
+ Get interface name of specified pci device on linux.
+ """
+ try:
+ get_interface_name_linux = getattr(
+ self,
+ 'get_interface_name_linux_%s' %
+ driver)
+ except Exception as e:
+ generic_driver = 'generic'
+ get_interface_name_linux = getattr(self,
+ 'get_interface_name_linux_%s' % generic_driver)
+
+ return get_interface_name_linux(bus_id, devfun_id)
+
+ def get_interface_name_linux_generic(self, bus_id, devfun_id):
+ """
+ Get the interface name by the default way on linux.
+ """
+ command = 'ls --color=never /sys/bus/pci/devices/0000\:%s\:%s/net' % (
+ bus_id, devfun_id)
+ return self.__send_expect(command, '# ')
+
+ def get_interface_name_freebsd(self, bus_id, devfun_id, driver):
+ """
+ Get interface name of specified pci device on Freebsd.
+ """
+ try:
+ get_interface_name_linux = getattr(self,
+ 'get_interface_name_freebsd_%s' % driver)
+ except Exception as e:
+ generic_driver = 'generic'
+ get_interface_name_linux = getattr(self,
+ 'get_interface_name_freebsd_%s' % generic_driver)
+
+ return get_interface_name_freebsd(bus_id, devfun_id)
+
+ def get_interface_name_freebsd_generic(self, bus_id, devfun_id):
+ """
+ Get the interface name by the default way on freebsd.
+ """
+ out = self.__send_expect("pciconf -l", "# ")
+ rexp = r"(\w*)@pci0:%s" % bus_id
+ pattern = re.compile(rexp)
+ match = pattern.findall(out)
+ return match[0]
+
+ @nic_has_driver
+ def get_mac_addr(self):
+ """
+ Get mac address of specified pci device.
+ """
+ get_mac_addr = getattr(self, 'get_mac_addr_%s' % self.__get_os_type())
+ return get_mac_addr(self.intf_name, self.bus_id, self.devfun_id, self.current_driver)
+
+ def get_mac_addr_linux(self, intf, bus_id, devfun_id, driver):
+ """
+ Get mac address of specified pci device on linux.
+ """
+ try:
+ get_mac_addr_linux = getattr(
+ self,
+ 'get_mac_addr_linux_%s' %
+ driver)
+ except Exception as e:
+ generic_driver = 'generic'
+ get_mac_addr_linux = getattr(
+ self,
+ 'get_mac_addr_linux_%s' %
+ generic_driver)
+
+ return get_mac_addr_linux(intf, bus_id, devfun_id, driver)
+
+ def get_pci_id(self, bus_id, devfun_id):
+ command = ('cat /sys/bus/pci/devices/0000\:%s\:%s/vendor' %
+ (bus_id, devfun_id))
+ out = self.__send_expect(command, '# ')
+ vender = out[2:]
+ command = ('cat /sys/bus/pci/devices/0000\:%s\:%s/device' %
+ (bus_id, devfun_id))
+ out = self.__send_expect(command, '# ')
+ device = out[2:]
+ return "%s:%s" % (vender, device)
+
+ def get_mac_addr_linux_generic(self, intf, bus_id, devfun_id, driver):
+ """
+ Get MAC by the default way on linux.
+ """
+ command = ('cat /sys/bus/pci/devices/0000\:%s\:%s/net/%s/address' %
+ (bus_id, devfun_id, intf))
+ return self.__send_expect(command, '# ')
+
+ def get_mac_addr_freebsd(self, intf, bus_id, devfun_id, driver):
+ """
+ Get mac address of specified pci device on Freebsd.
+ """
+ try:
+ get_mac_addr_freebsd = getattr(
+ self,
+ 'get_mac_addr_freebsd_%s' %
+ driver)
+ except Exception as e:
+ generic_driver = 'generic'
+ get_mac_addr_freebsd = getattr(
+ self,
+ 'get_mac_addr_freebsd_%s' %
+ generic_driver)
+
+ return get_mac_addr_freebsd(intf, bus_id, devfun_id, driver)
+
+ def get_mac_addr_freebsd_generic(self, intf, bus_id, devfun_id):
+ """
+ Get the MAC by the default way on Freebsd.
+ """
+ out = self.__send_expect('ifconfig %s' % intf, '# ')
+ rexp = r"ether ([\da-f:]*)"
+ pattern = re.compile(rexp)
+ match = pattern.findall(out)
+ return match[0]
+
+ @nic_has_driver
+ def get_ipv4_addr(self):
+ """
+ Get ipv4 address of specified pci device.
+ """
+ get_ipv4_addr = getaddr(
+ self, 'get_ipv4_addr_%s' % self.__get_os_type())
+ return get_ipv4_addr(self.intf_name, self.currenct_driver)
+
+ def get_ipv4_addr_linux(self, intf, driver):
+ """
+ Get ipv4 address of specified pci device on linux.
+ """
+ try:
+ get_ipv4_addr_linux = getattr(self, 'get_ipv4_linux_%s' % driver)
+ except Exception as e:
+ generic_driver = 'generic'
+ get_ipv4_addr_linux = getattr(
+ self, 'get_ipv4_linux_%s' %
+ generic_driver)
+
+ return get_ipv4_addr_linux(intf, bus_id, devfun_id, driver)
+
+ def get_ipv4_addr_linux_generic(self, intf):
+ """
+ Get IPv4 address by the default way on linux.
+ """
+ out = self.__send_expect("ip -family inet address show dev %s | awk '/inet/ { print $2 }'"
+ % intf, "# ")
+ return out.split('/')[0]
+
+ def get_ipv4_addr_freebsd(self, intf, driver):
+ """
+ Get ipv4 address of specified pci device on Freebsd.
+ """
+ try:
+ get_ipv4_addr_freebsd = getattr(
+ self,
+ 'get_ipv4_addr_freebsd_%s' %
+ driver)
+ except Exception as e:
+ generic_driver = 'generic'
+ get_ipv4_addr_freebsd = getattr(
+ self,
+ 'get_ipv4_addr_freebsd_%s' %
+ generic_driver)
+
+ return get_ipv4_addr_freebsd(intf, bus_id, devfun_id)
+
+ def get_ipv4_addr_freebsd_generic(self, intf):
+ """
+ Get the IPv4 address by the default way on Freebsd.
+ """
+ out = self.__send_expect('ifconfig %s' % intf, '# ')
+ rexp = r"inet ([\d:]*)%"
+ pattern = re.compile(rexp)
+ match = pattern.findall(out)
+ if len(match) == 0:
+ return None
+
+ return match[0]
+
+ @nic_has_driver
+ def get_ipv6_addr(self):
+ """
+ Get ipv6 address of specified pci device.
+ """
+ get_ipv6_addr = getattr(
+ self, 'get_ipv6_addr_%s' % self.__get_os_type())
+ return get_ipv6_addr(self.intf_name, self.current_driver)
+
+ def get_ipv6_addr_linux(self, intf, driver):
+ """
+ Get ipv6 address of specified pci device on linux.
+ """
+ try:
+ get_ipv6_addr_linux = getattr(
+ self,
+ 'get_ipv6_addr_linux_%s' %
+ driver)
+ except Exception as e:
+ generic_driver = 'generic'
+ get_ipv6_addr_linux = getattr(
+ self,
+ 'get_ipv6_addr_linux_%s' %
+ generic_driver)
+
+ return get_ipv6_addr_linux(intf)
+
+ def get_ipv6_addr_linux_generic(self, intf):
+ """
+ Get the IPv6 address by the default way on linux.
+ """
+ out = self.__send_expect("ip -family inet6 address show dev %s | awk '/inet6/ { print $2 }'"
+ % intf, "# ")
+ return out.split('/')[0]
+
+ def get_ipv6_addr_freebsd(self, intf, driver):
+ """
+ Get ipv6 address of specified pci device on Freebsd.
+ """
+ try:
+ get_ipv6_addr_freebsd = getattr(
+ self,
+ 'get_ipv6_addr_freebsd_%s' %
+ driver)
+ except Exception as e:
+ generic_driver = 'generic'
+ get_ipv6_addr_freebsd = getattr(
+ self,
+ 'get_ipv6_addr_freebsd_%s' %
+ generic_driver)
+
+ return get_ipv6_addr_freebsd(intf)
+
+ def get_ipv6_addr_freebsd_generic(self, intf):
+ """
+ Get the IPv6 address by the default way on Freebsd.
+ """
+ out = self.__send_expect('ifconfig %s' % intf, '# ')
+ rexp = r"inet6 ([\da-f:]*)%"
+ pattern = re.compile(rexp)
+ match = pattern.findall(out)
+ if len(match) == 0:
+ return None
+
+ return match[0]
+
+ def get_nic_numa(self):
+ """
+ Get numa number of specified pci device.
+ """
+ self.crb.get_nic_numa(self.bus_id, self.devfun_id)
+
+ def get_card_type(self):
+ """
+ Get card type of specified pci device.
+ """
+ return self.crb.get_pci_dev_id(self.bus_id, self.devfun_id)
+
+ @nic_has_driver
+ def get_sriov_vfs_pci(self):
+ """
+ Get all SRIOV VF pci bus of specified pci device.
+ """
+ get_sriov_vfs_pci = getattr(
+ self, 'get_sriov_vfs_pci_%s' % self.__get_os_type())
+ return get_sriov_vfs_pci(self.bus_id, self.devfun_id, self.current_driver)
+
+ def get_sriov_vfs_pci_linux(self, bus_id, devfun_id, driver):
+ """
+ Get all SRIOV VF pci bus of specified pci device on linux.
+ """
+ try:
+ get_sriov_vfs_pci_linux = getattr(
+ self,
+ 'get_sriov_vfs_pci_linux_%s' %
+ driver)
+ except Exception as e:
+ generic_driver = 'generic'
+ get_sriov_vfs_pci_linux = getattr(
+ self,
+ 'get_sriov_vfs_pci_linux_%s' %
+ generic_driver)
+
+ return get_sriov_vfs_pci_linux(bus_id, devfun_id)
+
+ def get_sriov_vfs_pci_linux_generic(self, bus_id, devfun_id):
+ """
+ Get all the VF PCIs of specified PF by the default way on linux.
+ """
+ sriov_numvfs = self.__send_expect(
+ "cat /sys/bus/pci/devices/0000\:%s\:%s/sriov_numvfs" %
+ (bus_id, devfun_id), "# ")
+ sriov_vfs_pci = []
+ if int(sriov_numvfs) == 0:
+ pass
+ else:
+ try:
+ virtfns = self.__send_expect(
+ "ls -d /sys/bus/pci/devices/0000\:%s\:%s/virtfn*" %
+ (bus_id, devfun_id), "# ")
+ for virtfn in virtfns.split():
+ vf_uevent = self.__send_expect(
+ "cat %s" %
+ os.path.join(virtfn, "uevent"), "# ")
+ vf_pci = re.search(
+ r"PCI_SLOT_NAME=0000:([0-9a-f]+:[0-9a-f]+\.[0-9a-f]+)",
+ vf_uevent).group(1)
+ sriov_vfs_pci.append(vf_pci)
+ except Exception as e:
+ print "Scan linux port [0000:%s.%s] sriov vf failed: %s" % (bus_id, devfun_id, e)
+
+ return sriov_vfs_pci
+
+ @nic_has_driver
+ def generate_sriov_vfs(self, vf_num):
+ """
+ Generate some numbers of SRIOV VF.
+ """
+ if vf_num == 0:
+ self.bind_vf_driver()
+ generate_sriov_vfs = getattr(
+ self, 'generate_sriov_vfs_%s' %
+ self.__get_os_type())
+ generate_sriov_vfs(
+ self.bus_id,
+ self.devfun_id,
+ vf_num,
+ self.current_driver)
+ if vf_num != 0:
+ self.sriov_vfs_pci = self.get_sriov_vfs_pci()
+
+ vf_pci = self.sriov_vfs_pci[0]
+ addr_array = vf_pci.split(':')
+ bus_id = addr_array[0]
+ devfun_id = addr_array[1]
+
+ self.default_vf_driver = self.crb.get_pci_dev_driver(
+ bus_id, devfun_id)
+ else:
+ self.sriov_vfs_pci = []
+ time.sleep(1)
+
+ def generate_sriov_vfs_linux(self, bus_id, devfun_id, vf_num, driver):
+ """
+ Generate some numbers of SRIOV VF.
+ """
+ try:
+ generate_sriov_vfs_linux = getattr(
+ self,
+ 'generate_sriov_vfs_linux_%s' %
+ driver)
+ except Exception as e:
+ generic_driver = 'generic'
+ generate_sriov_vfs_linux = getattr(
+ self,
+ 'generate_sriov_vfs_linux_%s' %
+ generic_driver)
+
+ return generate_sriov_vfs_linux(bus_id, devfun_id, vf_num)
+
+ def generate_sriov_vfs_linux_generic(self, bus_id, devfun_id, vf_num):
+ """
+ Generate SRIOV VFs by the default way on linux.
+ """
+ nic_driver = self.get_nic_driver()
+
+ if not nic_driver:
+ return None
+
+ vf_reg_file = "sriov_numvfs"
+ vf_reg_path = os.path.join("/sys/bus/pci/devices/0000:%s:%s" %
+ (bus_id, devfun_id), vf_reg_file)
+ self.__send_expect("echo %d > %s" %
+ (int(vf_num), vf_reg_path), "# ")
+
+ def generate_sriov_vfs_linux_igb_uio(self, bus_id, devfun_id, vf_num):
+ """
+ Generate SRIOV VFs by the special way of igb_uio driver on linux.
+ """
+ nic_driver = self.get_nic_driver()
+
+ if not nic_driver:
+ return None
+
+ vf_reg_file = "max_vfs"
+ if self.default_driver == 'i40e':
+ regx_reg_path = "find /sys -name %s | grep %s:%s" % (vf_reg_file, bus_id, devfun_id)
+ vf_reg_path = self.__send_expect(regx_reg_path, "# ")
+ else:
+ vf_reg_path = os.path.join("/sys/bus/pci/devices/0000:%s:%s" %
+ (bus_id, devfun_id), vf_reg_file)
+ self.__send_expect("echo %d > %s" %
+ (int(vf_num), vf_reg_path), "# ")
+
+ def destroy_sriov_vfs(self):
+ """
+ Destroy the SRIOV VFs.
+ """
+ self.generate_sriov_vfs(0)
+
+ def bind_vf_driver(self, pci='', driver=''):
+ """
+ Bind the specified driver to VF.
+ """
+ bind_vf_driver = getattr(self, 'bind_driver_%s' % self.__get_os_type())
+ if not driver:
+ if not self.default_vf_driver:
+ print "Must specify a driver because default VF driver is NULL!"
+ return
+ driver = self.default_vf_driver
+
+ if not pci:
+ if not self.sriov_vfs_pci:
+ print "No VFs on the nic [%s]!" % self.pci
+ return
+ for vf_pci in self.sriov_vfs_pci:
+ addr_array = vf_pci.split(':')
+ bus_id = addr_array[0]
+ devfun_id = addr_array[1]
+
+ bind_vf_driver(bus_id, devfun_id, driver)
+ else:
+ addr_array = pci.split(':')
+ bus_id = addr_array[0]
+ devfun_id = addr_array[1]
+
+ bind_vf_driver(bus_id, devfun_id, driver)
+
+ def bind_driver(self, driver=''):
+ """
+ Bind specified driver to PF.
+ """
+ bind_driver = getattr(self, 'bind_driver_%s' % self.__get_os_type())
+ if not driver:
+ if not self.default_driver:
+ print "Must specify a driver because default driver is NULL!"
+ return
+ driver = self.default_driver
+ ret = bind_driver(self.bus_id, self.devfun_id, driver)
+ time.sleep(1)
+ return ret
+
+ def bind_driver_linux(self, bus_id, devfun_id, driver):
+ """
+ Bind NIC port to specified driver on linux.
+ """
+ driver_alias = driver.replace('-', '_')
+ try:
+ bind_driver_linux = getattr(
+ self,
+ 'bind_driver_linux_%s' %
+ driver_alias)
+ return bind_driver_linux(bus_id, devfun_id)
+ except Exception as e:
+ driver_alias = 'generic'
+ bind_driver_linux = getattr(
+ self,
+ 'bind_driver_linux_%s' %
+ driver_alias)
+ return bind_driver_linux(bus_id, devfun_id, driver)
+
+ def bind_driver_linux_generic(self, bus_id, devfun_id, driver):
+ """
+ Bind NIC port to specified driver by the default way on linux.
+ """
+ new_id = self.pci_id.replace(':', ' ')
+ nic_pci_num = ':'.join(['0000', bus_id, devfun_id])
+ self.__send_expect(
+ "echo %s > /sys/bus/pci/drivers/%s/new_id" % (new_id, driver), "# ")
+ self.__send_expect(
+ "echo %s > /sys/bus/pci/devices/0000\:%s\:%s/driver/unbind" %
+ (nic_pci_num, bus_id, devfun_id), "# ")
+ self.__send_expect(
+ "echo %s > /sys/bus/pci/drivers/%s/bind" %
+ (nic_pci_num, driver), "# ")
+
+ def bind_driver_linux_pci_stub(self, bus_id, devfun_id):
+ """
+ Bind NIC port to the pci-stub driver on linux.
+ """
+ new_id = self.pci_id.replace(':', ' ')
+ self.__send_expect(
+ "echo %s > /sys/bus/pci/drivers/pci-stub/new_id" % new_id, "# ")
+ self.__send_expect(
+ "echo %s > /sys/bus/pci/devices/0000\:%s\:%s/driver/unbind" %
+ (nic_pci_num, bus_id, devfun_id), "# ")
+ self.__send_expect(
+ "echo %s > /sys/bus/pci/drivers/pci-stub/bind" %
+ nic_pci_num, "# ")
+
+ @nic_has_driver
+ def unbind_driver(self, driver=''):
+ """
+ Unbind driver.
+ """
+ unbind_driver = getattr(
+ self, 'unbind_driver_%s' %
+ self.__get_os_type())
+ if not driver:
+ driver = 'generic'
+ ret = unbind_driver(self.bus_id, self.devfun_id, driver)
+ time.sleep(1)
+ return ret
+
+ def unbind_driver_linux(self, bus_id, devfun_id, driver):
+ """
+ Unbind driver on linux.
+ """
+ driver_alias = driver.replace('-', '_')
+
+ unbind_driver_linux = getattr(
+ self, 'unbind_driver_linux_%s' % driver_alias)
+ return unbind_driver_linux(bus_id, devfun_id)
+
+ def unbind_driver_linux_generic(self, bus_id, devfun_id):
+ """
+ Unbind driver by the default way on linux.
+ """
+ nic_pci_num = ':'.join(['0000', bus_id, devfun_id])
+ cmd = "echo %s > /sys/bus/pci/devices/0000\:%s\:%s/driver/unbind"
+ self.send_expect(cmd % (nic_pci_num, bus_id, devfun_id), "# ")
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 02/19] Add a base module for virtual test
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
2015-05-22 9:03 ` [dts] [PATCH v2 01/19] Abstract the NIC device as the single class NetDevice Jiajia, Sun
@ 2015-05-22 9:03 ` Jiajia, Sun
2015-05-22 9:03 ` [dts] [PATCH v2 03/19] Add QEMU KVM module based on virt_base module for KVM test cases Jiajia, Sun
` (16 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:03 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Added module: framework/virt_base.py
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/virt_base.py | 321 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 321 insertions(+)
create mode 100644 framework/virt_base.py
diff --git a/framework/virt_base.py b/framework/virt_base.py
new file mode 100644
index 0000000..285c1d6
--- /dev/null
+++ b/framework/virt_base.py
@@ -0,0 +1,321 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import sys
+import traceback
+from random import randint
+from itertools import imap
+
+import dts
+import exception
+from dut import Dut
+from config import VirtConf
+from config import VIRTCONF
+from logger import getLogger
+from settings import CONFIG_ROOT_PATH
+from virt_dut import VirtDut
+from utils import remove_old_rsa_key
+
+
+class VirtBase(object):
+
+ """
+ Basic module for customer special virtual type. This module implement functions
+ configurated and composed the VM boot command. With these function, we can get
+ and set the VM boot command, and instantiate the VM.
+ """
+
+ def __init__(self, dut, vm_name, suite_name):
+ """
+ Initialize the VirtBase.
+ dut: the instance of Dut
+ vm_name: the name of VM which you have confiured in the configure
+ suite_name: the name of test suite
+ """
+ self.host_dut = dut
+ self.vm_name = vm_name
+ self.suite = suite_name
+
+ # init the host session and logger for VM
+ self.host_dut.init_host_session()
+
+ # replace dut session
+ self.host_session = self.host_dut.host_session
+ self.host_logger = self.host_dut.logger
+
+ # init the host resouce pool for VM
+ self.virt_pool = self.host_dut.virt_pool
+
+ if not self.has_virtual_ability():
+ if not self.enable_virtual_ability():
+ raise Exception(
+ "Dut [ %s ] cannot have the virtual ability!!!")
+
+ self.virt_type = self.get_virt_type()
+
+ self.params = []
+ # default call back function is None
+ self.callback = None
+
+ def get_virt_type(self):
+ """
+ Get the virtual type, such as KVM, XEN or LIBVIRT.
+ """
+ NotImplemented
+
+ def has_virtual_ability(self):
+ """
+ Check if the host have the ability of virtualization.
+ """
+ NotImplemented
+
+ def enable_virtual_ability(self):
+ """
+ Enalbe the virtual ability on the DUT.
+ """
+ NotImplemented
+
+ def load_global_config(self):
+ """
+ Load global configure in the path DTS_ROOT_PAHT/conf.
+ """
+ conf = VirtConf(VIRTCONF)
+ conf.load_virt_config(self.virt_type)
+ global_conf = conf.get_virt_config()
+ for param in global_conf:
+ for key in param.keys():
+ self.__save_local_config(key, param[key])
+
+ def load_local_config(self, suite_name):
+ """
+ Load local configure in the path DTS_ROOT_PATH/conf.
+ """
+ # load local configuration by suite and vm name
+ conf = VirtConf(CONFIG_ROOT_PATH + suite_name + '.cfg')
+ conf.load_virt_config(self.vm_name)
+ local_conf = conf.get_virt_config()
+ # replace global configurations with local configurations
+ for param in local_conf:
+ if 'mem' in param.keys():
+ self.__save_local_config('mem', param['mem'])
+ continue
+ if 'cpu' in param.keys():
+ self.__save_local_config('cpu', param['cpu'])
+ continue
+ # save local configurations
+ for key in param.keys():
+ self.__save_local_config(key, param[key])
+
+ def __save_local_config(self, key, value):
+ """
+ Save the local config into the global dict self.param.
+ """
+ for param in self.params:
+ if key in param.keys():
+ param[key] = value
+ return
+ self.params.append({key: value})
+
+ def compose_boot_param(self):
+ """
+ Compose all boot param for starting the VM.
+ """
+ for param in self.params:
+ key = param.keys()[0]
+ value = param[key]
+ try:
+ param_func = getattr(self, 'add_vm_' + key)
+ if callable(param_func):
+ for option in value:
+ param_func(**option)
+ else:
+ print dts.RED("Virt %s function not callable!!!" % key)
+ except AttributeError:
+ print dts.RED("Virt %s function not implemented!!!" % key)
+ except Exception:
+ raise exception.VirtConfigParamException(key)
+
+ def find_option_index(self, option):
+ """
+ Find the boot option in the params which is generated from
+ the global and local configures, and this function will
+ return the index by which option can be indexed in the
+ param list.
+ """
+ index = 0
+ for param in self.params:
+ key = param.keys()[0]
+ if key.strip() == option.strip():
+ return index
+ index += 1
+
+ return None
+
+ def generate_unique_mac(self):
+ """
+ Generate a unique MAC based on the DUT.
+ """
+ mac_head = '00:00:00:'
+ mac_tail = ':'.join(
+ ['%02x' % x for x in imap(lambda x:randint(0, 255), range(3))])
+ return mac_head + mac_tail
+
+ def get_vm_ip(self):
+ """
+ Get the VM IP.
+ """
+ NotImplemented
+
+ def start(self):
+ """
+ Start VM and instantiate the VM with VirtDut.
+ """
+ try:
+ # load global and suite configuration file
+ self.load_global_config()
+ self.load_local_config(self.suite)
+
+ # compose boot command for different hypervisors
+ self.compose_boot_param()
+
+ # start virutal machine
+ self._start_vm()
+
+ # connect vm dut and init running environment
+ vm_dut = self.instantiate_vm_dut()
+ except Exception as vm_except:
+ if self.handle_exception(vm_except):
+ print dts.RED("Handled expection " + str(type(vm_except)))
+ else:
+ print dts.RED("Unhandled expection " + str(type(vm_except)) + " !!!")
+
+ if callable(self.callback):
+ self.callback()
+
+ return None
+ return vm_dut
+
+ def handle_exception(self, vm_except):
+ # show exception back trace
+ exc_type, exc_value, exc_traceback = sys.exc_info()
+ traceback.print_exception(exc_type, exc_value, exc_traceback,
+ limit=2, file=sys.stdout)
+ if type(vm_except) is exception.ConfigParseException:
+ # nothing to handle just return True
+ return True
+ elif type(vm_except) is exception.VirtConfigParseException:
+ # nothing to handle just return True
+ return True
+ elif type(vm_except) is exception.VirtConfigParamException:
+ # nothing to handle just return True
+ return True
+ elif type(vm_except) is exception.StartVMFailedException:
+ # start vm failure
+ return True
+ elif type(vm_except) is exception.VirtDutConnectException:
+ # need stop vm
+ self.virt_obj.stop()
+ return True
+ elif type(vm_except) is exception.VirtDutInitException:
+ # need close session
+ vm_except.vm_dut.close_sessions()
+ # need stop vm
+ self.virt_obj.stop()
+ return True
+ else:
+ return False
+
+ def __start_vm(self):
+ """
+ Start VM.
+ """
+ NotImplemented
+
+ def instantiate_vm_dut(self):
+ """
+ Instantiate the Dut class for VM.
+ """
+ crb = self.host_dut.crb.copy()
+ crb['bypass core0'] = False
+ vm_ip = self.get_vm_ip()
+ crb['IP'] = vm_ip
+
+ # remove default key
+ remove_old_rsa_key(self.host_dut.tester, crb['IP'])
+
+ serializer = self.host_dut.serializer
+
+ try:
+ vm_dut = VirtDut(
+ crb,
+ serializer,
+ self.vm_name,
+ self.suite)
+ except:
+ raise exception.VirtDutConnectException
+ return None
+
+ vm_dut.nic_type = 'any'
+ vm_dut.tester = self.host_dut.tester
+ vm_dut.host_dut = self.host_dut
+ vm_dut.host_session = self.host_session
+
+ read_cache = False
+ skip_setup = self.host_dut.skip_setup
+ base_dir = self.host_dut.base_dir
+ vm_dut.set_speedup_options(read_cache, skip_setup)
+ func_only = self.host_dut.want_func_tests
+ perf_only = self.host_dut.want_perf_tests
+ vm_dut.set_test_types(func_tests=func_only, perf_tests=perf_only)
+ # base_dir should be set before prerequisites
+ vm_dut.set_directory(base_dir)
+
+ try:
+ # setting up dpdk in vm, must call at last
+ vm_dut.prerequisites(dts.Package, dts.Patches)
+ target = self.host_dut.target
+ vm_dut.set_target(target)
+ except:
+ raise exception.VirtDutInitException(vm_dut)
+ return None
+
+ return vm_dut
+
+ def stop(self):
+ """
+ Stop the VM.
+ """
+ NotImplemented
+
+ def register_exit_callback(self, callback):
+ """
+ Call register exit call back function
+ """
+ self.callback = callback
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 03/19] Add QEMU KVM module based on virt_base module for KVM test cases
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
2015-05-22 9:03 ` [dts] [PATCH v2 01/19] Abstract the NIC device as the single class NetDevice Jiajia, Sun
2015-05-22 9:03 ` [dts] [PATCH v2 02/19] Add a base module for virtual test Jiajia, Sun
@ 2015-05-22 9:03 ` Jiajia, Sun
2015-05-22 9:03 ` [dts] [PATCH v2 04/19] Add a module to manage the host resource Jiajia, Sun
` (15 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:03 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Added module: framework/qemu_kvm.py
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/qemu_kvm.py | 972 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 972 insertions(+)
create mode 100644 framework/qemu_kvm.py
diff --git a/framework/qemu_kvm.py b/framework/qemu_kvm.py
new file mode 100644
index 0000000..e762695
--- /dev/null
+++ b/framework/qemu_kvm.py
@@ -0,0 +1,972 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+import time
+import re
+import os
+
+from virt_base import VirtBase
+from exception import StartVMFailedException
+
+# This name is derictly defined in the qemu guest serivce
+# So you can not change it except it is changed by the service
+QGA_DEV_NAME = 'org.qemu.guest_agent.0'
+# This path defines an socket path on the host connected with
+# a specified VM
+QGA_SOCK_PATH_TEMPLATE = '/tmp/%(vm_name)s_qga0.sock'
+
+
+class QEMUKvm(VirtBase):
+
+ DEFAULT_BRIDGE = 'br0'
+ QEMU_IFUP = "#!/bin/sh\n\n" + \
+ "set -x\n\n" + \
+ "switch=%(switch)s\n\n" + \
+ "if [ -n '$1' ];then\n" + \
+ " tunctl -t $1\n" + \
+ " ip link set $1 up\n" + \
+ " sleep 0.5s\n" + \
+ " brctl addif $switch $1\n" + \
+ " exit 0\n" + \
+ "else\n" + \
+ " echo 'Error: no interface specified'\n" + \
+ " exit 1\n" + \
+ "fi"
+
+ QEMU_IFUP_PATH = '/etc/qemu-ifup'
+
+ def __init__(self, dut, vm_name, suite_name):
+ super(QEMUKvm, self).__init__(dut, vm_name, suite_name)
+
+ # set some default values for vm,
+ # if there is not the values of the specified options
+ self.set_vm_default()
+
+ # initialize qemu emulator, example: qemu-system-x86_64
+ self.qemu_emulator = self.get_qemu_emulator()
+
+ # initialize qemu boot command line
+ # example: qemu-system-x86_64 -name vm1 -m 2048 -vnc :1 -daemonize
+ self.qemu_boot_line = ''
+
+ # initialize some resource used by guest.
+ self.init_vm_request_resource()
+
+ QGA_CLI_PATH = '-r dep/QMP/'
+ self.host_session.copy_file_to(QGA_CLI_PATH)
+
+ def set_vm_default(self):
+ self.set_vm_name(self.vm_name)
+ self.set_vm_enable_kvm()
+ self.set_vm_qga()
+ self.set_vm_daemon()
+
+ def init_vm_request_resource(self):
+ """
+ initialize some resource used by VM.
+ examples: CPU, PCIs, so on.
+ CPU:
+ initialize vcpus what will be pinned to the VM.
+ If specify this param, the specified vcpus will
+ be pinned to VM by the command 'taskset' when
+ starting the VM.
+ example:
+ vcpus_pinned_to_vm = '1 2 3 4'
+ taskset -c 1,2,3,4 qemu-boot-command-line
+ """
+ self.vcpus_pinned_to_vm = ''
+
+ # initialize assigned PCI
+ self.assigned_pcis = []
+
+ def get_virt_type(self):
+ """
+ Get the virtual type.
+ """
+ return 'KVM'
+
+ def get_qemu_emulator(self):
+ """
+ Get the qemu emulator based on the crb.
+ """
+ arch = self.host_session.send_expect('uname -m', '# ')
+ return 'qemu-system-' + arch
+
+ def set_qemu_emulator(self, qemu_emulator_path):
+ """
+ Set the qemu emulator in the specified path explicitly.
+ """
+ qemu_emulator_path = str(qemu_emulator_path)
+ out = self.host_session.send_expect(
+ 'ls %s' % qemu_emulator_path, '[.*')
+ if 'No such file or directory' in out:
+ self.host_logger.error("No emulator [ %s ] on the DUT [ %s ]" % \
+ (qemu_emulator, self.host_dut.get_ip_address()))
+ return None
+ out = self.host_session.send_expect("[ -x %s ];echo $?" % qemu_emulator_path, '# ')
+ if out == '1':
+ self.host_logger.error("Emulator [ %s ] not executable on the DUT [ %s ]" % \
+ (qemu_emulator, self.host_dut.get_ip_address()))
+ return None
+ self.qemu_emulator = qemu_emulator
+
+ def has_virtual_ability(self):
+ """
+ Check if host has the virtual ability.
+ """
+ out = self.host_session.send_expect('cat /proc/cpuinfo | grep flags', '# ')
+ rgx = re.search(' vmx ', out)
+ if rgx:
+ pass
+ else:
+ self.host_logger.warning("Hardware virtualization disabled on host!!!")
+ return False
+
+ out = self.host_session.send_expect('lsmod | grep kvm', '# ')
+ if 'kvm' in out and 'kvm_intel' in out:
+ return True
+ else:
+ self.host_logger.warning("kvm or kvm_intel not insmod!!!")
+ return False
+
+ def enable_virtual_ability(self):
+ """
+ Load the virutal module of kernel to enable the virutal ability.
+ """
+ self.host_session.send_expect('modprobe kvm', '# ')
+ self.host_session.send_expect('modprobe kvm_intel', '# ')
+ return True
+
+ def disk_image_is_ok(self, image):
+ """
+ Check if the image is OK and no error.
+ """
+ pass
+
+ def image_is_used(self, image_path):
+ """
+ Check if the image has been used on the host.
+ """
+ qemu_cmd_lines = self.host_session.send_expect(
+ "ps aux | grep qemu | grep -v grep", "# ")
+
+ image_name_flag = '/' + image_path.strip().split('/')[-1] + ' '
+ if image_path in qemu_cmd_lines or \
+ image_name_flag in qemu_cmd_lines:
+ return True
+ return False
+
+ def __add_boot_line(self, option_boot_line):
+ """
+ Add boot option into the boot line.
+ """
+ separator = ' '
+ self.qemu_boot_line += separator + option_boot_line
+
+ def set_vm_enable_kvm(self, enable='yes'):
+ """
+ Set VM boot option to enable the option 'enable-kvm'.
+ """
+ self.params.append({'enable_kvm': [{'enable': '%s' % enable}]})
+
+ def add_vm_enable_kvm(self, **options):
+ """
+ 'enable': 'yes'
+ """
+ if 'enable' in options.keys() and \
+ options['enable'] == 'yes':
+ enable_kvm_boot_line = '-enable-kvm'
+ self.__add_boot_line(enable_kvm_boot_line)
+
+ def set_vm_name(self, vm_name):
+ """
+ Set VM name.
+ """
+ self.params.append({'name': [{'name': '%s' % vm_name}]})
+
+ def add_vm_name(self, **options):
+ """
+ name: vm1
+ """
+ if 'name' in options.keys() and \
+ options['name']:
+ name_boot_line = '-name %s' % options['name']
+ self.__add_boot_line(name_boot_line)
+
+ def add_vm_cpu(self, **options):
+ """
+ model: [host | core2duo | ...]
+ usage:
+ choose model value from the command
+ qemu-system-x86_64 -cpu help
+ number: '4' #number of vcpus
+ cpupin: '3 4 5 6' # host cpu list
+ """
+ if 'model' in options.keys() and \
+ options['model']:
+ cpu_boot_line = '-cpu %s' % options['model']
+ self.__add_boot_line(cpu_boot_line)
+ if 'number' in options.keys() and \
+ options['number']:
+ smp_cmd_line = '-smp %d' % int(options['number'])
+ self.__add_boot_line(smp_cmd_line)
+ if 'cpupin' in options.keys() and \
+ options['cpupin']:
+ self.vcpus_pinned_to_vm = str(options['cpupin'])
+
+ def add_vm_mem(self, **options):
+ """
+ size: 1024
+ """
+ if 'size' in options.keys():
+ mem_boot_line = '-m %s' % options['size']
+ self.__add_boot_line(mem_boot_line)
+
+ def add_vm_disk(self, **options):
+ """
+ file: /home/image/test.img
+ """
+ if 'file' in options.keys():
+ disk_boot_line = '-drive file=%s' % options['file']
+ self.__add_boot_line(disk_boot_line)
+
+ def add_vm_net(self, **options):
+ """
+ Add VM net device.
+ type: [nic | user | tap | bridge | ...]
+ opt_[vlan | fd | br | mac | ...]
+ note:the sub-option will be decided according to the net type.
+ """
+ if 'type' in options.keys():
+ if 'opt_vlan' not in options.keys():
+ options['opt_vlan'] = '0'
+ if options['type'] == 'nic':
+ self.__add_vm_net_nic(**options)
+ if options['type'] == 'user':
+ self.__add_vm_net_user(**options)
+ if options['type'] == 'tap':
+ self.__add_vm_net_tap(**options)
+
+ if options['type'] == 'user':
+ self.net_type = 'hostfwd'
+ elif options['type'] in ['tap', 'bridge']:
+ self.net_type = 'bridge'
+
+ def __add_vm_net_nic(self, **options):
+ """
+ type: nic
+ opt_vlan: 0
+ note: Default is 0.
+ opt_macaddr: 00:00:00:00:01:01
+ note: if creating a nic, it`s better to specify a MAC,
+ else it will get a random number.
+ opt_model:["e1000" | "virtio" | "i82551" | ...]
+ note: Default is e1000.
+ opt_name: 'nic1'
+ opt_addr: ''
+ note: PCI cards only.
+ opt_vectors:
+ note: This option currently only affects virtio cards.
+ """
+ net_boot_line = '-net nic'
+ separator = ','
+ if 'opt_vlan' in options.keys() and \
+ options['opt_vlan']:
+ net_boot_line += separator + 'vlan=%s' % options['opt_vlan']
+
+ # add MAC info
+ if 'opt_macaddr' in options.keys() and \
+ options['opt_macaddr']:
+ mac = options['opt_macaddr']
+ else:
+ mac = self.generate_unique_mac()
+ net_boot_line += separator + 'macaddr=%s' % mac
+
+ if 'opt_model' in options.keys() and \
+ options['opt_model']:
+ net_boot_line += separator + 'model=%s' % options['opt_model']
+ if 'opt_name' in options.keys() and \
+ options['opt_name']:
+ net_boot_line += separator + 'name=%s' % options['opt_name']
+ if 'opt_addr' in options.keys() and \
+ options['opt_addr']:
+ net_boot_line += separator + 'addr=%s' % options['opt_addr']
+ if 'opt_vectors' in options.keys() and \
+ options['opt_vectors']:
+ net_boot_line += separator + 'vectors=%s' % options['opt_vectors']
+
+ if self.__string_has_multi_fields(net_boot_line, separator):
+ self.__add_boot_line(net_boot_line)
+
+ def __add_vm_net_user(self, **options):
+ """
+ type: user
+ opt_vlan: 0
+ note: default is 0.
+ opt_hostfwd: [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport
+ """
+ net_boot_line = '-net user'
+ separator = ','
+ if 'opt_vlan' in options.keys() and \
+ options['opt_vlan']:
+ net_boot_line += separator + 'vlan=%s' % options['opt_vlan']
+ if 'opt_hostfwd' in options.keys() and \
+ options['opt_hostfwd']:
+ self.__check_net_user_opt_hostfwd(options['opt_hostfwd'])
+ opt_hostfwd = options['opt_hostfwd']
+ else:
+ opt_hostfwd = '::-:'
+ hostfwd_line = self.__parse_net_user_opt_hostfwd(opt_hostfwd)
+ net_boot_line += separator + 'hostfwd=%s' % hostfwd_line
+
+ if self.__string_has_multi_fields(net_boot_line, separator):
+ self.__add_boot_line(net_boot_line)
+
+ def __check_net_user_opt_hostfwd(self, opt_hostfwd):
+ """
+ Use regular expression to check if hostfwd value format is correct.
+ """
+ regx_ip = '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
+ regx_hostfwd = r'["tcp" | "udp"]?:%s?:\d+-%s?:\d+' % (regx_ip, regx_ip)
+ if not re.match(regx_hostfwd, opt_hostfwd):
+ raise Exception("Option opt_hostfwd format is not correct,\n" +
+ "it is %s,\n " % opt_hostfwd +
+ "it should be [tcp|udp]:[hostaddr]:hostport-" +
+ "[guestaddr]:guestport.\n")
+
+ def __parse_net_user_opt_hostfwd(self, opt_hostfwd):
+ """
+ Parse the boot option 'hostfwd'.
+ """
+ separator = ':'
+ field = lambda option, index, separator=':': \
+ option.split(separator)[index]
+
+ # get the forword type
+ fwd_type = field(opt_hostfwd, 0)
+ if not fwd_type:
+ fwd_type = 'tcp'
+
+ # get the host addr
+ host_addr = field(opt_hostfwd, 1)
+ if not host_addr:
+ host_addr = str(self.host_dut.get_ip_address())
+
+ # get the host port in the option
+ host_port = field(opt_hostfwd, 2).split('-')[0]
+ if not host_port:
+ host_port = str(self.virt_pool.alloc_port(self.vm_name))
+ self.redir_port = host_port
+
+ # get the guest addr
+ try:
+ guest_addr = str(field(opt_hostfwd, 2).split('-')[1])
+ except IndexError as e:
+ guest_addr = ''
+
+ # get the guest port in the option
+ guest_port = str(field(opt_hostfwd, 3))
+ if not guest_port:
+ guest_port = '22'
+
+ hostfwd_line = fwd_type + separator + \
+ host_addr + separator + \
+ host_port + \
+ '-' + \
+ guest_addr + separator + \
+ guest_port
+
+ # init the redirect incoming TCP or UDP connections
+ # just combine host address and host port, it is enough
+ # for using ssh to connect with VM
+ self.hostfwd_addr = host_addr + separator + host_port
+
+ return hostfwd_line
+
+ def __add_vm_net_tap(self, **options):
+ """
+ type: tap
+ opt_vlan: 0
+ note: default is 0.
+ opt_br: br0
+ note: if choosing tap, need to specify bridge name,
+ else it will be br0.
+ opt_script: QEMU_IFUP_PATH
+ note: if not specified, default is self.QEMU_IFUP_PATH.
+ opt_downscript: QEMU_IFDOWN_PATH
+ note: if not specified, default is self.QEMU_IFDOWN_PATH.
+ """
+ net_boot_line = '-net tap'
+ separator = ','
+
+ # add bridge info
+ if 'opt_br' in options.keys() and \
+ options['opt_br']:
+ bridge = options['opt_br']
+ else:
+ bridge = self.DEFAULT_BRIDGE
+ self.__generate_net_config_script(str(bridge))
+
+ if 'opt_vlan' in options.keys() and \
+ options['opt_vlan']:
+ net_boot_line += separator + 'vlan=%s' % options['opt_vlan']
+
+ # add network configure script path
+ if 'opt_script' in options.keys() and \
+ options['opt_script']:
+ script_path = options['opt_script']
+ else:
+ script_path = self.QEMU_IFUP_PATH
+ net_boot_line += separator + 'script=%s' % script_path
+
+ # add network configure downscript path
+ if 'opt_downscript' in options.keys() and \
+ options['opt_downscript']:
+ net_boot_line += separator + \
+ 'downscript=%s' % options['opt_downscript']
+
+ if self.__string_has_multi_fields(net_boot_line, separator):
+ self.__add_boot_line(net_boot_line)
+
+ def __generate_net_config_script(self, switch=DEFAULT_BRIDGE):
+ """
+ Generate a script for qemu emulator to build a tap device
+ between host and guest.
+ """
+ qemu_ifup = self.QEMU_IFUP % {'switch': switch}
+ file_name = os.path.basename(self.QEMU_IFUP_PATH)
+ tmp_file_path = '/tmp/%s' % file_name
+ self.host_dut.create_file(qemu_ifup, tmp_file_path)
+ self.host_session.send_expect('mv -f ~/%s %s' % (file_name,
+ self.QEMU_IFUP_PATH), '# ')
+ self.host_session.send_expect(
+ 'chmod +x %s' % self.QEMU_IFUP_PATH, '# ')
+
+ def set_vm_device(self, driver='pci-assign', **props):
+ """
+ Set VM device with specified driver.
+ """
+ props['driver'] = driver
+ index = self.find_option_index('device')
+ if index:
+ self.params[index]['device'].append(props)
+ else:
+ self.params.append({'device': [props]})
+
+ def add_vm_device(self, **options):
+ """
+ driver: [pci-assign | virtio-net-pci | ...]
+ prop_[host | addr | ...]: value
+ note:the sub-property will be decided according to the driver.
+ """
+ if 'driver' in options.keys() and \
+ options['driver']:
+ if options['driver'] == 'pci-assign':
+ self.__add_vm_pci_assign(**options)
+ elif options['driver'] == 'virtio-net-pci':
+ self.__add_vm_virtio_net_pci(**options)
+
+ def __add_vm_pci_assign(self, **options):
+ """
+ driver: pci-assign
+ prop_host: 08:00.0
+ prop_addr: 00:00:00:00:01:02
+ """
+ dev_boot_line = '-device pci-assign'
+ separator = ','
+ if 'prop_host' in options.keys() and \
+ options['prop_host']:
+ dev_boot_line += separator + 'host=%s' % options['prop_host']
+ if 'prop_addr' in options.keys() and \
+ options['prop_addr']:
+ dev_boot_line += separator + 'addr=%s' % options['prop_addr']
+ self.assigned_pcis.append(options['prop_addr'])
+
+ if self.__string_has_multi_fields(dev_boot_line, separator):
+ self.__add_boot_line(dev_boot_line)
+
+ def __add_vm_virtio_net_pci(self, **options):
+ """
+ driver: virtio-net-pci
+ prop_netdev: mynet1
+ prop_id: net1
+ prop_mac: 00:00:00:00:01:03
+ prop_bus: pci.0
+ prop_addr: 0x3
+ """
+ dev_boot_line = '-device virtio-net-pci'
+ separator = ','
+ if 'prop_netdev' in options.keys() and \
+ options['prop_netdev']:
+ dev_boot_line += separator + 'netdev=%s' % options['prop_netdev']
+ if 'prop_id' in options.keys() and \
+ options['prop_id']:
+ dev_boot_line += separator + 'id=%s' % options['prop_id']
+ if 'prop_mac' in options.keys() and \
+ options['prop_mac']:
+ dev_boot_line += separator + 'mac=%s' % options['prop_mac']
+ if 'prop_bus' in options.keys() and \
+ options['prop_bus']:
+ dev_boot_line += separator + 'bus=%s' % options['prop_bus']
+ if 'prop_addr' in options.keys() and \
+ options['prop_addr']:
+ dev_boot_line += separator + 'addr=%s' % options['prop_addr']
+
+ if self.__string_has_multi_fields(self, string, separator):
+ self.__add_boot_line(dev_boot_line)
+
+ def __string_has_multi_fields(self, string, separator, field_num=2):
+ """
+ Check if string has multiple fields which is splited with
+ specified separator.
+ """
+ fields = string.split(separator)
+ number = 0
+ for field in fields:
+ if field:
+ number += 1
+ if number >= field_num:
+ return True
+ else:
+ return False
+
+ def add_vm_monitor(self, **options):
+ """
+ port: 6061 # if adding monitor to vm, need to specicy
+ this port, else it will get a free port
+ on the host machine.
+ """
+ if 'port' in options.keys():
+ if options['port']:
+ port = options['port']
+ else:
+ port = self.virt_pool.alloc_port(self.vm_name)
+
+ monitor_boot_line = '-monitor tcp::%d,server,nowait' % int(port)
+ self.__add_boot_line(monitor_boot_line)
+
+ def set_vm_qga(self, enable='yes'):
+ """
+ Set VM qemu-guest-agent.
+ """
+ index = self.find_option_index('qga')
+ if index:
+ self.params[index] = {'qga': [{'enable': '%s' % enable}]}
+ else:
+ self.params.append({'qga': [{'enable': '%s' % enable}]})
+ QGA_SOCK_PATH = QGA_SOCK_PATH_TEMPLATE % {'vm_name': self.vm_name}
+ self.qga_sock_path = QGA_SOCK_PATH
+
+ def add_vm_qga(self, **options):
+ """
+ enable: 'yes'
+ """
+ QGA_DEV_ID = '%(vm_name)s_qga0' % {'vm_name': self.vm_name}
+ QGA_SOCK_PATH = QGA_SOCK_PATH_TEMPLATE % {'vm_name': self.vm_name}
+
+ separator = ' '
+
+ if 'enable' in options.keys():
+ if options['enable'] == 'yes':
+ qga_boot_block = '-chardev socket,path=%(SOCK_PATH)s,server,nowait,id=%(ID)s' + \
+ separator + '-device virtio-serial' + separator + \
+ '-device virtserialport,chardev=%(ID)s,name=%(DEV_NAME)s'
+ qga_boot_line = qga_boot_block % {'SOCK_PATH': QGA_SOCK_PATH,
+ 'DEV_NAME': QGA_DEV_NAME,
+ 'ID': QGA_DEV_ID}
+ self.__add_boot_line(qga_boot_line)
+ self.qga_sock_path = QGA_SOCK_PATH
+ else:
+ self.qga_sock_path = ''
+
+ def add_vm_serial_port(self, **options):
+ """
+ enable: 'yes'
+ """
+ SERAIL_SOCK_PATH = "/tmp/%s_serial.sock" % self.vm_name
+ if 'enable' in options.keys():
+ if options['enable'] == 'yes':
+ serial_boot_line = '-serial unix:%s,server,nowait' % SERIAL_SOCK_PATH
+ self.__add_boot_line(serial_boot_line)
+ else:
+ pass
+
+ def add_vm_vnc(self, **options):
+ """
+ displayNum: 1
+ """
+ if 'displayNum' in options.keys() and \
+ options['displayNum']:
+ display_num = options['displayNum']
+ else:
+ display_num = self.virt_pool.alloc_vnc_num(self.vm_name)
+
+ vnc_boot_line = '-vnc :%d' % int(display_num)
+ self.__add_boot_line(vnc_boot_line)
+
+ def set_vm_daemon(self, enable='yes'):
+ """
+ Set VM daemon option.
+ """
+ index = self.find_option_index('daemon')
+ if index:
+ self.params[index] = {'daemon': [{'enable': '%s' % enable}]}
+ else:
+ self.params.append({'daemon': [{'enable': '%s' % enable}]})
+
+ def add_vm_daemon(self, **options):
+ """
+ enable: 'yes'
+ note:
+ By default VM will start with the daemonize status.
+ Not support starting it on the stdin now.
+ """
+ if 'daemon' in options.keys() and \
+ options['enable'] == 'no':
+ pass
+ else:
+ daemon_boot_line = '-daemonize'
+ self.__add_boot_line(daemon_boot_line)
+
+ def _start_vm(self):
+ """
+ Start VM.
+ """
+ self.__alloc_assigned_pcis()
+
+ qemu_boot_line = self.generate_qemu_boot_line()
+
+ # Start VM using the qemu command
+ ret = self.host_session.send_expect(qemu_boot_line, '# ', verify=True)
+ time.sleep(30)
+ if type(ret) is int and ret != 0:
+ raise StartVMFailedException('Start VM failed!!!')
+
+ def generate_qemu_boot_line(self):
+ """
+ Generate the whole QEMU boot line.
+ """
+ qemu_emulator = self.qemu_emulator
+
+ if self.vcpus_pinned_to_vm.strip():
+ vcpus = self.__alloc_vcpus()
+
+ if vcpus.strip():
+ qemu_boot_line = 'taskset -c %s ' % vcpus + \
+ qemu_emulator + ' ' + \
+ self.qemu_boot_line
+ else:
+ qemu_boot_line = qemu_emulator + ' ' + \
+ self.qemu_boot_line
+
+ return qemu_boot_line
+
+ def __alloc_vcpus(self):
+ """
+ Allocate virtual CPUs for VM.
+ """
+ req_cpus = self.vcpus_pinned_to_vm.split()
+ cpus = self.virt_pool.alloc_cpu(vm=self.vm_name, corelist=req_cpus)
+
+ if len(req_cpus) != len(cpus):
+ self.host_logger.warn("VCPUs not enough, required [ %s ], just [ %s ]" % \
+ (req_cpus, cpus))
+ raise Exception("No enough required vcpus!!!")
+
+ vcpus_pinned_to_vm = ''
+ for cpu in cpus:
+ vcpus_pinned_to_vm += ',' + cpu
+ vcpus_pinned_to_vm = vcpus_pinned_to_vm.lstrip(',')
+
+ return vcpus_pinned_to_vm
+
+ def __alloc_assigned_pcis(self):
+ """
+ Record the PCI device info
+ Struct: {dev pci: {'is_vf': [True | False],
+ 'pf_pci': pci}}
+ example:
+ {'08:10.0':{'is_vf':True, 'pf_pci': 08:00.0}}
+ """
+ assigned_pcis_info = {}
+ for pci in self.assigned_pcis:
+ assigned_pcis_info[pci] = {}
+ if self.__is_vf_pci(pci):
+ assigned_pcis_info[pci]['is_vf'] = True
+ pf_pci = self.__map_vf_to_pf(pci)
+ assgined_pcis_info[pci]['pf_pci'] = pf_pci
+ if self.virt_pool.alloc_vf_from_pf(vm=self.vm_name,
+ pf_pci=pf_pci,
+ *[pci]):
+ port = self.__get_vf_port(pci)
+ port.unbind_driver()
+ port.bind_driver('pci-stub')
+ else:
+ # check that if any VF of specified PF has been
+ # used, raise exception
+ vf_pci = self.__vf_has_been_assinged(pci, **assinged_pcis_info)
+ if vf_pci:
+ raise Exception(
+ "Error: A VF [%s] generated by PF [%s] has " %
+ (vf_pci, pci) +
+ "been assigned to VM, so this PF can not be " +
+ "assigned to VM again!")
+ # get the port instance of PF
+ port = self.__get_net_device_by_pci(pci)
+
+ if self.virt_pool.alloc_pf(vm=self.vm_name,
+ *[pci]):
+ port.unbind_driver()
+
+ def __is_vf_pci(self, dev_pci):
+ """
+ Check if the specified PCI dev is a VF.
+ """
+ for port_info in self.host_dut.ports_info:
+ if 'sriov_vfs_pci' in port_info.keys():
+ if dev_pci in port_info['sriov_vfs_pci']:
+ return True
+ return False
+
+ def __map_vf_to_pf(self, dev_pci):
+ """
+ Map the specified VF to PF.
+ """
+ for port_info in self.host_dut.ports_info:
+ if 'sriov_vfs_pci' in port_info.keys():
+ if dev_pci in port_info['sriov_vfs_pci']:
+ return port_info['pci']
+ return None
+
+ def __get_vf_port(self, dev_pci):
+ """
+ Get the NetDevice instance of specified VF.
+ """
+ for port_info in self.host_dut.ports_info:
+ if 'vfs_port' in port_info.keys():
+ for port in port_info['vfs_port']:
+ if dev_pci == port.pci:
+ return port
+ return None
+
+ def __vf_has_been_assigned(self, pf_pci, **assigned_pcis_info):
+ """
+ Check if the specified VF has been used.
+ """
+ for pci in assigned_pcis_info.keys():
+ if assigned_pcis_info[pci]['is_vf'] and \
+ assigned_pcis_info[pci]['pf_pci'] == pf_pci:
+ return pci
+ return False
+
+ def __get_net_device_by_pci(self, net_device_pci):
+ """
+ Get NetDevice instance by the specified PCI bus number.
+ """
+ port_info = self.host_dut.get_port_info(net_device_pci)
+ return port_info['port']
+
+ def get_vm_ip(self):
+ """
+ Get VM IP.
+ """
+ get_vm_ip = getattr(self, "get_vm_ip_%s" % self.net_type)
+ return get_vm_ip()
+
+ def get_vm_ip_hostfwd(self):
+ """
+ Get IP which VM is connected by hostfwd.
+ """
+ return self.hostfwd_addr
+
+ def get_vm_ip_bridge(self):
+ """
+ Get IP which VM is connected by bridge.
+ """
+ out = self.__control_session('ping', '60')
+ if not out:
+ time.sleep(10)
+ out = self.__control_session('ifconfig')
+ ips = re.findall(r'inet (\d+\.\d+\.\d+\.\d+)', out)
+
+ if '127.0.0.1' in ips:
+ ips.remove('127.0.0.1')
+
+ num = 3
+ for ip in ips:
+ out = self.host_session.send_expect(
+ 'ping -c %d %s' % (num, ip), '# ')
+ if '0% packet loss' in out:
+ return ip
+ return ''
+
+ def __control_session(self, command, *args):
+ """
+ Use the qemu guest agent service to control VM.
+ Note:
+ :command: there are these commands as below:
+ cat, fsfreeze, fstrim, halt, ifconfig, info,\
+ ping, powerdown, reboot, shutdown, suspend
+ :args: give different args by the different commands.
+ """
+ if not self.qga_sock_path:
+ self.host_logger.info(
+ "No QGA service between host [ %s ] and guest [ %s ]" %
+ (self.host_dut.Name, self.vm_name))
+ return None
+
+ cmd_head = '~/QMP/' + \
+ "qemu-ga-client " + \
+ "--address=%s %s" % \
+ (self.qga_sock_path, command)
+
+ cmd = cmd_head
+ for arg in args:
+ cmd = cmd_head + ' ' + str(arg)
+
+ out = self.host_session.send_expect(cmd, '# ')
+
+ return out
+
+ def stop(self):
+ """
+ Stop VM.
+ """
+ self.__control_session('powerdown')
+ time.sleep(5)
+ self.virt_pool.free_all_resource(self.vm_name)
+
+
+if __name__ == "__main__":
+ import subprocess
+ import sys
+ from serializer import Serializer
+ from crbs import crbs
+ from tester import Tester
+ from dut import Dut
+ import dts
+ from virt_proxy import VirtProxy
+
+ command = "ifconfig br0"
+ subp = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
+ subp.wait()
+
+ intf_info = subp.stdout.readlines()
+ for line_info in intf_info:
+ regx = re.search(r'inet (\d+\.\d+\.\d+\.\d+)', line_info)
+ if regx:
+ dutIP = regx.group(1)
+ break
+
+ print "DEBUG: dutIp: ", dutIP
+
+ # look up in crbs - to find the matching IP
+ crbInst = None
+ for crb in crbs:
+ if crb['IP'] == dutIP:
+ crbInst = crb
+ break
+
+ # only run on the dut in known crbs
+ if crbInst is None:
+ raise Exception("No available crb instance!!!")
+
+ # initialize the dut and tester
+ serializer = Serializer()
+ serializer.set_serialized_filename('../.%s.cache' % crbInst['IP'])
+ serializer.load_from_file()
+
+ read_cache = None
+ skip_setup = None
+
+ project = "dpdk"
+ dts.Package = 'dep/dpdk.tar.gz'
+ dut = dts.get_project_obj(project, Dut, crbInst, serializer)
+ tester = dts.get_project_obj(project, Tester, crbInst, serializer)
+ dut.tester = tester
+ dut.base_dir = 'dpdk'
+ dut.set_nic_type('niantic')
+ tester.dut = dut
+
+ tester.set_test_types(True, False)
+ dut.set_test_types(True, False)
+
+ tester.set_speedup_options(read_cache, skip_setup)
+ tester.tester_prerequisites()
+ dut.set_speedup_options(read_cache, skip_setup)
+ dut.dut_prerequisites()
+
+ # test that generating and destroying VF
+ port0 = dut.ports_info[0]['port']
+ dut.generate_sriov_vfs_by_port(0, 4)
+ print "port 0 sriov vfs: ", dut.ports_info[0]
+
+ dut.destroy_sriov_vfs_by_port(0)
+
+ time.sleep(2)
+
+ # test that binding and unbing the NIC
+ port0_pci = dut.ports_info[0]['pci']
+ port0.unbind_driver()
+
+ dut.logger.info("JUST TESTING!!!")
+
+ # Start VM by the qemu kvm config file
+ vm1 = QEMUKvm(dut, 'vm1', 'pmd_sriov')
+ print "VM config params:"
+ print vm1.params
+ vm1_dut = vm1.start()
+
+ try:
+ host_ip = vm1.session.send_expect("ifconfig", '# ')
+ print "Host IP:"
+ print host_ip
+
+ vm1_ip = vm1.get_vm_ip()
+ print "VM1 IP:"
+ print vm1_ip
+
+ print "VM1 PCI device:"
+ print vm_dut.session.send_expect('lspci -nn | grep -i eth', '# ')
+ except Exception as e:
+ print e
+ vm1_dut.stop()
+ port0.bind_driver()
+ # Stop VM
+ vm1.stop()
+ port0.bind_driver()
+
+ dut.host_logger.logger_exit()
+ dut.logger.logger_exit()
+ tester.logger.logger_exit()
+
+ print "Start and stop VM over!"
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 04/19] Add a module to manage the host resource
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (2 preceding siblings ...)
2015-05-22 9:03 ` [dts] [PATCH v2 03/19] Add QEMU KVM module based on virt_base module for KVM test cases Jiajia, Sun
@ 2015-05-22 9:03 ` Jiajia, Sun
2015-05-22 9:03 ` [dts] [PATCH v2 05/19] Add a module to instantiate the VM Jiajia, Sun
` (14 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:03 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Added module: framework/virt_resource.py
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/virt_resource.py | 490 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 490 insertions(+)
create mode 100644 framework/virt_resource.py
diff --git a/framework/virt_resource.py b/framework/virt_resource.py
new file mode 100644
index 0000000..ce60751
--- /dev/null
+++ b/framework/virt_resource.py
@@ -0,0 +1,490 @@
+#!/usr/bin/python
+# BSD LICENSE
+#
+# Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+from random import randint
+
+from utils import get_obj_funcs
+
+INIT_FREE_PORT = 6060
+
+
+class VirtResource(object):
+
+ """
+ Class handle dut resource, like cpu, memory, net devices
+ """
+
+ def __init__(self, dut):
+ self.dut = dut
+
+ self.cores = [int(core['thread']) for core in dut.cores]
+ # initialized unused cores
+ self.unused_cores = self.cores[:]
+ # initialized used cores
+ self.used_cores = [-1] * len(self.unused_cores)
+
+ self.ports_info = dut.ports_info
+ # initialized unused ports
+ self.ports = [port['pci'] for port in dut.ports_info]
+ self.unused_ports = self.ports[:]
+ # initialized used ports
+ self.used_ports = ['unused'] * len(self.unused_ports)
+
+ # initialized vf ports
+ self.vfs_info = []
+ self.vfs = []
+ self.unused_vfs = []
+ self.used_vfs = []
+
+ # save allocated cores and related vm
+ self.allocated_info = {}
+
+ def __port_used(self, pci):
+ index = self.ports.index(pci)
+ self.used_ports[index] = pci
+ self.unused_ports[index] = 'used'
+
+ def __port_unused(self, pci):
+ index = self.ports.index(pci)
+ self.unused_ports[index] = pci
+ self.used_ports[index] = 'unused'
+
+ def __port_on_socket(self, pci, socket):
+ for port in self.ports_info:
+ if port['pci'] == pci:
+ if socket is -1:
+ return True
+
+ if port['numa'] == socket:
+ return True
+ else:
+ return False
+
+ return False
+
+ def __vf_used(self, pci):
+ index = self.vfs.index(pci)
+ self.used_vfs[index] = pci
+ self.unused_vfs[index] = 'used'
+
+ def __vf_unused(self, pci):
+ index = self.vfs.index(pci)
+ self.used_vfs[index] = 'unused'
+ self.unused_vfs[index] = pci
+
+ def __core_used(self, core):
+ core = int(core)
+ index = self.cores.index(core)
+ self.used_cores[index] = core
+ self.unused_cores[index] = -1
+
+ def __core_unused(self, core):
+ core = int(core)
+ index = self.cores.index(core)
+ self.unused_cores[index] = core
+ self.used_cores[index] = -1
+
+ def __core_on_socket(self, core, socket):
+ for dut_core in self.dut.cores:
+ if int(dut_core['thread']) == core:
+ if socket is -1:
+ return True
+
+ if int(dut_core['socket']) == socket:
+ return True
+ else:
+ return False
+
+ return False
+
+ def __core_isused(self, core):
+ index = self.cores.index(core)
+ if self.used_cores[index] != -1:
+ return True
+ else:
+ return False
+
+ def reserve_cpu(self, coremask=''):
+ """
+ Reserve dpdk used cpus by mask
+ """
+ val = int(coremask, base=16)
+ cpus = []
+ index = 0
+ while val != 0:
+ if val & 0x1:
+ cpus.append(index)
+
+ val = val >> 1
+ index += 1
+
+ for cpu in cpus:
+ self.__core_used(cpu)
+
+ def alloc_cpu(self, vm='', number=-1, socket=-1, corelist=None):
+ """
+ There're two options for request cpu resouce for vm.
+ If number is not -1, just allocate cpu from not used cores.
+ If list is not None, will allocate cpu after checked.
+ """
+ cores = []
+
+ if vm == '':
+ print "Alloc cpu request vitual machine name!!!"
+ return cores
+
+ if number != -1:
+ for core in self.unused_cores:
+ if core != -1 and number != 0:
+ if self.__core_on_socket(core, socket) is True:
+ self.__core_used(core)
+ cores.append(str(core))
+ number = number - 1
+ if number != 0:
+ print "Can't allocated requested cpu!!!"
+
+ if corelist is not None:
+ for core in corelist:
+ if self.__core_isused(int(core)) is True:
+ print "Core %s has been used!!!" % core
+ else:
+ if self.__core_on_socket(int(core), socket) is True:
+ self.__core_used(int(core))
+ cores.append(core)
+
+ if vm not in self.allocated_info:
+ self.allocated_info[vm] = {}
+
+ self.allocated_info[vm]['cores'] = cores
+ return cores
+
+ def __vm_has_resource(self, vm, resource=''):
+ if vm == '':
+ self.dut.logger.info("VM name cannt be NULL!!!")
+ raise Exception("VM name cannt be NULL!!!")
+ if vm not in self.allocated_info:
+ self.dut.logger.info(
+ "There is no resource allocated to VM [%s]." % vm)
+ return False
+ if resource == '':
+ return True
+ if resource not in self.allocated_info[vm]:
+ self.dut.logger.info(
+ "There is no resource [%s] allocated to VM [%s] " %
+ (resource, vm))
+ return False
+ return True
+
+ def free_cpu(self, vm):
+ if self.__vm_has_resource(vm, 'cores'):
+ for core in self.allocated_info[vm]['cores']:
+ self.__core_unused(core)
+ self.allocated_info[vm].pop('cores')
+
+ def alloc_pf(self, vm='', number=-1, socket=-1, pflist=[]):
+ """
+ There're two options for request pf devices for vm.
+ If number is not -1, just allocate pf device from not used pfs.
+ If list is not None, will allocate pf devices after checked.
+ """
+ ports = []
+
+ if number != -1:
+ for pci in self.unused_ports:
+ if pci != 'unused' and number != 0:
+ if self.__port_on_socket(pci, socket) is True:
+ self.__port_used(pci)
+ ports.append(pci)
+ number = number - 1
+ if number != 0:
+ print "Can't allocated requested PF devices!!!"
+
+ if pflist is not None:
+ for pci in pflist:
+ if self.__port_isused(pci) is True:
+ print "Port %s has been used!!!" % pci
+ else:
+ if self.__port_on_socket(pci, socket) is True:
+ self.__port_used(core)
+ ports.append(core)
+
+ if vm not in self.allocated_info:
+ self.allocated_info[vm] = {}
+
+ self.allocated_info[vm]['ports'] = ports
+ return ports
+
+ def free_pf(self, vm):
+ if self.__vm_has_resource(vm, 'ports'):
+ for pci in self.allocated_info[vm]['ports']:
+ self.__port_unused(pci)
+ self.allocated_info[vm].pop('ports')
+
+ def alloc_vf_from_pf(self, vm='', pf_pci='', number=-1, vflist=[]):
+ """
+ There're two options for request vf devices of pf device.
+ If number is not -1, just allocate vf device from not used vfs.
+ If list is not None, will allocate vf devices after checked.
+ """
+ vfs = []
+ if vm == '':
+ print "Alloc VF request vitual machine name!!!"
+ return vfs
+
+ if pf_pci == '':
+ print "Alloc VF request PF pci address!!!"
+ return vfs
+
+ for vf_info in self.vfs_info:
+ if vf_info['pf_pci'] == pf_pci:
+ if vf_info['pci'] in vflist:
+ vfs.append(vf_info['pci'])
+ continue
+
+ if number > 0:
+ vfs.append(vf_info['pci'])
+ number = number - 1
+
+ for vf in vfs:
+ self.__vf_used(vf)
+
+ if vm not in self.allocated_info:
+ self.allocated_info[vm] = {}
+
+ self.allocated_info[vm]['vfs'] = vfs
+ return vfs
+
+ def free_vf(self, vm):
+ if self.__vm_has_resource(vm, 'vfs'):
+ for pci in self.allocated_info[vm]['vfs']:
+ self.__vf_unused(pci)
+ self.allocated_info[vm].pop('vfs')
+
+ def add_vf_on_pf(self, pf_pci='', vflist=[]):
+ """
+ Add vf devices generated by specified pf devices.
+ """
+ # add vfs into vf info list
+ vfs = []
+ for vf in vflist:
+ if vf not in self.vfs:
+ self.vfs_info.append({'pci': vf, 'pf_pci': pf_pci})
+ vfs.append(vf)
+ used_vfs = ['unused'] * len(vflist)
+ self.unused_vfs += vfs
+ self.used_vfs += used_vfs
+ self.vfs += vfs
+
+ def del_vf_on_pf(self, pf_pci='', vflist=[]):
+ """
+ Remove vf devices generated by specified pf devices.
+ """
+ vfs = []
+ for vf in vflist:
+ for vfs_info in self.vfs_info:
+ if vfs_info['pci'] == vf:
+ vfs.append(vf)
+
+ for vf in vfs:
+ try:
+ index = self.vfs.index(vf)
+ except:
+ continue
+ del self.vfs_info[index]
+ del self.unused_vfs[index]
+ del self.used_vfs[index]
+ del self.vfs[index]
+
+ def alloc_port(self, vm=''):
+ """
+ Allocate unused host port for vm
+ """
+ if vm == '':
+ print "Alloc host port request vitual machine name!!!"
+ return None
+
+ port_start = INIT_FREE_PORT + randint(1, 100)
+ port_step = randint(1, 10)
+ port = None
+ count = 20
+ while True:
+ if self.dut.check_port_occupied(port_start) is False:
+ port = port_start
+ break
+ count -= 1
+ if count < 0:
+ print 'No available port on the host!!!'
+ break
+ port_start += port_step
+
+ if vm not in self.allocated_info:
+ self.allocated_info[vm] = {}
+
+ self.allocated_info[vm]['hostport'] = port
+ return port
+
+ def free_port(self, vm):
+ if self.__vm_has_resource(vm, 'hostport'):
+ self.allocated_info[vm].pop('hostport')
+
+ def alloc_vnc_num(self, vm=''):
+ """
+ Allocate unused host VNC display number for VM.
+ """
+ if vm == '':
+ print "Alloc vnc display number request vitual machine name!!!"
+ return None
+
+ max_vnc_display_num = self.dut.get_maximal_vnc_num()
+ free_vnc_display_num = max_vnc_display_num + 1
+
+ if vm not in self.allocated_info:
+ self.allocated_info[vm] = {}
+
+ self.allocated_info[vm]['vnc_display_num'] = free_vnc_display_num
+
+ return free_vnc_display_num
+
+ def free_vnc_num(self, vm):
+ if self.__vm_has_resource(vm, 'vnc_display_num'):
+ self.allocated_info[vm].pop('vnc_display_num')
+
+ def free_all_resource(self, vm):
+ """
+ Free all resource VM has been allocated.
+ """
+ self.free_port(vm)
+ self.free_vnc_num(vm)
+ self.free_vf(vm)
+ self.free_pf(vm)
+ self.free_cpu(vm)
+
+ if self.__vm_has_resource(vm):
+ self.allocated_info.pop(vm)
+
+ def get_cpu_on_vm(self, vm=''):
+ """
+ Return core list on specifid VM.
+ """
+ if vm in self.allocated_info:
+ if "cores" in self.allocated_info[vm]:
+ return self.allocated_info[vm]['cores']
+
+ def get_vfs_on_vm(self, vm=''):
+ """
+ Return vf device list on specifid VM.
+ """
+ if vm in self.allocated_info:
+ if 'vfs' in self.allocated_info[vm]:
+ return self.allocated_info[vm]['vfs']
+
+ def get_pfs_on_vm(self, vm=''):
+ """
+ Return pf device list on specifid VM.
+ """
+ if vm in self.allocated_info:
+ if 'ports' in self.allocated_info[vm]:
+ return self.allocated_info[vm]['ports']
+
+
+class simple_dut(object):
+
+ def __init__(self):
+ self.ports_info = []
+ self.cores = []
+
+ def check_port_occupied(self, port):
+ return False
+
+if __name__ == "__main__":
+ dut = simple_dut()
+ dut.cores = [{'thread': '1', 'socket': '0'}, {'thread': '2', 'socket': '0'},
+ {'thread': '3', 'socket': '0'}, {'thread': '4', 'socket': '0'},
+ {'thread': '5', 'socket': '0'}, {'thread': '6', 'socket': '0'},
+ {'thread': '7', 'socket': '1'}, {'thread': '8', 'socket': '1'},
+ {'thread': '9', 'socket': '1'}, {'thread': '10', 'socket': '1'},
+ {'thread': '11', 'socket': '1'}, {'thread': '12', 'socket': '1'}]
+
+ dut.ports_info = [{'intf': 'p786p1', 'source': 'cfg', 'mac': '90:e2:ba:69:e5:e4',
+ 'pci': '08:00.0', 'numa': 0, 'ipv6': 'fe80::92e2:baff:fe69:e5e4',
+ 'peer': 'IXIA:6.5', 'type': '8086:10fb'},
+ {'intf': 'p786p2', 'source': 'cfg', 'mac': '90:e2:ba:69:e5:e5',
+ 'pci': '08:00.1', 'numa': 0, 'ipv6': 'fe80::92e2:baff:fe69:e5e5',
+ 'peer': 'IXIA:6.6', 'type': '8086:10fb'},
+ {'intf': 'p787p1', 'source': 'cfg', 'mac': '90:e2:ba:69:e5:e6',
+ 'pci': '84:00.0', 'numa': 1, 'ipv6': 'fe80::92e2:baff:fe69:e5e6',
+ 'peer': 'IXIA:6.7', 'type': '8086:10fb'},
+ {'intf': 'p787p2', 'source': 'cfg', 'mac': '90:e2:ba:69:e5:e7',
+ 'pci': '84:00.1', 'numa': 1, 'ipv6': 'fe80::92e2:baff:fe69:e5e7',
+ 'peer': 'IXIA:6.8', 'type': '8086:10fb'}]
+
+ virt_pool = VirtResource(dut)
+ print "Alloc two PF devices on socket 1 from VM"
+ print virt_pool.alloc_pf(vm='test1', number=2, socket=1)
+
+ virt_pool.add_vf_on_pf(pf_pci='08:00.0', vflist=[
+ '08:10.0', '08:10.2', '08:10.4', '08:10.6'])
+ virt_pool.add_vf_on_pf(pf_pci='08:00.1', vflist=[
+ '08:10.1', '08:10.3', '08:10.5', '08:10.7'])
+ print "Add VF devices to resource pool"
+ print virt_pool.vfs_info
+
+ print "Alloc VF device from resource pool"
+ print virt_pool.alloc_vf_from_pf(vm='test1', pf_pci='08:00.0', number=2)
+ print virt_pool.used_vfs
+ print "Alloc VF device from resource pool"
+ print virt_pool.alloc_vf_from_pf(vm='test2', pf_pci='08:00.1', vflist=['08:10.3', '08:10.5'])
+ print virt_pool.used_vfs
+
+ print "Del VF devices from resource pool"
+ virt_pool.del_vf_on_pf(pf_pci='08:00.0', vflist=['08:10.4', '08:10.2'])
+ print virt_pool.vfs_info
+
+ virt_pool.reserve_cpu('e')
+ print "Reserve three cores from resource pool"
+ print virt_pool.unused_cores
+ print "Alloc two cores on socket1 for VM-test1"
+ print virt_pool.alloc_cpu(vm="test1", number=2, socket=1)
+ print "Alloc two cores in list for VM-test2"
+ print virt_pool.alloc_cpu(vm="test2", corelist=['4', '5'])
+ print "Alloc two cores for VM-test3"
+ print virt_pool.alloc_cpu(vm="test3", number=2)
+ print "Alloc port for VM-test1"
+ print virt_pool.alloc_port(vm='test1')
+ print "Alloc information after allcated"
+ print virt_pool.allocated_info
+
+ print "Get cores on VM-test1"
+ print virt_pool.get_cpu_on_vm("test1")
+ print "Get pfs on VM-test1"
+ print virt_pool.get_pfs_on_vm("test1")
+ print "Get vfs on VM-test2"
+ print virt_pool.get_vfs_on_vm("test2")
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 05/19] Add a module to instantiate the VM
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (3 preceding siblings ...)
2015-05-22 9:03 ` [dts] [PATCH v2 04/19] Add a module to manage the host resource Jiajia, Sun
@ 2015-05-22 9:03 ` Jiajia, Sun
2015-05-25 6:10 ` Qiu, Michael
2015-05-22 9:03 ` [dts] [PATCH v2 06/19] Add a third-party module of qemu-guest-agent to manage VM Jiajia, Sun
` (13 subsequent siblings)
18 siblings, 1 reply; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:03 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Added module: virt_dut.py
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/virt_dut.py | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 202 insertions(+)
create mode 100644 framework/virt_dut.py
diff --git a/framework/virt_dut.py b/framework/virt_dut.py
new file mode 100644
index 0000000..273b29e
--- /dev/null
+++ b/framework/virt_dut.py
@@ -0,0 +1,202 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+import re
+import time
+import dts
+import settings
+from config import PortConf
+from settings import NICS, LOG_NAME_SEP
+from ssh_connection import SSHConnection
+from project_dpdk import DPDKdut
+from dut import Dut
+from net_device import NetDevice
+from logger import getLogger
+
+
+class VirtDut(DPDKdut):
+
+ """
+ A connection to the CRB under test.
+ This class sends commands to the CRB and validates the responses. It is
+ implemented using either ssh for linuxapp or the terminal server for
+ baremetal.
+ All operations are in fact delegated to an instance of either CRBLinuxApp
+ or CRBBareMetal.
+ """
+
+ def __init__(self, crb, serializer, vm_name, suite):
+ super(Dut, self).__init__(crb, serializer)
+ self.vm_ip = self.get_ip_address()
+ self.NAME = 'virtdut' + LOG_NAME_SEP + '%s' % self.vm_ip
+ # load port config from suite cfg
+ self.suite = suite
+ self.logger = getLogger(self.NAME)
+ self.logger.config_execution('vmdut')
+ self.session = SSHConnection(self.vm_ip, self.NAME,
+ self.get_password())
+ self.session.init_log(self.logger)
+
+ # if redirect ssh port, there's only one session enabled
+ self.alt_session = SSHConnection(self.vm_ip, self.NAME + '_alt',
+ self.get_password())
+ self.alt_session.init_log(self.logger)
+
+ self.number_of_cores = 0
+ self.tester = None
+ self.cores = []
+ self.architecture = None
+ self.ports_info = None
+ self.ports_map = []
+
+ def set_nic_type(self, nic_type):
+ """
+ Set CRB NICS ready to validated.
+ """
+ self.nic_type = nic_type
+ # vm_dut config will load from vm configuration file
+
+ def load_portconf(self):
+ """
+ Load port config for this virtual machine
+ """
+ return
+
+ def set_target(self, target):
+ """
+ Set env variable, these have to be setup all the time. Some tests
+ need to compile example apps by themselves and will fail otherwise.
+ Set hugepage on DUT and install modules required by DPDK.
+ Configure default ixgbe PMD function.
+ """
+ self.set_toolchain(target)
+
+ # set env variable
+ # These have to be setup all the time. Some tests need to compile
+ # example apps by themselves and will fail otherwise.
+ self.send_expect("export RTE_TARGET=" + target, "#")
+ self.send_expect("export RTE_SDK=`pwd`", "#")
+
+ if not self.skip_setup:
+ self.build_install_dpdk(target)
+
+ self.setup_memory(hugepages=512)
+ self.setup_modules(target)
+
+ self.bind_interfaces_linux('igb_uio')
+
+ def prerequisites(self, pkgName, patch):
+ """
+ Prerequest function should be called before execute any test case.
+ Will call function to scan all lcore's information which on DUT.
+ Then call pci scan function to collect nic device information.
+ At last setup DUT' environment for validation.
+ """
+ self.prepare_package(pkgName, patch)
+
+ self.send_expect("cd %s" % self.base_dir, "# ")
+ self.host_session.send_expect("cd %s" % self.base_dir, "# ")
+ self.send_expect("alias ls='ls --color=none'", "#")
+
+ self.init_core_list()
+ self.pci_devices_information()
+
+ # scan ports before restore interface
+ self.scan_ports()
+ # restore dut ports to kernel
+ self.restore_interfaces()
+ # rescan ports after interface up
+ self.rescan_ports()
+
+ # no need to rescan ports for guest os just bootup
+ # load port infor from config file
+ self.load_portconf()
+
+ # enable tester port ipv6
+ self.host_dut.enable_tester_ipv6()
+ self.mount_procfs()
+ # auto detect network topology
+ self.map_available_ports()
+ # disable tester port ipv6
+ self.host_dut.disable_tester_ipv6()
+
+ # print latest ports_info
+ for port_info in self.ports_info:
+ self.logger.info(port_info)
+
+ def pci_devices_information(self):
+ self.pci_devices_information_uncached()
+
+ def get_memory_channels(self):
+ """
+ Virtual machine has no memory channel concept, so always return 1
+ """
+ return 1
+
+ def check_ports_available(self, pci_bus, pci_id):
+ """
+ Check that whether auto scanned ports ready to use
+ """
+ pci_addr = "%s:%s" % (pci_bus, pci_id)
+ if pci_id == "8086:100e":
+ return False
+ return True
+
+ def scan_ports(self):
+ """
+ Scan ports information, for vm will always scan
+ """
+ self.scan_ports_uncached()
+
+ def scan_ports_uncached(self):
+ """
+ Scan ports and collect port's pci id, mac adress, ipv6 address.
+ """
+ scan_ports_uncached = getattr(
+ self, 'scan_ports_uncached_%s' % self.get_os_type())
+ return scan_ports_uncached()
+
+ def map_available_ports(self):
+ """
+ Load or generate network connection mapping list.
+ """
+ self.map_available_ports_uncached()
+ self.logger.warning("DUT PORT MAP: " + str(self.ports_map))
+
+ def send_ping6(self, localPort, ipv6, mac=''):
+ """
+ Send ping6 packet from local port with destination ipv6 address.
+ """
+ if self.ports_info[localPort]['type'] == 'ixia':
+ pass
+ else:
+ return self.send_expect("ping6 -w 1 -c 1 -A -I %s %s" % (self.ports_info[localPort]['intf'], ipv6), "# ", 10)
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [dts] [PATCH v2 05/19] Add a module to instantiate the VM
2015-05-22 9:03 ` [dts] [PATCH v2 05/19] Add a module to instantiate the VM Jiajia, Sun
@ 2015-05-25 6:10 ` Qiu, Michael
2015-05-25 9:14 ` Jiajia, SunX
0 siblings, 1 reply; 24+ messages in thread
From: Qiu, Michael @ 2015-05-25 6:10 UTC (permalink / raw)
To: Jiajia, SunX, dts
On 5/22/2015 5:04 PM, Jiajia, Sun wrote:
> From: sjiajiax <sunx.jiajia@intel.com>
>
> Added module: virt_dut.py
>
> Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
> ---
> framework/virt_dut.py | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 202 insertions(+)
> create mode 100644 framework/virt_dut.py
>
> diff --git a/framework/virt_dut.py b/framework/virt_dut.py
> new file mode 100644
> index 0000000..273b29e
> --- /dev/null
> +++ b/framework/virt_dut.py
> @@ -0,0 +1,202 @@
> +# BSD LICENSE
> +#
> +# Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
> +# All rights reserved.
> +#
> +# Redistribution and use in source and binary forms, with or without
> +# modification, are permitted provided that the following conditions
> +# are met:
> +#
> +# * Redistributions of source code must retain the above copyright
> +# notice, this list of conditions and the following disclaimer.
> +# * Redistributions in binary form must reproduce the above copyright
> +# notice, this list of conditions and the following disclaimer in
> +# the documentation and/or other materials provided with the
> +# distribution.
> +# * Neither the name of Intel Corporation nor the names of its
> +# contributors may be used to endorse or promote products derived
> +# from this software without specific prior written permission.
> +#
> +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +import os
> +import re
> +import time
> +import dts
> +import settings
> +from config import PortConf
> +from settings import NICS, LOG_NAME_SEP
> +from ssh_connection import SSHConnection
> +from project_dpdk import DPDKdut
> +from dut import Dut
> +from net_device import NetDevice
> +from logger import getLogger
> +
> +
> +class VirtDut(DPDKdut):
> +
> + """
> + A connection to the CRB under test.
> + This class sends commands to the CRB and validates the responses. It is
> + implemented using either ssh for linuxapp or the terminal server for
> + baremetal.
> + All operations are in fact delegated to an instance of either CRBLinuxApp
> + or CRBBareMetal.
> + """
> +
> + def __init__(self, crb, serializer, vm_name, suite):
> + super(Dut, self).__init__(crb, serializer)
> + self.vm_ip = self.get_ip_address()
> + self.NAME = 'virtdut' + LOG_NAME_SEP + '%s' % self.vm_ip
> + # load port config from suite cfg
> + self.suite = suite
> + self.logger = getLogger(self.NAME)
> + self.logger.config_execution('vmdut')
> + self.session = SSHConnection(self.vm_ip, self.NAME,
> + self.get_password())
> + self.session.init_log(self.logger)
> +
> + # if redirect ssh port, there's only one session enabled
> + self.alt_session = SSHConnection(self.vm_ip, self.NAME + '_alt',
> + self.get_password())
> + self.alt_session.init_log(self.logger)
> +
> + self.number_of_cores = 0
> + self.tester = None
> + self.cores = []
> + self.architecture = None
> + self.ports_info = None
> + self.ports_map = []
> +
> + def set_nic_type(self, nic_type):
> + """
> + Set CRB NICS ready to validated.
> + """
> + self.nic_type = nic_type
> + # vm_dut config will load from vm configuration file
> +
> + def load_portconf(self):
> + """
> + Load port config for this virtual machine
> + """
> + return
> +
> + def set_target(self, target):
> + """
> + Set env variable, these have to be setup all the time. Some tests
> + need to compile example apps by themselves and will fail otherwise.
> + Set hugepage on DUT and install modules required by DPDK.
> + Configure default ixgbe PMD function.
> + """
> + self.set_toolchain(target)
> +
> + # set env variable
> + # These have to be setup all the time. Some tests need to compile
> + # example apps by themselves and will fail otherwise.
> + self.send_expect("export RTE_TARGET=" + target, "#")
> + self.send_expect("export RTE_SDK=`pwd`", "#")
Could "RTE_SDK" be configed in config file?
> +
> + if not self.skip_setup:
> + self.build_install_dpdk(target)
> +
> + self.setup_memory(hugepages=512)
> + self.setup_modules(target)
> +
> + self.bind_interfaces_linux('igb_uio')
> +
> + def prerequisites(self, pkgName, patch):
> + """
> + Prerequest function should be called before execute any test case.
> + Will call function to scan all lcore's information which on DUT.
> + Then call pci scan function to collect nic device information.
> + At last setup DUT' environment for validation.
> + """
> + self.prepare_package(pkgName, patch)
> +
> + self.send_expect("cd %s" % self.base_dir, "# ")
> + self.host_session.send_expect("cd %s" % self.base_dir, "# ")
> + self.send_expect("alias ls='ls --color=none'", "#")
> +
> + self.init_core_list()
> + self.pci_devices_information()
> +
> + # scan ports before restore interface
> + self.scan_ports()
> + # restore dut ports to kernel
> + self.restore_interfaces()
> + # rescan ports after interface up
> + self.rescan_ports()
> +
> + # no need to rescan ports for guest os just bootup
> + # load port infor from config file
> + self.load_portconf()
> +
> + # enable tester port ipv6
> + self.host_dut.enable_tester_ipv6()
> + self.mount_procfs()
> + # auto detect network topology
> + self.map_available_ports()
> + # disable tester port ipv6
> + self.host_dut.disable_tester_ipv6()
> +
> + # print latest ports_info
> + for port_info in self.ports_info:
> + self.logger.info(port_info)
> +
> + def pci_devices_information(self):
> + self.pci_devices_information_uncached()
> +
> + def get_memory_channels(self):
> + """
> + Virtual machine has no memory channel concept, so always return 1
> + """
> + return 1
> +
> + def check_ports_available(self, pci_bus, pci_id):
> + """
> + Check that whether auto scanned ports ready to use
> + """
> + pci_addr = "%s:%s" % (pci_bus, pci_id)
> + if pci_id == "8086:100e":
> + return False
Why here return false? better to give some comments.
Also pci_id here should be pci_addr I think.
> + return True
> +
> + def scan_ports(self):
> + """
> + Scan ports information, for vm will always scan
> + """
> + self.scan_ports_uncached()
> +
> + def scan_ports_uncached(self):
> + """
> + Scan ports and collect port's pci id, mac adress, ipv6 address.
> + """
> + scan_ports_uncached = getattr(
> + self, 'scan_ports_uncached_%s' % self.get_os_type())
> + return scan_ports_uncached()
> +
> + def map_available_ports(self):
> + """
> + Load or generate network connection mapping list.
> + """
> + self.map_available_ports_uncached()
> + self.logger.warning("DUT PORT MAP: " + str(self.ports_map))
> +
> + def send_ping6(self, localPort, ipv6, mac=''):
> + """
> + Send ping6 packet from local port with destination ipv6 address.
> + """
> + if self.ports_info[localPort]['type'] == 'ixia':
> + pass
> + else:
> + return self.send_expect("ping6 -w 1 -c 1 -A -I %s %s" % (self.ports_info[localPort]['intf'], ipv6), "# ", 10)
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [dts] [PATCH v2 05/19] Add a module to instantiate the VM
2015-05-25 6:10 ` Qiu, Michael
@ 2015-05-25 9:14 ` Jiajia, SunX
2015-05-26 9:07 ` Qiu, Michael
0 siblings, 1 reply; 24+ messages in thread
From: Jiajia, SunX @ 2015-05-25 9:14 UTC (permalink / raw)
To: Qiu, Michael, dts
Hi Michael,
Please see the comments below.
> -----Original Message-----
> From: Qiu, Michael
> Sent: Monday, May 25, 2015 2:11 PM
> To: Jiajia, SunX; dts@dpdk.org
> Subject: Re: [dts] [PATCH v2 05/19] Add a module to instantiate the VM
>
> On 5/22/2015 5:04 PM, Jiajia, Sun wrote:
> > From: sjiajiax <sunx.jiajia@intel.com>
> >
> > Added module: virt_dut.py
> >
> > Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
> > ---
> > framework/virt_dut.py | 202
> ++++++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 202 insertions(+)
> > create mode 100644 framework/virt_dut.py
> >
> > diff --git a/framework/virt_dut.py b/framework/virt_dut.py
> > new file mode 100644
> > index 0000000..273b29e
> > --- /dev/null
> > +++ b/framework/virt_dut.py
> > @@ -0,0 +1,202 @@
> > +# BSD LICENSE
> > +#
> > +# Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
> > +# All rights reserved.
> > +#
> > +# Redistribution and use in source and binary forms, with or without
> > +# modification, are permitted provided that the following conditions
> > +# are met:
> > +#
> > +# * Redistributions of source code must retain the above copyright
> > +# notice, this list of conditions and the following disclaimer.
> > +# * Redistributions in binary form must reproduce the above
> copyright
> > +# notice, this list of conditions and the following disclaimer
> in
> > +# the documentation and/or other materials provided with the
> > +# distribution.
> > +# * Neither the name of Intel Corporation nor the names of its
> > +# contributors may be used to endorse or promote products
> derived
> > +# from this software without specific prior written permission.
> > +#
> > +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS
> > +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> > +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
> FOR
> > +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> > +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> > +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> > +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
> USE,
> > +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
> ANY
> > +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> TORT
> > +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> USE
> > +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> > +
> > +import os
> > +import re
> > +import time
> > +import dts
> > +import settings
> > +from config import PortConf
> > +from settings import NICS, LOG_NAME_SEP
> > +from ssh_connection import SSHConnection
> > +from project_dpdk import DPDKdut
> > +from dut import Dut
> > +from net_device import NetDevice
> > +from logger import getLogger
> > +
> > +
> > +class VirtDut(DPDKdut):
> > +
> > + """
> > + A connection to the CRB under test.
> > + This class sends commands to the CRB and validates the responses.
> It is
> > + implemented using either ssh for linuxapp or the terminal server
> for
> > + baremetal.
> > + All operations are in fact delegated to an instance of either
> CRBLinuxApp
> > + or CRBBareMetal.
> > + """
> > +
> > + def __init__(self, crb, serializer, vm_name, suite):
> > + super(Dut, self).__init__(crb, serializer)
> > + self.vm_ip = self.get_ip_address()
> > + self.NAME = 'virtdut' + LOG_NAME_SEP + '%s' % self.vm_ip
> > + # load port config from suite cfg
> > + self.suite = suite
> > + self.logger = getLogger(self.NAME)
> > + self.logger.config_execution('vmdut')
> > + self.session = SSHConnection(self.vm_ip, self.NAME,
> > + self.get_password())
> > + self.session.init_log(self.logger)
> > +
> > + # if redirect ssh port, there's only one session enabled
> > + self.alt_session = SSHConnection(self.vm_ip, self.NAME +
> '_alt',
> > + self.get_password())
> > + self.alt_session.init_log(self.logger)
> > +
> > + self.number_of_cores = 0
> > + self.tester = None
> > + self.cores = []
> > + self.architecture = None
> > + self.ports_info = None
> > + self.ports_map = []
> > +
> > + def set_nic_type(self, nic_type):
> > + """
> > + Set CRB NICS ready to validated.
> > + """
> > + self.nic_type = nic_type
> > + # vm_dut config will load from vm configuration file
> > +
> > + def load_portconf(self):
> > + """
> > + Load port config for this virtual machine
> > + """
> > + return
> > +
> > + def set_target(self, target):
> > + """
> > + Set env variable, these have to be setup all the time. Some
> tests
> > + need to compile example apps by themselves and will fail
> otherwise.
> > + Set hugepage on DUT and install modules required by DPDK.
> > + Configure default ixgbe PMD function.
> > + """
> > + self.set_toolchain(target)
> > +
> > + # set env variable
> > + # These have to be setup all the time. Some tests need to
> compile
> > + # example apps by themselves and will fail otherwise.
> > + self.send_expect("export RTE_TARGET=" + target, "#")
> > + self.send_expect("export RTE_SDK=`pwd`", "#")
>
> Could "RTE_SDK" be configed in config file?
Now it cannot be configured in the configure file, but I think if it is
needed, doing some changes will be okay.
>
> > +
> > + if not self.skip_setup:
> > + self.build_install_dpdk(target)
> > +
> > + self.setup_memory(hugepages=512)
> > + self.setup_modules(target)
> > +
> > + self.bind_interfaces_linux('igb_uio')
> > +
> > + def prerequisites(self, pkgName, patch):
> > + """
> > + Prerequest function should be called before execute any test
> case.
> > + Will call function to scan all lcore's information which on
> DUT.
> > + Then call pci scan function to collect nic device
> information.
> > + At last setup DUT' environment for validation.
> > + """
> > + self.prepare_package(pkgName, patch)
> > +
> > + self.send_expect("cd %s" % self.base_dir, "# ")
> > + self.host_session.send_expect("cd %s" % self.base_dir, "# ")
> > + self.send_expect("alias ls='ls --color=none'", "#")
> > +
> > + self.init_core_list()
> > + self.pci_devices_information()
> > +
> > + # scan ports before restore interface
> > + self.scan_ports()
> > + # restore dut ports to kernel
> > + self.restore_interfaces()
> > + # rescan ports after interface up
> > + self.rescan_ports()
> > +
> > + # no need to rescan ports for guest os just bootup
> > + # load port infor from config file
> > + self.load_portconf()
> > +
> > + # enable tester port ipv6
> > + self.host_dut.enable_tester_ipv6()
> > + self.mount_procfs()
> > + # auto detect network topology
> > + self.map_available_ports()
> > + # disable tester port ipv6
> > + self.host_dut.disable_tester_ipv6()
> > +
> > + # print latest ports_info
> > + for port_info in self.ports_info:
> > + self.logger.info(port_info)
> > +
> > + def pci_devices_information(self):
> > + self.pci_devices_information_uncached()
> > +
> > + def get_memory_channels(self):
> > + """
> > + Virtual machine has no memory channel concept, so always
> return 1
> > + """
> > + return 1
> > +
> > + def check_ports_available(self, pci_bus, pci_id):
> > + """
> > + Check that whether auto scanned ports ready to use
> > + """
> > + pci_addr = "%s:%s" % (pci_bus, pci_id)
> > + if pci_id == "8086:100e":
> > + return False
>
> Why here return false? better to give some comments.
>
> Also pci_id here should be pci_addr I think.
Because the e1000 network is commonly the control port for tester,
So it will be ignored defaultly.
>
> > + return True
> > +
> > + def scan_ports(self):
> > + """
> > + Scan ports information, for vm will always scan
> > + """
> > + self.scan_ports_uncached()
> > +
> > + def scan_ports_uncached(self):
> > + """
> > + Scan ports and collect port's pci id, mac adress, ipv6
> address.
> > + """
> > + scan_ports_uncached = getattr(
> > + self, 'scan_ports_uncached_%s' % self.get_os_type())
> > + return scan_ports_uncached()
> > +
> > + def map_available_ports(self):
> > + """
> > + Load or generate network connection mapping list.
> > + """
> > + self.map_available_ports_uncached()
> > + self.logger.warning("DUT PORT MAP: " + str(self.ports_map))
> > +
> > + def send_ping6(self, localPort, ipv6, mac=''):
> > + """
> > + Send ping6 packet from local port with destination ipv6
> address.
> > + """
> > + if self.ports_info[localPort]['type'] == 'ixia':
> > + pass
> > + else:
> > + return self.send_expect("ping6 -w 1 -c 1 -A -I %s %s" %
> (self.ports_info[localPort]['intf'], ipv6), "# ", 10)
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [dts] [PATCH v2 05/19] Add a module to instantiate the VM
2015-05-25 9:14 ` Jiajia, SunX
@ 2015-05-26 9:07 ` Qiu, Michael
2015-05-27 1:36 ` Jiajia, SunX
0 siblings, 1 reply; 24+ messages in thread
From: Qiu, Michael @ 2015-05-26 9:07 UTC (permalink / raw)
To: Jiajia, SunX, dts
On 5/25/2015 5:14 PM, Jiajia, SunX wrote:
> Hi Michael,
>
> Please see the comments below.
>
>> -----Original Message-----
>> From: Qiu, Michael
>> Sent: Monday, May 25, 2015 2:11 PM
>> To: Jiajia, SunX; dts@dpdk.org
>> Subject: Re: [dts] [PATCH v2 05/19] Add a module to instantiate the VM
>>
>> On 5/22/2015 5:04 PM, Jiajia, Sun wrote:
>>> From: sjiajiax <sunx.jiajia@intel.com>
...
>>> + return 1
>>> +
>>> + def check_ports_available(self, pci_bus, pci_id):
>>> + """
>>> + Check that whether auto scanned ports ready to use
>>> + """
>>> + pci_addr = "%s:%s" % (pci_bus, pci_id)
>>> + if pci_id == "8086:100e":
>>> + return False
>> Why here return false? better to give some comments.
>>
>> Also pci_id here should be pci_addr I think.
> Because the e1000 network is commonly the control port for tester,
> So it will be ignored defaultly.
Does pci_addr needed here? It do nothing.
Thanks,
Michael
>
>>> + return True
>>> +
>>> + def scan_ports(self):
>>> + """
>>> + Scan ports information, for vm will always scan
>>> + """
>>> + self.scan_ports_uncached()
>>> +
>>> + def scan_ports_uncached(self):
>>> + """
>>> + Scan ports and collect port's pci id, mac adress, ipv6
>>
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [dts] [PATCH v2 05/19] Add a module to instantiate the VM
2015-05-26 9:07 ` Qiu, Michael
@ 2015-05-27 1:36 ` Jiajia, SunX
0 siblings, 0 replies; 24+ messages in thread
From: Jiajia, SunX @ 2015-05-27 1:36 UTC (permalink / raw)
To: Qiu, Michael, dts
> -----Original Message-----
> From: Qiu, Michael
> Sent: Tuesday, May 26, 2015 5:07 PM
> To: Jiajia, SunX; dts@dpdk.org
> Subject: Re: [dts] [PATCH v2 05/19] Add a module to instantiate the VM
>
> On 5/25/2015 5:14 PM, Jiajia, SunX wrote:
> > Hi Michael,
> >
> > Please see the comments below.
> >
> >> -----Original Message-----
> >> From: Qiu, Michael
> >> Sent: Monday, May 25, 2015 2:11 PM
> >> To: Jiajia, SunX; dts@dpdk.org
> >> Subject: Re: [dts] [PATCH v2 05/19] Add a module to instantiate the
> VM
> >>
> >> On 5/22/2015 5:04 PM, Jiajia, Sun wrote:
> >>> From: sjiajiax <sunx.jiajia@intel.com>
>
> ...
>
> >>> + return 1
> >>> +
> >>> + def check_ports_available(self, pci_bus, pci_id):
> >>> + """
> >>> + Check that whether auto scanned ports ready to use
> >>> + """
> >>> + pci_addr = "%s:%s" % (pci_bus, pci_id)
> >>> + if pci_id == "8086:100e":
> >>> + return False
> >> Why here return false? better to give some comments.
> >>
> >> Also pci_id here should be pci_addr I think.
> > Because the e1000 network is commonly the control port for tester,
> > So it will be ignored defaultly.
>
> Does pci_addr needed here? It do nothing.
Yes, it does nothing, it should be removed, I will change it next version.
>
> Thanks,
> Michael
> >
> >>> + return True
> >>> +
> >>> + def scan_ports(self):
> >>> + """
> >>> + Scan ports information, for vm will always scan
> >>> + """
> >>> + self.scan_ports_uncached()
> >>> +
> >>> + def scan_ports_uncached(self):
> >>> + """
> >>> + Scan ports and collect port's pci id, mac adress, ipv6
> >>
> >
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 06/19] Add a third-party module of qemu-guest-agent to manage VM
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (4 preceding siblings ...)
2015-05-22 9:03 ` [dts] [PATCH v2 05/19] Add a module to instantiate the VM Jiajia, Sun
@ 2015-05-22 9:03 ` Jiajia, Sun
2015-05-22 9:04 ` [dts] [PATCH v2 07/19] Move some general functions from dts.py to utils.py and settings.py Jiajia, Sun
` (12 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:03 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Added module: dep/QMP
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
dep/QMP/qemu-ga-client | 299 +++++++++++++++++++++++++++++++++++++++++++++++++
dep/QMP/qmp.py | 193 +++++++++++++++++++++++++++++++
2 files changed, 492 insertions(+)
create mode 100644 dep/QMP/qemu-ga-client
create mode 100644 dep/QMP/qmp.py
diff --git a/dep/QMP/qemu-ga-client b/dep/QMP/qemu-ga-client
new file mode 100644
index 0000000..46676c3
--- /dev/null
+++ b/dep/QMP/qemu-ga-client
@@ -0,0 +1,299 @@
+#!/usr/bin/python
+
+# QEMU Guest Agent Client
+#
+# Copyright (C) 2012 Ryota Ozaki <ozaki.ryota@gmail.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2. See
+# the COPYING file in the top-level directory.
+#
+# Usage:
+#
+# Start QEMU with:
+#
+# # qemu [...] -chardev socket,path=/tmp/qga.sock,server,nowait,id=qga0 \
+# -device virtio-serial -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0
+#
+# Run the script:
+#
+# $ qemu-ga-client --address=/tmp/qga.sock <command> [args...]
+#
+# or
+#
+# $ export QGA_CLIENT_ADDRESS=/tmp/qga.sock
+# $ qemu-ga-client <command> [args...]
+#
+# For example:
+#
+# $ qemu-ga-client cat /etc/resolv.conf
+# # Generated by NetworkManager
+# nameserver 10.0.2.3
+# $ qemu-ga-client fsfreeze status
+# thawed
+# $ qemu-ga-client fsfreeze freeze
+# 2 filesystems frozen
+#
+# See also: http://wiki.qemu.org/Features/QAPI/GuestAgent
+#
+
+import base64
+import random
+
+import qmp
+
+
+class QemuGuestAgent(qmp.QEMUMonitorProtocol):
+ def __getattr__(self, name):
+ def wrapper(**kwds):
+ return self.command('guest-' + name.replace('_', '-'), **kwds)
+ return wrapper
+
+
+class QemuGuestAgentClient:
+ error = QemuGuestAgent.error
+
+ def __init__(self, address):
+ self.qga = QemuGuestAgent(address)
+ self.qga.connect(negotiate=False)
+
+ def sync(self, timeout=3):
+ # Avoid being blocked forever
+ if not self.ping(timeout):
+ raise EnvironmentError('Agent seems not alive')
+ uid = random.randint(0, (1 << 32) - 1)
+ while True:
+ ret = self.qga.sync(id=uid)
+ if isinstance(ret, int) and int(ret) == uid:
+ break
+
+ def __file_read_all(self, handle):
+ eof = False
+ data = ''
+ while not eof:
+ ret = self.qga.file_read(handle=handle, count=1024)
+ _data = base64.b64decode(ret['buf-b64'])
+ data += _data
+ eof = ret['eof']
+ return data
+
+ def read(self, path):
+ handle = self.qga.file_open(path=path)
+ try:
+ data = self.__file_read_all(handle)
+ finally:
+ self.qga.file_close(handle=handle)
+ return data
+
+ def info(self):
+ info = self.qga.info()
+
+ msgs = []
+ msgs.append('version: ' + info['version'])
+ msgs.append('supported_commands:')
+ enabled = [c['name'] for c in info['supported_commands'] if c['enabled']]
+ msgs.append('\tenabled: ' + ', '.join(enabled))
+ disabled = [c['name'] for c in info['supported_commands'] if not c['enabled']]
+ msgs.append('\tdisabled: ' + ', '.join(disabled))
+
+ return '\n'.join(msgs)
+
+ def __gen_ipv4_netmask(self, prefixlen):
+ mask = int('1' * prefixlen + '0' * (32 - prefixlen), 2)
+ return '.'.join([str(mask >> 24),
+ str((mask >> 16) & 0xff),
+ str((mask >> 8) & 0xff),
+ str(mask & 0xff)])
+
+ def ifconfig(self):
+ nifs = self.qga.network_get_interfaces()
+
+ msgs = []
+ for nif in nifs:
+ msgs.append(nif['name'] + ':')
+ if 'ip-addresses' in nif:
+ for ipaddr in nif['ip-addresses']:
+ if ipaddr['ip-address-type'] == 'ipv4':
+ addr = ipaddr['ip-address']
+ mask = self.__gen_ipv4_netmask(int(ipaddr['prefix']))
+ msgs.append("\tinet %s netmask %s" % (addr, mask))
+ elif ipaddr['ip-address-type'] == 'ipv6':
+ addr = ipaddr['ip-address']
+ prefix = ipaddr['prefix']
+ msgs.append("\tinet6 %s prefixlen %s" % (addr, prefix))
+ if nif['hardware-address'] != '00:00:00:00:00:00':
+ msgs.append("\tether " + nif['hardware-address'])
+
+ return '\n'.join(msgs)
+
+ def ping(self, timeout):
+ self.qga.settimeout(timeout)
+ try:
+ self.qga.ping()
+ except self.qga.timeout:
+ return False
+ return True
+
+ def fsfreeze(self, cmd):
+ if cmd not in ['status', 'freeze', 'thaw']:
+ raise StandardError('Invalid command: ' + cmd)
+
+ return getattr(self.qga, 'fsfreeze' + '_' + cmd)()
+
+ def fstrim(self, minimum=0):
+ return getattr(self.qga, 'fstrim')(minimum=minimum)
+
+ def suspend(self, mode):
+ if mode not in ['disk', 'ram', 'hybrid']:
+ raise StandardError('Invalid mode: ' + mode)
+
+ try:
+ getattr(self.qga, 'suspend' + '_' + mode)()
+ # On error exception will raise
+ except self.qga.timeout:
+ # On success command will timed out
+ return
+
+ def shutdown(self, mode='powerdown'):
+ if mode not in ['powerdown', 'halt', 'reboot']:
+ raise StandardError('Invalid mode: ' + mode)
+
+ try:
+ self.qga.shutdown(mode=mode)
+ except self.qga.timeout:
+ return
+
+
+def _cmd_cat(client, args):
+ if len(args) != 1:
+ print('Invalid argument')
+ print('Usage: cat <file>')
+ sys.exit(1)
+ print(client.read(args[0]))
+
+
+def _cmd_fsfreeze(client, args):
+ usage = 'Usage: fsfreeze status|freeze|thaw'
+ if len(args) != 1:
+ print('Invalid argument')
+ print(usage)
+ sys.exit(1)
+ if args[0] not in ['status', 'freeze', 'thaw']:
+ print('Invalid command: ' + args[0])
+ print(usage)
+ sys.exit(1)
+ cmd = args[0]
+ ret = client.fsfreeze(cmd)
+ if cmd == 'status':
+ print(ret)
+ elif cmd == 'freeze':
+ print("%d filesystems frozen" % ret)
+ else:
+ print("%d filesystems thawed" % ret)
+
+
+def _cmd_fstrim(client, args):
+ if len(args) == 0:
+ minimum = 0
+ else:
+ minimum = int(args[0])
+ print(client.fstrim(minimum))
+
+
+def _cmd_ifconfig(client, args):
+ print(client.ifconfig())
+
+
+def _cmd_info(client, args):
+ print(client.info())
+
+
+def _cmd_ping(client, args):
+ if len(args) == 0:
+ timeout = 3
+ else:
+ timeout = float(args[0])
+ alive = client.ping(timeout)
+ if not alive:
+ print("Not responded in %s sec" % args[0])
+ sys.exit(1)
+
+
+def _cmd_suspend(client, args):
+ usage = 'Usage: suspend disk|ram|hybrid'
+ if len(args) != 1:
+ print('Less argument')
+ print(usage)
+ sys.exit(1)
+ if args[0] not in ['disk', 'ram', 'hybrid']:
+ print('Invalid command: ' + args[0])
+ print(usage)
+ sys.exit(1)
+ client.suspend(args[0])
+
+
+def _cmd_shutdown(client, args):
+ client.shutdown()
+_cmd_powerdown = _cmd_shutdown
+
+
+def _cmd_halt(client, args):
+ client.shutdown('halt')
+
+
+def _cmd_reboot(client, args):
+ client.shutdown('reboot')
+
+
+commands = [m.replace('_cmd_', '') for m in dir() if '_cmd_' in m]
+
+
+def main(address, cmd, args):
+ if not os.path.exists(address):
+ print('%s not found' % address)
+ sys.exit(1)
+
+ if cmd not in commands:
+ print('Invalid command: ' + cmd)
+ print('Available commands: ' + ', '.join(commands))
+ sys.exit(1)
+
+ try:
+ client = QemuGuestAgentClient(address)
+ except QemuGuestAgent.error, e:
+ import errno
+
+ print(e)
+ if e.errno == errno.ECONNREFUSED:
+ print('Hint: qemu is not running?')
+ sys.exit(1)
+
+ if cmd != 'ping':
+ client.sync()
+
+ globals()['_cmd_' + cmd](client, args)
+
+
+if __name__ == '__main__':
+ import sys
+ import os
+ import optparse
+
+ address = os.environ['QGA_CLIENT_ADDRESS'] if 'QGA_CLIENT_ADDRESS' in os.environ else None
+
+ usage = "%prog [--address=<unix_path>|<ipv4_address>] <command> [args...]\n"
+ usage += '<command>: ' + ', '.join(commands)
+ parser = optparse.OptionParser(usage=usage)
+ parser.add_option('--address', action='store', type='string',
+ default=address, help='Specify a ip:port pair or a unix socket path')
+ options, args = parser.parse_args()
+
+ address = options.address
+ if address is None:
+ parser.error('address is not specified')
+ sys.exit(1)
+
+ if len(args) == 0:
+ parser.error('Less argument')
+ sys.exit(1)
+
+ main(address, args[0], args[1:])
diff --git a/dep/QMP/qmp.py b/dep/QMP/qmp.py
new file mode 100644
index 0000000..4ade3ce
--- /dev/null
+++ b/dep/QMP/qmp.py
@@ -0,0 +1,193 @@
+# QEMU Monitor Protocol Python class
+#
+# Copyright (C) 2009, 2010 Red Hat Inc.
+#
+# Authors:
+# Luiz Capitulino <lcapitulino@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2. See
+# the COPYING file in the top-level directory.
+
+import json
+import errno
+import socket
+
+class QMPError(Exception):
+ pass
+
+class QMPConnectError(QMPError):
+ pass
+
+class QMPCapabilitiesError(QMPError):
+ pass
+
+class QEMUMonitorProtocol:
+ def __init__(self, address, server=False):
+ """
+ Create a QEMUMonitorProtocol class.
+
+ @param address: QEMU address, can be either a unix socket path (string)
+ or a tuple in the form ( address, port ) for a TCP
+ connection
+ @param server: server mode listens on the socket (bool)
+ @raise socket.error on socket connection errors
+ @note No connection is established, this is done by the connect() or
+ accept() methods
+ """
+ self.__events = []
+ self.__address = address
+ self.__sock = self.__get_sock()
+ if server:
+ self.__sock.bind(self.__address)
+ self.__sock.listen(1)
+
+ def __get_sock(self):
+ if isinstance(self.__address, tuple):
+ family = socket.AF_INET
+ else:
+ family = socket.AF_UNIX
+ return socket.socket(family, socket.SOCK_STREAM)
+
+ def __negotiate_capabilities(self):
+ greeting = self.__json_read()
+ if greeting is None or not greeting.has_key('QMP'):
+ raise QMPConnectError
+ # Greeting seems ok, negotiate capabilities
+ resp = self.cmd('qmp_capabilities')
+ if "return" in resp:
+ return greeting
+ raise QMPCapabilitiesError
+
+ def __json_read(self, only_event=False):
+ while True:
+ data = self.__sockfile.readline()
+ if not data:
+ return
+ resp = json.loads(data)
+ if 'event' in resp:
+ self.__events.append(resp)
+ if not only_event:
+ continue
+ return resp
+
+ error = socket.error
+
+ def connect(self, negotiate=True):
+ """
+ Connect to the QMP Monitor and perform capabilities negotiation.
+
+ @return QMP greeting dict
+ @raise socket.error on socket connection errors
+ @raise QMPConnectError if the greeting is not received
+ @raise QMPCapabilitiesError if fails to negotiate capabilities
+ """
+ self.__sock.connect(self.__address)
+ self.__sockfile = self.__sock.makefile()
+ if negotiate:
+ return self.__negotiate_capabilities()
+
+ def accept(self):
+ """
+ Await connection from QMP Monitor and perform capabilities negotiation.
+
+ @return QMP greeting dict
+ @raise socket.error on socket connection errors
+ @raise QMPConnectError if the greeting is not received
+ @raise QMPCapabilitiesError if fails to negotiate capabilities
+ """
+ self.__sock, _ = self.__sock.accept()
+ self.__sockfile = self.__sock.makefile()
+ return self.__negotiate_capabilities()
+
+ def cmd_obj(self, qmp_cmd):
+ """
+ Send a QMP command to the QMP Monitor.
+
+ @param qmp_cmd: QMP command to be sent as a Python dict
+ @return QMP response as a Python dict or None if the connection has
+ been closed
+ """
+ try:
+ self.__sock.sendall(json.dumps(qmp_cmd))
+ except socket.error, err:
+ if err[0] == errno.EPIPE:
+ return
+ raise socket.error(err)
+ return self.__json_read()
+
+ def cmd(self, name, args=None, id=None):
+ """
+ Build a QMP command and send it to the QMP Monitor.
+
+ @param name: command name (string)
+ @param args: command arguments (dict)
+ @param id: command id (dict, list, string or int)
+ """
+ qmp_cmd = { 'execute': name }
+ if args:
+ qmp_cmd['arguments'] = args
+ if id:
+ qmp_cmd['id'] = id
+ return self.cmd_obj(qmp_cmd)
+
+ def command(self, cmd, **kwds):
+ ret = self.cmd(cmd, kwds)
+ if not ret:
+ return
+ else:
+ if ret.has_key('error'):
+ raise Exception(ret['error']['desc'])
+ return ret['return']
+
+ def pull_event(self, wait=False):
+ """
+ Get and delete the first available QMP event.
+
+ @param wait: block until an event is available (bool)
+ """
+ self.__sock.setblocking(0)
+ try:
+ self.__json_read()
+ except socket.error, err:
+ if err[0] == errno.EAGAIN:
+ # No data available
+ pass
+ self.__sock.setblocking(1)
+ if not self.__events and wait:
+ self.__json_read(only_event=True)
+ event = self.__events[0]
+ del self.__events[0]
+ return event
+
+ def get_events(self, wait=False):
+ """
+ Get a list of available QMP events.
+
+ @param wait: block until an event is available (bool)
+ """
+ self.__sock.setblocking(0)
+ try:
+ self.__json_read()
+ except socket.error, err:
+ if err[0] == errno.EAGAIN:
+ # No data available
+ pass
+ self.__sock.setblocking(1)
+ if not self.__events and wait:
+ self.__json_read(only_event=True)
+ return self.__events
+
+ def clear_events(self):
+ """
+ Clear current list of pending events.
+ """
+ self.__events = []
+
+ def close(self):
+ self.__sock.close()
+ self.__sockfile.close()
+
+ timeout = socket.timeout
+
+ def settimeout(self, timeout):
+ self.__sock.settimeout(timeout)
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 07/19] Move some general functions from dts.py to utils.py and settings.py
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (5 preceding siblings ...)
2015-05-22 9:03 ` [dts] [PATCH v2 06/19] Add a third-party module of qemu-guest-agent to manage VM Jiajia, Sun
@ 2015-05-22 9:04 ` Jiajia, Sun
2015-05-22 9:04 ` [dts] [PATCH v2 08/19] Add and move some functions because of the virtual tests and network device instantiation Jiajia, Sun
` (11 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:04 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/dts.py | 86 +++++++++----------------------------------
framework/settings.py | 43 ++++++++++++++++++++++
framework/utils.py | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 160 insertions(+), 69 deletions(-)
create mode 100644 framework/utils.py
diff --git a/framework/dts.py b/framework/dts.py
index c9ecccb..f6a14ad 100644
--- a/framework/dts.py
+++ b/framework/dts.py
@@ -49,6 +49,7 @@ from test_case import TestCase
from test_result import Result
from stats_reporter import StatsReporter
from excel_reporter import ExcelReporter
+from utils import *
from exception import TimeoutException
from logger import getLogger
import logger
@@ -57,6 +58,7 @@ import sys
reload(sys)
sys.setdefaultencoding('UTF8')
+PROJECT_MODULE_PREFIX = 'project_'
debug_mode = False
config = None
@@ -73,44 +75,12 @@ result = None
excel_report = None
stats = None
log_handler = None
+Package = ''
+Patches = []
drivername = ""
interrupttypr = ""
-def RED(text):
- return "\x1B[" + "31;1m" + text + "\x1B[" + "0m"
-
-
-def BLUE(text):
- return "\x1B[" + "36;1m" + text + "\x1B[" + "0m"
-
-
-def GREEN(text):
- return "\x1B[" + "32;1m" + text + "\x1B[" + "0m"
-
-
-def regexp(s, to_match, allString=False):
- """
- Ensure that the re `to_match' only has one group in it.
- """
-
- scanner = re.compile(to_match, re.DOTALL)
- if allString:
- return scanner.findall(s)
- m = scanner.search(s)
- if m is None:
- log_handler.warning("Failed to match " + to_match + " in the string " + s)
- return None
- return m.group(1)
-
-
-def pprint(some_dict):
- """
- Print JSON format dictionary object.
- """
- return json.dumps(some_dict, sort_keys=True, indent=4)
-
-
def report(text, frame=False, annex=False):
"""
Save report text into rst file.
@@ -130,37 +100,7 @@ def close_crb_sessions():
if tester is not None:
tester.close()
log_handler.info("DTS ended")
-
-
-def get_nic_driver(pci_id):
- """
- Return linux driver for specified pci device
- """
- driverlist = dict(zip(NICS.values(), DRIVERS.keys()))
- try:
- driver = DRIVERS[driverlist[pci_id]]
- except Exception as e:
- driver = None
- return driver
-
-
-def accepted_nic(pci_id):
- """
- Return True if the pci_id is a known NIC card in the settings file and if
- it is selected in the execution file, otherwise it returns False.
- """
- if pci_id not in NICS.values():
- return False
-
- if nic is 'any':
- return True
-
- else:
- if pci_id == NICS[nic]:
- return True
-
- return False
-
+
def get_crb_os(crb):
if 'OS' in crb:
@@ -220,9 +160,10 @@ def get_project_obj(project_name, super_class, crbInst, serializer):
"""
Load project module and return crb instance.
"""
+ global PROJECT_MODULE_PREFIX
project_obj = None
try:
- project_module = __import__("project_" + project_name)
+ project_module = __import__(PROJECT_MODULE_PREFIX + project_name)
for project_subclassname, project_subclass in get_subclasses(project_module, super_class):
project_obj = project_subclass(crbInst, serializer)
@@ -273,7 +214,7 @@ def dts_crbs_init(crbInst, skip_setup, read_cache, project, base_dir, nic):
"""
global dut
global tester
- serializer.set_serialized_filename('../.%s.cache' % crbInst['IP'])
+ serializer.set_serialized_filename('.%s.cache' % crbInst['IP'])
serializer.load_from_file()
dut = get_project_obj(project, Dut, crbInst, serializer)
@@ -337,7 +278,6 @@ def dts_run_target(crbInst, targets, test_suites, nic):
if 'nic_type' not in paramDict:
paramDict['nic_type'] = 'any'
nic = 'any'
- result.nic = nic
dts_run_suite(crbInst, test_suites, target, nic)
@@ -359,7 +299,9 @@ def dts_run_suite(crbInst, test_suites, target, nic):
test_module = __import__('TestSuite_' + test_suite)
for test_classname, test_class in get_subclasses(test_module, TestCase):
- test_suite = test_class(dut, tester, target)
+ test_suite = test_class(dut, tester, target, test_suite)
+ result.nic = test_suite.nic
+
dts_log_testsuite(test_suite, log_handler, test_classname)
log_handler.info("\nTEST SUITE : " + test_classname)
@@ -400,6 +342,12 @@ def run_all(config_file, pkgName, git, patch, skip_setup,
global stats
global log_handler
global debug_mode
+ global Package
+ global Patches
+
+ # save global variable
+ Package = pkgName
+ Patches = patch
# prepare the output folder
if not os.path.exists(output_dir):
diff --git a/framework/settings.py b/framework/settings.py
index feb6fa5..2eccc64 100644
--- a/framework/settings.py
+++ b/framework/settings.py
@@ -48,6 +48,7 @@ NICS = {
'powerville': '8086:1521',
'ophir': '8086:105e',
'niantic': '8086:10fb',
+ 'niantic_vf': '8086:10ed',
'ironpond': '8086:151c',
'twinpond': '8086:1528',
'twinville': '8086:1512',
@@ -77,6 +78,7 @@ DRIVERS = {
'powerville': 'igb',
'ophir': 'igb',
'niantic': 'ixgbe',
+ 'niantic_vf': 'ixgbevf',
'ironpond': 'ixgbe',
'twinpond': 'ixgbe',
'twinville': 'ixgbe',
@@ -137,6 +139,17 @@ Global macro for dts.
"""
IXIA = "ixia"
+"""
+The root path of framework configs.
+"""
+CONFIG_ROOT_PATH = "./conf/"
+
+"""
+The log name seperater.
+"""
+LOG_NAME_SEP = '.'
+
+
def nic_name_from_type(type):
"""
strip nic code name by nic type
@@ -145,3 +158,33 @@ def nic_name_from_type(type):
if nic_type == type:
return name
return 'Unknown'
+
+
+def get_nic_driver(pci_id):
+ """
+ Return linux driver for specified pci device
+ """
+ driverlist = dict(zip(NICS.values(), DRIVERS.keys()))
+ try:
+ driver = DRIVERS[driverlist[pci_id]]
+ except Exception as e:
+ driver = None
+ return driver
+
+
+def accepted_nic(pci_id):
+ """
+ Return True if the pci_id is a known NIC card in the settings file and if
+ it is selected in the execution file, otherwise it returns False.
+ """
+ if pci_id not in NICS.values():
+ return False
+
+ if nic is 'any':
+ return True
+
+ else:
+ if pci_id == NICS[nic]:
+ return True
+
+ return False
diff --git a/framework/utils.py b/framework/utils.py
new file mode 100644
index 0000000..dd45e9e
--- /dev/null
+++ b/framework/utils.py
@@ -0,0 +1,100 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import json # json format
+import re
+
+
+def RED(text):
+ return "\x1B[" + "31;1m" + str(text) + "\x1B[" + "0m"
+
+
+def BLUE(text):
+ return "\x1B[" + "36;1m" + str(text) + "\x1B[" + "0m"
+
+
+def GREEN(text):
+ return "\x1B[" + "32;1m" + str(text) + "\x1B[" + "0m"
+
+
+def pprint(some_dict):
+ """
+ Print JSON format dictionary object.
+ """
+ return json.dumps(some_dict, sort_keys=True, indent=4)
+
+
+def regexp(s, to_match, allString=False):
+ """
+ Ensure that the re `to_match' only has one group in it.
+ """
+
+ scanner = re.compile(to_match, re.DOTALL)
+ if allString:
+ return scanner.findall(s)
+ m = scanner.search(s)
+ if m is None:
+ print RED("Failed to match " + to_match + " in the string " + s)
+ return None
+ return m.group(1)
+
+
+def get_obj_funcs(obj, func_name_regex):
+ """
+ Return function list which name matched regex.
+ """
+ for func_name in dir(obj):
+ func = getattr(obj, func_name)
+ if callable(func) and re.match(func_name_regex, func.__name__):
+ yield func
+
+
+def remove_old_rsa_key(crb, ip):
+ """
+ Remove the old RSA key of specified IP on crb.
+ """
+ if ':' not in ip:
+ ip = ip.strip()
+ port = ''
+ else:
+ addr = ip.split(':')
+ ip = addr[0].strip()
+ port = addr[1].strip()
+
+ rsa_key_path = "~/.ssh/known_hosts"
+ if port:
+ remove_rsa_key_cmd = "sed -i '/^\[%s\]:%d/d' %s" % \
+ (ip.strip(), int(
+ port), rsa_key_path)
+ else:
+ remove_rsa_key_cmd = "sed -i '/^%s/d' %s" % \
+ (ip.strip(), rsa_key_path)
+ crb.send_expect(remove_rsa_key_cmd, "# ")
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 08/19] Add and move some functions because of the virtual tests and network device instantiation
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (6 preceding siblings ...)
2015-05-22 9:04 ` [dts] [PATCH v2 07/19] Move some general functions from dts.py to utils.py and settings.py Jiajia, Sun
@ 2015-05-22 9:04 ` Jiajia, Sun
2015-05-22 9:04 ` [dts] [PATCH v2 09/19] Change and add some functions to support virtual test Jiajia, Sun
` (10 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:04 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/crb.py | 126 +++++++++++++++++++++++++++++++++----------------------
1 file changed, 76 insertions(+), 50 deletions(-)
diff --git a/framework/crb.py b/framework/crb.py
index a699bfc..3160fa0 100644
--- a/framework/crb.py
+++ b/framework/crb.py
@@ -80,7 +80,9 @@ class Crb(object):
"""
Get the huge page number of CRB.
"""
- huge_pages = self.send_expect("awk '/HugePages_Total/ { print $2 }' /proc/meminfo", "# ")
+ huge_pages = self.send_expect(
+ "awk '/HugePages_Total/ { print $2 }' /proc/meminfo",
+ "# ", alt_session=True)
if huge_pages != "":
return int(huge_pages)
return 0
@@ -127,13 +129,15 @@ class Crb(object):
Force set remote interface link status in FreeBSD.
"""
eth = self.ports_info[port]['intf']
- self.send_expect("ifconfig %s %s" % (eth, status), "# ")
+ self.send_expect("ifconfig %s %s" %
+ (eth, status), "# ", alt_session=True)
def admin_ports_linux(self, eth, status):
"""
Force set remote interface link status in Linux.
"""
- self.send_expect("ip link set %s %s" % (eth, status), "# ")
+ self.send_expect("ip link set %s %s" %
+ (eth, status), "# ", alt_session=True)
def pci_devices_information(self):
"""
@@ -157,8 +161,9 @@ class Crb(object):
"""
Look for the NIC's information (PCI Id and card type).
"""
- out = self.send_expect("lspci -nn | grep -i eth", "# ")
- rexp = r"([\da-f]{2}:[\da-f]{2}.\d{1}) Ethernet .*?([\da-f]{4}:[\da-f]{4})"
+ out = self.send_expect(
+ "lspci -nn | grep -i eth", "# ", alt_session=True)
+ rexp = r"([\da-f]{2}:[\da-f]{2}.\d{1}) .*Eth.*?ernet .*?([\da-f]{4}:[\da-f]{4})"
pattern = re.compile(rexp)
match = pattern.findall(out)
self.pci_devices_info = []
@@ -169,7 +174,7 @@ class Crb(object):
"""
Look for the NIC's information (PCI Id and card type).
"""
- out = self.send_expect("pciconf -l", "# ")
+ out = self.send_expect("pciconf -l", "# ", alt_session=True)
rexp = r"pci0:([\da-f]{1,3}:[\da-f]{1,2}:\d{1}):\s*class=0x020000.*chip=0x([\da-f]{4})8086"
pattern = re.compile(rexp)
match = pattern.findall(out)
@@ -179,66 +184,69 @@ class Crb(object):
card_type = "8086:%s" % match[i][1]
self.pci_devices_info.append((match[i][0], card_type))
- def get_interface_name(self, bus_id, devfun_id=''):
+ def get_pci_dev_driver(self, bus_id, devfun_id):
"""
- Get interface name of specified pci device.
+ Get the driver of specified pci device.
"""
- get_interface_name = getattr(self, 'get_interface_name_%s' % self.get_os_type())
- return get_interface_name(bus_id, devfun_id)
+ get_pci_dev_driver = getattr(
+ self, 'get_pci_dev_driver_%s' % self.get_os_type())
+ return get_pci_dev_driver(bus_id, devfun_id)
- def get_interface_name_linux(self, bus_id, devfun_id):
+ def get_pci_dev_driver_linux(self, bus_id, devfun_id):
"""
- Get interface name of specified pci device on linux.
+ Get the driver of specified pci device on linux.
"""
- command = 'ls --color=never /sys/bus/pci/devices/0000:%s:%s/net' % (bus_id, devfun_id)
- out = self.send_expect(command, '# ', verify=True)
- if out == -1:
- name = ""
- else:
- name = out.split()[0]
- return name
-
- def get_interface_name_freebsd(self, bus_id, devfun_id):
- """
- Get interface name of specified pci device on Freebsd.
- """
- out = self.send_expect("pciconf -l", "# ")
- rexp = r"(\w*)@pci0:%s" % bus_id
+ out = self.send_expect("cat /sys/bus/pci/devices/0000\:%s\:%s/uevent" %
+ (bus_id, devfun_id), "# ", alt_session=True)
+ rexp = r"DRIVER=(.+?)\r"
pattern = re.compile(rexp)
- match = pattern.findall(out)
- return match[0]
+ match = pattern.search(out)
+ if not match:
+ return None
+ return match.group(1)
- def get_mac_addr(self, intf, bus_id='', devfun_id=''):
+ def get_pci_dev_driver_freebsd(self, bus_id, devfun_id):
"""
- Get mac address of specified pci device.
+ Get the driver of specified pci device.
"""
- get_mac_addr = getattr(self, 'get_mac_addr_%s' % self.get_os_type())
- return get_mac_addr(intf, bus_id, devfun_id)
+ return True
- def get_mac_addr_linux(self, intf, bus_id, devfun_id):
+ def get_pci_dev_id(self, bus_id, devfun_id):
"""
- Get mac address of specified pci device on linux.
+ Get the pci id of specified pci device.
"""
- command = ('cat /sys/bus/pci/devices/0000:%s:%s/net/%s/address' %
- (bus_id, devfun_id, intf))
- return self.send_expect(command, '# ')
+ get_pci_dev_id = getattr(
+ self, 'get_pci_dev_id_%s' % self.get_os_type())
+ return get_pci_dev_id(bus_id, devfun_id)
- def get_mac_addr_freebsd(self, intf, bus_id, devfun_id):
+ def get_pci_dev_id_linux(self, bus_id, devfun_id):
"""
- Get mac address of specified pci device on Freebsd.
+ Get the pci id of specified pci device on linux.
"""
- out = self.send_expect('ifconfig %s' % intf, '# ')
- rexp = r"ether ([\da-f:]*)"
+ out = self.send_expect("cat /sys/bus/pci/devices/0000\:%s\:%s/uevent" %
+ (bus_id, devfun_id), "# ", alt_session=True)
+ rexp = r"PCI_ID=(.+)"
pattern = re.compile(rexp)
- match = pattern.findall(out)
- return match[0]
+ match = re.search(out)
+ if not match:
+ return None
+ return match.group(1)
def get_device_numa(self, bus_id, devfun_id):
"""
- Get numa id of specified pci device
+ Get numa number of specified pci device.
"""
- numa = self.send_expect("cat /sys/bus/pci/devices/0000\:%s\:%s/numa_node" %
- (bus_id, devfun_id), "# ")
+ get_device_numa = getattr(
+ self, "get_device_numa_%s" % self.get_os_type())
+ return get_device_numa(bus_id, devfun_id)
+
+ def get_device_numa_linux(self, bus_id, devfun_id):
+ """
+ Get numa number of specified pci device on Linux.
+ """
+ numa = self.send_expect(
+ "cat /sys/bus/pci/devices/0000\:%s\:%s/numa_node" %
+ (bus_id, devfun_id), "# ", alt_session=True)
try:
numa = int(numa)
@@ -259,14 +267,14 @@ class Crb(object):
Get ipv6 address of specified pci device on linux.
"""
out = self.send_expect("ip -family inet6 address show dev %s | awk '/inet6/ { print $2 }'"
- % intf, "# ")
+ % intf, "# ", alt_session=True)
return out.split('/')[0]
def get_ipv6_addr_freebsd(self, intf):
"""
Get ipv6 address of specified pci device on Freebsd.
"""
- out = self.send_expect('ifconfig %s' % intf, '# ')
+ out = self.send_expect('ifconfig %s' % intf, '# ', alt_session=True)
rexp = r"inet6 ([\da-f:]*)%"
pattern = re.compile(rexp)
match = pattern.findall(out)
@@ -275,6 +283,22 @@ class Crb(object):
return match[0]
+ def disable_ipv6(self, intf):
+ """
+ Disable ipv6 of of specified interface
+ """
+ if intf != 'N/A':
+ self.send_expect("sysctl net.ipv6.conf.%s.disable_ipv6=1" %
+ intf, "# ", alt_session=True)
+
+ def enable_ipv6(self, intf):
+ """
+ Enable ipv6 of of specified interface
+ """
+ if intf != 'N/A':
+ self.send_expect("sysctl net.ipv6.conf.%s.disable_ipv6=0" %
+ intf, "# ", alt_session=True)
+
def create_file(self, contents, fileName):
"""
Create file with contents and copy it to CRB.
@@ -318,7 +342,7 @@ class Crb(object):
if isinstance(self, Dut) and self.get_os_type() == 'freebsd':
expected = 'FreeBSD.*#'
- self.send_expect('uname', expected, 2)
+ self.send_expect('uname', expected, 2, alt_session=True)
def init_core_list(self):
"""
@@ -378,7 +402,9 @@ class Crb(object):
self.cores = []
cpuinfo = \
- self.send_expect("grep \"processor\\|physical id\\|core id\\|^$\" /proc/cpuinfo", "#")
+ self.send_expect(
+ "grep --color=never \"processor\\|physical id\\|core id\\|^$\" /proc/cpuinfo",
+ "#", alt_session=True)
cpuinfo = cpuinfo.split('\r\n\r\n')
for line in cpuinfo:
m = re.search("processor\t: (\d+)\r\n" +
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 09/19] Change and add some functions to support virtual test
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (7 preceding siblings ...)
2015-05-22 9:04 ` [dts] [PATCH v2 08/19] Add and move some functions because of the virtual tests and network device instantiation Jiajia, Sun
@ 2015-05-22 9:04 ` Jiajia, Sun
2015-05-22 9:04 ` [dts] [PATCH v2 10/19] add some exceptions to support framwork to handle virtual test exceptions Jiajia, Sun
` (9 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:04 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/config.py | 170 +++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 135 insertions(+), 35 deletions(-)
mode change 100755 => 100644 framework/config.py
diff --git a/framework/config.py b/framework/config.py
old mode 100755
new mode 100644
index d2548e8..7e2436a
--- a/framework/config.py
+++ b/framework/config.py
@@ -37,45 +37,133 @@ import re
import ConfigParser # config parse module
import argparse # prase arguments module
-portconf = "conf/ports.cfg"
-crbconf = "conf/crbs.cfg"
+PORTCONF = "conf/ports.cfg"
+CRBCONF = "conf/crbs.cfg"
+VIRTCONF = "conf/virt_global.cfg"
class UserConf():
- def __init__(self, port_conf=portconf, crb_conf=crbconf):
- self.port_config = port_conf
- self.crb_config = crb_conf
+ def __init__(self, config):
+ self.conf = ConfigParser.SafeConfigParser()
+ load_files = self.conf.read(config)
+ if load_files == []:
+ print "FAILED LOADING %s!!!" % config
+ self.conf = None
+ raise
+
+ def get_sections(self):
+ if self.conf is None:
+ return None
+
+ return self.conf.sections()
+
+ def load_section(self, section):
+ if self.conf is None:
+ return None
+
+ items = None
+ for conf_sect in self.conf.sections():
+ if conf_sect == section:
+ items = self.conf.items(section)
+
+ return items
+
+ def load_config(self, item):
+ confs = [conf.strip() for conf in item.split(';')]
+ if '' in confs:
+ confs.remove('')
+ return confs
+
+ def load_param(self, conf):
+ paramDict = dict()
+
+ for param in conf.split(','):
+ (key, _, value) = param.partition('=')
+ paramDict[key] = value
+ return paramDict
+
+
+class VirtConf(UserConf):
+
+ def __init__(self, virt_conf=VIRTCONF):
+ self.config_file = virt_conf
+ self.virt_cfg = {}
+ try:
+ self.virt_conf = UserConf(self.config_file)
+ except Exception as e:
+ print "FAILED LOADING VIRT CONFIG!!!"
+ self.virt_conf = None
+
+ def load_virt_config(self, name):
+ self.virt_cfgs = []
+
+ try:
+ virt_confs = self.virt_conf.load_section(name)
+ except:
+ print "FAILED FIND SECTION %s!!!" % name
+ return
+
+ for virt_conf in virt_confs:
+ virt_cfg = {}
+ virt_params = []
+ key, config = virt_conf
+ confs = self.virt_conf.load_config(config)
+ for config in confs:
+ virt_params.append(self.load_virt_param(config))
+ virt_cfg[key] = virt_params
+ self.virt_cfgs.append(virt_cfg)
+
+ def get_virt_config(self):
+ return self.virt_cfgs
+
+ def load_virt_param(self, config):
+ cfg_params = self.virt_conf.load_param(config)
+ return cfg_params
+
+
+class PortConf(UserConf):
+
+ def __init__(self, port_conf=PORTCONF):
+ self.config_file = port_conf
self.ports_cfg = {}
self.pci_regex = "([\da-f]{2}:[\da-f]{2}.\d{1})$"
try:
- self.port_conf = ConfigParser.SafeConfigParser()
- self.port_conf.read(self.port_config)
+ self.port_conf = UserConf(self.config_file)
except Exception as e:
print "FAILED LOADING PORT CONFIG!!!"
+ self.port_conf = None
def load_ports_config(self, crbIP):
- ports = []
- for crb in self.port_conf.sections():
- if crb != crbIP:
- continue
- ports = [port.strip()
- for port in self.port_conf.get(crb, 'ports').split(';')]
+ self.ports_cfg = {}
+ if self.port_conf is None:
+ return
+
+ ports = self.port_conf.load_section(crbIP)
+ if ports is None:
+ return
+ key, config = ports[0]
+ confs = self.port_conf.load_config(config)
+
+ for config in confs:
+ port_param = self.port_conf.load_param(config)
- for port in ports:
- port_cfg = self.__parse_port_param(port)
# check pci BDF validity
- if 'pci' not in port_cfg:
+ if 'pci' not in port_param:
print "NOT FOUND CONFIG FOR NO PCI ADDRESS!!!"
continue
- m = re.match(self.pci_regex, port_cfg['pci'])
+ m = re.match(self.pci_regex, port_param['pci'])
if m is None:
print "INVALID CONFIG FOR NO PCI ADDRESS!!!"
continue
- keys = port_cfg.keys()
+ keys = port_param.keys()
keys.remove('pci')
- self.ports_cfg[port_cfg['pci']] = {key: port_cfg[key] for key in keys}
+ self.ports_cfg[port_param['pci']] = {
+ key: port_param[key] for key in keys}
+ if 'numa' in self.ports_cfg[port_param['pci']]:
+ numa_str = self.ports_cfg[port_param['pci']]['numa']
+ self.ports_cfg[port_param['pci']]['numa'] = int(numa_str)
def get_ports_config(self):
return self.ports_cfg
@@ -86,23 +174,35 @@ class UserConf():
else:
return False
- def __parse_port_param(self, port):
- portDict = dict()
-
- for param in port.split(','):
- (key, _, value) = param.partition('=')
- if key == 'numa':
- portDict[key] = int(value)
- else:
- portDict[key] = value
- return portDict
if __name__ == '__main__':
- parser = argparse.ArgumentParser(description="Load DTS configuration files")
- parser.add_argument("-p", "--portconf", default=portconf)
- parser.add_argument("-c", "--crbconf", default=crbconf)
+ parser = argparse.ArgumentParser(
+ description="Load DTS configuration files")
+ parser.add_argument("-p", "--portconf", default=PORTCONF)
+ parser.add_argument("-c", "--crbconf", default=CRBCONF)
+ parser.add_argument("-v", "--virtconf", default=VIRTCONF)
args = parser.parse_args()
- conf = UserConf()
- conf.load_ports_config('192.168.1.1')
- conf.check_port_available('0000:86:00.0')
+
+ # not existed configuration file
+ VirtConf('/tmp/not-existed.cfg')
+
+ # example for basic use configuration file
+ conf = UserConf(PORTCONF)
+ for section in conf.get_sections():
+ items = conf.load_section(section)
+ key, value = items[0]
+ confs = conf.load_config(value)
+ for config in confs:
+ conf.load_param(config)
+
+ # example for port configuration file
+ portconf = PortConf(PORTCONF)
+ portconf.load_ports_config('DUT IP')
+ print portconf.get_ports_config()
+ portconf.check_port_available('86:00.0')
+
+ # example for global virtualization configuration file
+ virtconf = VirtConf(VIRTCONF)
+ virtconf.load_virt_config('LIBVIRT')
+ print virtconf.get_virt_config()
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 10/19] add some exceptions to support framwork to handle virtual test exceptions
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (8 preceding siblings ...)
2015-05-22 9:04 ` [dts] [PATCH v2 09/19] Change and add some functions to support virtual test Jiajia, Sun
@ 2015-05-22 9:04 ` Jiajia, Sun
2015-05-22 9:04 ` [dts] [PATCH v2 11/19] Add some codes to support virtual test log Jiajia, Sun
` (8 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:04 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/exception.py | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
diff --git a/framework/exception.py b/framework/exception.py
index be38c16..7ec03c2 100644
--- a/framework/exception.py
+++ b/framework/exception.py
@@ -46,3 +46,72 @@ class SSHConnectionException(Exception):
def __str__(self):
return 'Error trying to connect with %s' % self.host
+
+
+class SSHSessionDeadException(Exception):
+
+ """
+ SSH session is not alive.
+ It can no longer be used.
+ """
+
+ def __init__(self, host):
+ self.host = host
+
+ def __str__(self):
+ return 'SSH session with %s has been dead' % self.host
+
+
+class StartVMFailedException(Exception):
+
+ """
+ Start VM failed.
+ """
+
+ def __init__(self, error):
+ self.error = error
+
+ def __str__(self):
+ return repr(self.error)
+
+
+class ConfigParseException(Exception):
+
+ """
+ Configuration file parse failure exception.
+ """
+
+ def __init__(self, conf_file):
+ self.config = conf_file
+
+ def __str__(self):
+ return "Faile to parse config file [%s]" % (self.config)
+
+
+class VirtConfigParseException(Exception):
+ pass
+
+
+class PortConfigParseException(Exception):
+ pass
+
+
+class VirtConfigParamException(Exception):
+
+ """
+ Virtualizatoin param execution exception.
+ """
+ def __init__(self, param):
+ self.param = param
+
+ def __str__(self):
+ return "Faile to execute param [%s]" % (self.param)
+
+
+class VirtDutConnectException(Exception):
+ pass
+
+
+class VirtDutInitException(Exception):
+ def __init__(self, vm_dut):
+ self.vm_dut = vm_dut
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 11/19] Add some codes to support virtual test log
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (9 preceding siblings ...)
2015-05-22 9:04 ` [dts] [PATCH v2 10/19] add some exceptions to support framwork to handle virtual test exceptions Jiajia, Sun
@ 2015-05-22 9:04 ` Jiajia, Sun
2015-05-22 9:04 ` [dts] [PATCH v2 12/19] Add some codes to make session to support virtual test Jiajia, Sun
` (7 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:04 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/logger.py | 69 +++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 59 insertions(+), 10 deletions(-)
diff --git a/framework/logger.py b/framework/logger.py
index 1829e18..5597e33 100644
--- a/framework/logger.py
+++ b/framework/logger.py
@@ -35,6 +35,9 @@ import sys
import inspect
import re
+from settings import LOG_NAME_SEP
+from utils import RED
+
"""
DTS logger module with several log level. DTS framwork and TestSuite log
will saved into different log files.
@@ -58,6 +61,9 @@ logging.SUITE_TESTER_OUTPUT = logging.DEBUG + 4
logging.DTS_IXIA_CMD = logging.INFO + 5
logging.DTS_IXIA_OUTPUT = logging.DEBUG + 5
+logging.DTS_VIRTDUT_CMD = logging.INFO + 6
+logging.DTS_VIRTDUT_OUTPUT = logging.DEBUG + 6
+
logging.addLevelName(logging.DTS_DUT_CMD, 'DTS_DUT_CMD')
logging.addLevelName(logging.DTS_DUT_OUTPUT, 'DTS_DUT_OUTPUT')
logging.addLevelName(logging.DTS_DUT_RESULT, 'DTS_DUT_RESUTL')
@@ -66,6 +72,12 @@ logging.addLevelName(logging.DTS_TESTER_CMD, 'DTS_TESTER_CMD')
logging.addLevelName(logging.DTS_TESTER_OUTPUT, 'DTS_TESTER_OUTPUT')
logging.addLevelName(logging.DTS_TESTER_RESULT, 'DTS_TESTER_RESULT')
+logging.addLevelName(logging.DTS_IXIA_CMD, 'DTS_IXIA_CMD')
+logging.addLevelName(logging.DTS_IXIA_OUTPUT, 'DTS_IXIA_OUTPUT')
+
+logging.addLevelName(logging.DTS_VIRTDUT_CMD, 'VIRTDUT_CMD')
+logging.addLevelName(logging.DTS_VIRTDUT_OUTPUT, 'VIRTDUT_OUTPUT')
+
logging.addLevelName(logging.SUITE_DUT_CMD, 'SUITE_DUT_CMD')
logging.addLevelName(logging.SUITE_DUT_OUTPUT, 'SUITE_DUT_OUTPUT')
@@ -82,15 +94,18 @@ stream_fmt = '%(color)s%(levelname)20s: %(message)s' + RESET_COLOR
log_dir = None
-def RED(text):
- return "\x1B[" + "31;1m" + text + "\x1B[" + "0m"
-
-
def set_verbose():
global verbose
verbose = True
+def add_salt(salt, msg):
+ if not salt:
+ return msg
+ else:
+ return '[%s] ' % salt + str(msg)
+
+
class BaseLoggerAdapter(logging.LoggerAdapter):
"""
Upper layer of original logging module.
@@ -132,6 +147,12 @@ class BaseLoggerAdapter(logging.LoggerAdapter):
def dts_ixia_output(self, msg, *args, **kwargs):
self.log(logging.DTS_IXIA_OUTPUT, msg, *args, **kwargs)
+ def dts_virtdut_cmd(self, msg, *args, **kwargs):
+ self.log(logging.DTS_VIRTDUT_CMD, msg, *args, **kwargs)
+
+ def dts_virtdut_output(self, msg, *args, **kwargs):
+ self.log(logging.DTS_VIRTDUT_OUTPUT, msg, *args, **kwargs)
+
class ColorHandler(logging.StreamHandler):
"""
@@ -150,6 +171,8 @@ class ColorHandler(logging.StreamHandler):
logging.SUITE_TESTER_CMD: '', # SYSTEM
logging.DTS_IXIA_CMD: '', # SYSTEM
logging.DTS_IXIA_OUTPUT: '', # SYSTEM
+ logging.DTS_VIRTDUT_CMD: '', # SYSTEM
+ logging.DTS_VIRTDUT_OUTPUT: '', # SYSTEM
logging.WARN: '\033[01;33m', # BOLD YELLOW
logging.DTS_DUT_RESULT: '\033[01;34m', # BOLD BLUE
logging.DTS_TESTER_RESULT: '\033[01;34m', # BOLD BLUE
@@ -189,6 +212,8 @@ class DTSLOG(BaseLoggerAdapter):
self.crb = crb
super(DTSLOG, self).__init__(self.logger, dict(crb=self.crb))
+ self.salt = ''
+
self.fh = None
self.ch = None
@@ -221,24 +246,28 @@ class DTSLOG(BaseLoggerAdapter):
"""
DTS warnning level log function.
"""
+ message = add_salt(self.salt, message)
self.logger.log(self.warn_lvl, message)
def info(self, message):
"""
DTS information level log function.
"""
+ message = add_salt(self.salt, message)
self.logger.log(self.info_lvl, message)
def error(self, message):
"""
DTS error level log function.
"""
+ message = add_salt(self.salt, message)
self.logger.log(self.error_lvl, message)
def debug(self, message):
"""
DTS debug level log function.
"""
+ message = add_salt(self.salt, message)
self.logger.log(self.debug_lvl, message)
def set_logfile_path(self, path):
@@ -270,17 +299,34 @@ class DTSLOG(BaseLoggerAdapter):
ch = ColorHandler()
self.__log_hander(fh, ch)
- if crb == "dut":
+ def set_salt(crb, start_flag):
+ if LOG_NAME_SEP in crb:
+ old = '%s%s' % (start_flag, LOG_NAME_SEP)
+ if not self.salt:
+ self.salt = crb.replace(old, '', 1)
+
+ if crb.startswith('dut'):
self.info_lvl = logging.DTS_DUT_CMD
self.debug_lvl = logging.DTS_DUT_OUTPUT
self.warn_lvl = logging.DTS_DUT_RESULT
- elif crb == "tester":
+
+ set_salt(crb, 'dut')
+ elif crb.startswith('tester'):
self.info_lvl = logging.DTS_TESTER_CMD
self.debug_lvl = logging.DTS_TESTER_OUTPUT
self.warn_lvl = logging.DTS_TESTER_RESULT
- elif crb == "ixia":
+
+ set_salt(crb, 'tester')
+ elif crb.startswith('ixia'):
self.info_lvl = logging.DTS_IXIA_CMD
self.debug_lvl = logging.DTS_IXIA_OUTPUT
+
+ set_salt(crb, 'ixia')
+ elif crb.startswith('virtdut'):
+ self.info_lvl = logging.DTS_VIRTDUT_CMD
+ self.debug_lvl = logging.DTS_VIRTDUT_OUTPUT
+
+ set_salt(crb, 'virtdut')
else:
self.error_lvl = logging.ERROR
self.warn_lvl = logging.WARNING
@@ -296,15 +342,18 @@ class DTSLOG(BaseLoggerAdapter):
ch = ColorHandler()
self.__log_hander(fh, ch)
- if crb == "dut":
+ if crb == 'dut':
self.info_lvl = logging.SUITE_DUT_CMD
self.debug_lvl = logging.SUITE_DUT_OUTPUT
- elif crb == "tester":
+ elif crb == 'tester':
self.info_lvl = logging.SUITE_TESTER_CMD
self.debug_lvl = logging.SUITE_TESTER_OUTPUT
- elif crb == "ixia":
+ elif crb == 'ixia':
self.info_lvl = logging.DTS_IXIA_CMD
self.debug_lvl = logging.DTS_IXIA_OUTPUT
+ elif crb == 'virtdut':
+ self.info_lvl = logging.DTS_VIRTDUT_CMD
+ self.debug_lvl = logging.DTS_VIRTDUT_OUTPUT
def logger_exit(self):
"""
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 12/19] Add some codes to make session to support virtual test
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (10 preceding siblings ...)
2015-05-22 9:04 ` [dts] [PATCH v2 11/19] Add some codes to support virtual test log Jiajia, Sun
@ 2015-05-22 9:04 ` Jiajia, Sun
2015-05-22 9:04 ` [dts] [PATCH v2 13/19] Add some base functions to get the device info in the testpmd Jiajia, Sun
` (6 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:04 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/ssh_pexpect.py | 62 ++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 52 insertions(+), 10 deletions(-)
diff --git a/framework/ssh_pexpect.py b/framework/ssh_pexpect.py
index 735df44..98c3a60 100644
--- a/framework/ssh_pexpect.py
+++ b/framework/ssh_pexpect.py
@@ -2,7 +2,8 @@ import time
import pexpect
import pxssh
from debugger import ignore_keyintr, aware_keyintr
-from exception import TimeoutException, SSHConnectionException
+from exception import TimeoutException, SSHConnectionException, SSHSessionDeadException
+from utils import RED, GREEN
"""
Module handle ssh sessions between tester and DUT.
@@ -14,16 +15,28 @@ Aslo support transfer files to tester or DUT.
class SSHPexpect(object):
def __init__(self, host, username, password):
- self.magic_prompt = "[MAGIC PROMPT]"
+ self.magic_prompt = "MAGIC PROMPT"
try:
self.session = pxssh.pxssh()
self.username = username
self.host = host
self.password = password
- self.session.login(self.host, self.username,
- self.password, original_prompt='[$#>]')
+ if ':' in host:
+ self.ip = host.split(':')[0]
+ self.port = int(host.split(':')[1])
+ self.session.login(self.ip, self.username,
+ self.password, original_prompt='[$#>]',
+ port=self.port, login_timeout=20)
+ else:
+ self.session.login(self.host, self.username,
+ self.password, original_prompt='[$#>]')
self.send_expect('stty -echo', '# ', timeout=2)
- except Exception:
+ except Exception, e:
+ print RED(e)
+ if getattr(self, 'port', None):
+ suggestion = "\nSuggession: Check if the fireware on [ %s ] " % \
+ self.ip + "is stoped\n"
+ print GREEN(suggestion)
raise SSHConnectionException(host)
def init_log(self, logger, name):
@@ -45,30 +58,54 @@ class SSHPexpect(object):
def send_expect(self, command, expected, timeout=15, verify=False):
ret = self.send_expect_base(command, expected, timeout)
if verify:
- ret_status = self.send_expect_base("echo $?", expected)
+ ret_status = self.send_expect_base("echo $?", expected, timeout)
if not int(ret_status):
return ret
else:
self.logger.error("Command: %s failure!" % command)
- return -1
+ self.logger.error(ret)
+ return ret_status
else:
return ret
- def __flush(self):
+ def get_session_before(self, timeout=15):
+ """
+ Get all output before timeout
+ """
+ ignore_keyintr()
self.session.PROMPT = self.magic_prompt
- self.session.prompt(0.1)
+ try:
+ self.session.prompt(timeout)
+ except Exception as e:
+ pass
+
+ aware_keyintr()
+ before = self.get_output_before()
+ self.__flush()
+ return before
+
+ def __flush(self):
+ """
+ Clear all session buffer
+ """
+ self.session.buffer = ""
+ self.session.before = ""
def __prompt(self, command, timeout):
if not self.session.prompt(timeout):
raise TimeoutException(command, self.get_output_all())
def __sendline(self, command):
+ if not self.isalive():
+ raise SSHSessionDeadException(self.host)
if len(command) == 2 and command.startswith('^'):
self.session.sendcontrol(command[1])
else:
self.session.sendline(command)
def get_output_before(self):
+ if not self.isalive():
+ raise SSHSessionDeadException(self.host)
self.session.flush()
before = self.session.before.rsplit('\r\n', 1)
if before[0] == "[PEXPECT]":
@@ -103,7 +140,12 @@ class SSHPexpect(object):
"""
Sends a local file to a remote place.
"""
- command = 'scp {0} {1}@{2}:{3}'.format(src, self.username, self.host, dst)
+ if ':' in self.host:
+ command = 'scp -P {0} -o NoHostAuthenticationForLocalhost=yes {1} {2}@{3}:{4}'.format(
+ str(self.port), src, self.username, self.ip, dst)
+ else:
+ command = 'scp {0} {1}@{2}:{3}'.format(
+ src, self.username, self.host, dst)
if password == '':
self._spawn_scp(command, self.password)
else:
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 13/19] Add some base functions to get the device info in the testpmd
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (11 preceding siblings ...)
2015-05-22 9:04 ` [dts] [PATCH v2 12/19] Add some codes to make session to support virtual test Jiajia, Sun
@ 2015-05-22 9:04 ` Jiajia, Sun
2015-05-22 9:04 ` [dts] [PATCH v2 14/19] Change some codes to support network device instantiation and virtualization test Jiajia, Sun
` (5 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:04 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/pmd_output.py | 92 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 92 insertions(+)
diff --git a/framework/pmd_output.py b/framework/pmd_output.py
index 473339d..4ccdd0d 100644
--- a/framework/pmd_output.py
+++ b/framework/pmd_output.py
@@ -32,6 +32,7 @@
import os
import re
import dts
+from settings import TIMEOUT
class PmdOutput():
@@ -42,6 +43,7 @@ class PmdOutput():
def __init__(self, dut):
self.dut = dut
+ self.dut.testpmd = self
self.rx_pkts_prefix = "RX-packets:"
self.rx_missed_prefix = "RX-missed:"
self.rx_bytes_prefix = "RX-bytes:"
@@ -113,3 +115,93 @@ class PmdOutput():
out = self.dut.send_expect(command, "testpmd> ", 120)
self.command = command
return out
+
+ def execute_cmd(self, pmd_cmd, expected='testpmd> ', timeout=TIMEOUT,
+ alt_session=False):
+ return self.dut.send_expect('%s' % pmd_cmd, expected, timeout=timeout,
+ alt_session=alt_session)
+
+ def get_value_from_string(self, key_str, regx_str, string):
+ """
+ Get some values from the given string by the regular expression.
+ """
+ pattern = r"(?<=%s)%s" % (key_str, regx_str)
+ s = re.compile(pattern)
+ res = s.search(string)
+ if type(res).__name__ == 'NoneType':
+ return ' '
+ else:
+ return res.group(0)
+
+ def get_detail_from_port_info(self, key_str, regx_str, port):
+ """
+ Get the detail info from the output of pmd cmd 'show port info <port num>'.
+ """
+ out = self.dut.send_expect("show port info %d" % port, "testpmd> ")
+ find_value = self.get_value_from_string(key_str, regx_str, out)
+ return find_value
+
+ def get_port_mac(self, port_id):
+ """
+ Get the specified port MAC.
+ """
+ return self.get_detail_from_port_info("MAC address: ", "([0-9A-F]{2}:){5}[0-9A-F]{2}", port_id)
+
+ def get_port_connect_socket(self, port_id):
+ """
+ Get the socket id which the specified port is connectting with.
+ """
+ return self.get_detail_from_port_info("Connect to socket: ", "\d+", port_id)
+
+ def get_port_memory_socket(self, port_id):
+ """
+ Get the socket id which the specified port memory is allocated on.
+ """
+ return self.get_detail_from_port_info("memory allocation on the socket: ", "\d+", port_id)
+
+ def get_port_link_status(self, port_id):
+ """
+ Get the specified port link status now.
+ """
+ return self.get_detail_from_port_info("Link status: ", "\d+", port_id)
+
+ def get_port_link_speed(self, port_id):
+ """
+ Get the specified port link speed now.
+ """
+ return self.get_detail_from_port_info("Link speed: ", "\d+", port_id)
+
+ def get_port_link_duplex(self, port_id):
+ """
+ Get the specified port link mode, duplex or siplex.
+ """
+ return self.get_detail_from_port_info("Link duplex: ", "\S+", port_id)
+
+ def get_port_promiscuous_mode(self, port_id):
+ """
+ Get the promiscuous mode of port.
+ """
+ return self.get_detail_from_port_info("Promiscuous mode: ", "\S+", port_id)
+
+ def get_port_allmulticast_mode(self, port_id):
+ """
+ Get the allmulticast mode of port.
+ """
+ return self.get_detail_from_port_info("Allmulticast mode: ", "\S+", port_id)
+
+ def get_port_vlan_offload(self, port_id):
+ """
+ Function: get the port vlan settting info.
+ return value:
+ 'strip':'on'
+ 'filter':'on'
+ 'qinq':'off'
+ """
+ vlan_info = {}
+ vlan_info['strip'] = self.get_detail_from_port_info(
+ "strip ", '\S+', port_id)
+ vlan_info['filter'] = self.get_detail_from_port_info(
+ 'filter', '\S+', port_id)
+ vlan_info['qinq'] = self.get_detail_from_port_info(
+ 'qinq\(extend\) ', '\S+', port_id)
+ return vlan_info
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 14/19] Change some codes to support network device instantiation and virtualization test
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (12 preceding siblings ...)
2015-05-22 9:04 ` [dts] [PATCH v2 13/19] Add some base functions to get the device info in the testpmd Jiajia, Sun
@ 2015-05-22 9:04 ` Jiajia, Sun
2015-05-22 9:04 ` [dts] [PATCH v2 15/19] Add some codes to support network instantiation in the tester module Jiajia, Sun
` (4 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:04 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/dut.py | 235 +++++++++++++++++++++++++++++++++++++++-------
framework/project_dpdk.py | 29 +++---
2 files changed, 219 insertions(+), 45 deletions(-)
diff --git a/framework/dut.py b/framework/dut.py
index 5b7aba2..caaae62 100644
--- a/framework/dut.py
+++ b/framework/dut.py
@@ -33,11 +33,17 @@ import os
import re
import time
import dts
-from config import UserConf
-from settings import NICS
+import settings
+from config import PortConf
+from settings import NICS, LOG_NAME_SEP
from ssh_connection import SSHConnection
from crb import Crb
+from net_device import NetDevice
from logger import getLogger
+from virt_resource import VirtResource
+from utils import RED
+
+
class Dut(Crb):
@@ -60,20 +66,36 @@ class Dut(Crb):
def __init__(self, crb, serializer):
super(Dut, self).__init__(crb, serializer)
self.NAME = 'dut'
+
+ self.host_init_flag = 0
self.logger = getLogger(self.NAME)
self.session = SSHConnection(self.get_ip_address(), self.NAME,
self.get_password())
self.session.init_log(self.logger)
- self.alt_session = SSHConnection(self.get_ip_address(), self.NAME + '_alt',
- self.get_password())
+ self.alt_session = SSHConnection(
+ self.get_ip_address(),
+ self.NAME + '_alt',
+ self.get_password())
self.alt_session.init_log(self.logger)
self.number_of_cores = 0
self.tester = None
self.cores = []
self.architecture = None
self.ports_info = None
- self.conf = UserConf()
+ self.conf = PortConf()
self.ports_map = []
+ self.virt_pool = None
+
+ def init_host_session(self):
+ if self.host_init_flag:
+ pass
+ else:
+ self.host_session = SSHConnection(
+ self.get_ip_address(),
+ self.NAME + '_host',
+ self.get_password())
+ self.host_session.init_log(self.logger)
+ self.host_init_flag = 1
def change_config_option(self, target, parameter, value):
"""
@@ -82,12 +104,12 @@ class Dut(Crb):
self.send_expect("sed -i 's/%s=.*$/%s=%s/' config/defconfig_%s" %
(parameter, parameter, value, target), "# ")
- def set_nic_type(self, nic):
+ def set_nic_type(self, nic_type):
"""
Set CRB NICS ready to validated.
"""
- self.nic = nic
- if 'cfg' in nic:
+ self.nic_type = nic_type
+ if 'cfg' in nic_type:
self.conf.load_ports_config(self.get_ip_address())
def set_toolchain(self, target):
@@ -167,11 +189,17 @@ class Dut(Crb):
self.mount_procfs()
# auto detect network topology
self.map_available_ports()
+ # disable tester port ipv6
+ self.disable_tester_ipv6()
# print latest ports_info
- self.logger.info(dts.pprint(self.ports_info))
+ for port_info in self.ports_info:
+ self.logger.info(port_info)
if self.ports_map is None or len(self.ports_map) == 0:
raise ValueError("ports_map should not be empty, please check all links")
+ # initialize virtualization resource pool
+ self.virt_pool = VirtResource(self)
+
def restore_interfaces(self):
"""
Restore all ports's interfaces.
@@ -195,20 +223,22 @@ class Dut(Crb):
pci_bus = port['pci']
pci_id = port['type']
# get device driver
- driver = dts.get_nic_driver(pci_id)
+ driver = settings.get_nic_driver(pci_id)
if driver is not None:
# unbind device driver
addr_array = pci_bus.split(':')
bus_id = addr_array[0]
devfun_id = addr_array[1]
+ port = NetDevice(self, bus_id, devfun_id)
+
self.send_expect('echo 0000:%s > /sys/bus/pci/devices/0000\:%s\:%s/driver/unbind'
% (pci_bus, bus_id, devfun_id), '# ')
# bind to linux kernel driver
self.send_expect('modprobe %s' % driver, '# ')
self.send_expect('echo 0000:%s > /sys/bus/pci/drivers/%s/bind'
% (pci_bus, driver), '# ')
- itf = self.get_interface_name(addr_array[0], addr_array[1])
+ itf = port.get_interface_name()
self.send_expect("ifconfig %s up" % itf, "# ")
else:
self.logger.info("NOT FOUND DRIVER FOR PORT (%s|%s)!!!" % (pci_bus, pci_id))
@@ -265,6 +295,20 @@ class Dut(Crb):
return 'taskset %s ' % core
+ def is_ssh_session_port(self, pci_bus):
+ """
+ Check if the pci device is the dut SSH session port.
+ """
+ port = None
+ for port_info in self.ports_info:
+ if pci_bus == port_info['pci']:
+ port = port_info['port']
+ break
+ if port and port.get_ipv4_addr() == crbs['IP'].strip():
+ return True
+ else:
+ return False
+
def bind_interfaces_linux(self, driver='igb_uio', nics_to_bind=None):
"""
Bind the interfaces to the selected driver. nics_to_bind can be None
@@ -275,12 +319,17 @@ class Dut(Crb):
current_nic = 0
for (pci_bus, pci_id) in self.pci_devices_info:
- if dts.accepted_nic(pci_id):
+ if settings.accepted_nic(pci_id):
+ if self.is_ssh_session_port(pci_bus):
+ continue
if nics_to_bind is None or current_nic in nics_to_bind:
binding_list += '%s ' % (pci_bus)
current_nic += 1
+ if current_nic == 0:
+ self.logger.info("Not nic need bind driver: %s" % driver)
+ return
self.send_expect('tools/dpdk_nic_bind.py %s' % binding_list, '# ')
@@ -293,13 +342,19 @@ class Dut(Crb):
current_nic = 0
for (pci_bus, pci_id) in self.pci_devices_info:
- if dts.accepted_nic(pci_id):
+ if settings.accepted_nic(pci_id):
+ if self.is_ssh_session_port(pci_bus):
+ continue
if nics_to_bind is None or current_nic in nics_to_bind:
binding_list += '%s ' % (pci_bus)
current_nic += 1
+ if current_nic == 0:
+ self.logger.info("Not nic need unbind driver")
+ return
+
self.send_expect('tools/dpdk_nic_bind.py %s' % binding_list, '# ', 30)
def get_ports(self, nic_type='any', perf=None, socket=None):
@@ -321,7 +376,10 @@ class Dut(Crb):
elif nic_type == 'cfg':
for portid in range(len(self.ports_info)):
if self.ports_info[portid]['source'] == 'cfg':
- ports.append(portid)
+ if (socket is None or
+ self.ports_info[portid]['numa'] == -1 or
+ socket == self.ports_info[portid]['numa']):
+ ports.append(portid)
return ports
else:
for portid in range(len(self.ports_info)):
@@ -440,36 +498,38 @@ class Dut(Crb):
Check that whether auto scanned ports ready to use
"""
pci_addr = "%s:%s" % (pci_bus, pci_id)
- if self.nic == 'any':
+ if self.nic_type == 'any':
return True
- elif self.nic == 'cfg':
+ elif self.nic_type == 'cfg':
if self.conf.check_port_available(pci_bus) is True:
return True
- elif self.nic not in NICS.keys():
- self.logger.warning("NOT SUPPORTED NIC TYPE: %s" % self.nic)
+ elif self.nic_type not in NICS.keys():
+ self.logger.warning("NOT SUPPORTED NIC TYPE: %s" % self.nic_type)
else:
- codename = NICS[self.nic]
+ codename = NICS[self.nic_type]
if pci_id == codename:
return True
return False
def rescan_ports(self):
- unknow_interface = dts.RED('Skipped: unknow_interface')
+ unknow_interface = RED('Skipped: unknow_interface')
for port_info in self.ports_info:
pci_bus = port_info['pci']
addr_array = pci_bus.split(':')
bus_id = addr_array[0]
devfun_id = addr_array[1]
- intf = self.get_interface_name(bus_id, devfun_id)
+
+ port = NetDevice(self, bus_id, devfun_id)
+ intf = port.get_interface_name()
if "No such file" in intf:
self.logger.info("DUT: [0000:%s] %s" % (pci_bus, unknow_interface))
out = self.send_expect("ip link show %s" % intf, "# ")
if "DOWN" in out:
self.send_expect("ip link set %s up" % intf, "# ")
time.sleep(5)
- macaddr = self.get_mac_addr(intf, bus_id, devfun_id)
+ macaddr = port.get_mac_addr()
out = self.send_expect("ip -family inet6 address show dev %s | awk '/inet6/ { print $2 }'"
% intf, "# ")
ipv6 = out.split('/')[0]
@@ -481,16 +541,32 @@ class Dut(Crb):
port_info['intf'] = intf
port_info['ipv6'] = ipv6
+ def load_serializer_ports(self):
+ self.ports_info = []
+ cached_ports_info = self.serializer.load(self.PORT_INFO_CACHE_KEY)
+ if cached_ports_info is None:
+ return
+ for port in cached_ports_info:
+ self.ports_info.append({'pci': port['pci'], 'type': port['type'],
+ 'numa': port['numa']})
+
+ def save_serializer_ports(self):
+ cached_ports_info = []
+ for port in self.ports_info:
+ cached_ports_info.append({'pci': port['pci'], 'type': port['type'],
+ 'numa': port['numa']})
+ self.serializer.save(self.PORT_INFO_CACHE_KEY, cached_ports_info)
+
def scan_ports(self):
"""
Scan ports information or just read it from cache file.
"""
if self.read_cache:
- self.ports_info = self.serializer.load(self.PORT_INFO_CACHE_KEY)
+ self.load_serializer_ports()
if not self.read_cache or self.ports_info is None:
self.scan_ports_uncached()
- self.serializer.save(self.PORT_INFO_CACHE_KEY, self.ports_info)
+ self.save_serializer_ports()
def scan_ports_uncached(self):
"""
@@ -505,8 +581,8 @@ class Dut(Crb):
"""
self.ports_info = []
- skipped = dts.RED('Skipped: Unknown/not selected')
- unknow_interface = dts.RED('Skipped: unknow_interface')
+ skipped = RED('Skipped: Unknown/not selected')
+ unknow_interface = RED('Skipped: unknow_interface')
for (pci_bus, pci_id) in self.pci_devices_info:
if self.check_ports_available(pci_bus, pci_id) is False:
@@ -518,9 +594,11 @@ class Dut(Crb):
bus_id = addr_array[0]
devfun_id = addr_array[1]
+ port = NetDevice(self, bus_id, devfun_id)
numa = self.get_device_numa(bus_id, devfun_id)
# store the port info to port mapping
- self.ports_info.append({'pci': pci_bus, 'type': pci_id, 'numa': numa})
+ self.ports_info.append(
+ {'port': port, 'pci': pci_bus, 'type': pci_id, 'numa': numa})
def scan_ports_uncached_freebsd(self):
"""
@@ -528,16 +606,17 @@ class Dut(Crb):
"""
self.ports_info = []
- skipped = dts.RED('Skipped: Unknown/not selected')
+ skipped = RED('Skipped: Unknown/not selected')
for (pci_bus, pci_id) in self.pci_devices_info:
- if not dts.accepted_nic(pci_id):
+ if not setttings.accepted_nic(pci_id):
self.logger.info("DUT: [%s %s] %s" % (pci_bus, pci_id,
skipped))
continue
- intf = self.get_interface_name(pci_bus)
+ port = NetDevice(self, pci_bus, '')
+ intf = port.get_interface_name(pci_bus)
macaddr = self.get_mac_addr(intf)
ipv6 = self.get_ipv6_addr(intf)
@@ -560,9 +639,69 @@ class Dut(Crb):
pci_str = "%s:%s.%s" % (pci_bus_id, pci_dev_str, pci_split[2])
# store the port info to port mapping
- self.ports_info.append({'pci': pci_str, 'type': pci_id, 'intf':
+ self.ports_info.append({'port': port, 'pci': pci_str, 'type': pci_id, 'intf':
intf, 'mac': macaddr, 'ipv6': ipv6, 'numa': -1})
+ def generate_sriov_vfs_by_port(self, port_id, vf_num, driver='default'):
+ """
+ Generate SRIOV VFs with default driver it is bound now or specifid driver.
+ """
+ port = self.ports_info[port_id]['port']
+ port_driver = port.get_nic_driver()
+
+ if driver == 'default':
+ if not port_driver:
+ self.logger.info(
+ "No driver on specified port, can not generate SRIOV VF.")
+ return None
+ else:
+ if port_driver != driver:
+ port.bind_driver(driver)
+ port.generate_sriov_vfs(vf_num)
+
+ # append the VF PCIs into the ports_info
+ sriov_vfs_pci = port.get_sriov_vfs_pci()
+ self.ports_info[port_id]['sriov_vfs_pci'] = sriov_vfs_pci
+
+ # instantiate the VF with NetDevice
+ vfs_port = []
+ for vf_pci in sriov_vfs_pci:
+ addr_array = vf_pci.split(':')
+ bus_id = addr_array[0]
+ devfun_id = addr_array[1]
+ vf_port = NetDevice(self, bus_id, devfun_id)
+ vfs_port.append(vf_port)
+ self.ports_info[port_id]['vfs_port'] = vfs_port
+
+ pci = self.ports_info[port_id]['pci']
+ self.virt_pool.add_vf_on_pf(pf_pci=pci, vflist=sriov_vfs_pci)
+
+ def destroy_sriov_vfs_by_port(self, port_id):
+ port = self.ports_info[port_id]['port']
+ vflist = []
+ port_driver = port.get_nic_driver()
+ if 'sriov_vfs_pci' in self.ports_info[port_id] and \
+ self.ports_info[port_id]['sriov_vfs_pci']:
+ vflist = self.ports_info[port_id]['sriov_vfs_pci']
+ else:
+ if not port.get_sriov_vfs_pci():
+ return
+
+ if not port_driver:
+ self.logger.info(
+ "No driver on specified port, skip destroy SRIOV VF.")
+ else:
+ sriov_vfs_pci = port.destroy_sriov_vfs()
+ self.ports_info[port_id]['sriov_vfs_pci'] = []
+ self.ports_info[port_id]['vfs_port'] = []
+
+ pci = self.ports_info[port_id]['pci']
+ self.virt_pool.del_vf_on_pf(pf_pci=pci, vflist=vflist)
+
+ def get_vm_core_list(self):
+ return VMCORELIST[self.crb['VM CoreList']]
+
+
def load_portconf(self):
"""
Load port configurations for ports_info. If manually configured infor
@@ -637,7 +776,11 @@ class Dut(Crb):
if ipv6 == "Not connected":
continue
- out = self.tester.send_ping6(remotePort, ipv6, self.get_mac_address(dutPort))
+ if getattr(self, 'send_ping6', None):
+ self.send_ping6(
+ dutPort, self.tester.ports_info[remotePort]['ipv6'])
+ out = self.tester.send_ping6(
+ remotePort, ipv6, self.get_mac_address(dutPort))
if ('64 bytes from' in out):
self.logger.info("PORT MAP: [dut %d: tester %d]" % (dutPort, remotePort))
@@ -656,3 +799,31 @@ class Dut(Crb):
for port in remove:
self.ports_info.remove(port)
+
+ def disable_tester_ipv6(self):
+ for tester_port in self.ports_map:
+ intf = self.tester.get_interface(tester_port)
+ self.tester.disable_ipv6(intf)
+
+ def enable_tester_ipv6(self):
+ for tester_port in self.ports_map:
+ intf = self.tester.get_interface(tester_port)
+ self.tester.enable_ipv6(intf)
+
+ def check_port_occupied(self, port):
+ out = self.alt_session.send_expect('lsof -i:%d' % port, '# ')
+ if out == '':
+ return False
+ else:
+ return True
+
+ def get_maximal_vnc_num(self):
+ out = self.send_expect("ps aux | grep '\-vnc' | grep -v grep", '# ')
+ if out:
+ ports = re.findall(r'-vnc .*?:(\d+)', out)
+ for num in range(len(ports)):
+ ports[num] = int(ports[num])
+ ports.sort()
+ else:
+ ports = [0, ]
+ return ports[-1]
diff --git a/framework/project_dpdk.py b/framework/project_dpdk.py
index 8963924..0b94b99 100644
--- a/framework/project_dpdk.py
+++ b/framework/project_dpdk.py
@@ -39,7 +39,7 @@ from crb import Crb
from dut import Dut
from tester import Tester
from logger import getLogger
-from settings import IXIA
+from settings import IXIA, accepted_nic
class DPDKdut(Dut):
@@ -50,8 +50,8 @@ class DPDKdut(Dut):
"""
def __init__(self, crb, serializer):
- self.NAME = 'dut'
super(DPDKdut, self).__init__(crb, serializer)
+ self.testpmd = None
def set_target(self, target):
"""
@@ -60,6 +60,7 @@ class DPDKdut(Dut):
Set hugepage on DUT and install modules required by DPDK.
Configure default ixgbe PMD function.
"""
+ self.target = target
self.set_toolchain(target)
# set env variable
@@ -110,7 +111,7 @@ class DPDKdut(Dut):
binding_list = ''
for (pci_bus, pci_id) in self.pci_devices_info:
- if dts.accepted_nic(pci_id):
+ if accepted_nic(pci_id):
binding_list += '%s,' % (pci_bus)
self.send_expect("kldunload if_ixgbe.ko", "#")
@@ -191,10 +192,7 @@ class DPDKdut(Dut):
assert ("Error" not in out), "Compilation error..."
assert ("No rule to make" not in out), "No rule to make error..."
- def prerequisites(self, pkgName, patch):
- """
- Copy DPDK package to DUT and apply patch files.
- """
+ def prepare_package(self, pkgName, patch):
if not self.skip_setup:
assert (os.path.isfile(pkgName) is True), "Invalid package"
@@ -249,6 +247,11 @@ class DPDKdut(Dut):
(self.base_dir, dst_dir + p), "# ")
assert "****" not in out
+ def prerequisites(self, pkgName, patch):
+ """
+ Copy DPDK package to DUT and apply patch files.
+ """
+ self.prepare_package(pkgName, patch)
self.dut_prerequisites()
def bind_interfaces_linux(self, driver='igb_uio', nics_to_bind=None):
@@ -354,7 +357,7 @@ class DPDKtester(Tester):
total_huge_pages = self.get_total_huge_pages()
if total_huge_pages == 0:
self.mount_huge_pages()
- self.set_huge_pages(4096)
+ self.set_huge_pages(1024)
self.session.copy_file_to("dep/tgen.tgz")
self.session.copy_file_to("dep/tclclient.tgz")
@@ -386,10 +389,10 @@ class DPDKtester(Tester):
"""
hugepages_size = self.send_expect("awk '/Hugepagesize/ {print $2}' /proc/meminfo", "# ")
- if int(hugepages_size) < (1024 * 1024):
- arch_huge_pages = hugepages if hugepages > 0 else 4096
+ if int(hugepages_size) < (2048 * 2048):
+ arch_huge_pages = hugepages if hugepages > 0 else 2048
total_huge_pages = self.get_total_huge_pages()
- self.mount_huge_pages()
- if total_huge_pages != arch_huge_pages:
- self.set_huge_pages(arch_huge_pages)
+ self.mount_huge_pages()
+ if total_huge_pages != arch_huge_pages:
+ self.set_huge_pages(arch_huge_pages)
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 15/19] Add some codes to support network instantiation in the tester module
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (13 preceding siblings ...)
2015-05-22 9:04 ` [dts] [PATCH v2 14/19] Change some codes to support network device instantiation and virtualization test Jiajia, Sun
@ 2015-05-22 9:04 ` Jiajia, Sun
2015-05-22 9:04 ` [dts] [PATCH v2 16/19] Make test_case know its suite name Jiajia, Sun
` (3 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:04 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/tester.py | 51 +++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 43 insertions(+), 8 deletions(-)
diff --git a/framework/tester.py b/framework/tester.py
index aba0356..ce136e4 100644
--- a/framework/tester.py
+++ b/framework/tester.py
@@ -38,6 +38,7 @@ from time import sleep
from settings import NICS
from ssh_connection import SSHConnection
from crb import Crb
+from net_device import NetDevice
from etgen import IxiaPacketGenerator, SoftwarePacketGenerator
from logger import getLogger
from settings import IXIA
@@ -152,6 +153,7 @@ class Tester(Crb):
index += 1
if pci == port['pci']:
return index
+ return -1
def get_pci(self, localPort):
"""
@@ -163,6 +165,9 @@ class Tester(Crb):
"""
Return tester local port interface name.
"""
+ if 'intf' not in self.ports_info[localPort]:
+ return 'N/A'
+
return self.ports_info[localPort]['intf']
def get_mac(self, localPort):
@@ -202,26 +207,51 @@ class Tester(Crb):
try:
for (pci_bus, pci_id) in self.pci_devices_info:
addr_array = pci_bus.split(':')
- itf = self.get_interface_name(addr_array[0], addr_array[1])
+ port = NetDevice(self, addr_array[0], addr_array[1])
+ itf = port.get_interface_name()
+ self.enable_ipv6(itf)
self.send_expect("ifconfig %s up" % itf, "# ")
except Exception as e:
self.logger.error(" !!! Restore ITF: " + e.message)
+ sleep(2)
+
+ def load_serializer_ports(self):
+ self.ports_info = []
+ cached_ports_info = self.serializer.load(self.PORT_INFO_CACHE_KEY)
+ if cached_ports_info is None:
+ return
+
+ # now not save netdev object, will implemented later
+ self.ports_info = cached_ports_info
+
+ def save_serializer_ports(self):
+ cached_ports_info = []
+ for port in self.ports_info:
+ port_info = {}
+ for key in port.keys():
+ if type(port[key]) is str:
+ port_info[key] = port[key]
+ # need save netdev objects
+ cached_ports_info.append(port_info)
+ self.serializer.save(self.PORT_INFO_CACHE_KEY, cached_ports_info)
+
def scan_ports(self):
"""
Scan all ports on tester and save port's pci/mac/interface.
"""
if self.read_cache:
- self.ports_info = self.serializer.load(self.PORT_INFO_CACHE_KEY)
+ self.load_serializer_ports()
if not self.read_cache or self.ports_info is None:
self.scan_ports_uncached()
if self.it_uses_external_generator():
self.ports_info.extend(self.ixia_packet_gen.get_ports())
- self.serializer.save(self.PORT_INFO_CACHE_KEY, self.ports_info)
+ self.save_serializer_ports()
- self.logger.info(self.ports_info)
+ for port_info in self.ports_info:
+ self.logger.info(port_info)
def scan_ports_uncached(self):
"""
@@ -240,7 +270,8 @@ class Tester(Crb):
bus_id = addr_array[0]
devfun_id = addr_array[1]
- intf = self.get_interface_name(bus_id, devfun_id)
+ port = NetDevice(self, bus_id, devfun_id)
+ intf = port.get_interface_name()
if "No such file" in intf:
self.logger.info("Tester: [000:%s %s] %s" % (pci_bus, pci_id,
@@ -248,13 +279,17 @@ class Tester(Crb):
continue
self.logger.info("Tester: [000:%s %s] %s" % (pci_bus, pci_id, intf))
- macaddr = self.get_mac_addr(intf, bus_id, devfun_id)
+ macaddr = port.get_mac_addr()
+
+ ipv6 = port.get_ipv6_addr()
# store the port info to port mapping
- self.ports_info.append({'pci': pci_bus,
+ self.ports_info.append({'port': port,
+ 'pci': pci_bus,
'type': pci_id,
'intf': intf,
- 'mac': macaddr})
+ 'mac': macaddr,
+ 'ipv6': ipv6})
def send_ping6(self, localPort, ipv6, mac):
"""
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 16/19] Make test_case know its suite name
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (14 preceding siblings ...)
2015-05-22 9:04 ` [dts] [PATCH v2 15/19] Add some codes to support network instantiation in the tester module Jiajia, Sun
@ 2015-05-22 9:04 ` Jiajia, Sun
2015-05-22 9:04 ` [dts] [PATCH v2 17/19] Add a global virtualization config and a config related to SRIOV KVM suite Jiajia, Sun
` (2 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:04 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/test_case.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/framework/test_case.py b/framework/test_case.py
index 3d2e2dc..a519691 100644
--- a/framework/test_case.py
+++ b/framework/test_case.py
@@ -40,10 +40,11 @@ from settings import DRIVERS, NICS, nic_name_from_type
class TestCase(object):
- def __init__(self, dut, tester, target):
+ def __init__(self, dut, tester, target, suite):
self.dut = dut
self.tester = tester
self.target = target
+ self.suite = suite
self.nics = []
for portid in range(len(self.dut.ports_info)):
nic_type = self.dut.ports_info[portid]['type']
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 17/19] Add a global virtualization config and a config related to SRIOV KVM suite
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (15 preceding siblings ...)
2015-05-22 9:04 ` [dts] [PATCH v2 16/19] Make test_case know its suite name Jiajia, Sun
@ 2015-05-22 9:04 ` Jiajia, Sun
2015-05-22 9:04 ` [dts] [PATCH v2 18/19] Add a test plan of how to test SRIOV on the KVM ENV Jiajia, Sun
2015-05-22 9:04 ` [dts] [PATCH v2 19/19] Add a test suite to verify the SRIOV feature " Jiajia, Sun
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:04 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
conf/sriov_kvm.cfg | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++
conf/virt_global.cfg | 24 ++++++++
2 files changed, 188 insertions(+)
create mode 100644 conf/sriov_kvm.cfg
create mode 100644 conf/virt_global.cfg
diff --git a/conf/sriov_kvm.cfg b/conf/sriov_kvm.cfg
new file mode 100644
index 0000000..8db36bb
--- /dev/null
+++ b/conf/sriov_kvm.cfg
@@ -0,0 +1,164 @@
+# QEMU options
+# name
+# name: vm0
+#
+# enable_kvm
+# enable: [yes | no]
+#
+# cpu
+# model: [host | core2duo | ...]
+# usage:
+# choose model value from the command
+# qemu-system-x86_64 -cpu help
+# number: '4' #number of vcpus
+# cpupin: '3 4 5 6' # host cpu list
+#
+# mem
+# size: 1024
+#
+# disk
+# file: /path/to/image/test.img
+#
+# net
+# type: [nic | user | tap | bridge | ...]
+# nic
+# opt_vlan: 0
+# note: Default is 0.
+# opt_macaddr: 00:00:00:00:01:01
+# note: if creating a nic, it`s better to specify a MAC,
+# else it will get a random number.
+# opt_model:["e1000" | "virtio" | "i82551" | ...]
+# note: Default is e1000.
+# opt_name: 'nic1'
+# opt_addr: ''
+# note: PCI cards only.
+# opt_vectors:
+# note: This option currently only affects virtio cards.
+# user
+# opt_vlan: 0
+# note: default is 0.
+# opt_hostfwd: [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport
+# note: If not specified, it will be setted automatically.
+# tap
+# opt_vlan: 0
+# note: default is 0.
+# opt_br: br0
+# note: if choosing tap, need to specify bridge name,
+# else it will be br0.
+# opt_script: QEMU_IFUP_PATH
+# note: if not specified, default is self.QEMU_IFUP_PATH.
+# opt_downscript: QEMU_IFDOWN_PATH
+# note: if not specified, default is self.QEMU_IFDOWN_PATH.
+#
+# device
+# driver: [pci-assign | virtio-net-pci | ...]
+# pci-assign
+# prop_host: 08:00.0
+# prop_addr: 00:00:00:00:01:02
+# virtio-net-pci
+# prop_netdev: mynet1
+# prop_id: net1
+# prop_mac: 00:00:00:00:01:03
+# prop_bus: pci.0
+# prop_addr: 0x3
+#
+# monitor
+# port: 6061
+# note: if adding monitor to vm, need to specicy
+# this port, else it will get a free port
+# on the host machine.
+#
+# qga
+# enable: [yes | no]
+#
+# serial_port
+# enable: [yes | no]
+#
+# vnc
+# displayNum: 1
+# note: you can choose a number not used on the host.
+#
+# daemon
+# enable: 'yes'
+# note:
+# By default VM will start with the daemonize status.
+# Not support starting it on the stdin now.
+
+
+# vm configuration for pmd sriov case
+[vm0]
+cpu =
+ model=host,number=4,cpupin=5 6 7 8;
+disk =
+ file=/home/image/vdisk01-sriov-fc20.img;
+login =
+ user=root,password=tester;
+net =
+ type=nic,opt_vlan=0;
+ type=user,opt_vlan=0;
+monitor =
+ port=;
+qga =
+ enable=yes;
+vnc =
+ displayNum=1;
+daemon =
+ enable=yes;
+
+[vm1]
+cpu =
+ model=host,number=4,cpupin=9 10 11 12;
+disk =
+ file=/home/image/vdisk02-sriov-fc20.img;
+login =
+ user=root,password=tester;
+net =
+ type=nic,opt_vlan=1;
+ type=user,opt_vlan=1;
+monitor =
+ port=;
+qga =
+ enable=yes;
+vnc =
+ displayNum=2;
+daemon =
+ enable=yes;
+
+[vm2]
+cpu =
+ model=host,number=4,cpupin=13 14 15 16;
+disk =
+ file=/home/image/vdisk03-ivshmem-fc20.img;
+login =
+ user=root,password=tester;
+net =
+ type=nic,opt_vlan=3;
+ type=tap,opt_vlan=3,opt_br=br0;
+monitor =
+ port=;
+qga =
+ enable=yes;
+vnc =
+ displayNum=3;
+daemon =
+ enable=yes;
+
+[vm3]
+cpu =
+ model=host,number=4,cpupin=17 18 19 20;
+disk =
+ file=/home/image/vdisk04-ivshmem-fc20.img;
+login =
+ user=root,password=tester;
+net =
+ type=nic,opt_vlan=4;
+ type=tap,opt_vlan=4,opt_br=br0;
+monitor =
+ port=;
+qga =
+ enable=yes;
+vnc =
+ displayNum=4;
+daemon =
+ enable=yes;
+
diff --git a/conf/virt_global.cfg b/conf/virt_global.cfg
new file mode 100644
index 0000000..f26a90c
--- /dev/null
+++ b/conf/virt_global.cfg
@@ -0,0 +1,24 @@
+# virtualization global configurations
+#[LIBVIRT]
+#[KVM]
+#[XEN]
+[LIBVIRT]
+cpu =
+ number=4,cpupin=3 4 5 6;
+mem =
+ size=2048;
+net =
+ local=unused
+[KVM]
+cpu =
+ model=host,number=4,cpupin=3 4 5 6;
+mem =
+ size=2048;
+[XEN]
+cpu =
+ number=4,cpupin=3 4 5 6;
+mem =
+ size=2048;
+vif =
+ mac=random,bridge=br0
+
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 18/19] Add a test plan of how to test SRIOV on the KVM ENV
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (16 preceding siblings ...)
2015-05-22 9:04 ` [dts] [PATCH v2 17/19] Add a global virtualization config and a config related to SRIOV KVM suite Jiajia, Sun
@ 2015-05-22 9:04 ` Jiajia, Sun
2015-05-22 9:04 ` [dts] [PATCH v2 19/19] Add a test suite to verify the SRIOV feature " Jiajia, Sun
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:04 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
test_plans/sriov_kvm_test_plan.rst | 756 +++++++++++++++++++++++++++++++++++++
1 file changed, 756 insertions(+)
create mode 100644 test_plans/sriov_kvm_test_plan.rst
diff --git a/test_plans/sriov_kvm_test_plan.rst b/test_plans/sriov_kvm_test_plan.rst
new file mode 100644
index 0000000..52dd0ca
--- /dev/null
+++ b/test_plans/sriov_kvm_test_plan.rst
@@ -0,0 +1,756 @@
+.. Copyright (c) <2013>, Intel Corporation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ - Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ OF THE POSSIBILITY OF SUCH DAMAGE.
+
+===============================
+SRIOV and InterVM Communication
+===============================
+
+Some applications such as pipelining of virtual appliances and traffic
+mirroring to virtual appliances require the high performance InterVM
+communications.
+
+The testpmd application is used to configure traffic mirroring, PF VM receive
+mode, PFUTA hash table and control traffic to a VF for inter-VM communication.
+
+The 82599 supports four separate mirroring rules, each associated with a
+destination pool. Each rule is programmed with one of the four mirroring types:
+
+1. Pool mirroring: reflect all the packets received to a pool from the network.
+2. Uplink port mirroring: reflect all the traffic received from the network.
+3. Downlink port mirroring: reflect all the traffic transmitted to the
+ network.
+4. VLAN mirroring: reflect all the traffic received from the network
+ in a set of given VLANs (either from the network or from local VMs).
+
+
+Prerequisites for all 2VMs cases/Mirror 2VMs cases
+==================================================
+
+Create two VF interface VF0 and VF1 from one PF interface and then attach them
+to VM0 and VM1. Suppose PF is 0000:08:00.0.Below are commands which can be
+used to generate 2VFs and make them in pci-stub modes.::
+
+ ./tools/pci_unbind.py --bind=igb_uio 0000:08:00.0
+ echo 2 > /sys/bus/pci/devices/0000\:08\:00.0/max_vfs
+ echo "8086 10ed" > /sys/bus/pci/drivers/pci-stub/new_id
+ echo 0000:08:10.0 >/sys/bus/pci/devices/0000\:08\:10.0/driver/unbind
+ echo 0000:08:10.2 >/sys/bus/pci/devices/0000\:08\:10.2/driver/unbind
+ echo 0000:08:10.0 >/sys/bus/pci/drivers/pci-stub/bind
+ echo 0000:08:10.0 >/sys/bus/pci/drivers/pci-stub/bind
+
+Start PF driver on the Host and skip the VFs.::
+
+ ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -b 0000:08:10.0 -b 0000:08:10.2 -- -i
+
+For VM0 start up command, you can refer to below command.::
+
+ qemu-system-x86_64 -name vm0 -enable-kvm -m 2048 -smp 4 -cpu host -drive file=/root/Downloads/vm0.img -net nic,macaddr=00:00:00:00:00:01 -net tap,script=/etc/qemu-ifup -device pci-assign,host=08:10.0 -vnc :1 --daemonize
+
+The /etc/qemu-ifup can be below script, need you to create first::
+
+ #!/bin/sh
+ set -x
+ switch=br0
+ if [ -n "$1" ];then
+ /usr/sbin/tunctl -u `whoami` -t $1
+ /sbin/ip link set $1 up
+ sleep 0.5s
+ /usr/sbin/brctl addif $switch $1
+ exit 0
+ else
+ echo "Error: no interface specified"
+ exit 1
+ fi
+
+Similar for VM1, please refer to below command for VM1::
+
+ qemu-system-x86_64 -name vm1 -enable-kvm -m 2048 -smp 4 -cpu host -drive file=/root/Downloads/vm1.img -net nic,macaddr=00:00:00:00:00:02 -net tap,script=/etc/qemu-ifup -device pci-assign,host=08:10.2 -vnc :4 -daemonize
+
+If you want to run all common 2VM cases, please run testpmd on VM0 and VM1 and
+start traffic forward on the VM hosts. Some specific prerequisites need to be
+set up in each case::
+
+ VF0 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
+ VF0 testpmd-> set fwd rxonly
+ VF0 testpmd-> start
+
+ VF1 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
+ VF1 testpmd-> set fwd mac
+ VF1 testpmd-> start
+
+Test Case1: InterVM communication test on 2VMs
+==============================================
+
+Set the VF0 destination mac address to VF1 mac address, packets send from VF0
+will be forwarded to VF1 and then send out::
+
+ VF1 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
+ VF1 testpmd-> show port info 0
+ VF1 testpmd-> set fwd mac
+ VF1 testpmd-> start
+
+ VF0 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- --eth-peer=0,"VF1 mac" -i
+ VF0 testpmd-> set fwd mac
+ VF0 testpmd-> start
+
+Send 10 packets with VF0 mac address and make sure the packets will be
+forwarded by VF1.
+
+Test Case2: Mirror Traffic between 2VMs with Pool mirroring
+===========================================================
+
+Set up common 2VM prerequisites.
+
+Add one mirror rule that will mirror VM0 income traffic to VM1::
+
+ PF testpmd-> set port 0 mirror-rule 0 pool-mirror 0x1 dst-pool 1 on
+
+Send 10 packets to VM0 and verify the packets has been mirrored to VM1 and
+forwarded the packet.
+
+After test need reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+
+
+Test Case3: Mirror Traffic between 2VMs with Uplink mirroring
+=============================================================
+
+Set up common 2VM prerequisites.
+
+Add one mirror rule that will mirror VM0 income traffic to VM1::
+
+ PF testpmd-> set port 0 mirror-rule 0 uplink-mirror dst-pool 1 on
+
+Send 10 packets to VM0 and verify the packets has been mirrored to VM1 and
+forwarded the packet.
+
+After test need reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+
+Test Case4: Mirror Traffic between 2VMs with Downlink mirroring
+===============================================================
+
+Run testpmd on VM0 and VM1 and start traffic forward on the VM hosts::
+
+ VF0 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
+ VF1 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
+
+
+Add one mirror rule that will mirror VM0 outcome traffic to VM1::
+
+ PF testpmd-> set port 0 mirror-rule 0 downlink-mirror dst-pool 1 on
+
+Make sure VM1 in receive only mode, VM0 send 16 packets, and verify the VM0
+packets has been mirrored to VM1::
+
+ VF1 testpmd-> set fwd rxonly
+ VF1 testpmd-> start
+ VF0 testpmd-> start tx_first
+
+Note: don't let VF1 fwd packets since downlink mirror will mirror back the
+packets to received packets, which will be an infinite loop.
+
+After test need reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+
+Test Case5: Mirror Traffic between VMs with Vlan mirroring
+==========================================================
+
+Set up common 2VM prerequisites.
+
+Add rx vlan-id 0 on VF0, add one mirror rule that will mirror VM0 income
+traffic with specified vlan to VM1::
+
+ PF testpmd-> rx_vlan add 0 port 0 vf 0x1
+ PF testpmd-> set port 0 mirror-rule 0 vlan-mirror 0 dst-pool 1 on
+
+Send 10 packets with vlan-id0/vm0 MAC to VM0 and verify the packets has been
+mirrored to VM1 and forwarded the packet.
+
+After test need reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+
+Test Case6: Mirror Traffic between 2VMs with Vlan & Pool mirroring
+==================================================================
+
+Set up common 2VM prerequisites.
+
+Add rx vlan-id 3 of VF1, and 2 mirror rules, one is VM0 income traffic to VM1,
+one is VM1 vlan income traffic to VM0::
+
+ PF testpmd-> rx_vlan add 3 port 0 vf 0x2
+ PF testpmd-> set port 0 mirror-rule 0 pool-mirror 0x1 dst-pool 1 on
+ PF testpmd-> set port 0 mirror-rule 1 vlan-mirror 3 dst-pool 0 on
+
+Send 2 flows one by one, first 10 packets with VM0 mac, and the second 100
+packets with VM1 vlan and mac, and verify the first 10 packets has been
+mirrored first to VM1, second 100 packets go to VM0 and the packets have been
+forwarded.
+
+After test need reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+ PF testpmd-> reset port 0 mirror-rule 1
+
+Test Case7: Mirror Traffic between 2VMs with Uplink & Downlink mirroring
+========================================================================
+
+Run testpmd on VM0 and VM1 and start traffic forward on the VM hosts::
+
+ VF0 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
+ VF1 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
+
+Add 2 mirror rules that will mirror VM0 outcome and income traffic to VM1::
+
+ PF testpmd-> set port 0 mirror-rule 0 downlink-mirror dst-pool 1 on
+ PF testpmd-> set port 0 mirror-rule 0 uplink-mirror dst-pool 1 on
+
+Make sure VM1 in receive only mode, VM0 first send 16 packets, and verify the
+VM0 packets has been mirrored to VM1::
+
+ VF1 testpmd-> set fwd rxonly
+ VF1 testpmd-> start
+ VF0 testpmd-> start tx_first
+
+Note: don't let VF1 fwd packets since downlink mirror will mirror back the
+packets to received packets, which will be an infinite loop.
+
+Send 10 packets to VF0 with VF0 MAC from ixia, verify that all VF0 received
+packets and transmitted packets will mirror to VF1::
+
+ VF0 testpmd-> stop
+ VF0 testpmd-> start
+
+After test need reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+
+Test Case8: Mirror Traffic between 2VMs with Vlan & Pool & Uplink & Downlink mirroring
+======================================================================================
+
+Run testpmd on VM0 and VM1 and start traffic forward on the VM hosts::
+
+ VF0 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
+ VF1 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
+
+
+Add rx vlan-id 0 on VF0 and add 4 mirror rules::
+
+ PF testpmd-> reset port 0 mirror-rule 1
+ PF testpmd-> set port 0 mirror-rule 0 downlink-mirror dst-pool 1 on
+ PF testpmd-> set port 0 mirror-rule 1 uplink-mirror dst-pool 1 on
+ PF testpmd-> rx_vlan add 0 port 0 vf 0x2
+ PF testpmd-> set port 0 mirror-rule 2 vlan-mirror 0 dst-pool 0 on
+ PF testpmd-> set port 0 mirror-rule 3 pool-mirror 0x1 dst-pool 1 on
+
+Make sure VM1 in receive only mode, VM0 first send 16 packets, and verify the
+VM0 packets has been mirrored to VM1, VF1, RX, 16packets (downlink mirror)::
+
+ VF1 testpmd-> set fwd rxonly
+ VF1 testpmd-> start
+ VF0 testpmd-> start tx_first
+
+Note: don't let VF1 fwd packets since downlink mirror will mirror back the
+packets to received packets, which will be an infinite loop.
+
+Send 1 packet to VF0 with VF0 MAC from ixia, check if VF0 RX 1 packet and TX 1
+packet, and VF1 has 2 packets mirror from VF0(uplink mirror/downlink/pool)::
+
+ VF0 testpmd-> stop
+ VF0 testpmd-> set fwd mac
+ VF0 testpmd-> start
+
+Send 1 packet with VM1 vlan id and mac, and verify that VF0 have 1 RX packet, 1
+TX packet, and VF1 have 2 packets(downlink mirror)::
+
+ VF0 testpmd-> stop
+ VF0 testpmd-> set fwd rxonly
+ VF0 testpmd-> start
+
+After test need reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+ PF testpmd-> reset port 0 mirror-rule 1
+ PF testpmd-> reset port 0 mirror-rule 2
+ PF testpmd-> reset port 0 mirror-rule 3
+
+
+Test Case9: Add Multi exact MAC address on VF
+=============================================
+
+Add an exact destination mac address on VF0::
+
+ PF testpmd-> mac_addr add port 0 vf 0 00:11:22:33:44:55
+
+Send 10 packets with dst mac 00:11:22:33:44:55 to VF0 and make sure VF0 will
+receive the packets.
+
+Add another exact destination mac address on VF0::
+
+ PF testpmd-> mac_addr add port 0 vf 0 00:55:44:33:22:11
+
+Send 10 packets with dst mac 00:55:44:33:22:11 to VF0 and make sure VF0 will
+receive the packets.
+
+After test need restart PF and VF for clear exact mac addresss, first quit VF,
+then quit PF.
+
+Test Case10: Enable/Disable one uta MAC address on VF
+=====================================================
+
+Enable PF promisc mode and enable VF0 accept uta packets::
+
+ PF testpmd-> set promisc 0 on
+ PF testpmd-> set port 0 vf 0 rxmode ROPE on
+
+Add an uta destination mac address on VF0::
+
+ PF testpmd-> set port 0 uta 00:11:22:33:44:55 on
+
+Send 10 packets with dst mac 00:11:22:33:44:55 to VF0 and make sure VF0 will
+the packets.
+
+Disable PF promisc mode, repeat step3, check VF0 should not accept uta packets::
+
+ PF testpmd-> set promisc 0 off
+ PF testpmd-> set port 0 vf 0 rxmode ROPE off
+
+Test Case11: Add Multi uta MAC addresses on VF
+==============================================
+
+Add 2 uta destination mac address on VF0::
+
+ PF testpmd-> set port 0 uta 00:55:44:33:22:11 on
+ PF testpmd-> set port 0 uta 00:55:44:33:22:66 on
+
+Send 2 flows, first 10 packets with dst mac 00:55:44:33:22:11, another 100
+packets with dst mac 00:55:44:33:22:66 to VF0 and make sure VF0 will receive
+all the packets.
+
+Test Case12: Add/Remove uta MAC address on VF
+=============================================
+
+Add one uta destination mac address on VF0::
+
+ PF testpmd-> set port 0 uta 00:55:44:33:22:11 on
+
+Send 10 packets with dst mac 00:55:44:33:22:11 to VF0 and make sure VF0 will
+receive the packets.
+
+Remove the uta destination mac address on VF0::
+
+ PF testpmd-> set port 0 uta 00:55:44:33:22:11 off
+
+Send 10 packets with dst mac 00:11:22:33:44:55 to VF0 and make sure VF0 will
+not receive the packets.
+
+Add an uta destination mac address on VF0 again::
+
+ PF testpmd-> set port 0 uta 00:11:22:33:44:55 on
+
+Send packet with dst mac 00:11:22:33:44:55 to VF0 and make sure VF0 will
+receive again and forwarded the packet. This step is to make sure the on/off
+switch is working.
+
+Test Case13: Pause RX Queues
+============================
+
+Pause RX queue of VF0 then send 10 packets to VF0 and make sure VF0 will not
+receive the packets::
+
+ PF testpmd-> set port 0 vf 0 rx off
+
+Enable RX queue of VF0 then send 10 packets to VF0 and make sure VF0 will
+receive the packet::
+
+ PF testpmd-> set port 0 vf 0 rx on
+
+Repeat the off/on twice to check the switch capability, and ensure on/off can
+work stable.
+
+Test Case14: Pause TX Queues
+============================
+
+Pause TX queue of VF0 then send 10 packets to VF0 and make sure VF0 will not
+forward the packet::
+
+ PF testpmd-> set port 0 vf 0 tx off
+
+Enable RX queue of VF0 then send 10 packets to VF0 and make sure VF0 will
+forward the packet::
+
+ PF testpmd-> set port 0 vf 0 tx on
+
+Repeat the off/on twice to check the switch capability, and ensure on/off can
+work stable.
+
+Test Case15: Prevent Rx of Broadcast on VF
+==========================================
+
+Disable VF0 rx broadcast packets then send broadcast packet to VF0 and make
+sure VF0 will not receive the packet::
+
+ PF testpmd-> set port 0 vf 0 rxmode BAM off
+
+Enable VF0 rx broadcast packets then send broadcast packet to VF0 and make sure
+VF0 will receive and forward the packet::
+
+ PF testpmd-> set port 0 vf 0 rxmode BAM on
+
+Repeat the off/on twice to check the switch capability, and ensure on/off can
+work stable.
+
+Test Case16: Negative input to commands
+=======================================
+
+Input invalid commands on PF/VF to make sure the commands can't work::
+
+ 1. PF testpmd-> set port 0 vf 65 tx on
+ 2. PF testpmd-> set port 2 vf -1 tx off
+ 3. PF testpmd-> set port 0 vf 0 rx oneee
+ 4. PF testpmd-> set port 0 vf 0 rx offdd
+ 5. PF testpmd-> set port 0 vf 0 rx oneee
+ 6. PF testpmd-> set port 0 vf 64 rxmode BAM on
+ 7. PF testpmd-> set port 0 vf 64 rxmode BAM off
+ 8. PF testpmd-> set port 0 uta 00:11:22:33:44 on
+ 9. PF testpmd-> set port 7 uta 00:55:44:33:22:11 off
+ 10. PF testpmd-> set port 0 vf 34 rxmode ROPE on
+ 11. PF testpmd-> mac_addr add port 0 vf 65 00:55:44:33:22:11
+ 12. PF testpmd-> mac_addr add port 5 vf 0 00:55:44:88:22:11
+ 13. PF testpmd-> set port 0 mirror-rule 0 pool-mirror 65 dst-pool 1 on
+ 14. PF testpmd-> set port 0 mirror-rule 0xf uplink-mirror dst-pool 1 on
+ 15. PF testpmd-> set port 0 mirror-rule 2 vlan-mirror 9 dst-pool 1 on
+ 16. PF testpmd-> set port 0 mirror-rule 0 downlink-mirror 0xf dst-pool 2 off
+ 17. PF testpmd-> reset port 0 mirror-rule 4
+ 18. PF testpmd-> reset port 0xff mirror-rule 0
+
+Prerequisites for Scaling 4VFs per 1PF
+======================================
+
+Create 4VF interface VF0, VF1, VF2, VF3 from one PF interface and then attach
+them to VM0, VM1, VM2 and VM3.Start PF driver on the Host and skip the VF
+driver will has been already attached to VMs::
+
+ On PF ./tools/pci_unbind.py --bind=igb_uio 0000:08:00.0
+ echo 2 > /sys/bus/pci/devices/0000\:08\:00.0/max_vfs
+ ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -b 0000:08:10.0 -b 0000:08:10.2 -b 0000:08:10.4 -b 0000:08:10.6 -- -i
+
+If you want to run all common 4VM cases, please run testpmd on VM0, VM1, VM2
+and VM3 and start traffic forward on the VM hosts. Some specific prerequisites
+are set up in each case::
+
+ VF0 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
+ VF1 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
+ VF2 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
+ VF3 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
+
+Test Case17: Scaling Pool Mirror on 4VFs
+========================================
+
+Make sure prerequisites for Scaling 4VFs per 1PF is set up.
+
+Add one mirror rules that will mirror VM0/VM1/VM2 income traffic to VM3::
+
+ PF testpmd-> set port 0 mirror-rule 0 pool-mirror 0x7 dst-pool 3 on
+ VF0 testpmd-> set fwd rxonly
+ VF0 testpmd-> start
+ VF1 testpmd-> set fwd rxonly
+ VF1 testpmd-> start
+ VF2 testpmd-> set fwd rxonly
+ VF2 testpmd-> start
+ VF3 testpmd-> set fwd rxonly
+ VF3 testpmd-> start
+
+Send 3 flows to VM0/VM1/VM2, one with VM0 mac, one with VM1 mac, one with VM2
+mac, and verify the packets has been mirrored to VM3.
+
+Reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+
+Set another 2 mirror rules. VM0/VM1 income traffic mirror to VM2 and VM3::
+
+ PF testpmd-> set port 0 mirror-rule 0 pool-mirror 0x3 dst-pool 2 on
+ PF testpmd-> set port 0 mirror-rule 1 pool-mirror 0x3 dst-pool 3 on
+
+Send 2 flows to VM0/VM1, one with VM0 mac, one with VM1 mac and verify the
+packets has been mirrored to VM2/VM3 and VM2/VM3 have forwarded these packets.
+
+Reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+ PF testpmd-> reset port 0 mirror-rule 1
+
+Test Case18: Scaling Uplink Mirror on 4VFs
+==========================================
+
+Make sure prerequisites for Scaling 4VFs per 1PF is set up.
+
+Add one mirror rules that will mirror all income traffic to VM2 and VM3::
+
+ PF testpmd-> set port 0 mirror-rule 0 uplink-mirror dst-pool 2 on
+ PF testpmd-> set port 0 mirror-rule 1 uplink-mirror dst-pool 3 on
+ VF0 testpmd-> set fwd rxonly
+ VF0 testpmd-> start
+ VF1 testpmd-> set fwd rxonly
+ VF1 testpmd-> start
+ VF2 testpmd-> set fwd rxonly
+ VF2 testpmd-> start
+ VF3 testpmd-> set fwd rxonly
+ VF3 testpmd-> start
+
+Send 4 flows to VM0/VM1/VM2/VM3, one packet with VM0 mac, one packet with VM1
+mac, one packet with VM2 mac, and one packet with VM3 mac and verify the
+income packets has been mirrored to VM2 and VM3. Make sure VM2/VM3 will have 4
+packets.
+
+Reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+ PF testpmd-> reset port 0 mirror-rule 1
+
+Test Case19: Scaling Downlink Mirror on 4VFs
+============================================
+
+Make sure prerequisites for scaling 4VFs per 1PF is set up.
+
+Add one mirror rules that will mirror all outcome traffic to VM2 and VM3::
+
+ PF testpmd-> set port 0 mirror-rule 0 downlink-mirror dst-pool 2 on
+ PF testpmd-> set port 0 mirror-rule 1 downlink-mirror dst-pool 3 on
+ VF0 testpmd-> set fwd mac
+ VF0 testpmd-> start
+ VF1 testpmd-> set fwd mac
+ VF1 testpmd-> start
+ VF2 testpmd-> set fwd rxonly
+ VF2 testpmd-> start
+ VF3 testpmd-> set fwd rxonly
+ VF3 testpmd-> start
+
+Send 2 flows to VM0/VM1, one with VM0 mac, one with VM1 mac, and verify VM0/VM1
+will forward these packets. And verify the VM0/VM1 outcome packets have been
+mirrored to VM2 and VM3.
+
+Reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+ PF testpmd-> reset port 0 mirror-rule 1
+
+Test Case20: Scaling Vlan Mirror on 4VFs
+========================================
+
+Make sure prerequisites for scaling 4VFs per 1PF is set up.
+
+Add 3 mirror rules that will mirror VM0/VM1/VM2 vlan income traffic to VM3::
+
+ PF testpmd-> rx_vlan add 1 port 0 vf 0x1
+ PF testpmd-> rx_vlan add 2 port 0 vf 0x2
+ PF testpmd-> rx_vlan add 3 port 0 vf 0x4
+ PF testpmd-> set port 0 mirror-rule 0 vlan-mirror 1,2,3 dst-pool 3 on
+ VF0 testpmd-> set fwd mac
+ VF0 testpmd-> start
+ VF1 testpmd-> set fwd mac
+ VF1 testpmd-> start
+ VF2 testpmd-> set fwd mac
+ VF2 testpmd-> start
+ VF3 testpmd-> set fwd mac
+ VF3 testpmd-> start
+
+Send 3 flows to VM0/VM1/VM2, one with VM0 mac/vlanid, one with VM1 mac/vlanid,
+one with VM2 mac/vlanid,and verify the packets has been mirrored to VM3 and
+VM3 has forwards these packets.
+
+Reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+
+Set another 2 mirror rules. VM0/VM1 income traffic mirror to VM2 and VM3::
+
+ PF testpmd-> set port 0 mirror-rule 0 vlan-mirror 1 dst-pool 2 on
+ PF testpmd-> set port 0 mirror-rule 1 vlan-mirror 2 dst-pool 3 on
+
+Send 2 flows to VM0/VM1, one with VM0 mac/vlanid, one with VM1 mac/vlanid and
+verify the packets has been mirrored to VM2 and VM3, then VM2 and VM3 have
+forwarded these packets.
+
+Reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+ PF testpmd-> reset port 0 mirror-rule 1
+
+Test Case21: Scaling Vlan Mirror & Pool Mirror on 4VFs
+======================================================
+
+Make sure prerequisites for scaling 4VFs per 1PF is set up.
+
+Add 3 mirror rules that will mirror VM0/VM1 vlan income traffic to VM2, VM0/VM1
+pool will come to VM3::
+
+ PF testpmd-> rx_vlan add 1 port 0 vf 0x1
+ PF testpmd-> rx_vlan add 2 port 0 vf 0x2
+ PF testpmd-> set port 0 mirror-rule 0 vlan-mirror 1 dst-pool 2 on
+ PF testpmd-> set port 0 mirror-rule 1 vlan-mirror 2 dst-pool 2 on
+ PF testpmd-> set port 0 mirror-rule 2 pool-mirror 0x3 dst-pool 3 on
+ VF0 testpmd-> set fwd mac
+ VF0 testpmd-> start
+ VF1 testpmd-> set fwd mac
+ VF1 testpmd-> start
+ VF2 testpmd-> set fwd mac
+ VF2 testpmd-> start
+ VF3 testpmd-> set fwd mac
+ VF3 testpmd-> start
+
+Send 2 flows to VM0/VM1, one with VM0 mac/vlanid, one with VM1 mac/vlanid, and
+verify the packets has been mirrored to VM2 and VM3, and VM2/VM3 have
+forwarded these packets.
+
+Reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+ PF testpmd-> reset port 0 mirror-rule 1
+ PF testpmd-> reset port 0 mirror-rule 2
+
+Set 3 mirror rules. VM0/VM1 income traffic mirror to VM2, VM2 traffic will
+mirror to VM3::
+
+ PF testpmd-> set port 0 mirror-rule 0 vlan-mirror 1,2 dst-pool 2 on
+ PF testpmd-> set port 0 mirror-rule 2 pool-mirror 0x2 dst-pool 3 on
+
+Send 2 flows to VM0/VM1, one with VM0 mac/vlanid, one with VM1 mac/vlanid and
+verify the packets has been mirrored to VM2, VM2 traffic will be mirrored to
+VM3, then VM2 and VM3 have forwarded these packets.
+
+Reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+ PF testpmd-> reset port 0 mirror-rule 1
+ PF testpmd-> reset port 0 mirror-rule 2
+
+Test Case22: Scaling Uplink Mirror & Downlink Mirror on 4VFs
+============================================================
+
+Make sure prerequisites for scaling 4VFs per 1PF is set up.
+
+Add 2 mirror rules that will mirror all income traffic to VM2, all outcome
+traffic to VM3. Make sure VM2 and VM3 rxonly::
+
+ PF testpmd-> set port 0 mirror-rule 0 uplink-mirror dst-pool 2 on
+ PF testpmd-> set port 0 mirror-rule 1 downlink-mirror dst-pool 3 on
+ VF0 testpmd-> set fwd mac
+ VF0 testpmd-> start
+ VF1 testpmd-> set fwd mac
+ VF1 testpmd-> start
+ VF2 testpmd-> set fwd rxonly
+ VF2 testpmd-> start
+ VF3 testpmd-> set fwd rxonly
+ VF3 testpmd-> start
+
+Send 2 flows to VM0/VM1, one with VM0 mac, one with VM1 mac and make sure
+VM0/VM1 will forward packets. Verify the income packets have been mirrored to
+VM2, the outcome packets has been mirrored to VM3.
+
+Reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+ PF testpmd-> reset port 0 mirror-rule 1
+
+Test Case23: Scaling Pool & Vlan & Uplink & Downlink Mirror on 4VFs
+===================================================================
+
+Make sure prerequisites for scaling 4VFs per 1PF is set up.
+
+Add mirror rules that VM0 vlan mirror to VM1, all income traffic mirror to VM2,
+all outcome traffic mirror to VM3, all VM1 traffic will mirror to VM0. Make
+sure VM2 and VM3 rxonly::
+
+ PF testpmd-> rx_vlan add 1 port 0 vf 0x1
+ PF testpmd-> set port 0 mirror-rule 0 vlan-mirror 1 dst-pool 1 on
+ PF testpmd-> set port 0 mirror-rule 1 pool-mirror 0x2 dst-pool 0 on
+ PF testpmd-> set port 0 mirror-rule 2 uplink-mirror dst-pool 2 on
+ PF testpmd-> set port 0 mirror-rule 3 downlink-mirror dst-pool 3 on
+ VF0 testpmd-> set fwd mac
+ VF0 testpmd-> start
+ VF1 testpmd-> set fwd mac
+ VF1 testpmd-> start
+ VF2 testpmd-> set fwd rxonly
+ VF2 testpmd-> start
+ VF3 testpmd-> set fwd rxonly
+ VF3 testpmd-> start
+
+Send 10 packets to VM0 with VM0 mac/vlanid, verify that VM1 will be mirrored
+and packets will be forwarded, VM2 will have all income traffic mirrored, VM3
+will have all outcome traffic mirrored
+
+Send 10 packets to VM1 with VM1 mac, verify that VM0 will be mirrored and
+packets will be forwarded, VM2 will have all income traffic mirrored; VM3 will
+have all outcome traffic mirrored
+
+Reset mirror rule::
+
+ PF testpmd-> reset port 0 mirror-rule 0
+ PF testpmd-> reset port 0 mirror-rule 1
+ PF testpmd-> reset port 0 mirror-rule 2
+ PF testpmd-> reset port 0 mirror-rule 3
+
+Test Case24: Scaling InterVM communication on 4VFs
+==================================================
+
+Set the VF0 destination mac address to VF1 mac address, packets send from VF0
+will be forwarded to VF1 and then send out. Similar for VF2 and VF3::
+
+ VF1 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
+ VF1 testpmd-> show port info 0
+ VF1 testpmd-> set fwd mac
+ VF1 testpmd-> start
+
+ VF0 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- --eth-peer=0,"VF1 mac" -i
+ VF0 testpmd-> set fwd mac
+ VF0 testpmd-> start
+
+ VF3 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- -i
+ VF3 testpmd-> show port info 0
+ VF3 testpmd-> set fwd mac
+ VF3 testpmd-> start
+
+ VF2 ./x86_64-default-linuxapp-gcc/app/testpmd -c f -n 4 -- --eth-peer=0,"VF3 mac" -i
+ VF2 testpmd-> set fwd mac
+ VF2 testpmd-> start
+
+Send 2 flows, one with VF0 mac address and make sure the packets will be
+forwarded by VF1, another with VF2 mac address and make sure the packets will
+be forwarded by VF3.
+
+
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [dts] [PATCH v2 19/19] Add a test suite to verify the SRIOV feature on the KVM ENV
2015-05-22 9:03 [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework *** Jiajia, Sun
` (17 preceding siblings ...)
2015-05-22 9:04 ` [dts] [PATCH v2 18/19] Add a test plan of how to test SRIOV on the KVM ENV Jiajia, Sun
@ 2015-05-22 9:04 ` Jiajia, Sun
18 siblings, 0 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22 9:04 UTC (permalink / raw)
To: dts
From: sjiajiax <sunx.jiajia@intel.com>
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
tests/TestSuite_sriov_kvm.py | 1291 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1291 insertions(+)
create mode 100644 tests/TestSuite_sriov_kvm.py
diff --git a/tests/TestSuite_sriov_kvm.py b/tests/TestSuite_sriov_kvm.py
new file mode 100644
index 0000000..8109840
--- /dev/null
+++ b/tests/TestSuite_sriov_kvm.py
@@ -0,0 +1,1291 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+
+Test userland 10Gb PMD.
+
+"""
+
+import re
+import pdb
+import time
+
+import dts
+from qemu_kvm import QEMUKvm
+from test_case import TestCase
+
+from pmd_output import PmdOutput
+
+FRAME_SIZE_64 = 64
+VM_CORES_MASK = 'all'
+
+
+class TestSriovKvm(TestCase):
+
+ def set_up_all(self):
+ # port_mirror_ref = {port_id: rule_id_list}
+ # rule_id should be integer, and should be increased based on
+ # the most rule_id when add a rule for a port successfully,
+ # case should not be operate it directly
+ # example:
+ # port_mirror_ref = {0: 1, 1: 3}
+ self.port_mirror_ref = {}
+ self.dut_ports = self.dut.get_ports(self.nic)
+ self.verify(len(self.dut_ports) >= 1, "Insufficient ports")
+
+ self.vm0 = None
+ self.vm1 = None
+ self.vm2 = None
+ self.vm3 = None
+
+ def set_up(self):
+ self.setup_2vm_2pf_env_flag = 0
+
+ self.setup_2vm_2vf_env_flag = 0
+ self.setup_2vm_prerequisite_flag = 0
+
+ self.setup_4vm_4vf_env_flag = 0
+ self.setup_4vm_prerequisite_flag = 0
+
+ def get_stats(self, dut, portid, rx_tx):
+ """
+ Get packets number from port statistic
+ """
+
+ stats = dut.testpmd.get_pmd_stats(portid)
+
+ if rx_tx == "rx":
+ stats_result = [
+ stats['RX-packets'], stats['RX-missed'], stats['RX-bytes']]
+ elif rx_tx == "tx":
+ stats_result = [
+ stats['TX-packets'], stats['TX-errors'], stats['TX-bytes']]
+ else:
+ return None
+
+ return stats_result
+
+ def parse_ether_ip(self, dut, dut_ports, dest_port, **ether_ip):
+ """
+ dut: which you want to send packet to
+ dest_port: the port num must be the index of dut.get_ports()
+ ether_ip:
+ 'ether':
+ {
+ 'dest_mac':False
+ 'src_mac':"52:00:00:00:00:00"
+ }
+ 'dot1q':
+ {
+ 'vlan':1
+ }
+ 'ip':
+ {
+ 'dest_ip':"10.239.129.88"
+ 'src_ip':"10.239.129.65"
+ }
+ 'udp':
+ {
+ 'dest_port':53
+ 'src_port':53
+ }
+ """
+ ret_ether_ip = {}
+ ether = {}
+ dot1q = {}
+ ip = {}
+ udp = {}
+
+ try:
+ dut_dest_port = dut_ports[dest_port]
+ except Exception as e:
+ print e
+
+ tester_port = dut.ports_map[dut_dest_port]
+ if not ether_ip.get('ether'):
+ ether['dest_mac'] = dut.get_mac_address(dut_dest_port)
+ ether['src_mac'] = dut.tester.get_mac(tester_port)
+ else:
+ if not ether_ip['ether'].get('dest_mac'):
+ ether['dest_mac'] = dut.get_mac_address(dut_dest_port)
+ else:
+ ether['dest_mac'] = ether_ip['ether']['dest_mac']
+ if not ether_ip['ether'].get('src_mac'):
+ ether['src_mac'] = dut.tester.get_mac(tester_port)
+ else:
+ ether['src_mac'] = ether_ip["ether"]["src_mac"]
+
+ if not ether_ip.get('dot1q'):
+ pass
+ else:
+ if not ether_ip['dot1q'].get('vlan'):
+ dot1q['vlan'] = '1'
+ else:
+ dot1q['vlan'] = ether_ip['dot1q']['vlan']
+
+ if not ether_ip.get('ip'):
+ ip['dest_ip'] = "10.239.129.88"
+ ip['src_ip'] = "10.239.129.65"
+ else:
+ if not ether_ip['ip'].get('dest_ip'):
+ ip['dest_ip'] = "10.239.129.88"
+ else:
+ ip['dest_ip'] = ether_ip['ip']['dest_ip']
+ if not ether_ip['ip'].get('src_ip'):
+ ip['src_ip'] = "10.239.129.65"
+ else:
+ ip['src_ip'] = ether_ip['ip']['src_ip']
+
+ if not ether_ip.get('udp'):
+ udp['dest_port'] = 53
+ udp['src_port'] = 53
+ else:
+ if not ether_ip['udp'].get('dest_port'):
+ udp['dest_port'] = 53
+ else:
+ udp['dest_port'] = ether_ip['udp']['dest_port']
+ if not ether_ip['udp'].get('src_port'):
+ udp['src_port'] = 53
+ else:
+ udp['src_port'] = ether_ip['udp']['src_port']
+
+ ret_ether_ip['ether'] = ether
+ ret_ether_ip['dot1q'] = dot1q
+ ret_ether_ip['ip'] = ip
+ ret_ether_ip['udp'] = udp
+
+ return ret_ether_ip
+
+ def send_packet(self,
+ dut,
+ dut_ports,
+ dest_port,
+ src_port=False,
+ frame_size=FRAME_SIZE_64,
+ count=1,
+ invert_verify=False,
+ **ether_ip):
+ """
+ Send count packet to portid
+ dut: which you want to send packet to
+ dest_port: the port num must be the index of dut.get_ports()
+ count: 1 or 2 or 3 or ... or 'MANY'
+ if count is 'MANY', then set count=1000,
+ send packets during 5 seconds.
+ ether_ip:
+ 'ether':
+ {
+ 'dest_mac':False
+ 'src_mac':"52:00:00:00:00:00"
+ }
+ 'dot1q':
+ {
+ 'vlan':1
+ }
+ 'ip':
+ {
+ 'dest_ip':"10.239.129.88"
+ 'src_ip':"10.239.129.65"
+ }
+ 'udp':
+ {
+ 'dest_port':53
+ 'src_port':53
+ }
+ """
+ during = 0
+ loop = 0
+ try:
+ count = int(count)
+ except ValueError as e:
+ if count == 'MANY':
+ during = 20
+ count = 1000 * 10
+ else:
+ raise e
+
+ gp0rx_pkts, gp0rx_err, gp0rx_bytes = [int(_)
+ for _ in self.get_stats(dut, dest_port, "rx")]
+ if not src_port:
+ itf = self.tester.get_interface(
+ dut.ports_map[dut_ports[dest_port]])
+ else:
+ itf = src_port
+
+ ret_ether_ip = self.parse_ether_ip(
+ dut,
+ dut_ports,
+ dest_port,
+ **ether_ip)
+
+ pktlen = frame_size - 18
+ padding = pktlen - 20
+
+ start = time.time()
+ while True:
+ self.tester.scapy_foreground()
+ self.tester.scapy_append(
+ 'nutmac="%s"' % ret_ether_ip['ether']['dest_mac'])
+ self.tester.scapy_append(
+ 'srcmac="%s"' % ret_ether_ip['ether']['src_mac'])
+
+ if ether_ip.get('dot1q'):
+ self.tester.scapy_append(
+ 'vlanvalue=%d' % int(ret_ether_ip['dot1q']['vlan']))
+ self.tester.scapy_append(
+ 'destip="%s"' % ret_ether_ip['ip']['dest_ip'])
+ self.tester.scapy_append(
+ 'srcip="%s"' % ret_ether_ip['ip']['src_ip'])
+ self.tester.scapy_append(
+ 'destport=%d' % ret_ether_ip['udp']['dest_port'])
+ self.tester.scapy_append(
+ 'srcport=%d' % ret_ether_ip['udp']['src_port'])
+ if not ret_ether_ip.get('dot1q'):
+ send_cmd = 'sendp([Ether(dst=nutmac, src=srcmac)/' + \
+ 'IP(dst=destip, src=srcip, len=%s)/' % pktlen + \
+ 'UDP(sport=srcport, dport=destport)/' + \
+ 'Raw(load="\x50"*%s)], ' % padding + \
+ 'iface="%s", count=%d)' % (itf, count)
+ else:
+ send_cmd = 'sendp([Ether(dst=nutmac, src=srcmac)/Dot1Q(vlan=vlanvalue)/' + \
+ 'IP(dst=destip, src=srcip, len=%s)/' % pktlen + \
+ 'UDP(sport=srcport, dport=destport)/' + \
+ 'Raw(load="\x50"*%s)], iface="%s", count=%d)' % (
+ padding, itf, count)
+ self.tester.scapy_append(send_cmd)
+
+ self.tester.scapy_execute()
+ loop += 1
+
+ now = time.time()
+ if (now - start) >= during:
+ break
+ time.sleep(.5)
+
+ p0rx_pkts, p0rx_err, p0rx_bytes = [int(_)
+ for _ in self.get_stats(dut, dest_port, "rx")]
+
+ p0rx_pkts -= gp0rx_pkts
+ p0rx_bytes -= gp0rx_bytes
+
+ if not invert_verify:
+ self.verify(p0rx_pkts >= count * loop,
+ "Data not received by port")
+ else:
+ self.verify(p0rx_pkts == 0 or
+ p0rx_pkts < count * loop,
+ "Data received by port, but should not.")
+ return count * loop
+
+ def setup_2vm_2pf_env(self):
+ p0 = self.dut_ports[0]
+ p1 = self.dut_ports[1]
+
+ self.port0 = self.dut.ports_info[p0]['port']
+ self.port0.unbind_driver()
+ self.port0_pci = self.dut.ports_info[p0]['pci']
+
+ self.port1 = self.dut.ports_info[p1]['port']
+ self.port1.unbind_driver()
+ self.port1_pci = self.dut.ports_info[p1]['pci']
+
+ vf0_prop = {'prop_host': self.port0_pci}
+ vf1_prop = {'prop_host': self.port1_pci}
+
+ # set up VM0 ENV
+ self.vm0 = QEMUKvm(self.dut, 'vm0', 'sriov_kvm')
+ self.vm0.set_vm_device(driver='pci-assign', **vf0_prop)
+ self.vm_dut_0 = self.vm0.start()
+
+ # set up VM1 ENV
+ self.vm1 = QEMUKvm(self.dut, 'vm1', 'sriov_kvm')
+ self.vm1.set_vm_device(driver='pci-assign', **vf1_prop)
+ self.vm_dut_1 = self.vm1.start()
+
+ self.setup_2vm_2vf_env_flag = 1
+
+ def destroy_2vm_2pf_env(self):
+ self.vm_dut_0.close()
+ self.vm_dut_0.logger.logger_exit()
+ self.vm0.stop()
+ self.port0.bind_driver('igb_uio')
+ self.vm0 = None
+
+ self.vm_dut_1.close()
+ self.vm_dut_1.logger.logger_exit()
+ self.vm1.stop()
+ self.port1.bind_driver('igb_uio')
+ self.vm1 = None
+
+ self.setup_2vm_2vf_env_flag = 0
+
+ def setup_2vm_2vf_env(self, driver='igb_uio'):
+ self.used_dut_port = self.dut_ports[0]
+
+ self.dut.generate_sriov_vfs_by_port(
+ self.used_dut_port, 2, driver=driver)
+ self.sriov_vfs_port = self.dut.ports_info[
+ self.used_dut_port]['vfs_port']
+
+ try:
+
+ for port in self.sriov_vfs_port:
+ port.bind_driver('pci-stub')
+
+ time.sleep(1)
+
+ vf0_prop = {'prop_host': self.sriov_vfs_port[0].pci}
+ vf1_prop = {'prop_host': self.sriov_vfs_port[1].pci}
+
+ for port_id in self.dut_ports:
+ if port_id == self.used_dut_port:
+ continue
+ port = self.dut.ports_info[port_id]['port']
+ port.bind_driver()
+
+ if driver == 'igb_uio':
+ # start testpmd with the two VFs on the host
+ self.host_testpmd = PmdOutput(self.dut)
+ eal_param = '-b %(vf0)s -b %(vf1)s' % {'vf0': self.sriov_vfs_port[0].pci,
+ 'vf1': self.sriov_vfs_port[1].pci}
+ self.host_testpmd.start_testpmd(
+ "1S/2C/2T", eal_param=eal_param)
+
+ # set up VM0 ENV
+ self.vm0 = QEMUKvm(self.dut, 'vm0', 'sriov_kvm')
+ self.vm0.set_vm_device(driver='pci-assign', **vf0_prop)
+ self.vm_dut_0 = self.vm0.start()
+ if self.vm_dut_0 is None:
+ raise Exception("Set up VM0 ENV failed!")
+
+ # set up VM1 ENV
+ self.vm1 = QEMUKvm(self.dut, 'vm1', 'sriov_kvm')
+ self.vm1.set_vm_device(driver='pci-assign', **vf1_prop)
+ self.vm_dut_1 = self.vm1.start()
+ if self.vm_dut_1 is None:
+ raise Exception("Set up VM1 ENV failed!")
+
+ self.setup_2vm_2vf_env_flag = 1
+ except Exception as e:
+ self.destroy_2vm_2vf_env()
+ raise Exception(e)
+
+ def destroy_2vm_2vf_env(self):
+ if getattr(self, 'vm_dut_0', None):
+ self.vm_dut_0.close()
+ self.vm_dut_0.logger.logger_exit()
+ if getattr(self, 'vm0', None):
+ self.vm0.stop()
+ self.vm0 = None
+
+ if getattr(self, 'vm_dut_1', None):
+ self.vm_dut_1.close()
+ self.vm_dut_1.logger.logger_exit()
+ if getattr(self, 'vm1', None):
+ self.vm1.stop()
+ self.vm1 = None
+
+ if getattr(self, 'host_testpmd', None):
+ self.host_testpmd.execute_cmd('quit', '# ')
+ self.host_testpmd = None
+
+ if getattr(self, 'used_dut_port', None):
+ self.dut.destroy_sriov_vfs_by_port(self.used_dut_port)
+ port = self.dut.ports_info[self.used_dut_port]['port']
+ port.bind_driver('igb_uio')
+ self.used_dut_port = None
+
+ for port_id in self.dut_ports:
+ port = self.dut.ports_info[port_id]['port']
+ port.bind_driver('igb_uio')
+
+ self.setup_2vm_2vf_env_flag = 0
+
+ def setup_4vm_4vf_env(self, driver='igb_uio'):
+ self.used_dut_port = self.dut_ports[0]
+
+ self.dut.generate_sriov_vfs_by_port(
+ self.used_dut_port, 4, driver=driver)
+ self.sriov_vfs_port = self.dut.ports_info[self.used_dut_port]['port']
+
+ try:
+ for port in self.sriov_vfs_port:
+ port.bind_driver('pci-stub')
+
+ time.sleep(1)
+
+ vf0_prop = {'prop_host': self.sriov_vfs_port[0].pci}
+ vf1_prop = {'prop_host': self.sriov_vfs_port[1].pci}
+ vf2_prop = {'prop_host': self.sriov_vfs_port[2].pci}
+ vf3_prop = {'prop_host': self.sriov_vfs_port[3].pci}
+
+ for port_id in self.dut_ports:
+ if port_id == self.used_dut_port:
+ continue
+ port = self.dut.ports_info[port_id]['port']
+ port.bind_driver()
+
+ if driver == 'igb_uio':
+ # start testpmd with the four VFs on the host
+ self.host_testpmd = PmdOutput(self.dut)
+ eal_param = '-b %(vf0) -b %(vf1)s -b %(vf2)s -b %(vf3)s' % \
+ {'vf0': self.sriov_vfs_pci[0],
+ 'vf1': self.sriov_vfs_pci[1],
+ 'vf2': self.sriov_vfs_pci[2],
+ 'vf3': self.sriov_vfs_pci[3]}
+ self.host_testpmd.start_testpmd(
+ "1S/2C/2T", eal_param=eal_param)
+
+ self.vm0 = QEMUKvm(self.dut, 'vm0', 'sriov_kvm')
+ self.vm0.set_vm_device(driver='pci-assign', **vf0_prop)
+ self.vm_dut_0 = self.vm0.start()
+ if self.vm_dut_0 is None:
+ raise Exception("Set up VM0 ENV failed!")
+
+ self.vm1 = QEMUKvm(self.dut, 'vm1', 'sriov_kvm')
+ self.vm1.set_vm_device(driver='pci-assign', **vf1_prop)
+ self.vm_dut_1 = self.vm1.start()
+ if self.vm_dut_1 is None:
+ raise Exception("Set up VM1 ENV failed!")
+
+ self.vm2 = QEMUKvm(self.dut, 'vm2', 'sriov_kvm')
+ self.vm2.set_vm_device(driver='pci-assign', **vf2_prop)
+ self.vm_dut_2 = self.vm1.start()
+ if self.vm_dut_2 is None:
+ raise Exception("Set up VM2 ENV failed!")
+
+ self.vm3 = QEMUKvm(self.dut, 'vm3', 'sriov_kvm')
+ self.vm3.set_vm_device(driver='pci-assign', **vf3_prop)
+ self.vm_dut_3 = self.vm3.start()
+ if self.vm_dut_3 is None:
+ raise Exception("Set up VM3 ENV failed!")
+
+ self.setup_4vm_4vf_env_flag = 1
+ except Exception as e:
+ self.destroy_4vm_4vf_env()
+ raise Exception(e)
+
+ def destroy_4vm_4vf_env(self):
+ if getattr(self, 'vm_dut_0', None):
+ self.vm_dut_0.close()
+ self.vm_dut_0.logger.logger_exit()
+ if getattr(self, 'vm0', None):
+ self.vm0.stop()
+ self.vm0 = None
+
+ if getattr(self, 'vm_dut_1', None):
+ self.vm_dut_1.close()
+ self.vm_dut_1.logger.logger_exit()
+ if getattr(self, 'vm1', None):
+ self.vm1.stop()
+ self.vm1 = None
+
+ if getattr(self, 'vm_dut_2', None):
+ self.vm_dut_2.close()
+ self.vm_dut_2.logger.logger_exit()
+ if getattr(self, 'vm2', None):
+ self.vm2.stop()
+ self.vm2 = None
+
+ if getattr(self, 'vm_dut_3', None):
+ self.vm_dut_3.close()
+ self.vm_dut_3.logger.logger_exit()
+ if getattr(slef, 'vm3', None):
+ self.vm3.stop()
+ self.vm3 = None
+
+ if getattr(self, 'host_testpmd', None):
+ self.host_testpmd.execute_cmd('stop')
+ self.host_testpmd.execute_cmd('quit', '# ')
+ self.host_testpmd = None
+
+ if getattr(self, 'used_dut_port', None):
+ self.dut.destroy_sriov_vfs_by_port(self.used_dut_port)
+ port = self.ports_info[self.used_dut_port]['port']
+ port.bind_driver('igb_uio')
+ slef.used_dut_port = None
+
+ for port_id in self.dut_ports:
+ port = self.dut.ports_info[port_id]['port']
+ port.bind_driver('igb_uio')
+
+ self.setup_4vm_4vf_env_flag = 0
+
+ def transform_integer(self, value):
+ try:
+ value = int(value)
+ except ValueError as e:
+ raise Exception("Value not integer,but is " + type(value))
+ return value
+
+ def make_port_new_ruleid(self, port):
+ port = self.transform_integer(port)
+ if port not in self.port_mirror_ref.keys():
+ max_rule_id = 0
+ else:
+ rule_ids = sorted(self.port_mirror_ref[port])
+ if rule_ids:
+ max_rule_id = rule_ids[-1] + 1
+ else:
+ max_rule_id = 0
+ return max_rule_id
+
+ def add_port_ruleid(self, port, rule_id):
+ port = self.transform_integer(port)
+ rule_id = self.transform_integer(rule_id)
+
+ if port not in self.port_mirror_ref.keys():
+ self.port_mirror_ref[port] = [rule_id]
+ else:
+ self.verify(rule_id not in self.port_mirror_ref[port],
+ "Rule id [%d] has been repeated, please check!" % rule_id)
+ self.port_mirror_ref[port].append(rule_id)
+
+ def remove_port_ruleid(self, port, rule_id):
+ port = self.transform_integer(port)
+ rule_id = self.transform_integer(rule_id)
+ if port not in self.port_mirror_ref.keys():
+ pass
+ else:
+ if rule_id not in self.port_mirror_ref[port]:
+ pass
+ else:
+ self.port_mirror_ref[port].remove(rule_id)
+ if not self.port_mirror_ref[port]:
+ self.port_mirror_ref.pop(port)
+
+ def set_port_mirror_rule(self, port, mirror_name, rule_detail):
+ """
+ Set the mirror rule for specified port.
+ """
+ port = self.transform_integer(port)
+
+ rule_id = self.make_port_new_ruleid(port)
+
+ mirror_rule_cmd = "set port %d mirror-rule %d %s %s" % \
+ (port, rule_id, mirror_name, rule_detail)
+ out = self.dut.send_expect("%s" % mirror_rule_cmd, "testpmd> ")
+ self.verify('Bad arguments' not in out, "Set port %d %s failed!" %
+ (port, mirror_name))
+
+ self.add_port_ruleid(port, rule_id)
+ return rule_id
+
+ def set_port_pool_mirror(self, port, pool_mirror_rule):
+ """
+ Set the pool mirror for specified port.
+ """
+ return self.set_port_mirror_rule(port, 'pool-mirror-up', pool_mirror_rule)
+
+ def set_port_vlan_mirror(self, port, vlan_mirror_rule):
+ """
+ Set the vlan mirror for specified port.
+ """
+ return self.set_port_mirror_rule(port, 'vlan-mirror', vlan_mirror_rule)
+
+ def set_port_uplink_mirror(self, port, uplink_mirror_rule):
+ """
+ Set the uplink mirror for specified port.
+ """
+ return self.set_port_mirror_rule(port, 'uplink-mirror', uplink_mirror_rule)
+
+ def set_port_downlink_mirror(self, port, downlink_mirror_rule):
+ """
+ Set the downlink mirror for specified port.
+ """
+ return self.set_port_mirror_rule(port, 'downlink-mirror', downlink_mirror_rule)
+
+ def reset_port_mirror_rule(self, port, rule_id):
+ """
+ Reset the pool mirror for specified port.
+ """
+ port = self.transform_integer(port)
+ rule_id = self.transform_integer(rule_id)
+
+ mirror_rule_cmd = "reset port %d mirror-rule %d" % (port, rule_id)
+ out = self.dut.send_expect("%s" % mirror_rule_cmd, "testpmd> ")
+ self.verify("Bad arguments" not in out,
+ "Reset port %d mirror rule failed!")
+
+ self.remove_port_ruleid(port, rule_id)
+
+ def reset_port_all_mirror_rule(self, port):
+ """
+ Reset all mirror rules of specified port.
+ """
+ port = self.transform_integer(port)
+
+ if port not in self.port_mirror_ref.keys():
+ pass
+ else:
+ for rule_id in self.port_mirror_ref[port]:
+ self.reset_port_mirror_rule(port, rule_id)
+
+ def setup_two_vm_common_prerequisite(self):
+ self.vm0_dut_ports = self.vm_dut_0.get_ports('any')
+ self.vm0_testpmd = PmdOutput(self.vm_dut_0)
+ self.vm0_testpmd.start_testpmd(VM_CORES_MASK)
+ self.vm0_testpmd.execute_cmd('set fwd rxonly')
+ self.vm0_testpmd.execute_cmd('start')
+
+ self.vm1_dut_ports = self.vm_dut_1.get_ports('any')
+ self.vm1_testpmd = PmdOutput(self.vm_dut_1)
+ self.vm1_testpmd.start_testpmd(VM_CORES_MASK)
+ self.vm1_testpmd.execute_cmd('set fwd mac')
+ self.vm1_testpmd.execute_cmd('start')
+
+ self.setup_2vm_prerequisite_flag = 1
+
+ def destroy_two_vm_common_prerequisite(self):
+ self.vm0_testpmd.execute_cmd('stop')
+ self.vm0_testpmd.execute_cmd('quit', '# ')
+ self.vm0_testpmd = None
+ self.vm0_dut_ports = None
+
+ self.vm1_testpmd.execute_cmd('stop')
+ self.vm1_testpmd.execute_cmd('quit', '# ')
+ self.vm0_testpmd = None
+ self.vm1_dut_ports = None
+
+ self.setup_2vm_prerequisite_flag = 0
+
+ def stop_test_setup_two_vm_pf_env(self):
+ self.setup_2vm_2pf_env()
+
+ out = self.vm_dut_0.send_expect("ifconfig", '# ')
+ print out
+ out = self.vm_dut_0.send_expect("lspci -nn | grep -i eth", '# ')
+ print out
+
+ out = self.vm_dut_1.send_expect("ifconfig", '# ')
+ print out
+ out = self.vm_dut_1.send_expect("lspci -nn | grep -i eth", '# ')
+ print out
+
+ self.destroy_2vm_2pf_env()
+
+ def test_two_vms_intervm_communication(self):
+ self.setup_2vm_2vf_env()
+
+ self.vm0_dut_ports = self.vm_dut_0.get_ports('any')
+ self.vm1_dut_ports = self.vm_dut_1.get_ports('any')
+ port_id_0 = 0
+ packet_num = 10
+
+ self.vm1_testpmd = PmdOutput(self.vm_dut_1)
+ self.vm1_testpmd.start_testpmd(VM_CORES_MASK)
+ vf1_mac = self.vm1_testpmd.get_port_mac(port_id_0)
+ self.vm1_testpmd.execute_cmd('set fwd mac')
+ self.vm1_testpmd.execute_cmd('start')
+
+ self.vm0_testpmd = PmdOutput(self.vm_dut_0)
+ self.vm0_testpmd.start_testpmd(
+ VM_CORES_MASK, "--eth-peer=0,%s" % vf1_mac)
+ vf0_mac = self.vm0_testpmd.get_port_mac(port_id_0)
+ self.vm0_testpmd.execute_cmd('set fwd mac')
+ self.vm0_testpmd.execute_cmd('start')
+
+ self.setup_2vm_prerequisite_flag = 1
+ time.sleep(2)
+
+ vm1_start_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+ self.send_packet(
+ self.vm_dut_0, self.vm0_dut_ports, port_id_0, count=packet_num)
+ vm1_end_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+
+ self.verify(
+ vm1_end_stats["TX-packets"] - vm1_start_stats["TX-packets"] == packet_num,
+ "VM1 transmit packets failed when sending packets to VM0")
+
+ def calculate_stats(self, start_stats, end_stats):
+ ret_stats = {}
+ for key in start_stats.keys():
+ try:
+ start_stats[key] = int(start_stats[key])
+ end_stats[key] = int(end_stats[key])
+ except TypeError:
+ ret_stats[key] = end_stats[key]
+ continue
+ ret_stats[key] = end_stats[key] - start_stats[key]
+ return ret_stats
+
+ def test_two_vms_pool_mirror(self):
+ self.setup_2vm_2vf_env()
+ self.setup_two_vm_common_prerequisite()
+
+ port_id_0 = 0
+ packet_num = 10
+
+ rule_id = self.set_port_pool_mirror(port_id_0, '0x1 dst-pool 1 on')
+ vm1_start_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+ self.send_packet(
+ self.vm_dut_0, self.vm0_dut_ports, port_id_0, count=packet_num)
+ vm1_end_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+
+ vm1_ret_stats = self.calculate_stats(vm1_start_stats, vm1_end_stats)
+
+ self.verify(vm1_ret_stats['RX-packets'] == packet_num and
+ vm1_ret_stats['TX-packets'] == packet_num,
+ "Pool mirror failed between VM0 and VM1!")
+
+ self.reset_port_mirror_rule(port_id_0, rule_id)
+
+ def test_two_vms_uplink_mirror(self):
+ self.setup_2vm_2vf_env()
+ self.setup_two_vm_common_prerequisite()
+
+ port_id_0 = 0
+ packet_num = 10
+
+ rule_id = self.set_port_uplink_mirror(port_id_0, 'dst-pool 1 on')
+ vm1_start_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+ self.send_packet(
+ self.vm_dut_0, self.vm0_dut_ports, port_id_0, count=packet_num)
+ vm1_end_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+
+ vm1_ret_stats = self.calculate_stats(vm1_start_stats, vm1_end_stats)
+
+ self.verify(vm1_ret_stats['RX-packets'] == packet_num and
+ vm1_ret_stats['TX-packets'] == packet_num,
+ "Uplink mirror failed between VM0 and VM1!")
+
+ self.reset_port_mirror_rule(port_id_0, rule_id)
+
+ def test_two_vms_downlink_mirror(self):
+ self.setup_2vm_2vf_env()
+ self.setup_two_vm_common_prerequisite()
+
+ self.vm0_testpmd.execute_cmd('stop')
+ self.vm1_testpmd.execute_cmd('stop')
+
+ port_id_0 = 0
+
+ rule_id = self.set_port_downlink_mirror(port_id_0, 'dst-pool 1 on')
+
+ self.vm1_testpmd.execute_cmd('set fwd rxonly')
+ self.vm1_testpmd.execute_cmd('start')
+ vm1_start_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+ vm0_start_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ self.vm0_testpmd.execute_cmd('start tx_first')
+ vm0_end_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ vm1_end_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+
+ vm0_ret_stats = self.calculate_stats(vm0_start_stats, vm0_end_stats)
+ vm1_ret_stats = self.calculate_stats(vm1_start_stats, vm1_end_stats)
+
+ self.verify(vm1_ret_stats['RX-packets'] == vm0_ret_stats['TX-packets'],
+ "Downlink mirror failed between VM0 and VM1!")
+
+ self.reset_port_mirror_rule(port_id_0, rule_id)
+
+ def test_two_vms_vlan_mirror(self):
+ self.setup_2vm_2vf_env()
+ self.setup_two_vm_common_prerequisite()
+
+ port_id_0 = 0
+ vlan_id = 0
+ vf_mask = '0x1'
+ packet_num = 10
+
+ self.host_testpmd.execute_cmd(
+ 'rx_vlan add %d port %d vf %s' % (vlan_id, port_id_0, vf_mask))
+ rule_id = self.set_port_vlan_mirror(port_id_0, '0 dst-pool 1 on')
+
+ vm1_start_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+ ether_ip = {}
+ ether_ip['dot1q'] = {'vlan': '%d' % vlan_id}
+ self.send_packet(
+ self.vm_dut_0,
+ self.vm0_dut_ports,
+ port_id_0,
+ count=packet_num,
+ **ether_ip)
+ vm1_end_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+
+ vm1_ret_stats = self.calculate_stats(vm1_start_stats, vm1_end_stats)
+
+ self.verify(vm1_ret_stats['RX-packets'] == packet_num and
+ vm1_ret_stats['TX-packets'] == packet_num,
+ "Vlan mirror failed between VM0 and VM1!")
+
+ self.reset_port_mirror_rule(port_id_0, rule_id)
+
+ def test_two_vms_vlan_and_pool_mirror(self):
+ self.setup_2vm_2vf_env()
+ self.setup_two_vm_common_prerequisite()
+
+ port_id_0 = 0
+ vlan_id = 3
+ vf_mask = '0x2'
+ packet_num = 10
+
+ self.host_testpmd.execute_cmd(
+ 'rx_vlan add %d port %d vf %s' % (vlan_id, port_id_0, vf_mask))
+ self.set_port_pool_mirror(port_id_0, '0x1 dst-pool 1 on')
+ self.set_port_vlan_mirror(port_id_0, '%d dst-pool 0 on' % vlan_id)
+
+ vm1_start_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+ self.send_packet(
+ self.vm_dut_0,
+ self.vm0_dut_ports,
+ port_id_0,
+ count=packet_num)
+ vm1_end_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+
+ vm1_ret_stats = self.calculate_stats(vm1_start_stats, vm1_end_stats)
+
+ self.verify(vm1_ret_stats['RX-packets'] == packet_num and
+ vm1_ret_stats['TX-packets'] == packet_num,
+ "Pool mirror failed between VM0 and VM1 when set vlan and pool mirror!")
+
+ vm0_start_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ ether_ip = {}
+ ether_ip['dot1q'] = {'vlan': '%d' % vlan_id}
+ self.send_packet(
+ self.vm_dut_1,
+ self.vm1_dut_ports,
+ port_id_0,
+ count=10 *
+ packet_num,
+ **ether_ip)
+ vm0_end_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+
+ vm0_ret_stats = self.calculate_stats(vm0_start_stats, vm0_end_stats)
+
+ self.verify(vm0_ret_stats['RX-packets'] == 10 * packet_num,
+ "Vlan mirror failed between VM0 and VM1 when set vlan and pool mirror!")
+
+ self.reset_port_all_mirror_rule(port_id_0)
+
+ def test_two_vms_uplink_and_downlink_mirror(self):
+ self.setup_2vm_2vf_env()
+ self.setup_two_vm_common_prerequisite()
+
+ self.vm0_testpmd.execute_cmd('stop')
+ self.vm1_testpmd.execute_cmd('stop')
+
+ port_id_0 = 0
+ packet_num = 10
+
+ self.set_port_downlink_mirror(port_id_0, 'dst-pool 1 on')
+ self.set_port_uplink_mirror(port_id_0, 'dst-pool 1 on')
+
+ self.vm1_testpmd.execute_cmd('set fwd rxonly')
+ self.vm1_testpmd.execute_cmd('start')
+ vm1_start_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+ vm0_start_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ self.vm0_testpmd.execute_cmd('start tx_first')
+ vm0_end_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ vm1_end_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+
+ vm0_ret_stats = self.calculate_stats(vm0_start_stats, vm0_end_stats)
+ vm1_ret_stats = self.calculate_stats(vm1_start_stats, vm1_end_stats)
+
+ self.verify(vm1_ret_stats['RX-packets'] == vm0_ret_stats['TX-packets'],
+ "Downlink mirror failed between VM0 and VM1 " +
+ "when set uplink and downlink mirror!")
+
+ self.vm0_testpmd.execute_cmd('stop')
+ self.vm0_testpmd.execute_cmd('set fwd mac')
+ self.vm0_testpmd.execute_cmd('start')
+
+ vm1_start_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+ self.send_packet(
+ self.vm_dut_0,
+ self.vm0_dut_ports,
+ port_id_0,
+ count=packet_num)
+ vm1_end_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+
+ vm1_ret_stats = self.calculate_stats(vm1_start_stats, vm1_end_stats)
+
+ self.verify(vm1_ret_stats['RX-packets'] == 2 * packet_num,
+ "Uplink and down link mirror failed between VM0 and VM1 " +
+ "when set uplink and downlink mirror!")
+
+ self.reset_port_all_mirror_rule(port_id_0)
+
+ def test_two_vms_vlan_and_pool_and_uplink_and_downlink(self):
+ self.setup_2vm_2vf_env()
+ self.setup_two_vm_common_prerequisite()
+
+ self.vm0_testpmd.execute_cmd('stop')
+ self.vm1_testpmd.execute_cmd('stop')
+
+ port_id_0 = 0
+ vlan_id = 3
+ vf_mask = '0x2'
+ packet_num = 1
+
+ self.set_port_downlink_mirror(port_id_0, 'dst-pool 1 on')
+ self.set_port_uplink_mirror(port_id_0, 'dst-pool 1 on')
+ self.host_testpmd.execute_cmd("rx_vlan add %d port %d vf %s" %
+ (vlan_id, port_id_0, vf_mask))
+ self.set_port_vlan_mirror(port_id_0, '%d dst-pool 0 on' % vlan_id)
+ self.set_port_pool_mirror(port_id_0, '0x1 dst-pool 1 on')
+
+ self.vm1_testpmd.execute_cmd('set fwd rxonly')
+ self.vm1_testpmd.execute_cmd('start')
+ vm1_start_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+ vm0_start_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ self.vm0_testpmd.execute_cmd('start tx_first')
+ vm0_end_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ vm1_end_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+
+ vm0_ret_stats = self.calculate_stats(vm0_start_stats, vm0_end_stats)
+ vm1_ret_stats = self.calculate_stats(vm1_start_stats, vm1_end_stats)
+
+ self.verify(vm1_ret_stats['RX-packets'] == vm0_ret_stats['TX-packets'],
+ "Downlink mirror failed between VM0 and VM1 " +
+ "when set vlan, pool, uplink and downlink mirror!")
+
+ self.vm0_testpmd.execute_cmd('stop')
+ self.vm0_testpmd.execute_cmd('set fwd mac')
+ self.vm0_testpmd.execute_cmd('start')
+ vm0_start_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ vm1_start_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+ self.send_packet(
+ self.vm_dut_0,
+ self.vm0_dut_ports,
+ port_id_0,
+ count=packet_num)
+ vm0_end_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ vm1_end_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+
+ vm0_ret_stats = self.calculate_stats(vm0_start_stats, vm0_end_stats)
+ vm1_ret_stats = self.calculate_stats(vm1_start_stats, vm1_end_stats)
+
+ self.verify(vm0_ret_stats['RX-packets'] == packet_num and
+ vm0_ret_stats['TX-packets'] == packet_num and
+ vm1_ret_stats['RX-packets'] == 2 * packet_num,
+ "Uplink and downlink mirror failed between VM0 and VM1 " +
+ "when set vlan, pool, uplink and downlink mirror!")
+
+ self.vm0_testpmd.execute_cmd('stop')
+ self.vm0_testpmd.execute_cmd('set fwd mac')
+ self.vm0_testpmd.execute_cmd('start')
+
+ ether_ip = {}
+ ether_ip['dot1q'] = {'vlan': '%d' % vlan_id}
+ vm1_start_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+ vm0_start_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ self.send_packet(
+ self.vm_dut_1,
+ self.vm1_dut_ports,
+ port_id_0,
+ count=packet_num,
+ **ether_ip)
+ vm0_end_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ vm1_end_stats = self.vm1_testpmd.get_pmd_stats(port_id_0)
+
+ vm0_ret_stats = self.calculate_stats(vm0_start_stats, vm0_end_stats)
+ vm1_ret_stats = self.calculate_stats(vm1_start_stats, vm1_end_stats)
+
+ self.verify(vm0_ret_stats['RX-packets'] == packet_num and
+ vm0_ret_stats['TX-packets'] == packet_num and
+ vm1_ret_stats['RX-packets'] == 2 * packet_num,
+ "Vlan and downlink mirror failed between VM0 and VM1 " +
+ "when set vlan, pool, uplink and downlink mirror!")
+
+ self.reset_port_all_mirror_rule(port_id_0)
+
+ def test_two_vms_add_multi_exact_mac_on_vf(self):
+ self.setup_2vm_2vf_env()
+ self.setup_two_vm_common_prerequisite()
+
+ port_id_0 = 0
+ vf_num = 0
+ packet_num = 10
+
+ for vf_mac in ["00:11:22:33:44:55", "00:55:44:33:22:11"]:
+ self.host_testpmd.execute_cmd("mac_addr add port %d vf %d %s" %
+ (port_id_0, vf_num, vf_mac))
+
+ vm0_start_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ ether_ip = {}
+ ether_ip['ether'] = {'dest_mac': '%s' % vf_mac}
+ self.send_packet(
+ self.vm_dut_0,
+ self.vm0_dut_ports,
+ port_id_0,
+ count=packet_num,
+ **ether_ip)
+ vm0_end_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+
+ vm0_ret_stats = self.calculate_stats(
+ vm0_start_stats, vm0_end_stats)
+
+ self.verify(vm0_ret_stats['RX-packets'] == packet_num,
+ "Add exact MAC %s failed btween VF0 and VF1" % vf_mac +
+ "when add multi exact MAC address on VF!")
+
+ def test_two_vms_enalbe_or_disable_one_uta_mac_on_vf(self):
+ self.setup_2vm_2vf_env()
+ self.setup_two_vm_common_prerequisite()
+
+ port_id_0 = 0
+ vf_mac = "00:11:22:33:44:55"
+ packet_num = 10
+
+ self.host_testpmd.execute_cmd('set promisc %d on' % port_id_0)
+ self.host_testpmd.execute_cmd(
+ 'set port %d vf 0 rxmode ROPE on' % port_id_0)
+ self.host_testpmd.execute_cmd(
+ 'set port %d vf 1 rxmode ROPE off' % port_id_0)
+ self.host_testpmd.execute_cmd(
+ 'set port %d uta %s on' % (port_id_0, vf_mac))
+
+ vm0_start_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ ether_ip = {}
+ ether_ip['ether'] = {'dest_mac': '%s' % vf_mac}
+ self.send_packet(self.vm_dut_0, self.vm0_dut_ports, port_id_0,
+ count=packet_num, **ether_ip)
+ vm0_end_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+
+ vm0_ret_stats = self.calculate_stats(vm0_start_stats, vm0_end_stats)
+
+ self.verify(vm0_ret_stats['RX-packets'] == packet_num,
+ "Enable one uta MAC failed between VM0 and VM1 " +
+ "when enable or disable one uta MAC address on VF!")
+
+ self.host_testpmd.execute_cmd('set promisc %d off' % port_id_0)
+ self.host_testpmd.execute_cmd(
+ 'set port %d vf 0 rxmode ROPE off' % port_id_0)
+
+ vm0_start_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ ether_ip = {}
+ ether_ip['ether'] = {'dest_mac': '%s' % vf_mac}
+ self.send_packet(self.vm_dut_0, self.vm0_dut_ports, port_id_0,
+ count=packet_num, invert_verify=True, **ether_ip)
+ vm0_end_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+
+ vm0_ret_stats = self.calculate_stats(vm0_start_stats, vm0_end_stats)
+
+ self.verify(vm0_ret_stats['RX-packets'] == 0,
+ "Disable one uta MAC failed between VM0 and VM1 " +
+ "when enable or disable one uta MAC address on VF!")
+
+ def test_two_vms_add_multi_uta_mac_on_vf(self):
+ self.setup_2vm_2vf_env()
+ self.setup_two_vm_common_prerequisite()
+
+ port_id_0 = 0
+ packet_num = 10
+
+ for vf_mac in ["00:55:44:33:22:11", "00:55:44:33:22:66"]:
+ self.host_testpmd.execute_cmd("set port %d uta %s on" %
+ (port_id_0, vf_mac))
+ self.host_testpmd.execute_cmd("set port %d uta %s on" %
+ (port_id_0, vf_mac))
+
+ for vf_mac in ["00:55:44:33:22:11", "00:55:44:33:22:66"]:
+ vm0_start_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ ether_ip = {}
+ ether_ip['ether'] = {'dest_mac': '%s' % vf_mac}
+ self.send_packet(self.vm_dut_0, self.vm0_dut_ports,
+ port_id_0, count=packet_num, **ether_ip)
+ vm0_end_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+
+ vm0_ret_stats = self.calculate_stats(
+ vm0_start_stats, vm0_end_stats)
+
+ self.verify(vm0_ret_stats['RX-packets'] == packet_num,
+ "Add MULTI uta MAC %s failed between VM0 and VM1 " % vf_mac +
+ "when add multi uta MAC address on VF!")
+
+ def test_two_vms_add_or_remove_uta_mac_on_vf(self):
+ self.setup_2vm_2vf_env()
+ self.setup_two_vm_common_prerequisite()
+
+ port_id_0 = 0
+ vf_mac = "00:55:44:33:22:11"
+ packet_num = 10
+
+ for switch in ['on', 'off', 'on']:
+ self.host_testpmd.execute_cmd("set port %d uta %s %s" %
+ (port_id_0, vf_mac, switch))
+
+ vm0_start_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ ether_ip = {}
+ ether_ip['ether'] = {'dest_mac': '%s' % vf_mac}
+ if switch == 'on':
+ self.send_packet(self.vm_dut_0, self.vm0_dut_ports,
+ port_id_0, count=packet_num, **ether_ip)
+ else:
+ self.send_packet(self.vm_dut_0, self.vm0_dut_ports, port_id_0,
+ count=packet_num, invert_verify=True, **ether_ip)
+ vm0_end_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+
+ vm0_ret_stats = self.calculate_stats(
+ vm0_start_stats, vm0_end_stats)
+
+ if switch == 'on':
+ self.verify(vm0_ret_stats['RX-packets'] == packet_num,
+ "Add MULTI uta MAC %s failed between VM0 and VM1 " % vf_mac +
+ "when add or remove multi uta MAC address on VF!")
+ else:
+ self.verify(vm0_ret_stats['RX-packets'] == 0,
+ "Remove MULTI uta MAC %s failed between VM0 and VM1 " % vf_mac +
+ "when add or remove multi uta MAC address on VF!")
+
+ def test_two_vms_pause_rx_queues(self):
+ self.setup_2vm_2vf_env()
+ self.setup_two_vm_common_prerequisite()
+
+ port_id_0 = 0
+ packet_num = 10
+
+ for switch in ['on', 'off', 'on']:
+ self.host_testpmd.execute_cmd("set port %d vf 0 rx %s" %
+ (port_id_0, switch))
+
+ vm0_start_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ if switch == 'on':
+ self.send_packet(self.vm_dut_0, self.vm0_dut_ports,
+ port_id_0, count=packet_num)
+ else:
+ self.send_packet(self.vm_dut_0, self.vm0_dut_ports, port_id_0,
+ count=packet_num, invert_verify=True)
+ vm0_end_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+
+ vm0_ret_stats = self.calculate_stats(
+ vm0_start_stats, vm0_end_stats)
+
+ if switch == 'on':
+ self.verify(vm0_ret_stats['RX-packets'] == packet_num,
+ "Enable RX queues failed between VM0 and VM1 " +
+ "when enable or pause RX queues on VF!")
+ else:
+ self.verify(vm0_ret_stats['RX-packets'] == 0,
+ "Pause RX queues failed between VM0 and VM1 " +
+ "when enable or pause RX queues on VF!")
+
+ def test_two_vms_pause_tx_queuse(self):
+ self.setup_2vm_2vf_env()
+ self.setup_two_vm_common_prerequisite()
+
+ self.vm0_testpmd.execute_cmd("stop")
+ self.vm0_testpmd.execute_cmd("set fwd mac")
+ self.vm0_testpmd.execute_cmd("start")
+
+ port_id_0 = 0
+ packet_num = 10
+
+ for switch in ['on', 'off', 'on']:
+ self.host_testpmd.execute_cmd("set port %d vf 0 tx %s" %
+ (port_id_0, switch))
+
+ vm0_start_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ self.send_packet(
+ self.vm_dut_0,
+ self.vm0_dut_ports,
+ port_id_0,
+ count=packet_num)
+ vm0_end_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+
+ vm0_ret_stats = self.calculate_stats(
+ vm0_start_stats, vm0_end_stats)
+
+ if switch == 'on':
+ self.verify(vm0_ret_stats['TX-packets'] == packet_num,
+ "Enable TX queues failed between VM0 and VM1 " +
+ "when enable or pause TX queues on VF!")
+ else:
+ self.verify(vm0_ret_stats['TX-packets'] == 0,
+ "Pause TX queues failed between VM0 and VM1 " +
+ "when enable or pause TX queues on VF!")
+
+ def test_two_vms_prevent_rx_broadcast_on_vf(self):
+ self.setup_2vm_2vf_env()
+ self.setup_two_vm_common_prerequisite()
+
+ port_id_0 = 0
+ vf_mac = "FF:FF:FF:FF:FF:FF"
+ packet_num = 10
+
+ for switch in ['on', 'off', 'on']:
+ self.host_testpmd.execute_cmd("set port %d vf 0 rxmode BAM %s" %
+ (port_id_0, switch))
+
+ vm0_start_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+ ether_ip = {}
+ ether_ip['ether'] = {'dest_mac': '%s' % vf_mac}
+ if switch == 'on':
+ self.send_packet(self.vm_dut_0, self.vm0_dut_ports, port_id_0,
+ count=packet_num, **ether_ip)
+ else:
+ self.send_packet(self.vm_dut_0, self.vm0_dut_ports, port_id_0,
+ count=packet_num, invert_verify=True, **ether_ip)
+ vm0_end_stats = self.vm0_testpmd.get_pmd_stats(port_id_0)
+
+ vm0_ret_stats = self.calculate_stats(
+ vm0_start_stats, vm0_end_stats)
+
+ if switch == 'on':
+ self.verify(vm0_ret_stats['RX-packets'] == packet_num,
+ "Enable RX broadcast failed between VM0 and VM1 " +
+ "when enable or disable RX queues on VF!")
+ else:
+ self.verify(vm0_ret_stats['RX-packets'] == 0,
+ "Disable RX broadcast failed between VM0 and VM1 " +
+ "when enable or pause TX queues on VF!")
+
+ def test_two_vms_negative_input_commands(self):
+ self.setup_2vm_2vf_env()
+ self.setup_two_vm_common_prerequisite()
+
+ for command in ["set port 0 vf 65 tx on",
+ "set port 2 vf -1 tx off",
+ "set port 0 vf 0 rx oneee",
+ "set port 0 vf 0 rx offdd",
+ "set port 0 vf 64 rxmode BAM on",
+ "set port 0 vf 64 rxmode BAM off",
+ "set port 0 uta 00:11:22:33:44 on",
+ "set port 7 uta 00:55:44:33:22:11 off",
+ "set port 0 vf 34 rxmode ROPE on",
+ "mac_addr add port 0 vf 65 00:55:44:33:22:11",
+ "mac_addr add port 5 vf 0 00:55:44:88:22:11",
+ "set port 0 mirror-rule 0xf uplink-mirror dst-pool 1 on",
+ "set port 0 mirror-rule 2 vlan-mirror 9 dst-pool 1 on",
+ "set port 0 mirror-rule 0 downlink-mirror 0xf dst-pool 2 off",
+ "reset port 0 mirror-rule 4",
+ "reset port 0xff mirror-rule 0"]:
+ output = self.host_testpmd.execute_cmd(command)
+ error = False
+
+ for error_regx in [r'Bad', r'bad', r'failed', r'-[0-9]+', r'error', r'Invalid']:
+ ret_regx = re.search(error_regx, output)
+ if ret_regx and ret_regx.group():
+ error = True
+ break
+ self.verify(
+ error, "Execute command '%s' successfully, it should be failed!" % command)
+
+ def tear_down(self):
+ if self.setup_2vm_prerequisite_flag == 1:
+ self.destroy_two_vm_common_prerequisite()
+ if self.setup_2vm_2vf_env_flag == 1:
+ self.destroy_2vm_2vf_env()
+
+ if self.setup_2vm_2pf_env_flag == 1:
+ slef.destroy_2vm_2pf_env()
+
+ if self.setup_4vm_prerequisite_flag == 1:
+ self.destroy_four_vm_common_prerequisite()
+ if self.setup_4vm_4vf_env_flag == 1:
+ self.destroy_4vm_4vf_env()
+
+ def tear_down_all(self):
+ if getattr(self, 'vm0', None):
+ self.vm0.stop()
+ if getattr(self, 'vm1', None):
+ self.vm1.stop()
+ if getattr(self, 'vm2', None):
+ self.vm2.stop()
+ if getattr(self, 'vm3', None):
+ self.vm3.stop()
+
+ for port_id in self.dut_ports:
+ self.dut.destroy_sriov_vfs_by_port(port_id)
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread