[dts] [‘dts-v1’ 1/9] Abstract the NIC device as the single class NetDevice

Xu, HuilongX huilongx.xu at intel.com
Mon May 18 09:46:40 CEST 2015


Hi Jiajia,
I have two comments in this patch,
Would you check the comments in function "def destroy_sriov_vfs_by_port(self, port_id):" and "def set_toolchain(self, target):"
Thanks  a lot

-----Original Message-----
From: dts [mailto:dts-bounces at dpdk.org] On Behalf Of sjiajiax
Sent: Monday, May 18, 2015 1:07 PM
To: dts at dpdk.org
Subject: [dts] [‘dts-v1’ 1/9] Abstract the NIC device as the single class NetDevice

Signed-off-by: sjiajiax <sunx.jiajia at intel.com>
---
 framework/crb.py        | 135 +++++++----
 framework/dut.py        | 268 ++++++++++++++++++---
 framework/net_device.py | 600 ++++++++++++++++++++++++++++++++++++++++++++++++
 framework/settings.py   |  43 ++++
 framework/test_case.py  |   3 +-
 framework/tester.py     |  51 +++-
 6 files changed, 1006 insertions(+), 94 deletions(-)
 create mode 100644 framework/net_device.py

diff --git a/framework/crb.py b/framework/crb.py
index a699bfc..2eb2033 100644
--- a/framework/crb.py
+++ b/framework/crb.py
@@ -69,6 +69,12 @@ class Crb(object):
 
         return self.session.send_expect(cmds, expected, timeout, verify)
 
+    def get_session_output(self, timeout=TIMEOUT):
+        """
+        Get session output message before timeout
+        """
+        return self.session.get_session_before(timeout)
+
     def set_test_types(self, func_tests, perf_tests):
         """
         Enable or disable function/performance test.
@@ -80,7 +86,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
@@ -115,6 +123,9 @@ class Crb(object):
         """
         self.base_dir = base_dir
 
+    def set_virttype(self, virttype):
+        self.virttype = virttype
+
     def admin_ports(self, port, status):
         """
         Force set port's interface status.
@@ -127,13 +138,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 +170,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 +183,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 +193,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=''):
-        """
-        Get interface name 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)
-
-    def get_interface_name_linux(self, bus_id, devfun_id):
+    def get_pci_dev_driver(self, bus_id, devfun_id):
         """
-        Get interface name of specified pci device on linux.
+        Get the driver of specified pci device.
         """
-        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
+        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_freebsd(self, bus_id, devfun_id):
+    def get_pci_dev_driver_linux(self, bus_id, devfun_id):
         """
-        Get interface name of specified pci device on Freebsd.
+        Get the driver of specified pci device on linux.
         """
-        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.
+        """
+        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), "# ")
+        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 +276,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 +292,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 +351,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 +411,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" +
diff --git a/framework/dut.py b/framework/dut.py
index 5b7aba2..247b01c 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)
         when virt dut init not have any port, but we will add port by hot plug or build vport by dpdk app testpmd(eg, xen virtio test)
         The test will can't continued
         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))
@@ -228,7 +258,10 @@ class Dut(Crb):
         """
         Setup Linux hugepages.
         """
-        hugepages_size = self.send_expect("awk '/Hugepagesize/ {print $2}' /proc/meminfo", "# ")
+        if self.virttype == 'xen':
+            return
+        hugepages_size = self.send_expect(
+            "awk '/Hugepagesize/ {print $2}' /proc/meminfo", "# ")
 
         if int(hugepages_size) < (1024 * 1024):
             if self.architecture == "x86_64":
@@ -265,6 +298,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 +322,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 +345,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):
@@ -314,14 +372,17 @@ class Dut(Crb):
             perf = self.want_perf_tests
 
         nictypes = []
-        if nic_type == 'any':
+        if self.nic_type == 'any':
             for portid in range(len(self.ports_info)):
                 ports.append(portid)
             return ports
-        elif nic_type == 'cfg':
+        elif self.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 +501,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 +544,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 +584,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 +597,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 +609,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 +642,93 @@ 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:
             Why we need "sriov_vfs_pci"? would we check destroy sriov vfs succeed or failed before we reset ports_info?
+            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 create_blacklist_string(self, target, nic):
+        create_blacklist_string = getattr(
+            self, 'create_blacklist_string_%s' % self.get_os_type())
+        return create_blacklist_string(target, nic)
+
+    def create_blacklist_string_linux(self, target, nic):
+        blacklist = ''
+        dutPorts = self.get_ports(nic)
+        self.restore_interfaces()
+        if dts.drivername == "igb_uio":
+            self.send_expect('insmod ./%s/kmod/igb_uio.ko ' % target, '# ')
+        elif dts.drivername == "vfio-pci":
+            self.send_expect("modprobe vfio", '# ')
+            self.send_expect("modprobe vfio-pci", '# ')
+        self.bind_interfaces_linux(dts.drivername)
+        for port in range(0, len(self.ports_info)):
+            if(port not in dutPorts):
+                blacklist += '-b 0000:%s ' % self.ports_info[port]['pci']
+        return blacklist
+
+    def create_blacklist_string_freebsd(self, target, nic):
+        blacklist = ''
+        # No blacklist option in FreeBSD
+        return blacklist
+
     def load_portconf(self):
         """
         Load port configurations for ports_info. If manually configured infor
@@ -637,7 +803,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 +826,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/net_device.py b/framework/net_device.py
new file mode 100644
index 0000000..c04d442
--- /dev/null
+++ b/framework/net_device.py
@@ -0,0 +1,600 @@
+import os
+import re
+from functools import wraps
+import time
+import pdb
+
+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)
+        # bind to default driver
+        current_driver = self.get_nic_driver()
+        if self.default_driver != current_driver:
+            self.bind_driver()
+        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"
+        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.
+        """
+        nic_pci_num = ':'.join(['0000', bus_id, devfun_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/%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.
+        """
+        nic_pci_num = ':'.join(['0000', bus_id, devfun_id])
+        pci_id = self.get_card_type()
+        self.__send_expect(
+            "echo %s > /sys/bus/pci/drivers/pci-stub/new_id" %
+            nic_pci_num, "# ")
+        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), "# ")
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/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']
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.0



More information about the dts mailing list