From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 95226A3160 for ; Thu, 10 Oct 2019 10:04:06 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 6BA591C211; Thu, 10 Oct 2019 10:04:06 +0200 (CEST) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 20A371C1D3 for ; Thu, 10 Oct 2019 10:04:03 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 10 Oct 2019 01:04:02 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.67,279,1566889200"; d="scan'208";a="393954758" Received: from fmsmsx107.amr.corp.intel.com ([10.18.124.205]) by fmsmga005.fm.intel.com with ESMTP; 10 Oct 2019 01:04:02 -0700 Received: from fmsmsx606.amr.corp.intel.com (10.18.126.86) by fmsmsx107.amr.corp.intel.com (10.18.124.205) with Microsoft SMTP Server (TLS) id 14.3.439.0; Thu, 10 Oct 2019 01:04:02 -0700 Received: from fmsmsx606.amr.corp.intel.com (10.18.126.86) by fmsmsx606.amr.corp.intel.com (10.18.126.86) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Thu, 10 Oct 2019 01:04:01 -0700 Received: from shsmsx103.ccr.corp.intel.com (10.239.4.69) by fmsmsx606.amr.corp.intel.com (10.18.126.86) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.1713.5 via Frontend Transport; Thu, 10 Oct 2019 01:04:01 -0700 Received: from shsmsx104.ccr.corp.intel.com ([169.254.5.166]) by SHSMSX103.ccr.corp.intel.com ([169.254.4.165]) with mapi id 14.03.0439.000; Thu, 10 Oct 2019 16:04:00 +0800 From: "Wang, Yinan" To: "Ma, LihongX" , "dts@dpdk.org" Thread-Topic: [dts][PATCH V1 3/3][migration] tests/vhost_user_live_migration: update code Thread-Index: AQHVfz6LhqsDOaueQkGEPi06IGaFPKdTg/Rw Date: Thu, 10 Oct 2019 08:03:59 +0000 Message-ID: References: <1570666746-12853-1-git-send-email-lihongx.ma@intel.com> <1570666746-12853-3-git-send-email-lihongx.ma@intel.com> In-Reply-To: <1570666746-12853-3-git-send-email-lihongx.ma@intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiMmM1YWI4MmMtODk3Ny00MDdjLThkZTQtNDZlMjgzOWEzNTEwIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoidTB5ZGJrNlo0a2VuZytcL1VUOE5LT2FKUllxaWFJdURcL3Y5OWZub1pUYU5lUjlYVUZUQ3F4QkdWWXlwdzFBblVkIn0= x-ctpclassification: CTP_NT dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-originating-ip: [10.239.127.40] Content-Type: text/plain; charset="iso-2022-jp" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dts] [PATCH V1 3/3][migration] tests/vhost_user_live_migration: update code 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: , Errors-To: dts-bounces@dpdk.org Sender: "dts" Acked-by: Wang, Yinan > -----Original Message----- > From: Ma, LihongX > Sent: 2019=1B$BG/=1B(B10=1B$B7n=1B(B10=1B$BF|=1B(B 8:19 > To: dts@dpdk.org > Cc: Wang, Yinan ; Ma, LihongX > Subject: [dts][PATCH V1 3/3][migration] tests/vhost_user_live_migration: = update > code >=20 > Signed-off-by: lihong > --- > tests/TestSuite_vhost_user_live_migration.py | 532 > +++++++++++++++++---------- > 1 file changed, 332 insertions(+), 200 deletions(-) >=20 > diff --git a/tests/TestSuite_vhost_user_live_migration.py > b/tests/TestSuite_vhost_user_live_migration.py > index 9bd3237..fa21b93 100644 > --- a/tests/TestSuite_vhost_user_live_migration.py > +++ b/tests/TestSuite_vhost_user_live_migration.py > @@ -1,10 +1,40 @@ > -# > +# BSD LICENSE > +# > +# Copyright(c) <2019> Intel Corporation. > +# All rights reserved. > +# > +# Redistribution and use in source and binary forms, with or without # > +modification, are permitted provided that the following conditions # > +are met: > +# > +# * Redistributions of source code must retain the above copyright > +# notice, this list of conditions and the following disclaimer. > +# * Redistributions in binary form must reproduce the above copyright > +# notice, this list of conditions and the following disclaimer in > +# the documentation and/or other materials provided with the > +# distribution. > +# * Neither the name of Intel Corporation nor the names of its > +# contributors may be used to endorse or promote products derived > +# from this software without specific prior written permission. > +# > +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > CONTRIBUTORS # > +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # > +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > # > +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT > # > +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > # > +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # > +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > # > +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON > ANY # > +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # > +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE > USE # > +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >=20 > import re > import time > - > -from qemu_kvm import QEMUKvm > +import utils > +from virt_common import VM > from test_case import TestCase > +from config import UserConf > from exception import VirtDutInitException >=20 >=20 > @@ -13,109 +43,174 @@ class TestVhostUserLiveMigration(TestCase): > def set_up_all(self): > # verify at least two duts > self.verify(len(self.duts) >=3D 2, "Insufficient duts for live m= igration!!!") > + self.host_dut =3D self.duts[0] > + self.backup_dut =3D self.duts[1] >=20 > # each dut required one ports > - self.dut_ports =3D self.dut.get_ports() > - # Verify that enough ports are available > - self.verify(len(self.dut_ports) >=3D 1, "Insufficient ports for = testing") > - self.dut_port =3D self.dut_ports[0] > - dut_ip =3D self.dut.crb['My IP'] > - self.host_tport =3D self.tester.get_local_port_bydut(self.dut_po= rt, > dut_ip) > - self.host_tintf =3D self.tester.get_interface(self.host_tport) > - > - self.backup_ports =3D self.duts[1].get_ports() > - # Verify that enough ports are available > - self.verify(len(self.backup_ports) >=3D 1, "Insufficient ports f= or testing") > - self.backup_port =3D self.backup_ports[0] > - # backup host ip will be used in migrate command > - self.backup_dutip =3D self.duts[1].crb['My IP'] > - self.backup_tport =3D self.tester.get_local_port_bydut(self.back= up_port, > self.backup_dutip) > - self.backup_tintf =3D self.tester.get_interface(self.backup_tpor= t) > - > - # Use testpmd as vhost-user application on host/backup server > - self.vhost =3D "./%s/app/testpmd" % self.target > - self.vm_testpmd =3D "./%s/app/testpmd -c 0x3 -n 4 -- -i" % self.= target > - self.virio_mac =3D "52:54:00:00:00:01" > + host_dut_ports =3D self.host_dut.get_ports() > + backup_dut_ports =3D self.backup_dut.get_ports() > + self.verify(len(host_dut_ports) >=3D 1 and len(backup_dut_ports)= >=3D 1, > + "Insufficient ports for testing") > + > + # get mount info from cfg file > + conf_info =3D UserConf('conf/%s.cfg' % self.suite_name) > + conf_session =3D conf_info.conf._sections['mount_info'] > + self.mount_path =3D conf_session['backup_mount_path'] > + self.share_path =3D conf_session['host_share_dir'] > + # config the mount server and client > + self.config_mount_server() > + self.config_mount_client() > + > + host_dut_port =3D host_dut_ports[0] > + host_dut_ip =3D self.host_dut.crb['My IP'] > + backup_dut_port =3D backup_dut_ports[0] > + self.backup_dut_ip =3D self.backup_dut.crb['My IP'] > + > + host_tport =3D self.tester.get_local_port_bydut(host_dut_port, > host_dut_ip) > + backup_tport =3D self.tester.get_local_port_bydut(backup_dut_por= t, > self.backup_dut_ip) > + self.host_tintf =3D self.tester.get_interface(host_tport) > + self.backup_tintf =3D self.tester.get_interface(backup_tport) > + > + self.host_mem_channels =3D self.host_dut.get_memory_channels() > + self.backup_mem_channels =3D > self.backup_dut.get_memory_channels() > + self.host_pci_info =3D self.host_dut.ports_info[0]['pci'] > + self.backup_pci_info =3D self.backup_dut.ports_info[0]['pci'] >=20 > - # flag for environment > - self.env_done =3D False > + self.virio_mac =3D "52:54:00:00:00:01" > + self.queue_number =3D 1 > + self.vm_dut_host =3D None > + self.backup_vm =3D None > + self.screen_name =3D 'migration' > + self.base_dir =3D self.dut.base_dir.replace('~', '/root') > + host_socket_num =3D len(set([int(core['socket']) for core in > self.host_dut.cores])) > + backup_socket_num =3D len(set([int(core['socket']) for core in > self.backup_dut.cores])) > + self.host_socket_mem =3D ','.join(['1024']*host_socket_num) > + self.backup_socket_mem =3D ','.join(['1024']*backup_socket_num) >=20 > def set_up(self): > - self.setup_vm_env() > - pass > - > - def bind_nic_driver(self, crb, ports, driver=3D""): > - # modprobe vfio driver > - if driver =3D=3D "vfio-pci": > - for port in ports: > - netdev =3D crb.ports_info[port]['port'] > - driver =3D netdev.get_nic_driver() > - if driver !=3D 'vfio-pci': > - netdev.bind_driver(driver=3D'vfio-pci') > - > - elif driver =3D=3D "igb_uio": > - # igb_uio should insmod as default, no need to check > - for port in ports: > - netdev =3D crb.ports_info[port]['port'] > - driver =3D netdev.get_nic_driver() > - if driver !=3D 'igb_uio': > - netdev.bind_driver(driver=3D'igb_uio') > - else: > - for port in ports: > - netdev =3D crb.ports_info[port]['port'] > - driver_now =3D netdev.get_nic_driver() > - if driver =3D=3D "": > - driver =3D netdev.default_driver > - if driver !=3D driver_now: > - netdev.bind_driver(driver=3Ddriver) > - > - def setup_vm_env(self, driver=3D'default'): > + self.host_dut.send_expect('rm ./vhost-net*', '# ', 30) > + self.backup_dut.send_expect('rm ./vhost-net*', '# ', 30) > + self.migration_done =3D False > + > + def config_mount_server(self): > + ''' > + get the mount server config from file /etc/exports > + if not config the mount info of host_dut and backup_dut, config = it > + ''' > + config =3D '%s %s(rw,sync,no_root_squash)' % ( > + self.share_path, self.backup_dut.crb['IP']) > + try: > + fd =3D open('/etc/exports', 'r+') > + except Exception as e: > + self.logger.error('read file /etc/exports failed as %s' % st= r(e)) > + raise e > + line =3D fd.readline() > + while(line): > + # already config in etc file > + if not line.startswith('#') and config in line: > + break > + line =3D fd.readline() > + # not config in etc file, wirte the config to it > + if not line: > + fd.write(config) > + fd.close() > + > + def config_mount_client(self): > + ''' > + config the mount client to access the mount server > + ''' > + out =3D self.backup_dut.send_expect('ls -d %s' % self.mount_path= , '# ') > + if 'No such file or directory' in out: > + self.backup_dut.send_expect('mkdir -p %s' % self.mount_path,= '# > ') > + config =3D 'mount -t nfs -o nolock,vers=3D4 %s:%s %s' % ( > + self.host_dut.crb['IP'], self.share_path, > self.mount_path) > + self.host_dut.send_expect('service nfs-server restart', '# ') > + self.backup_dut.send_expect('service nfs-server restart', '# ') > + self.backup_dut.send_expect('umount %s' % self.mount_path, '# ') > + self.backup_dut.send_expect(config, '# ') > + time.sleep(2) > + # verify the mount result > + out_host =3D self.host_dut.send_expect('ls %s' % self.share_path= , '#') > + out_backup =3D self.backup_dut.send_expect('ls %s' % self.mount_= path, > '#') > + self.verify(out_host =3D=3D out_backup, 'the mount action failed= , > + please confrim it') > + > + def get_core_list(self): > + core_number =3D self.queue_number + 1 > + core_config =3D '1S/%dC/1T' % core_number > + core_list0 =3D self.duts[0].get_core_list(core_config) > + core_list1 =3D self.duts[1].get_core_list(core_config) > + self.verify(len(core_list0) >=3D core_number and len(core_list1)= >=3D > core_number, > + 'There have not enough cores to start testpmd on dut= s') > + self.host_core_mask_user =3D utils.create_mask(core_list0) > + self.backup_core_mask_user =3D utils.create_mask(core_list1) > + > + def launch_testpmd_as_vhost_on_both_dut(self, zero_copy=3DFalse): > + """ > + start testpmd as vhost user on host_dut and backup_dut > + """ > + self.get_core_list() > + zero_copy_str =3D '' > + if zero_copy is True: > + zero_copy_str =3D ',dequeue-zero-copy=3D1' > + vdev_info =3D 'eth_vhost0,iface=3D%s/vhost-net,queues=3D%d%s' % = ( > + self.base_dir, self.queue_number, zero_copy_str) > + > + params_info =3D '--nb-cores=3D%d --rxq=3D%d --txq=3D%d' % ( > + self.queue_number, self.queue_number, > + self.queue_number) > + > + cmd_line =3D self.dut.target + '/app/testpmd -c %s -n %d -w %s '= + \ > + "--socket-mem %s --legacy-mem --file-prefix=3Dvhost --vd= ev > '%s' " + \ > + "-- -i %s" > + host_cmd_line =3D cmd_line % (self.host_core_mask_user, > self.host_mem_channels, > + self.host_pci_info, self.host_socket_mem, > + vdev_info, params_info) > + backup_cmd_line =3D cmd_line % (self.backup_core_mask_user, > self.backup_mem_channels, > + self.backup_pci_info, self.backup_socket_mem, > + vdev_info, params_info) > + > + self.host_dut.send_expect(host_cmd_line, 'testpmd> ', 30) > + self.backup_dut.send_expect(backup_cmd_line, 'testpmd> ', 30) > + > + def start_testpmd_with_fwd_mode_on_both_dut(self, fwd_mode=3D'io'): > + self.host_dut.send_expect('set fwd %s' % fwd_mode, 'testpmd> ', = 30) > + self.host_dut.send_expect('start', 'testpmd> ', 30) > + self.backup_dut.send_expect('set fwd %s' % fwd_mode, 'testpmd> '= , > 30) > + self.backup_dut.send_expect('start', 'testpmd> ', 30) > + > + def setup_vm_env_on_both_dut(self, driver=3D'default'): > """ > Create testing environment on Host and Backup > """ > - if self.env_done: > - return > - > - # start vhost application on host and backup machines > - self.logger.info("Start vhost on host and backup host") > - for crb in self.duts[:2]: > - self.bind_nic_driver(crb, [crb.get_ports()[0]], driver=3D"ig= b_uio") > - # start vhost app: testpmd, predict hugepage on both sockets > - base_dir =3D crb.base_dir.replace('~', '/root') > - crb.send_expect("rm -f %s/vhost-net" % base_dir, "# ") > - crb.send_expect("%s -c f -n 4 --socket-mem 512,512 --vdev > 'eth_vhost0,iface=3D./vhost-net,queues=3D1' -- -i" % self.vhost, "testpmd= > ",60) > - crb.send_expect("start", "testpmd> ") > - > try: > # set up host virtual machine > - self.host_vm =3D QEMUKvm(self.duts[0], 'host', > 'vhost_user_live_migration') > + self.host_vm =3D VM(self.duts[0], 'host', '%s' % > + self.suite_name) > vhost_params =3D {} > vhost_params['driver'] =3D 'vhost-user' > - # qemu command can't use ~ > - base_dir =3D self.dut.base_dir.replace('~', '/root') > - vhost_params['opt_path'] =3D base_dir + '/vhost-net' > + vhost_params['opt_path'] =3D self.base_dir + '/vhost-net' > vhost_params['opt_mac'] =3D self.virio_mac > + opt_params =3D 'mrg_rxbuf=3Don' > + if self.queue_number > 1: > + vhost_params['opt_queue'] =3D self.queue_number > + opt_params =3D 'mrg_rxbuf=3Don,mq=3Don,vectors=3D%d' % > (2*self.queue_number + 2) > + vhost_params['opt_settings'] =3D opt_params > self.host_vm.set_vm_device(**vhost_params) >=20 > self.logger.info("Start virtual machine on host") > - self.vm_host =3D self.host_vm.start() > + self.vm_dut_host =3D self.host_vm.start() >=20 > - if self.vm_host is None: > + if self.vm_dut_host is None: > raise Exception("Set up host VM ENV failed!") >=20 > - self.host_serial =3D > self.host_vm.connect_serial_port(name=3D'vhost_user_live_migration') > - if self.host_serial is None: > - raise Exception("Connect host serial port failed!") > - > self.logger.info("Start virtual machine on backup host") > # set up backup virtual machine > - self.backup_vm =3D QEMUKvm(self.duts[1], 'backup', > 'vhost_user_live_migration') > + self.backup_vm =3D VM(self.duts[1], 'backup', > + 'vhost_user_live_migration') > vhost_params =3D {} > vhost_params['driver'] =3D 'vhost-user' > - # qemu command can't use ~ > - base_dir =3D self.dut.base_dir.replace('~', '/root') > - vhost_params['opt_path'] =3D base_dir + '/vhost-net' > + vhost_params['opt_path'] =3D self.base_dir + '/vhost-net' > vhost_params['opt_mac'] =3D self.virio_mac > + if self.queue_number > 1: > + vhost_params['opt_queue'] =3D self.queue_number > + vhost_params['opt_settings'] =3D opt_params > self.backup_vm.set_vm_device(**vhost_params) >=20 > # start qemu command > @@ -132,90 +227,118 @@ class TestVhostUserLiveMigration(TestCase): > self.destroy_vm_env() > raise Exception(ex) >=20 > - self.env_done =3D True > - > def destroy_vm_env(self): > - # if environment has been destroyed, just skip > - if self.env_done is False: > - return > - > - if getattr(self, 'host_serial', None): > - if self.host_vm is not None: > - self.host_vm.close_serial_port() > - > - if getattr(self, 'backup_serial', None): > - if self.backup_serial is not None and self.backup_vm is not = None: > - self.backup_vm.close_serial_port() > - > - > - if getattr(self, 'vm_host', None): > - if self.vm_host is not None: > + self.logger.info("Stop virtual machine on host") > + try: > + if self.vm_dut_host is not None: > + if not self.migration_done: > + self.vm_dut_host.send_expect('pkill screen', '# ') > self.host_vm.stop() > self.host_vm =3D None > + except Exception as e: > + self.logger.error('stop the qemu host failed as %s' % > + str(e)) >=20 > self.logger.info("Stop virtual machine on backup host") > - if getattr(self, 'vm_backup', None): > - if self.vm_backup is not None: > - self.vm_backup.kill_all() > - # backup vm dut has been initialized, destroy backup vm > - self.backup_vm.stop() > - self.backup_vm =3D None > - > - if getattr(self, 'backup_vm', None): > - # only qemu start, no session created > + try: > if self.backup_vm is not None: > + if self.migration_done: > + self.vm_dut_backup.kill_all() > + self.vm_dut_backup.send_expect('pkill screen', '# > + ') > self.backup_vm.stop() > self.backup_vm =3D None > + except Exception as e: > + self.logger.error('stop the qemu backup failed as %s' % > + str(e)) >=20 > # after vm stopped, stop vhost testpmd > - for crb in self.duts[:2]: > + for crb in self.duts: > + crb.send_expect('quit', '# ') > crb.kill_all() >=20 > - for crb in self.duts[:2]: > - self.bind_nic_driver(crb, [crb.get_ports()[0]], driver=3D"ig= b_uio") > - > - self.env_done =3D False > - > - def send_pkts(self, intf, number=3D0): > + def bind_nic_driver_of_vm(self, crb, driver=3D""): > + # modprobe vfio driver > + ports =3D crb.get_ports() > + if driver =3D=3D "vfio-pci": > + crb.send_expect('modprobe vfio-pci', '# ') > + for port in ports: > + netdev =3D crb.ports_info[port]['port'] > + driver_now =3D netdev.get_nic_driver() > + if driver_now !=3D driver: > + netdev.bind_driver(driver) > + > + def send_pkts_in_bg(self): > """ > send packet from tester > """ > - sendp_fmt =3D "sendp([Ether(dst=3D'%(DMAC)s')/IP()/UDP()/Raw('x'= *18)], > iface=3D'%(INTF)s', count=3D%(COUNT)d)" > - sendp_cmd =3D sendp_fmt % {'DMAC': self.virio_mac, 'INTF': intf, > 'COUNT': number} > - self.tester.scapy_append(sendp_cmd) > - self.tester.scapy_execute() > - # sleep 10 seconds for heavy load with backup host > - time.sleep(10) > - > - def verify_dpdk(self, tester_port, serial_session): > - num_pkts =3D 10 > + sendp_fmt =3D "sendp([Ether(dst=3D'%s')/IP(src=3D'%s', > dst=3D'%s')/UDP(sport=3D11,dport=3D12)/('x'*18)], iface=3D'%s', loop=3D1,= inter=3D0.5)" > + sendp_cmd =3D sendp_fmt % (self.virio_mac, '1.1.1.1', '2.2.2.2', > self.host_tintf) > + self.send_pks_session =3D self.tester.create_session("scapy1") > + self.send_pks_session.send_expect("scapy", ">>>") > + self.send_pks_session.send_command(sendp_cmd) > + > + if self.host_tintf !=3D self.backup_tintf: > + sendp_cmd =3D sendp_fmt % {'DMAC': self.virio_mac, 'INTF': > self.backup_tintf} > + self.send_pks_session2 =3D self.tester.create_session("scapy= 2") > + self.send_pks_session2.send_expect("scapy", ">>>") > + self.send_pks_session2.send_command(sendp_cmd) > + > + def stop_send_pkts_on_tester(self): > + self.tester.send_expect('pkill scapy', '# ') > + if getattr(self, "scapy1", None): > + self.tester.destroy_session(self.send_pks_session) > + if getattr(self, "scapy2", None): > + self.tester.destroy_session(self.send_pks_session2) > + > + def start_testpmd_on_vm(self, vm_dut): > + vm_dut.send_expect('export TERM=3Dscreen', '# ') > + vm_dut.send_expect('screen -S %s' % self.screen_name, '# ', > + 120) > + > + vm_testpmd =3D self.target + '/app/testpmd -c 0x3 -n 4 -- -i' > + vm_dut.send_expect('cd %s' % self.base_dir, "# ") > + vm_dut.send_expect(vm_testpmd, 'testpmd> ', 120) > + vm_dut.send_expect('set fwd rxonly', 'testpmd> ', 30) > + vm_dut.send_expect('set promisc all off', 'testpmd> ', 30) > + vm_dut.send_expect('start', 'testpmd> ', 30) > + vm_dut.send_command('^a') > + vm_dut.send_command('^d') > + > + def verify_dpdk(self, vm_dut): > + vm_dut.send_expect('export TERM=3Dscreen', '# ') > + vm_dut.send_command('screen -r %s' % self.screen_name) >=20 > stats_pat =3D re.compile("RX-packets: (\d+)") > - intf =3D self.tester.get_interface(tester_port) > - serial_session.send_expect("stop", "testpmd> ") > - serial_session.send_expect("set fwd rxonly", "testpmd> ") > - serial_session.send_expect("clear port stats all", "testpmd> ") > - serial_session.send_expect("start tx_first", "testpmd> ") > - > - # send packets from tester > - self.send_pkts(intf, number=3Dnum_pkts) > - > - out =3D serial_session.send_expect("show port stats 0", "testpmd= > ") > + vm_dut.send_expect("clear port stats all", "testpmd> ") > + time.sleep(5) > + out =3D vm_dut.send_expect("show port stats 0", "testpmd> ") > + print out > m =3D stats_pat.search(out) > if m: > num_received =3D int(m.group(1)) > else: > num_received =3D 0 >=20 > - self.logger.info("Verified %s packets recevied" % num_received) > - self.verify(num_received >=3D num_pkts, "Not receive packets as > expected!!!") > + self.verify(num_received > 0, "Not receive packets as expected!!= !") > + vm_dut.send_command('^a') > + vm_dut.send_command('^d') >=20 > - def verify_kernel(self, tester_port, vm_dut): > + def verify_kernel(self, vm_dut): > """ > Function to verify packets received by virtIO > """ > - intf =3D self.tester.get_interface(tester_port) > - num_pkts =3D 10 > + vm_dut.send_expect('export TERM=3Dscreen', '# ') > + vm_dut.send_command('screen -r %s' % self.screen_name) > + # clean the output info before verify > + vm_dut.get_session_output(timeout=3D1) > + time.sleep(5) > + out =3D vm_dut.get_session_output(timeout=3D1) > + print out > + num =3D out.count('UDP') > + self.verify(num > 0, "Not receive packets as expected!!!") > + vm_dut.send_command('^a') > + vm_dut.send_command('^d') > + > + def start_tcpdump_on_vm(self, vm_dut): > + vm_dut.send_expect('export TERM=3Dscreen', '# ') > + vm_dut.send_expect('screen -S %s' % self.screen_name, '# ', > + 120) >=20 > # get host interface > vm_intf =3D vm_dut.ports_info[0]['port'].get_interface_name() > @@ -232,99 +355,108 @@ class TestVhostUserLiveMigration(TestCase): > direct_param =3D "" >=20 > vm_dut.send_expect("tcpdump -i %s %s -v" % (vm_intf, > direct_param), "listening on", 120) > - # wait for promisc on > - time.sleep(3) > + time.sleep(2) > + vm_dut.send_command('^a') > + vm_dut.send_command('^d') > + > + def send_and_verify(self, verify_fun, multi_queue=3DFalse): > + ''' > + start to send packets > + verify vm_host can recevied packets before migration > + verify vm_host can recevied packets during migration > + verify vm_backup can recevied packets after migration > + ''' > # send packets from tester > - self.send_pkts(intf, number=3Dnum_pkts) > + self.send_pkts_in_bg() >=20 > - # killall tcpdump and verify packet received > - out =3D vm_dut.get_session_output(timeout=3D1) > - vm_dut.send_expect("^C", "# ") > - num =3D out.count('UDP') > - self.logger.info("Verified %s packets recevied" % num_pkts) > - self.verify(num =3D=3D num_pkts, "Not receive packets as expecte= d!!!") > - > - def test_migrate_with_kernel(self): > - """ > - Verify migrate virtIO device from host to backup host, > - Verify before/in/after migration, device with kernel driver can = receive > packets > - """ > - # bind virtio-net back to virtio-pci > - self.bind_nic_driver(self.vm_host, [self.vm_host.get_ports()[0]]= , > driver=3D"") > # verify host virtio-net work fine > - self.verify_kernel(self.host_tport, self.vm_host) > + verify_fun(self.vm_dut_host) >=20 > self.logger.info("Migrate host VM to backup host") > # start live migration > - ret =3D self.host_vm.start_migration(self.backup_dutip, > self.backup_vm.migrate_port) > + ret =3D self.host_vm.start_migration(self.backup_dut_ip, > + self.backup_vm.migrate_port) > self.verify(ret, "Failed to migration, please check VM and qemu > version") >=20 > - # make sure still can receive packets in migration process > - self.verify_kernel(self.host_tport, self.vm_host) > + if multi_queue is True: > + vm_intf =3D > self.vm_dut_host.ports_info[0]['port'].get_interface_name() > + out =3D self.vm_dut_host.send_expect('ethtool -L %s combined= 4' % > vm_intf, '# ') > + self.verify('Error' not in out and 'Failed' not in out, > + 'ethtool set combined failed during migration') >=20 > self.logger.info("Waiting migration process done") > # wait live migration done > self.host_vm.wait_migration_done() > - > - # check vhost testpmd log after migration > - out =3D self.duts[0].get_session_output(timeout=3D1) > - self.verify("closed" in out, "Vhost Connection NOT closed on hos= t") > - out =3D self.duts[1].get_session_output(timeout=3D1) > - self.verify("established" in out, "Device not ready on backup ho= st") > + self.migration_done =3D True >=20 > self.logger.info("Migration process done, then go to backup VM") > # connected backup VM > - self.vm_backup =3D self.backup_vm.migrated_start() > + self.vm_dut_backup =3D > + self.backup_vm.migrated_start(set_target=3DFalse) >=20 > # make sure still can receive packets > - self.verify_kernel(self.backup_tport, self.vm_backup) > + verify_fun(self.vm_dut_backup) >=20 > - def test_migrate_with_dpdk(self): > - # bind virtio-net to igb_uio > - self.bind_nic_driver(self.vm_host, [self.vm_host.get_ports()[0]]= , > driver=3D"igb_uio") > + def test_migrate_with_virtio_net(self): > + """ > + Verify migrate virtIO device from host to backup host, > + Verify before/in/after migration, device with kernel driver can = receive > packets > + """ > + self.queue_number =3D 1 > + self.launch_testpmd_as_vhost_on_both_dut() > + self.start_testpmd_with_fwd_mode_on_both_dut() > + self.setup_vm_env_on_both_dut() >=20 > - # start testpmd on host vm > - base_dir =3D self.vm_host.base_dir.replace('~', '/root') > - self.host_serial.send_expect('cd %s' % base_dir, "# ") > - self.host_serial.send_expect(self.vm_testpmd, "testpmd> ", 120) > + # bind virtio-net back to virtio-pci > + self.bind_nic_driver_of_vm(self.vm_dut_host, driver=3D"") > + # start screen and tcpdump on vm > + self.start_tcpdump_on_vm(self.vm_dut_host) >=20 > - # verify testpmd receive packets > - self.verify_dpdk(self.host_tport, self.host_serial) > + self.send_and_verify(self.verify_kernel) >=20 > - self.logger.info("Migrate host VM to backup host") > - # start live migration > + def test_migrete_with_vritio_net_with_multi_queue(self): > + self.queue_number =3D 4 > + self.launch_testpmd_as_vhost_on_both_dut() > + self.start_testpmd_with_fwd_mode_on_both_dut() > + self.setup_vm_env_on_both_dut() >=20 > - ret =3D self.host_vm.start_migration(self.backup_dutip, > self.backup_vm.migrate_port) > - self.verify(ret, "Failed to migration, please check VM and qemu > version") > + # bind virtio-net back to virtio-pci > + self.bind_nic_driver_of_vm(self.vm_dut_host, driver=3D"") > + self.start_tcpdump_on_vm(self.vm_dut_host) >=20 > - # make sure still can receive packets in migration process > - self.verify_dpdk(self.host_tport, self.host_serial) > + self.send_and_verify(self.verify_kernel, True) >=20 > - self.logger.info("Waiting migration process done") > - # wait live migration done > - self.host_vm.wait_migration_done() > + def test_migrate_with_virtio_pmd(self): > + self.queue_number =3D 1 > + self.launch_testpmd_as_vhost_on_both_dut() > + self.start_testpmd_with_fwd_mode_on_both_dut() > + self.setup_vm_env_on_both_dut() >=20 > - # check vhost testpmd log after migration > - out =3D self.duts[0].get_session_output(timeout=3D1) > - self.verify("closed" in out, "Vhost Connection NOT closed on hos= t") > - out =3D self.duts[1].get_session_output(timeout=3D1) > - self.verify("established" in out, "Device not ready on backup ho= st") > + # bind virtio-net to igb_uio > + self.bind_nic_driver_of_vm(self.vm_dut_host, driver=3D"igb_uio") > + self.start_testpmd_on_vm(self.vm_dut_host) >=20 > - self.logger.info("Migration process done, then go to backup VM") > - time.sleep(5) > + self.send_and_verify(self.verify_dpdk) >=20 > - # make sure still can receive packets > - self.backup_serial =3D > self.backup_vm.connect_serial_port(name=3D'vhost_user_live_migration', > first=3DFalse) > - if self.backup_serial is None: > - raise Exception("Connect backup host serial port failed!") > + def test_migrate_with_zero_copy_virtio_pmd(self): > + self.queue_number =3D 1 > + zero_copy =3D True > + # start testpmd and qemu on dut > + # after qemu start ok, then send 'start' command to testpmd > + # if send 'start' command before start qemu, maybe qemu will sta= rt > failed > + self.launch_testpmd_as_vhost_on_both_dut(zero_copy) > + self.setup_vm_env_on_both_dut() > + self.start_testpmd_with_fwd_mode_on_both_dut() >=20 > - self.verify_dpdk(self.backup_tport, self.backup_serial) > + # bind virtio-net to igb_uio > + self.bind_nic_driver_of_vm(self.vm_dut_host, driver=3D"igb_uio") > + self.start_testpmd_on_vm(self.vm_dut_host) >=20 > - # quit testpmd > - self.backup_serial.send_expect("quit", "# ") > + self.send_and_verify(self.verify_dpdk) >=20 > def tear_down(self): > self.destroy_vm_env() > + # stop send packet on tester > + self.stop_send_pkts_on_tester() > + self.duts[0].send_expect('killall -s INT qemu-system-x86_64', '#= ') > + self.duts[1].send_expect('killall -s INT qemu-system-x86_64', > + '#') > pass >=20 > def tear_down_all(self): > -- > 2.7.4