def get_stats(self, portid): """ Get packets number from port statistic. @param: stop -- stop forward before get stats """ output = PmdOutput(self.dut) stats = output.get_pmd_stats(portid) return stats
class TestVF2VFBridge(TestCase): supported_vf_driver = ['pci-stub', 'vfio-pci'] def set_up_all(self): self.dut_ports = self.dut.get_ports(self.nic) self.verify(len(self.dut_ports) >= 1, "Insufficient ports") self.vm0 = None self.vm1 = None # set vf assign method and vf driver self.vf_driver = self.get_suite_cfg()['vf_driver'] if self.vf_driver is None: self.vf_driver = 'pci-stub' self.verify(self.vf_driver in self.supported_vf_driver, "Unspported vf driver") if self.vf_driver == 'pci-stub': self.vf_assign_method = 'pci-assign' else: self.vf_assign_method = 'vfio-pci' self.dut.send_expect('modprobe vfio-pci', '#') def set_up(self): self.set_up_vf_to_vf_env() def set_up_vf_to_vf_env(self, driver='default'): self.pf_port_for_vfs = self.dut_ports[0] self.dut.restore_interfaces() self.dut.generate_sriov_vfs_by_port( self.pf_port_for_vfs, VF_NUMS_ON_ONE_PF, driver=driver) self.sriov_vfs_ports = self.dut.ports_info[ self.pf_port_for_vfs]['vfs_port'] self.host_port_intf = self.dut.ports_info[self.pf_port_for_vfs]['intf'] for i in range(VF_NUMS_ON_ONE_PF): self.dut.send_expect('ip link set dev %s vf %d mac %s' % (self.host_port_intf, i, VF_TEMP_MAC % i), '#', 10) try: for port in self.sriov_vfs_ports: port.bind_driver(self.vf_driver) time.sleep(1) except Exception as e: raise Exception(e) vf0_prop = {'opt_host': self.sriov_vfs_ports[0].pci} vf1_prop = {'opt_host': self.sriov_vfs_ports[1].pci} time.sleep(1) self.vm0 = VM(self.dut, 'vm0', 'vf_to_vf_bridge') self.vm0.set_vm_device(driver=self.vf_assign_method, **vf0_prop) try: self.vm0_dut = self.vm0.start() if self.vm0_dut is None: raise Exception('Set up VM0 failed') except Exception as e: print utils.RED(str(e)) self.vm1 = VM(self.dut, 'vm1', 'vf_to_vf_bridge') self.vm1.set_vm_device(driver=self.vf_assign_method, **vf1_prop) try: self.vm1_dut = self.vm1.start() if self.vm1_dut is None: raise Exception('Set up VM1 failed') except Exception as e: print utils.RED(str(e)) def clear_vf_to_vf_env(self): if self.vm0 is not None: self.vm0.stop() self.vm0 = None if self.vm1 is not None: self.vm1.stop() self.vm1 = None self.dut.virt_exit() if self.pf_port_for_vfs is not None: self.dut.destroy_sriov_vfs_by_port(self.pf_port_for_vfs) port = self.dut.ports_info[self.pf_port_for_vfs]['port'] port.bind_driver() self.pf_port_for_vfs = 0 def generate_pcap_pkt(self, dst, src, load, pktname='flow.pcap'): """ dst: server: dst server object ether: dst mac ip: dst ip udp: dst udp protocol tcp: dst tcp protocal src: server: src server object ether: src mac ip: src ip udp: src udp protocol tcp: src tcp protocal load: content: pay load length: content length """ context = '[Ether(dst="%s", src="%s")/IP()/Raw(load=%s)]' % \ (str(dst['ether']), str(src['ether']), load['content']) src['server'].send_expect('scapy', '>>> ', 10) src['server'].send_expect( 'wrpcap("%s", %s)' % (pktname, context), '>>> ', 10) src['server'].send_expect('quit()', '#', 10) def prepare_pktgen(self, vm): vm.session.copy_file_to('./dep/tgen.tgz') vm.send_expect("cd /root", "#", 10) vm.send_expect("tar xvf tgen.tgz", '#', 20) def send_stream_pktgen(self, vm, pktname='flow.pcap'): vm.send_expect( "echo 2048 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages", "#", 10) vm.send_expect(" mount -t hugetlbfs nodedev /mnt/huge/", "#", 10) vm.send_expect( "./pktgen -c 0xf -n 2 --proc-type auto -- -P -T -m '1.0' -s 0:%s" % pktname, "", 100) time.sleep(60) vm.send_expect("set 0 rate 50", "", 20) time.sleep(5) vm.send_expect("set 0 count %d" % SEND_PACKET, "", 20) time.sleep(5) vm.send_expect("start all", "", 20) time.sleep(20) def stop_stream_pktgen(self, vm): vm.send_expect("stop all", "", 20) time.sleep(5) vm.send_expect("quit", "#", 20) def test_2vf_d2d_pktgen_stream(self): self.vm0_ports = self.vm0_dut.get_ports('any') self.vm0_pmd = PmdOutput(self.vm0_dut) self.vm0_pmd.start_testpmd('all') self.vm0_pmd.execute_cmd('set fwd rxonly') self.vm0_pmd.execute_cmd("set promisc all off") self.vm0_pmd.execute_cmd('start') self.vm1_ports = self.vm1_dut.get_ports('any') self.prepare_pktgen(self.vm1_dut) dst = {} dst['server'] = self.vm0_dut dst['ether'] = self.vm0_dut.ports_info[self.vm0_ports[0]]['mac'] src = {} src['server'] = self.vm1_dut src['ether'] = self.vm1_dut.ports_info[self.vm1_ports[0]]['mac'] load = {} load['content'] = "'X'*46" self.generate_pcap_pkt(dst, src, load) self.vm0_pmd.execute_cmd('clear port stats all') self.send_stream_pktgen(self.vm1_dut) recv_num = self.vm0_pmd.get_pmd_stats(0)['RX-packets'] time.sleep(1) self.stop_stream_pktgen(self.vm1_dut) self.vm0_pmd.execute_cmd('stop') self.vm0_pmd.execute_cmd('quit', '# ') self.verify(recv_num is SEND_PACKET, 'Rx port recv error: %d' % recv_num) def test_2vf_d2k_pktgen_stream(self): self.vm0_dut.restore_interfaces() self.vm0_ports = self.vm0_dut.get_ports('any') vf0_intf = self.vm0_dut.ports_info[self.vm0_ports[0]]['intf'] self.vm1_ports = self.vm1_dut.get_ports('any') self.prepare_pktgen(self.vm1_dut) dst = {} dst['server'] = self.vm0_dut dst['ether'] = self.vm0_dut.ports_info[self.vm0_ports[0]]['mac'] src = {} src['server'] = self.vm1_dut src['ether'] = self.vm1_dut.ports_info[self.vm1_ports[0]]['mac'] load = {} load['content'] = "'X'*46" self.generate_pcap_pkt(dst, src, load) self.vm0_dut.send_expect( 'tcpdump -i %s -s 1000 "ether src %s and ether dst %s"' % (vf0_intf, src['ether'], dst['ether']), 'tcpdump', 30) self.send_stream_pktgen(self.vm1_dut) self.stop_stream_pktgen(self.vm1_dut) recv_tcpdump = self.vm0_dut.send_expect('^C', '#', 30) time.sleep(5) recv_pattern = re.compile("(\d+) packets captured") recv_info = recv_pattern.search(recv_tcpdump) recv_str = recv_info.group(0).split(' ')[0] recv_number = int(recv_str, 10) self.vm0_dut.bind_interfaces_linux(self.drivername) self.verify(recv_number is SEND_PACKET, 'Rx port recv error: %d' % recv_number) def test_2vf_k2d_scapy_stream(self): self.vm0_ports = self.vm0_dut.get_ports('any') self.vm0_pmd = PmdOutput(self.vm0_dut) self.vm0_pmd.start_testpmd('all') self.vm1_ports = self.vm1_dut.get_ports('any') self.vm1_dut.restore_interfaces() vf1_intf = self.vm1_dut.ports_info[self.vm1_ports[0]]['intf'] dst_mac = self.vm0_dut.ports_info[self.vm0_ports[0]]['mac'] src_mac = self.vm1_dut.ports_info[self.vm1_ports[0]]['mac'] pkt_content = 'Ether(dst="%s", src="%s")/IP()/Raw(load="X"*46)' % \ (dst_mac, src_mac) self.vm1_dut.send_expect('scapy', '>>> ', 10) self.vm0_pmd.execute_cmd('set promisc all off') self.vm0_pmd.execute_cmd('set fwd rxonly') self.vm0_pmd.execute_cmd('set verbose 1') self.vm0_pmd.execute_cmd('start') self.vm1_dut.send_expect('sendp([%s], iface="%s", count=%d)' % (pkt_content, vf1_intf, SEND_PACKET), '>>> ', 30) out = self.vm0_dut.get_session_output(timeout=60) rx_packets = re.findall("src=%s - dst=%s" % (src_mac, dst_mac), out) recv_num = len(rx_packets) self.vm1_dut.send_expect('quit()', '# ', 10) self.vm1_dut.bind_interfaces_linux(self.drivername) self.vm0_pmd.execute_cmd('stop') self.vm0_pmd.execute_cmd('quit', '# ') self.verify(recv_num is SEND_PACKET, 'Rx port recv error: %d' % recv_num) def tear_down(self): self.clear_vf_to_vf_env() def tear_down_all(self): pass
class TestVfJumboFrame(TestCase): supported_vf_driver = ['pci-stub', 'vfio-pci'] def set_up_all(self): self.dut_ports = self.dut.get_ports(self.nic) self.verify(len(self.dut_ports) >= 1, "Insufficient ports") self.vm0 = None self.env_done = False self.port = self.dut_ports[0] self.vm_port = 0 cores = self.dut.get_core_list("1S/1C/1T") self.port_mask = utils.create_mask([self.port]) # set vf assign method and vf driver self.dut.send_expect('modprobe vfio-pci', '#') self.vf_driver = self.get_suite_cfg()['vf_driver'] if self.vf_driver is None: self.vf_driver = 'pci-stub' self.verify(self.vf_driver in self.supported_vf_driver, "Unspported vf driver") if self.vf_driver == 'pci-stub': self.vf_assign_method = 'pci-assign' else: self.vf_assign_method = 'vfio-pci' self.dut.send_expect('modprobe vfio-pci', '#') # enable tester mtu tester_port = self.tester.get_local_port(self.port) self.netobj = self.tester.ports_info[tester_port]['port'] self.netobj.enable_jumbo(framesize=ETHER_JUMBO_FRAME_MTU + 100) def set_up(self): self.setup_vm_env() def bind_nic_driver(self, ports, driver=""): # modprobe vfio driver if driver == "vfio-pci": for port in ports: netdev = self.dut.ports_info[port]['port'] driver = netdev.get_nic_driver() if driver != 'vfio-pci': netdev.bind_driver(driver='vfio-pci') elif driver == "igb_uio": # igb_uio should insmod as default, no need to check for port in ports: netdev = self.dut.ports_info[port]['port'] driver = netdev.get_nic_driver() if driver != 'igb_uio': netdev.bind_driver(driver='igb_uio') else: for port in ports: netdev = self.dut.ports_info[port]['port'] driver_now = netdev.get_nic_driver() if driver == None: driver = netdev.default_driver if driver != driver_now: netdev.bind_driver(driver=driver) def setup_vm_env(self, driver='default'): """ Create testing environment with 1VF generated from 1PF """ if self.env_done: return # bind to default driver self.bind_nic_driver(self.dut_ports[:1], driver="") self.used_dut_port = self.dut_ports[0] self.host_intf = self.dut.ports_info[self.used_dut_port]['intf'] tester_port = self.tester.get_local_port(self.used_dut_port) self.tester_intf = self.tester.get_interface(tester_port) self.dut.generate_sriov_vfs_by_port(self.used_dut_port, 1, driver=driver) self.sriov_vfs_port = self.dut.ports_info[ self.used_dut_port]['vfs_port'] self.vf_mac = "00:10:00:00:00:00" self.dut.send_expect( "ip link set %s vf 0 mac %s" % (self.host_intf, self.vf_mac), "# ") try: for port in self.sriov_vfs_port: port.bind_driver(self.vf_driver) time.sleep(1) vf_popt = {'opt_host': self.sriov_vfs_port[0].pci} # set up VM ENV self.vm = QEMUKvm(self.dut, 'vm0', 'vf_jumboframe') self.vm.set_vm_device(driver=self.vf_assign_method, **vf_popt) self.vm_dut = self.vm.start() if self.vm_dut is None: raise Exception("Set up VM ENV failed!") TESTPMD_MAIN = "app/test-pmd/testpmd.c" if self.kdriver == "ixgbe": self.vm_dut.send_expect( "sed -i -e 's/.jumbo_frame = .*$/.jumbo_frame = 1,/g' %s" % TESTPMD_MAIN, "# ") self.vm_dut.build_install_dpdk(self.target) self.vm_testpmd = PmdOutput(self.vm_dut) except Exception as e: self.destroy_vm_env() raise Exception(e) self.env_done = True def destroy_vm_env(self): if getattr(self, 'vm', None): if getattr(self, 'vm_dut', None): self.vm_dut.kill_all() self.vm_testpmd = None self.vm_dut_ports = None # destroy vm0 self.vm.stop() self.dut.virt_exit() time.sleep(3) self.vm = None if getattr(self, 'used_dut_port', None) != None: self.dut.destroy_sriov_vfs_by_port(self.used_dut_port) self.used_dut_port = None self.bind_nic_driver(self.dut_ports[:1], driver='default') self.env_done = False def jumboframes_get_stat(self, portid, rx_tx): """ Get packets number from port statistic """ stats = self.vm_testpmd.get_pmd_stats(portid) if rx_tx == "rx": return [stats['RX-packets'], stats['RX-errors'], stats['RX-bytes']] elif rx_tx == "tx": return [stats['TX-packets'], stats['TX-errors'], stats['TX-bytes']] else: return None def jumboframes_send_packet(self, pktsize, received=True): """ Send 1 packet to portid """ tx_pkts_ori, _, tx_bytes_ori = [ int(_) for _ in self.jumboframes_get_stat(self.vm_port, "tx") ] rx_pkts_ori, rx_err_ori, rx_bytes_ori = [ int(_) for _ in self.jumboframes_get_stat(self.vm_port, "rx") ] mac = self.vm_dut.get_mac_address(self.vm_port) pkt = Packet(pkt_type='UDP', pkt_len=pktsize) pkt.config_layer('ether', {'dst': mac}) pkt.send_pkt(tx_port=self.tester_intf) time.sleep(1) tx_pkts, _, tx_bytes = [ int(_) for _ in self.jumboframes_get_stat(self.port, "tx") ] rx_pkts, rx_err, rx_bytes = [ int(_) for _ in self.jumboframes_get_stat(self.vm_port, "rx") ] tx_pkts -= tx_pkts_ori tx_bytes -= tx_bytes_ori rx_pkts -= rx_pkts_ori rx_bytes -= rx_bytes_ori rx_err -= rx_err_ori if received: self.verify((rx_pkts == 1) and (tx_pkts == 1), "Packet forward assert error") if self.kdriver == "ixgbe": self.verify((rx_bytes + 4) == pktsize, "Rx packet size should be packet size - 4") else: self.verify(rx_bytes == pktsize, "Tx packet size should be equal to packet size") if self.kdriver == "igb": self.verify(tx_bytes == pktsize, "Tx packet size should be packet size") else: self.verify((tx_bytes + 4) == pktsize, "Tx packet size should be packet size - 4") else: self.verify(rx_err == 1 or tx_pkts == 0, "Packet drop assert error") def test_vf_normal_nojumbo(self): """ This case aims to test transmitting normal size packet without jumbo enable """ # should enable jumbo on host self.dutobj = self.dut.ports_info[self.port]['port'] self.dutobj.enable_jumbo(framesize=ETHER_STANDARD_MTU) self.vm_testpmd.start_testpmd( "Default", "--max-pkt-len=%d --port-topology=loop --txqflags=0x0" % (ETHER_STANDARD_MTU)) self.vm_testpmd.execute_cmd("set fwd mac") self.vm_testpmd.execute_cmd("start") self.jumboframes_send_packet(ETHER_STANDARD_MTU - 1) self.jumboframes_send_packet(ETHER_STANDARD_MTU) self.vm_testpmd.execute_cmd("stop") self.vm_testpmd.quit() def test_vf_normal_withjumbo(self): """ When jumbo frame supported, this case is to verify that the normal size packet forwrding should be support correct. """ # should enable jumbo on host self.dutobj = self.dut.ports_info[self.port]['port'] self.dutobj.enable_jumbo(framesize=ETHER_JUMBO_FRAME_MTU) self.vm_testpmd.start_testpmd( "Default", "--max-pkt-len=%d --port-topology=loop --txqflags=0x0" % (ETHER_JUMBO_FRAME_MTU)) self.vm_testpmd.execute_cmd("set fwd mac") self.vm_testpmd.execute_cmd("start") self.jumboframes_send_packet(ETHER_STANDARD_MTU - 1) self.jumboframes_send_packet(ETHER_STANDARD_MTU) self.vm_testpmd.execute_cmd("stop") self.vm_testpmd.quit() def test_vf_jumbo_nojumbo(self): """ This case aims to test transmitting jumbo frame packet on testpmd without jumbo frame support. """ # should enable jumbo on host self.dutobj = self.dut.ports_info[self.port]['port'] self.dutobj.enable_jumbo(framesize=ETHER_STANDARD_MTU) self.vm_testpmd.start_testpmd("Default", "--port-topology=loop --txqflags=0x0") self.vm_testpmd.execute_cmd("set fwd mac") self.vm_testpmd.execute_cmd("start") # On igb, for example i350, refer to :DPDK-1117 # For PF, the max-pkt-len = mtu + 18 + 4(VLAN header len). # For VF, the real max-pkt-len = the given max-pkt-len + 4(VLAN header len). # This behavior is levelraged from kernel driver. # And it means max-pkt-len is always 4 bytes longer than assumed. if self.kdriver == "igb": self.jumboframes_send_packet(ETHER_STANDARD_MTU + 1 + 4, False) else: self.jumboframes_send_packet(ETHER_STANDARD_MTU + 1, False) self.vm_testpmd.execute_cmd("stop") self.vm_testpmd.quit() def test_vf_jumbo_withjumbo(self): """ When jumbo frame supported, this case is to verify that jumbo frame packet can be forwarded correct. """ # should enable jumbo on host self.dutobj = self.dut.ports_info[self.port]['port'] self.dutobj.enable_jumbo(framesize=ETHER_JUMBO_FRAME_MTU) self.vm_testpmd.start_testpmd( "Default", "--max-pkt-len=%d --port-topology=loop --txqflags=0x0" % (ETHER_JUMBO_FRAME_MTU)) self.vm_testpmd.execute_cmd("set fwd mac") self.vm_testpmd.execute_cmd("start") self.jumboframes_send_packet(ETHER_STANDARD_MTU + 1) self.jumboframes_send_packet(ETHER_JUMBO_FRAME_MTU - 1) self.jumboframes_send_packet(ETHER_JUMBO_FRAME_MTU) self.vm_testpmd.execute_cmd("stop") self.vm_testpmd.quit() def test_vf_jumbo_overjumbo(self): """ When the jubmo frame MTU set as 9000, this case is to verify that the packet which the length bigger than MTU can not be forwarded. """ # should enable jumbo on host self.dutobj = self.dut.ports_info[self.port]['port'] self.dutobj.enable_jumbo(framesize=ETHER_JUMBO_FRAME_MTU) self.vm_testpmd.start_testpmd( "Default", "--max-pkt-len=%d --port-topology=loop --txqflags=0x0" % (ETHER_JUMBO_FRAME_MTU)) self.vm_testpmd.execute_cmd("set fwd mac") self.vm_testpmd.execute_cmd("start") # On 1G NICs, when the jubmo frame MTU set as 9000, the software adjust it to 9004. if self.kdriver == "igb": self.jumboframes_send_packet(ETHER_JUMBO_FRAME_MTU + 4 + 1, False) else: self.jumboframes_send_packet(ETHER_JUMBO_FRAME_MTU + 1, False) self.vm_testpmd.execute_cmd("stop") self.vm_testpmd.quit() def tear_down(self): """ Run after each test case. """ self.destroy_vm_env() def tear_down_all(self): """ When the case of this test suite finished, the enviroment should clear up. """ self.destroy_vm_env() self.netobj.enable_jumbo(framesize=ETHER_STANDARD_MTU)
class TestVfPacketRxtx(TestCase): supported_vf_driver = ['pci-stub', 'vfio-pci'] def set_up_all(self): self.dut_ports = self.dut.get_ports(self.nic) self.verify(len(self.dut_ports) > 1, "Insufficient ports") self.vm0 = None self.vm1 = None # set vf assign method and vf driver self.vf_driver = self.get_suite_cfg()['vf_driver'] if self.vf_driver is None: self.vf_driver = 'pci-stub' self.verify(self.vf_driver in self.supported_vf_driver, "Unspported vf driver") if self.vf_driver == 'pci-stub': self.vf_assign_method = 'pci-assign' else: self.vf_assign_method = 'vfio-pci' self.tester.send_expect('modprobe vfio-pci', '#') def set_up(self): self.setup_2pf_2vf_1vm_env_flag = 0 self.setup_3vf_2vm_env_flag = 0 def setup_2pf_2vf_1vm_env(self, driver='default'): self.used_dut_port_0 = self.dut_ports[0] self.dut.generate_sriov_vfs_by_port(self.used_dut_port_0, 1, driver=driver) self.sriov_vfs_port_0 = self.dut.ports_info[ self.used_dut_port_0]['vfs_port'] self.used_dut_port_1 = self.dut_ports[1] self.dut.generate_sriov_vfs_by_port(self.used_dut_port_1, 1, driver=driver) self.sriov_vfs_port_1 = self.dut.ports_info[ self.used_dut_port_1]['vfs_port'] try: for port in self.sriov_vfs_port_0: port.bind_driver(self.vf_driver) for port in self.sriov_vfs_port_1: port.bind_driver(self.vf_driver) time.sleep(1) vf0_prop = {'opt_host': self.sriov_vfs_port_0[0].pci} vf1_prop = {'opt_host': self.sriov_vfs_port_1[0].pci} if driver == 'igb_uio': # start testpmd without the two VFs on the host self.host_testpmd = PmdOutput(self.dut) eal_param = '-b %(vf0)s -b %(vf1)s' % { 'vf0': self.sriov_vfs_port_0[0].pci, 'vf1': self.sriov_vfs_port_1[0].pci } if (self.nic in ["niantic", "sageville", "sagepond"]): self.host_testpmd.start_testpmd("1S/9C/1T", "--txq=4 --rxq=4 ", eal_param=eal_param) else: self.host_testpmd.start_testpmd("1S/5C/1T", "", eal_param=eal_param) # set up VM0 ENV self.vm0 = QEMUKvm(self.dut, 'vm0', 'vf_packet_rxtx') self.vm0.set_vm_device(driver=self.vf_assign_method, **vf0_prop) self.vm0.set_vm_device(driver=self.vf_assign_method, **vf1_prop) self.vm_dut_0 = self.vm0.start() if self.vm_dut_0 is None: raise Exception("Set up VM0 ENV failed!") self.setup_2pf_2vf_1vm_env_flag = 1 except Exception as e: self.destroy_2pf_2vf_1vm_env() raise Exception(e) def destroy_2pf_2vf_1vm_env(self): if getattr(self, 'vm0', None): #destroy testpmd in vm0 if getattr(self, 'vm0_testpmd', None): self.vm0_testpmd.execute_cmd('stop') self.vm0_testpmd.execute_cmd('quit', '# ') self.vm0_testpmd = None self.vm0_dut_ports = None #destroy vm0 self.vm0.stop() self.vm0 = None if getattr(self, 'host_testpmd', None): self.host_testpmd.execute_cmd('quit', '# ') self.host_testpmd = None self.dut.virt_exit() if getattr(self, 'used_dut_port_0', None) != None: self.dut.destroy_sriov_vfs_by_port(self.used_dut_port_0) port = self.dut.ports_info[self.used_dut_port_0]['port'] port.bind_driver() self.used_dut_port_0 = None if getattr(self, 'used_dut_port_1', None) != None: self.dut.destroy_sriov_vfs_by_port(self.used_dut_port_1) port = self.dut.ports_info[self.used_dut_port_1]['port'] port.bind_driver() self.used_dut_port_1 = None for port_id in self.dut_ports: port = self.dut.ports_info[port_id]['port'] port.bind_driver() self.setup_2pf_2vf_1vm_env_flag = 0 def packet_rx_tx(self, driver='default'): if driver == 'igb_uio': self.setup_2pf_2vf_1vm_env(driver='igb_uio') else: self.setup_2pf_2vf_1vm_env(driver='') self.vm0_dut_ports = self.vm_dut_0.get_ports('any') port_id_0 = 0 self.vm0_testpmd = PmdOutput(self.vm_dut_0) out = self.vm0_testpmd.start_testpmd(VM_CORES_MASK) pmd_vf0_mac = self.vm0_testpmd.get_port_mac(port_id_0) self.vm0_testpmd.execute_cmd('set fwd mac') self.vm0_testpmd.execute_cmd('start') time.sleep(2) tgen_ports = [] tx_port = self.tester.get_local_port(self.dut_ports[0]) rx_port = self.tester.get_local_port(self.dut_ports[1]) tgen_ports.append((tx_port, rx_port)) dst_mac = pmd_vf0_mac src_mac = self.tester.get_mac(tx_port) pkt_param = [("ether", {'dst': dst_mac, 'src': src_mac})] result = self.tester.check_random_pkts(tgen_ports, allow_miss=False, params=pkt_param) print self.vm0_testpmd.execute_cmd('show port stats all') self.verify(result != False, "VF0 failed to forward packets to VF1") ######1. test case for kernel pf and dpdk vf 2pf_2vf_1vm scenario packet rx tx. def test_kernel_2pf_2vf_1vm(self): self.packet_rx_tx(driver='') ######2. test case for dpdk pf and dpdk vf 2pf_2vf_1vm scenario packet rx tx. def test_dpdk_2pf_2vf_1vm(self): self.packet_rx_tx(driver='igb_uio') def setup_3vf_2vm_env(self, driver='default'): self.used_dut_port = self.dut_ports[0] self.dut.generate_sriov_vfs_by_port(self.used_dut_port, 3, driver=driver) self.sriov_vfs_port = self.dut.ports_info[ self.used_dut_port]['vfs_port'] try: for port in self.sriov_vfs_port: print port.pci port.bind_driver(self.vf_driver) time.sleep(1) vf0_prop = {'opt_host': self.sriov_vfs_port[0].pci} vf1_prop = {'opt_host': self.sriov_vfs_port[1].pci} vf2_prop = {'opt_host': self.sriov_vfs_port[2].pci} for port_id in self.dut_ports: if port_id == self.used_dut_port: continue port = self.dut.ports_info[port_id]['port'] port.bind_driver() if driver == 'igb_uio': self.host_testpmd = PmdOutput(self.dut) eal_param = '-b %(vf0)s -b %(vf1)s -b %(vf2)s' % { 'vf0': self.sriov_vfs_port[0].pci, 'vf1': self.sriov_vfs_port[1].pci, 'vf2': self.sriov_vfs_port[2].pci } self.host_testpmd.start_testpmd("1S/2C/2T", eal_param=eal_param) # set up VM0 ENV self.vm0 = QEMUKvm(self.dut, 'vm0', 'vf_packet_rxtx') self.vm0.set_vm_device(driver=self.vf_assign_method, **vf0_prop) self.vm0.set_vm_device(driver=self.vf_assign_method, **vf1_prop) self.vm_dut_0 = self.vm0.start() if self.vm_dut_0 is None: raise Exception("Set up VM0 ENV failed!") # set up VM1 ENV self.vm1 = QEMUKvm(self.dut, 'vm1', 'vf_packet_rxtx') self.vm1.set_vm_device(driver=self.vf_assign_method, **vf2_prop) self.vm_dut_1 = self.vm1.start() if self.vm_dut_1 is None: raise Exception("Set up VM1 ENV failed!") self.setup_3vf_2vm_env_flag = 1 except Exception as e: self.destroy_3vf_2vm_env() raise Exception(e) def destroy_3vf_2vm_env(self): if getattr(self, 'vm0', None): if getattr(self, 'vm0_testpmd', None): self.vm0_testpmd.execute_cmd('stop') self.vm0_testpmd.execute_cmd('quit', '# ') self.vm0_testpmd = None self.vm0_dut_ports = None self.vm_dut_0 = None self.vm0.stop() self.vm0 = None if getattr(self, 'vm1', None): if getattr(self, 'vm1_testpmd', None): self.vm1_testpmd.execute_cmd('stop') self.vm1_testpmd.execute_cmd('quit', '# ') self.vm1_testpmd = None self.vm1_dut_ports = None self.vm_dut_1 = None self.vm1.stop() self.vm1 = None self.dut.virt_exit() if getattr(self, 'host_testpmd', None) != None: self.host_testpmd.execute_cmd('quit', '# ') self.host_testpmd = None if getattr(self, 'used_dut_port', None) != None: self.dut.destroy_sriov_vfs_by_port(self.used_dut_port) port = self.dut.ports_info[self.used_dut_port]['port'] port.bind_driver() self.used_dut_port = None for port_id in self.dut_ports: port = self.dut.ports_info[port_id]['port'] port.bind_driver() self.setup_3vf_2vm_env_flag = 0 def test_vf_reset(self): self.setup_3vf_2vm_env(driver='') self.vm0_dut_ports = self.vm_dut_0.get_ports('any') self.vm1_dut_ports = self.vm_dut_1.get_ports('any') port_id_0 = 0 port_id_1 = 1 self.vm0_testpmd = PmdOutput(self.vm_dut_0) self.vm0_testpmd.start_testpmd(VM_CORES_MASK) self.vm0_testpmd.execute_cmd('show port info all') pmd0_vf0_mac = self.vm0_testpmd.get_port_mac(port_id_0) self.vm0_testpmd.execute_cmd('set fwd mac') self.vm0_testpmd.execute_cmd('start') time.sleep(2) self.vm1_testpmd = PmdOutput(self.vm_dut_1) self.vm1_testpmd.start_testpmd(VM_CORES_MASK) self.vm1_testpmd.execute_cmd('show port info all') tx_port = self.tester.get_local_port(self.dut_ports[0]) rx_port = tx_port dst_mac = pmd0_vf0_mac self.tester.sendpkt_bg(tx_port, dst_mac) #vf port stop/start can trigger reset action for num in range(1000): self.vm1_testpmd.execute_cmd('port stop all') time.sleep(0.1) self.vm1_testpmd.execute_cmd('port start all') time.sleep(0.1) self.tester.stop_sendpkt_bg() pmd0_vf0_stats = self.vm0_testpmd.get_pmd_stats(port_id_0) pmd0_vf1_stats = self.vm0_testpmd.get_pmd_stats(port_id_1) vf0_rx_cnt = pmd0_vf0_stats['RX-packets'] self.verify(vf0_rx_cnt != 0, "no packet was received by vm0_VF0") vf0_rx_err = pmd0_vf0_stats['RX-errors'] self.verify(vf0_rx_err == 0, "vm0_VF0 rx-errors") vf1_tx_cnt = pmd0_vf1_stats['TX-packets'] self.verify(vf1_tx_cnt != 0, "no packet was transmitted by vm0_VF1") vf1_tx_err = pmd0_vf1_stats['TX-errors'] self.verify(vf1_tx_err == 0, "vm0_VF0 tx-errors") self.verify( vf0_rx_cnt == vf1_tx_cnt, "vm0_VF0 failed to forward packets to vm0_VF1 when reset vm1_VF0 frequently" ) def tear_down(self): if self.setup_2pf_2vf_1vm_env_flag == 1: self.destroy_2pf_2vf_1vm_env() if self.setup_3vf_2vm_env_flag == 1: self.destroy_3vf_2vm_env() if getattr(self, 'vm0', None): self.vm0.stop() if getattr(self, 'vm1', None): self.vm1.stop() self.dut.virt_exit() for port_id in self.dut_ports: self.dut.destroy_sriov_vfs_by_port(port_id) # DPDK-1754 intf = self.dut.ports_info[port_id]['intf'] self.dut.send_expect("ethtool -s %s autoneg on" % intf, "# ") def tear_down_all(self): pass
class TestPmd(TestCase, IxiaPacketGenerator): def set_up_all(self): """ Run at the start of each test suite. PMD prerequisites. """ self.tester.extend_external_packet_generator(TestPmd, self) self.frame_sizes = [64, 72, 128, 256, 512, 1024, 1280, 1518] self.rxfreet_values = [0, 8, 16, 32, 64, 128] self.test_cycles = [{'cores': '1S/2C/1T', 'Mpps': {}, 'pct': {}}] self.table_header = ['Frame Size'] for test_cycle in self.test_cycles: self.table_header.append("%s Mpps" % test_cycle['cores']) self.table_header.append("% linerate") self.perf_results = {'header': [], 'data': []} self.blacklist = "" # Update config file and rebuild to get best perf on FVL self.dut.send_expect( "sed -i -e 's/CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=n/CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=y/' ./config/common_base", "#", 20) self.dut.build_install_dpdk(self.target) # Based on h/w type, choose how many ports to use self.dut_ports = self.dut.get_ports() if self.dut.get_os_type() == 'linux': # Get dut system information port_num = self.dut_ports[0] pci_device_id = self.dut.ports_info[port_num]['pci'] ori_driver = self.dut.ports_info[port_num]['port'].get_nic_driver() self.dut.ports_info[port_num]['port'].bind_driver() sut = SystemInfo(self.dut, pci_device_id) self.system_info = sut.get_system_info() self.nic_info = sut.get_nic_info() self.dut.ports_info[port_num]['port'].bind_driver(ori_driver) ###### self.headers_size = HEADER_SIZE['eth'] + HEADER_SIZE[ 'ip'] + HEADER_SIZE['tcp'] self.ports_socket = self.dut.get_numa_id(self.dut_ports[0]) self.pmdout = PmdOutput(self.dut) def set_up(self): """ Run before each test case. """ pass def test_perf_single_core_performance(self): """ Run single core performance """ self.perf_results['header'] = [] self.perf_results['data'] = [] if len(self.dut_ports) >= 4: self.pmd_performance_4ports() else: self.verify( len(self.dut_ports) >= 2, "Insufficient ports for 2 ports performance test") self.pmd_performance_2ports() #To replace False to True for if condition to send the result by email. if False: #it need place dpdk source git repo under dep directory. repo_dir = FOLDERS["Depends"] + r'/dpdk' git_info = perf_report.get_dpdk_git_info(repo_dir) self.verify(git_info is not None, "get dpdk git repo error") tpl_path = FOLDERS["NicDriver"] + r'/perf_report.jinja' file_tpl = os.path.abspath(tpl_path) html_msg = perf_report.generate_html_report(file_tpl, \ perf_data = self.perf_results['data'], \ git_info = git_info, \ nic_info = self.nic_info, \ system_info = self.system_info) self.verify(html_msg is not None, "generate html report error") subject = "Single core performance test with %d ports %s -- %s" % \ (len(self.dut_ports), self.nic, datetime.now().strftime('%Y-%m-%d %H:%M')) sender = '*****@*****.**' mailto = ['*****@*****.**'] smtp_server = 'smtp.intel.com' perf_report.send_html_report(sender, mailto, subject, html_msg, smtp_server) def pmd_performance_4ports(self): """ PMD Performance Benchmarking with 4 ports. """ all_cores_mask = utils.create_mask(self.dut.get_core_list("all")) # prepare traffic generator input tgen_input = [] tgen_input.append( (self.tester.get_local_port(self.dut_ports[0]), self.tester.get_local_port(self.dut_ports[1]), "test.pcap")) tgen_input.append( (self.tester.get_local_port(self.dut_ports[2]), self.tester.get_local_port(self.dut_ports[3]), "test.pcap")) tgen_input.append( (self.tester.get_local_port(self.dut_ports[1]), self.tester.get_local_port(self.dut_ports[0]), "test.pcap")) tgen_input.append( (self.tester.get_local_port(self.dut_ports[3]), self.tester.get_local_port(self.dut_ports[2]), "test.pcap")) # run testpmd for each core config for test_cycle in self.test_cycles: core_config = test_cycle['cores'] core_list = self.dut.get_core_list(core_config, socket=self.ports_socket) if len(core_list) > 4: queues = len(core_list) / 4 else: queues = 1 core_mask = utils.create_mask(core_list) port_mask = utils.create_mask(self.dut.get_ports()) self.pmdout.start_testpmd( core_config, " --rxq=%d --txq=%d --portmask=%s --rss-ip --txrst=32 --txfreet=32 --txd=128 --tx-offloads=0" % (queues, queues, port_mask), socket=self.ports_socket) command_line = self.pmdout.get_pmd_cmd() info = "Executing PMD using %s\n" % test_cycle['cores'] self.rst_report(info, annex=True) self.logger.info(info) self.rst_report(command_line + "\n\n", frame=True, annex=True) # self.dut.send_expect("set fwd mac", "testpmd> ", 100) self.dut.send_expect("start", "testpmd> ", 100) for frame_size in self.frame_sizes: wirespeed = self.wirespeed(self.nic, frame_size, 4) # create pcap file self.logger.info("Running with frame size %d " % frame_size) payload_size = frame_size - self.headers_size self.tester.scapy_append( 'wrpcap("test.pcap", [Ether(src="52:00:00:00:00:00")/IP(src="1.2.3.4",dst="1.1.1.1")/TCP()/("X"*%d)])' % payload_size) self.tester.scapy_execute() # run traffic generator _, pps = self.tester.traffic_generator_throughput( tgen_input, rate_percent=100, delay=60) pps /= 1000000.0 pct = pps * 100 / wirespeed test_cycle['Mpps'][frame_size] = float('%.3f' % pps) test_cycle['pct'][frame_size] = float('%.3f' % pct) self.dut.send_expect("stop", "testpmd> ") self.dut.send_expect("quit", "# ", 30) sleep(5) for n in range(len(self.test_cycles)): for frame_size in self.frame_sizes: self.verify(self.test_cycles[n]['Mpps'][frame_size] is not 0, "No traffic detected") # Print results self.result_table_create(self.table_header) self.perf_results['header'] = self.table_header for frame_size in self.frame_sizes: table_row = [frame_size] for test_cycle in self.test_cycles: table_row.append(test_cycle['Mpps'][frame_size]) table_row.append(test_cycle['pct'][frame_size]) self.result_table_add(table_row) self.perf_results['data'].append(table_row) self.result_table_print() def pmd_performance_2ports(self): """ PMD Performance Benchmarking with 2 ports. """ all_cores_mask = utils.create_mask(self.dut.get_core_list("all")) # prepare traffic generator input tgen_input = [] tgen_input.append( (self.tester.get_local_port(self.dut_ports[0]), self.tester.get_local_port(self.dut_ports[1]), "test.pcap")) tgen_input.append( (self.tester.get_local_port(self.dut_ports[1]), self.tester.get_local_port(self.dut_ports[0]), "test.pcap")) # run testpmd for each core config for test_cycle in self.test_cycles: core_config = test_cycle['cores'] core_list = self.dut.get_core_list(core_config, socket=self.ports_socket) if len(core_list) > 2: queues = len(core_list) / 2 else: queues = 1 core_mask = utils.create_mask(core_list) port_mask = utils.create_mask( [self.dut_ports[0], self.dut_ports[1]]) #self.pmdout.start_testpmd("all", "--coremask=%s --rxq=%d --txq=%d --portmask=%s" % (core_mask, queues, queues, port_mask)) self.pmdout.start_testpmd( core_config, " --rxq=%d --txq=%d --portmask=%s --rss-ip --txrst=32 --txfreet=32 --txd=128" % (queues, queues, port_mask), socket=self.ports_socket) command_line = self.pmdout.get_pmd_cmd() info = "Executing PMD using %s\n" % test_cycle['cores'] self.logger.info(info) self.rst_report(info, annex=True) self.rst_report(command_line + "\n\n", frame=True, annex=True) self.dut.send_expect("start", "testpmd> ", 100) for frame_size in self.frame_sizes: wirespeed = self.wirespeed(self.nic, frame_size, 2) # create pcap file self.logger.info("Running with frame size %d " % frame_size) payload_size = frame_size - self.headers_size self.tester.scapy_append( 'wrpcap("test.pcap", [Ether(src="52:00:00:00:00:00")/IP(src="1.2.3.4",dst="1.1.1.1")/TCP()/("X"*%d)])' % payload_size) self.tester.scapy_execute() # run traffic generator _, pps = self.tester.traffic_generator_throughput( tgen_input, rate_percent=100, delay=60) pps /= 1000000.0 pct = pps * 100 / wirespeed test_cycle['Mpps'][frame_size] = float('%.3f' % pps) test_cycle['pct'][frame_size] = float('%.3f' % pct) self.dut.send_expect("stop", "testpmd> ") self.dut.send_expect("quit", "# ", 30) sleep(5) for n in range(len(self.test_cycles)): for frame_size in self.frame_sizes: self.verify(self.test_cycles[n]['Mpps'][frame_size] > 0, "No traffic detected") # Print results self.result_table_create(self.table_header) self.perf_results['header'] = self.table_header for frame_size in self.frame_sizes: table_row = [frame_size] for test_cycle in self.test_cycles: table_row.append(test_cycle['Mpps'][frame_size]) table_row.append(test_cycle['pct'][frame_size]) self.result_table_add(table_row) self.perf_results['data'].append(table_row) self.result_table_print() def test_checksum_checking(self): """ Packet forwarding checking test """ self.dut.kill_all() port_mask = utils.create_mask([self.dut_ports[0], self.dut_ports[1]]) for rxfreet_value in self.rxfreet_values: self.pmdout.start_testpmd( "1S/2C/1T", "--portmask=%s --enable-rx-cksum --disable-rss --rxd=1024 --txd=1024 --rxfreet=%d" % (port_mask, rxfreet_value), socket=self.ports_socket) self.dut.send_expect("set fwd csum", "testpmd> ") self.dut.send_expect("start", "testpmd> ") self.send_packet(self.frame_sizes[0], checksum_test=True) l4csum_error = self.stop_and_get_l4csum_errors() # Check the l4 checksum errors reported for Rx port self.verify( 1 == int(l4csum_error[1]), "Wrong l4 checksum error count using rxfreet=%d (expected 1, reported %s)" % (rxfreet_value, l4csum_error[1])) self.dut.send_expect("quit", "# ", 30) sleep(5) def test_packet_checking(self): """ Packet forwarding checking test """ self.dut.kill_all() port_mask = utils.create_mask([self.dut_ports[0], self.dut_ports[1]]) self.pmdout.start_testpmd("1S/2C/1T", "--portmask=%s" % port_mask, socket=self.ports_socket) self.dut.send_expect("start", "testpmd> ") for size in self.frame_sizes: self.send_packet(size) self.dut.send_expect("stop", "testpmd> ") self.dut.send_expect("quit", "# ", 30) sleep(5) def stop_and_get_l4csum_errors(self): """ Stop forwarding and get Bad-l4csum number from stop statistic """ out = self.dut.send_expect("stop", "testpmd> ") result_scanner = r"Bad-l4csum: ([0-9]+) \s*" scanner = re.compile(result_scanner, re.DOTALL) m = scanner.findall(out) return m def get_stats(self, portid): """ Get packets number from port statistic """ stats = self.pmdout.get_pmd_stats(portid) return stats def send_packet(self, frame_size, checksum_test=False): """ Send 1 packet to portid """ port0_stats = self.get_stats(self.dut_ports[0]) gp0tx_pkts, gp0tx_bytes = [ port0_stats['TX-packets'], port0_stats['TX-bytes'] ] port1_stats = self.get_stats(self.dut_ports[1]) gp1rx_pkts, gp1rx_err, gp1rx_bytes = [ port1_stats['RX-packets'], port1_stats['RX-errors'], port1_stats['RX-bytes'] ] interface = self.tester.get_interface( self.tester.get_local_port(self.dut_ports[1])) mac = self.dut.get_mac_address(self.dut_ports[1]) load_size = frame_size - HEADER_SIZE['eth'] padding = frame_size - HEADER_SIZE['eth'] - HEADER_SIZE['ip'] - \ HEADER_SIZE['udp'] checksum = '' if checksum_test: checksum = 'chksum=0x1' self.tester.scapy_foreground() self.tester.scapy_append('nutmac="%s"' % mac) self.tester.scapy_append( 'sendp([Ether(dst=nutmac, src="52:00:00:00:00:00")/IP(len=%s)/UDP(%s)/Raw(load="\x50"*%s)], iface="%s")' % (load_size, checksum, padding, interface)) out = self.tester.scapy_execute() time.sleep(.5) port0_stats = self.get_stats(self.dut_ports[0]) p0tx_pkts, p0tx_bytes = [ port0_stats['TX-packets'], port0_stats['TX-bytes'] ] port1_stats = self.get_stats(self.dut_ports[1]) p1rx_pkts, p1rx_err, p1rx_bytes = [ port1_stats['RX-packets'], port1_stats['RX-errors'], port1_stats['RX-bytes'] ] p0tx_pkts -= gp0tx_pkts p0tx_bytes -= gp0tx_bytes p1rx_pkts -= gp1rx_pkts p1rx_bytes -= gp1rx_bytes p1rx_err -= gp1rx_err time.sleep(5) self.verify( self.pmdout.check_tx_bytes(p0tx_pkts, p1rx_pkts), "packet pass assert error, %d RX packets, %d TX packets" % (p1rx_pkts, p0tx_pkts)) self.verify( p1rx_bytes == frame_size - 4, "packet pass assert error, expected %d RX bytes, actual %d" % (frame_size - 4, p1rx_bytes)) self.verify( self.pmdout.check_tx_bytes(p0tx_bytes, frame_size - 4), "packet pass assert error, expected %d TX bytes, actual %d" % (frame_size - 4, p0tx_bytes)) return out def ip(self, port, frag, src, proto, tos, dst, chksum, len, options, version, flags, ihl, ttl, id): self.add_tcl_cmd("protocol config -name ip") self.add_tcl_cmd('ip config -sourceIpAddr "%s"' % src) self.add_tcl_cmd("ip config -sourceIpAddrMode ipRandom") self.add_tcl_cmd('ip config -destIpAddr "%s"' % dst) self.add_tcl_cmd("ip config -destIpAddrMode ipIdle") self.add_tcl_cmd("ip config -ttl %d" % ttl) self.add_tcl_cmd("ip config -totalLength %d" % len) self.add_tcl_cmd("ip config -fragment %d" % frag) self.add_tcl_cmd("ip config -ipProtocol ipV4ProtocolReserved255") self.add_tcl_cmd("ip config -identifier %d" % id) self.add_tcl_cmd("stream config -framesize %d" % (len + 18)) self.add_tcl_cmd("ip set %d %d %d" % (self.chasId, port['card'], port['port'])) def tear_down(self): """ Run after each test case. """ pass def tear_down_all(self): """ Run after each test suite. """ self.dut.kill_all()
class TestPmd(TestCase): def plot_results(self, number_ports): cores_configs = [] percent_values = [] # Append the percentage results for the all the cores configs for test_cycle in self.test_cycles: cores_configs.append(test_cycle['cores']) config_results = [] for frame_size in self.frame_sizes: config_results.append(test_cycle['pct'][frame_size]) percent_values.append(config_results) image_path = self.plotting.create_bars_plot( 'test_perf_pmd_%sports' % number_ports, 'PMD, %d ports' % number_ports, self.frame_sizes, percent_values, ylabel='% linerate', legend=cores_configs) dts.results_plot_print(image_path) def set_up_all(self): """ Run at the start of each test suite. PMD prerequisites. """ self.frame_sizes = [64, 65, 128, 256, 512, 1024, 1280, 1518] self.rxfreet_values = [0, 8, 16, 32, 64, 128] self.test_cycles = [{ 'cores': '1S/1C/1T', 'Mpps': {}, 'pct': {} }, { 'cores': '1S/1C/2T', 'Mpps': {}, 'pct': {} }, { 'cores': '1S/2C/1T', 'Mpps': {}, 'pct': {} }, { 'cores': '1S/2C/2T', 'Mpps': {}, 'pct': {} }, { 'cores': '1S/4C/2T', 'Mpps': {}, 'pct': {} }] self.table_header = ['Frame Size'] for test_cycle in self.test_cycles: self.table_header.append("%s Mpps" % test_cycle['cores']) self.table_header.append("% linerate") self.blacklist = "" # Based on h/w type, choose how many ports to use self.dut_ports = self.dut.get_ports() self.headers_size = HEADER_SIZE['eth'] + HEADER_SIZE[ 'ip'] + HEADER_SIZE['udp'] self.ports_socket = self.dut.get_numa_id(self.dut_ports[0]) self.plotting = Plotting(self.dut.crb['name'], self.target, self.nic) self.pmdout = PmdOutput(self.dut) def set_up(self): """ Run before each test case. """ pass def test_perf_pmd_performance_4ports(self): """ PMD Performance Benchmarking with 4 ports. """ all_cores_mask = dts.create_mask(self.dut.get_core_list("all")) # prepare traffic generator input self.verify( len(self.dut_ports) >= 4, "Insufficient ports for 4 ports performance") tgen_input = [] tgen_input.append( (self.tester.get_local_port(self.dut_ports[0]), self.tester.get_local_port(self.dut_ports[1]), "test.pcap")) tgen_input.append( (self.tester.get_local_port(self.dut_ports[2]), self.tester.get_local_port(self.dut_ports[3]), "test.pcap")) tgen_input.append( (self.tester.get_local_port(self.dut_ports[1]), self.tester.get_local_port(self.dut_ports[0]), "test.pcap")) tgen_input.append( (self.tester.get_local_port(self.dut_ports[3]), self.tester.get_local_port(self.dut_ports[2]), "test.pcap")) # run testpmd for each core config for test_cycle in self.test_cycles: core_config = test_cycle['cores'] core_list = self.dut.get_core_list(core_config, socket=self.ports_socket) if len(core_list) > 4: queues = len(core_list) / 4 else: queues = 1 core_mask = dts.create_mask(core_list) port_mask = dts.create_mask(self.dut.get_ports()) self.pmdout.start_testpmd( "all", "--coremask=%s --rxq=%d --txq=%d --portmask=%s" % (core_mask, queues, queues, port_mask)) info = "Executing PMD (mac fwd) using %s\n" % test_cycle['cores'] dts.report(info, annex=True) self.logger.info(info) dts.report(commandLine + "\n\n", frame=True, annex=True) # self.dut.send_expect("set fwd mac", "testpmd> ", 100) self.dut.send_expect("start", "testpmd> ") for frame_size in self.frame_sizes: wirespeed = self.wirespeed(self.nic, frame_size, 4) # create pcap file self.logger.info("Running with frame size %d " % frame_size) payload_size = frame_size - self.headers_size self.tester.scapy_append( 'wrpcap("test.pcap", [Ether(src="52:00:00:00:00:00")/IP()/UDP()/("X"*%d)])' % payload_size) self.tester.scapy_execute() # run traffic generator _, pps = self.tester.traffic_generator_throughput(tgen_input) pps /= 1000000.0 test_cycle['Mpps'][frame_size] = pps test_cycle['pct'][frame_size] = pps * 100 / wirespeed self.dut.send_expect("stop", "testpmd> ") self.dut.send_expect("quit", "# ", 30) sleep(5) for n in range(len(self.test_cycles)): for frame_size in self.frame_sizes: self.verify(self.test_cycles[n]['Mpps'][frame_size] is not 0, "No traffic detected") # Print results dts.results_table_add_header(self.table_header) for frame_size in self.frame_sizes: table_row = [frame_size] for test_cycle in self.test_cycles: table_row.append(test_cycle['Mpps'][frame_size]) table_row.append(test_cycle['pct'][frame_size]) dts.results_table_add_row(table_row) self.plot_results(number_ports=4) dts.results_table_print() def test_perf_pmd_performance_2ports(self): """ PMD Performance Benchmarking with 2 ports. """ all_cores_mask = dts.create_mask(self.dut.get_core_list("all")) # prepare traffic generator input tgen_input = [] tgen_input.append( (self.tester.get_local_port(self.dut_ports[0]), self.tester.get_local_port(self.dut_ports[1]), "test.pcap")) tgen_input.append( (self.tester.get_local_port(self.dut_ports[1]), self.tester.get_local_port(self.dut_ports[0]), "test.pcap")) # run testpmd for each core config for test_cycle in self.test_cycles: core_config = test_cycle['cores'] core_list = self.dut.get_core_list(core_config, socket=self.ports_socket) if len(core_list) > 2: queues = len(core_list) / 2 else: queues = 1 core_mask = dts.create_mask(core_list) port_mask = dts.create_mask([self.dut_ports[0], self.dut_ports[1]]) self.pmdout.start_testpmd( "all", "--coremask=%s --rxq=%d --txq=%d --portmask=%s" % (core_mask, queues, queues, port_mask)) command_line = self.pmdout.get_pmd_cmd() info = "Executing PMD using %s\n" % test_cycle['cores'] self.logger.info(info) dts.report(info, annex=True) dts.report(command_line + "\n\n", frame=True, annex=True) self.dut.send_expect("start", "testpmd> ") for frame_size in self.frame_sizes: wirespeed = self.wirespeed(self.nic, frame_size, 2) # create pcap file self.logger.info("Running with frame size %d " % frame_size) payload_size = frame_size - self.headers_size self.tester.scapy_append( 'wrpcap("test.pcap", [Ether(src="52:00:00:00:00:00")/IP()/UDP()/("X"*%d)])' % payload_size) self.tester.scapy_execute() # run traffic generator _, pps = self.tester.traffic_generator_throughput(tgen_input) pps /= 1000000.0 test_cycle['Mpps'][frame_size] = pps test_cycle['pct'][frame_size] = pps * 100 / wirespeed self.dut.send_expect("stop", "testpmd> ") self.dut.send_expect("quit", "# ", 30) sleep(5) for n in range(len(self.test_cycles)): for frame_size in self.frame_sizes: self.verify(self.test_cycles[n]['Mpps'][frame_size] > 0, "No traffic detected") # Print results dts.results_table_add_header(self.table_header) for frame_size in self.frame_sizes: table_row = [frame_size] for test_cycle in self.test_cycles: table_row.append(test_cycle['Mpps'][frame_size]) table_row.append(test_cycle['pct'][frame_size]) dts.results_table_add_row(table_row) self.plot_results(number_ports=2) dts.results_table_print() def test_checksum_checking(self): """ Packet forwarding checking test """ self.dut.kill_all() all_cores_mask = dts.create_mask(self.dut.get_core_list("all")) core_mask = dts.create_mask( self.dut.get_core_list('1S/1C/1T', socket=self.ports_socket)) port_mask = dts.create_mask([self.dut_ports[0], self.dut_ports[1]]) for rxfreet_value in self.rxfreet_values: self.pmdout.start_testpmd( "all", "--coremask=%s --portmask=%s --nb-cores=2 --enable-rx-cksum --disable-hw-vlan --disable-rss --crc-strip --rxd=1024 --txd=1024 --rxfreet=%d" % (core_mask, port_mask, rxfreet_value)) self.dut.send_expect("set fwd csum", "testpmd> ") self.dut.send_expect("start", "testpmd> ") self.send_packet(self.frame_sizes[0], checksum_test=True) l4csum_error = self.stop_and_get_l4csum_errors() # Check the l4 checksum errors reported for Rx port self.verify( 1 == int(l4csum_error[1]), "Wrong l4 checksum error count using rxfreet=%d (expected 1, reported %s)" % (rxfreet_value, l4csum_error[1])) self.dut.send_expect("quit", "# ", 30) sleep(5) def test_packet_checking(self): """ Packet forwarding checking test """ self.dut.kill_all() all_cores_mask = dts.create_mask(self.dut.get_core_list("all")) core_mask = dts.create_mask( self.dut.get_core_list('1S/1C/1T', socket=self.ports_socket)) port_mask = dts.create_mask([self.dut_ports[0], self.dut_ports[1]]) self.pmdout.start_testpmd( "all", "--coremask=%s --portmask=%s" % (core_mask, port_mask)) self.dut.send_expect("start", "testpmd> ") for size in self.frame_sizes: self.send_packet(size) self.dut.send_expect("stop", "testpmd> ") self.dut.send_expect("quit", "# ", 30) sleep(5) def stop_and_get_l4csum_errors(self): """ Stop forwarding and get Bad-l4csum number from stop statistic """ out = self.dut.send_expect("stop", "testpmd> ") result_scanner = r"Bad-l4csum: ([0-9]+) \s*" scanner = re.compile(result_scanner, re.DOTALL) m = scanner.findall(out) return m def get_stats(self, portid): """ Get packets number from port statistic """ stats = self.pmdout.get_pmd_stats(portid) return stats def send_packet(self, frame_size, checksum_test=False): """ Send 1 packet to portid """ port0_stats = self.get_stats(self.dut_ports[0]) gp0tx_pkts, gp0tx_bytes = [ port0_stats['TX-packets'], port0_stats['TX-bytes'] ] port1_stats = self.get_stats(self.dut_ports[1]) gp1rx_pkts, gp1rx_err, gp1rx_bytes = [ port1_stats['RX-packets'], port1_stats['RX-errors'], port1_stats['RX-bytes'] ] interface = self.tester.get_interface( self.tester.get_local_port(self.dut_ports[1])) mac = self.dut.get_mac_address(self.dut_ports[1]) load_size = frame_size - HEADER_SIZE['eth'] padding = frame_size - HEADER_SIZE['eth'] - HEADER_SIZE['ip'] - \ HEADER_SIZE['udp'] checksum = '' if checksum_test: checksum = 'chksum=0x0' self.tester.scapy_foreground() self.tester.scapy_append('nutmac="%s"' % mac) self.tester.scapy_append( 'sendp([Ether(dst=nutmac, src="52:00:00:00:00:00")/IP(len=%s)/UDP(%s)/Raw(load="\x50"*%s)], iface="%s")' % (load_size, checksum, padding, interface)) out = self.tester.scapy_execute() time.sleep(.5) port0_stats = self.get_stats(self.dut_ports[0]) p0tx_pkts, p0tx_bytes = [ port0_stats['TX-packets'], port0_stats['TX-bytes'] ] port1_stats = self.get_stats(self.dut_ports[1]) p1rx_pkts, p1rx_err, p1rx_bytes = [ port1_stats['RX-packets'], port1_stats['RX-errors'], port1_stats['RX-bytes'] ] p0tx_pkts -= gp0tx_pkts p0tx_bytes -= gp0tx_bytes p1rx_pkts -= gp1rx_pkts p1rx_bytes -= gp1rx_bytes p1rx_err -= gp1rx_err time.sleep(5) self.verify( p0tx_pkts == p1rx_pkts, "packet pass assert error, %d RX packets, %d TX packets" % (p1rx_pkts, p0tx_pkts)) if checksum_test: self.verify( p1rx_bytes == frame_size - 4, "packet pass assert error, expected %d RX bytes, actual %d" % (frame_size - 4, p1rx_bytes)) else: self.verify( p1rx_bytes == frame_size, "packet pass assert error, expected %d RX bytes, actual %d" % (frame_size, p1rx_bytes)) self.verify( p0tx_bytes == frame_size, "packet pass assert error, expected %d TX bytes, actual %d" % (frame_size, p0tx_bytes)) return out def tear_down(self): """ Run after each test case. """ pass def tear_down_all(self): """ Run after each test suite. """ self.dut.kill_all()
class TestPmd(TestCase): def plot_results(self, number_ports): cores_configs = [] percent_values = [] # Append the percentage results for the all the cores configs for test_cycle in self.test_cycles: cores_configs.append(test_cycle['cores']) config_results = [] for frame_size in self.frame_sizes: config_results.append(test_cycle['pct'][frame_size]) percent_values.append(config_results) image_path = self.plotting.create_bars_plot( 'test_perf_pmd_%sports' % number_ports, 'PMD, %d ports' % number_ports, self.frame_sizes, percent_values, ylabel='% linerate', legend=cores_configs) dts.results_plot_print(image_path) def set_up_all(self): """ Run at the start of each test suite. PMD prerequisites. """ self.frame_sizes = [64, 65, 128, 256, 512, 1024, 1280, 1518] self.rxfreet_values = [0, 8, 16, 32, 64, 128] self.test_cycles = [{'cores': '1S/1C/1T', 'Mpps': {}, 'pct': {}}, {'cores': '1S/1C/2T', 'Mpps': {}, 'pct': {}}, {'cores': '1S/2C/1T', 'Mpps': {}, 'pct': {}}, {'cores': '1S/2C/2T', 'Mpps': {}, 'pct': {}}, {'cores': '1S/4C/2T', 'Mpps': {}, 'pct': {}} ] self.table_header = ['Frame Size'] for test_cycle in self.test_cycles: self.table_header.append("%s Mpps" % test_cycle['cores']) self.table_header.append("% linerate") self.blacklist = "" # Based on h/w type, choose how many ports to use self.dut_ports = self.dut.get_ports() self.headers_size = HEADER_SIZE['eth'] + HEADER_SIZE[ 'ip'] + HEADER_SIZE['udp'] self.ports_socket = self.dut.get_numa_id(self.dut_ports[0]) self.plotting = Plotting(self.dut.crb['name'], self.target, self.nic) self.pmdout = PmdOutput(self.dut) def set_up(self): """ Run before each test case. """ pass def test_perf_pmd_performance_4ports(self): """ PMD Performance Benchmarking with 4 ports. """ all_cores_mask = dts.create_mask(self.dut.get_core_list("all")) # prepare traffic generator input self.verify(len(self.dut_ports) >= 4, "Insufficient ports for 4 ports performance") tgen_input = [] tgen_input.append((self.tester.get_local_port(self.dut_ports[0]), self.tester.get_local_port(self.dut_ports[1]), "test.pcap")) tgen_input.append((self.tester.get_local_port(self.dut_ports[2]), self.tester.get_local_port(self.dut_ports[3]), "test.pcap")) tgen_input.append((self.tester.get_local_port(self.dut_ports[1]), self.tester.get_local_port(self.dut_ports[0]), "test.pcap")) tgen_input.append((self.tester.get_local_port(self.dut_ports[3]), self.tester.get_local_port(self.dut_ports[2]), "test.pcap")) # run testpmd for each core config for test_cycle in self.test_cycles: core_config = test_cycle['cores'] core_list = self.dut.get_core_list(core_config, socket=self.ports_socket) if len(core_list) > 4: queues = len(core_list) / 4 else: queues = 1 core_mask = dts.create_mask(core_list) port_mask = dts.create_mask(self.dut.get_ports()) self.pmdout.start_testpmd("all", "--coremask=%s --rxq=%d --txq=%d --portmask=%s" % (core_mask, queues, queues, port_mask)) info = "Executing PMD (mac fwd) using %s\n" % test_cycle['cores'] dts.report(info, annex=True) self.logger.info(info) dts.report(commandLine + "\n\n", frame=True, annex=True) # self.dut.send_expect("set fwd mac", "testpmd> ", 100) self.dut.send_expect("start", "testpmd> ") for frame_size in self.frame_sizes: wirespeed = self.wirespeed(self.nic, frame_size, 4) # create pcap file self.logger.info("Running with frame size %d " % frame_size) payload_size = frame_size - self.headers_size self.tester.scapy_append( 'wrpcap("test.pcap", [Ether(src="52:00:00:00:00:00")/IP()/UDP()/("X"*%d)])' % payload_size) self.tester.scapy_execute() # run traffic generator _, pps = self.tester.traffic_generator_throughput(tgen_input) pps /= 1000000.0 test_cycle['Mpps'][frame_size] = pps test_cycle['pct'][frame_size] = pps * 100 / wirespeed self.dut.send_expect("stop", "testpmd> ") self.dut.send_expect("quit", "# ", 30) sleep(5) for n in range(len(self.test_cycles)): for frame_size in self.frame_sizes: self.verify(self.test_cycles[n]['Mpps'][ frame_size] is not 0, "No traffic detected") # Print results dts.results_table_add_header(self.table_header) for frame_size in self.frame_sizes: table_row = [frame_size] for test_cycle in self.test_cycles: table_row.append(test_cycle['Mpps'][frame_size]) table_row.append(test_cycle['pct'][frame_size]) dts.results_table_add_row(table_row) self.plot_results(number_ports=4) dts.results_table_print() def test_perf_pmd_performance_2ports(self): """ PMD Performance Benchmarking with 2 ports. """ all_cores_mask = dts.create_mask(self.dut.get_core_list("all")) # prepare traffic generator input tgen_input = [] tgen_input.append((self.tester.get_local_port(self.dut_ports[0]), self.tester.get_local_port(self.dut_ports[1]), "test.pcap")) tgen_input.append((self.tester.get_local_port(self.dut_ports[1]), self.tester.get_local_port(self.dut_ports[0]), "test.pcap")) # run testpmd for each core config for test_cycle in self.test_cycles: core_config = test_cycle['cores'] core_list = self.dut.get_core_list(core_config, socket=self.ports_socket) if len(core_list) > 2: queues = len(core_list) / 2 else: queues = 1 core_mask = dts.create_mask(core_list) port_mask = dts.create_mask([self.dut_ports[0], self.dut_ports[1]]) self.pmdout.start_testpmd("all", "--coremask=%s --rxq=%d --txq=%d --portmask=%s" % (core_mask, queues, queues, port_mask)) command_line = self.pmdout.get_pmd_cmd() info = "Executing PMD using %s\n" % test_cycle['cores'] self.logger.info(info) dts.report(info, annex=True) dts.report(command_line + "\n\n", frame=True, annex=True) self.dut.send_expect("start", "testpmd> ") for frame_size in self.frame_sizes: wirespeed = self.wirespeed(self.nic, frame_size, 2) # create pcap file self.logger.info("Running with frame size %d " % frame_size) payload_size = frame_size - self.headers_size self.tester.scapy_append( 'wrpcap("test.pcap", [Ether(src="52:00:00:00:00:00")/IP()/UDP()/("X"*%d)])' % payload_size) self.tester.scapy_execute() # run traffic generator _, pps = self.tester.traffic_generator_throughput(tgen_input) pps /= 1000000.0 test_cycle['Mpps'][frame_size] = pps test_cycle['pct'][frame_size] = pps * 100 / wirespeed self.dut.send_expect("stop", "testpmd> ") self.dut.send_expect("quit", "# ", 30) sleep(5) for n in range(len(self.test_cycles)): for frame_size in self.frame_sizes: self.verify(self.test_cycles[n]['Mpps'][ frame_size] > 0, "No traffic detected") # Print results dts.results_table_add_header(self.table_header) for frame_size in self.frame_sizes: table_row = [frame_size] for test_cycle in self.test_cycles: table_row.append(test_cycle['Mpps'][frame_size]) table_row.append(test_cycle['pct'][frame_size]) dts.results_table_add_row(table_row) self.plot_results(number_ports=2) dts.results_table_print() def test_checksum_checking(self): """ Packet forwarding checking test """ self.dut.kill_all() all_cores_mask = dts.create_mask(self.dut.get_core_list("all")) core_mask = dts.create_mask(self.dut.get_core_list('1S/1C/1T', socket=self.ports_socket)) port_mask = dts.create_mask([self.dut_ports[0], self.dut_ports[1]]) for rxfreet_value in self.rxfreet_values: self.pmdout.start_testpmd("all", "--coremask=%s --portmask=%s --nb-cores=2 --enable-rx-cksum --disable-hw-vlan --disable-rss --crc-strip --rxd=1024 --txd=1024 --rxfreet=%d" % (core_mask, port_mask, rxfreet_value)) self.dut.send_expect("set fwd csum", "testpmd> ") self.dut.send_expect("start", "testpmd> ") self.send_packet(self.frame_sizes[0], checksum_test=True) l4csum_error = self.stop_and_get_l4csum_errors() # Check the l4 checksum errors reported for Rx port self.verify(1 == int(l4csum_error[1]), "Wrong l4 checksum error count using rxfreet=%d (expected 1, reported %s)" % (rxfreet_value, l4csum_error[1])) self.dut.send_expect("quit", "# ", 30) sleep(5) def test_packet_checking(self): """ Packet forwarding checking test """ self.dut.kill_all() all_cores_mask = dts.create_mask(self.dut.get_core_list("all")) core_mask = dts.create_mask(self.dut.get_core_list('1S/1C/1T', socket=self.ports_socket)) port_mask = dts.create_mask([self.dut_ports[0], self.dut_ports[1]]) self.pmdout.start_testpmd("all", "--coremask=%s --portmask=%s" % (core_mask, port_mask)) self.dut.send_expect("start", "testpmd> ") for size in self.frame_sizes: self.send_packet(size) self.dut.send_expect("stop", "testpmd> ") self.dut.send_expect("quit", "# ", 30) sleep(5) def stop_and_get_l4csum_errors(self): """ Stop forwarding and get Bad-l4csum number from stop statistic """ out = self.dut.send_expect("stop", "testpmd> ") result_scanner = r"Bad-l4csum: ([0-9]+) \s*" scanner = re.compile(result_scanner, re.DOTALL) m = scanner.findall(out) return m def get_stats(self, portid): """ Get packets number from port statistic """ stats = self.pmdout.get_pmd_stats(portid) return stats def send_packet(self, frame_size, checksum_test=False): """ Send 1 packet to portid """ port0_stats = self.get_stats(self.dut_ports[0]) gp0tx_pkts, gp0tx_bytes = [port0_stats['TX-packets'], port0_stats['TX-bytes']] port1_stats = self.get_stats(self.dut_ports[1]) gp1rx_pkts, gp1rx_err, gp1rx_bytes = [port1_stats['RX-packets'], port1_stats['RX-errors'], port1_stats['RX-bytes']] interface = self.tester.get_interface( self.tester.get_local_port(self.dut_ports[1])) mac = self.dut.get_mac_address(self.dut_ports[1]) load_size = frame_size - HEADER_SIZE['eth'] padding = frame_size - HEADER_SIZE['eth'] - HEADER_SIZE['ip'] - \ HEADER_SIZE['udp'] checksum = '' if checksum_test: checksum = 'chksum=0x0' self.tester.scapy_foreground() self.tester.scapy_append('nutmac="%s"' % mac) self.tester.scapy_append('sendp([Ether(dst=nutmac, src="52:00:00:00:00:00")/IP(len=%s)/UDP(%s)/Raw(load="\x50"*%s)], iface="%s")' % ( load_size, checksum, padding, interface)) out = self.tester.scapy_execute() time.sleep(.5) port0_stats = self.get_stats(self.dut_ports[0]) p0tx_pkts, p0tx_bytes = [port0_stats['TX-packets'], port0_stats['TX-bytes']] port1_stats = self.get_stats(self.dut_ports[1]) p1rx_pkts, p1rx_err, p1rx_bytes = [port1_stats['RX-packets'], port1_stats['RX-errors'], port1_stats['RX-bytes']] p0tx_pkts -= gp0tx_pkts p0tx_bytes -= gp0tx_bytes p1rx_pkts -= gp1rx_pkts p1rx_bytes -= gp1rx_bytes p1rx_err -= gp1rx_err time.sleep(5) self.verify(p0tx_pkts == p1rx_pkts, "packet pass assert error, %d RX packets, %d TX packets" % (p1rx_pkts, p0tx_pkts)) if checksum_test: self.verify(p1rx_bytes == frame_size - 4, "packet pass assert error, expected %d RX bytes, actual %d" % (frame_size - 4, p1rx_bytes)) else: self.verify(p1rx_bytes == frame_size, "packet pass assert error, expected %d RX bytes, actual %d" % (frame_size, p1rx_bytes)) self.verify(p0tx_bytes == frame_size, "packet pass assert error, expected %d TX bytes, actual %d" % (frame_size, p0tx_bytes)) return out def tear_down(self): """ Run after each test case. """ pass def tear_down_all(self): """ Run after each test suite. """ self.dut.kill_all()
class PmdBonding(object): ''' common methods for testpmd bonding ''' def __init__(self, **kwargs): # set parent instance self.parent = kwargs.get('parent') # set target source code directory self.target_source = self.parent.dut.base_dir # set logger self.logger = self.parent.logger self.verify = self.parent.verify # select packet generator self.pktgen_name = 'ixia' if self.is_perf else 'scapy' # traffic default config self.default_pkt_size = kwargs.get('pkt_size') or FRAME_SIZE_64 self.default_src_mac = kwargs.get('src_mac') self.default_src_ip = kwargs.get('src_ip') self.default_src_port = kwargs.get('src_port') self.default_dst_ip = kwargs.get('dst_ip') self.default_dst_port = kwargs.get('dst_port') self.default_pkt_name = kwargs.get('pkt_name') # testpmd self.testpmd = PmdOutput(self.parent.dut) self.testpmd_status = 'close' # # On tester platform, packet transmission # def mac_str_to_int(self, mac_str): """ convert the MAC type from the string into the int. """ mac_hex = '0x' for mac_part in mac_str.split(':'): mac_hex += mac_part return int(mac_hex, 16) def mac_int_to_str(self, mac_int): """ Translate the MAC type from the string into the int. """ temp = hex(mac_int)[2:] b = [] [b.append(temp[n:n+2]) for n in range(len(temp)) if n % 2 == 0] new_mac = ":".join(b) return new_mac def ip_str_to_int(self, ip_str): """ convert the IP type from the string into the int. """ ip_int = socket.ntohl(struct.unpack( "I", socket.inet_aton(str(ip_str)))[0]) return ip_int def ip_int_to_str(self, ip_int): """ convert the IP type from the int into the string. """ ip_str = socket.inet_ntoa(struct.pack('I', socket.htonl(ip_int))) return ip_str def increase_ip(self, ip, step=1): ''' ip: string format ''' _ip_int = self.ip_str_to_int(ip) new_ip = self.ip_int_to_str(_ip_int + step) return new_ip def increase_mac(self, mac, step=1): ''' mac: string format ''' _mac_int = self.mac_str_to_int(mac) new_mac = self.mac_int_to_str(_mac_int+step) return new_mac def increase_port(self, port, step=1): ''' port: int format ''' new_port = port + step return new_port def increase_mac_ip_port(self, step=1): # get source port setting mac, ip, port = (self.default_src_mac, self.default_src_ip, self.default_src_port) return (self.increase_mac(mac, step), self.increase_ip(ip, step), self.increase_port(port, step)) def get_pkt_len(self, pkt_type): ''' get packet payload size ''' frame_size = self.default_pkt_size headers_size = sum(map(lambda x: HEADER_SIZE[x], ['eth', 'ip', pkt_type])) pktlen = frame_size - headers_size return pktlen def set_stream_to_slave_port(self, dut_port_id): ''' use framework/packet.py module to create one stream, send stream to slave port ''' # get dst port mac address pkt_name = self.default_pkt_name destport = self.default_dst_port destip = self.default_dst_ip dst_mac = self.get_port_info(dut_port_id, 'mac') # packet size pktlen = self.get_pkt_len(pkt_name) # set stream configuration srcmac, srcip, srcport = self.increase_mac_ip_port(0) pkt_config = { 'type': pkt_name.upper(), 'pkt_layers': { # Ether(dst=nutmac, src=srcmac) 'ether': {'src': srcmac, 'dst': dst_mac}, # IP(dst=destip, src=srcip, len=%s) 'ipv4': {'src': srcip, 'dst': destip}, # pkt_name(sport=srcport, dport=destport) pkt_name: {'src': srcport, 'dst': destport}, # Raw(load='\x50'*%s) 'raw': {'payload': ['58'] * self.get_pkt_len(pkt_name)}}} # create packet streams = [] # keep a copy of pcap for debug savePath = os.sep.join([self.target_source, "pkt_{0}.pcap".format(pkt_name)]) pkt_type = pkt_config.get('type') pkt_layers = pkt_config.get('pkt_layers') pkt = Packet(pkt_type=pkt_type.upper()) for layer in pkt_layers.keys(): pkt.config_layer(layer, pkt_layers[layer]) pkt.pktgen.write_pcap(savePath) streams.append(pkt.pktgen.pkt) return streams def set_stream_to_bond_port(self, bond_port, slaves): ''' : use framework/packet.py module to create multiple streams send streams from bond port to slaves :param bond_port: bonded device port id :param slaves: slaves port id ''' pkt_configs = [] # get dst port mac address pkt_name = self.default_pkt_name destport = self.default_dst_port destip = self.default_dst_ip dst_mac = self.get_port_info(bond_port, 'mac') # packet size pktlen = self.get_pkt_len(pkt_type) # set stream configuration for packet_id in range(len(slaves['active'])): srcmac, srcip, srcport = self.increase_mac_ip_port(packet_id) pkt_configs.append({ 'type': pkt_name.upper(), 'pkt_layers': { # Ether(dst=nutmac, src=srcmac) 'ether': {'src': srcmac, 'dst': dst_mac}, # IP(dst=destip, src=srcip, len=%s) 'ipv4': {'src': srcip, 'dst': destip}, # pkt_name(sport=srcport, dport=destport) pkt_name: {'src': srcport, 'dst': destport}, # Raw(load='\x50'*%s) 'raw': {'payload': ['58'] * self.get_pkt_len(pkt_name)}}}) # create packet streams = [] for values in pkt_configs: # keep a copy of pcap for debug savePath = os.sep.join([self.target_source, "pkt_{0}.pcap".format(stm_name)]) pkt_type = values.get('type') pkt_layers = values.get('pkt_layers') pkt = Packet(pkt_type=pkt_type.upper()) for layer in pkt_layers.keys(): pkt.config_layer(layer, pkt_layers[layer]) pkt.pktgen.write_pcap(savePath) streams.append(pkt.pktgen.pkt) return streams def send_packets_by_scapy(self, **kwargs): tx_iface = kwargs.get('port topo')[0] # set interface ready to send packet cmd = "ifconfig {0} up".format(tx_iface) self.parent.tester.send_expect(cmd, '# ', 30) send_pkts = kwargs.get('stream') # stream config stream_configs = kwargs.get('traffic configs') count = stream_configs.get('count') interval = stream_configs.get('interval', 0.01) # run traffic sendp(send_pkts, iface=tx_iface, inter=interval, verbose=False, count=count) def send_packets_by_ixia(self, **kwargs): tester_port = kwargs.get('tx_intf') count = kwargs.get('count', 1) traffic_type = kwargs.get('traffic_type', 'normal') traffic_time = kwargs.get('traffic_time', 0) rate_percent = kwargs.get('rate_percent', float(100)) #--------------------------------------------------------------- send_pkts = [] self.tgen_input = [] tgen_input = self.tgen_input # generate packet contain multi stream for pkt in self.packet_types.values(): send_pkts.append(pkt.pktgen.pkt) ixia_pkt = os.sep.join([self.target_source, 'bonding_ixia.pcap']) wrpcap(ixia_pkt, send_pkts) #---------------------------------------------------------------- # set packet for send # pause frame basic configuration pause_time = 65535 pause_rate = 0.50 # run ixia testing frame_size = self.default_pkt_size # calculate number of packets expect_pps = self.parent.wirespeed(self.parent.nic, frame_size, 1) * \ 1000000.0 # get line rate linerate = expect_pps * (frame_size + 20) * 8 # calculate default sleep time for one pause frame sleep = (1 / linerate) * pause_time * 512 # calculate packets dropped in sleep time self.n_pkts = int((sleep / (1 / expect_pps)) * (1 / pause_rate)) #---------------------------------------------------------------- tester_port = self.parent.tester.get_local_port(self.parent.dut_ports[0]) tgen_input.append((tester_port, tester_port,ixia_pkt)) # run latency stat statistics self.parent.tester.loop_traffic_generator_throughput(tgen_input, self.rate_percent) def stop_ixia(self, data_types='packets'): tester_inst = self.parent.tester # get ixia statistics line_rate = tester_inst.get_port_line_rate() rx_bps, rx_pps = \ tester_inst.stop_traffic_generator_throughput_loop(self.tgen_input) output = tester_inst.traffic_get_port_stats(self.tgen_input) self.cur_data['ixia statistics'] = [] append = self.cur_data['ixia statistics'].append append('send packets: {0}'.format(output[0])) append('line_rate: {0}'.format(line_rate[0])) append('rate_percent: {0}%'.format(self.rate_percent)) def get_pktgen(self, name): pkt_gens = { 'ixia': self.send_packets_by_ixia, 'scapy': self.send_packets_by_scapy,} pkt_generator = pkt_gens.get(name) return pkt_generator def send_packet(self, traffic_config): """ stream transmission on specified link topology """ time.sleep(2) # start traffic self.logger.info("begin transmission ...") pktgen = self.get_pktgen(self.pktgen_name) result = pktgen(**traffic_config) # end traffic self.logger.info("complete transmission") return result # # On dut, dpdk testpmd common methods # def check_process_status(self, process_name='testpmd'): cmd = "ps aux | grep -i %s | grep -v grep | awk {'print $2'}"%( process_name) out = self.parent.dut.alt_session.send_expect(cmd, "# ", 10) status = True if out != "" else False return status def check_process_exist(self, process_name='testpmd'): status = self.check_process_status(process_name) if not status: msg = "{0} process exceptional quit".format(process_name) out = self.parent.dut.session.session.get_output_all() self.logger.info(out) raise VerifyFailure(msg) def d_console(self, cmds): ''' wrap up testpmd command interactive console ''' if len(cmds) == 0: return # check if cmds is string if isinstance(cmds, str): timeout = 10 cmds = [[cmds, '', timeout]] # check if cmds is only one command if not isinstance(cmds[0], list): cmds = [cmds] outputs = [] if len(cmds) > 1 else '' for item in cmds: expected_items = item[1] if expected_items and isinstance(expected_items, (list, tuple)): check_output = True expected_str = expected_items[0] or 'testpmd> ' else: check_output = False expected_str = expected_items or 'testpmd> ' timeout = int(item[2]) if len(item) == 3 else 5 #---------------------------------------------------------------- # run command on session try: console = self.testpmd.execute_cmd msg_pipe = self.testpmd.get_output output = console(item[0], expected_str, timeout) output = msg_pipe(timeout) if not output else output except TimeoutException: try: # check if testpmd quit self.check_process_exist() except Exception as e: self.testpmd_status = 'close' msg = "execute '{0}' timeout".format(item[0]) output = out = self.parent.dut.session.session.get_output_all() self.logger.error(output) raise Exception(msg) if len(cmds) > 1: outputs.append(output) else: outputs = output if check_output and len(expected_items) >= 2: self.logger.info(output) expected_output = expected_items[1] check_type = True if len(expected_items) == 2 \ else expected_items[2] if check_type and expected_output in output: msg = "expected '{0}' is in output".format(expected_output) self.logger.info(msg) elif not check_type and expected_output not in output: fmt = "unexpected '{0}' is not in output" msg = fmt.format(expected_output) self.logger.info(msg) else: status = "isn't in" if check_type else "is in" msg = "[{0}] {1} output".format(expected_output, status) self.logger.error(msg) raise VerifyFailure(msg) time.sleep(2) return outputs def preset_testpmd(self, core_mask, options='', eal_param=''): try: self.testpmd.start_testpmd( core_mask, param=' '.join(options), eal_param=eal_param) except TimeoutException: # check if testpmd quit try: self.check_process_exist() except Exception as e: self.testpmd_status = 'close' msg = "execute '{0}' timeout".format(item[0]) self.logger.error(msg_pipe(timeout)) raise TimeoutException(msg) # wait lsc event udpate done time.sleep(10) # check if testpmd has bootep up if self.check_process_status(): self.logger.info("testpmd boot up successful") else: raise VerifyFailure("testpmd boot up failed") self.d_console(self.preset_testpmd_cmds) self.preset_testpmd_cmds = [] time.sleep(1) def start_testpmd(self, eal_option=''): if self.testpmd_status == 'running': return # boot up testpmd hw_mask = 'all' options = '' self.preset_testpmd_cmds = ['port stop all', '', 15] self.preset_testpmd(hw_mask, options, eal_param=eal_option) self.testpmd_status = 'running' def stop_testpmd(self): time.sleep(1) testpmd_cmds =[['port stop all', '', 15], ['show port stats all', ''], ['stop', ''],] output = self.d_console(testpmd_cmds) time.sleep(1) return output def close_testpmd(self): if self.testpmd_status == 'close': return None output = self.stop_testpmd() time.sleep(1) self.testpmd.quit() time.sleep(10) if self.check_process_status(): raise VerifyFailure("testpmd close failed") else: self.logger.info("close testpmd successful") self.testpmd_status = 'close' return output def start_ports(self, port='all'): """ Start a port which the testpmd can see. """ timeout = 12 if port=='all' else 5 cmds =[ ["port start %s" % str(port), " ", timeout], # to avoid lsc event message interfere normal status [" ", '', timeout]] self.d_console(cmds) def get_stats(self, portid, flow=['rx', 'tx']): """ get one port statistics of testpmd """ _portid = int(portid) if isinstance(portid, (str, unicode)) else portid info = self.testpmd.get_pmd_stats(_portid) _kwd = ["-packets", "-errors", "-bytes"] stats = {} if isinstance(flow, list): for item in flow: for item2 in _kwd: name = item.upper() + item2 stats[name] = int(info[name]) elif isinstance(flow, (str, unicode)): for item in _kwd: name = flow.upper() + item stats[name] = int(info[name]) else: msg = 'unknown data type' raise Exception(msg) return stats def get_all_stats(self, ports): """ Get a group of ports statistics, which testpmd can display. """ stats = {} attrs = ['tx', 'rx'] for port_id in ports: stats[port_id] = self.get_stats(port_id, attrs) return stats def set_tester_port_status(self, port_name, status): """ Do some operations to the network interface port, such as "up" or "down". """ eth = self.parent.tester.get_interface(port_name) self.parent.tester.admin_ports_linux(eth, status) time.sleep(5) def set_dut_peer_port_by_id(self, port_id, status): # stop peer port on tester intf = self.parent.tester.get_local_port(self.parent.dut_ports[port_id]) self.set_tester_port_status(intf, status) time.sleep(5) cur_status = self.get_port_info(port_id, 'link_status') self.logger.info("port {0} is [{1}]".format(port_id, cur_status)) if cur_status != status: self.logger.warning("expected status is [{0}]".format(status)) def set_dut_port_status(self, port_id, status): opt = 'link-up' if status == 'up' else 'link-down' # stop slave link by force cmd = "set {0} port {1}".format(opt, port_id) self.d_console(cmd) time.sleep(5) cur_status = self.get_port_info(port_id, 'link_status') self.logger.info("port {0} is [{1}]".format(port_id, cur_status)) if cur_status != status: self.logger.warning("expected status is [{0}]".format(status)) # # testpmd bonding commands # def get_value_from_str(self, key_str, regx_str, string): """ Get some values from the given string by the regular expression. """ if isinstance(key_str, (unicode, str)): pattern = r"(?<=%s)%s" % (key_str, regx_str) s = re.compile(pattern) res = s.search(string) if type(res).__name__ == 'NoneType': msg = "{0} hasn't match anything".format(key_str) self.logger.warning(msg) return ' ' else: return res.group(0) elif isinstance(key_str, (list, tuple)): for key in key_str: pattern = r"(?<=%s)%s" % (key, regx_str) s = re.compile(pattern) res = s.search(string) if type(res).__name__ == 'NoneType': continue else: return res.group(0) else: self.logger.warning("all key_str hasn't match anything") return ' ' def _get_detail_from_port_info(self, port_id, args): """ Get the detail info from the output of pmd cmd 'show port info <port num>'. """ key_str, regx_str = args out = self.d_console("show port info %d" % port_id) find_value = self.get_value_from_str(key_str, regx_str, out) return find_value def get_detail_from_port_info(self, port_id, args): if isinstance(args[0], (list, tuple)): return [self._get_detail_from_port_info(port_id, sub_args) for sub_args in args] else: return self._get_detail_from_port_info(port_id, args) def get_port_info(self, port_id, info_type): ''' Get the specified port information by its output message format ''' info_set = { 'mac': ["MAC address: ", "([0-9A-F]{2}:){5}[0-9A-F]{2}"], 'connect_socket': ["Connect to socket: ", "\d+"], 'memory_socket': ["memory allocation on the socket: ", "\d+"], 'link_status': ["Link status: ", "\S+"], 'link_speed': ["Link speed: ", "\d+"], 'link_duplex': ["Link duplex: ", "\S+"], 'promiscuous_mode': ["Promiscuous mode: ", "\S+"], 'allmulticast_mode':["Allmulticast mode: ", "\S+"], 'vlan_offload': [ ["strip ", "\S+"], ['filter', "\S+"], ['qinq\(extend\) ', "\S+"]], 'queue_config': [ ["Max possible RX queues: ", "\d+"], ['Max possible number of RXDs per queue: ', "\d+"], ['Min possible number of RXDs per queue: ', "\d+"], ["Max possible TX queues: ", "\d+"], ['Max possible number of TXDs per queue: ', "\d+"], ['Min possible number of TXDs per queue: ', "\d+"],] } if info_type in info_set.keys(): return self.get_detail_from_port_info(port_id, info_set[info_type]) else: msg = os.linesep.join([ "support query items including::", os.linesep.join(info_set.keys())]) self.logger.warning(msg) return None # # On dut, dpdk testpmd common bonding methods # def get_bonding_config(self, config_content, args): """ Get bonding info by command "show bonding config". """ key_str, regx_str = args find_value = self.get_value_from_str(key_str, regx_str, config_content) return find_value def get_info_from_bond_config(self, config_content, args): """ Get active slaves of the bonding device which you choose. """ search_args = args if isinstance(args[0], (list, tuple)) else [args] for search_args in search_args: try: info = self.get_bonding_config(config_content, search_args) break except Exception as e: self.logger.info(e) else: info = None return info def get_bonding_info(self, bond_port, info_types): ''' Get the specified port information by its output message format ''' info_set = { 'mode': ["Bonding mode: ", "\d*"], 'agg_mode': ["IEEE802.3AD Aggregator Mode: ", "\S*"], 'balance_policy':["Balance Xmit Policy: ", "\S+"], 'slaves': [["Slaves \(\d\): \[", "\d*( \d*)*"], ["Slaves: \[", "\d*( \d*)*"]], 'active_slaves': [["Active Slaves \(\d\): \[", "\d*( \d*)*"], ["Acitve Slaves: \[", "\d*( \d*)*"]], 'primary': ["Primary: \[", "\d*"]} # get all config information config_content = self.d_console("show bonding config %d" % bond_port) if isinstance(info_types, (list or tuple)): query_values = [] for info_type in info_types: if info_type in info_set.keys(): find_value = self.get_info_from_bond_config( config_content, info_set[info_type]) if info_type in ['active_slaves', 'slaves']: find_value = [value for value in find_value.split(' ') if value] else: find_value = None query_values.append(find_value) return query_values else: info_type = info_types if info_type in info_set.keys(): find_value = self.get_info_from_bond_config( config_content, info_set[info_type]) if info_type in ['active_slaves', 'slaves']: find_value = [value for value in find_value.split(' ') if value] return find_value else: return None def get_active_slaves(self, bond_port): primary_port = int(self.get_bonding_info(bond_port, 'primary')) active_slaves = self.get_bonding_info(bond_port, 'active_slaves') return int(primary_port), [int(slave) for slave in active_slaves] def create_bonded_device(self, mode=0, socket=0, verify_detail=False): """ Create a bonding device with the parameters you specified. """ cmd = "create bonded device %d %d" % (mode, socket) out = self.d_console(cmd) err_fmt = "Create bonded device on mode [%d] socket [%d] failed" self.verify("Created new bonded device" in out, err_fmt% (mode, socket)) fmts = [ "Created new bonded device net_bond_testpmd_[\d] on \(port ", "Created new bonded device net_bonding_testpmd_[\d] on \(port ", "Created new bonded device eth_bond_testpmd_[\d] on \(port "] bond_port = self.get_value_from_str(fmts, "\d+", out) bond_port = int(bond_port) if verify_detail: out = self.d_console("show bonding config %d" % bond_port) self.verify("Bonding mode: %d" % mode in out, "Bonding mode display error when create bonded device") self.verify("Slaves: []" in out, "Slaves display error when create bonded device") self.verify("Active Slaves: []" in out, "Active Slaves display error when create bonded device") self.verify("Primary: []" not in out, "Primary display error when create bonded device") out = self.d_console("show port info %d" % bond_port) self.verify("Connect to socket: %d" % socket in out, "Bonding port connect socket error") self.verify("Link status: down" in out, "Bonding port default link status error") self.verify("Link speed: 0 Mbps" in out, "Bonding port default link speed error") return bond_port def add_slave(self, bond_port, invert_verify=False, expected_str='', *slave_ports): """ Add ports into the bonding device as slaves. """ if len(slave_ports) <= 0: utils.RED("No port exist when add slave to bonded device") for slave_id in slave_ports: cmd = "add bonding slave %d %d" % (slave_id, bond_port) out = self.d_console(cmd) if expected_str: self.verify(expected_str in out, "message <{0}> is missing".format(expected_str)) slaves = self.get_bonding_info(bond_port, 'slaves') if not invert_verify: self.verify(str(slave_id) in slaves, "Add port as bonding slave failed") else: err = "Add port as bonding slave successfully,should fail" self.verify(str(slave_id) not in slaves, err) def remove_slaves(self, bond_port, invert_verify=False, *slave_port): """ Remove the specified slave port from the bonding device. """ if len(slave_port) <= 0: msg = "No port exist when remove slave from bonded device" self.logger.error(msg) for slave_id in slave_port: cmd = "remove bonding slave %d %d" % (int(slave_id), bond_port) self.d_console(cmd) slaves = self.get_bonding_info(bond_port, 'slaves') if not invert_verify: self.verify(str(slave_id) not in slaves, "Remove slave to fail from bonding device") else: err = ( "Remove slave successfully from bonding device, " "should be failed") self.verify(str(slave_id) in slaves, err) def remove_all_slaves(self, bond_port): """ Remove all slaves of specified bound device. """ all_slaves = self.get_bonding_info(bond_port, 'slaves') if not all_slaves: return all_slaves = all_slaves.split() if len(all_slaves) == 0: return self.remove_slaves(bond_port, False, *all_slaves) def set_primary_slave(self, bond_port, slave_port, invert_verify=False): """ Set the primary slave for the bonding device. """ cmd = "set bonding primary %d %d" % (slave_port, bond_port) self.d_console(cmd) out = self.get_bonding_info(bond_port, 'primary') if not invert_verify: self.verify(str(slave_port) in out, "Set bonding primary port failed") else: err = "Set bonding primary port successfully, should not success" self.verify(str(slave_port) not in out, err) def set_bonding_mode(self, bond_port, mode): """ Set the bonding mode for port_id. """ cmd = "set bonding mode %d %d" % (mode, bond_port) self.d_console(cmd) mode_value = self.get_bonding_info(bond_port, 'mode') self.verify(str(mode) in mode_value, "Set bonding mode failed") def set_bonding_mac(self, bond_port, mac): """ Set the MAC for the bonding device. """ cmd = "set bonding mac_addr %s %s" % (bond_port, mac) self.d_console(cmd) new_mac = self.get_port_mac(bond_port) self.verify(new_mac == mac, "Set bonding mac failed") def get_port_mac(self, bond_port, query_type): bond_port_mac = self.get_port_info(bond_port, query_type) return bond_port_mac def set_bonding_balance_policy(self, bond_port, policy): """ Set the balance transmit policy for the bonding device. """ cmd = "set bonding balance_xmit_policy %d %s" % (bond_port, policy) self.d_console(cmd) new_policy = self.get_bonding_info(bond_port, 'balance_policy') policy = "BALANCE_XMIT_POLICY_LAYER" + policy.lstrip('l') self.verify(new_policy == policy, "Set bonding balance policy failed") @property def is_perf(self): return self.parent._enable_perf