From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id EFA564CA0 for ; Mon, 21 Jan 2019 08:19:40 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Jan 2019 23:19:40 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,502,1539673200"; d="scan'208";a="109786486" Received: from fmsmsx108.amr.corp.intel.com ([10.18.124.206]) by orsmga006.jf.intel.com with ESMTP; 20 Jan 2019 23:19:39 -0800 Received: from fmsmsx157.amr.corp.intel.com (10.18.116.73) by FMSMSX108.amr.corp.intel.com (10.18.124.206) with Microsoft SMTP Server (TLS) id 14.3.408.0; Sun, 20 Jan 2019 23:19:38 -0800 Received: from shsmsx108.ccr.corp.intel.com (10.239.4.97) by FMSMSX157.amr.corp.intel.com (10.18.116.73) with Microsoft SMTP Server (TLS) id 14.3.408.0; Sun, 20 Jan 2019 23:19:38 -0800 Received: from shsmsx104.ccr.corp.intel.com ([169.254.5.159]) by SHSMSX108.ccr.corp.intel.com ([169.254.8.85]) with mapi id 14.03.0415.000; Mon, 21 Jan 2019 15:19:36 +0800 From: "Chen, Zhaoyan" To: "Mo, YufengX" , "dts@dpdk.org" CC: "Mo, YufengX" , "Tu, Lijuan" , "Chen, Zhaoyan" Thread-Topic: [dts] [PATCH V1 2/6] pmd_bonded_8023ad: upload automation script Thread-Index: AQHT/VizkoZ8YoenV0eRERrMcU0R9qW6uE6A Date: Mon, 21 Jan 2019 07:19:36 +0000 Message-ID: <9DEEADBC57E43F4DA73B571777FECECA41C12148@SHSMSX104.ccr.corp.intel.com> References: <1528263513-26500-1-git-send-email-yufengx.mo@intel.com> <1528263513-26500-3-git-send-email-yufengx.mo@intel.com> In-Reply-To: <1528263513-26500-3-git-send-email-yufengx.mo@intel.com> Accept-Language: zh-CN, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 11.0.400.15 dlp-reaction: no-action x-originating-ip: [10.239.127.40] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dts] [PATCH V1 2/6] pmd_bonded_8023ad: upload automation script X-BeenThere: dts@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: test suite reviews and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 21 Jan 2019 07:19:42 -0000 Yufeng, - Please extract the common functions into common file and share between ea= ch bond test suite. - Remove "Switch" related code.=20 Regards, Zhaoyan Chen > -----Original Message----- > From: dts [mailto:dts-bounces@dpdk.org] On Behalf Of yufengx.mo@intel.com > Sent: Wednesday, June 6, 2018 1:38 PM > To: dts@dpdk.org > Cc: Mo, YufengX > Subject: [dts] [PATCH V1 2/6] pmd_bonded_8023ad: upload automation script >=20 > From: yufengmx >=20 >=20 > This automation script is for pmd bonded 8023ad feature. >=20 > IEEE 802.3ad Dynamic link aggregation. Creates aggregation groups that s= hare > the same speed and duplex settings. Utilizes all slaves in the active > aggregator according to the 802.3ad specification. Slave selection for ou= tgoing > traffic is done according to the transmit hash policy. >=20 > Signed-off-by: yufengmx > --- > tests/TestSuite_pmd_bonded_8023ad.py | 2147 > ++++++++++++++++++++++++++++++++++ > 1 file changed, 2147 insertions(+) > create mode 100644 tests/TestSuite_pmd_bonded_8023ad.py >=20 > diff --git a/tests/TestSuite_pmd_bonded_8023ad.py > b/tests/TestSuite_pmd_bonded_8023ad.py > new file mode 100644 > index 0000000..b9aa3f4 > --- /dev/null > +++ b/tests/TestSuite_pmd_bonded_8023ad.py > @@ -0,0 +1,2147 @@ > +# BSD LICENSE > +# > +# Copyright(c) 2010-2018 Intel Corporation. All rights reserved. > +# 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. > + > +import os > +import time > +import re > +import random > +import inspect > +import struct > +import socket > +from socket import htons, htonl > + > +from packet import Packet, NVGRE, IPPROTO_NVGRE > +from scapy.sendrecv import sendp > +from scapy.utils import wrpcap, rdpcap, hexstr > + > +import utils > +from test_case import TestCase > +from exception import TimeoutException, SwitchException, VerifyFailure > +from settings import TIMEOUT > +from pmd_output import PmdOutput > +from settings import HEADER_SIZE > +from serializer import Serializer > + > +SOCKET_0 =3D 0 > +SOCKET_1 =3D 1 > +MODE_LACP =3D 4 > +FRAME_SIZE_64 =3D 64 > + > +#-------------------------------------------------- > +# use for debug > +from pprint import pprint, pformat > +from functools import wraps > +import traceback > +import pdb > + > +import threading > + > +class DaemonThread(threading.Thread): > + THREAD_TIMEOUT_MAX =3D 1e10 > + > + def __init__(self, func, name=3DNone, **kwargs): > + super(DaemonThread, self).__init__() > + self._is_start =3D threading.Event() > + self._is_stopped =3D threading.Event() > + self.func =3D func > + self.daemon =3D True > + self.name =3D name or self.__class__.__name__ > + self.kwargs =3D kwargs > + self.start() > + > + def on_crash(self, msg, *fmt, **kwargs): > + #print(msg.format(*fmt), file=3Dsys.stderr) > + print msg.format(*fmt) > + exc_info =3D sys.exc_info() > + try: > + traceback.print_exception(exc_info[0], > + exc_info[1], > + exc_info[2], > + None, > + sys.stderr) > + finally: > + del(exc_info) > + > + def run(self): > + start_set =3D self._is_start.is_set > + while not start_set(): > + time.sleep(0.1) > + try: > + try: > + self.func(**self.kwargs) > + except Exception as exc: > + try: > + self.on_crash('{0!r} crashed: {1!r}', > + self.name, > + exc) > + self._set_stopped() > + finally: > + # exiting by normal means won't work > + os._exit(1) > + finally: > + self._set_stopped() > + > + def _set_stopped(self): > + try: > + self._is_stopped.set() > + except TypeError: > + # we lost the race at interpreter shutdown, > + # so gc collected built-in modules. > + pass > + > + def activate(self): > + """enter main executing loop""" > + self._is_start.set() > + > + def stop(self): > + """Graceful shutdown.""" > + self._is_stopped.wait() > + if self.is_alive(): > + self.join(self.THREAD_TIMEOUT_MAX) > + > +############# > + > +############# > +class TestBonding8023AD(TestCase): > + AGG_MODES =3D ["bandwidth", "stable", "count"] > + DEDICATED_QUEUES =3D ['disable', 'enable'] > + # > + # On tester platform, packet transmission > + # > + def get_stats(self, portid, flow): > + """ > + get testpmd port statistic > + """ > + _portid =3D int(portid) if isinstance(portid, (str, unicode)) el= se portid > + info =3D self.testpmd.get_pmd_stats(_portid) > + _kwd =3D ["-packets", "-missed", "-bytes"] > + kwd =3D map(lambda x: flow.upper() + x, _kwd) > + result =3D [int(info[item]) for item in kwd] > + > + return result > + > + def config_tester_port(self, port_name, status): > + """ > + Do some operations to the network interface port, > + such as "up" or "down". > + """ > + if self.tester.get_os_type() =3D=3D 'freebsd': > + self.tester.admin_ports(port_name, status) > + else: > + eth =3D self.tester.get_interface(port_name) > + self.tester.admin_ports_linux(eth, status) > + time.sleep(5) > + > + def config_tester_port_by_number(self, number, status): > + # stop slave link by force > + cmd =3D "port stop %d"%number > + self.d_console(cmd) > + # stop peer port on tester > + port_name =3D self.tester.get_local_port(self.dut_ports[number]) > + self.config_tester_port( port_name, status) > + time.sleep(5) > + cur_status =3D self.get_port_info(number, 'link_status') > + self.logger.info("port {0} is [{1}]".format(number, cur_status)) > + if cur_status !=3D status: > + self.logger.warning("expected status is [{0}]".format(status= )) > + > + def mac_str_to_int(self, mac_str): > + """ > + convert the MAC type from the string into the int. > + """ > + mac_hex =3D '0x' > + for mac_part in mac_str.split(':'): > + mac_hex +=3D 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 =3D hex(mac_int)[2:] > + b =3D [] > + [b.append(temp[n:n+2]) for n in range(len(temp)) if n % 2 =3D=3D= 0 ] > + new_mac =3D ":".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 =3D 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 =3D socket.inet_ntoa(struct.pack('I', socket.htonl(ip_int= ))) > + return ip_str > + > + def increase_ip(self, ip, step=3D1): > + ''' ip: string format ''' > + _ip_int =3D self.ip_str_to_int(ip) > + new_ip =3D self.ip_int_to_str(_ip_int + step) > + return new_ip > + > + def increase_mac(self, mac, step=3D1): > + ''' mac: string format ''' > + _mac_int =3D self.mac_str_to_int(mac) > + new_mac =3D self.mac_int_to_str(_mac_int+step) > + return new_mac > + > + def increase_port(self, port, step=3D1): > + ''' port: int format ''' > + new_port =3D port + step > + return new_port > + > + def increase_mac_ip_port(self, step=3D1): > + # get src layer setting > + ori_config =3D ('52:00:00:00:00:03', '10.239.129.65', 61) > + mac, ip, port =3D ori_config > + return (self.increase_mac(mac, step), > + self.increase_ip(ip, step), > + self.increase_port(port, step)) > + > + def set_stream2(self, stm_names=3DNone): > + ''' using packet.py module to create a stream ''' > + #---------------------------------------------------------------= ------- > + # set streams for traffic > + pkt_configs =3D { > + # UDP_1: > + # Frame Data/Protocols: Ethernet 2 0800, IPv4,UDP/IP, Fixed 6= 4. > + # IPv4 Header Page: Dest Address: 2.2.2.7 Src Address: 2.2.2= .3 > + # UDP Header: Src Port: 32 Dest Port: 33 > + # > + # Stream Control: Stop after this Stream, Packet Count 32. > + # > + 'UDP_1': { > + 'type': 'TCP', > + 'pkt_layers': { > + #'ether': {'src': srcmac, 'dst': nutmac}, > + 'ipv4': {'src': '2.2.2.3', 'dst': '2.2.2.7'}, > + 'udp': {'src': 32, 'dst': 33}, > + 'raw': {'payload': ['58'] * self.get_pkt_len('udp')}}}, > + } > + > + # create packet for send > + streams =3D [] > + for stm_name in stm_names: > + if stm_name not in pkt_configs.keys(): > + continue > + values =3D pkt_configs[stm_name] > + # keep a copy of pcap for debug > + savePath =3D os.sep.join([self.target_source, > + "pkt_{0}.pcap".format(stm_name)]) > + pkt_type =3D values.get('type') > + pkt_layers =3D values.get('pkt_layers') > + pkt =3D Packet(pkt_type=3Dpkt_type) > + 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 get_pkt_len(self, pkt_type): > + # packet size > + frame_size =3D FRAME_SIZE_64 > + headers_size =3D sum(map(lambda x: HEADER_SIZE[x], > + ['eth', 'ip', pkt_type])) > + pktlen =3D frame_size - headers_size > + return pktlen > + > + def parse_ether_ip(self, dst_port, **ether_ip): > + """ > + ether_ip: > + 'ether':'dst_mac':False > + 'src_mac':"52:00:00:00:00:00" > + 'dot1q': 'vlan':1 > + 'ip': 'dst_ip':"10.239.129.88" > + 'src_ip':"10.239.129.65" > + 'udp': 'dst_port':53 > + 'src_port':53 > + """ > + ret_ether_ip =3D {} > + ether =3D {} > + dot1q =3D {} > + ip =3D {} > + udp =3D {} > + > + try: > + dut_dst_port =3D self.dut_ports[dst_port] > + except Exception, e: > + dut_dst_port =3D dst_port > + # create src/dst mac address > + if not ether_ip.get('ether'): > + ether['dst_mac'] =3D self.dut.get_mac_address(dut_dst_port) > + ether['src_mac'] =3D "52:00:00:00:00:00" > + else: > + # dst > + if not ether_ip['ether'].get('dst_mac'): > + ether['dst_mac'] =3D self.dut.get_mac_address(dut_dst_po= rt) > + else: > + ether['dst_mac'] =3D ether_ip['ether']['dst_mac'] > + # src > + if not ether_ip['ether'].get('src_mac'): > + ether['src_mac'] =3D "52:00:00:00:00:00" > + else: > + ether['src_mac'] =3D ether_ip["ether"]["src_mac"] > + # create src/dst dot1q > + if not ether_ip.get('dot1q'): > + pass > + else: > + if not ether_ip['dot1q'].get('vlan'): > + dot1q['vlan'] =3D '1' > + else: > + dot1q['vlan'] =3D ether_ip['dot1q']['vlan'] > + # create src/dst ip address > + if not ether_ip.get('ip'): > + ip['dst_ip'] =3D "10.239.129.88" > + ip['src_ip'] =3D "10.239.129.65" > + else: > + if not ether_ip['ip'].get('dst_ip'): > + ip['dst_ip'] =3D "10.239.129.88" > + else: > + ip['dst_ip'] =3D ether_ip['ip']['dst_ip'] > + if not ether_ip['ip'].get('src_ip'): > + ip['src_ip'] =3D "10.239.129.65" > + else: > + ip['src_ip'] =3D ether_ip['ip']['src_ip'] > + # create src/dst port number > + if not ether_ip.get('udp'): > + udp['dst_port'] =3D 53 > + udp['src_port'] =3D 53 > + else: > + if not ether_ip['udp'].get('dst_port'): > + udp['dst_port'] =3D 53 > + else: > + udp['dst_port'] =3D ether_ip['udp']['dst_port'] > + if not ether_ip['udp'].get('src_port'): > + udp['src_port'] =3D 53 > + else: > + udp['src_port'] =3D ether_ip['udp']['src_port'] > + > + ret_ether_ip['ether'] =3D ether > + ret_ether_ip['dot1q'] =3D dot1q > + ret_ether_ip['ip'] =3D ip > + ret_ether_ip['udp'] =3D udp > + > + return ret_ether_ip > + > + def set_stream(self, dst_port, src_port=3DFalse, frame_size=3DFRAME_= SIZE_64, > + pkt_type=3D'tcp', **slaves): > + # get dst layer setting > + dst_mac =3D self.get_port_info(dst_port, 'mac') > + destport =3D 53 > + nutmac =3D dst_mac > + destip =3D '10.239.129.88' > + # packet size > + pktlen =3D self.get_pkt_len(pkt_type) > + self.packet_types =3D {} > + for packet_id in range(len(slaves['active'])): > + # src config > + srcmac, srcip, srcport =3D self.increase_mac_ip_port(packet_= id) > + # config layer format > + pkt =3D Packet(pkt_type=3Dpkt_type.upper()) > + pkt.config_layer('ether', {'src': srcmac, 'dst': nutmac}) > + pkt.config_layer('ipv4', {'src': srcip, 'dst': destip}) > + pkt.config_layer('raw', {'payload': ['58'] * pktlen}) > + pkt.config_layer(pkt_type, {'src': srcport, 'dst': destport}= ) > + # generate stream > + self.packet_types[packet_id] =3D pkt > + # save a pcap file for debug convenience > + savePath =3D os.sep.join([self.dut.base_dir, > + "port_{0}.pcap".format(str(packet_id= ))]) > + pkt.pktgen.write_pcap(savePath) > + > + def send_packet_quick(self, tx_iface, count=3D1, interval=3D0.01): > + for pkt_id in sorted(self.packet_types.keys()): > + pkt =3D self.packet_types[pkt_id].pktgen.pkt > + sendp(pkt, iface=3Dtx_iface, inter=3Dinterval, verbose=3DFal= se, > + count=3Dcount) > + wait_time =3D 0.0001 > + > + def send_pkt_multi_stream(self, intf, count): > + sendp(self.pkt, iface=3Dintf, count=3Dcount) > + > + def send_packets_by_ixia(self, intf, count=3D1): > + send_pkts =3D [] > + self.tgen_input =3D [] > + tgen_input =3D self.tgen_input > + # generate packet contain multi stream > + for pkt in self.packet_types.values(): > + send_pkts.append(pkt.pktgen.pkt) > + ixia_pkt =3D os.sep.join([self.dut.base_dir, 'lacp_tx.pcap']) > + wrpcap(ixia_pkt, send_pkts) > + #---------------------------------------------------------------= - > + # set packet for send > + # pause frame basic configuration > + pause_time =3D 65535 > + pause_rate =3D 0.50 > + # run ixia testing > + frame_size =3D 64 > + # calculate number of packets > + expect_pps =3D self.wirespeed(self.nic, frame_size, 1) * 1000000= .0 > + # get line rate > + linerate =3D expect_pps * (frame_size + 20) * 8 > + # calculate default sleep time for one pause frame > + sleep =3D (1 / linerate) * pause_time * 512 > + # calculate packets dropped in sleep time > + self.n_pkts =3D int((sleep / (1 / expect_pps)) * (1 / pause_rate= )) > + #---------------------------------------------------------------= - > + tester_port =3D self.tester.get_local_port(self.dut_ports[0]) > + tgen_input.append((tester_port, > + tester_port, > + ixia_pkt)) > + # run latency stat statistics > + rate_percent =3D self.rate_percent > + self.tester.loop_traffic_generator_throughput(tgen_input, > + rate_percent) > + > + def stop_ixia(self, data_types=3D'packets'): > + # get ixia statistics > + line_rate =3D self.tester.get_port_line_rate() > + rx_bps, rx_pps =3D \ > + self.tester.stop_traffic_generator_throughput_loop(self.tgen_inp= ut) > + output =3D self.tester.traffic_get_port_stats(self.tgen_input) > + self.cur_data['ixia statistics'] =3D [] > + append =3D 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 send_packets(self, intf, pkts=3DNone, interval=3D0.01 ,count=3D1= ): > + send_pkts =3D [] > + for pkt in pkts: > + send_pkts.append(pkt.pktgen.pkt) > + sendp(send_pkts, iface=3Dintf, inter=3Dinterval, > + verbose=3DFalse, count=3Dcount) > + > + def send_multi_packet_quick(self, tx_iface, count=3D1): > + self.send_packets(tx_iface, self.packet_types.values(), count=3D= count) > + # > + # On dut, dpdk testpmd > + # > + def preset_testpmd(self, core_mask, options=3D'', eal_param=3D''): > + try: > + self.testpmd.start_testpmd( core_mask, param=3D' '.join(opti= ons), > + eal_param=3Deal_param) > + # add exception for debug usage > + except TimeoutException: > + try: > + self.check_process_exist() # used for debug > + except Exception as e: > + self.testpmd_status =3D 'close' > + finally: > + pass > + msg =3D "execute '{0}' timeout".format(item[0]) > + self.logger.error(msg_pipe(timeout)) > + raise TimeoutException(msg) > + finally: > + pass > + > + time.sleep(20) > + # check if testpmd has bootep up > + if not self.check_process_status(): > + raise VerifyFailure("testpmd boot up failed") > + else: > + self.logger.info("testpmd boot up sucessful") > + self.d_console(self.preset_testpmd_cmds) > + self.preset_testpmd_cmds =3D list() > + time.sleep(1) > + > + def check_process_status(self, process_name=3D'testpmd'): > + cmd =3D "ps aux | grep -i %s | grep -v grep | awk {'print $2'}"%= ( > + process_= name) > + out =3D self.dut.alt_session.send_expect(cmd, "# ", 10) > + status =3D True if out !=3D "" else False > + return status > + # use for debug > + def check_process_exist(self, process_name=3D'testpmd'): > + status =3D self.check_process_status(process_name) > + if not status: > + msg =3D "{0} process quit exceptional".format(process_name) > + out =3D self.dut.session.session.get_output_all() > + self.logger.info(out) > + raise VerifyFailure(msg) > + > + def d_console(self, cmds): > + if len(cmds) =3D=3D 0: > + return > + # check if cmds is string > + if isinstance(cmds, str): > + timeout =3D 10 > + cmds =3D [[cmds, '', timeout]] > + # check if cmds is only one command > + if not isinstance(cmds[0], list): > + cmds =3D [cmds] > + if len(cmds) > 1: > + outputs =3D [] > + else: > + outputs =3D '' > + for item in cmds: > + expected_items =3D item[1] > + if expected_items and isinstance(expected_items, (list, tupl= e)): > + check_output =3D True > + expected_str =3D expected_items[0] or 'testpmd> ' > + else: > + check_output =3D False > + expected_str =3D expected_items or 'testpmd> ' > + timeout =3D int(item[2]) if len(item) =3D=3D 3 else 5 > + #-----------------------------------------------------------= ----- > + # run command on session > + try: > + console =3D self.testpmd.execute_cmd > + msg_pipe =3D self.testpmd.get_output > + output =3D console(item[0], expected_str, timeout) > + output =3D msg_pipe(timeout) if not output else output > + except TimeoutException: > + try: > + self.check_process_exist() # used for debug > + except Exception as e: > + self.testpmd_status =3D 'close' > + finally: > + pass > + msg =3D "execute '{0}' timeout".format(item[0]) > + output =3D out =3D self.dut.session.session.get_output_a= ll() > + self.logger.error(output) > + raise TimeoutException(msg) > + finally: > + pass > + > + if len(cmds) > 1: > + outputs.append(output) > + else: > + outputs =3D output > + if check_output and len(expected_items) >=3D 2: > + self.logger.info(output) > + expected_output =3D expected_items[1] > + check_type =3D True if len(expected_items) =3D=3D 2 \ > + else expected_items[2] > + if check_type and expected_output in output: > + msg =3D "expected '{0}' is in output".format(expecte= d_output) > + self.logger.info(msg) > + elif not check_type and expected_output not in output: > + fmt =3D "unexpected '{0}' is not in output" > + msg =3D fmt.format(expected_output) > + self.logger.info(msg) > + else: > + status =3D "isn't in" if check_type else "is in" > + msg =3D "[{0}] {1} output".format(expected_output, s= tatus) > + self.logger.error(msg) > + raise VerifyFailure(msg) > + > + time.sleep(2) > + return outputs > + > + def start_testpmd(self, eal_option=3D''): > + if self.testpmd_status =3D=3D 'running': > + return > + if self.is_perf: > + options =3D map(lambda x: "--" + x, [ > + # 'burst=3D32', > + # 'rxfreet=3D32', > + # 'mbcache=3D250', > + # 'txpt=3D32', > + # 'rxht=3D8', > + # 'rxwt=3D0', > + # 'txfreet=3D32', > + # 'txrst=3D32', > + # 'txqflags=3D0xf01' > + ]) > + #options =3D '' #TBD > + offloadd =3D '0x1fbf' if self.driver =3D=3D 'i40e' else '0x2= 203f' > + options =3D ["--tx-offloads=3D{0}".format(offloadd)] > + else: > + offloadd =3D '0x1fbf' if self.driver =3D=3D 'i40e' else '0x2= 203f' > + options =3D ["--tx-offloads=3D{0}".format(offloadd)] > + # link eal option and testpmd options > + #options =3D [eal_option, options] if eal_option else [options] > + # boot up testpmd > + hw_mask =3D 'all' > + #hw_mask =3D '1S/4C/1T' > + self.preset_testpmd_cmds =3D ['port stop all', '', 15] > + self.preset_testpmd(hw_mask, options, eal_param=3Deal_option) > + self.testpmd_status =3D 'running' > + > + def stop_testpmd(self): > + time.sleep(1) > + testpmd_cmds =3D[['port stop all', '', 15], > + ['show port stats all', ''], > + ['stop', ''], > + ] > + output =3D self.d_console(testpmd_cmds) > + time.sleep(1) > + return output > + > + def close_testpmd(self): > + if self.testpmd_status =3D=3D 'close': > + return None > + output =3D 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 sucessful") > + self.testpmd_status =3D 'close' > + return output > + > + # > + # On dut, dpdk bonding > + # > + 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 =3D r"(?<=3D%s)%s" % (key_str, regx_str) > + s =3D re.compile(pattern) > + res =3D s.search(string) > + if type(res).__name__ =3D=3D 'NoneType': > + self.logger.warning("{0} hasn't match anything".format(k= ey_str)) > + return ' ' > + else: > + return res.group(0) > + elif isinstance(key_str, (list, tuple)): > + for key in key_str: > + pattern =3D r"(?<=3D%s)%s" % (key, regx_str) > + s =3D re.compile(pattern) > + res =3D s.search(string) > + if type(res).__name__ =3D=3D 'NoneType': > + continue > + else: > + return res.group(0) > + else: > + self.logger.warning("all key_str hasn't match anything") > + return ' ' > + > + # > + # dpdk link bonding > + # > + def _get_detail_from_port_info(self, port_id, args): > + """ > + Get the detail info from the output of pmd cmd > + 'show port info ' > + """ > + key_str, regx_str =3D args > + out =3D self.d_console("show port info %d" % port_id) > + find_value =3D 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 =3D { > + '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: > + return None > + > + def get_bonding_config(self, config_content, args): > + """ > + Get info by executing the command "show bonding config". > + """ > + key_str, regx_str =3D args > + find_value =3D 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 the active slaves of the bonding device which you choose. > + """ > + info =3D None > + > + if isinstance(args[0], (list, tuple)): > + search_args =3D args > + else: > + search_args =3D [args] > + > + for search_args in search_args: > + try: > + info =3D self.get_bonding_config(config_content, search_= args) > + break > + except Exception as e: > + self.logger.info(e) > + finally: > + pass > + else: > + info =3D None > + > + return info > + > + def get_bonding_info(self, bond_port, info_types): > + ''' > + Get the specified port information by its output message format > + ''' > + info_set =3D { > + '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 =3D self.d_console("show bonding config %d" % bon= d_port) > + if isinstance(info_types, (list or tuple)): > + query_values =3D [] > + for info_type in info_types: > + if info_type in info_set.keys(): > + find_value =3D self.get_info_from_bond_config( > + config_content, > + info_set[info_ty= pe]) > + if info_type in ['active_slaves', 'slaves']: > + find_value =3D [value for value in find_value.sp= lit(' ') > + if value] > + else: > + find_value =3D None > + query_values.append(find_value) > + return query_values > + else: > + info_type =3D info_types > + if info_type in info_set.keys(): > + find_value =3D self.get_info_from_bond_config(config_con= tent, > + info_set[inf= o_type]) > + if info_type in ['active_slaves', 'slaves']: > + find_value =3D [value for value in find_value.split(= ' ') > + if value] > + return find_value > + else: > + return None > + > + def get_all_stats(self, unbound_port, rx_tx, bond_port, **slaves): > + """ > + Get all the port stats which the testpmd can display. > + > + :param unbound_port: pmd port id > + :param rx_tx: unbond port stat 'rx' or 'tx' > + :param bond_port: bonding port > + :param slaves: > + 'active' =3D [] > + 'inactive' =3D [] > + """ > + pkt_now =3D {} > + bond_stat =3D 'tx' if rx_tx =3D=3D 'rx' else 'rx' > + if unbound_port: # if unbound_port has not been set, ignore this > + pkt_now[unbound_port] =3D \ > + [int(_) for _ in self.get_stats(unbound_port, rx_tx)] > + > + pkt_now[bond_port] =3D \ > + [int(_) for _ in self.get_stats(bond_port, bond_stat)] > + for slave in slaves['active']: > + pkt_now[slave] =3D [int(_) for _ in self.get_stats(slave, bo= nd_stat)] > + for slave in slaves['inactive']: > + pkt_now[slave] =3D [int(_) for _ in self.get_stats(slave, bo= nd_stat)] > + > + return pkt_now > + > + def get_active_slaves(self, primary_slave, bond_port): > + self.config_tester_port_by_number(primary_slave, "down") > + primary_port =3D self.get_bonding_info(bond_port, 'primary') > + active_slaves =3D self.get_bonding_info(bond_port, 'active_slave= s') > + if active_slaves and primary_port in active_slaves: > + active_slaves.remove(primary_port) > + else: > + fmt =3D "primary port <{0}> isn't in active slaves list" > + raise VerifyFailure(fmt.format(primary_port)) > + > + return primary_port, active_slaves > + > + def create_bonded_device(self, mode=3D0, socket=3D0, verify_detail= =3DFalse): > + """ > + Create a bonding device with the parameters you specified. > + """ > + cmd =3D "create bonded device %d %d" % (mode, socket) > + out =3D self.d_console(cmd) > + err_fmt =3D "Create bonded device on mode [%d] socket [%d] faile= d" > + self.verify("Created new bonded device" in out, > + err_fmt% (mode, socket)) > + fmts =3D [ > + "Created new bonded device net_bond_testpmd_[\d] on \(port = ", > + "Created new bonded device net_bonding_testpmd_[\d] on \(po= rt ", > + "Created new bonded device eth_bond_testpmd_[\d] on \(port = "] > + bond_port =3D self.get_value_from_str(fmts, "\d+", out) > + bond_port =3D int(bond_port) > + > + if verify_detail: > + out =3D self.d_console("show bonding config %d" % bond_port) > + self.verify("Bonding mode: %d" % mode in out, > + "Bonding mode display error when create bonded d= evice") > + 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 =3D 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 start_ports(self, port=3D'all'): > + """ > + Start a port which the testpmd can see. > + """ > + timeout =3D 12 if port=3D=3D'all' else 5 > + # to avoid lsc event message interfere normal status > + cmds =3D[] > + cmds.append(["port start %s" % str(port), " ", timeout]) > + cmds.append([" ", '', timeout]) > + self.d_console(cmds) > + > + def add_slave(self, bond_port, invert_verify=3DFalse, expected_str= =3D'', > + *slave_ports): > + """ > + Add the ports into the bonding device as slaves. > + """ > + if len(slave_ports) <=3D 0: > + utils.RED("No port exist when add slave to bonded device") > + for slave_id in slave_ports: > + cmd =3D "add bonding slave %d %d" % (slave_id, bond_port) > + out =3D self.d_console(cmd) > + if expected_str: > + self.verify(expected_str in out, > + "message <{0}> is missiong".format(expected_= str)) > + slaves =3D 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 =3D "Add port as bonding slave successfully,should f= ail" > + self.verify(str(slave_id) not in slaves, err) > + > + def remove_slaves(self, bond_port, invert_verify=3DFalse, *slave_por= t): > + """ > + Remove the specified slave port from the bonding device. > + """ > + if len(slave_port) <=3D 0: > + utils.RED("No port exist when remove slave from bonded devic= e") > + for slave_id in slave_port: > + cmd =3D "remove bonding slave %d %d" % (int(slave_id), bond_= port) > + self.d_console(cmd) > + slaves =3D 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 =3D ("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 =3D self.get_bonding_info(bond_port, 'slaves') > + all_slaves =3D all_slaves.split() > + if len(all_slaves) =3D=3D 0: > + pass > + else: > + self.remove_slaves(bond_port, False, *all_slaves) > + > + def set_primary_slave(self, bond_port, slave_port, invert_verify=3DF= alse): > + """ > + Set the primary slave for the bonding device. > + """ > + cmd =3D "set bonding primary %d %d" % (slave_port, bond_port) > + self.d_console(cmd) > + out =3D 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 =3D "Set bonding primary port successfully,should not su= ccess" > + self.verify(str(slave_port) not in out, err) > + > + def set_bonding_mode(self, bond_port, mode): > + """ > + Set the mode for the bonding device. > + """ > + cmd =3D "set bonding mode %d %d" % (mode, bond_port) > + self.d_console(cmd) > + mode_value =3D 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 =3D "set bonding mac_addr %s %s" % (bond_port, mac) > + self.d_console(cmd) > + new_mac =3D self.get_port_mac(bond_port) > + self.verify(new_mac =3D=3D mac, "Set bonding mac failed") > + > + def set_bonding_balance_policy(self, bond_port, policy): > + """ > + Set the balance transmit policy for the bonding device. > + """ > + cmd =3D "set bonding balance_xmit_policy %d %s" % (bond_port, po= licy) > + self.d_console(cmd) > + new_policy =3D self.get_bonding_info(bond_port, 'balance_policy'= ) > + policy =3D "BALANCE_XMIT_POLICY_LAYER" + policy.lstrip('l') > + self.verify(new_policy =3D=3D policy, "Set bonding balance polic= y failed") > + > + def set_8023ad_agg_mode(self, bond_port, mode=3D"bandwidth"): > + """ > + set bonding agg_mode > + > + Set 802.11AD Aggregator Mode > + """ > + cmd =3D "set bonding agg_mode %d %s" % (bond_port, mode) > + self.d_console(cmd) > + cur_mode =3D self.get_bonding_info(bond_port, 'agg_mode') > + if mode =3D=3D cur_mode: > + fmt =3D "set bonding agg_mode <{0}> successfully" > + self.logger.info(fmt.format(mode)) > + else: > + msg =3D "failed to set bonding agg_mode <{0}>".format(mode) > + self.logger.error(msg) > + raise VerifyFailure(msg) > + > + def get_8023ad_agg_mode(self, bond_port): > + """ > + get bonding agg_mode > + > + get 802.11AD Aggregator Mode > + """ > + cur_mode =3D self.get_bonding_info(bond_port, 'agg_mode') > + return cur_mode > + > + def set_8023ad_dedicated_queue(self, bond_port, status=3D'disable'): > + """ > + set 802.11AD dedicated_queues status > + enable|disable > + """ > + cmds =3D[ ["set bonding lacp dedicated_queues %s %s" % (bond_por= t, > + status), > + ['', 'port %s failed'%bond_port, False], 2], > + ] > + out =3D self.d_console(cmds) > + # when set 'hw' > + if status =3D=3D 'enable': > + expected_msg =3D 'queues for LACP control packets enabled' > + err_fmt =3D "link bonding mode 4 (802.3ad) set {0} failed" > + self.verify(expected_msg in out, err_fmt.format(status)) > + elif status =3D=3D 'disable': > + expected_msg =3D 'queues for LACP control packets disabled' > + err_fmt =3D "link bonding mode 4 (802.3ad) set {0} failed" > + self.verify(expected_msg in out, err_fmt.format(status)) > + else: > + pass > + > + def get_8023ad_dedicated_queues(self, bond_port): > + """ > + get 802.11AD dedicated_queues status > + enable|disable > + """ > + status =3D self.get_bonding_info(bond_port, 'dedicated_queues') > + return status > + > + def set_bond_port_ready(self, tx_port, bond_port): > + # there is a issue of core dump, 2017.0822 > + cmd=3D "set portlist {0},{1}".format(tx_port, bond_port) > + self.d_console(cmd) > + # for port link up is slow and unstable, > + # every port should start one by one > + start_fmt =3D "port start {0}".format > + cmds =3D [] > + port_num =3D len(self.dut_ports) > + for cnt in range(port_num): > + cmds.append([start_fmt(cnt), '', 5]) > + self.d_console(cmds) > + time.sleep(10) > + self.d_console([start_fmt(self.bond_port), '', 15]) > + time.sleep(5) > + self.d_console(["start", '', 10]) > + self.logger.info("set bond port ready done !!!") > + > + def set_8023ad_dedicated_traffic(self): > + # If RX fing full free lacpdu message and drop packet > + pass > + > + def set_8023ad_bonded(self, slaves, bond_mode): > + ''' set stacked bonded mode for the specified bonding mode ''' > + specified_socket =3D SOCKET_0 > + # create bonded device 1, add slaves in it > + bond_port =3D self.create_bonded_device(bond_mode, specified_soc= ket) > + # when no slave attached, mac should be 00:00:00:00:00:00 > + self.bonding_8023ad_check_macs_without_slaves(bond_port) > + # add slave > + self.add_slave(bond_port, False, '', *slaves) > + # check if master bonding/each slaves queue configuration is the= same. > + ports =3D slaves + [bond_port] > + return bond_port > + > + def run_8023ad_pre(self, slaves, bond_mode): > + bond_port =3D self.set_8023ad_bonded(slaves, bond_mode) > + # should set port to stop and make sure port re-sync with parter > + cmds =3D ["port stop all", '', 15] > + self.d_console(cmds) > + time.sleep(2) > + cmds =3D ["port start all", '', 10] > + self.d_console(cmds) > + time.sleep(2) > + return bond_port > + > + def get_bond_port_mac(self, bond_port, query_type): > + bond_port_mac =3D self.get_port_info(bond_port, query_type) > + return bond_port_mac > + > + def bonding_8023ad_check_macs_without_slaves(self, bond_port): > + ''' check if bonded device's mac is one of its slaves macs ''' > + query_type =3D 'mac' > + bond_port_mac =3D self.get_bond_port_mac(bond_port, query_type) > + default_mac =3D '00:00:00:00:00:00' > + if bond_port_mac =3D=3D default_mac: > + msg =3D "bond port default mac is [{0}]".format(default_mac) > + self.logger.info(msg) > + else: > + fmt =3D "bond port default mac is [{0}], not expected mac" > + msg =3D fmt.format(bond_port_mac) > + self.logger.warning(msg) > + > + def bonding_8023ad_check_macs(self, slaves, bond_port): > + ''' check if bonded device's mac is one of its slaves macs ''' > + query_type =3D 'mac' > + bond_port_mac =3D self.get_bond_port_mac(bond_port, query_type) > + if bond_port_mac =3D=3D '00:00:00:00:00:00': > + msg =3D "bond port hasn't set mac address" > + self.logger.info(msg) > + return > + > + for port_id in slaves: > + slave_mac =3D self.get_port_info(port_id, query_type) > + if bond_port_mac =3D=3D slave_mac: > + fmt =3D "bonded device's mac is slave [{0}]'s mac [{1}]" > + msg =3D fmt.format(port_id, slave_mac) > + self.logger.info(msg) > + return port_id > + else: > + fmt =3D "bonded device's current mac [{0}] " + \ > + "is not one of its slaves macs" > + msg =3D fmt.format(bond_port_mac) > + # it is not supported by dpdk, but supported by linux normal > + # bodning/lacp tool > + self.logger.warning('bonding_8023ad_check_macs: ' + msg) > + > + def check_bonded_device_mac_change(self, slaves, bond_port): > + remove_slave =3D 0 > + cur_slaves =3D slaves[1:] > + self.remove_slaves(bond_port, *[remove_slave]) > + self.bonding_8023ad_check_macs(cur_slaves, bond_port) > + > + def check_slave_mac_restore(self, slave, bond): > + query_type =3D 'mac' > + slave_old_mac =3D self.get_bond_port_mac(slave, query_type) > + self.remove_slave_from_bonding_device(bond, False, > + self.dut_ports[2]) > + > + def check_bonded_device_start(self, bond_port): > + cmds =3D [["port stop all", '', 15]] > + portList =3D [bond_port] > + cmds +=3D[["port start %s"%bond_port, '', 10], > + ["start", [' ', 'core dump', False]]] > + self.d_console(cmds) > + time.sleep(2) > + return bond_port > + > + def check_bonded_device_up_down(self, bond_port): > + # stop bonded device > + cmds =3D ["port stop {0}".format(bond_port), ''] > + self.d_console(cmds) > + status =3D self.get_port_info(bond_port, 'link_status') > + if status !=3D 'down': > + msg =3D "bond port {0} fail to set down".format(bond_port) > + self.logger.error(msg) > + raise VerifyFailure(msg) > + else: > + msg =3D "bond port {0} set down successful !".format(bond_po= rt) > + self.logger.info(msg) > + # start bond port > + cmds =3D ["port start {0}".format(bond_port), '', 10] > + self.d_console(cmds) > + status =3D self.get_port_info(bond_port, 'link_status') > + if status !=3D 'up': > + msg =3D "bond port {0} fail to set up".format(bond_port) > + self.logger.error(msg) > + raise VerifyFailure(msg) > + else: > + msg =3D "bond port {0} set up successful !".format(bond_port= ) > + self.logger.info(msg) > + > + def check_bonded_device_promisc_mode(self, slaves, bond_port): > + # close bonded device promiscuous mode > + cmds =3D [["set promisc {0} off".format(bond_port), '']] > + time.sleep(3) > + self.d_console(cmds) > + status =3D self.get_port_info(bond_port, 'promiscuous_mode') > + if status !=3D 'disabled': > + fmt =3D "bond port {0} fail to set promiscuous mode disabled= " > + msg =3D fmt.format(bond_port) > + self.logger.warning(msg) > + else: > + fmt =3D "bond port {0} set promiscuous mode disabled success= ful !" > + msg =3D fmt.format(bond_port) > + self.logger.info(msg) > + # check slave promiscuous status > + for port_id in slaves: > + status =3D self.get_port_info(port_id, 'promiscuous_mode') > + if status !=3D 'disabled': > + fmt =3D ("slave port {0} promiscuous mode " > + "isn't the same as bond port 'disabled'") > + msg =3D fmt.format(port_id) > + self.logger.error(msg) > + raise VerifyFailure(msg) > + else: > + fmt =3D "slave port {0} promiscuous mode is 'disabled' t= oo" > + msg =3D fmt.format(port_id) > + self.logger.info(msg) > + # open bonded device promiscuous mode > + cmds =3D [["set promisc {0} on".format(bond_port), '']] > + self.d_console(cmds) > + time.sleep(3) > + status =3D self.get_port_info(bond_port, 'promiscuous_mode') > + if status !=3D 'enabled': > + fmt =3D "bond port {0} fail to set promiscuous mode enabled" > + msg =3D fmt.format(bond_port) > + self.logger.error(msg) > + raise VerifyFailure(msg) > + else: > + fmt =3D "bond port {0} set promiscuous mode enabled successf= ul !" > + msg =3D fmt.format(bond_port) > + self.logger.info(msg) > + # check slave promiscuous status > + for port_id in slaves: > + status =3D self.get_port_info(port_id, 'promiscuous_mode') > + if status !=3D 'enabled': > + fmt =3D "slave port {0} promiscuous mode " + \ > + "isn't the same as bond port 'enabled'" > + msg =3D fmt.format(port_id) > + self.logger.error(msg) > + raise VerifyFailure(msg) > + else: > + fmt =3D "slave port {0} promiscuous mode is 'enabled' to= o" > + msg =3D fmt.format(port_id) > + self.logger.info(msg) > + > + def get_agg_mode_fmt(self): > + retStatus =3D False > + # if agg mode has added to cmdline.c > + target_file =3D os.sep.join([self.dut.base_dir, 'app/test-pmd/cm= dline.c']) > + with open(target_file, 'rb') as fp: > + if 'agg_mode' in fp.read(): > + retStatus =3D True > + > + if retStatus: > + agg_config =3D 'agg_mode=3D{0}' > + msg =3D "agg_mode has been merged" > + self.logger.warning(msg) > + #raise VerifyFailure(msg) > + else: > + self.logger.info("has no agg_mode such option") > + agg_config =3D '' > + > + return agg_config > + > + def check_8023ad_agg_modes(self, slaves, bond_mode): > + # check aggregator mode > + #--------------------------- > + check_results =3D [] > + default_agg_mode =3D 'stable' > + for mode in self.AGG_MODES: > + try: > + self.start_testpmd() > + bond_port =3D self.set_8023ad_bonded(slaves, > + bond_mode) > + cur_agg_mode =3D self.get_8023ad_agg_mode(bond_port) > + > + if cur_agg_mode !=3D default_agg_mode: > + fmt =3D ("link bonding mode 4 (802.3ad) default agg = mode " > + "isn't {0}") > + msg =3D fmt.format(default_agg_mode) > + self.logger.warning(msg) > + # ignore default mode > + if mode =3D=3D cur_agg_mode: > + fmt =3D ("link bonding mode 4 (802.3ad) " > + "current agg mode is {0}") > + msg =3D fmt.format(mode) > + self.logger.info(msg) > + continue > + #---------------- > + # set test pmd > + cmds =3D [] > + cmds =3D [["port stop all", '', 15]] > + portList =3D [bond_port] > + cmds +=3D[["port start all", '', 15]] > + self.d_console(cmds) > + #---------------- > + self.set_8023ad_agg_mode(bond_port, mode) > + except Exception as e: > + check_results.append(e); print traceback.format_exc() > + finally: > + self.close_testpmd() > + time.sleep(2) > + #--------------------------- > + if check_results: > + for e in check_results: > + self.logger.error(e) > + raise VerifyFailure('check_8023ad_agg_modes is failed') > + return > + > + def check_8023ad_packet_transmission(self, slaves, bond_mode): > + # check aggregator mode > + #--------------------------- > + check_results =3D [] > + default_agg_mode =3D 'stable' > + for mode in self.AGG_MODES: > + try: > + bond_port =3D self.run_8023ad_pre(slaves, mode) > + # ignore default mode > + if mode =3D=3D default_agg_mode: > + continue > + self.set_8023ad_agg_mode(bond_port, mode) > + # do packet transmission > + except Exception as e: > + check_results.append(e); print traceback.format_exc() > + finally: > + self.close_testpmd() > + time.sleep(2) > + #--------------------------- > + if check_results: > + for e in check_results: > + self.logger.error(e) > + raise VerifyFailure('check_8023ad_packet_transmission is fai= led') > + return > + > + def check_8023ad_dedicated_queues(self, slaves, bond_mode): > + # check aggregator mode > + #--------------------------- > + check_results =3D [] > + default_slow_queue =3D 'unknown' > + for mode in self.DEDICATED_QUEUES: > + try: > + self.start_testpmd() > + bond_port =3D self.set_8023ad_bonded(slaves, bond_mode) > + self.set_8023ad_dedicated_queue(bond_port, mode) > + except Exception as e: > + check_results.append(e); print traceback.format_exc() > + finally: > + self.close_testpmd() > + time.sleep(2) > + #--------------------------- > + if check_results: > + for e in check_results: > + self.logger.error(e) > + raise VerifyFailure('check_8023ad_dedicated_queues is failed= ') > + return > + > + def check_8023ad_dedicated_queues_transmission(self, slaves, bond_mo= de): > + # check aggregator mode > + #--------------------------- > + check_results =3D [] > + default_slow_queue =3D 'unknown' > + for mode in self.DEDICATED_QUEUES: > + try: > + self.start_testpmd() > + bond_port =3D self.set_8023ad_bonded(slaves, > + bond_mode) > + #cur_slow_queue =3D self.get_8023ad_slow_queue(bond_port= ) > + #if cur_slow_queue !=3D default_slow_queue: > + # msg =3D "link bonding mode 4 (802.3ad) default slow= queue > + # isn't {0}".format(default_slow_queue) > + # self.logger.warning(msg) > + # ignore default mode > + #if mode !=3D default_slow_queue: > + self.set_8023ad_agg_mode(bond_port, mode) > + #---------------- > + pass > + except Exception as e: > + check_results.append(e); print traceback.format_exc() > + finally: > + self.close_testpmd() > + time.sleep(2) > + #--------------------------- > + if check_results: > + for e in check_results: > + self.logger.error(e) > + msg =3D 'check_8023ad_dedicated_queues_transmission is faile= d' > + raise VerifyFailure(msg) > + return > + > + ############################### > + # testpmd other command > + ############################### > + def start_all_ports(self): > + """ > + Start all the ports which the testpmd can see. > + """ > + self.start_port("all") > + > + def start_port(self, port): > + """ > + Start a port which the testpmd can see. > + """ > + cmd =3D"port start %s" % str(port) > + self.d_console(cmd) > + time.sleep(3) > + > + def switch_daemon_config(self, **kwargs): > + if self.switch_name =3D=3D 'quanta': > + return > + port_id =3D kwargs.get('port_id') > + console =3D kwargs.get('console') > + wait_time =3D kwargs.get('wait_time') > + time.sleep(wait_time) > + self.logger.info(console.get_stats()) > + console.set_intf_down(port_id) > + self.logger.info(console.get_stats()) > + > + def create_intf_down_daemon(self, sw_scene, port_id, wait_time): > + para =3D {'port_id': port_id, > + 'wait_time': wait_time, > + 'console': sw_scene} > + daemon =3D DaemonThread( self.switch_daemon_config, > + name=3D"switch", **para) > + return daemon > + > + def check_8023ad_rx(self, unbound_port, bond_port, **slaves): > + """Verify that receiving packets correctly in the mode 4. > + > + :param unbound_port: the unbonded port id > + :param bond_port: the bonded device port id > + :param slaves: > + 'active':[] > + 'inactive':[] > + """ > + pass > + > + def run_switch_pre(self): > + sw_scene =3D self.sw_scene > + sw_scene.reset() > + sw_ports =3D sw_scene.ports() > + # set one random port as slave down port > + # if salve ports are more than three. > + slave_down_id =3D random.randint(0, len(sw_ports) - 1) > + sw_port_id =3D sw_ports[0] > + #[scene.set_intf_up(port_id) for port_id in sw_ports] > + sw_scene.get_stats() > + wait_time =3D 10 > + switch_daemon =3D self.create_intf_down_daemon(sw_scene, sw_port= _id, > + wait_time) > + return sw_scene, switch_daemon, sw_ports > + > + def traffic(self, bond_port, slaves): > + pkt_count =3D 1000 > + pkt_now =3D {} > + multi_stream =3D "/home/myf/multi.log" > + down =3D "/home/myf/down.log" > + #---------------------------- > + # create stream for traffic > + tx_port =3D self.tx_port > + self.set_stream( bond_port, src_port=3Dtx_port, pkt_type=3D'udp'= , **slaves) > + if not os.path.exists(down): > + switch_daemon =3D None > + if self.is_perf: > + pkt_gen_type =3D 'ixia' > + pkt_generator =3D self.send_packets_by_ixia > + elif os.path.exists(multi_stream): > + pkt_gen_type =3D 'scapy' > + os.remove(multi_stream) > + pkt_generator =3D self.send_multi_packet_quick # send multi = packet > + else: > + pkt_gen_type =3D 'scapy' > + pkt_generator =3D self.send_packet_quick > + time.sleep(3) > + #---------------------------- > + # run traffic > + self.logger.info("begin transmission data......") > + try: > + pkt_generator(tx_port, pkt_count) > + if self.switch_name =3D=3D 'quanta': > + loop_count =3D 5 > + wait =3D loop_count/3 > + interval =3D 15 > + #interval =3D 1 > + time.sleep(wait*interval) > + wait_time =3D (loop_count -wait)*interval > + self.logger.info("wait {0}".format(wait_time)) > + time.sleep(wait_time) > + #------------------------------------ > + if pkt_gen_type =3D=3D 'scapy': > + pkt_now =3D self.get_all_stats(None, "tx", bond_port, > + **slaves) > + self.logger.info("batch packet transmission data") > + for port_id in sorted(pkt_now.keys()): > + values =3D [str(value).rjust(10) > + for value in pkt_now[port_id]] > + msg =3D "port {0}: ".format(port_id) + ",".join(val= ues) > + self.logger.info(msg) > + except Exception as e: > + msg =3D traceback.format_exc() > + self.logger.error(msg) > + finally: > + pass > + #------------------------------ > + # end traffic > + if self.is_perf: > + self.stop_ixia() > + self.logger.info("complete transmission") > + > + def traffic_with_random_slave_down(self, bond_port, slaves): > + pkt_count =3D 1000 > + pkt_now =3D {} > + multi_stream =3D "/home/myf/multi.log" > + down =3D "/home/myf/down.log" > + #---------------------------- > + # create stream for traffic > + tx_port =3D self.tx_port > + self.set_stream(bond_port, src_port=3Dtx_port, pkt_type=3D'udp',= **slaves) > + if not os.path.exists(down): > + switch_daemon =3D None > + if self.is_perf: > + pkt_generator =3D self.send_packets_by_ixia > + elif os.path.exists(multi_stream): > + os.remove(multi_stream) > + pkt_generator =3D self.send_multi_packet_quick # send multi = packet > + else: > + pkt_generator =3D self.send_packet_quick > + time.sleep(3) > + cnt =3D 0 > + #---------------------------- > + # run traffic > + self.logger.info("begin transmission data......") > + wait_time =3D '' > + loop_count =3D 5 > + while cnt < loop_count: > + try: > + if os.path.exists(quit_file): > + os.remove(quit_file) > + break > + ################################## > + pkt_generator(tx_port, pkt_count) > + if self.switch_name =3D=3D 'quanta': > + wait =3D loop_count/3 > + #interval =3D 50 > + interval =3D 1 > + time.sleep(wait*interval) > + if self.slave_down: > + # add random wait time to get a scatter sample d= ata > + random_wait_time =3D random.randint(1, 20) > + #time.sleep(random_wait_time) > + wait_time =3D (loop_count -wait)*interval > + self.logger.info("wait {0}".format(wait_time)) > + time.sleep(wait_time) > + break > + else: > + if cnt =3D=3D loop_count/3: > + if switch_daemon: > + switch_daemon.activate() > + #------------------------------------ > + #pkt_total =3D pkt_total + pkt_count*len(sw_ports) > + if False: > + pkt_now =3D self.get_all_stats(None, "tx", bond_port= , > + **slaves) > + self.logger.info("batch packet transmission data") > + for port_id in sorted(pkt_now.keys()): > + values =3D [str(value).rjust(10) > + for value in pkt_now[port_id]] > + msg =3D "port {0}: ".format(port_id) + ",".join= (values) > + self.logger.info(msg) > + except Exception as e: > + msg =3D traceback.format_exc() > + self.logger.error(msg) > + finally: > + pass > + cnt +=3D 1 > + #------------------------------------------------------------- > + # end traffic > + # stop ixia > + if self.is_perf: > + self.stop_ixia() > + else: > + if switch_daemon: > + switch_daemon.stop() > + self.logger.info("complete transmission") > + > + def verify_8023ad_tx(self, tx_ports, bond_port, **slaves): > + """Verify that transmitting the packets correctly in the lacp mo= de.""" > + if self.switch_status =3D=3D 'active': > + self.d_console("stop") > + sw_scene, switch_daemon, sw_ports =3D self.run_switch_pre() > + self.d_console("start") > + #------------------------------------------------------------- > + # run traffic > + self.traffic(bond_port, slaves) > + #------------------------------------------------------------- > + time.sleep(3) > + if self.switch_status =3D=3D 'active': > + sw_scene.stop() > + switch_stats =3D sw_scene.get_stats() > + self.cur_data['switch statistics'] =3D switch_stats > + self.logger.warning("batch packet transmission data") > + > + def get_switch_port(self, dut_port_id): > + ''' get switch port name corresponding to dut port id ''' > + peer =3D self.dut.ports_info[dut_port_id]['peer'] > + sw_port =3D peer.split(":")[1] if 'switch' in peer else None > + return sw_port > + > + def get_switch_keys(self, key): > + if self.switch_name =3D=3D 'quanta': > + keys_table =3D {'rx ucast': 'RX Ucast Pkts', > + 'tx ucast': 'TX Ucast Pkts'} > + elif self.switch_name =3D=3D 'cisco': > + keys_table =3D {'RX-packets': '', > + 'TX-packets': ''} > + else: > + return None > + return keys_table[key] > + > + def check_sample_data(self, case_name): > + expected_rate =3D 1/10e4 > + summary_msg =3D [] > + for mode in self.data_results[case_name]: > + data =3D self.data_results[case_name][mode] > + pmd_stats =3D data['testpmd ports statistics'] > + switch_stats =3D data['switch statistics'] > + # check slave traffic stats > + port_msg =3D [] > + sw_total_rx =3D 0 > + for dut_port_id in pmd_stats: > + pmd_stat =3D pmd_stats[dut_port_id] > + sw_port_name =3D self.get_switch_port(dut_port_id) > + if not sw_port_name: > + continue > + switch_stat =3D switch_stats[sw_port_name] > + # check each slave's traffic loss > + # lacpdu packet is calculated by testpmd , so there is m= ore > + # pkts number on testpmd statistics > + port_text =3D "dut port [{0}]".format(dut_port_id) > + if sw_port_name: > + pmd_tx =3D pmd_stat['TX-packets'] > + key =3D 'rx ucast' > + sw_rx =3D switch_stat[self.get_switch_keys(key)] > + sw_total_rx +=3D sw_rx > + rate =3D 1 - float(sw_rx)/float(pmd_tx) > + msg =3D port_text + \ > + " traffic loss {0} is more than expected".forma= t(rate) > + if rate > expected_rate: > + port_msg.append(msg) > + else: > + msg =3D port_text + " has not corresponding switch p= ort" > + port_msg.append() > + > + # check total fwd traffic loss of bonding device > + pmd_fwd_stats =3D data['testpmd fwd statistics'] > + bond_port_id =3D self.bond_port > + tx_port_id =3D None > + for dut_port_id in pmd_fwd_stats: > + if dut_port_id !=3D bond_port_id: > + pmd_fwd_tx =3D pmd_fwd_stats[dut_port_id]['RX-packet= s'] > + tx_port_id =3D dut_port_id > + break > + pmd_bond_rx =3D pmd_fwd_stats[bond_port_id]['TX-packets'] > + fwd_msg =3D [] > + if pmd_bond_rx < pmd_fwd_tx: > + rate =3D 1 - float(pmd_bond_rx)/float(pmd_fwd_tx) > + port_text =3D "dut port [{0}] fwd to bond port [{1}]".fo= rmat( > + tx_port_= id, > + bond_por= t_id) > + msg =3D port_text + \ > + " traffic loss {0} is more than expected".format(ra= te) > + if rate > expected_rate: > + fwd_msg.append(msg) > + # check total traffic loss of bonding device > + # > + bond_msg =3D [] > + if sw_total_rx =3D=3D 0 or pmd_fwd_tx =3D=3D 0: > + msg =3D "total packet is zero, transmission not happen" > + bond_msg.append(msg) > + elif sw_total_rx < pmd_fwd_tx: > + rate =3D 1 - float(sw_total_rx)/float(pmd_fwd_tx) > + port_text =3D "bond port [{0}] to switch".format(bond_po= rt_id) > + msg =3D port_text + \ > + " traffic loss {0} is more than expected".format(ra= te) > + if rate > expected_rate: > + bond_msg.append(msg) > + # check status > + if fwd_msg or bond_msg: > + mode_msg =3D "mode {0}".format(mode) > + summary_msg.append(mode_msg) > + summary_msg +=3D port_msg + fwd_msg + bond_msg > + if summary_msg: > + self.logger.error(os.linesep.join(summary_msg)) > + return True > + else: > + self.logger.info('sample data are ok') > + return False > + > + def get_pci_link(self): > + # get forwarding port > + # TBD, unkown usage > + tx_pci =3D [] > + for port_info in self.dut.ports_info: > + tx_pci.append(port_info['pci']) > + if not tx_pci: > + msg =3D "can't find tx_port pci" > + self.logger.error(msg) > + raise VerifyFailure(msg) > + #------------------- > + # get bonding ports configuration > + slaves =3D self.dut_ports[:] > + slave_pcis =3D [] > + slave_ids =3D [] > + for port_id in slaves: > + slave_pcis.append(self.dut.ports_info[port_id]['pci']) > + slave_ids.append(port_id) > + return slave_ids, slave_pcis > + > + def get_pci_link_with_switch(self): > + # get forwarding port > + tx_pci =3D [] > + for port_info in self.dut.ports_info: > + if 'switch' not in port_info['peer']: > + tx_pci.append(port_info['pci']) > + if not tx_pci: > + msg =3D "can't find tx_port pci" > + self.logger.error(msg) > + raise VerifyFailure(msg) > + #------------------- > + # get bonding ports configuration > + slaves =3D self.dut_ports[:] > + slave_pcis =3D [] > + slave_ids =3D [] > + for port_id in slaves: > + if 'switch' in self.dut.ports_info[port_id]['peer']: > + slave_pcis.append(self.dut.ports_info[port_id]['pci']) > + slave_ids.append(port_id) > + return slave_ids, slave_pcis > + > + def get_commandline_options(self, agg_mode): > + # get bonding ports configuration > + if self.is_perf: > + slave_ids, slave_pcis =3D self.get_pci_link_with_switch() > + else: > + slave_ids, slave_pcis =3D self.get_pci_link() > + # get nic configuration > + bonding_name =3D 'net_bonding0' > + slaves_pci =3D ["slave=3D" + pci for pci in slave_pcis] > + bonding_mode =3D 'mode=3D{0}'.format(str(MODE_LACP)) > + agg_config =3D 'agg_mode=3D{0}' > + vdev_format =3D ",".join([bonding_name] + slaves_pci + \ > + [bonding_mode, agg_config]) > + # begin check command line options > + check_results =3D [] > + mode =3D str(MODE_LACP) > + options =3D vdev_format.format(agg_mode) > + vdev_options =3D " --vdev '{0}'".format(options) > + bond_port =3D len(self.dut_ports) > + return bond_port, vdev_options > + > + def run_test_pre(self, agg_mode): > + msgs =3D [] > + if self.switch_status =3D=3D 'active': > + self.tester.ixia_packet_gen.clean_ownership() > + self.sw_scene.clear() # clear switch statistics > + # get bonding ports configuration > + bond_port, vdev_options =3D self.get_commandline_options(agg_mod= e) > + self.bond_port =3D bond_port > + # boot up testpmd > + self.start_testpmd(eal_option=3Dvdev_options) > + cur_slaves, cur_agg_mode =3D self.get_bonding_info(bond_port, > + ['slaves', 'agg_mode']) > + if agg_mode !=3D cur_agg_mode: > + fmt =3D 'expected agg mode is [{0}], current agg mode is [{1= }]' > + msg =3D fmt.format(agg_mode, cur_agg_mode) > + msgs.append(msg) > + #------------------- > + # get forwarding port > + #------------------- > + tx_port_id =3D '' > + for port_id in range(bond_port): > + if str(port_id) not in cur_slaves: > + tx_port_id =3D port_id > + break > + else: > + tx_port_id =3D bond_port > + # raise VerifyFailure > + if msgs: > + for msg in msgs: > + self.logger.warning(msg) > + fmt =3D 'fail to config from command line at {0}' > + msg =3D fmt.format(agg_mode) > + self.logger.warning(msg) > + #raise VerifyFailure(msg) > + #----------------------------------------- > + # open dedicated queue > + self.set_8023ad_dedicated_queue(bond_port, 'enable') > + if self.switch_status =3D=3D 'active': > + self.sw_scene.start() > + self.set_bond_port_ready(tx_port_id, bond_port) > + slaves =3D [int(slave) for slave in cur_slaves] > + > + return bond_port, slaves, tx_port_id > + > + def run_test_post(self, bond_port, tx_port_id): > + slave_stats =3D {} > + for port_id in range(bond_port): > + if tx_port_id =3D=3D port_id or bond_port =3D=3D port_id: > + continue > + slave_stats[port_id] =3D self.testpmd.get_pmd_stats(port_id) > + > + self.cur_data['testpmd ports statistics'] =3D slave_stats > + #------------- > + fwd_pmd_stats =3D {} > + for port_id in [bond_port, tx_port_id]: > + fwd_pmd_stats[port_id] =3D self.testpmd.get_pmd_stats(port_i= d) > + self.cur_data['testpmd fwd statistics'] =3D fwd_pmd_stats > + output =3D self.close_testpmd() > + self.sw_scene.clear() > + self.tester.ixia_packet_gen.clean_ownership() > + > + def run_dpdk_pre2(self): > + slaves =3D self.dut_ports[:] > + self.start_testpmd() > + mode =3D MODE_LACP > + bond_port =3D self.run_8023ad_pre(slaves, mode) > + return slaves, bond_port > + > + def run_dpdk_post2(self): > + self.close_testpmd() > + return True > + > + def check_traffic_with_cmd_line_options(self, agg_mode=3D'count'): > + # begin check command line options > + check_results =3D [] > + max_loop =3D self.sample_number > + cur_case_name =3D self.cur_case > + sample_results =3D {} > + for cnt in range(max_loop): > + self.data_results[cur_case_name] =3D {} > + case_data =3D self.data_results[cur_case_name] > + #for agg_mode in self.AGG_MODES: > + if agg_mode in self.AGG_MODES: > + case_data[agg_mode] =3D {} > + self.cur_data =3D case_data[agg_mode] > + self.logger.info('begin to check {0}'.format(agg_mode)) > + bond_port, cur_slaves, tx_port_id =3D self.run_test_pre(= agg_mode) > + try: > + #----------------------------------------- > + # begin loop sending packet transmission > + slaves =3D {} > + slaves['active'] =3D cur_slaves > + slaves['inactive'] =3D [] > + tx_ports =3D[self.tx_port] > + self.verify_8023ad_tx(tx_ports, bond_port, **slaves) > + except Exception as e: > + check_results.append(e); print traceback.format_exc(= ) > + finally: > + pass > + self.run_test_post(bond_port, tx_port_id) > + # check sample data, if there are exception, mark it and put= it on > + # result list > + try: > + status =3D self.check_sample_data(cur_case_name) > + if status: > + sample_results[cnt] =3D status > + except Exception as e: > + sample_results[cnt] =3D 'data absence' > + finally: > + pass > + > + if sample_results: > + check_results.append(pformat(sample_results, indent=3D1, wid= th=3D1)) > + > + if check_results: > + for e in check_results: > + self.logger.error(e) > + raise VerifyFailure('test_command_line_option is failed') > + self.logger.info("traffic good") > + > + return > + > + def check_cmd_line_option_status(self, agg_mode, bond_port, slaves): > + mode =3D str(MODE_LACP) > + msgs =3D [] > + cur_mode, cur_slaves, cur_active_slaves, cur_agg_mode =3D\ > + self.get_bonding_info(bond_port, > + ['mode', > + 'slaves', > + 'active_slaves', > + 'agg_mode']) > + #--------------------------------- > + # check bonding mode > + if mode !=3D cur_mode: > + fmt =3D 'expected mode is [{0}], current mode is [{1}]' > + msg =3D fmt.format(mode, cur_mode) > + msgs.append(msg) > + #--------------------------------- > + # check bonding 802.3ad agg mode > + if agg_mode !=3D cur_agg_mode: > + fmt =3D'expected agg mode is [{0}], current agg mode is [{1}= ]' > + msg =3D fmt.format(agg_mode, cur_agg_mode) > + msgs.append(msg) > + #--------------------------------- > + # check bonded slaves > + _cur_slaves =3D [int(id) for id in cur_slaves] > + if not _cur_slaves or cmp(sorted(slaves), sorted(_cur_slaves)) != =3D 0: > + slaves_str =3D ' '.join([str(id) for id in slaves]) > + cur_slaves_str =3D ' '.join([str(id) for id in _cur_slaves])= \ > + if _cur_slaves else '' > + msg_format =3D 'expected slaves is [{0}], current slaves is = [{1}]' > + msg =3D msg_format.format(slaves_str, cur_slaves_str) > + msgs.append(msg) > + #--------------------------------- > + # check active slaves status before ports start > + if self.kdriver is 'i40e': > + if cur_active_slaves: > + check_active_slaves =3D [int(id) for id in cur_active_sl= aves] > + if cmp(sorted(slaves), sorted(check_active_slaves)) !=3D= 0: > + slaves_str =3D ' '.join([str(id) for id in slaves]) > + msg_fmt =3D ('expected active slaves is [{0}], ' > + 'current active slaves is [{1}]') > + msg =3D msg_fmt.format(slaves_str, cur_active_slaves= ) > + msgs.append(msg) > + else: > + msg =3D 'active slaves should not be empty' > + self.logger.warning(msg) > + #msgs.append(msg) > + else: > + if cur_active_slaves: > + msg =3D 'active slaves should be empty' > + self.logger.warning(msg) > + #msgs.append(msg) > + #--------------------------------- > + # check status after ports start > + self.start_ports() > + # set bonded device to active status > + if self.kdriver is not 'i40e': > + cur_active_slaves =3D [int(id) for id in self.get_bonding_in= fo( > + bond_port, > + 'active_slav= es')] > + if not cur_active_slaves or cmp(sorted(slaves), > + sorted(cur_active_slaves)) != =3D 0: > + slaves_str =3D ' '.join([str(id) for id in slaves]) > + active_str =3D ' '.join([str(id) for id in cur_active_sl= aves]) \ > + if cur_active_slaves else= '' > + msg_fmt =3D ('expected active slaves is [{0}], ' > + 'current active slaves is [{1}]') > + msg =3D msg_fmt.format(slaves_str, active_str) > + msgs.append(msg) > + #--------------------------------- > + # raise exception > + if msgs: > + for msg in msgs: > + self.logger.warning(msg) > + msg =3D 'fail to config from command line at {0}'.format(agg= _mode) > + raise VerifyFailure(msg) > + > + def verify_tx(self): > + """Verify that transmitting the packets correctly in the lacp mo= de. """ > + pkt_count =3D 1000 > + pkt_total =3D 0 > + pkt_now =3D {} > + loop_count =3D 5 > + cnt =3D 0 > + tx_port =3D self.tx_port > + bond_port =3D 0 > + slaves =3D {} > + slaves['active'] =3D['0', '1','2','3'] > + self.set_stream(bond_port, src_port=3Dtx_port, pkt_type=3D'udp',= **slaves) > + #------------------------------------------------------------ > + pkt_generator =3D self.send_packets_by_ixia > + self.logger.info("begin transmission data......") > + wait_time =3D 30*1 > + #------------------------------------------------------------ > + try: > + ################################## > + pkt_generator(tx_port, pkt_count) > + time.sleep(wait_time) > + except Exception as e: > + msg =3D traceback.format_exc() > + self.logger.error(msg) > + finally: > + pass > + > + # stop ixia > + self.stop_ixia() > + return > + > + @property > + def is_perf(self): > + return self._enable_perf > + > + @property > + def is_switch(self): > + return self.tester.has_switch() > + > + @property > + def driver(self): > + return self.kdriver > + # > + # Test cases. > + # > + def set_up_all(self): > + """ > + Run before each test suite > + """ > + self.verify('bsdapp' not in self.target, "Bonding not support fr= eebsd") > + #------------------------------------------------------------ > + # link peer resource > + self.dut_ports =3D self.dut.get_ports() > + required_link =3D 5 if self.is_switch else 2 > + self.verify(len(self.dut_ports) >=3D required_link, "Insufficien= t ports") > + self.ports_socket =3D self.dut.get_numa_id(self.dut_ports[0]) > + self.all_cores_mask =3D utils.create_mask(self.dut.get_core_list= ("all")) > + #------------------------------------------------------------ > + # stream configs > + self.stream_dst_configs =3D [] > + #------------------------------------------------------------ > + # testpmd related > + self.testpmd =3D PmdOutput(self.dut) > + self.testpmd_status =3D 'close' > + #------------------------------------------------------------ > + # 802.3ad related > + self.tester_bond =3D "bond0" > + self.agg_mode =3D None > + self.bond_port =3D None > + #-------------------------------- > + # switch related > + # only itecStvDts02 platform support lacp testing > + #tester_hostname =3D socket.gethostname() > + if self.is_switch: > + self.tx_port =3D self.tester.get_interface( > + self.tester.get_local_port(self.dut_port= s[0])) > + switch_name =3D 'quanta' > + if 'lacp_group' not in self.tester.switch_scenes: > + msg =3D "[lacp_group] section not set in switch.cfg" > + raise SwitchException(msg) > + self.sw_scene =3D self.tester.switch_scenes['lacp_group'] > + self.switch_name =3D switch_name > + self.switch_status =3D 'active' > + #--------------------------------- > + self.multi_stream_flg =3D False > + self.add_options =3D False > + self.slave_down =3D False > + else: > + self.switch_status =3D 'close' > + # use for sample long time pressure testing > + self.sample_number =3D 1 > + #-------------------------------- > + # traffic related > + self.packet_types =3D {} > + #---------- > + # ixia > + self.rate_percent =3D float(100) > + #---------------------------------------------------------------= --- > + # use for debug > + self.data =3D [] > + self.cur_data =3D {} > + self.data_results =3D {} > + self.cur_case =3D 'lacp' > + > + def set_up(self): > + """ > + Run before each test case. > + """ > + pass > + > + def tear_down(self): > + """ > + Run after each test case. > + """ > + try: > + self.close_testpmd() > + except Exception as e: > + pass > + finally: > + pass > + > + def tear_down_all(self): > + """ > + Run after each test suite. > + """ > + if self.switch_status =3D=3D 'active': > + self.sw_scene.quit() > + self.switch_status =3D 'close' > + > + def test_basic_behav_startStop(self): > + ''' > + test 802.3ad basic behavior(port start/stop) > + ''' > + #---------------------------- > + msg =3D '' > + slaves, bond_port =3D self.run_dpdk_pre2() > + try: > + for _ in range(10): > + self.check_bonded_device_start(bond_port) > + except Exception as e: > + msg =3D "bonding 8023ad check start/stop failed" > + finally: > + pass > + self.run_dpdk_post2() > + if msg: > + raise VerifyFailure(msg) > + return > + > + def test_basic_behav_mac(self): > + ''' > + test 802.3ad basic behavior(mac address) > + ''' > + #---------------------------- > + msg =3D '' > + slaves, bond_port =3D self.run_dpdk_pre2() > + try: > + self.bonding_8023ad_check_macs(slaves, bond_port) > + self.check_bonded_device_mac_change(slaves, bond_port) > + except Exception as e: > + msg =3D "bonding 8023ad check macs failed" > + finally: > + pass > + self.run_dpdk_post2() > + if msg: > + raise VerifyFailure(msg) > + return > + > + def test_basic_behav_upDown(self): > + ''' > + test 802.3ad basic behavior(link up/down) > + ''' > + msg =3D '' > + slaves, bond_port =3D self.run_dpdk_pre2() > + try: > + self.check_bonded_device_up_down(bond_port) > + except Exception as e: > + msg =3D "bonding 8023ad check link up/down failed" > + finally: > + pass > + self.run_dpdk_post2() > + if msg: > + raise VerifyFailure(msg) > + return > + > + def test_basic_behav_promisc_mode(self): > + ''' > + test 802.3ad basic behavior(promisc mode) > + ''' > + msg =3D '' > + slaves, bond_port =3D self.run_dpdk_pre2() > + try: > + self.check_bonded_device_promisc_mode(slaves, bond_port) > + except Exception as e: > + msg =3D "bonding 8023ad check promisc mode failed" > + finally: > + pass > + self.run_dpdk_post2() > + if msg: > + raise VerifyFailure(msg) > + return > + > + def test_command_line_option(self): > + ''' > + test 802.3ad basic behavior(bonded configs using command line op= tion) > + ''' > + for agg_mode in self.AGG_MODES: > + bond_port, cur_slaves, tx_port_id =3D self.run_test_pre(agg_= mode) > + self.check_cmd_line_option_status(agg_mode, bond_port, cur_s= laves) > + self.close_testpmd() > + > + def test_basic_behav_agg_mode(self): > + slaves =3D self.dut_ports[:] > + mode =3D MODE_LACP > + self.check_8023ad_agg_modes(slaves, mode) > + return > + > + def test_basic_dedicated_queues(self): > + slaves =3D self.dut_ports[:] > + mode =3D MODE_LACP > + self.check_8023ad_dedicated_queues(slaves, mode) > + return > + > + def check_perf_tx(self, agg_mode): > + #---------------------------------------------------------------= ----- > + if self.switch_status =3D=3D 'close': > + raise VerifyFailure("no switch support this testing case") > + self.slave_down =3D False > + #=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > + # select agg mode > + #------------------- > + # create command line options > + self.check_traffic_with_cmd_line_options(agg_mode=3Dagg_mode) > + return > + > + def test_perf_agg_count_tx(self): > + self.check_perf_tx("count") > + > + def test_perf_agg_stable_tx(self): > + self.check_perf_tx("stable") > + > + def test_perf_agg_bandwidth_tx(self): > + self.check_perf_tx("bandwidth") > \ No newline at end of file > -- > 1.9.3