[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