test suite reviews and discussions
 help / color / mirror / Atom feed
* [dts] [PATCH 0/3] Optimize virtual machine network topology discovery
@ 2015-06-29  5:17 Yong Liu
  2015-06-29  5:17 ` [dts] [PATCH 1/3] Add new API for get host and VM pass-throught devices pci mapping Yong Liu
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Yong Liu @ 2015-06-29  5:17 UTC (permalink / raw)
  To: dts

From: Marvin Liu <yong.liu@intel.com>

When host and tester on the same crb, network topology discovery routine
should skipped ping from those devcies which on the same PF devices.

For only qemu process known the host pci address of pass-through device,
framework add support for qemu monitor session.

Marvin Liu (3):
  Add new API for get host and VM pass-throught devices pci mapping
  Optimize virtual machine port map routine
  Refresh default VM configurations after setting VM name

 framework/qemu_kvm.py   | 134 +++++++++++++++++++++++++++++++++++++++---------
 framework/virt_base.py  |   6 +++
 framework/virt_dut.py   |  37 +++++++------
 framework/virt_scene.py |   1 +
 4 files changed, 138 insertions(+), 40 deletions(-)

-- 
1.9.3

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

* [dts] [PATCH 1/3] Add new API for get host and VM pass-throught devices pci mapping
  2015-06-29  5:17 [dts] [PATCH 0/3] Optimize virtual machine network topology discovery Yong Liu
@ 2015-06-29  5:17 ` Yong Liu
  2015-06-29  5:17 ` [dts] [PATCH 2/3] Optimize virtual machine port map routine Yong Liu
  2015-06-29  5:17 ` [dts] [PATCH 3/3] Refresh default VM configurations after setting VM name Yong Liu
  2 siblings, 0 replies; 4+ messages in thread
From: Yong Liu @ 2015-06-29  5:17 UTC (permalink / raw)
  To: dts

From: Marvin Liu <yong.liu@intel.com>

After device pass-through into VM, qemu will assigned pci address
automatically. The mapping between host pci and guest pci only be obtained
from qemu process.
The mapping used in network topology scansion, skip ping from those devices
which belong to same PF device.

Support qemu monitor session in kvm module.
Optimize qemu hypervisor initialization process.

Signed-off-by: Marvin Liu <yong.liu@intel.com>

diff --git a/framework/qemu_kvm.py b/framework/qemu_kvm.py
index 482ba46..20a1df4 100644
--- a/framework/qemu_kvm.py
+++ b/framework/qemu_kvm.py
@@ -68,10 +68,6 @@ class QEMUKvm(VirtBase):
     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()
 
@@ -88,25 +84,37 @@ class QEMUKvm(VirtBase):
         # charater and network device default index
         self.char_idx = 0
         self.netdev_idx = 0
+        self.pt_idx = 0
 
         # devices pass-through into vm
         self.pt_devices = []
+        self.pci_maps = []
 
         # default login user,password
         self.username = dut.crb['user']
         self.password = dut.crb['pass']
 
+        # internal variable to track whether default nic has been added
+        self.__default_nic = False
+
+        # set some default values for vm,
+        # if there is not the values of the specified options
+        self.set_vm_default()
+
     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()
+        self.set_vm_monitor()
 
-        # add default control interface
-        def_nic = {'type': 'nic', 'opt_vlan': '0'}
-        self.set_vm_net(**def_nic)
-        def_net = {'type': 'user', 'opt_vlan': '0'}
-        self.set_vm_net(**def_net)
+        if not self.__default_nic:
+            # add default control interface
+            def_nic = {'type': 'nic', 'opt_vlan': '0'}
+            self.set_vm_net(**def_nic)
+            def_net = {'type': 'user', 'opt_vlan': '0'}
+            self.set_vm_net(**def_net)
+            self.__default_nic = True
 
     def init_vm_request_resource(self):
         """
@@ -214,7 +222,11 @@ class QEMUKvm(VirtBase):
         """
         Set VM boot option to enable the option 'enable-kvm'.
         """
-        self.params.append({'enable_kvm': [{'enable': '%s' % enable}]})
+        index = self.find_option_index('enable_kvm')
+        if index:
+            self.params[index] = {'enable_kvm': [{'enable': '%s' % enable}]}
+        else:
+            self.params.append({'enable_kvm': [{'enable': '%s' % enable}]})
 
     def add_vm_enable_kvm(self, **options):
         """
@@ -229,7 +241,11 @@ class QEMUKvm(VirtBase):
         """
         Set VM name.
         """
-        self.params.append({'name': [{'name': '%s' % vm_name}]})
+        index = self.find_option_index('name')
+        if index:
+            self.params[index] = {'name': [{'name': '%s' % vm_name}]}
+        else:
+            self.params.append({'name': [{'name': '%s' % vm_name}]})
 
     def add_vm_name(self, **options):
         """
@@ -559,6 +575,8 @@ class QEMUKvm(VirtBase):
         if 'opt_host' in options.keys() and \
                 options['opt_host']:
             dev_boot_line += separator + 'host=%s' % options['opt_host']
+            dev_boot_line += separator + 'id=pt_%d' % self.pt_idx
+            self.pt_idx += 1
             self.pt_devices.append(options['opt_host'])
         if 'opt_addr' in options.keys() and \
                 options['opt_addr']:
@@ -641,20 +659,28 @@ class QEMUKvm(VirtBase):
         else:
             return False
 
-    def add_vm_monitor(self, **options):
+    def set_vm_monitor(self):
         """
-        port: 6061   # if adding monitor to vm, need to specicy
-                       this port, else it will get a free port
-                       on the host machine.
+        Set VM boot option to enable qemu monitor.
         """
-        if 'port' in options.keys():
-            if options['port']:
-                port = options['port']
-            else:
-                port = self.virt_pool.alloc_port(self.vm_name)
+        index = self.find_option_index('monitor')
+        if index:
+            self.params[index] = {'monitor': [{'path': '/tmp/%s_monitor.sock' %
+                                                (self.vm_name)}]}
+        else:
+            self.params.append({'monitor': [{'path': '/tmp/%s_monitor.sock' %
+                                         (self.vm_name)}]})
 
-            monitor_boot_line = '-monitor tcp::%d,server,nowait' % int(port)
+    def add_vm_monitor(self, **options):
+        """
+        path: if adding monitor to vm, need to specify unix socket patch
+        """
+        if 'path' in options.keys():
+            monitor_boot_line = '-monitor unix:%s,server,nowait' % options['path']
             self.__add_boot_line(monitor_boot_line)
+            self.monitor_sock_path = options['path']
+        else:
+            self.monitor_sock_path = None
 
     def set_vm_qga(self, enable='yes'):
         """
@@ -765,6 +791,7 @@ class QEMUKvm(VirtBase):
         if "Not responded" in out:
             raise StartVMFailedException('Not response in 60 seconds!!!')
 
+        self.__get_pci_mapping()
         self.__wait_vmnet_ready()
 
     def generate_qemu_boot_line(self):
@@ -940,8 +967,69 @@ class QEMUKvm(VirtBase):
                     return ip
         return ''
 
-    def get_vm_pt_devices(self):
-        return self.pt_devices
+    def __get_pci_mapping(self):
+        devices = self.__strip_guest_pci()
+        for hostpci in self.pt_devices:
+            index = self.pt_devices.index(hostpci)
+            pt_id = 'pt_%d' %index
+            pci_map = {}
+            for device in devices:
+                if device['id'] == pt_id:
+                    pci_map['hostpci'] = hostpci
+                    pci_map['guestpci'] = device['pci']
+                    self.pci_maps.append(pci_map)
+
+    def get_pci_mappings(self):
+        """
+        Return guest and host pci devices mapping structure
+        """
+        return self.pci_maps
+
+    def __monitor_session(self, command, *args):
+        """
+        Connect the qemu montior session, send command and return output message.
+        """
+        if not self.monitor_sock_path:
+            self.host_logger.info(
+                "No monitor between on host [ %s ] for guest [ %s ]" %
+                (self.host_dut.Name, self.vm_name))
+            return None
+
+        self.host_session.send_expect('nc -U %s' % self.monitor_sock_path, '(qemu)', 2)
+
+        cmd = command
+        for arg in args:
+            cmd += ' ' + str(arg)
+
+        out = self.host_session.send_expect('%s' % cmd, '(qemu)')
+        self.host_session.send_expect('^C', "# ")
+        return out
+
+    def __strip_guest_pci(self):
+        """
+        Strip all pci-passthrough device information, based on qemu monitor
+        """
+        pci_reg = r'^.*Bus(\s+)(\d+), device(\s+)(\d+), function (\d+)'
+        id_reg = r'^.*id \"(.*)\"'
+
+        out = self.__monitor_session('info', 'pci')
+        lines = out.split("\r\n")
+
+        pcis = []
+        for line in lines:
+            m = re.match(pci_reg, line)
+            n = re.match(id_reg, line)
+            if m:
+                pci = "%02d:%02d.%d" %(int(m.group(2)), int(m.group(4)), int(m.group(5)))
+            if n:
+                dev_id = n.group(1)
+                if dev_id != '':
+                    pt_dev = {}
+                    pt_dev['pci'] = pci
+                    pt_dev['id'] = dev_id
+                    pcis.append(pt_dev)
+
+        return pcis
 
     def __control_session(self, command, *args):
         """
diff --git a/framework/virt_base.py b/framework/virt_base.py
index 063342f..b9ea56f 100644
--- a/framework/virt_base.py
+++ b/framework/virt_base.py
@@ -196,6 +196,12 @@ class VirtBase(object):
         """
         NotImplemented
 
+    def get_pci_mappings(self):
+        """
+        Get host and VM pass-through device mapping
+        """
+        NotImplemented
+
     def isalive(self):
         """
         Check whether VM existed.
-- 
1.9.3

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

* [dts] [PATCH 2/3] Optimize virtual machine port map routine
  2015-06-29  5:17 [dts] [PATCH 0/3] Optimize virtual machine network topology discovery Yong Liu
  2015-06-29  5:17 ` [dts] [PATCH 1/3] Add new API for get host and VM pass-throught devices pci mapping Yong Liu
@ 2015-06-29  5:17 ` Yong Liu
  2015-06-29  5:17 ` [dts] [PATCH 3/3] Refresh default VM configurations after setting VM name Yong Liu
  2 siblings, 0 replies; 4+ messages in thread
From: Yong Liu @ 2015-06-29  5:17 UTC (permalink / raw)
  To: dts

From: Marvin Liu <yong.liu@intel.com>

Skip ping from those devices which on the same PF devices.

Signed-off-by: Marvin Liu <yong.liu@intel.com>

diff --git a/framework/virt_dut.py b/framework/virt_dut.py
index 79ecc2a..2edbf6f 100644
--- a/framework/virt_dut.py
+++ b/framework/virt_dut.py
@@ -285,29 +285,32 @@ class VirtDut(DPDKdut):
 
         hits = [False] * len(self.tester.ports_info)
 
-        for dutPort in range(nrPorts):
-            peer = self.get_peer_pci(dutPort)
+        for vmPort in range(nrPorts):
+            vmpci = self.ports_info[vmPort]['pci']
+            peer = self.get_peer_pci(vmPort)
             # if peer pci configured
             if peer is not None:
                 for remotePort in range(len(self.tester.ports_info)):
                     if self.tester.ports_info[remotePort]['pci'] == peer:
                         hits[remotePort] = True
-                        self.ports_map[dutPort] = remotePort
+                        self.ports_map[vmPort] = remotePort
                         break
-                if self.ports_map[dutPort] == -1:
+                if self.ports_map[vmPort] == -1:
                     self.logger.error("CONFIGURED TESTER PORT CANNOT FOUND!!!")
                 else:
                     continue  # skip ping6 map
 
-            if hasattr(self.hyper, 'pt_devices'):
-                hostpci = self.hyper.pt_devices[dutPort]
-                netdev = get_netdev(self.host_dut, hostpci)
+            # strip pci address on host for pass-through device
+            hostpci = 'N/A'
+            for pci_map in self.hyper.pci_maps:
+                if vmpci == pci_map['guestpci']:
+                    hostpci = pci_map['hostpci']
+                    break
 
             # auto ping port map
             for remotePort in range(len(self.tester.ports_info)):
                 # for two vfs connected to same tester port
-                # can't skip those teste ports even have hits
-                # need skip ping self vf port
+                # need skip ping from devices on same pf device
                 remotepci = self.tester.ports_info[remotePort]['pci']
                 remoteport =  self.tester.ports_info[remotePort]['port']
                 vfs = []
@@ -315,21 +318,21 @@ class VirtDut(DPDKdut):
                 host_ip = self.crb['IP'].split(':')[0]
                 if self.crb['tester IP'] == host_ip:
                     vfs = remoteport.get_sriov_vfs_pci()
-                # if hostpci is vf of tester port
-                if netdev.pci in vfs:
-                    print dts.RED("Skip ping from PF device")
-                    continue
+                    # if hostpci is vf of tester port
+                    if hostpci == remotepci or hostpci in vfs:
+                        print dts.RED("Skip ping from same PF device")
+                        continue
 
-                ipv6 = self.get_ipv6_address(dutPort)
+                ipv6 = self.get_ipv6_address(vmPort)
                 if ipv6 == "Not connected":
                     continue
 
                 out = self.tester.send_ping6(
-                    remotePort, ipv6, self.get_mac_address(dutPort))
+                    remotePort, ipv6, self.get_mac_address(vmPort))
 
                 if ('64 bytes from' in out):
                     self.logger.info(
-                        "PORT MAP: [dut %d: tester %d]" % (dutPort, remotePort))
-                    self.ports_map[dutPort] = remotePort
+                        "PORT MAP: [dut %d: tester %d]" % (vmPort, remotePort))
+                    self.ports_map[vmPort] = remotePort
                     hits[remotePort] = True
                     continue
-- 
1.9.3

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

* [dts] [PATCH 3/3] Refresh default VM configurations after setting VM name
  2015-06-29  5:17 [dts] [PATCH 0/3] Optimize virtual machine network topology discovery Yong Liu
  2015-06-29  5:17 ` [dts] [PATCH 1/3] Add new API for get host and VM pass-throught devices pci mapping Yong Liu
  2015-06-29  5:17 ` [dts] [PATCH 2/3] Optimize virtual machine port map routine Yong Liu
@ 2015-06-29  5:17 ` Yong Liu
  2 siblings, 0 replies; 4+ messages in thread
From: Yong Liu @ 2015-06-29  5:17 UTC (permalink / raw)
  To: dts

From: Marvin Liu <yong.liu@intel.com>

Signed-off-by: Marvin Liu <yong.liu@intel.com>

diff --git a/framework/virt_scene.py b/framework/virt_scene.py
index 3725ca2..cd566ac 100644
--- a/framework/virt_scene.py
+++ b/framework/virt_scene.py
@@ -387,6 +387,7 @@ class VirtScene(object):
                              'virt_global')
                 vm.load_config()
                 vm.vm_name = vm_name
+                vm.set_vm_default()
                 # merge default config and scene config
                 scene_params = self.vm_confs[vm_name]
                 # reload merged configurations
-- 
1.9.3

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

end of thread, other threads:[~2015-06-29  5:17 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-29  5:17 [dts] [PATCH 0/3] Optimize virtual machine network topology discovery Yong Liu
2015-06-29  5:17 ` [dts] [PATCH 1/3] Add new API for get host and VM pass-throught devices pci mapping Yong Liu
2015-06-29  5:17 ` [dts] [PATCH 2/3] Optimize virtual machine port map routine Yong Liu
2015-06-29  5:17 ` [dts] [PATCH 3/3] Refresh default VM configurations after setting VM name Yong Liu

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).