From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by dpdk.org (Postfix) with ESMTP id 872234CA0 for ; Mon, 21 Jan 2019 08:17:33 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Jan 2019 23:17:32 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,502,1539673200"; d="scan'208";a="268668210" Received: from fmsmsx106.amr.corp.intel.com ([10.18.124.204]) by orsmga004.jf.intel.com with ESMTP; 20 Jan 2019 23:17:32 -0800 Received: from fmsmsx155.amr.corp.intel.com (10.18.116.71) by FMSMSX106.amr.corp.intel.com (10.18.124.204) with Microsoft SMTP Server (TLS) id 14.3.408.0; Sun, 20 Jan 2019 23:17:31 -0800 Received: from shsmsx106.ccr.corp.intel.com (10.239.4.159) by FMSMSX155.amr.corp.intel.com (10.18.116.71) with Microsoft SMTP Server (TLS) id 14.3.408.0; Sun, 20 Jan 2019 23:17:30 -0800 Received: from shsmsx104.ccr.corp.intel.com ([169.254.5.159]) by SHSMSX106.ccr.corp.intel.com ([169.254.10.86]) with mapi id 14.03.0415.000; Mon, 21 Jan 2019 15:17:28 +0800 From: "Chen, Zhaoyan" To: "dts@dpdk.org" CC: "Mo, YufengX" , "Tu, Lijuan" , "Chen, Zhaoyan" Thread-Topic: [dts] [PATCH V1 2/2] pmd_stacked_bonded: upload automation script Thread-Index: AQHT/ViLTW02wgsBtUG0Ngt3JyIXaKW6p+6g Date: Mon, 21 Jan 2019 07:17:28 +0000 Message-ID: <9DEEADBC57E43F4DA73B571777FECECA41C120F1@SHSMSX104.ccr.corp.intel.com> References: <1528263463-25840-1-git-send-email-yufengx.mo@intel.com> <1528263463-25840-3-git-send-email-yufengx.mo@intel.com> In-Reply-To: <1528263463-25840-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/2] pmd_stacked_bonded: 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:17:34 -0000 Yufeng, - Could you move the hard code ip/mac/port address to constants? and put th= em at the begin of the code. - Extract the common functions which used by bond test into common file and= share between each bond test suite. 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/2] pmd_stacked_bonded: upload automation scrip= t >=20 > From: yufengmx >=20 >=20 > This automation script is for pmd stacked bonded feature. >=20 > Allow bonded devices to be stacked to allow two or more bonded devices to= be > bonded into one master bonded device >=20 > Signed-off-by: yufengmx > --- > tests/TestSuite_pmd_stacked_bonded.py | 1593 > +++++++++++++++++++++++++++++++++ > 1 file changed, 1593 insertions(+) > create mode 100644 tests/TestSuite_pmd_stacked_bonded.py >=20 > diff --git a/tests/TestSuite_pmd_stacked_bonded.py > b/tests/TestSuite_pmd_stacked_bonded.py > new file mode 100644 > index 0000000..4596c58 > --- /dev/null > +++ b/tests/TestSuite_pmd_stacked_bonded.py > @@ -0,0 +1,1593 @@ > +# 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 traceback > +import os > +import time > +import re > +import random > +from socket import htons, htonl > + > +import utils > +from test_case import TestCase > +from exception import TimeoutException, VerifyFailure > +from settings import TIMEOUT > +from pmd_output import PmdOutput > + > +SOCKET_0 =3D 0 > +SOCKET_1 =3D 1 > + > +MODE_ROUND_ROBIN =3D 0 > +MODE_ACTIVE_BACKUP =3D 1 > +MODE_XOR_BALANCE =3D 2 > +MODE_BROADCAST =3D 3 > +MODE_LACP =3D 4 > +MODE_TLB_BALANCE =3D 5 > +MODE_ALB_BALANCE =3D 6 > + > +FRAME_SIZE_64 =3D 64 > + > +class TestBondingStacked(TestCase): > + > + def get_static_ip_configs(self): > + S_MAC_IP_PORT =3D [('52:00:00:00:00:00', '10.239.129.65', 61), > + ('52:00:00:00:00:01', '10.239.129.66', 62), > + ('52:00:00:00:00:02', '10.239.129.67', 63)] > + return S_MAC_IP_PORT > + # > + # 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 get_all_stats(self, unbound_port, rx_tx, bond_port, **slaves): > + """ > + Get all the port stats which the testpmd can display. > + Parameters: > + : unbound_port: pmd port id > + : rx_tx: unbond port stat 'rx' or 'tx' > + : bond_port: bonding port > + """ > + pkt_now =3D {} > + > + if rx_tx =3D=3D 'rx': > + bond_stat =3D 'tx' > + else: > + bond_stat =3D '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 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 > + > + 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: > + 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'] > + 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"] > + > + 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'] > + > + 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'] > + > + 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 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 > + cmds =3D [["port stop %d"%number, '']] > + self.execute_testpmd_cmd(cmds) > + # 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 send_packet(self, dst_port, src_port=3DFalse, frame_size=3DFRAME= _SIZE_64, > + count=3D1, invert_verify=3DFalse, **ether_ip): > + """ > + Send count packet to portid > + count: 1 or 2 or 3 or ... or 'MANY' > + if count is 'MANY', then set count=3D1000, > + send packets during 5 seconds. > + 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 > + """ > + during =3D 0 > + loop =3D 0 > + > + try: > + count =3D int(count) > + except ValueError as e: > + if count =3D=3D 'MANY': > + during =3D 5 > + count =3D 1000 > + else: > + raise e > + > + if not src_port: > + gp0rx_pkts, gp0rx_err, gp0rx_bytes =3D \ > + [int(_) for _ in self.get_stats(self.dut_ports[dst_port]= , > + "rx")] > + itf =3D self.tester.get_interface( > + self.tester.get_local_port(self.dut_ports[dst_po= rt])) > + os.system("ifconfig {0} up".format(itf)) > + # temp =3D os.system("ifconfig {0} up".format(itf)) > + else: > + gp0rx_pkts, gp0rx_err, gp0rx_bytes =3D \ > + [int(_) for _ in self.get_stats(dst_port, "rx")] > + itf =3D src_port > + > + time.sleep(2) > + ret_ether_ip =3D self.parse_ether_ip(dst_port, **ether_ip) > + > + pktlen =3D frame_size - 18 > + padding =3D pktlen - 20 > + > + start =3D time.time() > + while True: > + self.tester.scapy_foreground() > + append =3D self.tester.scapy_append > + append('nutmac=3D"%s"' % ret_ether_ip['ether']['dst_mac']) > + append('srcmac=3D"%s"' % ret_ether_ip['ether']['src_mac']) > + > + if ether_ip.get('dot1q'): > + append('vlanvalue=3D%d' % ret_ether_ip['dot1q']['vlan']) > + append('destip=3D"%s"' % ret_ether_ip['ip']['dst_ip']) > + append('srcip=3D"%s"' % ret_ether_ip['ip']['src_ip']) > + append('destport=3D%d' % ret_ether_ip['udp']['dst_port']) > + append('srcport=3D%d' % ret_ether_ip['udp']['src_port']) > + if not ret_ether_ip.get('dot1q'): > + packet =3D "/".join(["Ether(dst=3Dnutmac, src=3Dsrcmac)"= , > + "IP(dst=3Ddestip, src=3Dsrcip, len=3D%= s)", > + "UDP(sport=3Dsrcport, dport=3Ddestport= )", > + "Raw(load=3D'\x50'*%s)"]) > + cmd =3D 'sendp([{0}], iface=3D"%s", count=3D%d)'.format(= packet) > + append(cmd % (pktlen, padding, itf, count)) > + else: > + packet =3D "/".join(["Ether(dst=3Dnutmac, src=3Dsrcmac)"= , > + "Dot1Q(vlan=3Dvlanvalue)", > + "IP(dst=3Ddestip, src=3Dsrcip, len=3D%= s)", > + "UDP(sport=3Dsrcport, dport=3Ddestport= )", > + "Raw(load=3D'\x50'*%s)"]) > + cmd =3D 'sendp([{0}], iface=3D"%s", count=3D%d)'.format(= packet) > + append(cmd % (pktlen, padding, itf, count)) > + > + self.tester.scapy_execute() > + loop +=3D 1 > + > + now =3D time.time() > + if (now - start) >=3D during: > + break > + time.sleep(.5) > + > + if not src_port: > + p0rx_pkts, p0rx_err, p0rx_bytes =3D \ > + [int(_) for _ in self.get_stats(self.dut_ports[dst_port],= "rx")] > + else: > + p0rx_pkts, p0rx_err, p0rx_bytes =3D \ > + [int(_) for _ in self.get_stats(dst_port, "rx")] > + > + p0rx_pkts -=3D gp0rx_pkts > + p0rx_bytes -=3D gp0rx_bytes > + > + if invert_verify: > + LACP_MESSAGE_SIZE =3D 128 > + msg =3D ("port <{0}> Data received by port <{1}>, " > + "but should not.").format(itf, dst_port) > + self.verify(p0rx_pkts =3D=3D 0 or > + p0rx_bytes / p0rx_pkts =3D=3D LACP_MESSAGE_SIZE, > + msg) > + msg =3D "port {0} <-| |-> port {1} is ok".format(itf, > + dst_port) > + self.logger.info(msg) > + else: > + msg =3D "port <{0}> Data not received by port <{1}>".format(= itf, > + dst_p= ort) > + self.verify(p0rx_pkts >=3D count * loop, > + msg) > + msg =3D "port {0} <----> port {1} is ok".format( itf, dst_p= ort) > + self.logger.info(msg) > + return count * loop > + > + def send_default_packet_to_slave(self, unbound_port, bond_port, > + pkt_count=3D100, **slaves): > + """ > + Send packets to the slaves and calculate the slave`s RX packets > + and unbond port TX packets. > + Parameters: > + : unbound_port: the unbonded port id > + : bond_port: the bonded device port id > + """ > + pkt_orig =3D {} > + pkt_now =3D {} > + temp_count =3D 0 > + summary =3D 0 > + results =3D [] > + #--------------------------- > + # send to slave ports > + pkt_orig =3D self.get_all_stats(unbound_port, 'tx', bond_port, *= *slaves) > + self.logger.info("send packet to active slave ports") > + for slave in slaves['active']: > + try: > + temp_count =3D self.send_packet(self.dut_ports[int(slave= )], > + False, > + FRAME_SIZE_64, pkt_count) > + summary +=3D temp_count > + except Exception as e: > + results.append(e) > + finally: > + pass > + #--------------------------- > + if slaves['inactive'] and False: > + self.logger.info("send packet to inactive slave ports") > + for slave in slaves['inactive']: > + try: > + self.send_packet(self.dut_ports[int(slave)], False, > + FRAME_SIZE_64, pkt_count, True) > + except Exception as e: > + results.append(e) > + finally: > + pass > + > + if results: > + for item in results: > + self.logger.error(e) > + raise VerifyFailure("send_default_packet_to_slave failed") > + > + pkt_now =3D self.get_all_stats(unbound_port, 'tx', bond_port, **= slaves) > + > + for key in pkt_now: > + for num in [0, 1, 2]: > + pkt_now[key][num] -=3D pkt_orig[key][num] > + > + return pkt_now, summary > + > + def send_default_packet_to_unbound_port(self, unbound_port, bond_por= t, > + pkt_count=3D300, **slaves): > + """ > + Send packets to the unbound port and calculate unbound port RX p= ackets > + and the slave`s TX packets. > + Parameters: > + : unbound_port: the unbonded port id > + : bond_port: the bonded device port id > + """ > + pkt_orig =3D {} > + pkt_now =3D {} > + summary =3D 0 > + > + # send to unbonded device > + pkt_orig =3D self.get_all_stats(unbound_port, 'rx', bond_port, *= *slaves) > + summary =3D self.send_packet(unbound_port, False, > + FRAME_SIZE_64, pkt_count) > + pkt_now =3D self.get_all_stats(unbound_port, 'rx', bond_port, **= slaves) > + > + for key in pkt_now: > + for num in [0, 1, 2]: > + pkt_now[key][num] -=3D pkt_orig[key][num] > + > + return pkt_now, summary > + > + def send_customized_packet_to_unbound_port(self, unbound_port, bond_= port, > + policy, vlan_tag=3DFalse, > + pkt_count=3D100, **slaves= ): > + """ > + Verify that transmitting the packets correctly in the XOR mode. > + Parameters: > + : unbound_port: the unbonded port id > + : bond_port: the bonded device port id > + : policy: 'L2' , 'L23' or 'L34' > + : vlan_tag: False or True > + """ > + pkt_orig =3D {} > + pkt_now =3D {} > + summary =3D 0 > + temp_count =3D 0 > + > + # send to unbound_port > + pkt_orig =3D self.get_all_stats(unbound_port, 'rx', bond_port, *= *slaves) > + dest_mac =3D self.dut.get_mac_address(self.dut_ports[unbound_por= t]) > + dest_ip =3D "10.239.129.88" > + dest_port =3D 53 > + > + self.dst_pkt_configs =3D [dest_mac, dest_ip, dest_port] > + > + ether_ip =3D {} > + ether =3D {} > + ip =3D {} > + udp =3D {} > + > + ether['dest_mac'] =3D False > + ip['dest_ip'] =3D dest_ip > + udp['dest_port'] =3D 53 > + if vlan_tag: > + dot1q =3D {} > + dot1q['vlan'] =3D random.randint(1, 50) > + ether_ip['dot1q'] =3D dot1q > + > + ether_ip['ether'] =3D ether > + ether_ip['ip'] =3D ip > + ether_ip['udp'] =3D udp > + > + source =3D self.get_static_ip_configs() > + > + for src_mac, src_ip, src_port in source: > + ether_ip['ether']['src_mac'] =3D src_mac > + ether_ip['ip']['src_ip'] =3D src_ip > + ether_ip['udp']['src_port'] =3D src_port > + temp_count =3D self.send_packet(unbound_port, False, FRAME_S= IZE_64, > + pkt_count, False, **ether_ip) > + summary +=3D temp_count > + pkt_now =3D self.get_all_stats(unbound_port, 'rx', bond_port, **= slaves) > + > + for key in pkt_now: > + for num in [0, 1, 2]: > + pkt_now[key][num] -=3D pkt_orig[key][num] > + > + return pkt_now, summary > + > + # > + # On dut, dpdk testpmd > + # > + def preset_testpmd(self, core_mask, options=3D''): > + self.testpmd.start_testpmd( core_mask, param=3D' '.join(options)= ) > + self.execute_testpmd_cmd(self.preset_testpmd_cmds) > + self.preset_testpmd_cmds =3D list() > + time.sleep(1) > + > + def execute_testpmd_cmd(self, cmds): > + if len(cmds) =3D=3D 0: > + return > + for item in cmds: > + expected_str =3D item[1] or 'testpmd> ' > + if len(item) =3D=3D 3: > + self.testpmd.execute_cmd(item[0], item[1], int(item[2])) > + else: > + self.testpmd.execute_cmd(item[0], item[1]) > + time.sleep(2) > + > + def start_testpmd(self, eal_option=3DNone): > + if self.testpmd_status =3D=3D 'running': > + return > + # link eal option and testpmd options > + offloadd =3D '0x1fbf' if self.driver =3D=3D 'i40e' else '0x2203f= ' > + options =3D ["--tx-offloads=3D{0}".format(offloadd)] > +# options =3D " ".join([eal_option, options]) if eal_option else= '' > + # boot up testpmd > + hw_mask =3D '1S/2C/1T' > + self.preset_testpmd_cmds =3D [[' ', ''], # used to resolve lsc e= vent > + ['port stop all', '']] > + self.preset_testpmd(hw_mask, options) > + self.testpmd_status =3D 'running' > + > + def stop_testpmd(self): > + time.sleep(1) > + testpmd_cmds =3D[['port stop all', ''], > + ['stop', ''],] > + self.execute_testpmd_cmd(testpmd_cmds) > + time.sleep(1) > + > + def close_testpmd(self): > + if self.testpmd_status =3D=3D 'close': > + return > + self.stop_testpmd() > + time.sleep(1) > + self.testpmd.quit() > + self.testpmd_status =3D 'close' > + # > + # 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': > + msg =3D "{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 =3D r"(?<=3D%s)%s" % (key, regx_str) > + s =3D re.compile(pattern) > + res =3D s.search(string) > + if type(res).__name__ !=3D 'NoneType': > + 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 =3D port_id > + key_str, regx_str =3D args > + out =3D self.dut.send_expect("show port info %d" % port, "testpm= d> ") > + 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. > + """ > + search_args =3D args if isinstance(args[0], (list, tuple)) else = [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*"], > + '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.dut.send_expect( > + "show bonding config %d" % bond_port= , > + "testpmd> ") > + 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_content, > + info_set[info_ty= pe]) > + 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_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: > + msg =3D "primary port <{0}> isn't in active slaves list".for= mat( > + primary_= port) > + self.logger.error > + raise VerifyFailure(msg) > + > + 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.dut.send_expect(cmd, "testpmd> ") > + self.verify("Created new bonded device" in out, > + "Create bonded device on mode [%d] socket [%d] faile= d" % ( > + mode= , > + sock= et)) > + bond_port =3D self.get_value_from_str([ > + "Created new bonded device net_bond_testpmd_[\d] on \(port "= , > + "Created new bonded device net_bonding_testpmd_[\d] on \(por= t "], > + "\d+", out) > + bond_port =3D int(bond_port) > + > + if verify_detail: > + out =3D self.dut.send_expect("show bonding config %d" % bond= _port, > + "testpmd> ") > + 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 devi= ce") > + self.verify("Primary: []" not in out, > + "Primary display error when create bonded device= ") > + > + out =3D self.dut.send_expect("show port info %d" % bond_port= , > + "testpmd> ") > + 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 > + #self.dut.send_expect("port start %s" % str(port), " ", timeout) > + self.dut.send_expect("port start %s" % str(port), " ", timeout) > + self.dut.send_expect(" ", "testpmd> ", timeout) > + > + 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: > + out =3D self.dut.send_expect( > + "add bonding slave %d %d" % (slave_id, bond_port= ), > + "testpmd> ") > + 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: > + self.verify(str(slave_id) not in slaves, > + "Add port as bonding slave successfully,should f= ail") > + > + 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.dut.send_expect(cmd, "testpmd> ") > + 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: > + self.verify(str(slave_id) in slaves, > + ("Remove slave successfully from " > + "bonding device,should be failed")) > + > + 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.dut.send_expect(cmd, "testpmd> ") > + 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: > + self.verify(str(slave_port) not in out, > + ("Set bonding primary port successfully, " > + "should not success")) > + > + 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.dut.send_expect(cmd, "testpmd> ") > + 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.dut.send_expect(cmd, "testpmd> ") > + 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.dut.send_expect(cmd, "testpmd> ") > + 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 check_stacked_device_queue_config(self, *devices): > + ''' > + # check if master bonding/each slaves queue configuration is the= same. > + ''' > + master =3D self.get_port_info(devices[0], 'queue_config') > + for port_id in devices[1:]: > + config =3D self.get_port_info(port_id, 'queue_config') > + if cmp(config, master) =3D=3D 0: > + continue > + msg =3D ("slave bonded port [{0}] is " > + "different to top bonded port [{1}]").format(port_id, > + devices[= 0]) > + raise VerifyFailure('check_stacked_device_queue_config ' + m= sg) > + > + def set_stacked_bonded(self, slaveGrpOne, slaveGrpTwo, 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_1 =3D self.create_bonded_device(bond_mode, specified_s= ocket) > + self.add_slave(bond_port_1, False, '', *slaveGrpOne) > + # create bonded device 2, add slaves in it > + bond_port_2 =3D self.create_bonded_device(bond_mode, specified_s= ocket) > + self.add_slave(bond_port_2, False, '', *slaveGrpTwo) > + # create bonded device 3, which is the top bonded device > + bond_port_master =3D self.create_bonded_device(bond_mode, > + specified_socket) > + # bond bonded device 2 to bonded device 4 > + # and check bond 0/2 config status > + self.add_slave(bond_port_master, False, '', *[bond_port_1]) > + # bond bonded device 3 to bonded device 4 > + # and check bond 1/2 config status > + self.add_slave(bond_port_master, False, '', *[bond_port_2]) > + # check if master bonding/each slaves queue configuration is the= same. > + self.check_stacked_device_queue_config(*[bond_port_master, > + bond_port_1, bond_port_= 2]) > + # start all ports > + #self.start_ports() > + > + return [bond_port_1, bond_port_2, bond_port_master] > + > + def set_third_stacked_bonded(self, bond_port, bond_mode): > + ''' > + set third level stacked bonded to check stacked limitation > + ''' > + specified_socket =3D 0 > + third_bond_port =3D self.create_bonded_device(bond_mode, > + specified_socket) > + expected_str =3D 'Too many levels of bonding' > + try: > + self.add_slave(third_bond_port, True, expected_str, *[bond_p= ort]) > + except Exception as e: > + self.logger.warning(e) > + finally: > + pass > + > + def duplicate_add_stacked_bonded(self, bond_port_1, bond_port_2, > + bond_port_master): > + ''' > + check if adding stacked bonded duplicately is forbidden > + ''' > + # check exception process > + expected_str =3D 'Slave device is already a slave of a bonded de= vice' > + # bond bonded device 2 to bonded device 4 > + # and check bond 0/2 config status > + self.add_slave(bond_port_master, False, expected_str, *[bond_por= t_1]) > + # bond bonded device 3 to bonded device 4 > + # and check bond 1/2 config status > + self.add_slave(bond_port_master, False, expected_str, *[bond_por= t_2]) > + > + def preset_stacked_bonded(self, slaveGrpOne, slaveGrpTwo, bond_mode)= : > + bond_port_1, bond_port_2, bond_port_master =3D self.set_stacked_= bonded( > + slaveGrp= One, > + slaveGrp= Two, > + bond_mod= e) > + # set test pmd > + cmds =3D [] > + cmds =3D [["port stop all", '']] > + portList =3D [slaveGrpOne[0], > + slaveGrpTwo[0], > + bond_port_1, > + bond_port_2, > + bond_port_master] > + cmds +=3D [["set portlist " + ",".join([str(port) > + for port in portList]), ''= ]] > + cmds +=3D[["port start all", ' ', 15], > + ["start", '']] > + self.execute_testpmd_cmd(cmds) > + time.sleep(5) > + > + return bond_port_1, bond_port_2, bond_port_master > + > + def preset_normal_bonded(self, bond_mode): > + ''' > + ''' > + slaveGrpOne =3D self.slaveGrpOne > + slaveGrpTwo =3D self.slaveGrpTwo > + > + bond_port_1, bond_port_2, bond_port_master =3D self.set_stacked_= bonded( > + slaveGr= pOne, > + slaveGr= pTwo, > + bond_mo= de) > + # set test pmd > + cmds =3D [] > + cmds +=3D [["port stop all", '']] > + portList =3D [slaveGrpOne[0], > + slaveGrpTwo[0], > + bond_port_1, > + bond_port_2, > + bond_port_master] > + cmds +=3D [["set portlist " + ",".join([str(port) for port in po= rtList]), > + '']] > + cmds +=3D[["port start all", ' ', 15], > + ["start", '']] > + self.execute_testpmd_cmd(cmds) > + time.sleep(5) > + > + def check_packet_transmission(self): > + pkt_count =3D 100 > + # send 100 packet to bonded device 2 and check bond 2/4 statist= ics > + pkt_now, summary =3D self.send_default_packet_to_slave( > + unbound_port, bond_port_= master, > + pkt_count=3Dpkt_count, *= *slaves) > + > + # send 100 packet to bonded device 3 and check bond 3/4 statist= ics > + pkt_now, summary =3D self.send_default_packet_to_slave( > + unbound_port, bond_port_= master, > + pkt_count=3Dpkt_count, *= *slaves) > + > + def convert_mac_str_into_int(self, mac_str): > + """ > + Translate 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_hash(self, dst_mac, src_mac): > + """ > + Generate the hash value with the source and destination MAC. > + """ > + dst_port_mac =3D self.convert_mac_str_into_int(dst_mac) > + src_port_mac =3D self.convert_mac_str_into_int(src_mac) > + src_xor_dest =3D dst_port_mac ^ src_port_mac > + xor_value_1 =3D src_xor_dest >> 32 > + xor_value_2 =3D (src_xor_dest >> 16) ^ (xor_value_1 << 16) > + xor_value_3 =3D src_xor_dest ^ (xor_value_1 << 32) ^ (xor_value_= 2 << 16) > + return htons(xor_value_1 ^ xor_value_2 ^ xor_value_3) > + > + def translate_ip_str_into_int(self, ip_str): > + """ > + Translate the IP type from the string into the int. > + """ > + ip_part_list =3D ip_str.split('.') > + ip_part_list.reverse() > + num =3D 0 > + ip_int =3D 0 > + for ip_part in ip_part_list: > + ip_part_int =3D int(ip_part) << (num * 8) > + ip_int +=3D ip_part_int > + num +=3D 1 > + return ip_int > + > + def ipv4_hash(self, dst_ip, src_ip): > + """ > + Generate the hash value with the source and destination IP. > + """ > + dst_ip_int =3D self.translate_ip_str_into_int(dst_ip) > + src_ip_int =3D self.translate_ip_str_into_int(src_ip) > + return htonl(dst_ip_int ^ src_ip_int) > + > + def udp_hash(self, dst_port, src_port): > + """ > + Generate the hash value with the source and destination port. > + """ > + return htons(dst_port ^ src_port) > + > + def policy_and_slave_hash(self, policy, **slaves): > + """ > + Generate the hash value by the policy and active slave number. > + : policy:'L2' , 'L23' or 'L34' > + """ > + source =3D self.get_static_ip_configs() > + > + dst_mac, dst_ip, dst_port =3D self.dst_pkt_configs > + > + hash_values =3D [] > + if len(slaves['active']) =3D=3D 0: > + return hash_values > + > + for src_mac, src_ip, src_port in source: > + if policy =3D=3D "L2": > + hash_value =3D self.mac_hash(dst_mac, src_mac) > + elif policy =3D=3D "L23": > + hash_value =3D self.mac_hash(dst_mac, src_mac) ^ \ > + self.ipv4_hash(dst_ip, src_ip) > + else: > + hash_value =3D self.ipv4_hash(dst_ip, src_ip) ^ \ > + self.udp_hash(dst_port, src_port) > + > + if policy in ("L23", "L34"): > + hash_value ^=3D hash_value >> 16 > + hash_value ^=3D hash_value >> 8 > + hash_value =3D hash_value % len(slaves['active']) > + hash_values.append(hash_value) > + > + return hash_values > + > + def slave_map_hash(self, port, order_ports): > + """ > + Find the hash value by the given slave port id. > + """ > + if len(order_ports) =3D=3D 0: > + return None > + else: > + #order_ports =3D order_ports.split() > + return order_ports.index(str(port)) > + > + def verify_active_backup_rx(self, unbound_port, bond_port, **slaves)= : > + """ > + Verify the RX packets are all correct in the active-backup mode. > + Parameters: > + """ > + return > + pkt_count =3D 100 > + pkt_now =3D {} > + > + self.logger.info('verify_active_backup_rx') > + slave_num =3D slaves['active'].__len__() > + active_flag =3D 1 if slave_num !=3D 0 else 0 > + pkt_now, summary =3D self.send_default_packet_to_slave( > + unbound_port, > + bond_port, > + pkt_count=3Dpkt= _count, > + **slaves) > + results =3D [] > + try: > + self.verify(pkt_now[bond_port][0] =3D=3D pkt_count * slave_n= um, > + "Not correct RX pkt on bond port in mode 1") > + except Exception as e: > + results.append(e) > + finally: > + pass > + > + try: > + if unbound_port: > + self.verify( > + pkt_now[unbound_port][0] =3D=3D pkt_count * acti= ve_flag, > + "Not correct TX pkt on unbound port in mode 1") > + except Exception as e: > + results.append(e) > + finally: > + pass > + > + try: > + # check inactive slaves statistics > + for slave in slaves['inactive']: > + self.verify(pkt_now[slave][0] =3D=3D 0, > + "Not correct RX pkt on inactive port in mode= 1") > + except Exception as e: > + results.append(e) > + finally: > + pass > + > + try: > + # check active slaves statistics > + for slave in slaves['active']: > + self.verify(pkt_now[slave][0] =3D=3D pkt_count, > + "Not correct RX pkt on active port in mode 1= ") > + except Exception as e: > + results.append(e) > + finally: > + pass > + > + if not results: > + for item in results: > + self.logger.error(e) > + raise VerifyFailure("verify_active_backup_rx exception") > + > + return pkt_now, summary > + > + def verify_stacked_active_backup_rx(self, master_bonded, slave_bonde= d, > + **slaves): > + """ > + Verify the RX packets are all correct in the active-backup mode = with > + stacked bonded device. second level bonded device's statistics s= hould > + be the sum of slave bonded devices statistics. > + """ > + pkt_count =3D 100 > + pkt_now =3D {} > + > + self.logger.info('verify_stacked_active_backup_rx') > + slave_num =3D slaves['active'].__len__() > + active_flag =3D 1 if slave_num !=3D 0 else 0 > + pkt_now, summary =3D self.send_default_packet_to_slave( > + None, > + slave_bonded, > + pkt_count=3Dpkt= _count, > + **slaves) > + results =3D [] > + try: > + self.verify(pkt_now[slave_bonded][0] =3D=3D pkt_count * slav= e_num, > + "Not correct RX pkt on bond port in mode 1") > + except Exception as e: > + results.append(e) > + finally: > + pass > + > + try: > + if master_bonded: > + self.verify( > + pkt_now[master_bonded][0] =3D=3D pkt_count * active_= flag, > + "Not correct TX pkt on unbound port in mode 1") > + pass > + except Exception as e: > + results.append(e) > + finally: > + pass > + > + try: > + # check inactive slaves statistics > + for slave in slaves['inactive']: > + self.verify(pkt_now[slave][0] =3D=3D 0, > + "Not correct RX pkt on inactive port in mode= 1") > + except Exception as e: > + results.append(e) > + finally: > + pass > + > + try: > + # check active slaves statistics > + for slave in slaves['active']: > + self.verify(pkt_now[slave][0] =3D=3D pkt_count, > + "Not correct RX pkt on active port in mode 1= ") > + except Exception as e: > + results.append(e) > + finally: > + pass > + > + if results: > + for item in results: > + self.logger.error(e) > + raise VerifyFailure("verify_stacked_active_backup_rx excepti= on") > + > + return pkt_now, summary > + > + def verify_xor_rx(self, unbound_port, bond_port, **slaves): > + """ > + Verify receiving the pcakets correctly in the XOR mode. > + Parameters: > + : unbound_port: the unbonded port id > + : bond_port: the bonded device port id > + """ > + pkt_count =3D 100 > + pkt_now =3D {} > + > + pkt_now, summary =3D self.send_default_packet_to_slave( > + unbound_port, > + bond_port, > + pkt_count=3Dpkt= _count, > + **slaves) > + > + for slave in slaves['active']: > + self.verify(pkt_now[slave][0] =3D=3D pkt_count, > + "Slave have error RX packet in XOR") > + for slave in slaves['inactive']: > + self.verify(pkt_now[slave][0] =3D=3D 0, > + "Slave have error RX packet in XOR") > + > + if unbound_port: > + self.verify( > + pkt_now[unbound_port][0] =3D=3D pkt_count * len(slaves['= active']), > + "Unbonded device have error TX packet in XOR") > + > + def verify_xor_tx(self, unbound_port, bond_port, policy, > + vlan_tag=3DFalse, **slaves): > + """ > + Verify that transmitting the packets correctly in the XOR mode. > + Parameters: > + : unbound_port: the unbonded port id > + : bond_port: the bonded device port id > + : policy:'L2' , 'L23' or 'L34' > + : vlan_tag: False or True > + """ > + pkt_count =3D 100 > + pkt_now =3D {} > + try: > + pkt_now, summary =3D self.send_customized_packet_to_unbound_= port( > + unbound_port, > + bond_port, > + policy, > + vlan_tag=3DFalse= , > + pkt_count=3Dpkt_= count, > + **slaves) > + except Exception as e: > + self.logger.error(traceback.format_exc()) > + finally: > + pass > + > + hash_values =3D self.policy_and_slave_hash(policy, **slaves) > + order_ports =3D self.get_bonding_info(bond_port, 'active_slaves'= ) > + for slave in slaves['active']: > + slave_map_hash =3D self.slave_map_hash(slave, order_ports) > + self.verify( > + pkt_now[slave][0] =3D=3D pkt_count * hash_values.count(slave= _map_hash), > + "XOR load balance transmit error on the link up port") > + for slave in slaves['inactive']: > + self.verify( > + pkt_now[slave][0] =3D=3D 0, > + "XOR load balance transmit error on the link down port") > + > + @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 freebsd") > + self.dut_ports =3D self.dut.get_ports() > + > + self.port_mask =3D utils.create_mask(self.dut_ports) > + > + #self.verify(len(self.dut_ports) >=3D 4, "Insufficient 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")) > + > + # separate ports into two group > + sep_index =3D len(self.dut_ports)/2 > + self.slaveGrpOne =3D self.dut_ports[:sep_index] > + self.slaveGrpTwo =3D self.dut_ports[sep_index:] > + # testpmd initialization > + self.testpmd =3D PmdOutput(self.dut) > + self.testpmd_status =3D 'close' > + self.tester_bond =3D "bond0" > + self.dst_pkt_configs =3D [] > + > + def tear_down_all(self): > + """ > + Run after each test suite. > + """ > + pass > + > + def set_up(self): > + """ > + Run before each test case. > + """ > + pass > + > + def tear_down(self): > + """ > + Run after each test case. > + """ > + > + def backup_check_stacked_bonded_traffic(self): > + ''' > + ''' > + self.logger.info("begin checking stacked bonded transmission") > + self.start_testpmd() > + slaveGrpOne =3D self.slaveGrpOne > + slaveGrpTwo =3D self.slaveGrpTwo > + bond_port_1, bond_port_2, bond_port_master =3D \ > + self.preset_stacked_bond= ed( > + slaveGrpOne, > + slaveGrpTwo, > + MODE_ACTIVE_= BACKUP) > + results =3D [] > + # check first bonded device > + try: > + self.logger.info('check first bonded device') > + slaves =3D {} > + slaves['active'] =3D slaveGrpOne > + slaves['inactive'] =3D [] > + self.verify_stacked_active_backup_rx(None, bond_port_1, **sl= aves) > + except Exception as e: > + results.append(e) > + finally: > + pass > + > + try: > + # check second bonded device > + self.logger.info('check second bonded device') > + slaves =3D {} > + slaves['active'] =3D slaveGrpTwo > + slaves['inactive'] =3D [] > + self.verify_stacked_active_backup_rx(None, bond_port_2, **sl= aves) > + except Exception as e: > + results.append(e) > + finally: > + pass > + > + pkt_now, summary =3D 0, 0 > + try: > + self.logger.info('check master bonded device') > + # check top bonded device > + slaves =3D {} > + slaves['active'] =3D slaveGrpOne + slaveGrpTwo > + slaves['inactive'] =3D [] > + pkt_now, summary =3D self.verify_stacked_active_backup_rx(No= ne, > + bond_port_master, **= slaves) > + except Exception as e: > + results.append(e) > + finally: > + pass > + > + self.close_testpmd() > + if results: > + for item in results: > + self.logger.error(e) > + msg =3D "backup_check_stacked_bonded_traffic exception" > + raise VerifyFailure(msg) > + else: > + return pkt_now, summary > + > + def backup_check_stacked_one_slave_down(self): > + self.logger.info("begin checking backup stacked one slave down") > + self.start_testpmd() > + #------------------------------- > + # boot up testpmd > + mode =3D MODE_ACTIVE_BACKUP > + slaveGrpOne =3D self.slaveGrpOne > + slaveGrpTwo =3D self.slaveGrpTwo > + bond_port_1, bond_port_2, bond_port_master =3D \ > + self.preset_stacked_bonded(slave= GrpOne, > + slave= GrpTwo, > + mode) > + results =3D [] > + # check packet transmission when one slave of first level bonded= device > + #------------------------------- > + pkt_now, summary =3D 0, 0 > + try: > + # show one slave port of first level bonded device > + primary_slave =3D slaveGrpOne[0] > + self.logger.info("down one slave port of bond_port_1") > + self.config_tester_port_by_number(primary_slave, "down") > + primary_port =3D self.get_bonding_info(bond_port_1, 'primary= ') > + msg =3D "down status slave hasn't been remove from active sl= aves" > + self.verify(primary_port !=3D primary_slave, msg) > + #------------------------------------------------------ > + slaves =3D {} > + primary_port, active_slaves =3D self.get_active_slaves(prima= ry_slave, > + bond_po= rt_1) > + slaves['active'] =3D [primary_port] > + slaves['active'].extend(active_slaves) > + slaves['inactive'] =3D [self.dut_ports[primary_slave]] > + pkt_now, summary =3D self.verify_stacked_active_backup_rx( > + None, > + bond_port_ma= ster, > + **slaves) > + except Exception as e: > + results.append(e) > + finally: > + self.config_tester_port_by_number(primary_slave, "up") > + > + self.close_testpmd() > + if results: > + for item in results: > + self.logger.error(e) > + raise VerifyFailure("backup_check_stacked_one_slave_down exc= eption") > + > + def check_stacked_xor_rx(self): > + results =3D [] > + self.logger.info("begin checking xor stacked transmission") > + self.start_testpmd() > + #------------------------------------- > + #------------------------------- > + # boot up testpmd > + try: > + mode =3D MODE_XOR_BALANCE > + slaveGrpOne =3D self.slaveGrpOne > + slaveGrpTwo =3D self.slaveGrpTwo > + bond_port_1, bond_port_2, bond_port_master =3D \ > + self.preset_stacked_bonded( slaveGrpOne, slaveGrpTwo, mo= de) > + slaves =3D {} > + slaves['active'] =3D slaveGrpOne + slaveGrpTwo > + slaves['inactive'] =3D [] > + > + self.verify_xor_rx(None, bond_port_master, **slaves) > + except Exception as e: > + results.append(e) > + self.logger.error(traceback.format_exc()) > + finally: > + self.close_testpmd() > + #------------------------------------- > + if results: > + for item in results: > + self.logger.error(e) > + raise VerifyFailure("check_stacked_xor_rx exception !") > + > + def xor_check_stacked_rx_one_slave_down(self): > + """ > + Verify that transmitting packets correctly in the XOR mode, > + when bringing any one slave of the bonding device link down. > + """ > + results =3D [] > + self.logger.info("begin xor_check_stacked_rx_one_slave_down") > + #------------------------------- > + # boot up testpmd > + self.start_testpmd() > + try: > + #------------------------------- > + mode =3D MODE_ACTIVE_BACKUP > + slaveGrpOne =3D self.slaveGrpOne > + #slaveGrpTwo =3D self.slaveGrpTwo[:-1] > + slaveGrpTwo =3D self.slaveGrpTwo > + bond_port_1, bond_port_2, bond_port_master =3D \ > + self.preset_stacked_bonded( slaveGrpOne, > + slaveGrpTwo, > + mode) > + primary_slave =3D slaveGrpOne[0] > + self.logger.info("down one slave port of bond_port_1") > + self.config_tester_port_by_number(primary_slave, "down") > + primary_port =3D self.get_bonding_info(bond_port_1, 'primary= ') > + msg =3D "down status slave hasn't been remove from active sl= aves" > + self.verify(primary_port !=3D primary_slave, msg) > + #------------------------- > + # add first bonded > + primary_port, active_slaves =3D self.get_active_slaves(prima= ry_slave, > + bond_po= rt_1) > + slaves =3D {} > + slaves['active'] =3D [primary_port] > + slaves['active'].extend(active_slaves) > + # add second bonded > + primary_slave =3D slaveGrpOne[0] > + primary_port_2, active_slaves_2 =3D self.get_active_slaves( > + primary_slav= e, > + bond_port_2) > + slaves['active'] +=3D [primary_port_2] > + slaves['active'] +=3D active_slaves_2 > + if primary_slave in slaves['active']: > + slaves['active'].remove(primary_slave) > + msg =3D "{0} should not be in active slaves list".format= ( > + primary_= slave) > + self.logger.warning() > + > + slaves['inactive'] =3D []#[primary_slave] > +# self.verify_xor_tx(primary_slave, > +# bond_port_master, > +# "L2", False, > +# **slaves) > + self.verify_xor_rx(None, bond_port_master, **slaves) > + except Exception as e: > + results.append(e) > + self.logger.error(traceback.format_exc()) > + finally: > + self.config_tester_port_by_number(primary_slave, "up") > + self.close_testpmd() > + > + if results: > + for item in results: > + self.logger.error(e) > + raise VerifyFailure("xor_check_stacked_rx_one_slave_down fai= led") > + else: > + #return pkt_now, summary > + pass > + > + def test_basic_behav(self): > + ''' > + allow a bonded device to be added to another bonded device. > + There's two limitations to create master bonding: > + > + - Total depth of nesting is limited to two levels, > + - 802.3ad mode is not supported if one or more slaves is a bond= device > + > + note: There 802.3ad mode can not be supported on this bond devic= e. > + > + This case is aimed at testing basic stacked bonded device comman= ds. > + > + ''' > + #------------------------------------------------ > + # check stacked bonded status, except mode 4 (802.3ad) > + mode_list =3D[MODE_ROUND_ROBIN, > + MODE_ACTIVE_BACKUP, > + MODE_XOR_BALANCE, > + MODE_BROADCAST, > + MODE_TLB_BALANCE, > + MODE_ALB_BALANCE] > + slaveGrpOne =3D self.slaveGrpOne > + slaveGrpTwo =3D self.slaveGrpTwo > + check_result =3D [] > + for bond_mode in mode_list: > + self.logger.info("begin mode <{0}> checking".format(bond_mod= e)) > + # boot up testpmd > + self.start_testpmd() > + try: > + self.logger.info("check bonding mode <{0}>".format(bond_= mode)) > + # set up stacked bonded status > + bond_port_1, bond_port_2, bond_port_master =3D \ > + self.set_stacked_bonded(slaveGrpOne, slaveGrpTwo, > + bond_mode) > + # check duplicate add slave > + self.duplicate_add_stacked_bonded(bond_port_1, bond_port= _2, > + bond_port_master) > + # check stacked limitation > + self.set_third_stacked_bonded(bond_port_master, bond_mod= e) > + # quit testpmd, it is not supported to reset testpmd > + self.logger.info("mode <{0}> done !".format(bond_mode)) > + check_result.append([bond_mode, None]) > + except Exception as e: > + check_result.append([bond_mode, e]) > + self.logger.error(e) > + finally: > + self.close_testpmd() > + time.sleep(5) > + #------------ > + # 802.3ad mode is not supported > + # if one or more slaves is a bond device > + # so it should raise a exeption > + msg =3D '' > + try: > + # boot up testpmd > + self.start_testpmd() > + # set up stacked bonded status > + self.set_stacked_bonded(slaveGrpOne, slaveGrpTwo, MODE_LACP) > + # quit testpmd, it is not supported to reset testpmd > + msg =3D ("802.3ad mode hasn't been forbidden to " > + "use stacked bonded setting") > + check_result.append([MODE_LACP, msg]) > + except Exception as e: > + check_result.append([MODE_LACP, None]) > + finally: > + self.close_testpmd() > + > + exception_count =3D 0 > + for bond_mode, e in check_result: > + msg =3D "mode <{0}>".format(bond_mode) > + if e: > + self.logger.info(msg) > + self.logger.error(e) > + exception_count +=3D 1 > + else: > + self.logger.info(msg + ' done !') > + # if some checking item is failed, raise exception > + if exception_count: > + raise VerifyFailure('some test items failed') > + else: > + self.logger.info('all test items have done !') > + self.close_testpmd() > + > + def test_mode_backup_rx(self): > + """ > + Verify receiving and transmitting the packets correctly > + in the active-backup mode. > + """ > + stacked_stats =3D self.backup_check_stacked_bonded_traffic() > + > + def test_mode_backup_one_slave_down(self): > + """ > + Verify that receiving and transmitting the pcakets correctly > + in the active-backup mode, when bringing any one slave of > + the bonding device link down. > + """ > + if len(self.dut_ports) >=3D 4: > + self.backup_check_stacked_one_slave_down() > + else: > + msg =3D "ports less than 2, ignore stacked one slave down ch= eck" > + self.logger.warning(msg) > + > + def test_mode_xor_rx(self): > + """ > + Verify that receiving packets correctly in the XOR mode. > + """ > + self.check_stacked_xor_rx() > + > + def test_mode_xor_rx_one_slave_down(self): > + """ > + Verify that transmitting packets correctly in the XOR mode, > + when bringing any one slave of the bonding device link down. > + """ > + if len(self.dut_ports) >=3D 4: > + self.xor_check_stacked_rx_one_slave_down() > + else: > + msg =3D "ports less than 2, ignore stacked one slave down ch= eck" > + self.logger.warning(msg) > + > -- > 1.9.3