test suite reviews and discussions
 help / color / mirror / Atom feed
* [dts] [PATCH v2 00/19] *** Enable virtualization test for dts framework ***
@ 2015-05-22  9:03 Jiajia, Sun
  2015-05-22  9:03 ` [dts] [PATCH v2 01/19] Abstract the NIC device as the single class NetDevice Jiajia, Sun
                   ` (18 more replies)
  0 siblings, 19 replies; 24+ messages in thread
From: Jiajia, Sun @ 2015-05-22  9:03 UTC (permalink / raw)
  To: dts

From: sjiajiax <sunx.jiajia@intel.com>

This patch-set do many efforts to make dts framework to support 
virtualization test. First, add a virt_base class to define the
base property and methods, then extend the base class by the specified
virtualization type, and add a virtual DUT to abstract the VM,
try many efforts to make the VM DUT like the general DUT there has
been the DUT on the framework. 

And there is a test suite named as TestSuite_sriov_kvm.py to verify
the changed framework worked well.


sjiajiax (19):
  Abstract the NIC device as the single class NetDevice
  Add a base module for virtual test
  Add QEMU KVM module based on virt_base module for KVM test cases
  Add a module to manage the host resource
  Add a module to instantiate the VM
  Add a third-party module of qemu-guest-agent to manage VM
  Move some general functions from dts.py to utils.py and settings.py
  Add and move some functions because of the virtual tests and network
    device instantiation
  Change and add some functions to support virtual test
  add some exceptions to support framwork to handle virtual test
    exceptions
  Add some codes to support virtual test log
  Add some codes to make session to support virtual test
  Add some base functions to get the device info in the testpmd
  Change some codes to support network device instantiation and
    virtualization test
  Add some codes to support network instantiation in the tester module
  Make test_case know its suite name
  Add a global virtualization config and a config related to SRIOV KVM
    suite
  Add a test plan of how to test SRIOV on the KVM ENV
  Add a test suite to verify the SRIOV feature on the KVM ENV

 conf/sriov_kvm.cfg                 |  164 +++++
 conf/virt_global.cfg               |   24 +
 dep/QMP/qemu-ga-client             |  299 +++++++++
 dep/QMP/qmp.py                     |  193 ++++++
 framework/config.py                |  170 ++++-
 framework/crb.py                   |  126 ++--
 framework/dts.py                   |   86 +--
 framework/dut.py                   |  235 ++++++-
 framework/exception.py             |   69 ++
 framework/logger.py                |   69 +-
 framework/net_device.py            |  634 ++++++++++++++++++
 framework/pmd_output.py            |   92 +++
 framework/project_dpdk.py          |   29 +-
 framework/qemu_kvm.py              |  972 +++++++++++++++++++++++++++
 framework/settings.py              |   43 ++
 framework/ssh_pexpect.py           |   62 +-
 framework/test_case.py             |    3 +-
 framework/tester.py                |   51 +-
 framework/utils.py                 |  100 +++
 framework/virt_base.py             |  321 +++++++++
 framework/virt_dut.py              |  202 ++++++
 framework/virt_resource.py         |  490 ++++++++++++++
 test_plans/sriov_kvm_test_plan.rst |  756 +++++++++++++++++++++
 tests/TestSuite_sriov_kvm.py       | 1291 ++++++++++++++++++++++++++++++++++++
 24 files changed, 6253 insertions(+), 228 deletions(-)
 create mode 100644 conf/sriov_kvm.cfg
 create mode 100644 conf/virt_global.cfg
 create mode 100644 dep/QMP/qemu-ga-client
 create mode 100644 dep/QMP/qmp.py
 mode change 100755 => 100644 framework/config.py
 create mode 100644 framework/net_device.py
 create mode 100644 framework/qemu_kvm.py
 create mode 100644 framework/utils.py
 create mode 100644 framework/virt_base.py
 create mode 100644 framework/virt_dut.py
 create mode 100644 framework/virt_resource.py
 create mode 100644 test_plans/sriov_kvm_test_plan.rst
 create mode 100644 tests/TestSuite_sriov_kvm.py

-- 
1.9.3

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [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

* [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

* 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

end of thread, other threads:[~2015-05-27  1:38 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [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 ` [dts] [PATCH v2 04/19] Add a module to manage the host resource Jiajia, Sun
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
2015-05-26  9:07       ` Qiu, Michael
2015-05-27  1:36         ` Jiajia, SunX
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 ` [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 ` [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 ` [dts] [PATCH v2 09/19] Change and add some functions to support virtual test 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
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 ` [dts] [PATCH v2 12/19] Add some codes to make session to support virtual test 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
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 ` [dts] [PATCH v2 15/19] Add some codes to support network instantiation in the tester module Jiajia, Sun
2015-05-22  9:04 ` [dts] [PATCH v2 16/19] Make test_case know its suite name 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
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).