[dts] [PATCH V1 2/2] pmd_stacked_bonded: upload automation script
Chen, Zhaoyan
zhaoyan.chen at intel.com
Mon Jan 21 08:17:28 CET 2019
Yufeng,
- Could you move the hard code ip/mac/port address to constants? and put them at the begin of the code.
- Extract the common functions which used by bond test into common file and share between each bond test suite.
Regards,
Zhaoyan Chen
> -----Original Message-----
> From: dts [mailto:dts-bounces 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/2] pmd_stacked_bonded: upload automation script
>
> From: yufengmx <yufengx.mo at intel.com>
>
>
> This automation script is for pmd stacked bonded feature.
>
> Allow bonded devices to be stacked to allow two or more bonded devices to be
> bonded into one master bonded device
>
> Signed-off-by: yufengmx <yufengx.mo at intel.com>
> ---
> tests/TestSuite_pmd_stacked_bonded.py | 1593
> +++++++++++++++++++++++++++++++++
> 1 file changed, 1593 insertions(+)
> create mode 100644 tests/TestSuite_pmd_stacked_bonded.py
>
> diff --git a/tests/TestSuite_pmd_stacked_bonded.py
> b/tests/TestSuite_pmd_stacked_bonded.py
> new file mode 100644
> index 0000000..4596c58
> --- /dev/null
> +++ b/tests/TestSuite_pmd_stacked_bonded.py
> @@ -0,0 +1,1593 @@
> +# BSD LICENSE
> +#
> +# Copyright(c) 2010-2018 Intel Corporation. All rights reserved.
> +# All rights reserved.
> +#
> +# Redistribution and use in source and binary forms, with or without
> +# modification, are permitted provided that the following conditions
> +# are met:
> +#
> +# * Redistributions of source code must retain the above copyright
> +# notice, this list of conditions and the following disclaimer.
> +# * Redistributions in binary form must reproduce the above copyright
> +# notice, this list of conditions and the following disclaimer in
> +# the documentation and/or other materials provided with the
> +# distribution.
> +# * Neither the name of Intel Corporation nor the names of its
> +# contributors may be used to endorse or promote products derived
> +# from this software without specific prior written permission.
> +#
> +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS
> +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
> FOR
> +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
> ANY
> +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> USE
> +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +import traceback
> +import os
> +import time
> +import re
> +import random
> +from socket import htons, htonl
> +
> +import utils
> +from test_case import TestCase
> +from exception import TimeoutException, VerifyFailure
> +from settings import TIMEOUT
> +from pmd_output import PmdOutput
> +
> +SOCKET_0 = 0
> +SOCKET_1 = 1
> +
> +MODE_ROUND_ROBIN = 0
> +MODE_ACTIVE_BACKUP = 1
> +MODE_XOR_BALANCE = 2
> +MODE_BROADCAST = 3
> +MODE_LACP = 4
> +MODE_TLB_BALANCE = 5
> +MODE_ALB_BALANCE = 6
> +
> +FRAME_SIZE_64 = 64
> +
> +class TestBondingStacked(TestCase):
> +
> + def get_static_ip_configs(self):
> + S_MAC_IP_PORT = [('52:00:00:00:00:00', '10.239.129.65', 61),
> + ('52:00:00:00:00:01', '10.239.129.66', 62),
> + ('52:00:00:00:00:02', '10.239.129.67', 63)]
> + return S_MAC_IP_PORT
> + #
> + # On tester platform, packet transmission
> + #
> + def get_stats(self, portid, flow):
> + """
> + get testpmd port statistic
> + """
> + _portid = 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 get_all_stats(self, unbound_port, rx_tx, bond_port, **slaves):
> + """
> + Get all the port stats which the testpmd can display.
> + Parameters:
> + : unbound_port: pmd port id
> + : rx_tx: unbond port stat 'rx' or 'tx'
> + : bond_port: bonding port
> + """
> + pkt_now = {}
> +
> + if rx_tx == 'rx':
> + bond_stat = 'tx'
> + else:
> + bond_stat = '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 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
> +
> + 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:
> + 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']
> + 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"]
> +
> + 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']
> +
> + 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']
> +
> + 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 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
> + cmds = [["port stop %d"%number, '']]
> + self.execute_testpmd_cmd(cmds)
> + # 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 send_packet(self, dst_port, src_port=False, frame_size=FRAME_SIZE_64,
> + count=1, invert_verify=False, **ether_ip):
> + """
> + Send count packet to portid
> + count: 1 or 2 or 3 or ... or 'MANY'
> + if count is 'MANY', then set count=1000,
> + send packets during 5 seconds.
> + ether_ip:
> + 'ether': 'dst_mac':False
> + 'src_mac':"52:00:00:00:00:00"
> + 'dot1q': 'vlan':1
> + 'ip': 'dst_ip':"10.239.129.88"
> + 'src_ip':"10.239.129.65"
> + 'udp': 'dst_port':53
> + 'src_port':53
> + """
> + during = 0
> + loop = 0
> +
> + try:
> + count = int(count)
> + except ValueError as e:
> + if count == 'MANY':
> + during = 5
> + count = 1000
> + else:
> + raise e
> +
> + if not src_port:
> + gp0rx_pkts, gp0rx_err, gp0rx_bytes = \
> + [int(_) for _ in self.get_stats(self.dut_ports[dst_port],
> + "rx")]
> + itf = self.tester.get_interface(
> + self.tester.get_local_port(self.dut_ports[dst_port]))
> + os.system("ifconfig {0} up".format(itf))
> + # temp = os.system("ifconfig {0} up".format(itf))
> + else:
> + gp0rx_pkts, gp0rx_err, gp0rx_bytes = \
> + [int(_) for _ in self.get_stats(dst_port, "rx")]
> + itf = src_port
> +
> + time.sleep(2)
> + ret_ether_ip = self.parse_ether_ip(dst_port, **ether_ip)
> +
> + pktlen = frame_size - 18
> + padding = pktlen - 20
> +
> + start = time.time()
> + while True:
> + self.tester.scapy_foreground()
> + append = self.tester.scapy_append
> + append('nutmac="%s"' % ret_ether_ip['ether']['dst_mac'])
> + append('srcmac="%s"' % ret_ether_ip['ether']['src_mac'])
> +
> + if ether_ip.get('dot1q'):
> + append('vlanvalue=%d' % ret_ether_ip['dot1q']['vlan'])
> + append('destip="%s"' % ret_ether_ip['ip']['dst_ip'])
> + append('srcip="%s"' % ret_ether_ip['ip']['src_ip'])
> + append('destport=%d' % ret_ether_ip['udp']['dst_port'])
> + append('srcport=%d' % ret_ether_ip['udp']['src_port'])
> + if not ret_ether_ip.get('dot1q'):
> + packet = "/".join(["Ether(dst=nutmac, src=srcmac)",
> + "IP(dst=destip, src=srcip, len=%s)",
> + "UDP(sport=srcport, dport=destport)",
> + "Raw(load='\x50'*%s)"])
> + cmd = 'sendp([{0}], iface="%s", count=%d)'.format(packet)
> + append(cmd % (pktlen, padding, itf, count))
> + else:
> + packet = "/".join(["Ether(dst=nutmac, src=srcmac)",
> + "Dot1Q(vlan=vlanvalue)",
> + "IP(dst=destip, src=srcip, len=%s)",
> + "UDP(sport=srcport, dport=destport)",
> + "Raw(load='\x50'*%s)"])
> + cmd = 'sendp([{0}], iface="%s", count=%d)'.format(packet)
> + append(cmd % (pktlen, padding, itf, count))
> +
> + self.tester.scapy_execute()
> + loop += 1
> +
> + now = time.time()
> + if (now - start) >= during:
> + break
> + time.sleep(.5)
> +
> + if not src_port:
> + p0rx_pkts, p0rx_err, p0rx_bytes = \
> + [int(_) for _ in self.get_stats(self.dut_ports[dst_port], "rx")]
> + else:
> + p0rx_pkts, p0rx_err, p0rx_bytes = \
> + [int(_) for _ in self.get_stats(dst_port, "rx")]
> +
> + p0rx_pkts -= gp0rx_pkts
> + p0rx_bytes -= gp0rx_bytes
> +
> + if invert_verify:
> + LACP_MESSAGE_SIZE = 128
> + msg = ("port <{0}> Data received by port <{1}>, "
> + "but should not.").format(itf, dst_port)
> + self.verify(p0rx_pkts == 0 or
> + p0rx_bytes / p0rx_pkts == LACP_MESSAGE_SIZE,
> + msg)
> + msg = "port {0} <-| |-> port {1} is ok".format(itf,
> + dst_port)
> + self.logger.info(msg)
> + else:
> + msg = "port <{0}> Data not received by port <{1}>".format(itf,
> + dst_port)
> + self.verify(p0rx_pkts >= count * loop,
> + msg)
> + msg = "port {0} <----> port {1} is ok".format( itf, dst_port)
> + self.logger.info(msg)
> + return count * loop
> +
> + def send_default_packet_to_slave(self, unbound_port, bond_port,
> + pkt_count=100, **slaves):
> + """
> + Send packets to the slaves and calculate the slave`s RX packets
> + and unbond port TX packets.
> + Parameters:
> + : unbound_port: the unbonded port id
> + : bond_port: the bonded device port id
> + """
> + pkt_orig = {}
> + pkt_now = {}
> + temp_count = 0
> + summary = 0
> + results = []
> + #---------------------------
> + # send to slave ports
> + pkt_orig = self.get_all_stats(unbound_port, 'tx', bond_port, **slaves)
> + self.logger.info("send packet to active slave ports")
> + for slave in slaves['active']:
> + try:
> + temp_count = self.send_packet(self.dut_ports[int(slave)],
> + False,
> + FRAME_SIZE_64, pkt_count)
> + summary += temp_count
> + except Exception as e:
> + results.append(e)
> + finally:
> + pass
> + #---------------------------
> + if slaves['inactive'] and False:
> + self.logger.info("send packet to inactive slave ports")
> + for slave in slaves['inactive']:
> + try:
> + self.send_packet(self.dut_ports[int(slave)], False,
> + FRAME_SIZE_64, pkt_count, True)
> + except Exception as e:
> + results.append(e)
> + finally:
> + pass
> +
> + if results:
> + for item in results:
> + self.logger.error(e)
> + raise VerifyFailure("send_default_packet_to_slave failed")
> +
> + pkt_now = self.get_all_stats(unbound_port, 'tx', bond_port, **slaves)
> +
> + for key in pkt_now:
> + for num in [0, 1, 2]:
> + pkt_now[key][num] -= pkt_orig[key][num]
> +
> + return pkt_now, summary
> +
> + def send_default_packet_to_unbound_port(self, unbound_port, bond_port,
> + pkt_count=300, **slaves):
> + """
> + Send packets to the unbound port and calculate unbound port RX packets
> + and the slave`s TX packets.
> + Parameters:
> + : unbound_port: the unbonded port id
> + : bond_port: the bonded device port id
> + """
> + pkt_orig = {}
> + pkt_now = {}
> + summary = 0
> +
> + # send to unbonded device
> + pkt_orig = self.get_all_stats(unbound_port, 'rx', bond_port, **slaves)
> + summary = self.send_packet(unbound_port, False,
> + FRAME_SIZE_64, pkt_count)
> + pkt_now = self.get_all_stats(unbound_port, 'rx', bond_port, **slaves)
> +
> + for key in pkt_now:
> + for num in [0, 1, 2]:
> + pkt_now[key][num] -= pkt_orig[key][num]
> +
> + return pkt_now, summary
> +
> + def send_customized_packet_to_unbound_port(self, unbound_port, bond_port,
> + policy, vlan_tag=False,
> + pkt_count=100, **slaves):
> + """
> + Verify that transmitting the packets correctly in the XOR mode.
> + Parameters:
> + : unbound_port: the unbonded port id
> + : bond_port: the bonded device port id
> + : policy: 'L2' , 'L23' or 'L34'
> + : vlan_tag: False or True
> + """
> + pkt_orig = {}
> + pkt_now = {}
> + summary = 0
> + temp_count = 0
> +
> + # send to unbound_port
> + pkt_orig = self.get_all_stats(unbound_port, 'rx', bond_port, **slaves)
> + dest_mac = self.dut.get_mac_address(self.dut_ports[unbound_port])
> + dest_ip = "10.239.129.88"
> + dest_port = 53
> +
> + self.dst_pkt_configs = [dest_mac, dest_ip, dest_port]
> +
> + ether_ip = {}
> + ether = {}
> + ip = {}
> + udp = {}
> +
> + ether['dest_mac'] = False
> + ip['dest_ip'] = dest_ip
> + udp['dest_port'] = 53
> + if vlan_tag:
> + dot1q = {}
> + dot1q['vlan'] = random.randint(1, 50)
> + ether_ip['dot1q'] = dot1q
> +
> + ether_ip['ether'] = ether
> + ether_ip['ip'] = ip
> + ether_ip['udp'] = udp
> +
> + source = self.get_static_ip_configs()
> +
> + for src_mac, src_ip, src_port in source:
> + ether_ip['ether']['src_mac'] = src_mac
> + ether_ip['ip']['src_ip'] = src_ip
> + ether_ip['udp']['src_port'] = src_port
> + temp_count = self.send_packet(unbound_port, False, FRAME_SIZE_64,
> + pkt_count, False, **ether_ip)
> + summary += temp_count
> + pkt_now = self.get_all_stats(unbound_port, 'rx', bond_port, **slaves)
> +
> + for key in pkt_now:
> + for num in [0, 1, 2]:
> + pkt_now[key][num] -= pkt_orig[key][num]
> +
> + return pkt_now, summary
> +
> + #
> + # On dut, dpdk testpmd
> + #
> + def preset_testpmd(self, core_mask, options=''):
> + self.testpmd.start_testpmd( core_mask, param=' '.join(options))
> + self.execute_testpmd_cmd(self.preset_testpmd_cmds)
> + self.preset_testpmd_cmds = list()
> + time.sleep(1)
> +
> + def execute_testpmd_cmd(self, cmds):
> + if len(cmds) == 0:
> + return
> + for item in cmds:
> + expected_str = item[1] or 'testpmd> '
> + if len(item) == 3:
> + self.testpmd.execute_cmd(item[0], item[1], int(item[2]))
> + else:
> + self.testpmd.execute_cmd(item[0], item[1])
> + time.sleep(2)
> +
> + def start_testpmd(self, eal_option=None):
> + if self.testpmd_status == 'running':
> + return
> + # link eal option and testpmd options
> + offloadd = '0x1fbf' if self.driver == 'i40e' else '0x2203f'
> + options = ["--tx-offloads={0}".format(offloadd)]
> +# options = " ".join([eal_option, options]) if eal_option else ''
> + # boot up testpmd
> + hw_mask = '1S/2C/1T'
> + self.preset_testpmd_cmds = [[' ', ''], # used to resolve lsc event
> + ['port stop all', '']]
> + self.preset_testpmd(hw_mask, options)
> + self.testpmd_status = 'running'
> +
> + def stop_testpmd(self):
> + time.sleep(1)
> + testpmd_cmds =[['port stop all', ''],
> + ['stop', ''],]
> + self.execute_testpmd_cmd(testpmd_cmds)
> + time.sleep(1)
> +
> + def close_testpmd(self):
> + if self.testpmd_status == 'close':
> + return
> + self.stop_testpmd()
> + time.sleep(1)
> + self.testpmd.quit()
> + self.testpmd_status = 'close'
> + #
> + # On dut, dpdk bonding
> + #
> + def get_value_from_str(self, key_str, regx_str, string):
> + """
> + Get some values from the given string by the regular expression.
> + """
> + if isinstance(key_str, (unicode, str)):
> + pattern = r"(?<=%s)%s" % (key_str, regx_str)
> + s = re.compile(pattern)
> + res = s.search(string)
> + if type(res).__name__ == 'NoneType':
> + msg = "{0} hasn't match anything".format(key_str)
> + self.logger.warning(msg)
> + return ' '
> + else:
> + return res.group(0)
> + elif isinstance(key_str, (list, tuple)):
> + for key in key_str:
> + pattern = r"(?<=%s)%s" % (key, regx_str)
> + s = re.compile(pattern)
> + res = s.search(string)
> + if type(res).__name__ != 'NoneType':
> + return res.group(0)
> + else:
> + self.logger.warning("all key_str hasn't match anything")
> + return ' '
> +
> + def _get_detail_from_port_info(self, port_id, args):
> + """
> + Get the detail info from the output of pmd cmd
> + 'show port info <port num>'.
> + """
> + port = port_id
> + key_str, regx_str = args
> + out = self.dut.send_expect("show port info %d" % port, "testpmd> ")
> + 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.
> + """
> + search_args = args if isinstance(args[0], (list, tuple)) else [args]
> + for search_args in search_args:
> + try:
> + info = self.get_bonding_config(config_content, search_args)
> + break
> + except Exception as e:
> + self.logger.info(e)
> + 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*"],
> + '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.dut.send_expect(
> + "show bonding config %d" % bond_port,
> + "testpmd> ")
> + if isinstance(info_types, (list or tuple)):
> + query_values = []
> + for info_type in info_types:
> + if info_type in info_set.keys():
> + find_value = self.get_info_from_bond_config(
> + config_content,
> + info_set[info_type])
> + if info_type in ['active_slaves', 'slaves']:
> + find_value = [value for value in find_value.split(' ')
> + if value]
> + else:
> + find_value = None
> + query_values.append(find_value)
> + return query_values
> + else:
> + info_type = info_types
> + if info_type in info_set.keys():
> + find_value = self.get_info_from_bond_config(
> + config_content,
> + info_set[info_type])
> + if info_type in ['active_slaves', 'slaves']:
> + find_value = [value for value in find_value.split(' ')
> + if value]
> + return find_value
> + else:
> + return None
> +
> + def get_active_slaves(self, 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:
> + msg = "primary port <{0}> isn't in active slaves list".format(
> + primary_port)
> + self.logger.error
> + raise VerifyFailure(msg)
> +
> + 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.dut.send_expect(cmd, "testpmd> ")
> + self.verify("Created new bonded device" in out,
> + "Create bonded device on mode [%d] socket [%d] failed" % (
> + mode,
> + socket))
> + bond_port = self.get_value_from_str([
> + "Created new bonded device net_bond_testpmd_[\d] on \(port ",
> + "Created new bonded device net_bonding_testpmd_[\d] on \(port "],
> + "\d+", out)
> + bond_port = int(bond_port)
> +
> + if verify_detail:
> + out = self.dut.send_expect("show bonding config %d" % bond_port,
> + "testpmd> ")
> + self.verify("Bonding mode: %d" % mode in out,
> + "Bonding mode display error when create bonded 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.dut.send_expect("show port info %d" % bond_port,
> + "testpmd> ")
> + self.verify("Connect to socket: %d" % socket in out,
> + "Bonding port connect socket error")
> + self.verify("Link status: down" in out,
> + "Bonding port default link status error")
> + self.verify("Link speed: 0 Mbps" in out,
> + "Bonding port default link speed error")
> +
> + return bond_port
> +
> + def start_ports(self, port='all'):
> + """
> + Start a port which the testpmd can see.
> + """
> + timeout = 12 if port=='all' else 5
> + # to avoid lsc event message interfere normal status
> + #self.dut.send_expect("port start %s" % str(port), " ", timeout)
> + self.dut.send_expect("port start %s" % str(port), " ", timeout)
> + self.dut.send_expect(" ", "testpmd> ", timeout)
> +
> + def add_slave(self, bond_port, invert_verify=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:
> + out = self.dut.send_expect(
> + "add bonding slave %d %d" % (slave_id, bond_port),
> + "testpmd> ")
> + if expected_str:
> + self.verify(expected_str in out,
> + "message <{0}> is missiong".format(expected_str))
> + slaves = self.get_bonding_info(bond_port, 'slaves')
> + if not invert_verify:
> + self.verify(str(slave_id) in slaves,
> + "Add port as bonding slave failed")
> + else:
> + self.verify(str(slave_id) not in slaves,
> + "Add port as bonding slave successfully,should fail")
> +
> + 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.dut.send_expect(cmd, "testpmd> ")
> + 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:
> + self.verify(str(slave_id) in slaves,
> + ("Remove slave successfully from "
> + "bonding device,should be failed"))
> +
> + def remove_all_slaves(self, bond_port):
> + """
> + Remove all slaves of specified bound device.
> + """
> + all_slaves = 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.dut.send_expect(cmd, "testpmd> ")
> + 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:
> + self.verify(str(slave_port) not in out,
> + ("Set bonding primary port successfully, "
> + "should not success"))
> +
> + def set_bonding_mode(self, bond_port, mode):
> + """
> + Set the mode for the bonding device.
> + """
> + cmd = "set bonding mode %d %d" % (mode, bond_port)
> + self.dut.send_expect(cmd, "testpmd> ")
> + 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.dut.send_expect(cmd, "testpmd> ")
> + 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.dut.send_expect(cmd, "testpmd> ")
> + 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 check_stacked_device_queue_config(self, *devices):
> + '''
> + # check if master bonding/each slaves queue configuration is the same.
> + '''
> + master = self.get_port_info(devices[0], 'queue_config')
> + for port_id in devices[1:]:
> + config = self.get_port_info(port_id, 'queue_config')
> + if cmp(config, master) == 0:
> + continue
> + msg = ("slave bonded port [{0}] is "
> + "different to top bonded port [{1}]").format(port_id,
> + devices[0])
> + raise VerifyFailure('check_stacked_device_queue_config ' + msg)
> +
> + def set_stacked_bonded(self, slaveGrpOne, slaveGrpTwo, 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_1 = self.create_bonded_device(bond_mode, specified_socket)
> + self.add_slave(bond_port_1, False, '', *slaveGrpOne)
> + # create bonded device 2, add slaves in it
> + bond_port_2 = self.create_bonded_device(bond_mode, specified_socket)
> + self.add_slave(bond_port_2, False, '', *slaveGrpTwo)
> + # create bonded device 3, which is the top bonded device
> + bond_port_master = self.create_bonded_device(bond_mode,
> + specified_socket)
> + # bond bonded device 2 to bonded device 4
> + # and check bond 0/2 config status
> + self.add_slave(bond_port_master, False, '', *[bond_port_1])
> + # bond bonded device 3 to bonded device 4
> + # and check bond 1/2 config status
> + self.add_slave(bond_port_master, False, '', *[bond_port_2])
> + # check if master bonding/each slaves queue configuration is the same.
> + self.check_stacked_device_queue_config(*[bond_port_master,
> + bond_port_1, bond_port_2])
> + # start all ports
> + #self.start_ports()
> +
> + return [bond_port_1, bond_port_2, bond_port_master]
> +
> + def set_third_stacked_bonded(self, bond_port, bond_mode):
> + '''
> + set third level stacked bonded to check stacked limitation
> + '''
> + specified_socket = 0
> + third_bond_port = self.create_bonded_device(bond_mode,
> + specified_socket)
> + expected_str = 'Too many levels of bonding'
> + try:
> + self.add_slave(third_bond_port, True, expected_str, *[bond_port])
> + except Exception as e:
> + self.logger.warning(e)
> + finally:
> + pass
> +
> + def duplicate_add_stacked_bonded(self, bond_port_1, bond_port_2,
> + bond_port_master):
> + '''
> + check if adding stacked bonded duplicately is forbidden
> + '''
> + # check exception process
> + expected_str = 'Slave device is already a slave of a bonded device'
> + # bond bonded device 2 to bonded device 4
> + # and check bond 0/2 config status
> + self.add_slave(bond_port_master, False, expected_str, *[bond_port_1])
> + # bond bonded device 3 to bonded device 4
> + # and check bond 1/2 config status
> + self.add_slave(bond_port_master, False, expected_str, *[bond_port_2])
> +
> + def preset_stacked_bonded(self, slaveGrpOne, slaveGrpTwo, bond_mode):
> + bond_port_1, bond_port_2, bond_port_master = self.set_stacked_bonded(
> + slaveGrpOne,
> + slaveGrpTwo,
> + bond_mode)
> + # set test pmd
> + cmds = []
> + cmds = [["port stop all", '']]
> + portList = [slaveGrpOne[0],
> + slaveGrpTwo[0],
> + bond_port_1,
> + bond_port_2,
> + bond_port_master]
> + cmds += [["set portlist " + ",".join([str(port)
> + for port in portList]), '']]
> + cmds +=[["port start all", ' ', 15],
> + ["start", '']]
> + self.execute_testpmd_cmd(cmds)
> + time.sleep(5)
> +
> + return bond_port_1, bond_port_2, bond_port_master
> +
> + def preset_normal_bonded(self, bond_mode):
> + '''
> + '''
> + slaveGrpOne = self.slaveGrpOne
> + slaveGrpTwo = self.slaveGrpTwo
> +
> + bond_port_1, bond_port_2, bond_port_master = self.set_stacked_bonded(
> + slaveGrpOne,
> + slaveGrpTwo,
> + bond_mode)
> + # set test pmd
> + cmds = []
> + cmds += [["port stop all", '']]
> + portList = [slaveGrpOne[0],
> + slaveGrpTwo[0],
> + bond_port_1,
> + bond_port_2,
> + bond_port_master]
> + cmds += [["set portlist " + ",".join([str(port) for port in portList]),
> + '']]
> + cmds +=[["port start all", ' ', 15],
> + ["start", '']]
> + self.execute_testpmd_cmd(cmds)
> + time.sleep(5)
> +
> + def check_packet_transmission(self):
> + pkt_count = 100
> + # send 100 packet to bonded device 2 and check bond 2/4 statistics
> + pkt_now, summary = self.send_default_packet_to_slave(
> + unbound_port, bond_port_master,
> + pkt_count=pkt_count, **slaves)
> +
> + # send 100 packet to bonded device 3 and check bond 3/4 statistics
> + pkt_now, summary = self.send_default_packet_to_slave(
> + unbound_port, bond_port_master,
> + pkt_count=pkt_count, **slaves)
> +
> + def convert_mac_str_into_int(self, mac_str):
> + """
> + Translate 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_hash(self, dst_mac, src_mac):
> + """
> + Generate the hash value with the source and destination MAC.
> + """
> + dst_port_mac = self.convert_mac_str_into_int(dst_mac)
> + src_port_mac = self.convert_mac_str_into_int(src_mac)
> + src_xor_dest = dst_port_mac ^ src_port_mac
> + xor_value_1 = src_xor_dest >> 32
> + xor_value_2 = (src_xor_dest >> 16) ^ (xor_value_1 << 16)
> + xor_value_3 = src_xor_dest ^ (xor_value_1 << 32) ^ (xor_value_2 << 16)
> + return htons(xor_value_1 ^ xor_value_2 ^ xor_value_3)
> +
> + def translate_ip_str_into_int(self, ip_str):
> + """
> + Translate the IP type from the string into the int.
> + """
> + ip_part_list = ip_str.split('.')
> + ip_part_list.reverse()
> + num = 0
> + ip_int = 0
> + for ip_part in ip_part_list:
> + ip_part_int = int(ip_part) << (num * 8)
> + ip_int += ip_part_int
> + num += 1
> + return ip_int
> +
> + def ipv4_hash(self, dst_ip, src_ip):
> + """
> + Generate the hash value with the source and destination IP.
> + """
> + dst_ip_int = self.translate_ip_str_into_int(dst_ip)
> + src_ip_int = self.translate_ip_str_into_int(src_ip)
> + return htonl(dst_ip_int ^ src_ip_int)
> +
> + def udp_hash(self, dst_port, src_port):
> + """
> + Generate the hash value with the source and destination port.
> + """
> + return htons(dst_port ^ src_port)
> +
> + def policy_and_slave_hash(self, policy, **slaves):
> + """
> + Generate the hash value by the policy and active slave number.
> + : policy:'L2' , 'L23' or 'L34'
> + """
> + source = self.get_static_ip_configs()
> +
> + dst_mac, dst_ip, dst_port = self.dst_pkt_configs
> +
> + hash_values = []
> + if len(slaves['active']) == 0:
> + return hash_values
> +
> + for src_mac, src_ip, src_port in source:
> + if policy == "L2":
> + hash_value = self.mac_hash(dst_mac, src_mac)
> + elif policy == "L23":
> + hash_value = self.mac_hash(dst_mac, src_mac) ^ \
> + self.ipv4_hash(dst_ip, src_ip)
> + else:
> + hash_value = self.ipv4_hash(dst_ip, src_ip) ^ \
> + self.udp_hash(dst_port, src_port)
> +
> + if policy in ("L23", "L34"):
> + hash_value ^= hash_value >> 16
> + hash_value ^= hash_value >> 8
> + hash_value = hash_value % len(slaves['active'])
> + hash_values.append(hash_value)
> +
> + return hash_values
> +
> + def slave_map_hash(self, port, order_ports):
> + """
> + Find the hash value by the given slave port id.
> + """
> + if len(order_ports) == 0:
> + return None
> + else:
> + #order_ports = order_ports.split()
> + return order_ports.index(str(port))
> +
> + def verify_active_backup_rx(self, unbound_port, bond_port, **slaves):
> + """
> + Verify the RX packets are all correct in the active-backup mode.
> + Parameters:
> + """
> + return
> + pkt_count = 100
> + pkt_now = {}
> +
> + self.logger.info('verify_active_backup_rx')
> + slave_num = slaves['active'].__len__()
> + active_flag = 1 if slave_num != 0 else 0
> + pkt_now, summary = self.send_default_packet_to_slave(
> + unbound_port,
> + bond_port,
> + pkt_count=pkt_count,
> + **slaves)
> + results = []
> + try:
> + self.verify(pkt_now[bond_port][0] == pkt_count * slave_num,
> + "Not correct RX pkt on bond port in mode 1")
> + except Exception as e:
> + results.append(e)
> + finally:
> + pass
> +
> + try:
> + if unbound_port:
> + self.verify(
> + pkt_now[unbound_port][0] == pkt_count * active_flag,
> + "Not correct TX pkt on unbound port in mode 1")
> + except Exception as e:
> + results.append(e)
> + finally:
> + pass
> +
> + try:
> + # check inactive slaves statistics
> + for slave in slaves['inactive']:
> + self.verify(pkt_now[slave][0] == 0,
> + "Not correct RX pkt on inactive port in mode 1")
> + except Exception as e:
> + results.append(e)
> + finally:
> + pass
> +
> + try:
> + # check active slaves statistics
> + for slave in slaves['active']:
> + self.verify(pkt_now[slave][0] == pkt_count,
> + "Not correct RX pkt on active port in mode 1")
> + except Exception as e:
> + results.append(e)
> + finally:
> + pass
> +
> + if not results:
> + for item in results:
> + self.logger.error(e)
> + raise VerifyFailure("verify_active_backup_rx exception")
> +
> + return pkt_now, summary
> +
> + def verify_stacked_active_backup_rx(self, master_bonded, slave_bonded,
> + **slaves):
> + """
> + Verify the RX packets are all correct in the active-backup mode with
> + stacked bonded device. second level bonded device's statistics should
> + be the sum of slave bonded devices statistics.
> + """
> + pkt_count = 100
> + pkt_now = {}
> +
> + self.logger.info('verify_stacked_active_backup_rx')
> + slave_num = slaves['active'].__len__()
> + active_flag = 1 if slave_num != 0 else 0
> + pkt_now, summary = self.send_default_packet_to_slave(
> + None,
> + slave_bonded,
> + pkt_count=pkt_count,
> + **slaves)
> + results = []
> + try:
> + self.verify(pkt_now[slave_bonded][0] == pkt_count * slave_num,
> + "Not correct RX pkt on bond port in mode 1")
> + except Exception as e:
> + results.append(e)
> + finally:
> + pass
> +
> + try:
> + if master_bonded:
> + self.verify(
> + pkt_now[master_bonded][0] == pkt_count * active_flag,
> + "Not correct TX pkt on unbound port in mode 1")
> + pass
> + except Exception as e:
> + results.append(e)
> + finally:
> + pass
> +
> + try:
> + # check inactive slaves statistics
> + for slave in slaves['inactive']:
> + self.verify(pkt_now[slave][0] == 0,
> + "Not correct RX pkt on inactive port in mode 1")
> + except Exception as e:
> + results.append(e)
> + finally:
> + pass
> +
> + try:
> + # check active slaves statistics
> + for slave in slaves['active']:
> + self.verify(pkt_now[slave][0] == pkt_count,
> + "Not correct RX pkt on active port in mode 1")
> + except Exception as e:
> + results.append(e)
> + finally:
> + pass
> +
> + if results:
> + for item in results:
> + self.logger.error(e)
> + raise VerifyFailure("verify_stacked_active_backup_rx exception")
> +
> + return pkt_now, summary
> +
> + def verify_xor_rx(self, unbound_port, bond_port, **slaves):
> + """
> + Verify receiving the pcakets correctly in the XOR mode.
> + Parameters:
> + : unbound_port: the unbonded port id
> + : bond_port: the bonded device port id
> + """
> + pkt_count = 100
> + pkt_now = {}
> +
> + pkt_now, summary = self.send_default_packet_to_slave(
> + unbound_port,
> + bond_port,
> + pkt_count=pkt_count,
> + **slaves)
> +
> + for slave in slaves['active']:
> + self.verify(pkt_now[slave][0] == pkt_count,
> + "Slave have error RX packet in XOR")
> + for slave in slaves['inactive']:
> + self.verify(pkt_now[slave][0] == 0,
> + "Slave have error RX packet in XOR")
> +
> + if unbound_port:
> + self.verify(
> + pkt_now[unbound_port][0] == pkt_count * len(slaves['active']),
> + "Unbonded device have error TX packet in XOR")
> +
> + def verify_xor_tx(self, unbound_port, bond_port, policy,
> + vlan_tag=False, **slaves):
> + """
> + Verify that transmitting the packets correctly in the XOR mode.
> + Parameters:
> + : unbound_port: the unbonded port id
> + : bond_port: the bonded device port id
> + : policy:'L2' , 'L23' or 'L34'
> + : vlan_tag: False or True
> + """
> + pkt_count = 100
> + pkt_now = {}
> + try:
> + pkt_now, summary = self.send_customized_packet_to_unbound_port(
> + unbound_port,
> + bond_port,
> + policy,
> + vlan_tag=False,
> + pkt_count=pkt_count,
> + **slaves)
> + except Exception as e:
> + self.logger.error(traceback.format_exc())
> + finally:
> + pass
> +
> + hash_values = self.policy_and_slave_hash(policy, **slaves)
> + order_ports = self.get_bonding_info(bond_port, 'active_slaves')
> + for slave in slaves['active']:
> + slave_map_hash = self.slave_map_hash(slave, order_ports)
> + self.verify(
> + pkt_now[slave][0] == pkt_count * hash_values.count(slave_map_hash),
> + "XOR load balance transmit error on the link up port")
> + for slave in slaves['inactive']:
> + self.verify(
> + pkt_now[slave][0] == 0,
> + "XOR load balance transmit error on the link down port")
> +
> + @property
> + def driver(self):
> + return self.kdriver
> +
> + #
> + # Test cases.
> + #
> + def set_up_all(self):
> + """
> + Run before each test suite
> + """
> + self.verify('bsdapp' not in self.target,
> + "Bonding not support freebsd")
> + self.dut_ports = self.dut.get_ports()
> +
> + self.port_mask = utils.create_mask(self.dut_ports)
> +
> + #self.verify(len(self.dut_ports) >= 4, "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"))
> +
> + # separate ports into two group
> + sep_index = len(self.dut_ports)/2
> + self.slaveGrpOne = self.dut_ports[:sep_index]
> + self.slaveGrpTwo = self.dut_ports[sep_index:]
> + # testpmd initialization
> + self.testpmd = PmdOutput(self.dut)
> + self.testpmd_status = 'close'
> + self.tester_bond = "bond0"
> + self.dst_pkt_configs = []
> +
> + def tear_down_all(self):
> + """
> + Run after each test suite.
> + """
> + pass
> +
> + def set_up(self):
> + """
> + Run before each test case.
> + """
> + pass
> +
> + def tear_down(self):
> + """
> + Run after each test case.
> + """
> +
> + def backup_check_stacked_bonded_traffic(self):
> + '''
> + '''
> + self.logger.info("begin checking stacked bonded transmission")
> + self.start_testpmd()
> + slaveGrpOne = self.slaveGrpOne
> + slaveGrpTwo = self.slaveGrpTwo
> + bond_port_1, bond_port_2, bond_port_master = \
> + self.preset_stacked_bonded(
> + slaveGrpOne,
> + slaveGrpTwo,
> + MODE_ACTIVE_BACKUP)
> + results = []
> + # check first bonded device
> + try:
> + self.logger.info('check first bonded device')
> + slaves = {}
> + slaves['active'] = slaveGrpOne
> + slaves['inactive'] = []
> + self.verify_stacked_active_backup_rx(None, bond_port_1, **slaves)
> + except Exception as e:
> + results.append(e)
> + finally:
> + pass
> +
> + try:
> + # check second bonded device
> + self.logger.info('check second bonded device')
> + slaves = {}
> + slaves['active'] = slaveGrpTwo
> + slaves['inactive'] = []
> + self.verify_stacked_active_backup_rx(None, bond_port_2, **slaves)
> + except Exception as e:
> + results.append(e)
> + finally:
> + pass
> +
> + pkt_now, summary = 0, 0
> + try:
> + self.logger.info('check master bonded device')
> + # check top bonded device
> + slaves = {}
> + slaves['active'] = slaveGrpOne + slaveGrpTwo
> + slaves['inactive'] = []
> + pkt_now, summary = self.verify_stacked_active_backup_rx(None,
> + bond_port_master, **slaves)
> + except Exception as e:
> + results.append(e)
> + finally:
> + pass
> +
> + self.close_testpmd()
> + if results:
> + for item in results:
> + self.logger.error(e)
> + msg = "backup_check_stacked_bonded_traffic exception"
> + raise VerifyFailure(msg)
> + else:
> + return pkt_now, summary
> +
> + def backup_check_stacked_one_slave_down(self):
> + self.logger.info("begin checking backup stacked one slave down")
> + self.start_testpmd()
> + #-------------------------------
> + # boot up testpmd
> + mode = MODE_ACTIVE_BACKUP
> + slaveGrpOne = self.slaveGrpOne
> + slaveGrpTwo = self.slaveGrpTwo
> + bond_port_1, bond_port_2, bond_port_master = \
> + self.preset_stacked_bonded(slaveGrpOne,
> + slaveGrpTwo,
> + mode)
> + results = []
> + # check packet transmission when one slave of first level bonded device
> + #-------------------------------
> + pkt_now, summary = 0, 0
> + try:
> + # show one slave port of first level bonded device
> + primary_slave = slaveGrpOne[0]
> + self.logger.info("down one slave port of bond_port_1")
> + self.config_tester_port_by_number(primary_slave, "down")
> + primary_port = self.get_bonding_info(bond_port_1, 'primary')
> + msg = "down status slave hasn't been remove from active slaves"
> + self.verify(primary_port != primary_slave, msg)
> + #------------------------------------------------------
> + slaves = {}
> + primary_port, active_slaves = self.get_active_slaves(primary_slave,
> + bond_port_1)
> + slaves['active'] = [primary_port]
> + slaves['active'].extend(active_slaves)
> + slaves['inactive'] = [self.dut_ports[primary_slave]]
> + pkt_now, summary = self.verify_stacked_active_backup_rx(
> + None,
> + bond_port_master,
> + **slaves)
> + except Exception as e:
> + results.append(e)
> + finally:
> + self.config_tester_port_by_number(primary_slave, "up")
> +
> + self.close_testpmd()
> + if results:
> + for item in results:
> + self.logger.error(e)
> + raise VerifyFailure("backup_check_stacked_one_slave_down exception")
> +
> + def check_stacked_xor_rx(self):
> + results = []
> + self.logger.info("begin checking xor stacked transmission")
> + self.start_testpmd()
> + #-------------------------------------
> + #-------------------------------
> + # boot up testpmd
> + try:
> + mode = MODE_XOR_BALANCE
> + slaveGrpOne = self.slaveGrpOne
> + slaveGrpTwo = self.slaveGrpTwo
> + bond_port_1, bond_port_2, bond_port_master = \
> + self.preset_stacked_bonded( slaveGrpOne, slaveGrpTwo, mode)
> + slaves = {}
> + slaves['active'] = slaveGrpOne + slaveGrpTwo
> + slaves['inactive'] = []
> +
> + self.verify_xor_rx(None, bond_port_master, **slaves)
> + except Exception as e:
> + results.append(e)
> + self.logger.error(traceback.format_exc())
> + finally:
> + self.close_testpmd()
> + #-------------------------------------
> + if results:
> + for item in results:
> + self.logger.error(e)
> + raise VerifyFailure("check_stacked_xor_rx exception !")
> +
> + def xor_check_stacked_rx_one_slave_down(self):
> + """
> + Verify that transmitting packets correctly in the XOR mode,
> + when bringing any one slave of the bonding device link down.
> + """
> + results = []
> + self.logger.info("begin xor_check_stacked_rx_one_slave_down")
> + #-------------------------------
> + # boot up testpmd
> + self.start_testpmd()
> + try:
> + #-------------------------------
> + mode = MODE_ACTIVE_BACKUP
> + slaveGrpOne = self.slaveGrpOne
> + #slaveGrpTwo = self.slaveGrpTwo[:-1]
> + slaveGrpTwo = self.slaveGrpTwo
> + bond_port_1, bond_port_2, bond_port_master = \
> + self.preset_stacked_bonded( slaveGrpOne,
> + slaveGrpTwo,
> + mode)
> + primary_slave = slaveGrpOne[0]
> + self.logger.info("down one slave port of bond_port_1")
> + self.config_tester_port_by_number(primary_slave, "down")
> + primary_port = self.get_bonding_info(bond_port_1, 'primary')
> + msg = "down status slave hasn't been remove from active slaves"
> + self.verify(primary_port != primary_slave, msg)
> + #-------------------------
> + # add first bonded
> + primary_port, active_slaves = self.get_active_slaves(primary_slave,
> + bond_port_1)
> + slaves = {}
> + slaves['active'] = [primary_port]
> + slaves['active'].extend(active_slaves)
> + # add second bonded
> + primary_slave = slaveGrpOne[0]
> + primary_port_2, active_slaves_2 = self.get_active_slaves(
> + primary_slave,
> + bond_port_2)
> + slaves['active'] += [primary_port_2]
> + slaves['active'] += active_slaves_2
> + if primary_slave in slaves['active']:
> + slaves['active'].remove(primary_slave)
> + msg = "{0} should not be in active slaves list".format(
> + primary_slave)
> + self.logger.warning()
> +
> + slaves['inactive'] = []#[primary_slave]
> +# self.verify_xor_tx(primary_slave,
> +# bond_port_master,
> +# "L2", False,
> +# **slaves)
> + self.verify_xor_rx(None, bond_port_master, **slaves)
> + except Exception as e:
> + results.append(e)
> + self.logger.error(traceback.format_exc())
> + finally:
> + self.config_tester_port_by_number(primary_slave, "up")
> + self.close_testpmd()
> +
> + if results:
> + for item in results:
> + self.logger.error(e)
> + raise VerifyFailure("xor_check_stacked_rx_one_slave_down failed")
> + else:
> + #return pkt_now, summary
> + pass
> +
> + def test_basic_behav(self):
> + '''
> + allow a bonded device to be added to another bonded device.
> + There's two limitations to create master bonding:
> +
> + - Total depth of nesting is limited to two levels,
> + - 802.3ad mode is not supported if one or more slaves is a bond device
> +
> + note: There 802.3ad mode can not be supported on this bond device.
> +
> + This case is aimed at testing basic stacked bonded device commands.
> +
> + '''
> + #------------------------------------------------
> + # check stacked bonded status, except mode 4 (802.3ad)
> + mode_list =[MODE_ROUND_ROBIN,
> + MODE_ACTIVE_BACKUP,
> + MODE_XOR_BALANCE,
> + MODE_BROADCAST,
> + MODE_TLB_BALANCE,
> + MODE_ALB_BALANCE]
> + slaveGrpOne = self.slaveGrpOne
> + slaveGrpTwo = self.slaveGrpTwo
> + check_result = []
> + for bond_mode in mode_list:
> + self.logger.info("begin mode <{0}> checking".format(bond_mode))
> + # boot up testpmd
> + self.start_testpmd()
> + try:
> + self.logger.info("check bonding mode <{0}>".format(bond_mode))
> + # set up stacked bonded status
> + bond_port_1, bond_port_2, bond_port_master = \
> + self.set_stacked_bonded(slaveGrpOne, slaveGrpTwo,
> + bond_mode)
> + # check duplicate add slave
> + self.duplicate_add_stacked_bonded(bond_port_1, bond_port_2,
> + bond_port_master)
> + # check stacked limitation
> + self.set_third_stacked_bonded(bond_port_master, bond_mode)
> + # quit testpmd, it is not supported to reset testpmd
> + self.logger.info("mode <{0}> done !".format(bond_mode))
> + check_result.append([bond_mode, None])
> + except Exception as e:
> + check_result.append([bond_mode, e])
> + self.logger.error(e)
> + finally:
> + self.close_testpmd()
> + time.sleep(5)
> + #------------
> + # 802.3ad mode is not supported
> + # if one or more slaves is a bond device
> + # so it should raise a exeption
> + msg = ''
> + try:
> + # boot up testpmd
> + self.start_testpmd()
> + # set up stacked bonded status
> + self.set_stacked_bonded(slaveGrpOne, slaveGrpTwo, MODE_LACP)
> + # quit testpmd, it is not supported to reset testpmd
> + msg = ("802.3ad mode hasn't been forbidden to "
> + "use stacked bonded setting")
> + check_result.append([MODE_LACP, msg])
> + except Exception as e:
> + check_result.append([MODE_LACP, None])
> + finally:
> + self.close_testpmd()
> +
> + exception_count = 0
> + for bond_mode, e in check_result:
> + msg = "mode <{0}>".format(bond_mode)
> + if e:
> + self.logger.info(msg)
> + self.logger.error(e)
> + exception_count += 1
> + else:
> + self.logger.info(msg + ' done !')
> + # if some checking item is failed, raise exception
> + if exception_count:
> + raise VerifyFailure('some test items failed')
> + else:
> + self.logger.info('all test items have done !')
> + self.close_testpmd()
> +
> + def test_mode_backup_rx(self):
> + """
> + Verify receiving and transmitting the packets correctly
> + in the active-backup mode.
> + """
> + stacked_stats = self.backup_check_stacked_bonded_traffic()
> +
> + def test_mode_backup_one_slave_down(self):
> + """
> + Verify that receiving and transmitting the pcakets correctly
> + in the active-backup mode, when bringing any one slave of
> + the bonding device link down.
> + """
> + if len(self.dut_ports) >= 4:
> + self.backup_check_stacked_one_slave_down()
> + else:
> + msg = "ports less than 2, ignore stacked one slave down check"
> + self.logger.warning(msg)
> +
> + def test_mode_xor_rx(self):
> + """
> + Verify that receiving packets correctly in the XOR mode.
> + """
> + self.check_stacked_xor_rx()
> +
> + def test_mode_xor_rx_one_slave_down(self):
> + """
> + Verify that transmitting packets correctly in the XOR mode,
> + when bringing any one slave of the bonding device link down.
> + """
> + if len(self.dut_ports) >= 4:
> + self.xor_check_stacked_rx_one_slave_down()
> + else:
> + msg = "ports less than 2, ignore stacked one slave down check"
> + self.logger.warning(msg)
> +
> --
> 1.9.3
More information about the dts
mailing list