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