From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by dpdk.org (Postfix) with ESMTP id 6C394C4C2 for ; Mon, 29 Jun 2015 07:17:26 +0200 (CEST) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga103.jf.intel.com with ESMTP; 28 Jun 2015 22:17:25 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.13,696,1427785200"; d="scan'208";a="736631101" Received: from shvmail01.sh.intel.com ([10.239.29.42]) by fmsmga001.fm.intel.com with ESMTP; 28 Jun 2015 22:17:23 -0700 Received: from shecgisg003.sh.intel.com (shecgisg003.sh.intel.com [10.239.29.90]) by shvmail01.sh.intel.com with ESMTP id t5T5HL4f019678; Mon, 29 Jun 2015 13:17:21 +0800 Received: from shecgisg003.sh.intel.com (localhost [127.0.0.1]) by shecgisg003.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id t5T5HJNI028398; Mon, 29 Jun 2015 13:17:21 +0800 Received: (from yliu84x@localhost) by shecgisg003.sh.intel.com (8.13.6/8.13.6/Submit) id t5T5HIxN028394; Mon, 29 Jun 2015 13:17:18 +0800 From: Yong Liu To: dts@dpdk.org Date: Mon, 29 Jun 2015 13:17:13 +0800 Message-Id: <1435555035-28355-2-git-send-email-yong.liu@intel.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1435555035-28355-1-git-send-email-yong.liu@intel.com> References: <1435555035-28355-1-git-send-email-yong.liu@intel.com> Subject: [dts] [PATCH 1/3] Add new API for get host and VM pass-throught devices pci mapping X-BeenThere: dts@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: test suite reviews and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 29 Jun 2015 05:17:27 -0000 From: Marvin Liu 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 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