[dts] [PATCH V1 2/6] pmd_bonded_8023ad: upload automation script

Chen, Zhaoyan zhaoyan.chen at intel.com
Mon Jan 21 08:19:36 CET 2019


Yufeng,

- Please extract the common functions into common file and share between each bond test suite.
- Remove "Switch" related code. 




Regards,
Zhaoyan Chen


> -----Original Message-----
> From: dts [mailto:dts-bounces at dpdk.org] On Behalf Of yufengx.mo at intel.com
> Sent: Wednesday, June 6, 2018 1:38 PM
> To: dts at dpdk.org
> Cc: Mo, YufengX <yufengx.mo at intel.com>
> Subject: [dts] [PATCH V1 2/6] pmd_bonded_8023ad: upload automation script
> 
> From: yufengmx <yufengx.mo at intel.com>
> 
> 
> This automation script is for pmd bonded 8023ad feature.
> 
> IEEE 802.3ad Dynamic link aggregation.  Creates aggregation groups that share
> the same speed and duplex settings.  Utilizes all slaves in the active
> aggregator according to the 802.3ad specification. Slave selection for outgoing
> traffic is done according to the transmit hash policy.
> 
> Signed-off-by: yufengmx <yufengx.mo at intel.com>
> ---
>  tests/TestSuite_pmd_bonded_8023ad.py | 2147
> ++++++++++++++++++++++++++++++++++
>  1 file changed, 2147 insertions(+)
>  create mode 100644 tests/TestSuite_pmd_bonded_8023ad.py
> 
> 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 = 0
> +SOCKET_1 = 1
> +MODE_LACP = 4
> +FRAME_SIZE_64 = 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 = 1e10
> +
> +    def __init__(self, func, name=None, **kwargs):
> +        super(DaemonThread, self).__init__()
> +        self._is_start = threading.Event()
> +        self._is_stopped  = threading.Event()
> +        self.func = func
> +        self.daemon       = True
> +        self.name         = name or self.__class__.__name__
> +        self.kwargs = kwargs
> +        self.start()
> +
> +    def on_crash(self, msg, *fmt, **kwargs):
> +        #print(msg.format(*fmt), file=sys.stderr)
> +        print msg.format(*fmt)
> +        exc_info = 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 = 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 = ["bandwidth", "stable", "count"]
> +    DEDICATED_QUEUES = ['disable', 'enable']
> +    #
> +    # On tester platform, packet transmission
> +    #
> +    def get_stats(self, portid, flow):
> +        """
> +        get testpmd port statistic
> +        """
> +        _portid = int(portid) if isinstance(portid, (str, unicode)) else portid
> +        info = self.testpmd.get_pmd_stats(_portid)
> +        _kwd = ["-packets", "-missed", "-bytes"]
> +        kwd = map(lambda x: flow.upper() + x, _kwd)
> +        result =  [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() == 'freebsd':
> +            self.tester.admin_ports(port_name, status)
> +        else:
> +            eth = 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 = "port stop %d"%number
> +        self.d_console(cmd)
> +        # stop peer port on tester
> +        port_name = self.tester.get_local_port(self.dut_ports[number])
> +        self.config_tester_port( port_name, status)
> +        time.sleep(5)
> +        cur_status = self.get_port_info(number, 'link_status')
> +        self.logger.info("port {0} is [{1}]".format(number, cur_status))
> +        if cur_status != 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 = '0x'
> +        for mac_part in mac_str.split(':'):
> +            mac_hex += mac_part
> +        return int(mac_hex, 16)
> +
> +    def mac_int_to_str(self, mac_int):
> +        """
> +        Translate the MAC type from the string into the int.
> +        """
> +        temp = hex(mac_int)[2:]
> +        b = []
> +        [b.append(temp[n:n+2]) for n in range(len(temp)) if n % 2 == 0 ]
> +        new_mac = ":".join(b)
> +        return new_mac
> +
> +    def ip_str_to_int(self, ip_str):
> +        """
> +        convert the IP type from the string into the int.
> +        """
> +        ip_int = socket.ntohl(struct.unpack(
> +                                "I", socket.inet_aton(str(ip_str)))[0])
> +        return ip_int
> +
> +    def ip_int_to_str(self, ip_int):
> +        """
> +        convert the IP type from the int into the string.
> +        """
> +        ip_str = socket.inet_ntoa(struct.pack('I', socket.htonl(ip_int)))
> +        return ip_str
> +
> +    def increase_ip(self, ip, step=1):
> +        ''' ip: string format '''
> +        _ip_int = self.ip_str_to_int(ip)
> +        new_ip = self.ip_int_to_str(_ip_int + step)
> +        return new_ip
> +
> +    def increase_mac(self, mac, step=1):
> +        ''' mac: string format '''
> +        _mac_int = self.mac_str_to_int(mac)
> +        new_mac = self.mac_int_to_str(_mac_int+step)
> +        return new_mac
> +
> +    def increase_port(self, port, step=1):
> +        ''' port: int format '''
> +        new_port = port + step
> +        return new_port
> +
> +    def increase_mac_ip_port(self, step=1):
> +        # get src layer setting
> +        ori_config = ('52:00:00:00:00:03', '10.239.129.65', 61)
> +        mac, ip, port = ori_config
> +        return (self.increase_mac(mac, step),
> +                self.increase_ip(ip, step),
> +                self.increase_port(port, step))
> +
> +    def set_stream2(self, stm_names=None):
> +        ''' using packet.py module to create a stream '''
> +        #----------------------------------------------------------------------
> +        # set streams for traffic
> +        pkt_configs = {
> +        # UDP_1:
> +        #    Frame Data/Protocols: Ethernet 2 0800, IPv4,UDP/IP, Fixed 64.
> +        #    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 = []
> +        for stm_name in stm_names:
> +            if stm_name not in pkt_configs.keys():
> +                continue
> +            values = pkt_configs[stm_name]
> +            # keep a copy of pcap for debug
> +            savePath = os.sep.join([self.target_source,
> +                                    "pkt_{0}.pcap".format(stm_name)])
> +            pkt_type = values.get('type')
> +            pkt_layers = values.get('pkt_layers')
> +            pkt = Packet(pkt_type=pkt_type)
> +            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 = FRAME_SIZE_64
> +        headers_size = sum(map(lambda x: HEADER_SIZE[x],
> +                               ['eth', 'ip', pkt_type]))
> +        pktlen = 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 = {}
> +        ether = {}
> +        dot1q = {}
> +        ip = {}
> +        udp = {}
> +
> +        try:
> +            dut_dst_port = self.dut_ports[dst_port]
> +        except Exception, e:
> +            dut_dst_port = dst_port
> +        # create src/dst mac address
> +        if not ether_ip.get('ether'):
> +            ether['dst_mac'] = self.dut.get_mac_address(dut_dst_port)
> +            ether['src_mac'] = "52:00:00:00:00:00"
> +        else:
> +            # dst
> +            if not ether_ip['ether'].get('dst_mac'):
> +                ether['dst_mac'] = self.dut.get_mac_address(dut_dst_port)
> +            else:
> +                ether['dst_mac'] = ether_ip['ether']['dst_mac']
> +            # src
> +            if not ether_ip['ether'].get('src_mac'):
> +                ether['src_mac'] = "52:00:00:00:00:00"
> +            else:
> +                ether['src_mac'] = 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'] = '1'
> +            else:
> +                dot1q['vlan'] = ether_ip['dot1q']['vlan']
> +        # create src/dst ip address
> +        if not ether_ip.get('ip'):
> +            ip['dst_ip'] = "10.239.129.88"
> +            ip['src_ip'] = "10.239.129.65"
> +        else:
> +            if not ether_ip['ip'].get('dst_ip'):
> +                ip['dst_ip'] = "10.239.129.88"
> +            else:
> +                ip['dst_ip'] = ether_ip['ip']['dst_ip']
> +            if not ether_ip['ip'].get('src_ip'):
> +                ip['src_ip'] = "10.239.129.65"
> +            else:
> +                ip['src_ip'] = ether_ip['ip']['src_ip']
> +        # create src/dst port number
> +        if not ether_ip.get('udp'):
> +            udp['dst_port'] = 53
> +            udp['src_port'] = 53
> +        else:
> +            if not ether_ip['udp'].get('dst_port'):
> +                udp['dst_port'] = 53
> +            else:
> +                udp['dst_port'] = ether_ip['udp']['dst_port']
> +            if not ether_ip['udp'].get('src_port'):
> +                udp['src_port'] = 53
> +            else:
> +                udp['src_port'] = ether_ip['udp']['src_port']
> +
> +        ret_ether_ip['ether'] = ether
> +        ret_ether_ip['dot1q'] = dot1q
> +        ret_ether_ip['ip'] = ip
> +        ret_ether_ip['udp'] = udp
> +
> +        return ret_ether_ip
> +
> +    def set_stream(self, dst_port, src_port=False, frame_size=FRAME_SIZE_64,
> +                    pkt_type='tcp', **slaves):
> +        # get dst layer setting
> +        dst_mac = self.get_port_info(dst_port, 'mac')
> +        destport = 53
> +        nutmac = dst_mac
> +        destip = '10.239.129.88'
> +        # packet size
> +        pktlen = self.get_pkt_len(pkt_type)
> +        self.packet_types = {}
> +        for packet_id in range(len(slaves['active'])):
> +            # src config
> +            srcmac, srcip, srcport = self.increase_mac_ip_port(packet_id)
> +            # config layer format
> +            pkt = Packet(pkt_type=pkt_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] = pkt
> +            # save a pcap file for debug convenience
> +            savePath = 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=1, interval=0.01):
> +        for pkt_id in sorted(self.packet_types.keys()):
> +            pkt = self.packet_types[pkt_id].pktgen.pkt
> +            sendp(pkt, iface=tx_iface, inter=interval, verbose=False,
> +                  count=count)
> +            wait_time  = 0.0001
> +
> +    def send_pkt_multi_stream(self, intf, count):
> +        sendp(self.pkt, iface=intf, count=count)
> +
> +    def send_packets_by_ixia(self, intf, count=1):
> +        send_pkts = []
> +        self.tgen_input = []
> +        tgen_input = self.tgen_input
> +        # generate packet contain multi stream
> +        for pkt in self.packet_types.values():
> +            send_pkts.append(pkt.pktgen.pkt)
> +        ixia_pkt = os.sep.join([self.dut.base_dir, 'lacp_tx.pcap'])
> +        wrpcap(ixia_pkt, send_pkts)
> +        #----------------------------------------------------------------
> +        # set packet for send
> +        # pause frame basic configuration
> +        pause_time = 65535
> +        pause_rate = 0.50
> +        # run ixia testing
> +        frame_size = 64
> +        # calculate number of packets
> +        expect_pps = self.wirespeed(self.nic, frame_size, 1) * 1000000.0
> +        # get line rate
> +        linerate = expect_pps * (frame_size + 20) * 8
> +        # calculate default sleep time for one pause frame
> +        sleep = (1 / linerate) * pause_time * 512
> +        # calculate packets dropped in sleep time
> +        self.n_pkts = int((sleep / (1 / expect_pps)) * (1 / pause_rate))
> +        #----------------------------------------------------------------
> +        tester_port = self.tester.get_local_port(self.dut_ports[0])
> +        tgen_input.append((tester_port,
> +                           tester_port,
> +                           ixia_pkt))
> +        # run latency stat statistics
> +        rate_percent = self.rate_percent
> +        self.tester.loop_traffic_generator_throughput(tgen_input,
> +                                                      rate_percent)
> +
> +    def stop_ixia(self, data_types='packets'):
> +        # get ixia statistics
> +        line_rate = self.tester.get_port_line_rate()
> +        rx_bps, rx_pps = \
> +        self.tester.stop_traffic_generator_throughput_loop(self.tgen_input)
> +        output = self.tester.traffic_get_port_stats(self.tgen_input)
> +        self.cur_data['ixia statistics'] = []
> +        append = self.cur_data['ixia statistics'].append
> +        append('send packets: {0}'.format(output[0]))
> +        append('line_rate: {0}'.format(line_rate[0]))
> +        append('rate_percent: {0}%'.format(self.rate_percent))
> +
> +    def send_packets(self, intf, pkts=None, interval=0.01 ,count=1):
> +        send_pkts = []
> +        for pkt in pkts:
> +            send_pkts.append(pkt.pktgen.pkt)
> +        sendp(send_pkts, iface=intf, inter=interval,
> +              verbose=False, count=count)
> +
> +    def send_multi_packet_quick(self, tx_iface, count=1):
> +        self.send_packets(tx_iface, self.packet_types.values(), count=count)
> +    #
> +    # On dut, dpdk testpmd
> +    #
> +    def preset_testpmd(self, core_mask, options='', eal_param=''):
> +        try:
> +            self.testpmd.start_testpmd( core_mask, param=' '.join(options),
> +                                        eal_param=eal_param)
> +        # add exception for debug usage
> +        except TimeoutException:
> +            try:
> +                self.check_process_exist() # used for debug
> +            except Exception as e:
> +                self.testpmd_status = 'close'
> +            finally:
> +                pass
> +            msg = "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 = list()
> +        time.sleep(1)
> +
> +    def check_process_status(self, process_name='testpmd'):
> +        cmd = "ps aux | grep -i %s | grep -v grep | awk {'print $2'}"%(
> +                                                                process_name)
> +        out = self.dut.alt_session.send_expect(cmd, "# ", 10)
> +        status = True if out != "" else False
> +        return status
> +    # use for debug
> +    def check_process_exist(self, process_name='testpmd'):
> +        status = self.check_process_status(process_name)
> +        if not status:
> +            msg = "{0} process quit exceptional".format(process_name)
> +            out = self.dut.session.session.get_output_all()
> +            self.logger.info(out)
> +            raise VerifyFailure(msg)
> +
> +    def d_console(self, cmds):
> +        if len(cmds) == 0:
> +            return
> +        # check if cmds is string
> +        if isinstance(cmds, str):
> +            timeout = 10
> +            cmds = [[cmds, '', timeout]]
> +        # check if cmds is only one command
> +        if not isinstance(cmds[0], list):
> +            cmds = [cmds]
> +        if len(cmds) > 1:
> +            outputs = []
> +        else:
> +            outputs = ''
> +        for item in cmds:
> +            expected_items = item[1]
> +            if expected_items and isinstance(expected_items, (list, tuple)):
> +                check_output = True
> +                expected_str = expected_items[0] or 'testpmd> '
> +            else:
> +                check_output = False
> +                expected_str = expected_items or 'testpmd> '
> +            timeout = int(item[2]) if len(item) == 3 else 5
> +            #----------------------------------------------------------------
> +            # run command on session
> +            try:
> +                console = self.testpmd.execute_cmd
> +                msg_pipe = self.testpmd.get_output
> +                output = console(item[0], expected_str, timeout)
> +                output = msg_pipe(timeout) if not output else output
> +            except TimeoutException:
> +                try:
> +                    self.check_process_exist() # used for debug
> +                except Exception as e:
> +                    self.testpmd_status = 'close'
> +                finally:
> +                    pass
> +                msg = "execute '{0}' timeout".format(item[0])
> +                output = out = self.dut.session.session.get_output_all()
> +                self.logger.error(output)
> +                raise TimeoutException(msg)
> +            finally:
> +                pass
> +
> +            if len(cmds) > 1:
> +                outputs.append(output)
> +            else:
> +                outputs = output
> +            if check_output and len(expected_items) >= 2:
> +                self.logger.info(output)
> +                expected_output = expected_items[1]
> +                check_type = True if len(expected_items) == 2 \
> +                                  else expected_items[2]
> +                if check_type and expected_output in output:
> +                    msg = "expected '{0}' is in output".format(expected_output)
> +                    self.logger.info(msg)
> +                elif not check_type and expected_output not in output:
> +                    fmt = "unexpected '{0}' is not in output"
> +                    msg = fmt.format(expected_output)
> +                    self.logger.info(msg)
> +                else:
> +                    status = "isn't in" if check_type else "is in"
> +                    msg = "[{0}] {1} output".format(expected_output, status)
> +                    self.logger.error(msg)
> +                    raise VerifyFailure(msg)
> +
> +        time.sleep(2)
> +        return outputs
> +
> +    def start_testpmd(self, eal_option=''):
> +        if self.testpmd_status == 'running':
> +            return
> +        if self.is_perf:
> +            options = map(lambda x: "--" + x, [
> +                               # 'burst=32',
> +                               # 'rxfreet=32',
> +                               # 'mbcache=250',
> +                               # 'txpt=32',
> +                               # 'rxht=8',
> +                               # 'rxwt=0',
> +                               # 'txfreet=32',
> +                               # 'txrst=32',
> +                               # 'txqflags=0xf01'
> +                                 ])
> +            #options = '' #TBD
> +            offloadd = '0x1fbf' if self.driver == 'i40e' else '0x2203f'
> +            options = ["--tx-offloads={0}".format(offloadd)]
> +        else:
> +            offloadd = '0x1fbf' if self.driver == 'i40e' else '0x2203f'
> +            options = ["--tx-offloads={0}".format(offloadd)]
> +        # link eal option and testpmd options
> +        #options = [eal_option, options] if eal_option else [options]
> +        # boot up testpmd
> +        hw_mask = 'all'
> +        #hw_mask = '1S/4C/1T'
> +        self.preset_testpmd_cmds = ['port stop all', '', 15]
> +        self.preset_testpmd(hw_mask, options, eal_param=eal_option)
> +        self.testpmd_status = 'running'
> +
> +    def stop_testpmd(self):
> +        time.sleep(1)
> +        testpmd_cmds =[['port stop all', '', 15],
> +                       ['show port stats all', ''],
> +                       ['stop', ''],
> +                       ]
> +        output = self.d_console(testpmd_cmds)
> +        time.sleep(1)
> +        return output
> +
> +    def close_testpmd(self):
> +        if self.testpmd_status == 'close':
> +            return None
> +        output = self.stop_testpmd()
> +        time.sleep(1)
> +        self.testpmd.quit()
> +        time.sleep(10)
> +        if self.check_process_status():
> +            raise VerifyFailure("testpmd close failed")
> +        else:
> +            self.logger.info("close testpmd sucessful")
> +        self.testpmd_status = '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 = r"(?<=%s)%s" % (key_str, regx_str)
> +            s = re.compile(pattern)
> +            res = s.search(string)
> +            if type(res).__name__ == 'NoneType':
> +                self.logger.warning("{0} hasn't match anything".format(key_str))
> +                return ' '
> +            else:
> +                return res.group(0)
> +        elif isinstance(key_str, (list, tuple)):
> +            for key in key_str:
> +                pattern = r"(?<=%s)%s" % (key, regx_str)
> +                s = re.compile(pattern)
> +                res = s.search(string)
> +                if type(res).__name__ == 'NoneType':
> +                    continue
> +                else:
> +                    return res.group(0)
> +            else:
> +                self.logger.warning("all key_str hasn't match anything")
> +                return ' '
> +
> +    #
> +    # 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 <port num>'
> +        """
> +        key_str, regx_str = args
> +        out = self.d_console("show port info %d" % port_id)
> +        find_value = self.get_value_from_str(key_str, regx_str, out)
> +        return find_value
> +
> +    def get_detail_from_port_info(self, port_id, args):
> +        if isinstance(args[0], (list, tuple)):
> +            return [self._get_detail_from_port_info(port_id, sub_args)
> +                        for sub_args in args]
> +        else:
> +            return self._get_detail_from_port_info(port_id, args)
> +
> +    def get_port_info(self, port_id, info_type):
> +        '''
> +        Get the specified port information by its output message format
> +        '''
> +        info_set = {
> +            'mac':            ["MAC address: ", "([0-9A-F]{2}:){5}[0-9A-F]{2}"],
> +            'connect_socket': ["Connect to socket: ", "\d+"],
> +            'memory_socket':  ["memory allocation on the socket: ", "\d+"],
> +            'link_status':    ["Link status: ", "\S+"],
> +            'link_speed':     ["Link speed: ", "\d+"],
> +            'link_duplex':    ["Link duplex: ", "\S+"],
> +            'promiscuous_mode': ["Promiscuous mode: ", "\S+"],
> +            'allmulticast_mode':["Allmulticast mode: ", "\S+"],
> +            'vlan_offload':     [["strip ", "\S+"],
> +                                 ['filter', "\S+"],
> +                                 ['qinq\(extend\) ', "\S+"]],
> +            'queue_config': [
> +                         ["Max possible RX queues: ", "\d+"],
> +                         ['Max possible number of RXDs per queue: ', "\d+"],
> +                         ['Min possible number of RXDs per queue: ', "\d+"],
> +                         ["Max possible TX queues: ", "\d+"],
> +                         ['Max possible number of TXDs per queue: ', "\d+"],
> +                         ['Min possible number of TXDs per queue: ', "\d+"],]
> +            }
> +
> +        if info_type in info_set.keys():
> +            return self.get_detail_from_port_info(port_id, info_set[info_type])
> +        else:
> +            return None
> +
> +    def get_bonding_config(self, config_content, args):
> +        """
> +        Get info by executing the command "show bonding config".
> +        """
> +        key_str, regx_str = args
> +        find_value = self.get_value_from_str(key_str, regx_str, config_content)
> +        return find_value
> +
> +    def get_info_from_bond_config(self, config_content, args):
> +        """
> +        Get the active slaves of the bonding device which you choose.
> +        """
> +        info = None
> +
> +        if isinstance(args[0], (list, tuple)):
> +            search_args = args
> +        else:
> +            search_args = [args]
> +
> +        for search_args in search_args:
> +            try:
> +                info = self.get_bonding_config(config_content, search_args)
> +                break
> +            except Exception as e:
> +                self.logger.info(e)
> +            finally:
> +                pass
> +        else:
> +            info = None
> +
> +        return info
> +
> +    def get_bonding_info(self, bond_port, info_types):
> +        '''
> +        Get the specified port information by its output message format
> +        '''
> +        info_set = {
> +            'mode':          ["Bonding mode: ", "\d*"],
> +            'agg_mode':      ["IEEE802.3AD Aggregator Mode: ", "\S*"],
> +            'balance_policy':["Balance Xmit Policy: ", "\S+"],
> +            'slaves':        [["Slaves \(\d\): \[", "\d*( \d*)*"],
> +                              ["Slaves: \[", "\d*( \d*)*"]],
> +            'active_slaves': [["Active Slaves \(\d\): \[", "\d*( \d*)*"],
> +                              ["Acitve Slaves: \[", "\d*( \d*)*"]],
> +            'primary':       ["Primary: \[", "\d*"]}
> +        # get all config information
> +        config_content = self.d_console("show bonding config %d" % bond_port)
> +        if isinstance(info_types, (list or tuple)):
> +            query_values = []
> +            for info_type in info_types:
> +                if info_type in info_set.keys():
> +                    find_value = self.get_info_from_bond_config(
> +                                                        config_content,
> +                                                        info_set[info_type])
> +                    if info_type in ['active_slaves', 'slaves']:
> +                        find_value = [value for value in find_value.split(' ')
> +                                        if value]
> +                else:
> +                    find_value = None
> +                query_values.append(find_value)
> +            return query_values
> +        else:
> +            info_type = info_types
> +            if info_type in info_set.keys():
> +                find_value = self.get_info_from_bond_config(config_content,
> +                                                            info_set[info_type])
> +                if info_type in ['active_slaves', 'slaves']:
> +                    find_value = [value for value in find_value.split(' ')
> +                                            if value]
> +                return find_value
> +            else:
> +                return None
> +
> +    def get_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' = []
> +                 'inactive' = []
> +        """
> +        pkt_now = {}
> +        bond_stat = 'tx' if rx_tx == 'rx' else 'rx'
> +        if unbound_port: # if unbound_port has not been set, ignore this
> +            pkt_now[unbound_port] = \
> +                [int(_) for _ in self.get_stats(unbound_port, rx_tx)]
> +
> +        pkt_now[bond_port] = \
> +                [int(_) for _ in self.get_stats(bond_port, bond_stat)]
> +        for slave in slaves['active']:
> +            pkt_now[slave] = [int(_) for _ in self.get_stats(slave, bond_stat)]
> +        for slave in slaves['inactive']:
> +            pkt_now[slave] = [int(_) for _ in self.get_stats(slave, bond_stat)]
> +
> +        return pkt_now
> +
> +    def get_active_slaves(self, primary_slave, bond_port):
> +        self.config_tester_port_by_number(primary_slave, "down")
> +        primary_port = self.get_bonding_info(bond_port, 'primary')
> +        active_slaves = self.get_bonding_info(bond_port, 'active_slaves')
> +        if active_slaves and primary_port in active_slaves:
> +            active_slaves.remove(primary_port)
> +        else:
> +            fmt = "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=0, socket=0, verify_detail=False):
> +        """
> +        Create a bonding device with the parameters you specified.
> +        """
> +        cmd = "create bonded device %d %d" % (mode, socket)
> +        out = self.d_console(cmd)
> +        err_fmt = "Create bonded device on mode [%d] socket [%d] failed"
> +        self.verify("Created new bonded device" in out,
> +                     err_fmt% (mode, socket))
> +        fmts = [
> +             "Created new bonded device net_bond_testpmd_[\d] on \(port ",
> +             "Created new bonded device net_bonding_testpmd_[\d] on \(port ",
> +             "Created new bonded device eth_bond_testpmd_[\d] on \(port "]
> +        bond_port = self.get_value_from_str(fmts, "\d+", out)
> +        bond_port = int(bond_port)
> +
> +        if verify_detail:
> +            out = self.d_console("show bonding config %d" % bond_port)
> +            self.verify("Bonding mode: %d" % mode in out,
> +                        "Bonding mode display error when create bonded device")
> +            self.verify("Slaves: []" in out,
> +                        "Slaves display error when create bonded device")
> +            self.verify("Active Slaves: []" in out,
> +                        "Active Slaves display error when create bonded device")
> +            self.verify("Primary: []" not in out,
> +                        "Primary display error when create bonded device")
> +            out = self.d_console("show port info %d" % bond_port)
> +            self.verify("Connect to socket: %d" % socket in out,
> +                        "Bonding port connect socket error")
> +            self.verify("Link status: down" in out,
> +                        "Bonding port default link status error")
> +            self.verify("Link speed: 0 Mbps" in out,
> +                        "Bonding port default link speed error")
> +
> +        return bond_port
> +
> +    def start_ports(self, port='all'):
> +        """
> +        Start a port which the testpmd can see.
> +        """
> +        timeout = 12 if port=='all' else 5
> +        # to avoid lsc event message interfere normal status
> +        cmds =[]
> +        cmds.append(["port start %s" % str(port), " ", timeout])
> +        cmds.append([" ", '', timeout])
> +        self.d_console(cmds)
> +
> +    def add_slave(self, bond_port, invert_verify=False, expected_str='',
> +                  *slave_ports):
> +        """
> +        Add the ports into the bonding device as slaves.
> +        """
> +        if len(slave_ports) <= 0:
> +            utils.RED("No port exist when add slave to bonded device")
> +        for slave_id in slave_ports:
> +            cmd = "add bonding slave %d %d" % (slave_id, bond_port)
> +            out = self.d_console(cmd)
> +            if expected_str:
> +                self.verify(expected_str in out,
> +                            "message <{0}> is missiong".format(expected_str))
> +            slaves = self.get_bonding_info(bond_port, 'slaves')
> +            if not invert_verify:
> +                self.verify(str(slave_id) in slaves,
> +                            "Add port as bonding slave failed")
> +            else:
> +                err = "Add port as bonding slave successfully,should fail"
> +                self.verify(str(slave_id) not in slaves, err)
> +
> +    def remove_slaves(self, bond_port, invert_verify=False, *slave_port):
> +        """
> +        Remove the specified slave port from the bonding device.
> +        """
> +        if len(slave_port) <= 0:
> +            utils.RED("No port exist when remove slave from bonded device")
> +        for slave_id in slave_port:
> +            cmd = "remove bonding slave %d %d" % (int(slave_id), bond_port)
> +            self.d_console(cmd)
> +            slaves = self.get_bonding_info(bond_port, 'slaves')
> +            if not invert_verify:
> +                self.verify(str(slave_id) not in slaves,
> +                            "Remove slave to fail from bonding device")
> +            else:
> +                err = ("Remove slave successfully from bonding device, "
> +                      "should be failed")
> +                self.verify(str(slave_id) in slaves,
> +                            err)
> +
> +    def remove_all_slaves(self, bond_port):
> +        """
> +        Remove all slaves of specified bound device.
> +        """
> +        all_slaves = self.get_bonding_info(bond_port, 'slaves')
> +        all_slaves = all_slaves.split()
> +        if len(all_slaves) == 0:
> +            pass
> +        else:
> +            self.remove_slaves(bond_port, False, *all_slaves)
> +
> +    def set_primary_slave(self, bond_port, slave_port, invert_verify=False):
> +        """
> +        Set the primary slave for the bonding device.
> +        """
> +        cmd = "set bonding primary %d %d" % (slave_port, bond_port)
> +        self.d_console(cmd)
> +        out = self.get_bonding_info(bond_port, 'primary')
> +        if not invert_verify:
> +            self.verify(str(slave_port) in out,
> +                        "Set bonding primary port failed")
> +        else:
> +            err = "Set bonding primary port successfully,should not success"
> +            self.verify(str(slave_port) not in out, err)
> +
> +    def set_bonding_mode(self, bond_port, mode):
> +        """
> +        Set the mode for the bonding device.
> +        """
> +        cmd = "set bonding mode %d %d" % (mode, bond_port)
> +        self.d_console(cmd)
> +        mode_value = self.get_bonding_info(bond_port, 'mode')
> +        self.verify(str(mode) in mode_value, "Set bonding mode failed")
> +
> +    def set_bonding_mac(self, bond_port, mac):
> +        """
> +        Set the MAC for the bonding device.
> +        """
> +        cmd = "set bonding mac_addr %s %s" % (bond_port, mac)
> +        self.d_console(cmd)
> +        new_mac = self.get_port_mac(bond_port)
> +        self.verify(new_mac == mac, "Set bonding mac failed")
> +
> +    def set_bonding_balance_policy(self, bond_port, policy):
> +        """
> +        Set the balance transmit policy for the bonding device.
> +        """
> +        cmd = "set bonding balance_xmit_policy %d %s" % (bond_port, policy)
> +        self.d_console(cmd)
> +        new_policy = self.get_bonding_info(bond_port, 'balance_policy')
> +        policy = "BALANCE_XMIT_POLICY_LAYER" + policy.lstrip('l')
> +        self.verify(new_policy == policy, "Set bonding balance policy failed")
> +
> +    def set_8023ad_agg_mode(self, bond_port, mode="bandwidth"):
> +        """
> +        set bonding agg_mode <port_id> <agg_name>
> +
> +        Set 802.11AD Aggregator Mode
> +        """
> +        cmd = "set bonding agg_mode %d %s" % (bond_port, mode)
> +        self.d_console(cmd)
> +        cur_mode = self.get_bonding_info(bond_port, 'agg_mode')
> +        if mode == cur_mode:
> +            fmt = "set bonding agg_mode <{0}> successfully"
> +            self.logger.info(fmt.format(mode))
> +        else:
> +            msg = "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 <port_id> <agg_name>
> +
> +        get 802.11AD Aggregator Mode
> +        """
> +        cur_mode = self.get_bonding_info(bond_port, 'agg_mode')
> +        return cur_mode
> +
> +    def set_8023ad_dedicated_queue(self, bond_port, status='disable'):
> +        """
> +        set 802.11AD dedicated_queues status
> +        enable|disable
> +        """
> +        cmds =[ ["set bonding lacp dedicated_queues %s %s" % (bond_port,
> +                                                              status),
> +                ['', 'port %s failed'%bond_port, False], 2],
> +              ]
> +        out = self.d_console(cmds)
> +        # when set 'hw'
> +        if status == 'enable':
> +            expected_msg = 'queues for LACP control packets enabled'
> +            err_fmt = "link bonding mode 4 (802.3ad) set {0} failed"
> +            self.verify(expected_msg in out, err_fmt.format(status))
> +        elif status == 'disable':
> +            expected_msg = 'queues for LACP control packets disabled'
> +            err_fmt = "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 = 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= "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 = "port start {0}".format
> +        cmds = []
> +        port_num = 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 = SOCKET_0
> +        # create bonded device 1, add slaves in it
> +        bond_port = self.create_bonded_device(bond_mode, specified_socket)
> +        # 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 = slaves + [bond_port]
> +        return bond_port
> +
> +    def run_8023ad_pre(self, slaves, bond_mode):
> +        bond_port = self.set_8023ad_bonded(slaves, bond_mode)
> +        # should set port to stop and make sure port re-sync with parter
> +        cmds = ["port stop all", '', 15]
> +        self.d_console(cmds)
> +        time.sleep(2)
> +        cmds = ["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 = 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 = 'mac'
> +        bond_port_mac = self.get_bond_port_mac(bond_port, query_type)
> +        default_mac = '00:00:00:00:00:00'
> +        if bond_port_mac == default_mac:
> +            msg = "bond port default mac is [{0}]".format(default_mac)
> +            self.logger.info(msg)
> +        else:
> +            fmt = "bond port default mac is [{0}], not expected mac"
> +            msg = 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 = 'mac'
> +        bond_port_mac = self.get_bond_port_mac(bond_port, query_type)
> +        if bond_port_mac == '00:00:00:00:00:00':
> +            msg = "bond port hasn't set mac address"
> +            self.logger.info(msg)
> +            return
> +
> +        for port_id in slaves:
> +            slave_mac = self.get_port_info(port_id, query_type)
> +            if bond_port_mac == slave_mac:
> +                fmt = "bonded device's mac is slave [{0}]'s mac [{1}]"
> +                msg = fmt.format(port_id, slave_mac)
> +                self.logger.info(msg)
> +                return port_id
> +        else:
> +            fmt = "bonded device's current mac [{0}] " + \
> +                  "is not one of its slaves macs"
> +            msg = 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 = 0
> +        cur_slaves = 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 = 'mac'
> +        slave_old_mac = 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 = [["port stop all", '', 15]]
> +        portList = [bond_port]
> +        cmds +=[["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 = ["port stop {0}".format(bond_port), '']
> +        self.d_console(cmds)
> +        status = self.get_port_info(bond_port, 'link_status')
> +        if status != 'down':
> +            msg = "bond port {0} fail to set down".format(bond_port)
> +            self.logger.error(msg)
> +            raise VerifyFailure(msg)
> +        else:
> +            msg = "bond port {0} set down successful !".format(bond_port)
> +            self.logger.info(msg)
> +        # start bond port
> +        cmds = ["port start {0}".format(bond_port), '', 10]
> +        self.d_console(cmds)
> +        status = self.get_port_info(bond_port, 'link_status')
> +        if status != 'up':
> +            msg = "bond port {0} fail to set up".format(bond_port)
> +            self.logger.error(msg)
> +            raise VerifyFailure(msg)
> +        else:
> +            msg = "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 = [["set promisc {0} off".format(bond_port), '']]
> +        time.sleep(3)
> +        self.d_console(cmds)
> +        status = self.get_port_info(bond_port, 'promiscuous_mode')
> +        if status != 'disabled':
> +            fmt = "bond port {0} fail to set promiscuous mode disabled"
> +            msg = fmt.format(bond_port)
> +            self.logger.warning(msg)
> +        else:
> +            fmt = "bond port {0} set promiscuous mode disabled successful !"
> +            msg = fmt.format(bond_port)
> +            self.logger.info(msg)
> +        # check slave promiscuous status
> +        for port_id in slaves:
> +            status = self.get_port_info(port_id, 'promiscuous_mode')
> +            if status != 'disabled':
> +                fmt = ("slave port {0} promiscuous mode "
> +                      "isn't the same as bond port 'disabled'")
> +                msg = fmt.format(port_id)
> +                self.logger.error(msg)
> +                raise VerifyFailure(msg)
> +            else:
> +                fmt = "slave port {0} promiscuous mode is 'disabled' too"
> +                msg = fmt.format(port_id)
> +                self.logger.info(msg)
> +        # open bonded device promiscuous mode
> +        cmds = [["set promisc {0} on".format(bond_port), '']]
> +        self.d_console(cmds)
> +        time.sleep(3)
> +        status = self.get_port_info(bond_port, 'promiscuous_mode')
> +        if status != 'enabled':
> +            fmt = "bond port {0} fail to set promiscuous mode enabled"
> +            msg = fmt.format(bond_port)
> +            self.logger.error(msg)
> +            raise VerifyFailure(msg)
> +        else:
> +            fmt = "bond port {0} set promiscuous mode enabled successful !"
> +            msg = fmt.format(bond_port)
> +            self.logger.info(msg)
> +        # check slave promiscuous status
> +        for port_id in slaves:
> +            status = self.get_port_info(port_id, 'promiscuous_mode')
> +            if status != 'enabled':
> +                fmt = "slave port {0} promiscuous mode " + \
> +                      "isn't the same as bond port 'enabled'"
> +                msg = fmt.format(port_id)
> +                self.logger.error(msg)
> +                raise VerifyFailure(msg)
> +            else:
> +                fmt = "slave port {0} promiscuous mode is 'enabled' too"
> +                msg = fmt.format(port_id)
> +                self.logger.info(msg)
> +
> +    def get_agg_mode_fmt(self):
> +        retStatus = False
> +        # if agg mode has added to cmdline.c
> +        target_file = os.sep.join([self.dut.base_dir, 'app/test-pmd/cmdline.c'])
> +        with open(target_file, 'rb') as fp:
> +            if 'agg_mode' in fp.read():
> +                retStatus = True
> +
> +        if retStatus:
> +            agg_config = 'agg_mode={0}'
> +            msg = "agg_mode has been merged"
> +            self.logger.warning(msg)
> +            #raise VerifyFailure(msg)
> +        else:
> +            self.logger.info("has no agg_mode such option")
> +            agg_config = ''
> +
> +        return agg_config
> +
> +    def check_8023ad_agg_modes(self, slaves, bond_mode):
> +        # check aggregator mode
> +        #---------------------------
> +        check_results = []
> +        default_agg_mode = 'stable'
> +        for mode in self.AGG_MODES:
> +            try:
> +                self.start_testpmd()
> +                bond_port = self.set_8023ad_bonded(slaves,
> +                                                   bond_mode)
> +                cur_agg_mode = self.get_8023ad_agg_mode(bond_port)
> +
> +                if cur_agg_mode != default_agg_mode:
> +                    fmt = ("link bonding mode 4 (802.3ad) default agg mode "
> +                          "isn't {0}")
> +                    msg = fmt.format(default_agg_mode)
> +                    self.logger.warning(msg)
> +                # ignore default mode
> +                if mode == cur_agg_mode:
> +                    fmt = ("link bonding mode 4 (802.3ad) "
> +                          "current agg mode is {0}")
> +                    msg = fmt.format(mode)
> +                    self.logger.info(msg)
> +                    continue
> +                #----------------
> +                # set test pmd
> +                cmds = []
> +                cmds = [["port stop all", '', 15]]
> +                portList = [bond_port]
> +                cmds +=[["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 = []
> +        default_agg_mode = 'stable'
> +        for mode in self.AGG_MODES:
> +            try:
> +                bond_port = self.run_8023ad_pre(slaves, mode)
> +                # ignore default mode
> +                if mode == 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 failed')
> +        return
> +
> +    def check_8023ad_dedicated_queues(self, slaves, bond_mode):
> +        # check aggregator mode
> +        #---------------------------
> +        check_results = []
> +        default_slow_queue = 'unknown'
> +        for mode in self.DEDICATED_QUEUES:
> +            try:
> +                self.start_testpmd()
> +                bond_port = 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_mode):
> +        # check aggregator mode
> +        #---------------------------
> +        check_results = []
> +        default_slow_queue = 'unknown'
> +        for mode in self.DEDICATED_QUEUES:
> +            try:
> +                self.start_testpmd()
> +                bond_port = self.set_8023ad_bonded(slaves,
> +                                                   bond_mode)
> +                #cur_slow_queue = self.get_8023ad_slow_queue(bond_port)
> +                #if cur_slow_queue != default_slow_queue:
> +                #    msg = "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 != 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 = 'check_8023ad_dedicated_queues_transmission is failed'
> +            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 ="port start %s" % str(port)
> +        self.d_console(cmd)
> +        time.sleep(3)
> +
> +    def switch_daemon_config(self, **kwargs):
> +        if self.switch_name == 'quanta':
> +            return
> +        port_id = kwargs.get('port_id')
> +        console = kwargs.get('console')
> +        wait_time = 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 = {'port_id': port_id,
> +                'wait_time': wait_time,
> +                'console': sw_scene}
> +        daemon = DaemonThread( self.switch_daemon_config,
> +                               name="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 = self.sw_scene
> +        sw_scene.reset()
> +        sw_ports = sw_scene.ports()
> +        # set one random port as slave down port
> +        # if salve ports are more than three.
> +        slave_down_id = random.randint(0, len(sw_ports) - 1)
> +        sw_port_id = sw_ports[0]
> +        #[scene.set_intf_up(port_id) for port_id in sw_ports]
> +        sw_scene.get_stats()
> +        wait_time = 10
> +        switch_daemon = 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 = 1000
> +        pkt_now = {}
> +        multi_stream = "/home/myf/multi.log"
> +        down = "/home/myf/down.log"
> +        #----------------------------
> +        # create stream for traffic
> +        tx_port = self.tx_port
> +        self.set_stream( bond_port, src_port=tx_port, pkt_type='udp', **slaves)
> +        if not os.path.exists(down):
> +            switch_daemon = None
> +        if self.is_perf:
> +            pkt_gen_type = 'ixia'
> +            pkt_generator = self.send_packets_by_ixia
> +        elif os.path.exists(multi_stream):
> +            pkt_gen_type = 'scapy'
> +            os.remove(multi_stream)
> +            pkt_generator = self.send_multi_packet_quick # send multi packet
> +        else:
> +            pkt_gen_type = 'scapy'
> +            pkt_generator = 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 == 'quanta':
> +                loop_count = 5
> +                wait = loop_count/3
> +                interval = 15
> +                #interval = 1
> +                time.sleep(wait*interval)
> +                wait_time = (loop_count -wait)*interval
> +                self.logger.info("wait {0}".format(wait_time))
> +                time.sleep(wait_time)
> +            #------------------------------------
> +            if pkt_gen_type == 'scapy':
> +                pkt_now = 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 = [str(value).rjust(10)
> +                                for value in pkt_now[port_id]]
> +                    msg =  "port {0}: ".format(port_id) + ",".join(values)
> +                    self.logger.info(msg)
> +        except Exception as e:
> +            msg = 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 = 1000
> +        pkt_now = {}
> +        multi_stream = "/home/myf/multi.log"
> +        down = "/home/myf/down.log"
> +        #----------------------------
> +        # create stream for traffic
> +        tx_port = self.tx_port
> +        self.set_stream(bond_port, src_port=tx_port, pkt_type='udp', **slaves)
> +        if not os.path.exists(down):
> +            switch_daemon = None
> +        if self.is_perf:
> +            pkt_generator = self.send_packets_by_ixia
> +        elif os.path.exists(multi_stream):
> +            os.remove(multi_stream)
> +            pkt_generator = self.send_multi_packet_quick # send multi packet
> +        else:
> +            pkt_generator = self.send_packet_quick
> +        time.sleep(3)
> +        cnt = 0
> +        #----------------------------
> +        # run traffic
> +        self.logger.info("begin transmission data......")
> +        wait_time = ''
> +        loop_count = 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 == 'quanta':
> +                    wait = loop_count/3
> +                    #interval = 50
> +                    interval = 1
> +                    time.sleep(wait*interval)
> +                    if self.slave_down:
> +                        # add random wait time to get a scatter sample data
> +                        random_wait_time = random.randint(1, 20)
> +                        #time.sleep(random_wait_time)
> +                    wait_time = (loop_count -wait)*interval
> +                    self.logger.info("wait {0}".format(wait_time))
> +                    time.sleep(wait_time)
> +                    break
> +                else:
> +                    if cnt == loop_count/3:
> +                        if switch_daemon:
> +                            switch_daemon.activate()
> +                #------------------------------------
> +                #pkt_total = pkt_total + pkt_count*len(sw_ports)
> +                if False:
> +                    pkt_now = 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 = [str(value).rjust(10)
> +                                    for value in pkt_now[port_id]]
> +                        msg =  "port {0}: ".format(port_id) + ",".join(values)
> +                        self.logger.info(msg)
> +            except Exception as e:
> +                msg = traceback.format_exc()
> +                self.logger.error(msg)
> +            finally:
> +                pass
> +            cnt += 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 mode."""
> +        if self.switch_status == 'active':
> +            self.d_console("stop")
> +            sw_scene, switch_daemon, sw_ports = self.run_switch_pre()
> +            self.d_console("start")
> +        #-------------------------------------------------------------
> +        # run traffic
> +        self.traffic(bond_port, slaves)
> +        #-------------------------------------------------------------
> +        time.sleep(3)
> +        if self.switch_status == 'active':
> +            sw_scene.stop()
> +            switch_stats = sw_scene.get_stats()
> +            self.cur_data['switch statistics'] = 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 = self.dut.ports_info[dut_port_id]['peer']
> +        sw_port = peer.split(":")[1] if 'switch' in peer else None
> +        return sw_port
> +
> +    def get_switch_keys(self, key):
> +        if self.switch_name == 'quanta':
> +            keys_table = {'rx ucast': 'RX Ucast Pkts',
> +                          'tx ucast': 'TX Ucast Pkts'}
> +        elif self.switch_name == 'cisco':
> +            keys_table = {'RX-packets': '',
> +                          'TX-packets': ''}
> +        else:
> +            return None
> +        return keys_table[key]
> +
> +    def check_sample_data(self, case_name):
> +        expected_rate = 1/10e4
> +        summary_msg = []
> +        for mode in self.data_results[case_name]:
> +            data = self.data_results[case_name][mode]
> +            pmd_stats = data['testpmd ports statistics']
> +            switch_stats = data['switch statistics']
> +            # check slave traffic stats
> +            port_msg = []
> +            sw_total_rx = 0
> +            for dut_port_id in pmd_stats:
> +                pmd_stat = pmd_stats[dut_port_id]
> +                sw_port_name = self.get_switch_port(dut_port_id)
> +                if not sw_port_name:
> +                    continue
> +                switch_stat = switch_stats[sw_port_name]
> +                # check each slave's traffic loss
> +                # lacpdu packet is calculated by testpmd , so there is more
> +                # pkts number on testpmd statistics
> +                port_text = "dut port [{0}]".format(dut_port_id)
> +                if sw_port_name:
> +                    pmd_tx = pmd_stat['TX-packets']
> +                    key = 'rx ucast'
> +                    sw_rx = switch_stat[self.get_switch_keys(key)]
> +                    sw_total_rx += sw_rx
> +                    rate = 1 - float(sw_rx)/float(pmd_tx)
> +                    msg = port_text + \
> +                         " traffic loss {0} is more than expected".format(rate)
> +                    if rate > expected_rate:
> +                        port_msg.append(msg)
> +                else:
> +                    msg = port_text + " has not corresponding switch port"
> +                    port_msg.append()
> +
> +            # check total fwd traffic loss of bonding device
> +            pmd_fwd_stats = data['testpmd fwd statistics']
> +            bond_port_id = self.bond_port
> +            tx_port_id = None
> +            for dut_port_id in pmd_fwd_stats:
> +                if dut_port_id != bond_port_id:
> +                    pmd_fwd_tx = pmd_fwd_stats[dut_port_id]['RX-packets']
> +                    tx_port_id = dut_port_id
> +                    break
> +            pmd_bond_rx = pmd_fwd_stats[bond_port_id]['TX-packets']
> +            fwd_msg = []
> +            if pmd_bond_rx < pmd_fwd_tx:
> +                rate = 1 - float(pmd_bond_rx)/float(pmd_fwd_tx)
> +                port_text = "dut port [{0}] fwd to bond port [{1}]".format(
> +                                                                tx_port_id,
> +                                                                bond_port_id)
> +                msg = port_text + \
> +                     " traffic loss {0} is more than expected".format(rate)
> +                if rate > expected_rate:
> +                    fwd_msg.append(msg)
> +            # check total traffic loss of bonding device
> +            #
> +            bond_msg = []
> +            if sw_total_rx == 0 or pmd_fwd_tx == 0:
> +                msg = "total packet is zero, transmission not happen"
> +                bond_msg.append(msg)
> +            elif sw_total_rx < pmd_fwd_tx:
> +                rate = 1 - float(sw_total_rx)/float(pmd_fwd_tx)
> +                port_text = "bond port [{0}] to switch".format(bond_port_id)
> +                msg = port_text + \
> +                     " traffic loss {0} is more than expected".format(rate)
> +                if rate > expected_rate:
> +                    bond_msg.append(msg)
> +            # check status
> +            if fwd_msg or bond_msg:
> +                mode_msg = "mode {0}".format(mode)
> +                summary_msg.append(mode_msg)
> +                summary_msg += 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 = []
> +        for port_info in self.dut.ports_info:
> +            tx_pci.append(port_info['pci'])
> +        if not tx_pci:
> +            msg = "can't find tx_port pci"
> +            self.logger.error(msg)
> +            raise VerifyFailure(msg)
> +        #-------------------
> +        # get bonding ports configuration
> +        slaves = self.dut_ports[:]
> +        slave_pcis = []
> +        slave_ids = []
> +        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 = []
> +        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 = "can't find tx_port pci"
> +            self.logger.error(msg)
> +            raise VerifyFailure(msg)
> +        #-------------------
> +        # get bonding ports configuration
> +        slaves = self.dut_ports[:]
> +        slave_pcis = []
> +        slave_ids = []
> +        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 = self.get_pci_link_with_switch()
> +        else:
> +            slave_ids, slave_pcis = self.get_pci_link()
> +        # get nic configuration
> +        bonding_name = 'net_bonding0'
> +        slaves_pci = ["slave=" + pci for pci in slave_pcis]
> +        bonding_mode = 'mode={0}'.format(str(MODE_LACP))
> +        agg_config = 'agg_mode={0}'
> +        vdev_format = ",".join([bonding_name] + slaves_pci + \
> +                               [bonding_mode, agg_config])
> +        # begin check command line options
> +        check_results = []
> +        mode = str(MODE_LACP)
> +        options = vdev_format.format(agg_mode)
> +        vdev_options = " --vdev '{0}'".format(options)
> +        bond_port = len(self.dut_ports)
> +        return bond_port, vdev_options
> +
> +    def run_test_pre(self, agg_mode):
> +        msgs = []
> +        if self.switch_status == 'active':
> +            self.tester.ixia_packet_gen.clean_ownership()
> +            self.sw_scene.clear() # clear switch statistics
> +        # get bonding ports configuration
> +        bond_port, vdev_options = self.get_commandline_options(agg_mode)
> +        self.bond_port = bond_port
> +        # boot up testpmd
> +        self.start_testpmd(eal_option=vdev_options)
> +        cur_slaves, cur_agg_mode = self.get_bonding_info(bond_port,
> +                                            ['slaves', 'agg_mode'])
> +        if agg_mode != cur_agg_mode:
> +            fmt = 'expected agg mode is [{0}], current agg mode is [{1}]'
> +            msg = fmt.format(agg_mode, cur_agg_mode)
> +            msgs.append(msg)
> +        #-------------------
> +        # get forwarding port
> +        #-------------------
> +        tx_port_id = ''
> +        for port_id in range(bond_port):
> +            if str(port_id) not in cur_slaves:
> +                tx_port_id = port_id
> +                break
> +        else:
> +            tx_port_id = bond_port
> +        # raise VerifyFailure
> +        if msgs:
> +            for msg in msgs:
> +                self.logger.warning(msg)
> +            fmt = 'fail to config from command line at {0}'
> +            msg = 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 == 'active':
> +            self.sw_scene.start()
> +        self.set_bond_port_ready(tx_port_id, bond_port)
> +        slaves = [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 = {}
> +        for port_id in range(bond_port):
> +            if tx_port_id == port_id or bond_port == port_id:
> +                continue
> +            slave_stats[port_id] = self.testpmd.get_pmd_stats(port_id)
> +
> +        self.cur_data['testpmd ports statistics'] = slave_stats
> +        #-------------
> +        fwd_pmd_stats = {}
> +        for port_id in [bond_port, tx_port_id]:
> +            fwd_pmd_stats[port_id] = self.testpmd.get_pmd_stats(port_id)
> +        self.cur_data['testpmd fwd statistics'] = fwd_pmd_stats
> +        output = self.close_testpmd()
> +        self.sw_scene.clear()
> +        self.tester.ixia_packet_gen.clean_ownership()
> +
> +    def run_dpdk_pre2(self):
> +        slaves = self.dut_ports[:]
> +        self.start_testpmd()
> +        mode = MODE_LACP
> +        bond_port = 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='count'):
> +        # begin check command line options
> +        check_results = []
> +        max_loop = self.sample_number
> +        cur_case_name = self.cur_case
> +        sample_results = {}
> +        for cnt in range(max_loop):
> +            self.data_results[cur_case_name] = {}
> +            case_data = self.data_results[cur_case_name]
> +            #for agg_mode in self.AGG_MODES:
> +            if agg_mode in self.AGG_MODES:
> +                case_data[agg_mode] = {}
> +                self.cur_data = case_data[agg_mode]
> +                self.logger.info('begin to check {0}'.format(agg_mode))
> +                bond_port, cur_slaves, tx_port_id = self.run_test_pre(agg_mode)
> +                try:
> +                    #-----------------------------------------
> +                    # begin loop sending packet transmission
> +                    slaves = {}
> +                    slaves['active'] = cur_slaves
> +                    slaves['inactive'] = []
> +                    tx_ports =[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 = self.check_sample_data(cur_case_name)
> +                if status:
> +                    sample_results[cnt] = status
> +            except Exception as e:
> +                sample_results[cnt] = 'data absence'
> +            finally:
> +                pass
> +
> +        if sample_results:
> +            check_results.append(pformat(sample_results, indent=1, width=1))
> +
> +        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 = str(MODE_LACP)
> +        msgs = []
> +        cur_mode, cur_slaves, cur_active_slaves, cur_agg_mode =\
> +                self.get_bonding_info(bond_port,
> +                                       ['mode',
> +                                        'slaves',
> +                                        'active_slaves',
> +                                        'agg_mode'])
> +        #---------------------------------
> +        # check bonding mode
> +        if mode != cur_mode:
> +            fmt = 'expected mode is [{0}], current mode is [{1}]'
> +            msg = fmt.format(mode, cur_mode)
> +            msgs.append(msg)
> +        #---------------------------------
> +        # check bonding 802.3ad agg mode
> +        if agg_mode != cur_agg_mode:
> +            fmt ='expected agg mode is [{0}], current agg mode is [{1}]'
> +            msg = fmt.format(agg_mode, cur_agg_mode)
> +            msgs.append(msg)
> +        #---------------------------------
> +        # check bonded slaves
> +        _cur_slaves = [int(id) for id in cur_slaves]
> +        if not _cur_slaves or cmp(sorted(slaves), sorted(_cur_slaves)) != 0:
> +            slaves_str = ' '.join([str(id) for id in slaves])
> +            cur_slaves_str = ' '.join([str(id) for id in _cur_slaves]) \
> +                                        if _cur_slaves else ''
> +            msg_format = 'expected slaves is [{0}], current slaves is [{1}]'
> +            msg = 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 = [int(id) for id in cur_active_slaves]
> +                if cmp(sorted(slaves), sorted(check_active_slaves)) != 0:
> +                    slaves_str = ' '.join([str(id) for id in slaves])
> +                    msg_fmt = ('expected active slaves is [{0}], '
> +                              'current active slaves is [{1}]')
> +                    msg = msg_fmt.format(slaves_str, cur_active_slaves)
> +                    msgs.append(msg)
> +            else:
> +                msg = 'active slaves should not be empty'
> +                self.logger.warning(msg)
> +                #msgs.append(msg)
> +        else:
> +            if cur_active_slaves:
> +                msg = '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 = [int(id) for id in self.get_bonding_info(
> +                                                            bond_port,
> +                                                            'active_slaves')]
> +            if not cur_active_slaves or cmp(sorted(slaves),
> +                                            sorted(cur_active_slaves)) != 0:
> +                slaves_str = ' '.join([str(id) for id in slaves])
> +                active_str = ' '.join([str(id) for id in cur_active_slaves]) \
> +                                               if cur_active_slaves else ''
> +                msg_fmt = ('expected active slaves is [{0}], '
> +                          'current active slaves is [{1}]')
> +                msg = msg_fmt.format(slaves_str, active_str)
> +                msgs.append(msg)
> +        #---------------------------------
> +        # raise exception
> +        if msgs:
> +            for msg in msgs:
> +                self.logger.warning(msg)
> +            msg = '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 mode. """
> +        pkt_count = 1000
> +        pkt_total = 0
> +        pkt_now = {}
> +        loop_count = 5
> +        cnt = 0
> +        tx_port = self.tx_port
> +        bond_port = 0
> +        slaves = {}
> +        slaves['active'] =['0', '1','2','3']
> +        self.set_stream(bond_port, src_port=tx_port, pkt_type='udp', **slaves)
> +        #------------------------------------------------------------
> +        pkt_generator = self.send_packets_by_ixia
> +        self.logger.info("begin transmission data......")
> +        wait_time = 30*1
> +        #------------------------------------------------------------
> +        try:
> +            ##################################
> +            pkt_generator(tx_port, pkt_count)
> +            time.sleep(wait_time)
> +        except Exception as e:
> +            msg = 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 freebsd")
> +        #------------------------------------------------------------
> +        # link peer resource
> +        self.dut_ports = self.dut.get_ports()
> +        required_link = 5 if self.is_switch else 2
> +        self.verify(len(self.dut_ports) >= required_link, "Insufficient ports")
> +        self.ports_socket = self.dut.get_numa_id(self.dut_ports[0])
> +        self.all_cores_mask = utils.create_mask(self.dut.get_core_list("all"))
> +        #------------------------------------------------------------
> +        # stream configs
> +        self.stream_dst_configs = []
> +        #------------------------------------------------------------
> +        # testpmd related
> +        self.testpmd = PmdOutput(self.dut)
> +        self.testpmd_status = 'close'
> +        #------------------------------------------------------------
> +        # 802.3ad related
> +        self.tester_bond = "bond0"
> +        self.agg_mode = None
> +        self.bond_port = None
> +        #--------------------------------
> +        # switch related
> +        # only itecStvDts02 platform support lacp testing
> +        #tester_hostname = socket.gethostname()
> +        if self.is_switch:
> +            self.tx_port = self.tester.get_interface(
> +                                self.tester.get_local_port(self.dut_ports[0]))
> +            switch_name = 'quanta'
> +            if 'lacp_group' not in self.tester.switch_scenes:
> +                msg = "[lacp_group] section not set in switch.cfg"
> +                raise SwitchException(msg)
> +            self.sw_scene = self.tester.switch_scenes['lacp_group']
> +            self.switch_name = switch_name
> +            self.switch_status = 'active'
> +            #---------------------------------
> +            self.multi_stream_flg = False
> +            self.add_options = False
> +            self.slave_down = False
> +        else:
> +            self.switch_status = 'close'
> +        # use for sample long time pressure testing
> +        self.sample_number = 1
> +        #--------------------------------
> +        # traffic related
> +        self.packet_types = {}
> +        #----------
> +        # ixia
> +        self.rate_percent = float(100)
> +        #------------------------------------------------------------------
> +        # use for debug
> +        self.data = []
> +        self.cur_data = {}
> +        self.data_results = {}
> +        self.cur_case = '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 == 'active':
> +            self.sw_scene.quit()
> +            self.switch_status = 'close'
> +
> +    def test_basic_behav_startStop(self):
> +        '''
> +        test 802.3ad basic behavior(port start/stop)
> +        '''
> +        #----------------------------
> +        msg = ''
> +        slaves, bond_port = self.run_dpdk_pre2()
> +        try:
> +            for _ in range(10):
> +                self.check_bonded_device_start(bond_port)
> +        except Exception as e:
> +            msg = "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 = ''
> +        slaves, bond_port = 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 = "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 = ''
> +        slaves, bond_port = self.run_dpdk_pre2()
> +        try:
> +            self.check_bonded_device_up_down(bond_port)
> +        except Exception as e:
> +            msg = "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 = ''
> +        slaves, bond_port = self.run_dpdk_pre2()
> +        try:
> +            self.check_bonded_device_promisc_mode(slaves, bond_port)
> +        except Exception as e:
> +            msg = "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 option)
> +        '''
> +        for agg_mode in self.AGG_MODES:
> +            bond_port, cur_slaves, tx_port_id = self.run_test_pre(agg_mode)
> +            self.check_cmd_line_option_status(agg_mode, bond_port, cur_slaves)
> +            self.close_testpmd()
> +
> +    def test_basic_behav_agg_mode(self):
> +        slaves = self.dut_ports[:]
> +        mode = MODE_LACP
> +        self.check_8023ad_agg_modes(slaves, mode)
> +        return
> +
> +    def test_basic_dedicated_queues(self):
> +        slaves = self.dut_ports[:]
> +        mode = MODE_LACP
> +        self.check_8023ad_dedicated_queues(slaves, mode)
> +        return
> +
> +    def check_perf_tx(self, agg_mode):
> +        #--------------------------------------------------------------------
> +        if self.switch_status == 'close':
> +            raise VerifyFailure("no switch support this testing case")
> +        self.slave_down = False
> +        #================================
> +        # select agg mode
> +        #-------------------
> +        # create command line options
> +        self.check_traffic_with_cmd_line_options(agg_mode=agg_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



More information about the dts mailing list