* [dts] [PATCH V1 1/7] tests/vf_pmd_bonded: add case to test vf bonding
2023-01-05 10:40 [dts] [PATCH V1 0/7] add cases to test vf bonding Song Jiale
@ 2023-01-05 10:40 ` Song Jiale
2023-01-05 10:40 ` [dts] [PATCH V1 2/7] test_plans/vf_pmd_bonded: " Song Jiale
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Song Jiale @ 2023-01-05 10:40 UTC (permalink / raw)
To: dts; +Cc: Song Jiale
add case to test vf bonding.
Signed-off-by: Song Jiale <songx.jiale@intel.com>
---
tests/TestSuite_vf_pmd_bonded.py | 2152 ++++++++++++++++++++++++++++++
1 file changed, 2152 insertions(+)
create mode 100644 tests/TestSuite_vf_pmd_bonded.py
diff --git a/tests/TestSuite_vf_pmd_bonded.py b/tests/TestSuite_vf_pmd_bonded.py
new file mode 100644
index 00000000..e24138f4
--- /dev/null
+++ b/tests/TestSuite_vf_pmd_bonded.py
@@ -0,0 +1,2152 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 23.03 Intel Corporation
+#
+
+"""
+DPDK Test suite.
+
+
+Test userland 10Gb PMD.
+
+"""
+
+import random
+import re
+import time
+from socket import htonl, htons
+
+import framework.utils as utils
+import tests.bonding as bonding
+from framework.pmd_output import PmdOutput
+from framework.test_case import TestCase
+
+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
+FRAME_SIZE_65 = 65
+FRAME_SIZE_128 = 128
+FRAME_SIZE_256 = 256
+FRAME_SIZE_512 = 512
+FRAME_SIZE_1024 = 1024
+FRAME_SIZE_1280 = 1280
+FRAME_SIZE_1518 = 1518
+
+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),
+]
+
+D_MAC_IP_PORT = []
+LACP_MESSAGE_SIZE = 128
+
+
+class TestPmdBonded(TestCase):
+ def get_stats(self, portid, rx_tx):
+ """
+ Get packets number from port statistic
+ """
+
+ out = self.dut.send_expect("show port stats %d" % portid, "testpmd> ")
+
+ if rx_tx == "rx":
+ result_scanner = (
+ r"RX-packets: ([0-9]+)\s*RX-missed: ([0-9]+)\s*RX-bytes: ([0-9]+)"
+ )
+ elif rx_tx == "tx":
+ result_scanner = (
+ r"TX-packets: ([0-9]+)\s*TX-errors: ([0-9]+)\s*TX-bytes: ([0-9]+)"
+ )
+ else:
+ return None
+
+ scanner = re.compile(result_scanner, re.DOTALL)
+ m = scanner.search(out)
+
+ return m.groups()
+
+ def parse_ether_ip(self, dest_port, **ether_ip):
+ """
+ ether_ip:
+ 'ether':
+ {
+ 'dest_mac':False
+ 'src_mac':"52:00:00:00:00:00"
+ }
+ 'dot1q':
+ {
+ 'vlan':1
+ }
+ 'ip':
+ {
+ 'dest_ip':"10.239.129.88"
+ 'src_ip':"10.239.129.65"
+ }
+ 'udp':
+ {
+ 'dest_port':53
+ 'src_port':53
+ }
+ """
+ ret_ether_ip = {}
+ ether = {}
+ dot1q = {}
+ ip = {}
+ udp = {}
+ try:
+ dut_dest_port = self.vf_ports[dest_port]
+ except Exception as e:
+ dut_dest_port = dest_port
+
+ query_type = "mac"
+ if not ether_ip.get("ether"):
+ ether["dest_mac"] = self.bond_inst.get_port_mac(dut_dest_port, query_type)
+ ether["src_mac"] = "52:00:00:00:00:00"
+ else:
+ if not ether_ip["ether"].get("dest_mac"):
+ ether["dest_mac"] = self.bond_inst.get_port_mac(
+ dut_dest_port, query_type
+ )
+ else:
+ ether["dest_mac"] = ether_ip["ether"]["dest_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["dest_ip"] = "10.239.129.88"
+ ip["src_ip"] = "10.239.129.65"
+ else:
+ if not ether_ip["ip"].get("dest_ip"):
+ ip["dest_ip"] = "10.239.129.88"
+ else:
+ ip["dest_ip"] = ether_ip["ip"]["dest_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["dest_port"] = 53
+ udp["src_port"] = 53
+ else:
+ if not ether_ip["udp"].get("dest_port"):
+ udp["dest_port"] = 53
+ else:
+ udp["dest_port"] = ether_ip["udp"]["dest_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 send_packet(
+ self,
+ dest_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=100000,
+ send packets during 5 seconds.
+ ether_ip:
+ 'ether':
+ {
+ 'dest_mac':False
+ 'src_mac':"52:00:00:00:00:00"
+ }
+ 'dot1q':
+ {
+ 'vlan':1
+ }
+ 'ip':
+ {
+ 'dest_ip':"10.239.129.88"
+ 'src_ip':"10.239.129.65"
+ }
+ 'udp':
+ {
+ 'dest_port':53
+ 'src_port':53
+ }
+ """
+ during = 0
+ loop = 0
+ try:
+ count = int(count)
+ except ValueError as e:
+ if count == "MANY":
+ during = 5
+ count = 100000
+ else:
+ raise e
+
+ if not src_port:
+ gp0rx_pkts, gp0rx_err, gp0rx_bytes = [
+ int(_) for _ in self.get_stats(self.vf_ports[dest_port], "rx")
+ ]
+ itf = self.tester.get_interface(
+ self.tester.get_local_port(self.dut_ports[dest_port])
+ )
+ else:
+ gp0rx_pkts, gp0rx_err, gp0rx_bytes = [
+ int(_) for _ in self.get_stats(dest_port, "rx")
+ ]
+ itf = src_port
+
+ ret_ether_ip = self.parse_ether_ip(dest_port, **ether_ip)
+
+ pktlen = frame_size - 18
+ padding = pktlen - 20
+
+ start = time.time()
+ while True:
+ self.tester.scapy_foreground()
+ self.tester.scapy_append('nutmac="%s"' % ret_ether_ip["ether"]["dest_mac"])
+ self.tester.scapy_append('srcmac="%s"' % ret_ether_ip["ether"]["src_mac"])
+
+ if ether_ip.get("dot1q"):
+ self.tester.scapy_append("vlanvalue=%d" % ret_ether_ip["dot1q"]["vlan"])
+ self.tester.scapy_append('destip="%s"' % ret_ether_ip["ip"]["dest_ip"])
+ self.tester.scapy_append('srcip="%s"' % ret_ether_ip["ip"]["src_ip"])
+ self.tester.scapy_append("destport=%d" % ret_ether_ip["udp"]["dest_port"])
+ self.tester.scapy_append("srcport=%d" % ret_ether_ip["udp"]["src_port"])
+ if not ret_ether_ip.get("dot1q"):
+ self.tester.scapy_append(
+ 'sendp([Ether(dst=nutmac, src=srcmac)/IP(dst=destip, src=srcip, len=%s)/\
+UDP(sport=srcport, dport=destport)/Raw(load="\x50"*%s)], iface="%s", count=%d)'
+ % (pktlen, padding, itf, count)
+ )
+ else:
+ self.tester.scapy_append(
+ 'sendp([Ether(dst=nutmac, src=srcmac)/Dot1Q(vlan=vlanvalue)/IP(dst=destip, src=srcip, len=%s)/\
+UDP(sport=srcport, dport=destport)/Raw(load="\x50"*%s)], iface="%s", count=%d)'
+ % (pktlen, padding, itf, count)
+ )
+
+ self.tester.scapy_execute(timeout=180)
+ loop += 1
+
+ now = time.time()
+ if (now - start) >= during:
+ break
+ time.sleep(0.5)
+
+ if not src_port:
+ p0rx_pkts, p0rx_err, p0rx_bytes = [
+ int(_) for _ in self.get_stats(self.vf_ports[dest_port], "rx")
+ ]
+ else:
+ p0rx_pkts, p0rx_err, p0rx_bytes = [
+ int(_) for _ in self.get_stats(dest_port, "rx")
+ ]
+
+ p0rx_pkts -= gp0rx_pkts
+ p0rx_bytes -= gp0rx_bytes
+
+ if not invert_verify:
+ self.verify(p0rx_pkts >= count * loop, "Data not received by port")
+ else:
+ global LACP_MESSAGE_SIZE
+ self.verify(
+ p0rx_pkts == 0 or p0rx_bytes / p0rx_pkts == LACP_MESSAGE_SIZE,
+ "Data received by port, but should not.",
+ )
+ return count * loop
+
+ def get_value_from_str(self, key_str, regx_str, string):
+ """
+ Get some values from the given string by the regular expression.
+ """
+ pattern = r"(?<=%s)%s" % (key_str, regx_str)
+ s = re.compile(pattern)
+ res = s.search(string)
+ if type(res).__name__ == "NoneType":
+ return " "
+ else:
+ return res.group(0)
+
+ def get_detail_from_port_info(self, key_str, regx_str, port):
+ """
+ Get the detail info from the output of pmd cmd 'show port info <port num>'.
+ """
+ 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_port_mac(self, port_id):
+ """
+ Get the specified port MAC.
+ """
+ return self.get_detail_from_port_info(
+ "MAC address: ", "([0-9A-F]{2}:){5}[0-9A-F]{2}", port_id
+ )
+
+ def get_port_connect_socket(self, port_id):
+ """
+ Get the socket id which the specified port is connecting with.
+ """
+ return self.get_detail_from_port_info("Connect to socket: ", "\d+", port_id)
+
+ def get_port_memory_socket(self, port_id):
+ """
+ Get the socket id which the specified port memory is allocated on.
+ """
+ return self.get_detail_from_port_info(
+ "memory allocation on the socket: ", "\d+", port_id
+ )
+
+ def get_port_link_status(self, port_id):
+ """
+ Get the specified port link status now.
+ """
+ return self.get_detail_from_port_info("Link status: ", "\d+", port_id)
+
+ def get_port_link_speed(self, port_id):
+ """
+ Get the specified port link speed now.
+ """
+ return self.get_detail_from_port_info("Link speed: ", "\d+", port_id)
+
+ def get_port_link_duplex(self, port_id):
+ """
+ Get the specified port link mode, duplex or simplex.
+ """
+ return self.get_detail_from_port_info("Link duplex: ", "\S+", port_id)
+
+ def get_port_promiscuous_mode(self, port_id):
+ """
+ Get the promiscuous mode of port.
+ """
+ return self.get_detail_from_port_info("Promiscuous mode: ", "\S+", port_id)
+
+ def get_port_allmulticast_mode(self, port_id):
+ """
+ Get the allmulticast mode of port.
+ """
+ return self.get_detail_from_port_info("Allmulticast mode: ", "\S+", port_id)
+
+ def get_port_vlan_offload(self, port_id):
+ """
+ Function: get the port vlan setting info.
+ return value:
+ 'strip':'on'
+ 'filter':'on'
+ 'qinq':'off'
+ """
+ vlan_info = {}
+ vlan_info["strip"] = self.get_detail_from_port_info("strip ", "\S+", port_id)
+ vlan_info["filter"] = self.get_detail_from_port_info("filter", "\S+", port_id)
+ vlan_info["qinq"] = self.get_detail_from_port_info(
+ "qinq\(extend\) ", "\S+", port_id
+ )
+ return vlan_info
+
+ def get_info_from_bond_config(self, key_str, regx_str, bond_port):
+ """
+ Get info by executing the command "show bonding config".
+ """
+ out = self.dut.send_expect("show bonding config %d" % bond_port, "testpmd> ")
+ find_value = self.get_value_from_str(key_str, regx_str, out)
+ return find_value
+
+ def get_bond_mode(self, bond_port):
+ """
+ Get the mode of the bonding device which you choose.
+ """
+ return self.get_info_from_bond_config("Bonding mode: ", "\d*", bond_port)
+
+ def get_bond_balance_policy(self, bond_port):
+ """
+ Get the balance transmit policy of bonding device.
+ """
+ return self.get_info_from_bond_config("Balance Xmit Policy: ", "\S+", bond_port)
+
+ def get_bond_slaves(self, bond_port):
+ """
+ Get all the slaves of the bonding device which you choose.
+ """
+ try:
+ return self.get_info_from_bond_config(
+ "Slaves \(\d\): \[", "\d*( \d*)*", bond_port
+ )
+ except Exception as e:
+ return self.get_info_from_bond_config("Slaves: \[", "\d*( \d*)*", bond_port)
+
+ def get_bond_active_slaves(self, bond_port):
+ """
+ Get the active slaves of the bonding device which you choose.
+ """
+ try:
+ return self.get_info_from_bond_config(
+ "Active Slaves \(\d\): \[", "\d*( \d*)*", bond_port
+ )
+ except Exception as e:
+ return self.get_info_from_bond_config(
+ "Acitve Slaves: \[", "\d*( \d*)*", bond_port
+ )
+
+ def get_bond_primary(self, bond_port):
+ """
+ Get the primary slave of the bonding device which you choose.
+ """
+ return self.get_info_from_bond_config("Primary: \[", "\d*", bond_port)
+
+ def create_bonded_device(self, mode=0, socket=0, verify_detail=False):
+ """
+ Create a bonding device with the parameters you specified.
+ """
+ out = self.dut.send_expect(
+ "create bonded device %d %d" % (mode, socket), "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_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: None" in out, "Bonding port default link speed error"
+ )
+
+ return bond_port
+
+ def start_port(self, port):
+ """
+ Start a port which the testpmd can see.
+ """
+ self.pmdout.execute_cmd("port start %s" % str(port))
+
+ def add_slave_to_bonding_device(self, bond_port, invert_verify=False, *slave_port):
+ """
+ Add the ports into the bonding device as slaves.
+ """
+ if len(slave_port) <= 0:
+ utils.RED("No port exist when add slave to bonded device")
+ for slave_id in slave_port:
+ self.pmdout.execute_cmd("add bonding slave %d %d" % (slave_id, bond_port))
+ slaves = self.get_info_from_bond_config(
+ "Slaves \(\d\): \[", "\d*( \d*)*", bond_port
+ )
+ 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_slave_from_bonding_device(
+ 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:
+ self.dut.send_expect(
+ "remove bonding slave %d %d" % (int(slave_id), bond_port), "testpmd> "
+ )
+ out = self.get_info_from_bond_config("Slaves: \[", "\d*( \d*)*", bond_port)
+ if not invert_verify:
+ self.verify(
+ str(slave_id) not in out, "Remove slave to fail from bonding device"
+ )
+ else:
+ self.verify(
+ str(slave_id) in out,
+ "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_bond_slaves(bond_port)
+ all_slaves = all_slaves.split()
+ if len(all_slaves) == 0:
+ pass
+ else:
+ self.remove_slave_from_bonding_device(bond_port, False, *all_slaves)
+
+ def set_primary_for_bonding_device(
+ self, bond_port, slave_port, invert_verify=False
+ ):
+ """
+ Set the primary slave for the bonding device.
+ """
+ self.dut.send_expect(
+ "set bonding primary %d %d" % (slave_port, bond_port), "testpmd> "
+ )
+ out = self.get_info_from_bond_config("Primary: \[", "\d*", bond_port)
+ 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_mode_for_bonding_device(self, bond_port, mode):
+ """
+ Set the mode for the bonding device.
+ """
+ self.dut.send_expect("set bonding mode %d %d" % (mode, bond_port), "testpmd> ")
+ mode_value = self.get_bond_mode(bond_port)
+ self.verify(str(mode) in mode_value, "Set bonding mode failed")
+
+ def set_mac_for_bonding_device(self, bond_port, mac):
+ """
+ Set the MAC for the bonding device.
+ """
+ self.dut.send_expect(
+ "set bonding mac_addr %s %s" % (bond_port, mac), "testpmd> "
+ )
+ new_mac = self.get_port_mac(bond_port)
+ self.verify(new_mac == mac, "Set bonding mac failed")
+
+ def set_balance_policy_for_bonding_device(self, bond_port, policy):
+ """
+ Set the balance transmit policy for the bonding device.
+ """
+ self.dut.send_expect(
+ "set bonding balance_xmit_policy %d %s" % (bond_port, policy), "testpmd> "
+ )
+ new_policy = self.get_bond_balance_policy(bond_port)
+ policy = "BALANCE_XMIT_POLICY_LAYER" + policy.lstrip("l")
+ self.verify(new_policy == policy, "Set bonding balance policy failed")
+
+ 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
+ *** slaves:
+ ******* 'active'=[]
+ ******* 'inactive'=[]
+ """
+ summary = 0
+
+ # send to slave ports
+ pkt_orig = self.get_all_stats(unbound_port, "tx", bond_port, **slaves)
+ for slave in slaves["active"]:
+ temp_count = self.send_packet(
+ self.vf_ports[slave], False, FRAME_SIZE_64, pkt_count
+ )
+ summary += temp_count
+ for slave in slaves["inactive"]:
+ self.send_packet(
+ self.vf_ports[slave], False, FRAME_SIZE_64, pkt_count, True
+ )
+ time.sleep(1)
+ 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_customized_packet_to_slave(
+ self, unbound_port, bond_port, *pkt_info, **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_info: the first is necessary which will describe the packet,
+ the second is optional which will describe the params of
+ the function send_packet
+ *** slaves:
+ ******* 'active'=[]
+ ******* 'inactive'=[]
+ """
+ pkt_orig = {}
+ pkt_now = {}
+ temp_count = 0
+ summary = 0
+
+ pkt_info_len = len(pkt_info)
+ if pkt_info_len < 1:
+ self.verify(False, "At least one members for pkt_info!")
+
+ ether_ip = pkt_info[0]
+ if pkt_info_len > 1:
+ pkt_size = pkt_info[1].get("frame_size", FRAME_SIZE_64)
+ pkt_count = pkt_info[1].get("pkt_count", 1)
+ invert_verify = pkt_info[1].get("verify", False)
+ else:
+ pkt_size = FRAME_SIZE_64
+ pkt_count = 1
+ invert_verify = False
+
+ # send to slave ports
+ pkt_orig = self.get_all_stats(unbound_port, "tx", bond_port, **slaves)
+ for slave in slaves["active"]:
+ temp_count = self.send_packet(
+ self.vf_ports[slave],
+ False,
+ pkt_size,
+ pkt_count,
+ invert_verify,
+ **ether_ip,
+ )
+ summary += temp_count
+ for slave in slaves["inactive"]:
+ self.send_packet(
+ self.vf_ports[slave], False, FRAME_SIZE_64, pkt_count, True
+ )
+ 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, **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
+ *** slaves:
+ ******* 'active':[]
+ ******* 'inactive':[]
+ """
+ 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
+ *** slaves:
+ ******* 'active'=[]
+ ******* 'inactive'=[]
+ """
+ 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)
+ query_type = "mac"
+ dest_mac = self.bond_inst.get_port_mac(self.vf_ports[unbound_port], query_type)
+ dest_ip = "10.239.129.88"
+ dest_port = 53
+
+ global D_MAC_IP_PORT
+ D_MAC_IP_PORT = [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
+
+ global S_MAC_IP_PORT
+ source = S_MAC_IP_PORT
+
+ 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
+
+ #
+ # Test cases.
+ #
+ def set_up_all(self):
+ """
+ Run before each test suite
+ """
+ self.verify("bsdapp" not in self.target, "Bonding not support freebsd")
+ self.frame_sizes = [64, 65, 128, 256, 512, 1024, 1280, 1518]
+
+ self.eth_head_size = 18
+ self.ip_head_size = 20
+ self.udp_header_size = 8
+
+ self.dut_ports = self.dut.get_ports()
+ self.dport_info0 = self.dut.ports_info[self.dut_ports[0]]
+ self.dport_ifaces0 = self.dport_info0["intf"]
+ self.dport_info1 = self.dut.ports_info[self.dut_ports[1]]
+ self.dport_ifaces1 = self.dport_info1["intf"]
+ tester_port0 = self.tester.get_local_port(self.dut_ports[0])
+ self.tport_iface0 = self.tester.get_interface(tester_port0)
+ tester_port1 = self.tester.get_local_port(self.dut_ports[1])
+ self.tport_iface1 = self.tester.get_interface(tester_port1)
+ self.flag = "link-down-on-close"
+ self.default_stats = self.tester.get_priv_flags_state(
+ self.tport_iface0, self.flag
+ )
+ for port in self.dut_ports:
+ tester_port = self.tester.get_local_port(port)
+ tport_iface = self.tester.get_interface(tester_port)
+ self.tester.send_expect(
+ "ethtool --set-priv-flags %s %s on" % (tport_iface, self.flag), "# "
+ )
+ self.create_vfs(pfs_id=self.dut_ports, vf_num=1)
+ self.vf_ports = list(range(len(self.vfs_pci)))
+ self.pmdout = PmdOutput(self.dut)
+
+ self.tester_bond = "bond0"
+ # initialize bonding common methods name
+ config = {
+ "parent": self,
+ "pkt_name": "udp",
+ "pkt_size": FRAME_SIZE_64,
+ "src_mac": "52:00:00:00:00:03",
+ "src_ip": "10.239.129.65",
+ "src_port": 61,
+ "dst_ip": "10.239.129.88",
+ "dst_port": 53,
+ }
+ self.bond_inst = bonding.PmdBonding(**config)
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ if self.running_case in ["test_bound_promisc_opt", "test_tlb_basic"]:
+ self.dut.send_expect(
+ "ip link set %s vf 0 trust on" % (self.dport_ifaces0), "# "
+ )
+ self.pmdout.start_testpmd(
+ cores="1S/4C/1T",
+ ports=self.vfs_pci,
+ )
+
+ def create_vfs(self, pfs_id, vf_num):
+ self.sriov_vfs_port = []
+ self.vfs_pci = []
+ self.dut.bind_interfaces_linux(self.kdriver)
+ pfs_id = pfs_id if isinstance(pfs_id, list) else [pfs_id]
+ for pf_id in pfs_id:
+ self.dut.generate_sriov_vfs_by_port(pf_id, vf_num)
+ self.sriov_vfs_port += self.dut.ports_info[self.dut_ports[pf_id]][
+ "vfs_port"
+ ]
+ dport_iface = self.dut.ports_info[self.dut_ports[pf_id]]["intf"]
+ self.dut.send_expect(
+ "ip link set %s vf 0 spoofchk off" % (dport_iface), "# "
+ )
+ for vf in self.sriov_vfs_port:
+ self.vfs_pci.append(vf.pci)
+ try:
+ for port in self.sriov_vfs_port:
+ port.bind_driver(self.drivername)
+
+ except Exception as e:
+ self.destroy_iavf()
+ raise Exception(e)
+
+ def destroy_iavf(self):
+ self.dut.destroy_sriov_vfs_by_port(self.dut_ports[0])
+
+ def verify_bound_basic_opt(self, mode_set):
+ """
+ Do some basic operations to bonded devices and slaves,
+ such as adding, removing, setting primary or setting mode.
+ """
+ bond_port_0 = self.create_bonded_device(mode_set, SOCKET_0, True)
+ self.add_slave_to_bonding_device(bond_port_0, False, self.vf_ports[1])
+
+ mode_value = self.get_bond_mode(bond_port_0)
+ self.verify("%d" % mode_set in mode_value, "Setting bonding mode error")
+
+ bond_port_1 = self.create_bonded_device(mode_set, SOCKET_0)
+ self.add_slave_to_bonding_device(bond_port_0, False, self.vf_ports[0])
+ self.add_slave_to_bonding_device(bond_port_1, True, self.vf_ports[0])
+
+ OTHER_MODE = mode_set + 1 if not mode_set else mode_set - 1
+ self.set_mode_for_bonding_device(bond_port_0, OTHER_MODE)
+ self.set_mode_for_bonding_device(bond_port_0, mode_set)
+
+ self.add_slave_to_bonding_device(bond_port_0, False, self.vf_ports[2])
+ time.sleep(3)
+ self.set_primary_for_bonding_device(bond_port_0, self.vf_ports[2])
+
+ self.remove_slave_from_bonding_device(bond_port_0, False, self.vf_ports[2])
+ primary_now = self.get_bond_primary(bond_port_0)
+ self.verify(
+ int(primary_now) == self.vf_ports[1],
+ "Reset primary slave failed after removing primary slave",
+ )
+
+ for bond_port in [bond_port_0, bond_port_1]:
+ self.remove_all_slaves(bond_port)
+
+ self.dut.send_expect("quit", "# ")
+ self.pmdout.start_testpmd(
+ cores="1S/4C/1T",
+ ports=self.vfs_pci,
+ )
+
+ def verify_bound_mac_opt(self, mode_set):
+ """
+ Create bonded device, add one slave,
+ verify bonded device MAC action varies with the mode.
+ """
+ mac_address_0_orig = self.get_port_mac(self.vf_ports[0])
+ mac_address_1_orig = self.get_port_mac(self.vf_ports[1])
+ mac_address_2_orig = self.get_port_mac(self.vf_ports[2])
+ mac_address_3_orig = self.get_port_mac(self.vf_ports[3])
+
+ bond_port = self.create_bonded_device(mode_set, SOCKET_1)
+ self.add_slave_to_bonding_device(bond_port, False, self.vf_ports[1])
+
+ mac_address_bond_orig = self.get_port_mac(bond_port)
+ self.verify(
+ mac_address_1_orig == mac_address_bond_orig,
+ "Bonded device MAC address not same with first slave MAC",
+ )
+
+ self.add_slave_to_bonding_device(bond_port, False, self.vf_ports[2])
+ mac_address_2_now = self.get_port_mac(self.vf_ports[2])
+ mac_address_bond_now = self.get_port_mac(bond_port)
+ if mode_set in [MODE_ROUND_ROBIN, MODE_XOR_BALANCE, MODE_BROADCAST]:
+ self.verify(
+ mac_address_1_orig == mac_address_bond_now
+ and mac_address_bond_now == mac_address_2_now,
+ "NOT all slaves MAC address same with bonding device in mode %d"
+ % mode_set,
+ )
+ else:
+ self.verify(
+ mac_address_1_orig == mac_address_bond_now
+ and mac_address_bond_now != mac_address_2_now,
+ "All slaves should not be the same in mode %d" % mode_set,
+ )
+
+ new_mac = "00:11:22:00:33:44"
+ self.set_mac_for_bonding_device(bond_port, new_mac)
+ self.start_port(bond_port)
+ mac_address_1_now = self.get_port_mac(self.vf_ports[1])
+ mac_address_2_now = self.get_port_mac(self.vf_ports[2])
+ mac_address_bond_now = self.get_port_mac(bond_port)
+ if mode_set in [MODE_ROUND_ROBIN, MODE_XOR_BALANCE, MODE_BROADCAST]:
+ self.verify(
+ mac_address_1_now
+ == mac_address_2_now
+ == mac_address_bond_now
+ == new_mac,
+ "Set mac failed for bonding device in mode %d" % mode_set,
+ )
+ elif mode_set == MODE_LACP:
+ self.verify(
+ mac_address_bond_now == new_mac
+ and mac_address_1_now != new_mac
+ and mac_address_2_now != new_mac
+ and mac_address_1_now != mac_address_2_now,
+ "Set mac failed for bonding device in mode %d" % mode_set,
+ )
+ elif mode_set in [MODE_ACTIVE_BACKUP, MODE_TLB_BALANCE]:
+ self.verify(
+ mac_address_bond_now == new_mac
+ and mac_address_1_now == new_mac
+ and mac_address_bond_now != mac_address_2_now,
+ "Set mac failed for bonding device in mode %d" % mode_set,
+ )
+
+ self.set_primary_for_bonding_device(bond_port, self.vf_ports[2], False)
+ mac_address_1_now = self.get_port_mac(self.vf_ports[1])
+ mac_address_2_now = self.get_port_mac(self.vf_ports[2])
+ mac_address_bond_now = self.get_port_mac(bond_port)
+ self.verify(
+ mac_address_bond_now == new_mac, "Slave MAC changed when set primary slave"
+ )
+
+ mac_address_1_orig = mac_address_1_now
+ self.remove_slave_from_bonding_device(bond_port, False, self.vf_ports[2])
+ mac_address_2_now = self.get_port_mac(self.vf_ports[2])
+ self.verify(
+ mac_address_2_now == mac_address_2_orig,
+ "MAC not back to original after removing the port",
+ )
+
+ mac_address_1_now = self.get_port_mac(self.vf_ports[1])
+ mac_address_bond_now = self.get_port_mac(bond_port)
+ self.verify(
+ mac_address_bond_now == new_mac and mac_address_1_now == mac_address_1_orig,
+ "Bonding device or slave MAC changed after removing the primary slave",
+ )
+
+ self.remove_all_slaves(bond_port)
+ self.dut.send_expect("quit", "# ")
+ self.pmdout.start_testpmd(
+ cores="1S/4C/1T",
+ ports=self.vfs_pci,
+ )
+
+ def verify_bound_promisc_opt(self, mode_set):
+ """
+ Set promiscuous mode on bonded device, verify bonded device and all slaves
+ have different actions by the different modes.
+ """
+ unbound_port = self.vf_ports[3]
+ bond_port = self.create_bonded_device(mode_set, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (unbound_port, bond_port), "testpmd> "
+ )
+ self.start_port(bond_port)
+ self.dut.send_expect("start", "testpmd> ")
+
+ port_disabled_num = 0
+ testpmd_all_ports = self.vf_ports
+ testpmd_all_ports.append(bond_port)
+ for port_id in testpmd_all_ports:
+ value = self.get_detail_from_port_info(
+ "Promiscuous mode: ", "enabled", port_id
+ )
+ if not value:
+ port_disabled_num += 1
+ self.verify(
+ port_disabled_num == 0,
+ "Not all slaves of bonded device turn promiscuous mode on by default.",
+ )
+
+ ether_ip = {}
+ ether = {}
+ ether["dest_mac"] = "00:11:22:33:44:55"
+ ether_ip["ether"] = ether
+
+ send_param = {}
+ pkt_count = 1
+ send_param["pkt_count"] = pkt_count
+ pkt_info = [ether_ip, send_param]
+
+ slaves = {}
+ slaves["active"] = [self.vf_ports[0]]
+ slaves["inactive"] = []
+ curr_primary = self.vf_ports[0]
+
+ pkt_now, summary = self.send_customized_packet_to_slave(
+ unbound_port, bond_port, *pkt_info, **slaves
+ )
+ if mode_set == MODE_LACP:
+ do_transmit = False
+ pkt_size = 0
+ if pkt_now[unbound_port][0]:
+ do_transmit = True
+ pkt_size = pkt_now[unbound_port][2] / pkt_now[unbound_port][0]
+ self.verify(
+ do_transmit and pkt_size != LACP_MESSAGE_SIZE,
+ "Data not received by slave or bonding device when promiscuous enabled",
+ )
+ else:
+ self.verify(
+ pkt_now[self.vf_ports[0]][0] == pkt_now[bond_port][0]
+ and pkt_now[bond_port][0] == pkt_count,
+ "Data not received by slave or bonding device when promiscuous enabled",
+ )
+
+ self.dut.send_expect("set promisc %s off" % bond_port, "testpmd> ")
+ port_disabled_num = 0
+ testpmd_all_ports = [
+ self.vf_ports[0],
+ self.vf_ports[1],
+ self.vf_ports[2],
+ bond_port,
+ ]
+ for port_id in testpmd_all_ports:
+ value = self.get_detail_from_port_info(
+ "Promiscuous mode: ", "disabled", port_id
+ )
+ if value == "disabled":
+ port_disabled_num += 1
+ if mode_set in [MODE_ROUND_ROBIN, MODE_XOR_BALANCE, MODE_BROADCAST]:
+ self.verify(
+ port_disabled_num == 4,
+ "Not all slaves of bonded device turn promiscuous mode off in mode %d."
+ % mode_set,
+ )
+ elif mode_set == MODE_LACP:
+ self.verify(
+ port_disabled_num == 1,
+ "Not only turn bound device promiscuous mode off in mode %d" % mode_set,
+ )
+ else:
+ self.verify(
+ port_disabled_num == 2,
+ "Not only the primary slave turn promiscous mode off in mode %d, "
+ % mode_set
+ + " when bonded device promiscous disabled.",
+ )
+ curr_primary = int(self.get_bond_primary(bond_port))
+ slaves["active"] = [curr_primary]
+
+ if mode_set != MODE_LACP:
+ send_param["verify"] = True
+ pkt_now, summary = self.send_customized_packet_to_slave(
+ unbound_port, bond_port, *pkt_info, **slaves
+ )
+ if mode_set == MODE_LACP:
+ do_transmit = False
+ pkt_size = 0
+ if pkt_now[unbound_port][0]:
+ do_transmit = True
+ pkt_size = pkt_now[unbound_port][2] / pkt_now[unbound_port][0]
+ self.verify(
+ not do_transmit or pkt_size == LACP_MESSAGE_SIZE,
+ "Data received by slave or bonding device when promiscuous disabled",
+ )
+ else:
+ self.verify(
+ pkt_now[curr_primary][0] == 0 and pkt_now[bond_port][0] == 0,
+ "Data received by slave or bonding device when promiscuous disabled",
+ )
+
+ pkt_now, summary = self.send_default_packet_to_slave(
+ self.vf_ports[3], bond_port, pkt_count, **slaves
+ )
+ if mode_set == MODE_LACP:
+ do_transmit = False
+ pkt_size = 0
+ if pkt_now[unbound_port][0]:
+ do_transmit = True
+ pkt_size = pkt_now[unbound_port][2] / pkt_now[unbound_port][0]
+ self.verify(
+ not do_transmit or pkt_size != LACP_MESSAGE_SIZE,
+ "RX or TX packet number not correct when promiscuous disabled",
+ )
+ else:
+ self.verify(
+ pkt_now[curr_primary][0] == pkt_now[bond_port][0]
+ and pkt_now[self.vf_ports[3]][0] == pkt_now[bond_port][0]
+ and pkt_now[bond_port][0] == pkt_count,
+ "RX or TX packet number not correct when promiscuous disabled",
+ )
+
+ # Stop fwd threads first before removing slaves from bond to avoid
+ # races and crashes
+ self.dut.send_expect("stop", "testpmd> ")
+ self.remove_all_slaves(bond_port)
+ self.dut.send_expect("quit", "# ")
+
+ def test_bound_basic_opt(self):
+ """
+ Test Case1: Basic bonding--Create bonded devices and slaves
+ """
+ self.verify_bound_basic_opt(MODE_ACTIVE_BACKUP)
+
+ def test_bound_mac_opt(self):
+ """
+ Test Case2: Basic bonding--MAC Address Test
+ """
+ self.verify_bound_mac_opt(MODE_BROADCAST)
+
+ def test_bound_promisc_opt(self):
+ """
+ Test Case3: Basic bonding--Device Promiscuous Mode Test
+ """
+ self.verify_bound_promisc_opt(MODE_BROADCAST)
+
+ def admin_tester_port(self, local_port, 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(local_port, status)
+ else:
+ eth = self.tester.get_interface(local_port)
+ self.tester.admin_ports_linux(eth, status)
+ time.sleep(10)
+
+ def verify_round_robin_rx(self, unbound_port, bond_port, **slaves):
+ """
+ Verify the receiving packet are all correct in the round robin mode.
+ slaves:
+ 'active' = []
+ 'inactive' = []
+ """
+ pkt_count = 100
+ pkt_now = {}
+ pkt_now, summary = self.send_default_packet_to_slave(
+ unbound_port, bond_port, pkt_count=pkt_count, **slaves
+ )
+
+ self.verify(
+ pkt_now[unbound_port][0] == pkt_count * slaves["active"].__len__(),
+ "Unbonded port has error TX pkt count in mode 0",
+ )
+ self.verify(
+ pkt_now[bond_port][0] == pkt_count * slaves["active"].__len__(),
+ "Bonding port has error RX pkt count in mode 0",
+ )
+
+ def verify_round_robin_tx(self, unbound_port, bond_port, **slaves):
+ """
+ Verify the transmitting packet are all correct in the round robin mode.
+ slaves:
+ 'active' = []
+ 'inactive' = []
+ """
+ pkt_count = 300
+ pkt_now = {}
+ pkt_now, summary = self.send_default_packet_to_unbound_port(
+ unbound_port, bond_port, pkt_count=pkt_count, **slaves
+ )
+
+ if slaves["active"].__len__() == 0:
+ self.verify(
+ pkt_now[bond_port][0] == 0,
+ "Bonding port should not have TX pkt in mode 0 when all slaves down",
+ )
+ else:
+ self.verify(
+ pkt_now[bond_port][0] == pkt_count,
+ "Bonding port has error TX pkt count in mode 0",
+ )
+ for slave in slaves["active"]:
+ self.verify(
+ pkt_now[slave][0] == pkt_count / slaves["active"].__len__(),
+ "Active slave has error TX pkt count in mode 0",
+ )
+ for slave in slaves["inactive"]:
+ self.verify(
+ pkt_now[slave][0] == 0,
+ "Inactive slave has error TX pkt count in mode 0",
+ )
+
+ def test_round_robin_rx_tx(self):
+ """
+ Test Case4: Mode 0(Round Robin) TX/RX test
+ """
+ bond_port = self.create_bonded_device(MODE_ROUND_ROBIN, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+
+ slaves = {}
+ slaves["active"] = [self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]]
+ slaves["inactive"] = []
+ self.verify_round_robin_rx(self.vf_ports[3], bond_port, **slaves)
+ self.verify_round_robin_tx(self.vf_ports[3], bond_port, **slaves)
+
+ def test_round_robin_one_slave_down(self):
+ """
+ Test Case5: Mode 0(Round Robin) Bring one slave link down
+ """
+ bond_port = self.create_bonded_device(MODE_ROUND_ROBIN, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "down")
+
+ stat = self.tester.get_port_status(
+ self.tester.get_local_port(self.dut_ports[0])
+ )
+ self.dut.send_expect("show bonding config %d" % bond_port, "testpmd> ")
+ self.dut.send_expect("show port info all", "testpmd> ")
+
+ try:
+ slaves = {}
+ slaves["active"] = [self.vf_ports[1], self.vf_ports[2]]
+ slaves["inactive"] = [self.vf_ports[0]]
+ self.verify_round_robin_rx(self.vf_ports[3], bond_port, **slaves)
+ self.verify_round_robin_tx(self.vf_ports[3], bond_port, **slaves)
+ finally:
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "up")
+
+ def test_round_robin_all_slaves_down(self):
+ """
+ Test Case6: Mode 0(Round Robin) Bring all slave links down
+ """
+ bond_port = self.create_bonded_device(MODE_ROUND_ROBIN, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "down")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[1]), "down")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[2]), "down")
+
+ try:
+ slaves = {}
+ slaves["active"] = []
+ slaves["inactive"] = [
+ self.vf_ports[0],
+ self.vf_ports[1],
+ self.vf_ports[2],
+ ]
+ self.verify_round_robin_rx(self.vf_ports[3], bond_port, **slaves)
+ self.verify_round_robin_tx(self.vf_ports[3], bond_port, **slaves)
+ finally:
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "up")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[1]), "up")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[2]), "up")
+
+ def get_all_stats(self, unbound_port, rx_tx, bond_port, **slaves):
+ """
+ Get all the port stats which the testpmd can discover.
+ Parameters:
+ *** unbound_port: pmd port id
+ *** rx_tx: unbond port stat 'rx' or 'tx'
+ *** bond_port: bonding port
+ *** slaves:
+ ******** 'active' = []
+ ******** 'inactive' = []
+ """
+ pkt_now = {}
+
+ if rx_tx == "rx":
+ bond_stat = "tx"
+ else:
+ bond_stat = "rx"
+
+ 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 verify_active_backup_rx(self, unbound_port, bond_port, **slaves):
+ """
+ Verify the RX packets are all correct in the active-backup mode.
+ Parameters:
+ *** slaves:
+ ******* 'active' = []
+ ******* 'inactive' = []
+ """
+ pkt_count = 100
+ pkt_now = {}
+
+ slave_num = slaves["active"].__len__()
+ if slave_num != 0:
+ active_flag = 1
+ else:
+ active_flag = 0
+
+ pkt_now, summary = self.send_default_packet_to_slave(
+ unbound_port, bond_port, pkt_count=pkt_count, **slaves
+ )
+
+ self.verify(
+ pkt_now[bond_port][0] == pkt_count * slave_num,
+ "Not correct RX pkt on bond port in mode 1",
+ )
+ self.verify(
+ pkt_now[unbound_port][0] == pkt_count * active_flag,
+ "Not correct TX pkt on unbound port in mode 1",
+ )
+ for slave in slaves["inactive"]:
+ self.verify(
+ pkt_now[slave][0] == 0, "Not correct RX pkt on inactive port in mode 1"
+ )
+ for slave in slaves["active"]:
+ self.verify(
+ pkt_now[slave][0] == pkt_count,
+ "Not correct RX pkt on active port in mode 1",
+ )
+
+ def verify_active_backup_tx(self, unbound_port, bond_port, **slaves):
+ """
+ Verify the TX packets are all correct in the active-backup mode.
+ Parameters:
+ *** slaves:
+ ******* 'active' = []
+ ******* 'inactive' = []
+ """
+ pkt_count = 0
+ pkt_now = {}
+
+ if slaves["active"].__len__() != 0:
+ primary_port = slaves["active"][0]
+ active_flag = 1
+ else:
+ active_flag = 0
+
+ pkt_now, summary = self.send_default_packet_to_unbound_port(
+ unbound_port, bond_port, pkt_count=pkt_count, **slaves
+ )
+
+ self.verify(
+ pkt_now[bond_port][0] == pkt_count * active_flag,
+ "Not correct RX pkt on bond port in mode 1",
+ )
+ if active_flag == 1:
+ self.verify(
+ pkt_now[primary_port][0] == pkt_count,
+ "Not correct TX pkt on primary port in mode 1",
+ )
+ for slave in slaves["inactive"]:
+ self.verify(
+ pkt_now[slave][0] == 0, "Not correct TX pkt on inactive port in mode 1"
+ )
+ for slave in [slave for slave in slaves["active"] if slave != primary_port]:
+ self.verify(
+ pkt_now[slave][0] == 0, "Not correct TX pkt on backup port in mode 1"
+ )
+
+ def test_active_backup_rx_tx(self):
+ """
+ Test Case7: Mode 1(Active Backup) TX/RX Test
+ """
+ bond_port = self.create_bonded_device(MODE_ACTIVE_BACKUP, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+ time.sleep(5)
+
+ slaves = {}
+ slaves["active"] = [self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]]
+ slaves["inactive"] = []
+ self.verify_active_backup_rx(self.vf_ports[3], bond_port, **slaves)
+ self.verify_active_backup_tx(self.vf_ports[3], bond_port, **slaves)
+
+ def test_active_backup_change_primary(self):
+ """
+ Test Case8: Mode 1(Active Backup) Change active slave, RX/TX test
+ """
+ bond_port = self.create_bonded_device(MODE_ACTIVE_BACKUP, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+ self.set_primary_for_bonding_device(bond_port, self.vf_ports[1])
+ time.sleep(5)
+
+ slaves = {}
+ slaves["active"] = [self.vf_ports[1], self.vf_ports[0], self.vf_ports[2]]
+ slaves["inactive"] = []
+ self.verify_active_backup_rx(self.vf_ports[3], bond_port, **slaves)
+ self.verify_active_backup_tx(self.vf_ports[3], bond_port, **slaves)
+
+ def test_active_backup_one_slave_down(self):
+ """
+ Test Case9: Mode 1(Active Backup) Link up/down active eth dev
+ """
+ bond_port = self.create_bonded_device(MODE_ACTIVE_BACKUP, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "down")
+ primary_port = int(self.get_bond_primary(bond_port))
+
+ try:
+ slaves = {}
+ active_slaves = [self.vf_ports[1], self.vf_ports[2]]
+ active_slaves.remove(primary_port)
+ slaves["active"] = [primary_port]
+ slaves["active"].extend(active_slaves)
+ slaves["inactive"] = [self.vf_ports[0]]
+ self.verify_active_backup_rx(self.vf_ports[3], bond_port, **slaves)
+ self.verify_active_backup_tx(self.vf_ports[3], bond_port, **slaves)
+ finally:
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "up")
+
+ def test_active_backup_all_slaves_down(self):
+ """
+ Test Case10: Mode 1(Active Backup) Bring all slave links down
+ """
+ bond_port = self.create_bonded_device(MODE_ACTIVE_BACKUP, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "down")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[1]), "down")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[2]), "down")
+
+ try:
+ slaves = {}
+ slaves["active"] = []
+ slaves["inactive"] = [
+ self.vf_ports[0],
+ self.vf_ports[1],
+ self.vf_ports[2],
+ ]
+ self.verify_active_backup_rx(self.vf_ports[3], bond_port, **slaves)
+ self.verify_active_backup_tx(self.vf_ports[3], bond_port, **slaves)
+ finally:
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "up")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[1]), "up")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[2]), "up")
+
+ def translate_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, dest_mac, src_mac):
+ """
+ Generate the hash value with the source and destination MAC.
+ """
+ dest_port_mac = self.translate_mac_str_into_int(dest_mac)
+ src_port_mac = self.translate_mac_str_into_int(src_mac)
+ src_xor_dest = dest_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, dest_ip, src_ip):
+ """
+ Generate the hash value with the source and destination IP.
+ """
+ dest_ip_int = self.translate_ip_str_into_int(dest_ip)
+ src_ip_int = self.translate_ip_str_into_int(src_ip)
+ return htonl(dest_ip_int ^ src_ip_int)
+
+ def udp_hash(self, dest_port, src_port):
+ """
+ Generate the hash value with the source and destination port.
+ """
+ return htons(dest_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'
+ *** slaves:
+ ******* 'active'=[]
+ ******* 'inactive'=[]
+ """
+ global S_MAC_IP_PORT
+ source = S_MAC_IP_PORT
+
+ global D_MAC_IP_PORT
+ dest_mac = D_MAC_IP_PORT[0]
+ dest_ip = D_MAC_IP_PORT[1]
+ dest_port = D_MAC_IP_PORT[2]
+
+ hash_values = []
+ if len(slaves["active"]) != 0:
+ for src_mac, src_ip, src_port in source:
+ if policy == "L2":
+ hash_value = self.mac_hash(dest_mac, src_mac)
+ elif policy == "L23":
+ hash_value = self.mac_hash(dest_mac, src_mac) ^ self.ipv4_hash(
+ dest_ip, src_ip
+ )
+ else:
+ hash_value = self.ipv4_hash(dest_ip, src_ip) ^ self.udp_hash(
+ dest_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_xor_rx(self, unbound_port, bond_port, **slaves):
+ """
+ Verify receiving the packets correctly in the XOR mode.
+ Parameters:
+ *** unbound_port: the unbonded port id
+ *** bond_port: the bonded device port id
+ *** slaves:
+ ******* 'active'=[]
+ ******* 'inactive'=[]
+ """
+ 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")
+ 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
+ *** slaves:
+ ******* 'active'=[]
+ ******* 'inactive'=[]
+ """
+ pkt_count = 100
+ pkt_now = {}
+
+ pkt_now, summary = self.send_customized_packet_to_unbound_port(
+ unbound_port,
+ bond_port,
+ policy,
+ vlan_tag=False,
+ pkt_count=pkt_count,
+ **slaves,
+ )
+
+ hash_values = []
+ hash_values = self.policy_and_slave_hash(policy, **slaves)
+
+ order_ports = self.get_bond_active_slaves(bond_port)
+ 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",
+ )
+
+ def test_xor_tx(self):
+ """
+ Test Case11: Mode 2(Balance XOR) TX Load Balance test
+ """
+ bond_port = self.create_bonded_device(MODE_XOR_BALANCE, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+
+ slaves = {}
+ slaves["active"] = [self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]]
+ slaves["inactive"] = []
+
+ self.verify_xor_tx(self.vf_ports[3], bond_port, "L2", False, **slaves)
+
+ def test_xor_tx_one_slave_down(self):
+ """
+ Test Case12: Mode 2(Balance XOR) TX Load Balance Link down
+ """
+ bond_port = self.create_bonded_device(MODE_XOR_BALANCE, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[2], self.vf_ports[1]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "down")
+
+ try:
+ slaves = {}
+ slaves["active"] = [self.vf_ports[1], self.vf_ports[2]]
+ slaves["inactive"] = [self.vf_ports[0]]
+
+ self.verify_xor_tx(self.vf_ports[3], bond_port, "L2", False, **slaves)
+ finally:
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "up")
+
+ def test_xor_tx_all_slaves_down(self):
+ """
+ Test Case13: Mode 2(Balance XOR) Bring all slave links down
+ """
+ bond_port = self.create_bonded_device(MODE_XOR_BALANCE, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "down")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[1]), "down")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[2]), "down")
+
+ try:
+ slaves = {}
+ slaves["active"] = []
+ slaves["inactive"] = [
+ self.vf_ports[0],
+ self.vf_ports[1],
+ self.vf_ports[2],
+ ]
+
+ self.verify_xor_tx(self.vf_ports[3], bond_port, "L2", False, **slaves)
+ finally:
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "up")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[1]), "up")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[2]), "up")
+
+ def vlan_strip_and_filter(self, action="off", *ports):
+ """
+ Open or shutdown the vlan strip and filter option of specified port.
+ """
+ for port_id in ports:
+ self.dut.send_expect(
+ "vlan set strip %s %d" % (action, port_id), "testpmd> "
+ )
+ self.dut.send_expect(
+ "vlan set filter %s %d" % (action, port_id), "testpmd> "
+ )
+
+ def test_xor_l34_forward(self):
+ """
+ Test Case14: Mode 2(Balance XOR) Layer 3+4 forwarding
+ """
+ bond_port = self.create_bonded_device(MODE_XOR_BALANCE, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.set_balance_policy_for_bonding_device(bond_port, "l34")
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+
+ slaves = {}
+ slaves["active"] = [self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]]
+ slaves["inactive"] = []
+
+ self.verify_xor_tx(self.vf_ports[3], bond_port, "L34", False, **slaves)
+ self.vlan_strip_and_filter(
+ "off",
+ self.vf_ports[0],
+ self.vf_ports[1],
+ self.vf_ports[2],
+ self.vf_ports[3],
+ bond_port,
+ )
+ self.verify_xor_tx(self.vf_ports[3], bond_port, "L34", True, **slaves)
+
+ def test_xor_rx(self):
+ """
+ Test Case15: Mode 2(Balance XOR) RX test
+ """
+ bond_port = self.create_bonded_device(MODE_XOR_BALANCE, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+
+ slaves = {}
+ slaves["active"] = [self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]]
+ slaves["inactive"] = []
+
+ self.verify_xor_rx(self.vf_ports[3], bond_port, **slaves)
+
+ def verify_broadcast_rx(self, unbound_port, bond_port, **slaves):
+ """
+ Verify that receiving packets correctly in the broadcast mode.
+ Parameters:
+ *** unbound_port: the unbonded port id
+ *** bond_port: the bonded device port id
+ *** slaves:
+ ******* 'active':[]
+ ******* 'inactive':[]
+ """
+ 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 RX packet not correct in mode 3"
+ )
+ for slave in slaves["inactive"]:
+ self.verify(pkt_now[slave][0] == 0, "Slave RX packet not correct in mode 3")
+ self.verify(
+ pkt_now[unbound_port][0] == pkt_count * len(slaves["active"]),
+ "Unbonded port TX packet not correct in mode 3",
+ )
+ self.verify(
+ pkt_now[bond_port][0] == pkt_count * len(slaves["active"]),
+ "Bonded device RX packet not correct in mode 3",
+ )
+
+ def verify_broadcast_tx(self, unbound_port, bond_port, **slaves):
+ """
+ Verify that transmitting packets correctly in the broadcast mode.
+ Parameters:
+ *** unbound_port: the unbonded port id
+ *** bond_port: the bonded device port id
+ *** slaves:
+ ******* 'active':[]
+ ******* 'inactive':[]
+ """
+ pkt_count = 100
+ pkt_now = {}
+
+ pkt_now, summary = self.send_default_packet_to_unbound_port(
+ unbound_port, bond_port, pkt_count=pkt_count, **slaves
+ )
+
+ for slave in slaves["active"]:
+ self.verify(
+ pkt_now[slave][0] == pkt_count, "Slave TX packet not correct in mode 3"
+ )
+ for slave in slaves["inactive"]:
+ self.verify(pkt_now[slave][0] == 0, "Slave TX packet not correct in mode 3")
+ self.verify(
+ pkt_now[unbound_port][0] == pkt_count,
+ "Unbonded port RX packet not correct in mode 3",
+ )
+ self.verify(
+ pkt_now[bond_port][0] == pkt_count * len(slaves["active"]),
+ "Bonded device TX packet not correct in mode 3",
+ )
+
+ def test_broadcast_rx_tx(self):
+ """
+ Test Case16: Mode 3(Broadcast) TX/RX Test
+ """
+ bond_port = self.create_bonded_device(MODE_BROADCAST, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+
+ slaves = {}
+ slaves["active"] = [self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]]
+ slaves["inactive"] = []
+
+ self.verify_broadcast_rx(self.vf_ports[3], bond_port, **slaves)
+ self.verify_broadcast_tx(self.vf_ports[3], bond_port, **slaves)
+
+ def test_broadcast_tx_one_slave_down(self):
+ """
+ Test Case17: Mode 3(Broadcast) Bring one slave link down
+ """
+ bond_port = self.create_bonded_device(MODE_BROADCAST, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "down")
+
+ try:
+ slaves = {}
+ slaves["active"] = [self.vf_ports[1], self.vf_ports[2]]
+ slaves["inactive"] = [self.vf_ports[0]]
+
+ self.verify_broadcast_tx(self.vf_ports[3], bond_port, **slaves)
+ finally:
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "up")
+
+ def test_broadcast_tx_all_slaves_down(self):
+ """
+ Test Case18: Mode 3(Broadcast) Bring all slave links down
+ """
+ bond_port = self.create_bonded_device(MODE_BROADCAST, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "down")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[1]), "down")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[2]), "down")
+
+ try:
+ slaves = {}
+ slaves["active"] = []
+ slaves["inactive"] = [
+ self.vf_ports[0],
+ self.vf_ports[1],
+ self.vf_ports[2],
+ ]
+
+ self.verify_broadcast_tx(self.vf_ports[3], bond_port, **slaves)
+ finally:
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "up")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[1]), "up")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[2]), "up")
+
+ def verify_tlb_rx(self, unbound_port, bond_port, **slaves):
+ """
+ Verify that receiving packets correctly in the mode 4.
+ Parameters:
+ *** unbound_port: the unbonded port id
+ *** bond_port: the bonded device port id
+ *** slaves:
+ ******* 'active':[]
+ ******* 'inactive':[]
+ """
+ pkt_count = 100
+ pkt_now = {}
+
+ slave_num = slaves["active"].__len__()
+ if slave_num != 0:
+ active_flag = 1
+ else:
+ active_flag = 0
+
+ pkt_now, summary = self.send_default_packet_to_slave(
+ unbound_port, bond_port, pkt_count=pkt_count, **slaves
+ )
+
+ self.verify(
+ pkt_now[unbound_port][0] == pkt_count * active_flag,
+ "Unbonded device has error TX packet in TLB",
+ )
+ self.verify(
+ pkt_now[bond_port][0] == pkt_count * slave_num,
+ "Bounded device has error RX packet in TLB",
+ )
+ for slave in slaves["inactive"]:
+ self.verify(
+ pkt_now[slave][0] == 0, "Inactive slave has error RX packet in TLB"
+ )
+ for slave in slaves["active"]:
+ self.verify(
+ pkt_now[slave][0] == pkt_count,
+ "Active slave has error RX packet in TLB",
+ )
+
+ def verify_tlb_tx(self, unbound_port, bond_port, **slaves):
+ """
+ Verify that transmitting packets correctly in the broadcast mode.
+ Parameters:
+ *** unbound_port: the unbonded port id
+ *** bond_port: the bonded device port id
+ *** slaves:
+ ******* 'active':[]
+ ******* 'inactive':[]
+ """
+ pkt_count = "MANY"
+
+ # send to unbonded device
+ pkt_now, summary = self.send_default_packet_to_unbound_port(
+ unbound_port, bond_port, pkt_count=pkt_count, **slaves
+ )
+
+ active_slaves = len(slaves["active"])
+ if active_slaves:
+ mean = float(summary) / float(active_slaves)
+ active_flag = 1
+ else:
+ active_flag = 0
+
+ for slave in slaves["active"]:
+ self.verify(
+ pkt_now[slave][0] > mean * 0.9 and pkt_now[slave][0] < mean * 1.1,
+ "Slave TX packet not correct in mode 5",
+ )
+ for slave in slaves["inactive"]:
+ self.verify(pkt_now[slave][0] == 0, "Slave TX packet not correct in mode 5")
+ self.verify(
+ pkt_now[unbound_port][0] == summary,
+ "Unbonded port RX packet not correct in TLB",
+ )
+ self.verify(
+ pkt_now[bond_port][0] == summary * active_flag,
+ "Bonded device TX packet not correct in TLB",
+ )
+
+ def test_tlb_basic(self):
+ """
+ Test Case19: Mode 5(TLB) Base Test
+ """
+ self.verify_bound_basic_opt(MODE_TLB_BALANCE)
+ self.verify_bound_mac_opt(MODE_TLB_BALANCE)
+ self.verify_bound_promisc_opt(MODE_TLB_BALANCE)
+
+ def test_tlb_rx_tx(self):
+ """
+ Test Case20: Mode 5(TLB) TX/RX test
+ """
+ bond_port = self.create_bonded_device(MODE_TLB_BALANCE, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+
+ slaves = {}
+ slaves["active"] = [self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]]
+ slaves["inactive"] = []
+
+ self.verify_tlb_rx(self.vf_ports[3], bond_port, **slaves)
+ self.verify_tlb_tx(self.vf_ports[3], bond_port, **slaves)
+
+ def test_tlb_one_slave_dwon(self):
+ """
+ Test Case21: Mode 5(TLB) Bring one slave link down
+ """
+ bond_port = self.create_bonded_device(MODE_TLB_BALANCE, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "down")
+
+ try:
+ slaves = {}
+ slaves["active"] = [self.vf_ports[1], self.vf_ports[2]]
+ slaves["inactive"] = [self.vf_ports[0]]
+
+ self.verify_tlb_rx(self.vf_ports[3], bond_port, **slaves)
+ self.verify_tlb_tx(self.vf_ports[3], bond_port, **slaves)
+ finally:
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "up")
+
+ def test_tlb_all_slaves_down(self):
+ """
+ Test Case22: Mode 5(TLB) Bring all slave links down
+ """
+ bond_port = self.create_bonded_device(MODE_TLB_BALANCE, SOCKET_0)
+ self.add_slave_to_bonding_device(
+ bond_port, False, self.vf_ports[0], self.vf_ports[1], self.vf_ports[2]
+ )
+ self.dut.send_expect(
+ "set portlist %d,%d" % (self.vf_ports[3], bond_port), "testpmd> "
+ )
+ self.start_port("all")
+ self.dut.send_expect("start", "testpmd> ")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "down")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[1]), "down")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[2]), "down")
+
+ try:
+ slaves = {}
+ slaves["active"] = []
+ slaves["inactive"] = [
+ self.vf_ports[0],
+ self.vf_ports[1],
+ self.vf_ports[2],
+ ]
+
+ self.verify_tlb_rx(self.vf_ports[3], bond_port, **slaves)
+ self.verify_tlb_tx(self.vf_ports[3], bond_port, **slaves)
+ finally:
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[0]), "up")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[1]), "up")
+ self.admin_tester_port(self.tester.get_local_port(self.dut_ports[2]), "up")
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ """
+ self.pmdout.quit()
+ if self.running_case in ["test_bound_promisc_opt", "test_tlb_basic"]:
+ self.dut.send_expect(
+ "ip link set %s vf 0 trust off" % (self.dport_ifaces0), "# "
+ )
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ self.dut.kill_all()
+ self.destroy_iavf()
+ for port in self.dut_ports:
+ tester_port = self.tester.get_local_port(port)
+ tport_iface = self.tester.get_interface(tester_port)
+ self.tester.send_expect(
+ "ethtool --set-priv-flags %s %s %s"
+ % (tport_iface, self.flag, self.default_stats),
+ "# ",
+ )
--
2.25.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [dts] [PATCH V1 3/7] tests/vf_pmd_bonded_8023ad: add case to test vf bonding
2023-01-05 10:40 [dts] [PATCH V1 0/7] add cases to test vf bonding Song Jiale
2023-01-05 10:40 ` [dts] [PATCH V1 1/7] tests/vf_pmd_bonded: add case " Song Jiale
2023-01-05 10:40 ` [dts] [PATCH V1 2/7] test_plans/vf_pmd_bonded: " Song Jiale
@ 2023-01-05 10:40 ` Song Jiale
2023-01-05 10:40 ` [dts] [PATCH V1 4/7] test_plans/vf_pmd_bonded_8023ad: add cases " Song Jiale
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Song Jiale @ 2023-01-05 10:40 UTC (permalink / raw)
To: dts; +Cc: Song Jiale
add case to test vf bonding.
Signed-off-by: Song Jiale <songx.jiale@intel.com>
---
tests/TestSuite_vf_pmd_bonded_8023ad.py | 650 ++++++++++++++++++++++++
1 file changed, 650 insertions(+)
create mode 100644 tests/TestSuite_vf_pmd_bonded_8023ad.py
diff --git a/tests/TestSuite_vf_pmd_bonded_8023ad.py b/tests/TestSuite_vf_pmd_bonded_8023ad.py
new file mode 100644
index 00000000..5c6cda99
--- /dev/null
+++ b/tests/TestSuite_vf_pmd_bonded_8023ad.py
@@ -0,0 +1,650 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 23.03 Intel Corporation
+#
+
+import time
+import traceback
+
+# import bonding lib(common methods for pmd bonding command)
+import tests.bonding as bonding
+from framework.exception import VerifyFailure
+from framework.test_case import TestCase
+
+from .bonding import FRAME_SIZE_64, MODE_LACP
+
+
+######################
+# bonding 802.3ad mode
+######################
+class TestBonding8023AD(TestCase):
+ AGG_MODES = ["bandwidth", "stable", "count"]
+ DEDICATED_QUEUES = ["disable", "enable"]
+
+ #
+ # On dut, dpdk bonding
+ #
+
+ 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.bond_inst.d_console(cmd)
+ cur_mode = self.bond_inst.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 802.3ad mode aggregator Mode
+ """
+ cur_mode = self.bond_inst.get_bonding_info(bond_port, "agg_mode")
+ return cur_mode
+
+ def set_8023ad_dedicated_queues(self, bond_port, status="disable"):
+ """
+ set 802.11AD dedicated_queues mode(enable|disable)
+ """
+ cmds = [
+ [
+ "set bonding lacp dedicated_queues %s %s" % (bond_port, status),
+ ["", "port %s failed" % bond_port, False],
+ 2,
+ ],
+ ]
+ out = self.bond_inst.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))
+
+ def set_special_command(self, bond_port):
+ cmds = [
+ "set bonding lacp dedicated_queues {} enable".format(bond_port),
+ "set allmulti 0 on",
+ "set allmulti 1 on",
+ "set allmulti {} on".format(bond_port),
+ "set portlist {}".format(bond_port),
+ ]
+ [self.bond_inst.d_console([cmd, "testpmd>", 15]) for cmd in cmds]
+
+ def set_8023ad_bonded(self, slaves, bond_mode, ignore=True):
+ """set 802.3ad bonded mode for the specified bonding mode"""
+ specified_socket = self.dut.get_numa_id(slaves[0])
+ # create bonded device, add slaves in it
+ bond_port = self.bond_inst.create_bonded_device(bond_mode, specified_socket)
+ if not ignore:
+ # 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.bond_inst.add_slave(bond_port, False, "", *slaves)
+ # set special command
+ self.set_special_command(bond_port)
+ return bond_port
+
+ def set_8023ad_bonded2(self, slaves, bond_mode, ignore=True):
+ """set 802.3ad bonded mode for the specified bonding mode"""
+ specified_socket = self.dut.get_numa_id(slaves[0])
+ # create bonded device, add slaves in it
+ bond_port = self.bond_inst.create_bonded_device(bond_mode, specified_socket)
+ if not ignore:
+ # 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.bond_inst.add_slave(bond_port, False, "", *slaves)
+ return bond_port
+
+ def get_pci_link(self, slaves):
+ """get slaves ports pci address"""
+ slaves_pci = []
+ for port_id in slaves:
+ slaves_pci.append(self.dut.ports_info[port_id]["pci"])
+ if not slaves_pci:
+ msg = "can't find tx_port pci"
+ self.logger.error(msg)
+ raise VerifyFailure(msg)
+ return slaves_pci
+
+ def set_bond_port_ready(self, tx_port, bond_port):
+ cmd = "set portlist {0},{1}".format(tx_port, bond_port)
+ self.bond_inst.d_console(cmd)
+ # for port link up is slow and unstable,
+ # every port should start one by one
+ cmds = []
+ port_num = len(self.sriov_vfs_port)
+ start_fmt = "port start {0}".format
+ for cnt in range(port_num):
+ cmds.append([start_fmt(cnt), "", 5])
+ self.bond_inst.d_console(cmds)
+ time.sleep(10)
+ self.bond_inst.d_console([start_fmt(self.bond_port), "", 15])
+ time.sleep(5)
+ self.bond_inst.d_console(["start", "", 10])
+ self.verify(
+ self.bond_inst.testpmd.wait_link_status_up("all"),
+ "Failed to set bond port ready!!!",
+ )
+
+ 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 when
+ # testpmd linking with switch equipment
+ cmds = ["port stop all", "", 15]
+ self.bond_inst.d_console(cmds)
+ time.sleep(2)
+ cmds = ["port start all", "", 10]
+ self.bond_inst.d_console(cmds)
+ self.verify(
+ self.bond_inst.testpmd.wait_link_status_up("all"),
+ "run_8023ad_pre: Failed to start all port",
+ )
+ return bond_port
+
+ def bonding_8023ad_check_macs_without_slaves(self, bond_port):
+ query_type = "mac"
+ bond_port_mac = self.bond_inst.get_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 mac"""
+ query_type = "mac"
+ bond_port_mac = self.bond_inst.get_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.bond_inst.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 mac"
+ msg = fmt.format(bond_port_mac)
+ # it is not supported by dpdk, but supported by linux normal
+ # bonding/802.3ad 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.bond_inst.remove_slaves(bond_port, False, *[remove_slave])
+ self.bonding_8023ad_check_macs(cur_slaves, bond_port)
+
+ def check_bonded_device_start(self, bond_port):
+ cmds = [
+ ["port stop all", "", 15],
+ ["port start %s" % bond_port, "", 10],
+ ["start", [" ", "core dump", False]],
+ ]
+ self.bond_inst.d_console(cmds)
+ time.sleep(2)
+
+ def stop_bonded_device(self, bond_port):
+ cmds = [
+ ["stop", "", 10],
+ ["port stop %s" % bond_port, "", 10],
+ ]
+ self.bond_inst.d_console(cmds)
+ time.sleep(2)
+
+ def check_bonded_device_up_down(self, bond_port):
+ # stop bonded device
+ cmd = "port stop {0}".format(bond_port)
+ self.bond_inst.d_console(cmd)
+ status = self.bond_inst.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 bonded device
+ cmds = ["port start {0}".format(bond_port), "", 10]
+ self.bond_inst.d_console(cmds)
+ self.verify(
+ self.bond_inst.testpmd.wait_link_status_up("all", timeout=30),
+ "bond port {0} fail to set up".format(bond_port),
+ )
+
+ def check_bonded_device_promisc_mode(self, slaves, bond_port):
+ # disable bonded device promiscuous mode
+ cmd = "set promisc {0} off".format(bond_port)
+ self.bond_inst.d_console(cmd)
+ time.sleep(2)
+ status = self.bond_inst.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)
+ self.bond_inst.d_console("start")
+ time.sleep(2)
+ # check slave promiscuous mode
+ for port_id in slaves:
+ status = self.bond_inst.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.warning(msg)
+ # dpdk developer hasn't completed this function as linux
+ # document description about `Promiscuous mode`, ignore it here
+ # temporarily
+ # raise VerifyFailure(msg)
+ else:
+ fmt = "slave port {0} promiscuous mode is 'disabled' too"
+ msg = fmt.format(port_id)
+ self.logger.info(msg)
+ # enable bonded device promiscuous mode
+ cmd = "set promisc {0} on".format(bond_port)
+ self.bond_inst.d_console(cmd)
+ time.sleep(3)
+ status = self.bond_inst.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 mode
+ for port_id in slaves:
+ status = self.bond_inst.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.warning(msg)
+ # dpdk developer hasn't completed this function as linux
+ # document description about `Promiscuous mode`, ignore it here
+ # temporarily
+ # raise VerifyFailure(msg)
+ else:
+ fmt = "slave port {0} promiscuous mode is 'enabled' too"
+ msg = fmt.format(port_id)
+ self.logger.info(msg)
+
+ 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.bond_inst.start_testpmd(self.eal_param)
+ 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 == default_agg_mode:
+ fmt = "link bonding mode 4 (802.3ad) " "current agg mode is {0}"
+ msg = fmt.format(mode)
+ self.logger.info(msg)
+ continue
+ cmds = [["port stop all", "", 15], ["port start all", "", 15]]
+ self.bond_inst.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.bond_inst.close_testpmd()
+ time.sleep(2)
+
+ if check_results:
+ for result in check_results:
+ self.logger.error(result)
+ raise VerifyFailure("check_8023ad_agg_modes is failed")
+
+ def check_8023ad_dedicated_queues(self, slaves, bond_mode):
+ """check 802.3ad dedicated queues"""
+ check_results = []
+ default_slow_queue = "unknown"
+ for mode in self.DEDICATED_QUEUES:
+ try:
+ self.bond_inst.start_testpmd(self.eal_param)
+ bond_port = self.set_8023ad_bonded2(slaves, bond_mode)
+ self.set_8023ad_dedicated_queues(bond_port, mode)
+ except Exception as e:
+ check_results.append(e)
+ print(traceback.format_exc())
+ finally:
+ self.bond_inst.close_testpmd()
+ time.sleep(2)
+
+ if check_results:
+ for result in check_results:
+ self.logger.error(result)
+ raise VerifyFailure("check_8023ad_dedicated_queues is failed")
+
+ def get_commandline_options(self, agg_mode):
+ # get bonding port configuration
+ slave_pcis = self.vfs_pci
+ # create commandline option format
+ 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])
+ # command line option
+ mode = str(MODE_LACP)
+ option = vdev_format.format(agg_mode)
+ vdev_option = " --vdev '{0}'".format(option)
+ # 802.3ad bond port only create one, it must be the max port number
+ bond_port = len(self.sriov_vfs_port)
+ return bond_port, vdev_option
+
+ def run_test_pre(self, agg_mode):
+ # get bonding port configuration
+ bond_port, vdev_option = self.get_commandline_options(agg_mode)
+ self.bond_port = bond_port
+ # boot up testpmd
+ eal_param = self.eal_param + vdev_option
+ self.bond_inst.start_testpmd(eal_option=eal_param)
+ cur_slaves, cur_agg_mode = self.bond_inst.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)
+ self.logger.warning(msg)
+ # get forwarding port
+ for port_id in range(len(self.sriov_vfs_port)):
+ # select a non-slave port as forwarding port to do transmitting
+ if str(port_id) not in cur_slaves:
+ tx_port_id = port_id
+ break
+ else:
+ tx_port_id = bond_port
+ # enable dedicated queue
+ self.set_8023ad_dedicated_queues(bond_port, "enable")
+ 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_dpdk_functional_pre(self):
+ mode = MODE_LACP
+ slaves = self.vf_ports[:]
+ self.bond_inst.start_testpmd(self.eal_param)
+ bond_port = self.run_8023ad_pre(slaves, mode)
+ return slaves, bond_port
+
+ def run_dpdk_functional_post(self):
+ self.bond_inst.close_testpmd()
+
+ 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.bond_inst.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 sorted(slaves) != sorted(_cur_slaves):
+ 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 cur_active_slaves:
+ check_active_slaves = [int(id) for id in cur_active_slaves]
+ if sorted(slaves) != sorted(check_active_slaves):
+ 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)
+ # check status after ports start
+ self.bond_inst.start_ports()
+ # set bonded device to active status
+ cur_active_slaves = [
+ int(id)
+ for id in self.bond_inst.get_bonding_info(bond_port, "active_slaves")
+ ]
+ if not cur_active_slaves or sorted(slaves) != sorted(cur_active_slaves):
+ 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)
+ return msgs
+
+ #
+ # 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 = 2
+ self.dport_info0 = self.dut.ports_info[self.dut_ports[0]]
+ self.dport_ifaces = self.dport_info0["intf"]
+ self.verify(len(self.dut_ports) >= required_link, "Insufficient ports")
+ # Create a vf for each pf and get all vf info,
+ self.dut.restore_interfaces()
+ self.create_vfs(pfs_id=self.dut_ports[0:2], vf_num=1)
+ self.vf_ports = list(range(len(self.vfs_pci)))
+ self.eal_param = str()
+ for pci in self.vfs_pci:
+ self.eal_param += "-a {} ".format(pci)
+ # ------------------------------------------------------------
+ # 802.3ad related
+ self.bond_port = None
+ self.bond_slave = self.dut_ports[0]
+ # ----------------------------------------------------------------
+ # initialize bonding common methods name
+ config = {
+ "parent": self,
+ "pkt_name": "udp",
+ "pkt_size": FRAME_SIZE_64,
+ "src_mac": "52:00:00:00:00:03",
+ "src_ip": "10.239.129.65",
+ "src_port": 61,
+ "dst_ip": "10.239.129.88",
+ "dst_port": 53,
+ }
+ self.bond_inst = bonding.PmdBonding(**config)
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ pass
+
+ def create_vfs(self, pfs_id, vf_num):
+ self.sriov_vfs_port = []
+ self.vfs_pci = []
+ self.dut.bind_interfaces_linux(self.kdriver)
+ pfs_id = pfs_id if isinstance(pfs_id, list) else [pfs_id]
+ for pf_id in pfs_id:
+ self.dut.generate_sriov_vfs_by_port(pf_id, vf_num)
+ self.sriov_vfs_port += self.dut.ports_info[self.dut_ports[pf_id]][
+ "vfs_port"
+ ]
+ for vf in self.sriov_vfs_port:
+ self.vfs_pci.append(vf.pci)
+ try:
+ for port in self.sriov_vfs_port:
+ port.bind_driver(self.drivername)
+ except Exception as e:
+ self.destroy_iavf()
+ raise Exception(e)
+
+ def destroy_iavf(self):
+ self.dut.destroy_all_sriov_vfs()
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ """
+ try:
+ self.bond_inst.close_testpmd()
+ except Exception:
+ self.dut.kill_all()
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ self.destroy_iavf()
+
+ def test_basic_behav_startStop(self):
+ """
+ Test Case : basic behavior start/stop
+ """
+ msg = ""
+ slaves, bond_port = self.run_dpdk_functional_pre()
+ try:
+ for _ in range(10):
+ self.check_bonded_device_start(bond_port)
+ self.stop_bonded_device(bond_port)
+ except Exception as e:
+ print(traceback.format_exc())
+ msg = "bonding 8023ad check start/stop failed"
+ self.run_dpdk_functional_post()
+ if msg:
+ raise VerifyFailure(msg)
+
+ def test_basic_behav_mac(self):
+ """
+ Test Case : basic behavior mac
+ """
+ msg = ""
+ slaves, bond_port = self.run_dpdk_functional_pre()
+ 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 mac failed"
+ self.run_dpdk_functional_post()
+ if msg:
+ raise VerifyFailure(msg)
+
+ def test_basic_behav_upDown(self):
+ """
+ Test Case : basic behavior link up/down
+ """
+ msg = ""
+ slaves, bond_port = self.run_dpdk_functional_pre()
+ try:
+ self.check_bonded_device_up_down(bond_port)
+ except Exception as e:
+ msg = "bonding 8023ad check link up/down failed"
+ self.run_dpdk_functional_post()
+ if msg:
+ raise VerifyFailure(msg)
+
+ def test_basic_behav_promisc_mode(self):
+ """
+ Test Case : basic behavior promiscuous mode
+ """
+ msg = ""
+ slaves, bond_port = self.run_dpdk_functional_pre()
+ try:
+ self.check_bonded_device_promisc_mode(slaves, bond_port)
+ except Exception as e:
+ msg = "bonding 8023ad check promisc mode failed"
+ self.run_dpdk_functional_post()
+ if msg:
+ raise VerifyFailure(msg)
+
+ def test_command_line_option(self):
+ """
+ Test Case : command line option
+ """
+ agg_modes_msgs = []
+ for agg_mode in self.AGG_MODES:
+ bond_port, cur_slaves, tx_port_id = self.run_test_pre(agg_mode)
+ msgs = self.check_cmd_line_option_status(agg_mode, bond_port, cur_slaves)
+ if msgs:
+ agg_modes_msgs.append((msgs, agg_mode))
+ self.bond_inst.close_testpmd()
+ if agg_modes_msgs:
+ msgs = ""
+ for msg, agg_mode in agg_modes_msgs:
+ self.logger.warning(msg)
+ msgs += "fail to config from command line at {0} ".format(agg_mode)
+ raise VerifyFailure(msgs)
+
+ def test_basic_behav_agg_mode(self):
+ """
+ Test Case : basic behavior agg mode
+ """
+ mode = MODE_LACP
+ self.check_8023ad_agg_modes(self.vf_ports, mode)
+
+ def test_basic_dedicated_queues(self):
+ """
+ Test Case : basic behavior dedicated queues
+ """
+ mode = MODE_LACP
+ self.check_8023ad_dedicated_queues(self.vf_ports, mode)
--
2.25.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [dts] [PATCH V1 5/7] tests/vf_pmd_stacked_bonded: add cases to test vf bonding
2023-01-05 10:40 [dts] [PATCH V1 0/7] add cases to test vf bonding Song Jiale
` (3 preceding siblings ...)
2023-01-05 10:40 ` [dts] [PATCH V1 4/7] test_plans/vf_pmd_bonded_8023ad: add cases " Song Jiale
@ 2023-01-05 10:40 ` Song Jiale
2023-01-05 10:40 ` [dts] [PATCH V1 6/7] test_plans/vf_pmd_stacked_bonded: " Song Jiale
2023-01-05 10:40 ` [dts] [PATCH V1 7/7] test_plans/index: add 3 suite Song Jiale
6 siblings, 0 replies; 9+ messages in thread
From: Song Jiale @ 2023-01-05 10:40 UTC (permalink / raw)
To: dts; +Cc: Song Jiale
add case to test vf bonding.
Signed-off-by: Song Jiale <songx.jiale@intel.com>
---
tests/TestSuite_vf_pmd_stacked_bonded.py | 614 +++++++++++++++++++++++
1 file changed, 614 insertions(+)
create mode 100644 tests/TestSuite_vf_pmd_stacked_bonded.py
diff --git a/tests/TestSuite_vf_pmd_stacked_bonded.py b/tests/TestSuite_vf_pmd_stacked_bonded.py
new file mode 100644
index 00000000..e8556684
--- /dev/null
+++ b/tests/TestSuite_vf_pmd_stacked_bonded.py
@@ -0,0 +1,614 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 23.03 Intel Corporation
+#
+
+import time
+import traceback
+
+# import dts/framework libs
+import framework.utils as utils
+
+# import bonding lib
+import tests.bonding as bonding
+from framework.exception import VerifyFailure
+from framework.test_case import TestCase
+
+from .bonding import (
+ FRAME_SIZE_64,
+ MODE_ACTIVE_BACKUP,
+ MODE_ALB_BALANCE,
+ MODE_BROADCAST,
+ MODE_LACP,
+ MODE_ROUND_ROBIN,
+ MODE_TLB_BALANCE,
+ MODE_XOR_BALANCE,
+)
+
+
+class TestBondingStacked(TestCase):
+
+ #
+ # On dut, dpdk bonding
+ #
+ def check_bonded_device_queue_config(self, *devices):
+ """
+ check if master bonded device/slave device queue configuration
+ is the same.
+ """
+ # get master bonded device queue configuration
+ master = self.bond_inst.get_port_info(devices[0], "queue_config")
+ # get slave device queue configuration
+ for port_id in devices[1:]:
+ config = self.bond_inst.get_port_info(port_id, "queue_config")
+ if config == master:
+ continue
+ msg = (
+ "slave bonded port [{0}] is " "different to top bonded port [{1}]"
+ ).format(port_id, devices[0])
+ raise VerifyFailure("bonded device queue config:: " + msg)
+
+ def set_stacked_bonded(self, slaveGrpOne, slaveGrpTwo, bond_mode, ignore=False):
+ """
+ set stacked bonded mode for a custom bonding mode
+ """
+ inst = self.bond_inst
+ socket_id = self.dut.get_numa_id(self.bond_slave)
+ # create first bonded device 1, add slaves in it
+ bond_port_1 = inst.create_bonded_device(bond_mode, socket_id)
+ inst.add_slave(bond_port_1, False, "", *slaveGrpOne)
+ # create second bonded device 2, add slaves in it
+ bond_port_2 = inst.create_bonded_device(bond_mode, socket_id)
+ inst.add_slave(bond_port_2, False, "", *slaveGrpTwo)
+ # create master bonded device 3, which is the top bonded device
+ master_bond_port = inst.create_bonded_device(bond_mode, socket_id)
+ # add bond bonded device 1 to bonded device 3
+ # check bonding config status
+ inst.add_slave(master_bond_port, False, "", *[bond_port_1])
+ # add bonded device 2 to bonded device 3
+ # check bonding config status
+ inst.add_slave(master_bond_port, False, "", *[bond_port_2])
+ # check if master bonding/each slaves queue configuration is the same.
+ if not ignore:
+ self.check_bonded_device_queue_config(
+ *[master_bond_port, bond_port_1, bond_port_2]
+ )
+
+ return [bond_port_1, bond_port_2, master_bond_port]
+
+ def set_third_stacked_bonded(self, bond_port, bond_mode):
+ """
+ set third level stacked bonded to check if stacked level can be set
+ more than 2
+ """
+ inst = self.bond_inst
+ socket_id = self.dut.get_numa_id(self.bond_slave)
+ third_bond_port = inst.create_bonded_device(bond_mode, socket_id)
+ inst.add_slave(third_bond_port, False, "", *[bond_port])
+
+ def duplicate_add_stacked_bonded(self, bond_port_1, bond_port_2, master_bond_port):
+ """
+ check if adding duplicate stacked bonded device is forbidden
+ """
+ inst = self.bond_inst
+ # check exception process
+ expected_str = "Slave device is already a slave of a bonded device"
+ # add bonded device 1 to bonded device 3
+ # check bonding config status
+ inst.add_slave(master_bond_port, False, expected_str, *[bond_port_1])
+ # add bonded device 2 to bonded device 3
+ # check bonding config status
+ inst.add_slave(master_bond_port, False, expected_str, *[bond_port_2])
+
+ def preset_stacked_bonded(self, slaveGrpOne, slaveGrpTwo, bond_mode):
+ bond_port_1, bond_port_2, master_bond_port = self.set_stacked_bonded(
+ slaveGrpOne, slaveGrpTwo, bond_mode, ignore=True
+ )
+ portList = [
+ slaveGrpOne[0],
+ slaveGrpTwo[0],
+ bond_port_1,
+ bond_port_2,
+ master_bond_port,
+ ]
+ cmds = [
+ ["port stop all", ""],
+ ["set portlist " + ",".join([str(port) for port in portList]), ""],
+ # start top level bond port only, and let it propagate the start
+ # action to slave bond ports and its the real nics.
+ ["port start {}".format(master_bond_port), " ", 15],
+ ]
+ self.bond_inst.d_console(cmds)
+ # blank space command is used to skip LSC event to avoid core dumped issue
+ time.sleep(5)
+ cmds = [[" ", ""], ["start", ""]]
+ self.bond_inst.d_console(cmds)
+ time.sleep(5)
+
+ return bond_port_1, bond_port_2, master_bond_port
+
+ def send_packets_by_scapy(self, **kwargs):
+ tx_iface = kwargs.get("port topo")[0]
+ # set interface ready to send packet
+ self.dut1 = self.dut.new_session()
+ cmd = "ifconfig {0} up".format(tx_iface)
+ self.dut1.send_expect(cmd, "# ", 30)
+ send_pkts = kwargs.get("stream")
+ # stream config
+ stream_configs = kwargs.get("traffic configs")
+ count = stream_configs.get("count")
+ interval = stream_configs.get("interval", 0.01)
+ # run traffic
+ self.dut1.send_expect("scapy", ">>> ", 30)
+ cmd = (
+ "sendp("
+ + send_pkts[0].command()
+ + f',iface="{tx_iface}",count={count},inter={interval},verbose=False)'
+ )
+ self.dut1.send_expect(cmd, ">>> ")
+ self.dut1.send_expect("quit()", "# ")
+ self.dut.close_session(self.dut1)
+
+ #
+ # packet transmission
+ #
+ def traffic(self, traffic_config, ports, tport_is_up=True):
+ # get ports statistics before sending packets
+ stats_pre = self.bond_inst.get_all_stats(ports)
+ # send packets
+ if tport_is_up:
+ self.bond_inst.send_packet(traffic_config)
+ else:
+ self.send_packets_by_scapy(**traffic_config)
+ # get ports statistics after sending packets
+ stats_post = self.bond_inst.get_all_stats(ports)
+ # calculate ports statistics result
+ for port_id in ports:
+ stats_post[port_id]["RX-packets"] -= stats_pre[port_id]["RX-packets"]
+ stats_post[port_id]["TX-packets"] -= stats_pre[port_id]["TX-packets"]
+
+ return stats_post
+
+ def config_port_traffic(self, tx_port, rx_port, total_pkt):
+ """set traffic configuration"""
+ traffic_config = {
+ "port topo": [tx_port, rx_port],
+ "stream": self.bond_inst.set_stream_to_slave_port(rx_port),
+ "traffic configs": {
+ "count": total_pkt,
+ },
+ }
+
+ return traffic_config
+
+ def active_slave_rx(self, slave, bond_port, mode):
+ msg = "send packet to active slave port <{0}>".format(slave)
+ self.logger.info(msg)
+ if slave in [0, 1]:
+ tx_intf = self.tester.get_interface(
+ self.tester.get_local_port(self.dut_ports[0])
+ )
+ elif slave in [2, 3]:
+ tx_intf = self.tester.get_interface(
+ self.tester.get_local_port(self.dut_ports[1])
+ )
+ else:
+ self.verify(False, "Error slave port <{0}>".format(slave))
+ # get traffic config
+ traffic_config = self.config_port_traffic(tx_intf, slave, self.total_pkt)
+ # select ports for statistics
+ ports = [slave, bond_port]
+ # run traffic
+ stats = self.traffic(traffic_config, ports)
+ # check slave statistics
+ msg = "port <{0}> Data not received by port <{1}>".format(tx_intf, slave)
+ # here using `>=` to ignore some miscellaneous packets, e.g. lldp
+ self.verify(stats[slave]["RX-packets"] >= self.total_pkt, msg)
+ msg = "tester port {0} <----> VF port {1} is ok".format(tx_intf, slave)
+ self.logger.info(msg)
+ # check bond port statistics
+ # here using `>=` to ignore some miscellaneous packets, e.g. lldp
+ self.verify(
+ stats[slave]["RX-packets"] >= self.total_pkt,
+ "Bond port have error RX packet in XOR",
+ )
+
+ def inactive_slave_rx(self, slave, bond_port, mode):
+ msg = "send packet to inactive slave port <{0}>".format(slave)
+ self.logger.info(msg)
+ tx_intf = self.dport_ifaces
+ # get traffic config
+ traffic_config = self.config_port_traffic(tx_intf, slave, self.total_pkt)
+ # select ports for statistics
+ ports = [slave, bond_port]
+ # run traffic
+ stats = self.traffic(traffic_config, ports, tport_is_up=False)
+ # check slave statistics
+ msg = ("port <{0}> Data received by port <{1}>, " "but should not.").format(
+ tx_intf, slave
+ )
+ self.verify(stats[slave]["RX-packets"] == 0, msg)
+ msg = "tester port {0} <-| |-> VF port {1} is blocked".format(tx_intf, slave)
+ self.logger.info(msg)
+ # check bond port statistics
+ self.verify(
+ stats[slave]["RX-packets"] == 0,
+ "Bond port have error RX packet in {0}".format(mode),
+ )
+
+ def set_port_status(self, vfs_id, tport_inface, status):
+ # stop slave link by force
+ cmd = "ifconfig {0} {1}".format(tport_inface, status)
+ self.tester.send_expect(cmd, "# ")
+ time.sleep(3)
+ vfs_id = vfs_id if isinstance(vfs_id, list) else [vfs_id]
+ for vf in vfs_id:
+ cur_status = self.bond_inst.get_port_info(vf, "link_status")
+ self.logger.info("port {0} is [{1}]".format(vf, cur_status))
+ self.verify(cur_status == status, "expected status is [{0}]".format(status))
+
+ def check_traffic_with_one_slave_down(self, mode):
+ """
+ Verify that transmitting packets correctly when set one slave of
+ the bonded device link down.
+ """
+ results = []
+ # -------------------------------
+ # boot up testpmd
+ self.bond_inst.start_testpmd(self.eal_param)
+ self.bond_inst.d_console("set fwd mac")
+ try:
+ slaves = {"active": [], "inactive": []}
+ # -------------------------------
+ # preset stacked bonded device
+ slaveGrpOne = self.slaveGrpOne
+ slaveGrpTwo = self.slaveGrpTwo
+ bond_port_1, bond_port_2, master_bond_port = self.preset_stacked_bonded(
+ slaveGrpOne, slaveGrpTwo, mode
+ )
+ # ---------------------------------------------------
+ # set one slave of first bonded device and second bonded device link down
+ bond1_primary_slave = slaveGrpOne[0]
+ bond2_primary_slave = slaveGrpTwo[0]
+ # self.bond_inst.set_dut_port_status(primary_slave, "down")
+ self.set_port_status(
+ vfs_id=[0, 1], tport_inface=self.tport_iface0, status="down"
+ )
+ slaves["inactive"].append(bond1_primary_slave)
+ # get slave status
+ primary_port, active_slaves = self.bond_inst.get_active_slaves(bond_port_1)
+ slaves["active"].extend(active_slaves)
+ if bond1_primary_slave in slaves["active"]:
+ msg = "{0} should not be in active slaves list".format(
+ bond1_primary_slave
+ )
+ raise Exception(msg)
+ slaves["inactive"].append(bond2_primary_slave)
+ # check active slaves
+ primary_port_2, active_slaves_2 = self.bond_inst.get_active_slaves(
+ bond_port_2
+ )
+ slaves["active"].extend(active_slaves_2)
+ if bond2_primary_slave in slaves["active"]:
+ msg = "{0} should not be in active slaves list".format(
+ bond2_primary_slave
+ )
+ raise Exception(msg)
+ # traffic testing
+ # active slave traffic testing
+ for slave in slaves["active"]:
+ self.active_slave_rx(slave, master_bond_port, mode)
+ # inactive slave traffic testing
+ for slave in slaves["inactive"]:
+ self.inactive_slave_rx(slave, master_bond_port, mode)
+ except Exception as e:
+ results.append(e)
+ self.logger.error(traceback.format_exc())
+ finally:
+ self.bond_inst.close_testpmd()
+
+ return results
+
+ def check_traffic(self, mode):
+ """normal traffic with all slaves are under active status.
+ verify the RX packets are all correct with stacked bonded device.
+ bonded device's statistics should be the sum of slaves statistics.
+ """
+ self.bond_inst.start_testpmd(self.eal_param)
+ self.bond_inst.d_console("set fwd mac")
+ slaveGrpOne = self.slaveGrpOne
+ slaveGrpTwo = self.slaveGrpTwo
+ bond_port_1, bond_port_2, master_bond_port = self.preset_stacked_bonded(
+ slaveGrpOne, slaveGrpTwo, mode
+ )
+ results = []
+ # check first bonded device
+ try:
+ self.logger.info("check first bonded device")
+ # active slave traffic testing
+ for slave in slaveGrpOne:
+ self.active_slave_rx(slave, bond_port_1, mode)
+ except Exception as e:
+ results.append(e)
+ # check second bonded device
+ try:
+ self.logger.info("check second bonded device")
+ # active slave traffic testing
+ for slave in slaveGrpOne:
+ self.active_slave_rx(slave, bond_port_2, mode)
+ except Exception as e:
+ results.append(e)
+
+ # check top bonded device
+ try:
+ self.logger.info("check master bonded device")
+ # active slave traffic testing
+ for slave in slaveGrpOne + slaveGrpTwo:
+ self.active_slave_rx(slave, master_bond_port, mode)
+ except Exception as e:
+ results.append(e)
+
+ self.bond_inst.close_testpmd()
+
+ return results
+
+ def backup_check_traffic(self):
+ mode = MODE_ACTIVE_BACKUP
+ msg = "begin checking bonding backup(stacked) mode transmission"
+ self.logger.info(msg)
+ results = self.check_traffic(mode)
+ if results:
+ for item in results:
+ self.logger.error(item)
+ raise VerifyFailure("backup(stacked) mode: rx failed")
+
+ def backup_check_traffic_with_slave_down(self):
+ mode = MODE_ACTIVE_BACKUP
+ self.logger.info(
+ "begin checking bonding backup(stacked) "
+ "mode transmission with one slave down"
+ )
+ results = self.check_traffic_with_one_slave_down(mode)
+ if results:
+ for item in results:
+ self.logger.error(item)
+ msg = "backup(stacked) mode: rx with one slave down failed"
+ raise VerifyFailure(msg)
+
+ def xor_check_rx(self):
+ mode = MODE_XOR_BALANCE
+ msg = "begin checking bonding xor(stacked) mode transmission"
+ self.logger.info(msg)
+ results = self.check_traffic(mode)
+ if results:
+ for item in results:
+ self.logger.error(item)
+ raise VerifyFailure("xor(stacked) mode: rx failed")
+
+ def xor_check_stacked_rx_one_slave_down(self):
+ mode = MODE_XOR_BALANCE
+ self.logger.info(
+ "begin checking bonding xor(stacked) mode "
+ "transmission with one slave down"
+ )
+ results = self.check_traffic_with_one_slave_down(mode)
+ if results:
+ for item in results:
+ self.logger.error(item)
+ msg = "xor(stacked) mode: rx with one slave down failed"
+ raise VerifyFailure(msg)
+
+ #
+ # 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.dport_info0 = self.dut.ports_info[self.dut_ports[0]]
+ self.dport_ifaces = self.dport_info0["intf"]
+ num_ports = len(self.dut_ports)
+ self.verify(num_ports == 2 or num_ports == 4, "Insufficient ports")
+ tester_port0 = self.tester.get_local_port(self.dut_ports[0])
+ self.tport_iface0 = self.tester.get_interface(tester_port0)
+ self.flag = "link-down-on-close"
+ self.default_stats = self.tester.get_priv_flags_state(
+ self.tport_iface0, self.flag
+ )
+ self.tester.send_expect(
+ "ethtool --set-priv-flags %s %s on" % (self.tport_iface0, self.flag), "# "
+ )
+ tester_port1 = self.tester.get_local_port(self.dut_ports[1])
+ self.tport_iface1 = self.tester.get_interface(tester_port1)
+ self.tester.send_expect(
+ "ethtool --set-priv-flags %s %s on" % (self.tport_iface1, self.flag), "# "
+ )
+ # separate ports into two group as first level bond ports' slaves
+ self.slaveGrpOne = [0, 2]
+ self.slaveGrpTwo = [1, 3]
+ self.bond_slave = self.dut_ports[0]
+ # initialize bonding common methods name
+ self.total_pkt = 100
+ config = {
+ "parent": self,
+ "pkt_name": "udp",
+ "pkt_size": FRAME_SIZE_64,
+ "src_mac": "52:00:00:00:00:03",
+ "src_ip": "10.239.129.65",
+ "src_port": 61,
+ "dst_ip": "10.239.129.88",
+ "dst_port": 53,
+ }
+ self.bond_inst = bonding.PmdBonding(**config)
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ self.tester.send_expect(
+ "ethtool --set-priv-flags %s %s %s"
+ % (self.tport_iface0, self.flag, self.default_stats),
+ "# ",
+ )
+ self.tester.send_expect(
+ "ethtool --set-priv-flags %s %s %s"
+ % (self.tport_iface1, self.flag, self.default_stats),
+ "# ",
+ )
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ self.create_vfs(pfs_id=self.dut_ports[0:2], vf_num=2)
+ self.eal_param = ""
+ for pci in self.vfs_pci:
+ self.eal_param += " -a %s" % pci
+
+ def create_vfs(self, pfs_id, vf_num):
+ self.sriov_vfs_port = []
+ self.vfs_pci = []
+ self.dut.bind_interfaces_linux(self.kdriver)
+ pfs_id = pfs_id if isinstance(pfs_id, list) else [pfs_id]
+ for pf_id in pfs_id:
+ self.dut.generate_sriov_vfs_by_port(pf_id, vf_num)
+ self.sriov_vfs_port += self.dut.ports_info[self.dut_ports[pf_id]][
+ "vfs_port"
+ ]
+ for vf in self.sriov_vfs_port:
+ self.vfs_pci.append(vf.pci)
+ try:
+ for port in self.sriov_vfs_port:
+ port.bind_driver(self.drivername)
+ except Exception as e:
+ self.destroy_iavf()
+ raise Exception(e)
+
+ def destroy_iavf(self):
+ self.dut.destroy_sriov_vfs_by_port(self.dut_ports[0])
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ """
+ try:
+ self.bond_inst.close_testpmd()
+ except Exception:
+ self.dut.kill_all()
+ self.destroy_iavf()
+ for port in self.dut_ports:
+ tport = self.tester.get_local_port(port)
+ tport_iface = self.tester.get_interface(tport)
+ cmd = "ifconfig {0} up".format(tport_iface)
+ self.tester.send_expect(cmd, "# ")
+
+ def test_basic_behav(self):
+ """
+ Test Case: basic behavior
+ 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 behavior of stacked bonded 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.bond_inst.start_testpmd(self.eal_param)
+ self.bond_inst.d_console("set fwd mac")
+ try:
+ self.logger.info("check bonding mode <{0}>".format(bond_mode))
+ # set up stacked bonded status
+ bond_port_1, bond_port_2, master_bond_port = self.set_stacked_bonded(
+ slaveGrpOne, slaveGrpTwo, bond_mode
+ )
+ # check duplicate add slave
+ self.duplicate_add_stacked_bonded(
+ bond_port_1, bond_port_2, master_bond_port
+ )
+ # check stacked limitation
+ self.set_third_stacked_bonded(master_bond_port, 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.bond_inst.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 exception
+ msg = ""
+ try:
+ # boot up testpmd
+ self.bond_inst.start_testpmd(self.eal_param)
+ # 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.bond_inst.close_testpmd()
+
+ exception_flag = False
+ for bond_mode, e in check_result:
+ msg = "mode <{0}>".format(bond_mode)
+ if e:
+ self.logger.info(msg)
+ self.logger.error(e)
+ exception_flag = True
+ else:
+ self.logger.info(msg + " done !")
+ # if some checking item is failed, raise exception
+ if exception_flag:
+ raise VerifyFailure("some test items failed")
+ else:
+ self.logger.info("all test items have done !")
+
+ def test_mode_backup_rx(self):
+ """
+ Test Case: active-backup stacked bonded rx traffic
+ """
+ self.backup_check_traffic()
+
+ def test_mode_backup_one_slave_down(self):
+ """
+ Test Case: active-backup stacked bonded rx traffic with slave down
+ """
+ self.backup_check_traffic_with_slave_down()
+
+ def test_mode_xor_rx(self):
+ """
+ Test Case: balance-xor stacked bonded rx traffic
+ """
+ self.xor_check_rx()
+
+ def test_mode_xor_rx_one_slave_down(self):
+ """
+ Test Case: balance-xor stacked bonded rx traffic with slave down
+ """
+ self.xor_check_stacked_rx_one_slave_down()
--
2.25.1
^ permalink raw reply [flat|nested] 9+ messages in thread