summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorYong Liu <yong.liu@intel.com>2014-09-10 13:25:52 +0800
committerYong Liu <yong.liu@intel.com>2014-09-10 13:25:52 +0800
commitddbe46a51d4d5352737a1077b25cfe283a4d1fb2 (patch)
tree99d53ffb5bb5c1aba8c8b4fda39a9eece3763a0b /tests
import dcts first version
Diffstat (limited to 'tests')
-rw-r--r--tests/TestSuite_blacklist.py125
-rw-r--r--tests/TestSuite_checksum_offload.py317
-rw-r--r--tests/TestSuite_cmdline.py124
-rw-r--r--tests/TestSuite_fdir.py335
-rw-r--r--tests/TestSuite_hello_world.py86
-rw-r--r--tests/TestSuite_ieee1588.py145
-rw-r--r--tests/TestSuite_ip_pipeline.py567
-rw-r--r--tests/TestSuite_ipfrag.py381
-rw-r--r--tests/TestSuite_jumboframes.py226
-rw-r--r--tests/TestSuite_l2fwd.py215
-rw-r--r--tests/TestSuite_l3fwd.py602
-rw-r--r--tests/TestSuite_link_flowctrl.py407
-rw-r--r--tests/TestSuite_multiprocess.py258
-rw-r--r--tests/TestSuite_pmd.py477
-rw-r--r--tests/TestSuite_pmd_bonded.py1098
-rw-r--r--tests/TestSuite_timer.py86
-rw-r--r--tests/TestSuite_vlan.py182
-rw-r--r--tests/TestSuite_whitelist.py197
18 files changed, 5828 insertions, 0 deletions
diff --git a/tests/TestSuite_blacklist.py b/tests/TestSuite_blacklist.py
new file mode 100644
index 0000000..a7e5ca3
--- /dev/null
+++ b/tests/TestSuite_blacklist.py
@@ -0,0 +1,125 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+Test device blacklisting.
+
+"""
+
+import dcts
+
+
+from test_case import TestCase
+
+
+#
+#
+# Test class.
+#
+class TestBlacklist(TestCase):
+
+ #
+ #
+ #
+ # Test cases.
+ #
+
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+
+ Blacklist Prerequisites.
+ Requirements:
+ Two Ports
+ """
+
+ self.ports = self.dut.get_ports(self.nic)
+ self.verify(len(self.ports) >= 2, "Insufficient ports for testing")
+ self.regexp_blacklisted_port = "EAL: PCI device 0000:%s on NUMA socket [-0-9]+[^\n]*\nEAL: probe driver[^\n]*\nEAL: Device is blacklisted, not initializing"
+
+ def set_up(self):
+ """
+ Run before each test case.
+ Nothing to do.
+ """
+ pass
+
+ def check_blacklisted_ports(self, output, ports, blacklisted=False):
+ """
+ Check if any of the ports in `ports` have been blacklisted, if so, raise
+ exception.
+ If `blacklisted` is True, then raise an exception if any of the ports
+ in `ports` have not been blacklisted.
+ """
+ for port in ports:
+
+ # Look for the PCI ID of each card followed by
+ # "Device is blacklisted, not initializing" but avoid to consume more
+ # than one device.
+ regexp_blacklisted_port = self.regexp_blacklisted_port % self.dut.ports_info[port]['pci']
+
+ matching_ports = dcts.regexp(output, regexp_blacklisted_port, True)
+
+ if blacklisted:
+ self.verify(len(matching_ports) == 1,
+ "Blacklisted port is being initialized")
+ else:
+ self.verify(len(matching_ports) == 0,
+ "Not blacklisted port is being blacklisted")
+
+ def test_bl_noblacklisted(self):
+ """
+ Run testpmd with no blacklisted device.
+ """
+
+ cmdline = r"./%s/build/app/test-pmd/testpmd -n 1 -c 3 -- -i" % self.target
+ out = self.dut.send_expect(cmdline, "testpmd> ", 120)
+ rexp = r"Link"
+ match_status = dcts.regexp(out, rexp, True)
+
+ self.check_blacklisted_ports(out, self.ports)
+
+ def test_bl_oneportblacklisted(self):
+ """
+ Run testpmd with one port blacklisted.
+ """
+ self.dut.kill_all()
+
+ cmdline = r"./%s/build/app/test-pmd/testpmd -n 1 -c 3 -b 0000:%s -- -i" % (self.target, self.dut.ports_info[0]['pci'])
+ out = self.dut.send_expect(cmdline, "testpmd> ", 120)
+
+ self.check_blacklisted_ports(out, self.ports[1:])
+
+ def test_bl_allbutoneportblacklisted(self):
+ """
+ Run testpmd with all but one port blacklisted.
+ """
+ self.dut.kill_all()
+
+ ports_to_blacklist = self.ports[:-1]
+
+ cmdline = "./%s/build/app/test-pmd/testpmd -n 1 -c 3" % self.target
+ for port in ports_to_blacklist:
+ cmdline += " -b 0000:%s" % self.dut.ports_info[port]['pci']
+
+ cmdline += " -- -i"
+ out = self.dut.send_expect(cmdline, "testpmd> ", 180)
+
+ blacklisted_ports = self.check_blacklisted_ports(out,
+ ports_to_blacklist,
+ True)
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ Quit testpmd.
+ """
+ self.dut.send_expect("quit", "# ", 10)
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ Nothing to do.
+ """
+ pass
diff --git a/tests/TestSuite_checksum_offload.py b/tests/TestSuite_checksum_offload.py
new file mode 100644
index 0000000..e80c26a
--- /dev/null
+++ b/tests/TestSuite_checksum_offload.py
@@ -0,0 +1,317 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+Test support of RX/TX Checksum Offload Features by Poll Mode Drivers.
+
+"""
+
+import dcts
+import string
+import re
+import rst
+
+from test_case import TestCase
+
+#
+#
+# Test class.
+#
+
+
+class TestChecksumOffload(TestCase):
+
+ #
+ #
+ #
+ # Test cases.
+ #
+
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+
+ Checksum offload prerequisites.
+ """
+ # Based on h/w type, choose how many ports to use
+ self.dut_ports = self.dut.get_ports_performance(self.nic)
+
+ # Verify that enough ports are available
+ self.verify(len(self.dut_ports) >= 2, "Insufficient ports for testing")
+
+ # Verify that enough threads are available
+ cores = self.dut.get_core_list("1S/2C/2T")
+ self.verify(cores is not None, "Insufficient cores for speed testing")
+
+ self.coreMask = dcts.create_mask(cores)
+ self.portMask = dcts.create_mask([self.dut_ports[0], self.dut_ports[1]])
+ self.ports_socket = self.dut.get_numa_id(self.dut_ports[0])
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ if self.dut.want_func_tests:
+ self.dut.send_expect("./%s/build/app/test-pmd/testpmd -c %s -n 1 -- -i --burst=1 --txpt=32 --txht=8 --txwt=0 --txfreet=0 --rxfreet=64 --mbcache=250 --portmask=%s --disable-hw-vlan --enable-rx-cksum --crc-strip" % (self.target, self.coreMask, self.portMask), "testpmd>", 120)
+ self.dut.send_expect("set verbose 1", "testpmd>")
+ self.dut.send_expect("set fwd csum", "testpmd>")
+
+ def checksum_validate(self, packets_sent, packets_expected):
+ """
+ Validate the checksum.
+ """
+ tx_interface = self.tester.get_interface(self.tester.get_local_port(self.dut_ports[1]))
+ rx_interface = self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))
+
+ checksum_pattern = re.compile("chksum.*=.*(0x[0-9a-z]+)")
+
+ chksum = dict()
+ result = dict()
+
+ self.tester.send_expect("scapy", ">>> ")
+ self.tester.send_expect('sys.path.append("./")', ">>> ")
+ self.tester.send_expect('from sctp import *', ">>> ")
+
+ for packet_type in packets_expected.keys():
+ self.tester.send_expect("p = %s" % packets_expected[packet_type], ">>>")
+ out = self.tester.send_expect("p.show2()", ">>>")
+ chksums = checksum_pattern.findall(out)
+ chksum[packet_type] = chksums
+
+ self.tester.send_expect("exit()", "#")
+
+ self.tester.scapy_background()
+ self.tester.scapy_append('sys.path.append("./")')
+ self.tester.scapy_append('import sctp')
+ self.tester.scapy_append('from sctp import *')
+ self.tester.scapy_append('p = sniff(filter="ether src 52:00:00:00:00:00", iface="%s", count=%d)' % (rx_interface, len(packets_sent)))
+ self.tester.scapy_append('nr_packets=len(p)')
+ self.tester.scapy_append('reslist = [p[i].sprintf("%IP.chksum%;%TCP.chksum%;%UDP.chksum%;%SCTP.chksum%") for i in range(nr_packets)]')
+ self.tester.scapy_append('import string')
+ self.tester.scapy_append('RESULT = string.join(reslist, ",")')
+
+ # Send packet.
+ self.tester.scapy_foreground()
+ self.tester.scapy_append('sys.path.append("./")')
+ self.tester.scapy_append('import sctp')
+ self.tester.scapy_append('from sctp import *')
+
+ for packet_type in packets_sent.keys():
+ self.tester.scapy_append('sendp([%s], iface="%s")' % (packets_sent[packet_type], tx_interface))
+
+ self.tester.scapy_execute()
+ out = self.tester.scapy_get_result()
+ packets_received = out.split(',')
+ self.verify(len(packets_sent) == len(packets_received), "Unexpected Packets Drop")
+
+ for packet_received in packets_received:
+ ip_checksum, tcp_checksum, udp_checksup, sctp_checksum = packet_received.split(';')
+
+ packet_type = ''
+ l4_checksum = ''
+ if tcp_checksum != '??':
+ packet_type = 'TCP'
+ l4_checksum = tcp_checksum
+ elif udp_checksup != '??':
+ packet_type = 'UDP'
+ l4_checksum = udp_checksup
+ elif sctp_checksum != '??':
+ packet_type = 'SCTP'
+ l4_checksum = sctp_checksum
+
+ if ip_checksum != '??':
+ packet_type = 'IP/' + packet_type
+ if chksum[packet_type] != [ip_checksum, l4_checksum]:
+ result[packet_type] = packet_type + " checksum error"
+ else:
+ packet_type = 'IPv6/' + packet_type
+ if chksum[packet_type] != [l4_checksum]:
+ result[packet_type] = packet_type + " checksum error"
+
+ return result
+
+ def test_checksum_offload_with_vlan(self):
+ """
+ Do not insert IPv4/IPv6 UDP/TCP checksum on the transmit packet.
+ Verify that the same number of packet are correctly received on the
+ traffic generator side.
+ Use VLAN label.
+ """
+ dmac = self.dut.get_mac_address(self.dut_ports[1])
+ pktsChkErr = {'IP/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/Dot1Q(vlan=1)/IP(chksum=0x0)/UDP(chksum=0x0)/("X"*46)' % dmac,
+ 'IP/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/Dot1Q(vlan=2)/IP(chksum=0x0)/TCP(chksum=0x0)/("X"*46)' % dmac,
+ 'IP/SCTP': 'Ether(dst="%s", src="52:00:00:00:00:00")/Dot1Q(vlan=3)/IP(chksum=0x0)/SCTP(chksum=0x0)/("X"*48)' % dmac,
+ 'IPv6/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/Dot1Q(vlan=4)/IPv6()/UDP(chksum=0x0)/("X"*46)' % dmac,
+ 'IPv6/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/Dot1Q(vlan=5)/IPv6()/TCP(chksum=0x0)/("X"*46)' % dmac}
+
+ pkts = {'IP/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP()/UDP()/("X"*46)' % dmac,
+ 'IP/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP()/TCP()/("X"*46)' % dmac,
+ 'IP/SCTP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP()/SCTP()/("X"*48)' % dmac,
+ 'IPv6/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6()/UDP()/("X"*46)' % dmac,
+ 'IPv6/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6()/TCP()/("X"*46)' % dmac}
+
+ self.dut.send_expect("tx_checksum set 0xf %d" % self.dut_ports[0], "testpmd>")
+
+ self.dut.send_expect("start", "testpmd>")
+
+ result = self.checksum_validate(pktsChkErr, pkts)
+
+ self.dut.send_expect("stop", "testpmd>")
+
+ self.verify(len(result) == 0, string.join(result.values(), ","))
+
+ def test_checksum_offload_enable(self):
+ """
+ Insert IPv4/IPv6 UDP/TCP/SCTP checksum on the transmit packet.
+ Enable Checksum offload.
+ Verify that the same number of packet are correctly received on the
+ traffic generator side.
+ """
+
+ dmac = self.dut.get_mac_address(self.dut_ports[1])
+
+ pkts = {'IP/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP()/UDP()/("X"*46)' % dmac,
+ 'IP/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP()/TCP()/("X"*46)' % dmac,
+ 'IP/SCTP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP()/SCTP()/("X"*48)' % dmac,
+ 'IPv6/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6()/UDP()/("X"*46)' % dmac,
+ 'IPv6/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6()/TCP()/("X"*46)' % dmac}
+
+ self.dut.send_expect("tx_checksum set 0xf %d" % self.dut_ports[0], "testpmd>")
+
+ self.dut.send_expect("start", "testpmd>")
+
+ result = self.checksum_validate(pkts, pkts)
+
+ self.dut.send_expect("stop", "testpmd>")
+
+ self.verify(len(result) == 0, string.join(result.values(), ","))
+
+ def test_checksum_offload_disable(self):
+ """
+ Do not insert IPv4/IPv6 UDP/TCP checksum on the transmit packet.
+ Disable Checksum offload.
+ Verify that the same number of packet are correctly received on
+ the traffic generator side.
+ """
+
+ dmac = self.dut.get_mac_address(self.dut_ports[1])
+
+ sndIP = '10.0.0.1'
+ sndIPv6 = '::1'
+ sndPkts = {'IP/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="%s")/UDP()/("X"*46)' % (dmac, sndIP),
+ 'IP/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="%s")/TCP()/("X"*46)' % (dmac, sndIP),
+ 'IPv6/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6(src="%s")/UDP()/("X"*46)' % (dmac, sndIPv6),
+ 'IPv6/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6(src="%s")/TCP()/("X"*46)' % (dmac, sndIPv6)}
+
+ expIP = "11.0.0.1"
+ expIPv6 = '::1'
+ expPkts = {'IP/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="%s")/UDP()/("X"*46)' % (dmac, expIP),
+ 'IP/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="%s")/TCP()/("X"*46)' % (dmac, expIP),
+ 'IPv6/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6(src="%s")/UDP()/("X"*46)' % (dmac, expIPv6),
+ 'IPv6/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6(src="%s")/TCP()/("X"*46)' % (dmac, expIPv6)}
+
+ self.dut.send_expect("tx_checksum set 0x0 %d" % self.dut_ports[0], "testpmd>")
+
+ self.dut.send_expect("start", "testpmd>")
+ result = self.checksum_validate(sndPkts, expPkts)
+
+ self.verify(len(result) == 0, string.join(result.values(), ","))
+
+ self.dut.send_expect("stop", "testpmd>")
+
+ def benchmark(self, lcore, ptype, mode, flow_format, size_list, nic):
+ """
+ Test ans report checksum offload performance for given parameters.
+ """
+
+ Bps = dict()
+ Pps = dict()
+ Pct = dict()
+ dmac = self.dut.get_mac_address(self.dut_ports[0])
+
+ result = [2, lcore, ptype, mode]
+ for size in size_list:
+
+ flow = flow_format % (dmac, size)
+ self.tester.scapy_append('wrpcap("test.pcap", [%s])' % flow)
+
+ self.tester.scapy_execute()
+
+ tgenInput = []
+ tgenInput.append((self.tester.get_local_port(self.dut_ports[0]), self.tester.get_local_port(self.dut_ports[1]), "test.pcap"))
+ tgenInput.append((self.tester.get_local_port(self.dut_ports[1]), self.tester.get_local_port(self.dut_ports[0]), "test.pcap"))
+
+ Bps[str(size)], Pps[str(size)] = self.tester.traffic_generator_throughput(tgenInput)
+ self.verify(Pps[str(size)] > 0, "No traffic detected")
+ Pps[str(size)] /= 1E6
+ Pct[str(size)] = (Pps[str(size)] * 100) / self.wirespeed(self.nic, size, 2)
+
+ result.append(Pps[str(size)])
+ result.append(Pct[str(size)])
+
+ dcts.results_table_add_row(result)
+
+ def test_perf_checksum_throughtput(self):
+ """
+ Test checksum offload performance.
+ """
+
+ self.verify(self.nic == 'niantic', "throughtput case require niantic 10Gb self.nic")
+ # sizes = [64, 128, 256, 512, 1024]
+ sizes = [64, 128]
+ pkts = {
+ 'IP/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP()/UDP()/("X"*(%d-46))',
+ 'IP/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP()/TCP()/("X"*(%d-58))',
+ 'IP/SCTP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP()/SCTP()/("X"*(%d-50+2))',
+ 'IPv6/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6()/UDP()/("X"* (lambda x: x - 66 if x > 66 else 0)(%d))',
+ 'IPv6/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6()/TCP()/("X"* (lambda x: x - 78 if x > 78 else 0)(%d))'
+ }
+
+ lcore = "1S/2C/1T"
+ coreMask = dcts.create_mask(self.dut.get_core_list(lcore, socket=self.ports_socket))
+ portMask = dcts.create_mask([self.dut_ports[0], self.dut_ports[1]])
+
+ for mode in ["sw", "hw"]:
+ self.logger.info("%s performance" % mode)
+ rst.write_text(mode + " Performance" + '\r\n')
+ tblheader = ["Ports", "S/C/T", "Packet Type", "Mode"]
+ for size in sizes:
+ tblheader.append("%sB mpps" % str(size))
+ tblheader.append("%sB %% " % str(size))
+
+ dcts.results_table_add_header(tblheader)
+
+ self.dut.send_expect("./%s/build/app/test-pmd/testpmd -c%s -n %d -- -i --nb-cores=1 --txpt=40 --txht=4 --txwt=0 --rxfreet=64 --mbcache=250 --portmask=%s" % (self.target, coreMask, self.dut.get_memory_channels(), portMask), "testpmd>", 120)
+
+ self.dut.send_expect("set verbose 1", "testpmd> ")
+ self.dut.send_expect("set fwd csum", "testpmd> ")
+
+ if mode == "hw":
+ self.dut.send_expect("tx_checksum set 0xf %d" % self.dut_ports[0], "testpmd> ")
+ self.dut.send_expect("tx_checksum set 0xf %d" % self.dut_ports[1], "testpmd> ")
+ else:
+ self.dut.send_expect("tx_checksum set 0x0 %d" % self.dut_ports[0], "testpmd> ")
+ self.dut.send_expect("tx_checksum set 0x0 %d" % self.dut_ports[1], "testpmd> ")
+
+ self.dut.send_expect("start", "testpmd> ", 3)
+
+ for ptype in pkts.keys():
+ self.benchmark(lcore, ptype, mode, pkts[ptype], sizes, self.nic)
+
+ self.dut.send_expect("stop", "testpmd> ")
+ self.dut.send_expect("quit", "#", 10)
+ dcts.results_table_print()
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ """
+ if self.dut.want_func_tests:
+ self.dut.send_expect("quit", "#")
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ pass
diff --git a/tests/TestSuite_cmdline.py b/tests/TestSuite_cmdline.py
new file mode 100644
index 0000000..db3f205
--- /dev/null
+++ b/tests/TestSuite_cmdline.py
@@ -0,0 +1,124 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+Test cmdline.
+
+"""
+
+import dcts
+
+
+from test_case import TestCase
+
+#
+#
+# Test class.
+#
+
+
+class TestCmdline(TestCase):
+
+ #
+ #
+ #
+ # Test cases.
+ #
+
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+
+ Cmdline Prerequisites:
+ cmdline build pass
+ At least one core in DUT
+ """
+ out = self.dut.build_dpdk_apps('examples/cmdline')
+ self.verify('make: Leaving directory' in out, "Compilation failed")
+ self.verify("Error" not in out, "compilation error 1")
+ self.verify("No such file" not in out, "compilation error 2")
+
+ # Run cmdline app
+ cores = self.dut.get_core_list('1S/1C/1T')
+ coreMask = dcts.create_mask(cores)
+ self.dut.send_expect("./examples/cmdline/build/app/cmdline -n 1 -c " + coreMask, "> ", 5)
+
+ def set_up(self):
+ """
+ Run before each test case.
+ Nothing to do.
+ """
+ pass
+
+ def test_cmdline_sample_commands(self):
+ """
+ Sample commands test.
+ """
+
+ # add a test object with an IP address associated
+ out = self.dut.send_expect("add objtest 192.168.0.1", "example> ")
+ self.verify("Object objtest added, ip=192.168.0.1" in out, "add command error")
+
+ # verify the object existance
+ out = self.dut.send_expect("add objtest 192.168.0.1", "example> ")
+ self.verify("Object objtest already exist" in out, "double add command error")
+
+ # show the object result by 'show' command
+ out = self.dut.send_expect("show objtest", "example> ")
+ self.verify("Object objtest, ip=192.168.0.1" in out, "show command error")
+
+ # delete the object in cmdline
+ out = self.dut.send_expect("del objtest", "example> ")
+ self.verify("Object objtest removed, ip=192.168.0.1" in out, "del command error")
+
+ # double delete the object to verify the correctness
+ out = self.dut.send_expect("del objtest", "example> ", 1)
+ self.verify("Bad arguments" in out, "double del command error")
+
+ # verify no such object anymore
+ out = self.dut.send_expect("show objtest", "example> ", 1)
+ self.verify("Bad arguments" in out, "final show command error")
+
+ # verify the help command
+ out = self.dut.send_expect("help", "example> ", 1)
+
+ """
+ Demo example of command line interface in RTE
+
+ This is a readline-like interface that can be used to
+ debug your RTE application. It supports some features
+ of GNU readline like completion, cut/paste, and some
+ other special bindings.
+
+ This demo shows how rte_cmdline library can be
+ extended to handle a list of objects. There are
+ 3 commands:
+ - add obj_name IP
+ - del obj_name
+ - show obj_name
+ """
+ self.verify(" " in out, "help command error")
+
+ out = self.dut.send_expect("?", "example> ", 1)
+ """
+ show [Mul-choice STRING]: Show/del an object
+ del [Mul-choice STRING]: Show/del an object
+ add [Fixed STRING]: Add an object (name, val)
+ help [Fixed STRING]: show help
+ """
+ self.verify(" " in out, "? command error")
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ Nothing to do.
+ """
+ pass
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ Stop cmdline app.
+ """
+ self.dut.kill_all()
diff --git a/tests/TestSuite_fdir.py b/tests/TestSuite_fdir.py
new file mode 100644
index 0000000..61c7091
--- /dev/null
+++ b/tests/TestSuite_fdir.py
@@ -0,0 +1,335 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+Test 82599 Flow Director Support in DPDK
+"""
+
+import dcts
+import time
+
+
+from test_case import TestCase
+
+#
+#
+# Test class.
+#
+
+
+class TestFdir(TestCase):
+
+ #
+ #
+ # Utility methods and other non-test code.
+ #
+
+ def send_and_verify(self, condition, packet):
+ """
+ Send packages and verify behavior.
+ """
+ self.tester.scapy_foreground()
+ self.tester.scapy_append('sys.path.append("./")')
+ self.tester.scapy_append('from sctp import *')
+ self.tester.scapy_append(packet)
+ self.dut.send_expect("start", "testpmd>")
+ self.tester.scapy_execute()
+ time.sleep(.5)
+ out = self.dut.send_expect("stop", "testpmd>")
+ if condition:
+ self.verify("PKT_RX_PKT_RX_FDIR" in out, "FDIR hash not displayed when required")
+ else:
+ self.verify("PKT_RX_PKT_RX_FDIR" not in out, "FDIR hash displayed when not required")
+
+ #
+ #
+ #
+ # Test cases.
+ #
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+ """
+ self.verify('bsdapp' not in self.target, "FDIR not support freebsd")
+ self.verify(self.nic in ["kawela", "niantic"], "NIC Unsupported: " + str(self.nic))
+
+ ports = self.dut.get_ports(self.nic)
+ self.verify(len(ports) >= 2, "Not enough ports available")
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ pass
+
+ def test_fdir_space(self):
+ """
+ Setting memory reserved for FDir filters.
+ """
+
+ dutPorts = self.dut.get_ports(self.nic)
+
+ self.dut.send_expect("./%s/app/testpmd -c 0xff -n 1 -- -i --rxq=2 --txq=2 --disable-rss --pkt-filter-mode=perfect --pkt-filter-size=64K" % self.target, "testpmd>", 120)
+ out = self.dut.send_expect("show port fdir %s" % dutPorts[0], "testpmd>")
+ self.dut.send_expect("quit", "# ", 30)
+ self.verify("free: 2048" in out, "Free space doesn't match the expected value")
+
+ self.dut.send_expect("./%s/app/testpmd -c 0xff -n 1 -- -i --rxq=2 --txq=2 --disable-rss --pkt-filter-mode=perfect --pkt-filter-size=128K" % self.target, "testpmd>", 120)
+ out = self.dut.send_expect("show port fdir %s" % dutPorts[0], "testpmd>")
+ self.dut.send_expect("quit", "# ", 30)
+ self.verify("free: 4096" in out, "Free space doesn't match the expected value")
+
+ self.dut.send_expect("./%s/app/testpmd -c 0xff -n 1 -- -i --rxq=2 --txq=2 --disable-rss --pkt-filter-mode=perfect --pkt-filter-size=256K" % self.target, "testpmd>", 120)
+ out = self.dut.send_expect("show port fdir %s" % dutPorts[0], "testpmd>")
+ self.dut.send_expect("quit", "# ", 30)
+ self.verify("free: 8192" in out, "Free space doesn't match the expected value")
+
+ def test_fdir_signatures(self):
+ """
+ FDir signature matching mode.
+ """
+
+ dutPorts = self.dut.get_ports(self.nic)
+ localPort = self.tester.get_local_port(dutPorts[0])
+ itf = self.tester.get_interface(localPort)
+
+ self.dut.kill_all()
+ self.dut.send_expect("./%s/app/testpmd -c 0xff -n 1 -- -i --portmask=%s --rxq=2 --txq=2 --disable-rss --pkt-filter-mode=perfect --pkt-filter-report-hash=none" % (self.target, dcts.create_mask([dutPorts[0]])), "testpmd>", 120)
+ self.dut.send_expect("set verbose 1", "testpmd>")
+ self.dut.send_expect("set fwd rxonly", "testpmd>")
+ self.dut.send_expect("set nbcore 3", "testpmd>")
+
+ self.send_and_verify(False, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("add_perfect_filter %s udp src 192.168.0.1 1024 dst 192.168.0.2 1024 flexbytes 0x800 vlan 0 queue 1 soft 0x14" % dutPorts[0], "testpmd>")
+ self.send_and_verify(False, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("quit", "# ", 30)
+
+ self.dut.send_expect("./%s/app/testpmd -c 0xff -n 1 -- -i --portmask=%s --rxq=2 --txq=2 --disable-rss --pkt-filter-mode=perfect --pkt-filter-report-hash=match" % (self.target, dcts.create_mask([dutPorts[0]])), "testpmd>", 120)
+ self.dut.send_expect("set verbose 1", "testpmd>")
+ self.dut.send_expect("set fwd rxonly", "testpmd>")
+ self.dut.send_expect("set nbcore 3", "testpmd>")
+
+ self.send_and_verify(False, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("add_perfect_filter %s udp src 192.168.0.1 1024 dst 192.168.0.2 1024 flexbytes 0x800 vlan 0 queue 1 soft 0x14" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("upd_perfect_filter %s udp src 192.168.1.1 0 dst 192.168.1.2 0 flexbytes 0x800 vlan 0 queue 1 soft 0x14" % dutPorts[0], "testpmd>")
+
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.1.1", dst="192.168.1.2")/UDP(sport=0,dport=0)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("rm_perfect_filter %s udp src 192.168.1.1 0 dst 192.168.1.2 0 flexbytes 0x800 vlan 0 soft 0x14" % dutPorts[0], "testpmd>")
+
+ self.send_and_verify(False, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.1.1", dst="192.168.1.2")/UDP(sport=0,dport=0)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("quit", "# ", 30)
+
+ self.dut.send_expect("./%s/app/testpmd -c 0xff -n 1 -- -i --portmask=%s --rxq=2 --txq=2 --disable-rss --pkt-filter-mode=perfect --pkt-filter-report-hash=always" % (self.target, dcts.create_mask([dutPorts[0]])), "testpmd>", 120)
+ self.dut.send_expect("set verbose 1", "testpmd>")
+ self.dut.send_expect("set fwd rxonly", "testpmd>")
+ self.dut.send_expect("set nbcore 3", "testpmd>")
+
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("add_perfect_filter %s udp src 192.168.0.1 1024 dst 192.168.0.2 1024 flexbytes 0x800 vlan 0 queue 1 soft 0x14" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("quit", "# ", 30)
+
+ def test_fdir_matching(self):
+ """
+ FDir matching mode
+ """
+
+ dutPorts = self.dut.get_ports(self.nic)
+ localPort = self.tester.get_local_port(dutPorts[0])
+ itf = self.tester.get_interface(localPort)
+
+ self.dut.kill_all()
+ self.dut.send_expect("./%s/app/testpmd -c 0xff -n 1 -- -i --portmask=%s --rxq=2 --txq=2 --disable-rss --pkt-filter-mode=signature --pkt-filter-report-hash=match" % (self.target, dcts.create_mask([dutPorts[0]])), "testpmd>", 120)
+ self.dut.send_expect("set verbose 1", "testpmd>")
+ self.dut.send_expect("set fwd rxonly", "testpmd>")
+ self.dut.send_expect("set nbcore 3", "testpmd>")
+
+ self.send_and_verify(False, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("add_signature_filter %s udp src 192.168.0.1 1024 dst 192.168.0.2 1024 flexbytes 0x800 vlan 0 queue 1" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.send_and_verify(False, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/TCP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("upd_signature_filter %s udp src 192.168.1.1 0 dst 192.168.1.2 0 flexbytes 0x800 vlan 0 queue 1" % dutPorts[0], "testpmd>")
+
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.1.1", dst="192.168.1.2")/UDP(sport=0,dport=0)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("rm_signature_filter %s udp src 192.168.1.1 0 dst 192.168.1.2 0 flexbytes 0x800 vlan 0" % dutPorts[0], "testpmd>")
+
+ self.send_and_verify(False, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.1.1", dst="192.168.1.2")/UDP(sport=0,dport=0)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("add_signature_filter %s tcp src 192.168.0.1 1024 dst 192.168.0.2 1024 flexbytes 0x800 vlan 0 queue 1" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/TCP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.send_and_verify(False, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/SCTP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("add_signature_filter %s sctp src 192.168.0.1 0 dst 192.168.0.2 0 flexbytes 0x800 vlan 0 queue 1" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/SCTP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.send_and_verify(False, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("add_signature_filter %s ip src 192.168.0.1 0 dst 192.168.0.2 0 flexbytes 0x800 vlan 0 queue 1" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")], iface="%s")' % (itf, itf))
+
+ self.send_and_verify(False, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IPv6(src="2001:0db8:85a3:0000:0000:8a2e:0370:7000", dst="2001:0db8:85a3:0000:0000:8a2e:0370:7338")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("add_signature_filter %s udp src 2001:0db8:85a3:0000:0000:8a2e:0370:7000 1024 dst 2001:0db8:85a3:0000:0000:8a2e:0370:7338 1024 flexbytes 0x86dd vlan 0 queue 1" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IPv6(src="2001:0db8:85a3:0000:0000:8a2e:0370:7000", dst="2001:0db8:85a3:0000:0000:8a2e:0370:7338")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("quit", "# ", 30)
+
+ def test_fdir_perfect_matching(self):
+ """
+ FDir perfect matching mode.
+ """
+
+ dutPorts = self.dut.get_ports(self.nic)
+ localPort = self.tester.get_local_port(dutPorts[0])
+ itf = self.tester.get_interface(localPort)
+
+ self.dut.kill_all()
+ self.dut.send_expect("./%s/app/testpmd -c 0xff -n 1 -- -i --portmask=%s --rxq=2 --txq=2 --disable-rss --pkt-filter-mode=perfect --pkt-filter-report-hash=match" % (self.target, dcts.create_mask([dutPorts[0]])), "testpmd>", 120)
+ self.dut.send_expect("set verbose 1", "testpmd>")
+ self.dut.send_expect("set fwd rxonly", "testpmd>")
+ self.dut.send_expect("set nbcore 3", "testpmd>")
+
+ self.dut.send_expect("add_perfect_filter %s udp src 192.168.0.1 1024 dst 192.168.0.2 1024 flexbytes 0x800 vlan 0 queue 1 soft 0x14" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("add_perfect_filter %s tcp src 192.168.0.1 1024 dst 192.168.0.2 1024 flexbytes 0x800 vlan 0 queue 1 soft 0x15" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/TCP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("add_perfect_filter %s sctp src 192.168.0.1 0 dst 192.168.0.2 0 flexbytes 0x800 vlan 0 queue 1 soft 0x16" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/SCTP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("add_perfect_filter %s ip src 192.168.0.1 0 dst 192.168.0.2 0 flexbytes 0x800 vlan 0 queue 1 soft 0x17" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("quit", "# ", 30)
+
+ def test_fdir_filter_masks(self):
+ """
+ FDir filter masks.
+ """
+
+ dutPorts = self.dut.get_ports(self.nic)
+ localPort = self.tester.get_local_port(dutPorts[0])
+ itf = self.tester.get_interface(localPort)
+
+ self.dut.kill_all()
+ self.dut.send_expect("./%s/app/testpmd -c 0xff -n 1 -- -i --portmask=%s --rxq=2 --txq=2 --disable-rss --pkt-filter-mode=perfect --pkt-filter-size=64K --pkt-filter-report-hash=match" % (self.target, dcts.create_mask([dutPorts[0]])), "testpmd>", 120)
+ self.dut.send_expect("set verbose 1", "testpmd>")
+ self.dut.send_expect("set fwd rxonly", "testpmd>")
+ self.dut.send_expect("set nbcore 3", "testpmd>")
+
+ self.dut.send_expect("set_masks_filter %s only_ip_flow 0 src_mask 0xffffff00 0xffff dst_mask 0xffffff00 0xffff flexbytes 1 vlan_id 1 vlan_prio 1" % dutPorts[0], "testpmd>")
+ self.dut.send_expect("add_perfect_filter %s udp src 192.168.0.0 1024 dst 192.168.0.0 1024 flexbytes 0x800 vlan 0 queue 1 soft 0x17" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.15", dst="192.168.0.15")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.send_and_verify(False, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.1.1")/UDP(sport=1024,dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("set_masks_filter %s only_ip_flow 0 src_mask 0xffffffff 0xff00 dst_mask 0xffffffff 0xff00 flexbytes 1 vlan_id 1 vlan_prio 1" % dutPorts[0], "testpmd>")
+ self.dut.send_expect("add_perfect_filter %s udp src 10.11.12.1 0x4400 dst 10.11.12.2 0x4500 flexbytes 0x800 vlan 0 queue 1 soft 0x4" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="10.11.12.1", dst="10.11.12.2")/UDP(sport=0x4400,dport=0x4500)], iface="%s")' % (itf, itf))
+
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="10.11.12.1", dst="10.11.12.2")/UDP(sport=0x4411,dport=0x4517)], iface="%s")' % (itf, itf))
+
+ self.send_and_verify(False, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="10.11.12.1", dst="10.11.12.2")/UDP(sport=0x4500,dport=0x5500)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("set_masks_filter %s only_ip_flow 1 src_mask 0xffffffff 0x0 dst_mask 0xffffffff 0x0 flexbytes 1 vlan_id 1 vlan_prio 1" % dutPorts[0], "testpmd>")
+ self.dut.send_expect("add_perfect_filter %s ip src 192.168.0.1 0 dst 192.168.0.2 0 flexbytes 0x800 vlan 0 queue 1 soft 0x42" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024, dport=1024)], iface="%s")' % (itf, itf))
+
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/TCP(sport=1024, dport=1024)], iface="%s")' % (itf, itf))
+
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/SCTP(sport=1024, dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("quit", "# ", 30)
+
+ def test_fdir_flexbytes_filtering(self):
+ """
+ FDir flexbytes filtering
+ """
+
+ dutPorts = self.dut.get_ports(self.nic)
+ localPort = self.tester.get_local_port(dutPorts[0])
+ itf = self.tester.get_interface(localPort)
+
+ self.dut.kill_all()
+ self.dut.send_expect("./%s/app/testpmd -c 0xff -n 1 -- -i --portmask=%s --rxq=2 --txq=2 --disable-rss --pkt-filter-mode=perfect --pkt-filter-size=64K --pkt-filter-report-hash=match --pkt-filter-flexbytes-offset=18" % (self.target, dcts.create_mask([dutPorts[0]])), "testpmd>", 120)
+ self.dut.send_expect("set verbose 1", "testpmd>")
+ self.dut.send_expect("set fwd rxonly", "testpmd>")
+ self.dut.send_expect("set nbcore 3", "testpmd>")
+
+ self.dut.send_expect("add_perfect_filter %s ip src 192.168.0.1 0 dst 192.168.0.2 0 flexbytes 0x1 vlan 0 queue 1 soft 0x1" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/GRE(proto=0x1)/IP()/UDP()], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("add_perfect_filter %s ip src 192.168.0.1 0 dst 192.168.0.2 0 flexbytes 0xff vlan 0 queue 1 soft 0xff" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/GRE(proto=0xff)/IP()/UDP()], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("set_masks_filter %s only_ip_flow 0 src_mask 0xffffffff 0xffff dst_mask 0xffffffff 0xffff flexbytes 0 vlan_id 1 vlan_prio 1" % dutPorts[0], "testpmd>")
+ self.dut.send_expect("add_perfect_filter %s ip src 192.168.0.1 0 dst 192.168.0.2 0 flexbytes 0x0 vlan 0 queue 1 soft 0x42" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/GRE(proto=0x1)/IP()/UDP()], iface="%s")' % (itf, itf))
+
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/IP(src="192.168.0.1", dst="192.168.0.2")/GRE(proto=0xFF)/IP()/UDP()], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("quit", "# ", 30)
+
+ def test_fdir_vlanfiltering(self):
+ """
+ FDir VLAN field filtering
+ """
+
+ dutPorts = self.dut.get_ports(self.nic)
+ localPort = self.tester.get_local_port(dutPorts[0])
+ itf = self.tester.get_interface(localPort)
+
+ self.dut.kill_all()
+ self.dut.send_expect("./%s/app/testpmd -c 0xff -n 1 -- -i --portmask=%s --nb-cores=2 --rxq=2 --txq=2 --disable-rss --pkt-filter-mode=perfect" % (self.target, dcts.create_mask([dutPorts[0]])), "testpmd>", 120)
+ self.dut.send_expect("set verbose 1", "testpmd>")
+ self.dut.send_expect("set fwd rxonly", "testpmd>")
+ # "rx_vlan add all" has been removed from testpmd
+ self.dut.send_expect("rx_vlan add 0xFFF %s" % dutPorts[0], "testpmd>")
+ self.dut.send_expect("rx_vlan add 0x001 %s" % dutPorts[0], "testpmd>")
+ self.dut.send_expect("rx_vlan add 0x017 %s" % dutPorts[0], "testpmd>")
+
+ self.send_and_verify(False, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/Dot1Q(vlan=0x0FFF)/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024, dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("add_perfect_filter %s udp src 192.168.0.1 1024 dst 192.168.0.2 1024 flexbytes 0x8100 vlan 0xfff queue 1 soft 0x47" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/Dot1Q(vlan=0x0FFF)/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024, dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("set_masks_filter %s only_ip_flow 0 src_mask 0xffffffff 0xffff dst_mask 0xffffffff 0xffff flexbytes 1 vlan_id 0 vlan_prio 0" % dutPorts[0], "testpmd>")
+ self.dut.send_expect("add_perfect_filter %s udp src 192.168.0.1 1024 dst 192.168.0.2 1024 flexbytes 0x8100 vlan 0 queue 1 soft 0x47" % dutPorts[0], "testpmd>")
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/Dot1Q(vlan=0x001)/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024, dport=1024)], iface="%s")' % (itf, itf))
+ self.send_and_verify(True, 'sendp([Ether(src=get_if_hwaddr("%s"), dst="00:1B:21:8E:B2:30")/Dot1Q(vlan=0x0017)/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=1024, dport=1024)], iface="%s")' % (itf, itf))
+
+ self.dut.send_expect("quit", "# ", 30)
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ """
+ pass
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ pass
diff --git a/tests/TestSuite_hello_world.py b/tests/TestSuite_hello_world.py
new file mode 100644
index 0000000..3633ed7
--- /dev/null
+++ b/tests/TestSuite_hello_world.py
@@ -0,0 +1,86 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+Test HelloWorld example.
+"""
+
+import dcts
+from test_case import TestCase
+
+#
+#
+# Test class.
+#
+
+
+class TestHelloWorld(TestCase):
+
+ #
+ #
+ #
+ # Test cases.
+ #
+
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+ hello_world Prerequistites:
+ helloworld build pass
+ """
+ out = self.dut.build_dpdk_apps('examples/helloworld')
+
+ self.verify("Error" not in out, "compilation error 1")
+ self.verify("No such file" not in out, "compilation error 2")
+
+ def set_up(self):
+ """
+ Run before each test case.
+ Nothing to do.
+ """
+ pass
+
+ def test_hello_world_single_core(self):
+ """
+ Run hello world on single lcores
+ Only received hello message from core0
+ """
+
+ # get the mask for the first core
+ cores = self.dut.get_core_list('1S/1C/1T')
+ coreMask = dcts.create_mask(cores)
+ cmdline = "./examples/helloworld/build/app/helloworld -n 1 -c " + coreMask
+ out = self.dut.send_expect(cmdline, "# ", 3)
+
+ self.verify("hello from core %s" % cores[0] in out, "EAL not started on core%s" % cores[0])
+
+ def test_hello_world_all_cores(self):
+ """
+ Run hello world on all lcores
+ Received hello message from all lcores
+ """
+
+ # get the maximun logical core number
+ cores = self.dut.get_core_list('all')
+ coreMask = dcts.create_mask(cores)
+
+ cmdline = "./examples/helloworld/build/app/helloworld -n 1 -c " + coreMask
+ out = self.dut.send_expect(cmdline, "# ", 5)
+
+ for i in range(len(cores)):
+ self.verify("hello from core %s" % cores[i] in out, "EAL not started on core%s" % cores[i])
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ Nothing to do.
+ """
+ pass
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ Nothing to do.
+ """
+ pass
diff --git a/tests/TestSuite_ieee1588.py b/tests/TestSuite_ieee1588.py
new file mode 100644
index 0000000..09c1729
--- /dev/null
+++ b/tests/TestSuite_ieee1588.py
@@ -0,0 +1,145 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+Test support of IEEE1588 Precise Time Protocol.
+"""
+
+import dcts
+import time
+
+
+from test_case import TestCase
+
+#
+#
+# Test class.
+#
+
+
+class TestIeee1588(TestCase):
+
+ #
+ #
+ #
+ # Test cases.
+ #
+
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+
+
+ IEEE1588 Prerequisites
+ """
+
+ dutPorts = self.dut.get_ports(self.nic)
+ self.verify(len(dutPorts) > 0, "No ports found for " + self.nic)
+
+ # Change the config file to support IEEE1588 and recompile the package.
+ if "bsdapp" in self.target:
+ self.dut.send_expect("sed -i -e 's/IEEE1588=n$/IEEE1588=y/' config/common_bsdapp", "# ", 30)
+ else:
+ self.dut.send_expect("sed -i -e 's/IEEE1588=n$/IEEE1588=y/' config/common_linuxapp", "# ", 30)
+ self.dut.skip_setup = False
+ self.dut.build_install_dpdk(self.target)
+
+ self.dut.send_expect("./%s/app/testpmd -c ffffff -n 3 -- -i --rxpt=0 --rxht=0 --rxwt=0 --txpt=39 --txht=0 --txwt=0" % self.target,
+ "testpmd> ", 100)
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ pass
+
+ def test_ieee1588_enable(self):
+ """
+ IEEE1588 Enable test case.
+ """
+
+ self.dut.send_expect("set fwd ieee1588", "testpmd> ")
+ self.dut.send_expect("start", ">", 5) # Waiting for 'testpmd> ' Fails due to log messages, "Received non PTP packet", in the output
+ time.sleep(1) # Allow the output from the "start" command to finish before looking for a regexp in expect
+
+ # use the first port on that self.nic
+ dutPorts = self.dut.get_ports(self.nic)
+ port = self.tester.get_local_port(dutPorts[0])
+ itf = self.tester.get_interface(port)
+
+ self.tester.scapy_background()
+ self.tester.scapy_append('p = sniff(iface="%s", count=2)' % itf)
+ self.tester.scapy_append('RESULT = p[1].summary()')
+
+ # this is the output of sniff
+ # [<Ether dst=01:1b:19:00:00:00 src=00:00:00:00:00:00 type=0x88f7 |<Raw load='\x00\x02' |>>]
+
+ self.tester.scapy_foreground()
+ self.tester.scapy_append('nutmac="01:1b:19:00:00:00"')
+ self.tester.scapy_append('sendp([Ether(dst=nutmac,type=0x88f7)/"\\x00\\x02"], iface="%s")' % itf)
+ self.tester.scapy_append('time.sleep(1)')
+
+ self.tester.scapy_execute()
+ out = self.tester.scapy_get_result()
+ self.verify("0x88f7" in out, "Ether type is not PTP")
+ # self.verify("\\x00\\x02" in out, "Payload wrong in PTP")
+
+ time.sleep(1)
+ out = self.dut.send_expect("stop", "testpmd> ")
+
+ text = dcts.regexp(out, "(.*) by hardware")
+ self.verify("IEEE1588 PTP V2 SYNC" in text, "Not filtered " + text)
+
+ rx_time = dcts.regexp(out, "RX timestamp value (0x[0-9a-fA-F]+)")
+ tx_time = dcts.regexp(out, "TX timestamp value (0x[0-9a-fA-F]+)")
+
+ self.verify(rx_time is not None, "RX timestamp error ")
+ self.verify(tx_time is not None, "TX timestamp error ")
+ self.verify(int(tx_time, 16) > int(rx_time, 16), "Timestamp mismatch")
+
+ def test_ieee1588_disable(self):
+ """
+ IEEE1588 Disable test case.
+ """
+
+ self.dut.send_expect("stop", "testpmd> ")
+ time.sleep(3)
+
+ # use the first port on that self.nic
+ dutPorts = self.dut.get_ports(self.nic)
+ port = self.tester.get_local_port(dutPorts[0])
+ itf = self.tester.get_interface(port)
+
+ self.tester.scapy_background()
+ self.tester.scapy_append('p = sniff(iface="%s", count=2, timeout=1)' % itf)
+ self.tester.scapy_append('RESULT = p[1].summary()')
+
+ self.tester.scapy_foreground()
+ self.tester.scapy_append('nutmac="01:1b:19:00:00:00"')
+ self.tester.scapy_append('sendp([Ether(dst=nutmac,type=0x88f7)/"\\x00\\x02"], iface="%s")' % itf)
+
+ self.tester.scapy_execute()
+ time.sleep(2)
+
+ out = self.tester.scapy_get_result()
+ self.verify("Ether" not in out, "Ether type is not PTP")
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ """
+ pass
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ self.dut.send_expect("quit", "# ", 30)
+
+ # Restore the config file and recompile the package.
+ if "bsdapp" in self.target:
+ self.dut.send_expect("sed -i -e 's/IEEE1588=y$/IEEE1588=n/' config/common_bsdapp", "# ", 30)
+ else:
+ self.dut.send_expect("sed -i -e 's/IEEE1588=y$/IEEE1588=n/' config/common_linuxapp", "# ", 30)
+ self.dut.build_install_dpdk(self.target)
diff --git a/tests/TestSuite_ip_pipeline.py b/tests/TestSuite_ip_pipeline.py
new file mode 100644
index 0000000..5fade77
--- /dev/null
+++ b/tests/TestSuite_ip_pipeline.py
@@ -0,0 +1,567 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+Test userland 10Gb PMD
+
+"""
+
+from scapy.layers.inet import Ether, IP, TCP
+from scapy.utils import struct, socket, PcapWriter
+from settings import HEADER_SIZE
+from test_case import TestCase
+from time import sleep
+import dcts
+
+#
+#
+# Test class.
+#
+
+
+class TestIPPipeline(TestCase):
+
+ #
+ #
+ # Utility methods and other non-test code.
+ #
+ payload_watermark = 'TestPF'
+
+ frame_sizes = [64, 65, 128, 1024]
+ """Sizes of the frames to be sent"""
+
+ number_of_frames = [1, 3, 63, 64, 65, 127, 128]
+ """Number of frames in the pcap file to be created"""
+
+ incremental_ip_address = [True, False]
+ """True if the IP address is incremented in the frames"""
+
+ inter = [0, 0.7]
+ """Interval between frames sent in seconds"""
+
+ dummy_pcap = 'dummy.pcap'
+
+ def increment_ip_addr(self, ip_address, increment):
+
+ ip2int = lambda ipstr: struct.unpack('!I', socket.inet_aton(ipstr))[0]
+ x = ip2int(ip_address)
+ int2ip = lambda n: socket.inet_ntoa(struct.pack('!I', n))
+ return int2ip(x + increment)
+
+ def create_tcp_ipv4_frame(
+ self, ip_id, src_ip_addr, dst_ip_addr, frame_size,
+ src_mac_addr='00:00:0A:00:0B:00',
+ dst_mac_addr='00:00:0A:00:0A:00'):
+
+ payload_size = frame_size - HEADER_SIZE['eth'] - HEADER_SIZE['ip'] -\
+ HEADER_SIZE['tcp'] - \
+ len(TestIPPipeline.payload_watermark)
+
+ if payload_size < 0:
+ payload_size = 0
+
+ frame = Ether() / IP() / TCP(flags="") / (TestIPPipeline.payload_watermark +
+ "X" * payload_size)
+ frame[Ether].src = src_mac_addr
+ frame[Ether].dst = dst_mac_addr
+
+ frame[IP].src = src_ip_addr
+ frame[IP].dst = dst_ip_addr
+ frame[IP].id = ip_id
+
+ # TCP ports always 0
+ frame[TCP].sport = 0
+ frame[TCP].dport = 0
+
+ return frame
+
+ def create_pcap_file_from_frames(self, file_name, frames):
+
+ writer = PcapWriter(file_name, append=False)
+
+ for frame in frames:
+ writer.write(frame)
+
+ writer.close()
+
+ def create_pcap_file(self, file_name, frame_size, number_of_frames,
+ incremental_ip_address,
+ src_ip="0.0.0.0",
+ dst_ip="0.0.0.0"):
+
+ current_frame = 0
+ writer = PcapWriter(file_name, append=False)
+
+ while current_frame < number_of_frames:
+ ip_id = 0 # current_frame % 0x10000
+
+ frame = self.create_tcp_ipv4_frame(ip_id, src_ip, dst_ip,
+ frame_size)
+ writer.write(frame)
+
+ if incremental_ip_address:
+ dst_ip = self.increment_ip_addr(dst_ip, 1)
+
+ current_frame += 1
+
+ writer.close()
+
+ def enable_pmd_pcap(self, enable=True):
+
+ if enable:
+ self.dut.send_expect(
+ "sed -i 's/CONFIG_RTE_LIBRTE_PMD_PCAP=n$/CONFIG_RTE_LIBRTE_PMD_PCAP=y/' config/defconfig_%s" % self.target, "# ")
+ else:
+ self.dut.send_expect(
+ "sed -i 's/CONFIG_RTE_LIBRTE_PMD_PCAP=y$/CONFIG_RTE_LIBRTE_PMD_PCAP=n/' config/defconfig_%s" % self.target, "# ")
+
+ self.dut.build_install_dpdk(self.target)
+ out = self.dut.build_dpdk_apps("./examples/ip_pipeline")
+ self.verify("Error" not in out, "Compilation error")
+ self.dut.bind_interfaces_linux()
+
+ def start_ip_pipeline(self, ports):
+ command_line = "./examples/ip_pipeline/build/ip_pipeline -c %s -n %d -- -p %s" % \
+ (self.coremask,
+ self.dut.get_memory_channels(),
+ ports)
+
+ out = self.dut.send_expect(command_line, 'pipeline>', 60)
+ sleep(5) # 'Initialization completed' is not the last output, some
+ # seconds are still needed for init.
+
+ self.verify("Aborted" not in out, "Error starting ip_pipeline")
+ self.verify("PANIC" not in out, "Error starting ip_pipeline")
+ self.verify("ERROR" not in out, "Error starting ip_pipeline")
+
+ def start_ip_pipeline_pcap(self, pcap0_file, pcap1_file):
+
+ pcap_config = "'eth_pcap0;rx_pcap=/root/%s;tx_pcap=/tmp/port0out.pcap,eth_pcap1;rx_pcap=/root/%s;tx_pcap=/tmp/port1out.pcap'" % (
+ pcap0_file,
+ pcap1_file)
+
+ command_line = "./examples/ip_pipeline/build/ip_pipeline -c %s -n %d --use-device %s -- -p 0x3" % \
+ (self.coremask,
+ self.dut.get_memory_channels(),
+ pcap_config)
+
+ out = self.dut.send_expect(command_line, 'pipeline>', 60)
+ sleep(5) # 'Initialization completed' is not the last output, some
+ # seconds are still needed for init.
+
+ self.verify("Aborted" not in out, "Error starting ip_pipeline")
+ self.verify("PANIC" not in out, "Error starting ip_pipeline")
+
+ def quit_ip_pipeline(self):
+ self.dut.send_expect("quit", "# ", 5)
+
+ def tcpdump_start_sniffing(self, ifaces=[]):
+ """
+ Starts tcpdump in the background to sniff the tester interface where
+ the packets are transmitted to and from the self.dut.
+ All the captured packets are going to be stored in a file for a
+ post-analysis.
+ """
+
+ for iface in ifaces:
+ command = (
+ 'tcpdump -w tcpdump_{0}.pcap -i {0} 2>tcpdump_{0}.out &').format(iface)
+ self.tester.send_expect(
+ 'rm -f tcpdump_{0}.pcap', '#').format(iface)
+ self.tester.send_expect(command, '#')
+
+ def tcpdump_stop_sniff(self):
+ """
+ Stops the tcpdump process running in the background.
+ """
+
+ self.tester.send_expect('killall tcpdump', '#')
+ # For the [pid]+ Done tcpdump... message after killing the process
+ sleep(1)
+ self.tester.send_expect('echo "Cleaning buffer"', '#')
+ sleep(1)
+
+ def tcpdump_command(self, command, machine):
+ """
+ Sends a tcpdump related command and returns an integer from the output
+ """
+
+ if machine == 'dut':
+ result = self.dut.send_expect(command, '#', alt_session=True)
+ else:
+ result = self.tester.send_expect(command, '#', alt_session=True)
+
+ return int(result.strip())
+
+ def number_of_packets(self, file_name, machine='tester'):
+ """
+ By reading the file generated by tcpdump it counts how many packets were
+ forwarded by the sample app and received in the self.tester. The sample app
+ will add a known MAC address for the test to look for.
+ """
+
+ command = ('tcpdump -A -nn -e -v -r %s 2>/dev/null | grep -c "%s"' %
+ (file_name, TestIPPipeline.payload_watermark))
+ return int(self.tcpdump_command(command, machine))
+
+ def send_and_sniff_pcap_file(self, pcap_file, frames_number, from_port,
+ to_port, inter=0):
+ """
+ Sent frames_number frames from the pcap_file with inter seconds of
+ interval.
+ Returns the number of received frames.
+ """
+
+ tx_port = self.tester.get_local_port(self.dut_ports[from_port])
+ rx_port = self.tester.get_local_port(self.dut_ports[to_port])
+
+ tx_interface = self.tester.get_interface(tx_port)
+ rx_interface = self.tester.get_interface(rx_port)
+
+ self.tcpdump_start_sniffing([tx_interface, rx_interface])
+
+ self.dut.send_expect('link 0 up', 'pipeline>')
+ self.dut.send_expect('link 1 up', 'pipeline>')
+
+ timeout = frames_number * inter + 2
+ inter = ", inter=%d" % inter
+
+ # Prepare the frames to be sent
+ self.tester.scapy_foreground()
+ self.tester.scapy_append('p = rdpcap("%s")' % (pcap_file))
+ self.tester.scapy_append(
+ 'sendp(p[:%s], iface="%s" %s)' % (frames_number,
+ tx_interface,
+ inter))
+
+ # Execute scapy to sniff sniffing and send the frames
+ self.tester.scapy_execute(timeout)
+
+ self.tcpdump_stop_sniff()
+
+ self.dut.send_expect('link 0 down', 'pipeline>')
+ self.dut.send_expect('link 1 down', 'pipeline>')
+
+ rx_stats = self.number_of_packets('tcpdump_%s.pcap' % rx_interface)
+ tx_stats = self.number_of_packets('tcpdump_%s.pcap' % tx_interface)
+
+ # Do not count the sent frames in the tx_interface
+ tx_stats = tx_stats - frames_number
+
+ return {'rx': rx_stats, 'tx': tx_stats}
+
+ def check_results(self, stats, expected):
+ """
+ This function check that the Rx and Tx stats matches the expected.
+ expected = [Rx, Tx]
+ """
+
+ for port in ['rx', 'tx']:
+ self.verify(stats[port] == expected[port],
+ 'Frames expected (%s) and received (%s) mismatch on %s port' % (
+ expected[
+ port],
+ stats[
+ port],
+ port))
+
+ def pipeline_command(self, command):
+ out = self.dut.send_expect(command, 'pipeline>')
+ self.verify("Illegal" not in out, "Pipeline command error 1: '%s'" % command)
+ self.verify("Bad" not in out, "Pipeline command error 2: '%s'" % command)
+ return out
+
+ def pipeline_add_flow(self, port, src_ip, dst_ip, src_port, dst_port,
+ protocol=6):
+ command = 'flow add %s %s %d %d %d %d' % (src_ip, dst_ip, src_port,
+ dst_port, protocol, port)
+ out = self.pipeline_command(command)
+ self.verify("Adding flow" in out, "Add flow error")
+
+ def pipeline_del_flow(self, src_ip, dst_ip, src_port, dst_port,
+ protocol=6):
+ command = 'flow del %s %s %d %d %d' % (src_ip, dst_ip, src_port,
+ dst_port, protocol)
+ out = self.pipeline_command(command)
+ self.verify("Deleting flow" in out, "Del flow error")
+
+ def pipeline_add_route(self, port, src_ip, netmask, gw_ip):
+ command = 'route add %s %d %d %s' % (src_ip, netmask, port, gw_ip)
+ out = self.pipeline_command(command)
+ self.verify("Adding route" in out, "Add route error")
+
+ def pipeline_del_route(self, src_ip, netmask):
+ command = 'route del %s %d' % (src_ip, netmask)
+ out = self.pipeline_command(command)
+ self.verify("Deleting route" in out, "Del route error")
+
+ def pipeline_traffic_burst(self):
+ self.dut.send_expect('link 0 up', 'pipeline>')
+ self.dut.send_expect('link 1 up', 'pipeline>')
+ sleep(0.1)
+ self.dut.send_expect('link 0 down', 'pipeline>')
+ self.dut.send_expect('link 1 down', 'pipeline>')
+
+ #
+ #
+ #
+ # Test cases.
+ #
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+
+ PMD prerequisites.
+ """
+
+ # Check for port availability
+ self.needed_ports = {"niantic": 2}
+ self.dut_ports = self.dut.get_ports(self.nic)
+ self.verify(len(self.dut_ports) >= self.needed_ports[self.nic],
+ "Insufficient ports for speed testing")
+
+ # Enable the support for PCAP Driver
+ self.enable_pmd_pcap()
+ out = self.dut.build_dpdk_apps("./examples/ip_pipeline")
+ self.verify("Error" not in out, "Compilation error")
+
+ self.ports_mask = dcts.create_mask(
+ [self.dut_ports[0], self.dut_ports[1]])
+ self.coremask = "0x3e" # IP Pipeline app requires FIVE cores
+
+ self.dut.setup_memory(4096)
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ pass
+
+ def test_incremental_ip(self):
+ """
+ Testing that frames with incremental IP addresses pass through the
+ pipeline regardless the frames_number and the speed.
+ """
+ pcap_file = 'ip_pipeline.pcap'
+ frame_size = 64
+
+ self.start_ip_pipeline(ports=self.ports_mask)
+ self.dut.send_expect(
+ 'run examples/ip_pipeline/ip_pipeline.sh', 'pipeline>', 10)
+
+ # Create a PCAP file containing the maximum frames_number of frames needed
+ # with fixed size and incremental IP
+ self.create_pcap_file(pcap_file, frame_size,
+ max(TestIPPipeline.number_of_frames), True)
+ self.tester.session.copy_file_to(pcap_file)
+
+ for frames_number in TestIPPipeline.number_of_frames:
+ for inter in TestIPPipeline.inter:
+ print dcts.BLUE(
+ "\tNumber of frames %d, interval %.1f" % (frames_number,
+ inter))
+ stats = self.send_and_sniff_pcap_file(pcap_file, frames_number,
+ 1, 0, inter)
+
+ expected = {'tx': 0, 'rx': frames_number}
+ self.check_results(stats, expected)
+
+ stats = self.send_and_sniff_pcap_file(pcap_file, frames_number,
+ 0, 1, inter)
+
+ expected = {'tx': frames_number, 'rx': 0}
+ self.check_results(stats, expected)
+
+ def test_frame_sizes(self):
+ """
+ Testing that frames with different sizes pass through the pipeline.
+ """
+ pcap_file = 'ip_pipeline.pcap'
+ frames_number = 100
+ inter = 0.5
+
+ self.start_ip_pipeline(ports=self.ports_mask)
+ self.dut.send_expect(
+ 'run examples/ip_pipeline/ip_pipeline.sh', 'pipeline>', 10)
+
+ for frame_size in TestIPPipeline.frame_sizes:
+
+ # Create a PCAP file containing the fixed number of frames above
+ # with variable size and incremental IP
+ self.create_pcap_file(pcap_file, frame_size, 100, True)
+ self.tester.session.copy_file_to(pcap_file)
+
+ print dcts.BLUE("\tFrame size %d, interval %.1f" % (frame_size,
+ inter))
+
+ stats = self.send_and_sniff_pcap_file(pcap_file, frames_number,
+ 1, 0, inter)
+
+ expected = {'tx': 0, 'rx': frames_number}
+ self.check_results(stats, expected)
+
+ stats = self.send_and_sniff_pcap_file(pcap_file, frames_number,
+ 0, 1, inter)
+
+ expected = {'tx': frames_number, 'rx': 0}
+ self.check_results(stats, expected)
+
+ def test_flow_management(self):
+ """
+ Add several flows and check only frames with matching IPs passes
+ """
+ pcap_file = 'ip_pipeline.pcap'
+ frame_size = 64
+
+ default_setup = ['arp add 0 0.0.0.1 0a:0b:0c:0d:0e:0f',
+ 'arp add 1 0.128.0.1 1a:1b:1c:1d:1e:1f',
+ 'route add 0.0.0.0 9 0 0.0.0.1',
+ 'route add 0.128.0.0 9 1 0.128.0.1']
+
+ ip_addrs = [
+ '0.0.0.0', '0.0.0.1', '0.0.0.127', '0.0.0.128', '0.0.0.255',
+ '0.0.1.0', '0.0.127.0', '0.0.128.0', '0.0.129.0', '0.0.255.0',
+ '0.127.0.0', '0.127.1.0', '0.127.127.0', '0.127.255.0',
+ '0.127.255.255']
+
+ frames = []
+
+ for addr in ip_addrs:
+ frames.append(self.create_tcp_ipv4_frame(0, '0.0.0.0', addr,
+ frame_size))
+
+ self.create_pcap_file_from_frames(pcap_file, frames)
+ self.tester.session.copy_file_to(pcap_file)
+
+ # Start ip_pipeline app and setup defaults
+ self.start_ip_pipeline(ports=self.ports_mask)
+ for command in default_setup:
+ self.pipeline_command(command)
+
+ # Check that no traffic pass though
+ stats = self.send_and_sniff_pcap_file(pcap_file, len(frames),
+ 1, 0, 0.2)
+ expected = {'tx': 0, 'rx': 0}
+ self.check_results(stats, expected)
+
+ # Add the flows
+ flows_added = 0
+ for addrs in ip_addrs:
+ self.pipeline_add_flow(1, '0.0.0.0', addrs, 0, 0)
+ flows_added += 1
+
+ # Check that traffic matching flows pass though
+ stats = self.send_and_sniff_pcap_file(pcap_file, len(frames),
+ 1, 0, 0.2)
+ expected = {'tx': 0, 'rx': flows_added}
+ self.check_results(stats, expected)
+
+ # Remove flows
+ for addrs in ip_addrs:
+ self.pipeline_del_flow('0.0.0.0', addrs, 0, 0)
+ flows_added -= 1
+
+ # Check that traffic matching flows pass though
+ stats = self.send_and_sniff_pcap_file(pcap_file, len(frames),
+ 1, 0, 0.2)
+ expected = {'tx': 0, 'rx': flows_added}
+ self.check_results(stats, expected)
+
+ out = self.dut.send_expect('flow print', 'pipeline>')
+ self.verify("=> Port =" not in out, "Flow found after deletion")
+
+ # Check that again no traffic pass though
+ stats = self.send_and_sniff_pcap_file(pcap_file, len(frames),
+ 1, 0, 0.2)
+ expected = {'tx': 0, 'rx': 0}
+ self.check_results(stats, expected)
+
+ self.quit_ip_pipeline()
+
+ def test_route_management(self):
+ """
+ Add several flows and check only frames with matching IPs passes
+ """
+ pcap_file = 'ip_pipeline.pcap'
+ frame_size = 64
+
+ default_setup = ['arp add 0 0.0.0.1 0a:0b:0c:0d:0e:0f',
+ 'arp add 1 0.128.0.1 1a:1b:1c:1d:1e:1f',
+ 'flow add all']
+
+ ip_addrs = [
+ '0.0.0.0', '0.0.0.1', '0.0.0.127', '0.0.0.128', '0.0.0.255',
+ '0.0.1.0', '0.0.127.0', '0.0.128.0', '0.0.129.0', '0.0.255.0',
+ '0.127.0.0', '0.127.1.0', '0.127.127.0', '0.127.255.0',
+ '0.127.255.255']
+
+ frames = []
+
+ for addr in ip_addrs:
+ frames.append(self.create_tcp_ipv4_frame(0, '0.0.0.0', addr,
+ frame_size))
+
+ self.create_pcap_file_from_frames(pcap_file, frames)
+ self.tester.session.copy_file_to(pcap_file)
+
+ # Start ip_pipeline app and setup defaults
+ self.start_ip_pipeline(ports=self.ports_mask)
+ for command in default_setup:
+ self.pipeline_command(command)
+
+ # Check that no traffic pass though
+ stats = self.send_and_sniff_pcap_file(pcap_file, len(frames),
+ 1, 0, 0.2)
+ expected = {'tx': 0, 'rx': 0}
+ self.check_results(stats, expected)
+
+ # Add the routes
+ routes_added = 0
+ for addr in ip_addrs:
+ self.pipeline_add_route(0, addr, 32, '0.0.0.1')
+ routes_added += 1
+
+ # Check that traffic matching routes pass though
+ stats = self.send_and_sniff_pcap_file(pcap_file, len(frames),
+ 1, 0, 0.2)
+
+ expected = {'tx': 0, 'rx': routes_added}
+ self.check_results(stats, expected)
+
+ # Remove routes
+ for addr in ip_addrs:
+ self.pipeline_del_route(addr, 32)
+ routes_added -= 1
+
+ # Check that traffic matching flows pass though
+ stats = self.send_and_sniff_pcap_file(pcap_file, len(frames),
+ 1, 0, 0.2)
+ expected = {'tx': 0, 'rx': routes_added}
+ self.check_results(stats, expected)
+
+ out = self.dut.send_expect('route print', 'pipeline>')
+ self.verify("Destination = " not in out, "Route found after deletion")
+
+ # Check that again no traffic pass though
+ stats = self.send_and_sniff_pcap_file(pcap_file, len(frames),
+ 1, 0, 0.2)
+ expected = {'tx': 0, 'rx': 0}
+ self.check_results(stats, expected)
+
+ self.quit_ip_pipeline()
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ """
+ self.quit_ip_pipeline()
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ # Disable the support for PCAP Driver
+ # self.enable_pmd_pcap(False)
+ out = self.dut.build_dpdk_apps("./examples/ip_pipeline")
+ self.verify("Error" not in out, "Compilation error")
diff --git a/tests/TestSuite_ipfrag.py b/tests/TestSuite_ipfrag.py
new file mode 100644
index 0000000..8f33f7c
--- /dev/null
+++ b/tests/TestSuite_ipfrag.py
@@ -0,0 +1,381 @@
+"""
+DPDK Test suite.
+
+Test IPv4 fragmentation features in DPDK.
+
+"""
+
+import dcts
+import string
+import re
+
+lpm_table_ipv4 = [
+ "{IPv4(100,10,0,0), 16, P2}",
+ "{IPv4(100,20,0,0), 16, P2}",
+ "{IPv4(100,30,0,0), 16, P0}",
+ "{IPv4(100,40,0,0), 16, P0}",
+ "{IPv4(100,50,0,0), 16, P2}",
+ "{IPv4(100,60,0,0), 16, P2}",
+ "{IPv4(100,70,0,0), 16, P0}",
+ "{IPv4(100,80,0,0), 16, P0}",
+]
+
+lpm_table_ipv6 = [
+ "{{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, P2}",
+ "{{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, P2}",
+ "{{3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, P0}",
+ "{{4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, P0}",
+ "{{5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, P2}",
+ "{{6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, P2}",
+ "{{7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, P0}",
+ "{{8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, P0}",
+]
+
+from test_case import TestCase
+
+#
+#
+# Test class.
+#
+
+
+class TestIpfrag(TestCase):
+
+ def portRepl(self, match):
+ """
+ Function to replace P([0123]) pattern in tables
+ """
+
+ portid = match.group(1)
+ self.verify(int(portid) in range(4), "invalid port id")
+ return '%s' % eval("P" + str(portid))
+ #
+ #
+ # Utility methods and other non-test code.
+ #
+ # Insert or move non-test functions here.
+ #
+ #
+ #
+ # Test cases.
+ #
+
+ def set_up_all(self):
+ """
+ ip_fragmentation Prerequisites
+ """
+
+ # Based on h/w type, choose how many ports to use
+ ports = self.dut.get_ports(self.nic)
+ print ports
+
+ # Verify that enough ports are available
+ self.verify(len(ports) >= 4, "Insufficient ports for testing")
+
+ self.ports_socket = self.dut.get_numa_id(ports[0])
+
+ # Verify that enough threads are available
+ cores = self.dut.get_core_list("2S/2C/2T")
+ self.verify(cores is not None, "Insufficient cores for speed testing")
+
+ global P0, P2
+ P0 = ports[0]
+ P2 = ports[2]
+
+ pat = re.compile("P([0123])")
+
+ # Prepare long prefix match table, replace P(x) port pattern
+ lpmStr_ipv4 = "static struct l3fwd_ipv4_route \
+l3fwd_ipv4_route_array[] = {\\\n"
+ rtLpmTbl = list(lpm_table_ipv4)
+ for idx in range(len(rtLpmTbl)):
+ rtLpmTbl[idx] = pat.sub(self.portRepl, rtLpmTbl[idx])
+ lpmStr_ipv4 = lpmStr_ipv4 + ' ' * 4 + rtLpmTbl[idx] + ",\\\n"
+ lpmStr_ipv4 = lpmStr_ipv4 + "};"
+ print lpmStr_ipv4
+ lpmStr_ipv6 = "static struct l3fwd_ipv6_route l3fwd_ipv6_route_array[] = {\\\n"
+ rtLpmTbl = list(lpm_table_ipv6)
+ for idx in range(len(rtLpmTbl)):
+ rtLpmTbl[idx] = pat.sub(self.portRepl, rtLpmTbl[idx])
+ lpmStr_ipv6 = lpmStr_ipv6 + ' ' * 4 + rtLpmTbl[idx] + ",\\\n"
+ lpmStr_ipv6 = lpmStr_ipv6 + "};"
+ print lpmStr_ipv6
+ self.dut.send_expect(r"sed -i '/l3fwd_ipv4_route_array\[\].*{/,/^\}\;/c\\%s' examples/ip_fragmentation/main.c" % lpmStr_ipv4, "# ")
+ self.dut.send_expect(r"sed -i '/l3fwd_ipv6_route_array\[\].*{/,/^\}\;/c\\%s' examples/ip_fragmentation/main.c" % lpmStr_ipv6, "# ")
+ # make application
+ out = self.dut.build_dpdk_apps("examples/ip_fragmentation")
+ self.verify("Error" not in out, "compilation error 1")
+ self.verify("No such file" not in out, "compilation error 2")
+
+ def functional_check_ipv4(self, cores, pkt_sizes, burst=1, flag=None, funtion=None):
+ """
+ Perform functional fragmentation checks.
+ """
+
+ coremask = dcts.create_mask(cores)
+ portmask = dcts.create_mask([P0, P2])
+ numPortThread = len([P0, P2]) / len(cores)
+ result = True
+ errString = ''
+
+ # run ipv4_frag
+ self.dut.send_expect("examples/ip_fragmentation/build/ip_fragmentation -c %s -n %d -- -p %s -q %s" % (
+ coremask, self.dut.get_memory_channels(), portmask, numPortThread), "IP_FRAG:", 120)
+
+ txItf = self.tester.get_interface(self.tester.get_local_port(P0))
+ rxItf = self.tester.get_interface(self.tester.get_local_port(P2))
+ dmac = self.dut.get_mac_address(P0)
+ for size in pkt_sizes[::burst]:
+ # simulate to set TG properties
+ if flag == 'frag':
+ # do fragment
+ expPkts = (1517 + size) / 1518
+ val = 0
+ else:
+ expPkts = 1
+ val = 2
+
+ # set wait packet
+ self.tester.scapy_background()
+ self.tester.scapy_append('import string')
+ self.tester.scapy_append('p = sniff(iface="%s", count=%d)' % (rxItf, expPkts))
+ self.tester.scapy_append('nr_packets=len(p)')
+ self.tester.scapy_append('reslist = [p[i].sprintf("%IP.len%;%IP.id%;%IP.flags%;%IP.frag%") for i in range(nr_packets)]')
+ self.tester.scapy_append('RESULT = string.join(reslist, ",")')
+
+ # send packet
+ self.tester.scapy_foreground()
+ for times in range(burst):
+ self.tester.scapy_append('sendp([Ether(dst="%s")/IP(dst="100.10.0.1",src="1.2.3.4",flags=%d)/Raw(load="X"*%d)], iface="%s")' % (dmac, val, pkt_sizes[pkt_sizes.index(size) + times] - 38, txItf))
+
+ self.tester.scapy_execute()
+ out = self.tester.scapy_get_result()
+ nr_packets = len(out.split(','))
+ if funtion is not None:
+ if not funtion(size, out.split(',')):
+ result = False
+ errString = "failed on fragment check size " + str(size)
+ break
+ elif nr_packets != expPkts:
+ result = False
+ errString = "Failed on forward packet size " + str(size)
+ break
+
+ self.dut.send_expect("^C", "#")
+ # verify on the bottom so as to keep safety quit application
+ self.verify(result, errString)
+
+ def functional_check_ipv6(self, cores, pkt_sizes, burst=1, flag=None, funtion=None):
+ """
+ Perform functional fragmentation checks.
+ """
+ coremask = dcts.create_mask(cores)
+ portmask = dcts.create_mask([P0, P2])
+ numPortThread = len([P0, P2]) / len(cores)
+ result = True
+ errString = ''
+
+ # run ipv4_frag
+ self.dut.send_expect("examples/ip_fragmentation/build/ip_fragmentation -c %s -n %d -- -p %s -q %s" % (
+ coremask, self.dut.get_memory_channels(), portmask, numPortThread), "IP_FRAG:", 120)
+
+ txItf = self.tester.get_interface(self.tester.get_local_port(P0))
+ rxItf = self.tester.get_interface(self.tester.get_local_port(P2))
+ dmac = self.dut.get_mac_address(P0)
+ for size in pkt_sizes[::burst]:
+ # simulate to set TG properties
+ if flag == 'frag':
+ # do fragment
+ expPkts = (1517 + size) / 1518
+ val = 0
+ else:
+ expPkts = 1
+ val = 2
+
+ # set wait packet
+ self.tester.scapy_background()
+ self.tester.scapy_append('import string')
+ self.tester.scapy_append('p = sniff(iface="%s", count=%d)' % (rxItf, expPkts))
+ self.tester.scapy_append('nr_packets=len(p)')
+ self.tester.scapy_append('reslist = [p[i].sprintf("%IPv6.plen%;%IPv6.id%;%IPv6ExtHdrFragment.m%;%IPv6ExtHdrFragment.offset%") for i in range(nr_packets)]')
+ self.tester.scapy_append('RESULT = string.join(reslist, ",")')
+
+ # send packet
+ self.tester.scapy_foreground()
+ for times in range(burst):
+ self.tester.scapy_append('sendp([Ether(dst="%s")/IPv6(dst="101:101:101:101:101:101:101:101",src="ee80:ee80:ee80:ee80:ee80:ee80:ee80:ee80")/Raw(load="X"*%d)], iface="%s")' % (dmac, pkt_sizes[pkt_sizes.index(size) + times] - 58, txItf))
+
+ self.tester.scapy_execute()
+ out = self.tester.scapy_get_result()
+ nr_packets = len(out.split(','))
+ if funtion is not None:
+ if not funtion(size, out.split(',')):
+ result = False
+ errString = "failed on fragment check size " + str(size)
+ break
+ elif nr_packets != expPkts:
+ result = False
+ errString = "Failed on forward packet size " + str(size)
+ break
+
+ self.dut.send_expect("^C", "#")
+ # verify on the bottom so as to keep safety quit application
+ self.verify(result, errString)
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ pass
+
+ def test_ipfrag_normalfwd(self):
+ """
+ Normal forward with 64, 128, 256, 512, 1024, 1518.
+ """
+
+ sizelist = [64, 128, 256, 512, 1024, 1518]
+ cores = self.dut.get_core_list("1S/1C/2T")
+
+ self.functional_check_ipv4(cores, sizelist)
+ self.functional_check_ipv6(cores, sizelist)
+
+ def test_ipfrag_nofragment(self):
+ """
+ Don't fragment test with 1519
+ """
+
+ sizelist = [1519, 1518]
+ cores = self.dut.get_core_list("1S/1C/2T")
+ self.tester.send_expect("ifconfig %s mtu 9200" % self.tester.get_interface(self.tester.get_local_port(P0)), "#")
+ self.tester.send_expect("ifconfig %s mtu 9200" % self.tester.get_interface(self.tester.get_local_port(P2)), "#")
+
+ self.functional_check_ipv4(cores, sizelist, 2, 'nofrag')
+ self.functional_check_ipv6(cores, sizelist, 2, 'nofrag')
+ self.tester.send_expect("ifconfig %s mtu 1500" % self.tester.get_interface(self.tester.get_local_port(P0)), "#")
+ self.tester.send_expect("ifconfig %s mtu 1500" % self.tester.get_interface(self.tester.get_local_port(P2)), "#")
+
+ def test_ipfrag_fragment(self):
+ """
+ Fragment test with more than 1519 packet sizes.
+ """
+
+ sizelist = [1519, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000]
+ cores = self.dut.get_core_list("1S/1C/2T")
+
+ self.tester.send_expect("ifconfig %s mtu 9200" % self.tester.get_interface(self.tester.get_local_port(P0)), "#")
+ self.tester.send_expect("ifconfig %s mtu 9200" % self.tester.get_interface(self.tester.get_local_port(P2)), "#")
+
+ def chkfunc(size, output):
+ # check total size
+ if (1517 + size) / 1518 != len(output):
+ return False
+
+ # check every field in packet
+ for pkt in output:
+ _, _, _, _ = pkt.split(';')
+ # length, ID, fragoff, flags
+ pass
+ return True
+
+ self.functional_check_ipv4(cores, sizelist, 1, 'frag', chkfunc)
+ self.functional_check_ipv6(cores, sizelist, 1, 'frag', chkfunc)
+ self.tester.send_expect("ifconfig %s mtu 1500" % self.tester.get_interface(self.tester.get_local_port(P0)), "#")
+ self.tester.send_expect("ifconfig %s mtu 1500" % self.tester.get_interface(self.tester.get_local_port(P2)), "#")
+
+ def benchmark(self, index, lcore, num_pthreads, size_list):
+ """
+ Just Test IPv4 Throughput for selected parameters.
+ """
+
+ Bps = dict()
+ Pps = dict()
+ Pct = dict()
+
+ if int(lcore[0]) == 1:
+ core_mask = dcts.create_mask(self.dut.get_core_list(lcore, socket=self.ports_socket))
+ else:
+ core_mask = dcts.create_mask(self.dut.get_core_list(lcore))
+
+ portmask = dcts.create_mask([P0, P2])
+
+ self.dut.send_expect("examples/ip_fragmentation/build/ip_fragmentation -c %s -n %d -- -p %s -q %s" % (
+ core_mask, self.dut.get_memory_channels(), portmask, num_pthreads), "IP_FRAG:", 120)
+
+ result = [2, lcore, num_pthreads]
+ for size in size_list:
+ dmac = self.dut.get_mac_address(P0)
+ flows = ['Ether(dst="%s")/IP(src="1.2.3.4", dst="100.10.0.1", flags=0)/("X"*%d)' % (dmac, size - 38),
+ 'Ether(dst="%s")/IP(src="1.2.3.4", dst="100.20.0.1", flags=0)/("X"*%d)' % (dmac, size - 38),
+ 'Ether(dst="%s")/IPv6(dst="101:101:101:101:101:101:101:101",src="ee80:ee80:ee80:ee80:ee80:ee80:ee80:ee80")/Raw(load="X"*%d)' % (dmac, size - 58),
+ 'Ether(dst="%s")/IPv6(dst="201:101:101:101:101:101:101:101",src="ee80:ee80:ee80:ee80:ee80:ee80:ee80:ee80")/Raw(load="X"*%d)' % (dmac, size - 58)]
+ self.tester.scapy_append('wrpcap("test1.pcap", [%s])' % string.join(flows, ','))
+
+ # reserved for rx/tx bidirection test
+ dmac = self.dut.get_mac_address(P2)
+ flows = ['Ether(dst="%s")/IP(src="1.2.3.4", dst="100.30.0.1", flags=0)/("X"*%d)' % (dmac, size - 38),
+ 'Ether(dst="%s")/IP(src="1.2.3.4", dst="100.40.0.1", flags=0)/("X"*%d)' % (dmac, size - 38),
+ 'Ether(dst="%s")/IPv6(dst="301:101:101:101:101:101:101:101",src="ee80:ee80:ee80:ee80:ee80:ee80:ee80:ee80")/Raw(load="X"*%d)' % (dmac, size - 58),
+ 'Ether(dst="%s")/IPv6(dst="401:101:101:101:101:101:101:101",src="ee80:ee80:ee80:ee80:ee80:ee80:ee80:ee80")/Raw(load="X"*%d)' % (dmac, size - 58)]
+ self.tester.scapy_append('wrpcap("test2.pcap", [%s])' % string.join(flows, ','))
+
+ self.tester.scapy_execute()
+
+ tgenInput = []
+ tgenInput.append((self.tester.get_local_port(P0), self.tester.get_local_port(P2), "test1.pcap"))
+ tgenInput.append((self.tester.get_local_port(P2), self.tester.get_local_port(P0), "test2.pcap"))
+
+ factor = (size + 1517) / 1518
+ # wireSpd = 2 * 10000.0 / ((20 + size) * 8)
+ Bps[str(size)], Pps[str(size)] = self.tester.traffic_generator_throughput(tgenInput)
+ self.verify(Pps[str(size)] > 0, "No traffic detected")
+ Pps[str(size)] *= 1.0 / factor / 1000000
+ Pct[str(size)] = (1.0 * Bps[str(size)] * 100) / (2 * 10000000000)
+
+ result.append(Pps[str(size)])
+ result.append(Pct[str(size)])
+
+ dcts.results_table_add_row(result)
+
+ self.dut.send_expect("^C", "#")
+
+ def test_perf_ipfrag_throughtput(self):
+ """
+ Performance test for 64, 1518, 1519, 2k and 9k.
+ """
+
+ self.verify(self.nic == 'niantic', "throughtput case require niantic 10Gb self.nic")
+ self.tester.send_expect("ifconfig %s mtu 9600" % self.tester.get_interface(self.tester.get_local_port(P0)), "#")
+ self.tester.send_expect("ifconfig %s mtu 9600" % self.tester.get_interface(self.tester.get_local_port(P2)), "#")
+
+ sizes = [64, 1518, 1519, 2000, 9000]
+
+ tblheader = ["Ports", "S/C/T", "SW threads"]
+ for size in sizes:
+ tblheader.append("%dB Mpps" % size)
+ tblheader.append("%d" % size)
+
+ dcts.results_table_add_header(tblheader)
+
+ lcores = [("1S/1C/1T", 2), ("1S/1C/2T", 2), ("1S/2C/1T", 2), ("2S/1C/1T", 2)]
+ index = 1
+ for (lcore, numThr) in lcores:
+ self.benchmark(index, lcore, numThr, sizes)
+ index += 1
+
+ dcts.results_table_print()
+
+ self.tester.send_expect("ifconfig %s mtu 1500" % self.tester.get_interface(self.tester.get_local_port(P0)), "#")
+ self.tester.send_expect("ifconfig %s mtu 1500" % self.tester.get_interface(self.tester.get_local_port(P2)), "#")
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ """
+ pass
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ self.dut.send_expect("^C", "#")
+ pass
diff --git a/tests/TestSuite_jumboframes.py b/tests/TestSuite_jumboframes.py
new file mode 100644
index 0000000..a563769
--- /dev/null
+++ b/tests/TestSuite_jumboframes.py
@@ -0,0 +1,226 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+Test the support of Jumbo Frames by Poll Mode Drivers
+
+"""
+
+import dcts
+import re
+from time import sleep
+
+from test_case import TestCase
+from pmd_output import PmdOutput
+
+#
+#
+# Test class.
+#
+
+
+class TestJumboframes(TestCase):
+ #
+ #
+ # Utility methods and other non-test code.
+ #
+
+ # Insert or move non-test functions here.
+
+ def jumboframes_get_stat(self, portid, rx_tx):
+ """
+ Get packets number from port statistic
+ """
+ stats = self.pmdout.get_pmd_stats(portid)
+ if rx_tx == "rx":
+ return [stats['RX-packets'], stats['RX-errors'], stats['RX-bytes']]
+ elif rx_tx == "tx":
+ return [stats['TX-packets'], stats['TX-errors'], stats['TX-bytes']]
+ else:
+ return None
+
+ def jumboframes_send_packet(self, pktsize, received=True):
+ """
+ Send 1 packet to portid
+ """
+
+ gp0tx_pkts, _, gp0tx_bytes = [int(_) for _ in self.jumboframes_get_stat(self.dut_ports[0], "tx")]
+ gp1rx_pkts, gp1rx_err, gp1rx_bytes = [int(_) for _ in self.jumboframes_get_stat(self.dut_ports[1], "rx")]
+
+ itf = self.tester.get_interface(self.tester.get_local_port(self.dut_ports[1]))
+ mac = self.dut.get_mac_address(self.dut_ports[1])
+
+ pktlen = pktsize - 18
+ padding = pktlen - 20
+
+ self.tester.scapy_foreground()
+ self.tester.scapy_append('nutmac="%s"' % mac)
+ self.tester.scapy_append('sendp([Ether(dst=nutmac, src="52:00:00:00:00:00")/IP(len=%s)/Raw(load="\x50"*%s)], iface="%s")' % (pktlen, padding, itf))
+
+ out = self.tester.scapy_execute()
+ sleep(5)
+
+ p0tx_pkts, _, p0tx_bytes = [int(_) for _ in self.jumboframes_get_stat(self.dut_ports[0], "tx")]
+ # p0tx_pkts, p0tx_err, p0tx_bytes
+ p1rx_pkts, p1rx_err, p1rx_bytes = [int(_) for _ in self.jumboframes_get_stat(self.dut_ports[1], "rx")]
+
+ p0tx_pkts -= gp0tx_pkts
+ p0tx_bytes -= gp0tx_bytes
+ p1rx_pkts -= gp1rx_pkts
+ p1rx_bytes -= gp1rx_bytes
+ p1rx_err -= gp1rx_err
+
+ if received:
+ self.verify(p0tx_pkts == p1rx_pkts and p0tx_bytes == pktsize and p1rx_bytes == pktsize,
+ "packet pass assert error")
+
+ else:
+ self.verify(p0tx_pkts == p1rx_pkts and (p1rx_err == 1 or p1rx_pkts == 0),
+ "packet drop assert error")
+
+ return out
+
+ #
+ #
+ #
+ # Test cases.
+ #
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+
+
+ Dynamic config Prerequistites
+ """
+
+ self.dut_ports = self.dut.get_ports(self.nic)
+ self.verify(len(self.dut_ports) >= 2, "Insufficient ports")
+
+ cores = self.dut.get_core_list('1S/2C/2T')
+ self.coremask = dcts.create_mask(cores)
+
+ self.port_mask = dcts.create_mask([self.dut_ports[0], self.dut_ports[1]])
+
+ self.tester.send_expect("ifconfig %s mtu %s" % (self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0])), 9200), "# ")
+ self.tester.send_expect("ifconfig %s mtu %s" % (self.tester.get_interface(self.tester.get_local_port(self.dut_ports[1])), 9200), "# ")
+
+ self.pmdout = PmdOutput(self.dut)
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ pass
+
+ def test_jumboframes_normal_nojumbo(self):
+ """
+ Dynamic config default mode test
+ """
+
+ self.dut.kill_all()
+
+ cmd = r"./%s/build/app/test-pmd/testpmd -c%s -n 3 -- -i --rxd=1024 --txd=1024 \
+ --burst=144 --txpt=32 --txht=0 --txfreet=0 --rxfreet=64 \
+ --mbcache=200 --portmask=%s --mbuf-size=2048 --max-pkt-len=1518" % (self.target, self.coremask, self.port_mask)
+
+ self.dut.send_expect(cmd, "testpmd> ", 120)
+
+ self.dut.send_expect("start", "testpmd> ")
+
+ self.jumboframes_send_packet(1517)
+ self.jumboframes_send_packet(1518)
+
+ self.dut.send_expect("stop", "testpmd> ")
+ self.dut.send_expect("quit", "# ", 30)
+
+ def test_jumboframes_jumbo_nojumbo(self):
+ """
+ Dynamic config diable promiscuous test
+ """
+
+ self.dut.kill_all()
+
+ cmd = r"./%s/build/app/test-pmd/testpmd -c%s -n 3 -- -i --rxd=1024 --txd=1024 \
+ --burst=144 --txpt=32 --txht=8 --txwt=0 --txfreet=0 --rxfreet=64 \
+ --mbcache=200 --portmask=%s --mbuf-size=2048 --max-pkt-len=1518" % (self.target, self.coremask, self.port_mask)
+
+ self.dut.send_expect(cmd, "testpmd> ", 120)
+ self.dut.send_expect("start", "testpmd> ")
+
+ self.jumboframes_send_packet(1519, False)
+
+ self.dut.send_expect("stop", "testpmd> ")
+ self.dut.send_expect("quit", "# ", 30)
+
+ def test_jumboframes_normal_jumbo(self):
+ """
+ Dynamic config enable promiscuous test
+ """
+
+ self.dut.kill_all()
+
+ cmd = r"./%s/build/app/test-pmd/testpmd -c%s -n 3 -- -i --rxd=1024 --txd=1024 \
+ --burst=144 --txpt=32 --txht=8 --txwt=0 --txfreet=0 --rxfreet=64 \
+ --mbcache=200 --portmask=%s --mbuf-size=2048 --max-pkt-len=%s" % (self.target, self.coremask, self.port_mask, 9000)
+
+ self.dut.send_expect(cmd, "testpmd> ", 120)
+ self.dut.send_expect("start", "testpmd> ")
+
+ self.jumboframes_send_packet(1517)
+ self.jumboframes_send_packet(1518)
+
+ self.dut.send_expect("stop", "testpmd> ")
+ self.dut.send_expect("quit", "# ", 30)
+
+ def test_jumboframes_jumbo_jumbo(self):
+ """
+ Dynamic config enable promiscuous test
+ """
+
+ self.dut.kill_all()
+
+ cmd = r"./%s/build/app/test-pmd/testpmd -c%s -n 3 -- -i --rxd=1024 --txd=1024 \
+ --burst=144 --txpt=32 --txht=8 --txwt=0 --txfreet=0 --rxfreet=64 \
+ --mbcache=200 --portmask=%s --mbuf-size=2048 --max-pkt-len=%s" % (self.target, self.coremask, self.port_mask, 9000)
+
+ self.dut.send_expect(cmd, "testpmd> ", 120)
+ self.dut.send_expect("start", "testpmd> ")
+
+ self.jumboframes_send_packet(1519)
+ self.jumboframes_send_packet(9000 - 1)
+ self.jumboframes_send_packet(9000)
+
+ self.dut.send_expect("stop", "testpmd> ")
+ self.dut.send_expect("quit", "# ", 30)
+
+ def test_jumboframes_bigger_jumbo(self):
+ """
+ Dynamic config enable promiscuous test
+ """
+
+ self.dut.kill_all()
+
+ cmd = r"./%s/build/app/test-pmd/testpmd -c%s -n 3 -- -i --rxd=1024 --txd=1024 \
+ --burst=144 --txpt=32 --txht=8 --txwt=0 --txfreet=0 --rxfreet=64 \
+ --mbcache=200 --portmask=%s --mbuf-size=2048 --max-pkt-len=%s" % (
+ self.target, self.coremask, self.port_mask, 9000)
+
+ self.dut.send_expect(cmd, "testpmd> ", 120)
+ self.dut.send_expect("start", "testpmd> ")
+
+ self.jumboframes_send_packet(9000 + 1, False)
+
+ self.dut.send_expect("quit", "# ", 30)
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ """
+ pass
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ pass
diff --git a/tests/TestSuite_l2fwd.py b/tests/TestSuite_l2fwd.py
new file mode 100644
index 0000000..6233330
--- /dev/null
+++ b/tests/TestSuite_l2fwd.py
@@ -0,0 +1,215 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+Test Layer-2 Forwarding support
+
+"""
+
+import dcts
+from test_case import TestCase
+from plotting import Plotting
+from settings import HEADER_SIZE
+
+#
+#
+# Test class.
+#
+
+
+class TestL2fwd(TestCase):
+
+ #
+ #
+ # Utility methods and other non-test code.
+ #
+
+ def plot_results(self):
+
+ queues = []
+ queues_results = []
+
+ for test_queues in self.test_queues:
+ queues.append(str(test_queues['queues']))
+ results = []
+ for frame_size in self.frame_sizes:
+ results.append(test_queues['pct'][frame_size])
+ queues_results.append(results)
+
+ image_path = self.plotting.create_bars_plot(
+ 'test_perf_l2fwd',
+ 'L2fwd, %d ports' % self.number_of_ports,
+ self.frame_sizes,
+ queues_results,
+ ylabel='% linerate',
+ legend=queues)
+
+ dcts.results_plot_print(image_path)
+
+ #
+ #
+ #
+ # Test cases.
+ #
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+
+ L2fwd prerequisites.
+ """
+ self.frame_sizes = [64, 65, 128, 256, 512, 1024, 1280, 1518]
+
+ self.test_queues = [{'queues': 1, 'Mpps': {}, 'pct': {}},
+ {'queues': 2, 'Mpps': {}, 'pct': {}},
+ {'queues': 4, 'Mpps': {}, 'pct': {}},
+ {'queues': 8, 'Mpps': {}, 'pct': {}}
+ ]
+
+ self.core_config = "1S/4C/1T"
+ self.number_of_ports = 2
+ self.headers_size = HEADER_SIZE['eth'] + HEADER_SIZE['ip'] + \
+ HEADER_SIZE['udp']
+
+ self.dut_ports = self.dut.get_ports_performance(self.nic)
+
+ self.verify(len(self.dut_ports) >= self.number_of_ports,
+ "Not enough ports for " + self.nic)
+
+ self.ports_socket = self.dut.get_numa_id(self.dut_ports[0])
+
+ # compile
+ out = self.dut.build_dpdk_apps("./examples/l2fwd")
+ self.verify("Error" not in out, "Compilation error")
+ self.verify("No such" not in out, "Compilation error")
+
+ self.table_header = ['Frame']
+ for queue in self.test_queues:
+ self.table_header.append("%d queues Mpps" % queue['queues'])
+ self.table_header.append("% linerate")
+
+ dcts.results_table_add_header(self.table_header)
+ self.plotting = Plotting(self.dut.crb['name'], self.target, self.nic)
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ pass
+
+ def quit_l2fwd(self):
+ self.dut.send_expect("fg", "l2fwd ", 5)
+ self.dut.send_expect("^C", "# ", 5)
+
+ def test_port_testing(self):
+ """
+ Check port forwarding.
+ """
+ # the cases use the first two ports
+ port_mask = dcts.create_mask([self.dut_ports[0], self.dut_ports[1]])
+
+ self.dut.send_expect("./examples/l2fwd/build/app/l2fwd -n 1 -c f -- -q 8 -p %s &" % port_mask, "L2FWD: entering main loop", 60)
+
+ for i in [0, 1]:
+ tx_port = self.tester.get_local_port(self.dut_ports[i])
+ rx_port = self.tester.get_local_port(self.dut_ports[1 - i])
+
+ tx_interface = self.tester.get_interface(tx_port)
+ rx_interface = self.tester.get_interface(rx_port)
+
+ self.tester.scapy_background()
+ self.tester.scapy_append('p = sniff(iface="%s", count=1)' % rx_interface)
+ self.tester.scapy_append('number_packets=len(p)')
+ self.tester.scapy_append('RESULT = str(number_packets)')
+
+ self.tester.scapy_foreground()
+ self.tester.scapy_append('sendp([Ether()/IP()/UDP()/("X"*46)], iface="%s")' % tx_interface)
+
+ self.tester.scapy_execute()
+ number_packets = self.tester.scapy_get_result()
+ self.verify(number_packets == "1", "Failed to switch L2 frame")
+
+ self.quit_l2fwd()
+
+ def test_perf_l2fwd_performance(self):
+ """
+ Benchmark performance for frame_sizes.
+ """
+ ports = []
+ for port in xrange(self.number_of_ports):
+ ports.append(self.dut_ports[port])
+
+ port_mask = dcts.create_mask(ports)
+ core_mask = dcts.create_mask(self.dut.get_core_list(self.core_config,
+ socket=self.ports_socket))
+
+ for frame_size in self.frame_sizes:
+
+ payload_size = frame_size - self.headers_size
+
+ tgen_input = []
+ for port in xrange(self.number_of_ports):
+ rx_port = self.tester.get_local_port(self.dut_ports[port % self.number_of_ports])
+ tx_port = self.tester.get_local_port(self.dut_ports[(port + 1) % self.number_of_ports])
+ destination_mac = self.dut.get_mac_address(self.dut_ports[(port + 1) % self.number_of_ports])
+ self.tester.scapy_append('wrpcap("l2fwd_%d.pcap", [Ether(dst="%s")/IP()/UDP()/("X"*%d)])' % (
+ port, destination_mac, payload_size))
+
+ tgen_input.append((tx_port, rx_port, "l2fwd_%d.pcap" % port))
+
+ self.tester.scapy_execute()
+
+ for queues in self.test_queues:
+
+ command_line = "./examples/l2fwd/build/app/l2fwd -n %d -c %s -- -q %s -p %s &" % \
+ (self.dut.get_memory_channels(), core_mask,
+ str(queues['queues']), port_mask)
+
+ self.dut.send_expect(command_line, "memory mapped", 60)
+
+ info = "Executing l2fwd using %s queues, frame size %d and %s setup.\n" % \
+ (queues['queues'], frame_size, self.core_config)
+
+ self.logger.info(info)
+ dcts.report(info, annex=True)
+ dcts.report(command_line + "\n\n", frame=True, annex=True)
+ _, pps = self.tester.traffic_generator_throughput(tgen_input)
+ Mpps = pps / 1000000.0
+ queues['Mpps'][frame_size] = Mpps
+ queues['pct'][frame_size] = Mpps * 100 / float(self.wirespeed(
+ self.nic,
+ frame_size,
+ self.number_of_ports))
+
+ self.quit_l2fwd()
+
+ # Look for transmission error in the results
+ for frame_size in self.frame_sizes:
+ for n in range(len(self.test_queues)):
+ self.verify(self.test_queues[n]['Mpps'][frame_size] > 0,
+ "No traffic detected")
+
+ # Prepare the results for table and plot printing
+ for frame_size in self.frame_sizes:
+ results_row = []
+ results_row.append(frame_size)
+ for queue in self.test_queues:
+ results_row.append(queue['Mpps'][frame_size])
+ results_row.append(queue['pct'][frame_size])
+
+ dcts.results_table_add_row(results_row)
+
+ self.plot_results()
+ dcts.results_table_print()
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ """
+ pass
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ pass
diff --git a/tests/TestSuite_l3fwd.py b/tests/TestSuite_l3fwd.py
new file mode 100644
index 0000000..2753631
--- /dev/null
+++ b/tests/TestSuite_l3fwd.py
@@ -0,0 +1,602 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+
+Layer-3 forwarding test script.
+"""
+
+import dcts
+import string
+import re
+from plotting import Plotting
+from test_case import TestCase
+from exception import VerifyFailure
+from settings import HEADER_SIZE
+
+
+#
+#
+# Test class.
+#
+
+
+class TestL3fwd(TestCase):
+
+ path = "./examples/l3fwd/build/"
+
+ test_cases_2_ports = {"1S/1C/1T": "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{1.1.0}), (P1,0,C{1.1.0})'",
+ "1S/1C/2T": "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{1.1.0}), (P1,0,C{1.1.1})'",
+ "1S/2C/1T": "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{1.1.0}), (P1,0,C{1.2.0})'"
+ }
+
+ test_cases_4_ports = [(1, "1S/1C/1T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{1.1.0}),(P1,0,C{1.1.0}),(P2,0,C{1.1.0}),(P3,0,C{1.1.0})'"),
+ (1, "1S/1C/2T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{1.1.0}),(P1,0,C{1.1.0}),(P2,0,C{1.1.1}),(P3,0,C{1.1.1})'"),
+ (1, "1S/2C/1T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{1.1.0}),(P1,0,C{1.1.0}),(P2,0,C{1.2.0}),(P3,0,C{1.2.0})'"),
+ (1, "1S/2C/2T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{1.1.0}),(P1,0,C{1.1.1}),(P2,0,C{1.2.0}),(P3,0,C{1.2.1})'"),
+ (1, "1S/4C/1T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{1.1.0}),(P1,0,C{1.2.0}),(P2,0,C{1.3.0}),(P3,0,C{1.4.0})'"),
+ (1, "2S/1C/1T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{0.1.0}),(P1,0,C{0.1.0}),(P2,0,C{1.1.0}),(P3,0,C{1.1.0})'"),
+ (1, "2S/1C/2T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{0.1.0}),(P1,0,C{0.1.1}),(P2,0,C{1.1.0}),(P3,0,C{1.1.1})'"),
+ (1, "2S/2C/1T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{0.1.0}),(P1,0,C{0.2.0}),(P2,0,C{1.1.0}),(P3,0,C{1.2.0})'"),
+ (2, "1S/1C/1T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{1.1.0}),(P0,1,C{1.1.0}),(P1,0,C{1.1.0}),(P1,1,C{1.1.0}),(P2,0,C{1.1.0}),(P2,1,C{1.1.0}),(P3,0,C{1.1.0}),(P3,1,C{1.1.0})'"),
+ (2, "1S/1C/2T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{1.1.0}),(P0,1,C{1.1.0}),(P1,0,C{1.1.0}),(P1,1,C{1.1.0}),(P2,0,C{1.1.1}),(P2,1,C{1.1.1}),(P3,0,C{1.1.1}),(P3,1,C{1.1.1})'"),
+ (2, "1S/2C/1T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{1.1.0}),(P0,1,C{1.1.0}),(P1,0,C{1.1.0}),(P1,1,C{1.1.0}),(P2,0,C{1.2.0}),(P2,1,C{1.2.0}),(P3,0,C{1.2.0}),(P3,1,C{1.2.0})'"),
+ (2, "1S/2C/2T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{1.1.0}),(P0,1,C{1.1.0}),(P1,0,C{1.1.1}),(P1,1,C{1.1.1}),(P2,0,C{1.2.0}),(P2,1,C{1.2.0}),(P3,0,C{1.2.1}),(P3,1,C{1.2.1})'"),
+ (2, "1S/4C/1T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{1.1.0}),(P0,1,C{1.1.0}),(P1,0,C{1.2.0}),(P1,1,C{1.2.0}),(P2,0,C{1.3.0}),(P2,1,C{1.3.0}),(P3,0,C{1.4.0}),(P3,1,C{1.4.0})'"),
+ (2, "1S/4C/2T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{1.1.0}),(P0,1,C{1.1.1}),(P1,0,C{1.2.0}),(P1,1,C{1.2.1}),(P2,0,C{1.3.0}),(P2,1,C{1.3.1}),(P3,0,C{1.4.0}),(P3,1,C{1.4.1})'"),
+ (2, "2S/1C/1T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{0.1.0}),(P0,1,C{0.1.0}),(P1,0,C{0.1.0}),(P1,1,C{0.1.0}),(P2,0,C{1.1.0}),(P2,1,C{1.1.0}),(P3,0,C{1.1.0}),(P3,1,C{1.1.0})'"),
+ (2, "2S/1C/2T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{0.1.0}),(P0,1,C{0.1.0}),(P1,0,C{0.1.1}),(P1,1,C{0.1.1}),(P2,0,C{1.1.0}),(P2,1,C{1.1.0}),(P3,0,C{1.1.1}),(P3,1,C{1.1.1})'"),
+ (2, "2S/2C/1T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{0.1.0}),(P0,1,C{0.1.0}),(P1,0,C{0.2.0}),(P1,1,C{0.2.0}),(P2,0,C{1.1.0}),(P2,1,C{1.1.0}),(P3,0,C{1.2.0}),(P3,1,C{1.2.0})'"),
+ (2, "2S/2C/2T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{0.1.0}),(P0,1,C{0.1.1}),(P1,0,C{0.2.0}),(P1,1,C{0.2.1}),(P2,0,C{1.1.0}),(P2,1,C{1.1.1}),(P3,0,C{1.2.0}),(P3,1,C{1.2.1})'"),
+ (2, "2S/4C/1T",
+ "%s -c %s -n %d -- -p %s -P --config '(P0,0,C{0.1.0}),(P0,1,C{0.2.0}),(P1,0,C{0.3.0}),(P1,1,C{0.4.0}),(P2,0,C{1.1.0}),(P2,1,C{1.2.0}),(P3,0,C{1.3.0}),(P3,1,C{1.4.0})'")
+ ]
+
+ queues_4_ports = []
+
+ for case in test_cases_4_ports:
+ if case[0] * 4 not in queues_4_ports:
+ queues_4_ports.append(case[0] * 4)
+
+ host_table = [
+ "{{IPv4(10,100,0,1), IPv4(1,2,3,4), 1, 10, IPPROTO_UDP}, P0}",
+ "{{IPv4(10,101,0,1), IPv4(1,2,3,4), 1, 10, IPPROTO_UDP}, P0}",
+ "{{IPv4(11,100,0,1), IPv4(1,2,3,4), 1, 11, IPPROTO_UDP}, P1}",
+ "{{IPv4(11,101,0,1), IPv4(1,2,3,4), 1, 11, IPPROTO_UDP}, P1}",
+ "{{IPv4(12,100,0,1), IPv4(1,2,3,4), 1, 12, IPPROTO_UDP}, P2}",
+ "{{IPv4(12,101,0,1), IPv4(1,2,3,4), 1, 12, IPPROTO_UDP}, P2}",
+ "{{IPv4(13,100,0,1), IPv4(1,2,3,4), 1, 13, IPPROTO_UDP}, P3}",
+ "{{IPv4(13,101,0,1), IPv4(1,2,3,4), 1, 13, IPPROTO_UDP}, P3}",
+ ]
+
+ lpm_table = [
+ "{IPv4(10,100,0,0), 24, P0}",
+ "{IPv4(10,101,0,0), 24, P0}",
+ "{IPv4(11,100,0,0), 24, P1}",
+ "{IPv4(11,101,0,0), 24, P1}",
+ "{IPv4(12,100,0,0), 24, P2}",
+ "{IPv4(12,101,0,0), 24, P2}",
+ "{IPv4(13,100,0,0), 24, P3}",
+ "{IPv4(13,101,0,0), 24, P3}",
+ ]
+
+ frame_sizes = [64] # , 65, 128]
+
+ methods = ['lpm', 'exact']
+
+ #
+ #
+ # Utility methods and other non-test code.
+ #
+ # Insert or move non-test functions here.
+ def portRepl(self, match):
+ """
+ Function to replace P([0123]) pattern in tables
+ """
+
+ portid = match.group(1)
+ self.verify(int(portid) in range(4), "invalid port id")
+ if int(portid) >= len(valports):
+ return '0'
+ else:
+ return '%s' % valports[int(portid)]
+
+ #
+ #
+ #
+ # Test cases.
+ #
+
+ def plot_4_ports(self):
+
+ data = self.l3fwd_test_results['data']
+
+ # Create a plot for each number of queues for frame size and mode comparison
+ cores = '1S/1C/1T'
+ for queues in TestL3fwd.queues_4_ports:
+ ydata = []
+ lpm_ydata = []
+ exact_ydata = []
+ for frame_size in TestL3fwd.frame_sizes:
+ for row in data:
+ if row[1] * 4 == queues and row[2] == cores and \
+ row[0] == frame_size:
+ if len(TestL3fwd.methods) == 2:
+ lpm_ydata.append(row[4])
+ exact_ydata.append(row[6])
+ else:
+ if 'lpm' in TestL3fwd.methods:
+ lpm_ydata.append(row[4])
+ if 'exact' in TestL3fwd.methods:
+ exact_ydata.append(row[4])
+
+ if 'lpm' in TestL3fwd.methods:
+ ydata.append(lpm_ydata)
+ if 'exact' in TestL3fwd.methods:
+ ydata.append(exact_ydata)
+
+ if len(ydata[0]) == 0:
+ self.logger.warning('No data for plotting 1S/1C/1T')
+ break
+ else:
+ try:
+ image_path = self.plotting.create_bars_plot(
+ 'test_perf_l3fwd_4ports_1S_1C_1T_%dRxQ' % queues,
+ 'LPM & Exact modes, 1S/1C/1T, %d Rx Queues, 4 ports' % queues,
+ TestL3fwd.frame_sizes,
+ ydata,
+ ylabel='% linerate',
+ legend=TestL3fwd.methods)
+
+ dcts.results_plot_print(image_path, 50)
+ except VerifyFailure as e:
+ self.logger.error(str(e))
+
+ # Create a plot for each number of queues for core config and mode comparison
+ frame_size = TestL3fwd.frame_sizes[0] # Frame size fixed to the first selected
+ for queues in TestL3fwd.queues_4_ports:
+
+ cores = []
+ for row in data:
+ if row[2] not in cores and \
+ row[1] * 4 == queues:
+ cores.append(row[2])
+
+ ydata = []
+ lpm_ydata = []
+ exact_ydata = []
+
+ for core in cores:
+ for row in data:
+ if row[1] * 4 == queues and \
+ row[2] == core and \
+ row[0] == frame_size:
+ if len(TestL3fwd.methods) == 2:
+ lpm_ydata.append(row[4])
+ exact_ydata.append(row[6])
+ else:
+ if 'lpm' in TestL3fwd.methods:
+ lpm_ydata.append(row[4])
+ if 'exact' in TestL3fwd.methods:
+ exact_ydata.append(row[4])
+
+ if 'lpm' in TestL3fwd.methods:
+ ydata.append(lpm_ydata)
+ if 'exact' in TestL3fwd.methods:
+ ydata.append(exact_ydata)
+
+ try:
+ image_path = self.plotting.create_bars_plot(
+ 'test_perf_l3fwd_4ports_%d_%dRxQ' % (frame_size, queues),
+ 'LPM & Exact modes, %dB, %d Rx Queues, 4 ports' % (frame_size, queues),
+ cores,
+ ydata,
+ ylabel='% linerate',
+ legend=TestL3fwd.methods)
+
+ dcts.results_plot_print(image_path)
+ except VerifyFailure as e:
+ self.logger.error(str(e))
+
+ def plot_2_ports(self):
+
+ data = self.l3fwd_test_results['data']
+
+ cores = []
+ for row in data:
+ if row[2] not in cores:
+ cores.append(row[2])
+
+ # Create a plot for each mode for frame size and cores comparison
+ for mode in TestL3fwd.methods:
+ mode_ydata = []
+
+ for core in cores:
+ core_ydata = []
+ for row in data:
+ if row[5] == mode and row[2] == core:
+ core_ydata.append(float(row[4]))
+
+ mode_ydata.append(core_ydata)
+
+ image_path = self.plotting.create_bars_plot(
+ 'test_perf_l3fwd_2ports_%s' % mode,
+ 'L3fwd %s mode, 2 ports' % mode,
+ TestL3fwd.frame_sizes,
+ mode_ydata,
+ ylabel='% linerate',
+ legend=cores)
+
+ dcts.results_plot_print(image_path, 50)
+
+ # If testing only one mode, do nothing else.
+ if len(TestL3fwd.methods) == 1:
+ return
+
+ # Create a plot for 1st core config for mode and frame size comparison
+ core = '1S/1C/1T'
+
+ ydata = []
+ for mode in TestL3fwd.methods:
+ mode_ydata = []
+ for frame_size in TestL3fwd.frame_sizes:
+ for row in data:
+ if row[2] == core and row[0] == frame_size and \
+ row[5] == mode:
+ mode_ydata.append(float(row[4]))
+
+ ydata.append(mode_ydata)
+
+ str_frame_sizes = []
+ for frame_size in TestL3fwd.frame_sizes:
+ str_frame_sizes.append(str(frame_size))
+
+ image_path = self.plotting.create_bars_plot(
+ 'test_perf_l3fwd_2ports_1S_1C_1T',
+ 'L3fwd 1S/1C/1T cores, 2 ports',
+ TestL3fwd.frame_sizes,
+ ydata,
+ ylabel='% linerate',
+ legend=TestL3fwd.methods)
+
+ dcts.results_plot_print(image_path)
+
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+
+
+ L3fwd Prerequisites
+ """
+ # Based on h/w type, choose how many ports to use
+ ports = self.dut.get_ports(self.nic, socket=1)
+ if not ports:
+ ports = self.dut.get_ports(self.nic, socket=0)
+
+ # Verify that enough ports are available
+ self.verify(len(ports) >= 2, "Insufficient ports for speed testing")
+
+ # Verify that enough threads are available
+ cores = self.dut.get_core_list("2S/4C/2T")
+ self.verify(cores is not None, "Insufficient cores for speed testing")
+
+ global valports
+ valports = [_ for _ in ports if self.tester.get_local_port(_) != -1]
+ self.verify(len(valports) >= 2, "Insufficient active ports for speed testing")
+
+ pat = re.compile("P([0123])")
+
+ # Prepare long prefix match table, replace P(x) port pattern
+ lpmStr = "static struct ipv4_l3fwd_route ipv4_l3fwd_route_array[] = {\\\n"
+ for idx in range(len(TestL3fwd.lpm_table)):
+ TestL3fwd.lpm_table[idx] = pat.sub(self.portRepl, TestL3fwd.lpm_table[idx])
+ lpmStr = lpmStr + ' ' * 4 + TestL3fwd.lpm_table[idx] + ",\\\n"
+ lpmStr = lpmStr + "};"
+ self.logger.debug(lpmStr)
+
+ # Prepare host route table, replace P(x) port pattern
+ exactStr = "static struct ipv4_l3fwd_route ipv4_l3fwd_route_array[] = {\\\n"
+ for idx in range(len(TestL3fwd.host_table)):
+ TestL3fwd.host_table[idx] = pat.sub(self.portRepl, TestL3fwd.host_table[idx])
+ exactStr = exactStr + ' ' * 4 + TestL3fwd.host_table[idx] + ",\\\n"
+ exactStr = exactStr + "};"
+ self.logger.debug(exactStr)
+
+ # Compile l3fwd with LPM lookup.
+ self.dut.send_expect(r"sed -i '/ipv4_l3fwd_route_array\[\].*{/,/^\}\;/c\\%s' examples/l3fwd/main.c" % lpmStr, "# ")
+ out = self.dut.build_dpdk_apps("./examples/l3fwd", "USER_FLAGS=-DAPP_LOOKUP_METHOD=1")
+ self.verify("Error" not in out, "compilation error 1")
+ self.verify("No such file" not in out, "compilation error 2")
+
+ # Backup the LPM exe and clean up the build.
+ self.dut.send_expect("mv -f examples/l3fwd/build/l3fwd examples/l3fwd/build/l3fwd_lpm", "# ")
+ out = self.dut.send_expect("make clean -C examples/l3fwd", "# ")
+
+ # Compile l3fwd with hash/exact lookup.
+ self.dut.send_expect(r"sed -i -e '/ipv4_l3fwd_route_array\[\].*{/,/^\}\;/c\\%s' examples/l3fwd/main.c" % exactStr, "# ")
+ out = self.dut.build_dpdk_apps("./examples/l3fwd", "USER_FLAGS=-DAPP_LOOKUP_METHOD=0")
+
+ self.verify("Error" not in out, "compilation error 1")
+ self.verify("No such file" not in out, "compilation error 2")
+
+ # Backup the Hash/Exact exe.
+ self.dut.send_expect("mv -f examples/l3fwd/build/l3fwd examples/l3fwd/build/l3fwd_exact", "# ")
+
+ self.l3fwd_test_results = {'header': [],
+ 'data': []}
+
+ self.plotting = Plotting(self.dut.crb['name'], self.target, self.nic)
+
+ def flows(self):
+ """
+ Return a list of packets that implements the flows described in the
+ l3fwd test plan.
+
+ """
+ return [
+ 'IP(src="1.2.3.4",dst="10.100.0.1")/UDP(sport=10,dport=1)',
+ 'IP(src="1.2.3.4",dst="10.101.0.1")/UDP(sport=10,dport=1)',
+ 'IP(src="1.2.3.4",dst="11.100.0.1")/UDP(sport=11,dport=1)',
+ 'IP(src="1.2.3.4",dst="11.101.0.1")/UDP(sport=11,dport=1)',
+ 'IP(src="1.2.3.4",dst="12.100.0.1")/UDP(sport=12,dport=1)',
+ 'IP(src="1.2.3.4",dst="12.101.0.1")/UDP(sport=12,dport=1)',
+ 'IP(src="1.2.3.4",dst="13.100.0.1")/UDP(sport=13,dport=1)',
+ 'IP(src="1.2.3.4",dst="13.101.0.1")/UDP(sport=13,dport=1)']
+
+ def repl(self, match):
+ pid = match.group(1)
+ qid = match.group(2)
+ self.logger.debug("%s\n" % match.group(3))
+ lcid = self.dut.get_lcore_id(match.group(3))
+ self.logger.debug("%s\n" % lcid)
+
+ global corelist
+ corelist.append(int(lcid))
+
+ self.verify(int(pid) in range(4), "invalid port id")
+ self.verify(lcid, "invalid thread id")
+
+ return '%s,%s,%s' % (str(valports[int(pid)]), qid, lcid)
+
+ def get_throughput(self, frame_size, rx_queues_per_port, cores_config, command_line):
+ """
+ Get the throughput for a test case from test_cases_4_ports.
+ """
+
+ output_pattern = re.compile("P([0123]),([0123]),(C\{\d.\d.\d\})")
+
+ bps = dict()
+ pps = dict()
+ pct = dict()
+
+ global corelist
+ corelist = []
+
+ while output_pattern.search(command_line):
+ command_line = output_pattern.sub(self.repl, command_line)
+
+ self.logger.debug("%s\n" % str(corelist))
+ core_mask = dcts.create_mask(set(corelist))
+
+ # First, measure by two different methods
+ for method in TestL3fwd.methods:
+ # start l3fwd
+ method_command_line = command_line % (TestL3fwd.path + "l3fwd_" + method,
+ core_mask,
+ self.dut.get_memory_channels(),
+ dcts.create_mask(valports[:4]))
+
+ dcts.report(method_command_line + "\n", frame=True, annex=True)
+
+ out = self.dut.send_expect(method_command_line, "L3FWD:", 120)
+
+ # measure test
+ tgen_input = []
+ for rxPort in range(4):
+ if rxPort % 2 == 0:
+ tx_interface = self.tester.get_local_port(valports[rxPort + 1])
+ else:
+ tx_interface = self.tester.get_local_port(valports[rxPort - 1])
+
+ rx_interface = self.tester.get_local_port(valports[rxPort])
+ tgen_input.append((tx_interface, rx_interface, "dst%d.pcap" % valports[rxPort]))
+
+ # FIX ME
+ bps[method], pps[method] = self.tester.traffic_generator_throughput(tgen_input)
+ self.verify(pps[method] > 0, "No traffic detected")
+ pps[method] /= 1000000.0
+ pct[method] = pps[method] * 100 / float(self.wirespeed(self.nic,
+ frame_size,
+ 4))
+
+ # stop l3fwd
+ self.dut.send_expect("^C", "#")
+
+ data_row = [frame_size, rx_queues_per_port, cores_config]
+ for method in TestL3fwd.methods:
+ data_row.append(pps[method])
+ data_row.append(pct[method])
+
+ # generate report table
+ dcts.results_table_add_row(data_row)
+ self.l3fwd_test_results['data'].append(data_row)
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ pass
+
+ def test_perf_l3fwd_4ports(self):
+ """
+ L3fwd main 4 ports.
+ """
+
+ # Based on h/w type, choose how many ports to use
+ ports = self.dut.get_ports(self.nic)
+ # Verify that enough ports are available
+ self.verify(len(ports) >= 4, "Insufficient ports for speed testing")
+
+ header_row = ["Frame size", "RX Queues/NIC Port", "S/C/T"]
+
+ for method in TestL3fwd.methods:
+ header_row.append('%s Mpps' % method)
+ header_row.append('% linerate')
+
+ dcts.results_table_add_header(header_row)
+ self.l3fwd_test_results['header'] = header_row
+ self.l3fwd_test_results['data'] = []
+
+ for frame_size in TestL3fwd.frame_sizes:
+
+ # Prepare traffic flow
+ payload_size = frame_size - HEADER_SIZE['udp'] - \
+ HEADER_SIZE['ip'] - HEADER_SIZE['eth']
+
+ for _port in range(4):
+ dmac = self.dut.get_mac_address(valports[_port])
+ flows = ['Ether(dst="%s")/%s/("X"*%d)' % (dmac, flow, payload_size) for flow in self.flows()[_port * 2:(_port + 1) * 2]]
+ self.tester.scapy_append('wrpcap("dst%d.pcap", [%s])' % (valports[_port], string.join(flows, ',')))
+
+ self.tester.scapy_execute()
+
+ dcts.report("Flows for 4 ports, %d frame size.\n" % (frame_size),
+ annex=True)
+ dcts.report("%s" % string.join(flows, '\n'),
+ frame=True, annex=True)
+
+ # Get the number of sockets of the board
+ number_sockets = self.dut.send_expect("grep \"processor\|physical id\|core id\|^$\" /proc/cpuinfo | grep physical | sort -u | wc -l", "# ")
+ number_sockets = int(number_sockets.split('\r\n')[0])
+
+ # Run case by case
+ for test_case in TestL3fwd.test_cases_4_ports:
+
+ # Check if the board has sockets enough for the test case
+ if number_sockets >= int(test_case[1].split('/')[0][0]):
+ self.get_throughput(frame_size, *test_case)
+
+ self.plot_4_ports()
+ dcts.results_table_print()
+
+ def test_perf_l3fwd_2ports(self):
+ """
+ L3fwd main 2 ports.
+ """
+
+ header_row = ["Frame", "Ports", "S/C/T", "Mpps", "% linerate", "mode"]
+ self.l3fwd_test_results['header'] = header_row
+ dcts.results_table_add_header(header_row)
+ self.l3fwd_test_results['data'] = []
+
+ for frame_size in TestL3fwd.frame_sizes:
+
+ # Prepare traffic flow
+ payload_size = frame_size - HEADER_SIZE['udp'] - \
+ HEADER_SIZE['ip'] - HEADER_SIZE['eth']
+
+ flows = ['Ether()/%s/("X"*%d)' % (flow, payload_size) for flow in self.flows()[:4]]
+
+ dcts.report("Flows for 2 ports, %d frame size.\n" % (frame_size),
+ annex=True)
+ dcts.report("%s" % string.join(flows, '\n'),
+ frame=True, annex=True)
+
+ self.tester.scapy_append('wrpcap("test2ports.pcap", [%s])' % string.join(flows, ','))
+ self.tester.scapy_execute()
+
+ # Prepare the command line
+ global corelist
+ pat = re.compile("P([0123]),([0123]),(C\{\d.\d.\d\})")
+ coreMask = {}
+ rtCmdLines = dict(TestL3fwd.test_cases_2_ports)
+ for key in rtCmdLines.keys():
+ corelist = []
+ while pat.search(rtCmdLines[key]):
+ rtCmdLines[key] = pat.sub(self.repl, rtCmdLines[key])
+ self.logger.info("%s\n" % str(corelist))
+ coreMask[key] = dcts.create_mask(set(corelist))
+
+ # measure by two different mode
+ for mode in TestL3fwd.methods:
+
+ # start l3fwd
+ index = 0
+ subtitle = []
+ for cores in rtCmdLines.keys():
+
+ info = "Executing l3fwd using %s mode, 2 ports, %s and %d frame size.\n" % (
+ mode, cores, frame_size)
+
+ self.logger.info(info)
+ dcts.report(info, annex=True)
+
+ subtitle.append(cores)
+ cmdline = rtCmdLines[cores] % (TestL3fwd.path + "l3fwd_" + mode, coreMask[cores],
+ self.dut.get_memory_channels(), dcts.create_mask(valports[:2]))
+
+ dcts.report(cmdline + "\n", frame=True, annex=True)
+
+ out = self.dut.send_expect(cmdline, "L3FWD:", 120)
+
+ # Measure test
+ tgenInput = []
+ for rxPort in range(2):
+ # No use on rx/tx limitation
+ if rxPort % 2 == 0:
+ txIntf = self.tester.get_local_port(valports[rxPort + 1])
+ else:
+ txIntf = self.tester.get_local_port(valports[rxPort - 1])
+
+ rxIntf = self.tester.get_local_port(valports[rxPort])
+
+ tgenInput.append((txIntf, rxIntf, "test2ports.pcap"))
+
+ _, pps = self.tester.traffic_generator_throughput(tgenInput)
+ self.verify(pps > 0, "No traffic detected")
+ pps /= 1000000.0
+ linerate = self.wirespeed(self.nic, frame_size, 2)
+ pct = pps * 100 / linerate
+
+ index += 1
+
+ # Stop l3fwd
+ self.dut.send_expect("^C", "#")
+
+ data_row = [frame_size, 2, cores, str(pps), str(pct), mode]
+ dcts.results_table_add_row(data_row)
+ self.l3fwd_test_results['data'].append(data_row)
+
+ self.plot_2_ports()
+ dcts.results_table_print()
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ """
+ pass
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ pass
diff --git a/tests/TestSuite_link_flowctrl.py b/tests/TestSuite_link_flowctrl.py
new file mode 100644
index 0000000..98ff84b
--- /dev/null
+++ b/tests/TestSuite_link_flowctrl.py
@@ -0,0 +1,407 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+Test for Ethernet Link Flow Control Features by Poll Mode Drivers
+
+"""
+
+import dcts
+import re
+
+from time import sleep
+from test_case import TestCase
+
+#
+#
+# Test class.
+#
+
+
+class TestLinkFlowctrl(TestCase):
+
+ #
+ #
+ #
+ # Test cases.
+ #
+ pause_frame_dst = "01:80:C2:00:00:01"
+ pause_frame_type = "0x8808"
+ pause_frame_opcode = "\\x00\\x01"
+ pause_frame_control = "\\x00\\xFF"
+ pause_frame_paddign = "\\x00" * 42
+
+ pause_frame = '[Ether(src="%s",dst="%s",type=%s)/("%s%s%s")]'
+
+ frames_to_sent = 10
+
+ packet_size = 66 # 66 allows frame loss
+ ip_header_size = 20
+ udp_header_size = 8
+ eth_header_size = 18
+ payload_size = packet_size - eth_header_size - ip_header_size - udp_header_size
+
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+
+ Link flow control Prerequisites
+ """
+
+ self.dutPorts = self.dut.get_ports(self.nic)
+ self.verify(len(self.dutPorts) > 1, "Insuficient ports")
+
+ self.rx_port = self.dutPorts[0]
+ self.tester_tx_mac = self.tester.get_mac(self.tester.get_local_port(self.rx_port))
+
+ self.tx_port = self.dutPorts[1]
+
+ self.portMask = dcts.create_mask([self.rx_port, self.tx_port])
+ self.memChannels = self.dut.get_memory_channels()
+
+ cmdline = "./%s/app/testpmd -c ffffff -n %s -- -i --burst=1" % (self.target, self.memChannels) + \
+ "--txpt=32 --txht=8 --txwt=0 --txfreet=0 --mbcache=250 --portmask=%s" % self.portMask
+
+ self.dut.send_expect(cmdline, "testpmd> ", 120)
+
+ def pause_frame_loss_test(self, rx_flow_control='off',
+ tx_flow_control='off',
+ pause_frame_fwd='off'):
+
+ tester_tx_port = self.tester.get_local_port(self.rx_port)
+ tester_rx_port = self.tester.get_local_port(self.tx_port)
+
+ tgenInput = []
+ tgenInput.append((tester_tx_port, tester_rx_port, "test.pcap"))
+
+ self.dut.send_expect("set flow_ctrl rx %s tx %s 300 50 10 1 mac_ctrl_frame_fwd %s autoneg on %d " % (
+ rx_flow_control,
+ tx_flow_control,
+ pause_frame_fwd,
+ self.rx_port),
+ "testpmd> ")
+
+ self.dut.send_expect("set fwd csum", "testpmd> ")
+ self.dut.send_expect("start", "testpmd> ")
+
+ self.tester.scapy_append('wrpcap("test.pcap",[Ether()/IP()/UDP()/("X"*%d)])' %
+ TestLinkFlowctrl.payload_size)
+
+ self.tester.scapy_execute()
+
+ # Run traffic generator
+ result = self.tester.traffic_generator_loss(tgenInput, 100)
+ self.dut.send_expect("stop", "testpmd> ")
+
+ return result
+
+ def get_testpmd_port_stats(self, ports):
+ """
+ Returns the number of packets transmitted and received from testpmd.
+ Uses testpmd show port stats.
+ """
+
+ rx_pattern = "RX-packets: (\d*)"
+ tx_pattern = "TX-packets: (\d*)"
+ rx = re.compile(rx_pattern)
+ tx = re.compile(tx_pattern)
+
+ port_stats = {}
+
+ for port in ports:
+ out = self.dut.send_expect("show port stats %d" % port,
+ "testpmd> ")
+
+ rx_packets = int(rx.search(out).group(1))
+ tx_packets = int(tx.search(out).group(1))
+
+ port_stats[port] = (rx_packets, tx_packets)
+
+ return port_stats
+
+ def pause_frame_test(self, frame, flow_control='off',
+ pause_frame_fwd='off'):
+ """
+ Sets testpmd flow control and mac ctrl frame fwd according to the
+ parameters, starts forwarding and clears the stats, then sends the
+ passed frame and stops forwarding.
+ Returns the testpmd port stats.
+ """
+
+ tester_tx_port = self.tester.get_local_port(self.rx_port)
+ tx_interface = self.tester.get_interface(tester_tx_port)
+ tester_rx_port = self.tester.get_local_port(self.tx_port)
+
+ tgenInput = []
+ tgenInput.append((tester_tx_port, tester_rx_port, "test.pcap"))
+
+ self.dut.send_expect("set flow_ctrl rx %s tx %s 300 50 10 1 mac_ctrl_frame_fwd %s autoneg on %d " % (
+ flow_control,
+ flow_control,
+ pause_frame_fwd,
+ self.rx_port),
+ "testpmd> ")
+
+ self.dut.send_expect("set fwd io", "testpmd> ")
+ self.dut.send_expect("start", "testpmd> ")
+ self.dut.send_expect("clear port stats all", "testpmd> ")
+
+ self.tester.scapy_foreground()
+ self.tester.scapy_append('sendp(%s, iface="%s", count=%d)' % (frame,
+ tx_interface,
+ TestLinkFlowctrl.frames_to_sent))
+
+ self.tester.scapy_execute()
+
+ # The following sleep is needed to allow all the packets to arrive.
+ # 1s works for Crown Pass (FC18) DUT, Lizard Head Pass (FC14) tester
+ # using Niantic. Increase it in case of packet loosing.
+ sleep(1)
+
+ self.dut.send_expect("stop", "testpmd> ")
+
+ port_stats = self.get_testpmd_port_stats((self.rx_port, self.tx_port))
+
+ return port_stats
+
+ def check_pause_frame_test_result(self, result, expected_rx=False, expected_fwd=False):
+ """
+ Verifies the test results (use pause_frame_test before) against
+ the expected behavior.
+ """
+ print "Result (port, rx, tx) %s, expected rx %s, expected fwd %s" % (result,
+ expected_rx,
+ expected_fwd)
+
+ if expected_rx:
+ self.verify(result[self.rx_port][0] == TestLinkFlowctrl.frames_to_sent,
+ "Pause Frames are not being received by testpmd (%d received)" %
+ result[self.rx_port][0])
+ if expected_fwd:
+ self.verify(result[self.tx_port][1] == TestLinkFlowctrl.frames_to_sent,
+ "Pause Frames are not being forwarded by testpmd (%d sent)" % (
+ result[self.tx_port][1]))
+ else:
+ self.verify(result[self.tx_port][1] == 0,
+ "Pause Frames are being forwarded by testpmd (%d sent)" % (
+ result[self.tx_port][1]))
+ else:
+ self.verify(result[self.rx_port][0] == 0,
+ "Pause Frames are being received by testpmd (%d received)" %
+ result[self.rx_port][0])
+
+ def build_pause_frame(self, option=0):
+ """
+ Build the PAUSE Frame for the tests. 3 available options:
+ 0: Correct frame (correct src and dst addresses and opcode)
+ 1: Wrong source frame (worng src, correct and dst address and opcode)
+ 2: Wrong opcode frame (correct src and dst address and wrong opcode)
+ 3: Wrong destination frame (correct src and opcode, wrong dst address)
+ """
+
+ if option == 1:
+ return TestLinkFlowctrl.pause_frame % ("00:01:02:03:04:05",
+ TestLinkFlowctrl.pause_frame_dst,
+ TestLinkFlowctrl.pause_frame_type,
+ TestLinkFlowctrl.pause_frame_opcode,
+ TestLinkFlowctrl.pause_frame_control,
+ TestLinkFlowctrl.pause_frame_paddign)
+
+ elif option == 2:
+ return TestLinkFlowctrl.pause_frame % (self.tester_tx_mac,
+ TestLinkFlowctrl.pause_frame_dst,
+ TestLinkFlowctrl.pause_frame_type,
+ "\\x00\\x02",
+ TestLinkFlowctrl.pause_frame_control,
+ TestLinkFlowctrl.pause_frame_paddign)
+ elif option == 3:
+ return TestLinkFlowctrl.pause_frame % (self.tester_tx_mac,
+ "01:80:C2:00:AB:10",
+ TestLinkFlowctrl.pause_frame_type,
+ TestLinkFlowctrl.pause_frame_opcode,
+ TestLinkFlowctrl.pause_frame_control,
+ TestLinkFlowctrl.pause_frame_paddign)
+
+ return TestLinkFlowctrl.pause_frame % (self.tester_tx_mac,
+ TestLinkFlowctrl.pause_frame_dst,
+ TestLinkFlowctrl.pause_frame_type,
+ TestLinkFlowctrl.pause_frame_opcode,
+ TestLinkFlowctrl.pause_frame_control,
+ TestLinkFlowctrl.pause_frame_paddign)
+
+ def test_flowctrl_off_pause_fwd_off(self):
+ """
+ Flow control disabled, MAC PAUSE frame forwarding disabled.
+ PAUSE Frames must not be received by testpmd
+ """
+
+ pause_frames = [self.build_pause_frame(0),
+ self.build_pause_frame(1),
+ self.build_pause_frame(2),
+ self.build_pause_frame(3)]
+
+ for frame in pause_frames:
+ port_stats = self.pause_frame_test(frame)
+ self.check_pause_frame_test_result(port_stats)
+
+ def test_flowctrl_on_pause_fwd_off(self):
+ """
+ Flow control enabled, MAC PAUSE frame forwarding disabled.
+ PAUSE Frames must not be received by testpmd
+ """
+
+ pause_frames = [self.build_pause_frame(0),
+ self.build_pause_frame(1),
+ self.build_pause_frame(2),
+ self.build_pause_frame(3)]
+
+ for frame in pause_frames:
+ port_stats = self.pause_frame_test(frame, flow_control='on')
+ self.check_pause_frame_test_result(port_stats)
+
+ def test_flowctrl_off_pause_fwd_on(self):
+ """
+ Flow control disabled, MAC PAUSE frame forwarding enabled.
+ All PAUSE Frames must be forwarded by testpmd.
+ """
+
+ # Regular frames, check for no frames received
+ pause_frame = self.build_pause_frame()
+ port_stats = self.pause_frame_test(pause_frame, pause_frame_fwd='on')
+ self.check_pause_frame_test_result(port_stats, True, True)
+
+ # Wrong src MAC, check for no frames received
+ pause_frame = self.build_pause_frame(1)
+ port_stats = self.pause_frame_test(pause_frame, pause_frame_fwd='on')
+ self.check_pause_frame_test_result(port_stats, True, True)
+
+ # Unrecognized frames (wrong opcode), check for all frames received and fwd
+ pause_frame = self.build_pause_frame(2)
+ port_stats = self.pause_frame_test(pause_frame, pause_frame_fwd='on')
+ self.check_pause_frame_test_result(port_stats, True, True)
+
+ # Wrong dst MAC, check for all frames received
+ pause_frame = self.build_pause_frame(3)
+ port_stats = self.pause_frame_test(pause_frame, pause_frame_fwd='on')
+ self.check_pause_frame_test_result(port_stats, True, True)
+
+ def test_flowctrl_on_pause_fwd_on(self):
+ """
+ Flow control enabled, MAC PAUSE frame forwarding enabled.
+ Only unrecognized PAUSE Frames must be forwarded by testpmd.
+ """
+
+ # Regular frames, check for no frames received
+ pause_frame = self.build_pause_frame()
+ port_stats = self.pause_frame_test(pause_frame, flow_control='on',
+ pause_frame_fwd='on')
+ self.check_pause_frame_test_result(port_stats)
+
+ # Wrong src MAC, check for no frames received
+ pause_frame = self.build_pause_frame(1)
+ port_stats = self.pause_frame_test(pause_frame, flow_control='on',
+ pause_frame_fwd='on')
+ self.check_pause_frame_test_result(port_stats)
+
+ # Unrecognized frames (wrong opcode), check for all frames received and fwd
+ pause_frame = self.build_pause_frame(2)
+ port_stats = self.pause_frame_test(pause_frame, flow_control='on',
+ pause_frame_fwd='on')
+ self.check_pause_frame_test_result(port_stats, True, True)
+
+ # Wrong dst MAC, check for all frames received
+ pause_frame = self.build_pause_frame(3)
+ port_stats = self.pause_frame_test(pause_frame, flow_control='on',
+ pause_frame_fwd='on')
+ self.check_pause_frame_test_result(port_stats, True, True)
+
+ def test_perf_flowctrl_on_pause_fwd_on(self):
+ """
+ Disable link flow control and PAUSE frame forwarding
+ """
+
+ result = self.pause_frame_loss_test(rx_flow_control='on',
+ tx_flow_control='on',
+ pause_frame_fwd='on')
+
+ print "Packet loss: %.3f%%" % result
+
+ self.verify(result <= 0.01,
+ "Link flow control fail, the loss percent is more than 1%")
+
+ def test_perf_flowctrl_on_pause_fwd_off(self):
+ """
+ Disable link flow control and enable PAUSE frame forwarding
+ """
+
+ result = self.pause_frame_loss_test(rx_flow_control='on',
+ tx_flow_control='on',
+ pause_frame_fwd='off')
+
+ print "Packet loss: %.3f%%" % result
+
+ self.verify(result <= 0.01,
+ "Link flow control fail, the loss percent is more than 1%")
+
+ def test_perf_flowctrl_rx_on(self):
+ """
+ Enable only rx link flow control
+ """
+
+ result = self.pause_frame_loss_test(rx_flow_control='on',
+ tx_flow_control='on',
+ pause_frame_fwd='off')
+
+ print "Packet loss: %.3f%%" % result
+
+ self.verify(result <= 0.01,
+ "Link flow control fail, the loss percent is more than 1%")
+
+ def test_perf_flowctrl_off_pause_fwd_on(self):
+ """
+ Enable link flow control and disable PAUSE frame forwarding
+ """
+
+ result = self.pause_frame_loss_test(rx_flow_control='off',
+ tx_flow_control='off',
+ pause_frame_fwd='on')
+
+ print "Packet loss: %.3f%%" % result
+
+ self.verify(result >= 0.5,
+ "Link flow control fail, the loss percent is less than 50%")
+
+ def test_perf_flowctrl_off_pause_fwd_off(self):
+ """
+ Disable link flow control and PAUSE frame forwarding
+ """
+
+ result = self.pause_frame_loss_test(rx_flow_control='off',
+ tx_flow_control='off',
+ pause_frame_fwd='off')
+
+ print "Packet loss: %.3f%%" % result
+
+ self.verify(result >= 0.5,
+ "Link flow control fail, the loss percent is less than 50%")
+
+ def test_perf_flowctrl_tx_on(self):
+ """
+ Disable link flow control and PAUSE frame forwarding
+ """
+
+ result = self.pause_frame_loss_test(rx_flow_control='off',
+ tx_flow_control='on',
+ pause_frame_fwd='off')
+
+ print "Packet loss: %.3f%%" % result
+
+ self.verify(result <= 0.01,
+ "Link flow control fail, the loss percent is more than 1%")
+
+ def tear_down_all(self):
+ """
+ Run after each test case.
+ """
+ self.dut.send_expect("quit", "# ")
diff --git a/tests/TestSuite_multiprocess.py b/tests/TestSuite_multiprocess.py
new file mode 100644
index 0000000..3fbc31e
--- /dev/null
+++ b/tests/TestSuite_multiprocess.py
@@ -0,0 +1,258 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+Multi-process Test.
+
+"""
+
+import dcts
+import time
+from etgen import IxiaPacketGenerator
+
+executions = []
+from test_case import TestCase
+
+#
+#
+# Test class.
+#
+
+
+class TestMultiprocess(TestCase, IxiaPacketGenerator):
+
+ #
+ #
+ #
+ # Test cases.
+ #
+
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+
+ Multiprocess prerequisites.
+ Requirements:
+ OS is not freeBSD
+ DUT core number >= 4
+ multi_process build pass
+ """
+ self.verify('bsdapp' not in self.target, "Multiprocess not support freebsd")
+
+ self.verify(len(self.dut.get_all_cores()) >= 4, "Not enough Cores")
+ self.tester.extend_external_packet_generator(TestMultiprocess, self)
+
+ out = self.dut.build_dpdk_apps("./examples/multi_process/")
+ self.verify('Error' not in out, "Compilation failed")
+
+ executions.append({'nprocs': 1, 'cores': '1S/1C/1T', 'pps': 0})
+ executions.append({'nprocs': 2, 'cores': '1S/1C/2T', 'pps': 0})
+ executions.append({'nprocs': 2, 'cores': '1S/2C/1T', 'pps': 0})
+ executions.append({'nprocs': 4, 'cores': '1S/2C/2T', 'pps': 0})
+ executions.append({'nprocs': 4, 'cores': '1S/4C/1T', 'pps': 0})
+ executions.append({'nprocs': 8, 'cores': '1S/4C/2T', 'pps': 0})
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ pass
+
+ def test_multiprocess_simple_mpbasicoperation(self):
+ """
+ Basic operation.
+ """
+
+ # Send message from secondary to primary
+ self.dut.send_expect("./examples/multi_process/simple_mp/simple_mp/%s/simple_mp -n 1 -c 3 --proc-type=primary > out &" % self.target, "# ", 10)
+ time.sleep(20)
+ self.dut.send_expect("./examples/multi_process/simple_mp/simple_mp/%s/simple_mp -n 1 -c C --proc-type=secondary" % self.target, "Finished Process Init", 10)
+
+ self.dut.send_expect("send hello_primary", ">")
+ self.dut.send_expect("quit", "# ")
+ self.dut.send_expect("fg", "simple_mp")
+ self.dut.send_expect("quit", "# ")
+ out = self.dut.send_expect("cat out", "# ")
+
+ self.verify("Received 'hello_primary'" in out, "Message not received on primary process")
+
+ # Send message from primary to secondary
+ self.dut.send_expect("./examples/multi_process/simple_mp/simple_mp/%s/simple_mp -n 1 -c 3 --proc-type=primary &" % self.target, "# ", 10)
+ time.sleep(20)
+ self.dut.send_expect("./examples/multi_process/simple_mp/simple_mp/%s/simple_mp -n 1 -c C --proc-type=secondary > out &" % self.target, "Finished Process Init", 10)
+ self.dut.send_expect("fg 1", "simple_mp")
+ self.dut.send_expect("send hello_secondary", ">")
+ self.dut.send_expect("quit", "# ")
+ self.dut.send_expect("fg 2", "simple_mp")
+ self.dut.send_expect("quit", "# ")
+ out = self.dut.send_expect("cat out", "# ")
+
+ self.verify("Received 'hello_secondary'" in out,
+ "Message not received on primary process")
+
+ def test_multiprocess_simple_mploadtest(self):
+ """
+ Load test of Simple MP application.
+ """
+
+ self.dut.kill_all()
+ self.dut.send_expect("fg", "# ")
+
+ self.dut.send_expect("./examples/multi_process/simple_mp/simple_mp/%s/simple_mp -n 1 -c 3 --proc-type=primary > testing.txt &" % self.target, "# ")
+ time.sleep(20)
+ self.dut.send_expect("./examples/multi_process/simple_mp/simple_mp/%s/simple_mp -n 1 -c C --proc-type=secondary" % self.target, "Finished Process Init", 10)
+ stringsSent = 0
+ for line in open('/usr/share/dict/words', 'r').readlines():
+ line = line.split('\n')[0]
+ self.dut.send_expect("send %s" % line, ">")
+ stringsSent += 1
+ if stringsSent == 3:
+ break
+
+ time.sleep(5)
+ self.dut.send_expect("quit", "# ")
+ self.dut.send_expect("fg", ">")
+
+ def test_multiprocess_simple_mpapplicationstartup(self):
+ """
+ Test use of Auto for Application Startup.
+ """
+
+ self.dut.kill_all()
+
+ # Send message from secondary to primary (auto process type)
+ self.dut.send_expect("./examples/multi_process/simple_mp/simple_mp/%s/simple_mp -n 1 -c 3 --proc-type=auto > out &" % self.target, "# ", 30)
+ time.sleep(20)
+ out = self.dut.send_expect("./examples/multi_process/simple_mp/simple_mp/%s/simple_mp -n 1 -c C --proc-type=auto" % self.target, "Finished Process Init", 30)
+ self.verify("EAL: Auto-detected process type: SECONDARY" in out,
+ "The type of process (SECONDARY) was not detected properly")
+
+ self.dut.send_expect("send hello_primary", ">")
+ self.dut.send_expect("quit", "# ")
+ self.dut.send_expect("fg", "simple_mp")
+ self.dut.send_expect("quit", "# ")
+ out = self.dut.send_expect("cat out", "# ")
+
+ self.verify("EAL: Auto-detected process type: PRIMARY" in out, "The type of process (PRIMARY) was not detected properly")
+ self.verify("Received 'hello_primary'" in out, "Message not received on primary process")
+
+ # Send message from primary to secondary (auto process type)
+ out = self.dut.send_expect("./examples/multi_process/simple_mp/simple_mp/%s/simple_mp -n 1 -c 3 --proc-type=auto > out_primary &" % self.target, "# ", 30)
+ time.sleep(20)
+ self.dut.send_expect("./examples/multi_process/simple_mp/simple_mp/%s/simple_mp -n 1 -c C --proc-type=auto > out_secondary &" % self.target, "#", 30)
+ self.dut.send_expect("fg 1", "simple_mp")
+ self.dut.send_expect("send hello_secondary", ">")
+ self.dut.send_expect("quit", "# ")
+ self.dut.send_expect("fg 2", "simple_mp")
+ self.dut.send_expect("quit", "# ")
+ out = self.dut.send_expect("cat out_primary", "# ")
+ self.verify("EAL: Auto-detected process type: PRIMARY" in out, "The type of process (PRIMARY) was not detected properly")
+
+ out = self.dut.send_expect("cat out_secondary", "# ")
+ self.verify("EAL: Auto-detected process type: SECONDARY" in out, "The type of process (SECONDARY) was not detected properly")
+ self.verify("Received 'hello_secondary'" in out,
+ "Message not received on primary process")
+
+ def test_multiprocess_simple_mpnoflag(self):
+ """
+ Multiple processes without "--proc-type" flag.
+ """
+
+ self.dut.kill_all()
+
+ self.dut.send_expect("./examples/multi_process/simple_mp/simple_mp/%s/simple_mp -n 1 -c 3 -m 64 &" % self.target, "Finished Process Init")
+ out = self.dut.send_expect("./examples/multi_process/simple_mp/simple_mp/%s/simple_mp -n 1 -c C" % self.target, "# ")
+ self.verify("Is another primary process running" in out,
+ "No other primary process detected")
+
+ self.dut.send_expect("fg", " > ")
+ self.dut.send_expect("quit", "# ")
+
+ def test_perf_multiprocess_client_serverperformance(self):
+ """
+ Benchmark Multiprocess client-server performance.
+ """
+ self.dut.kill_all()
+ self.dut.send_expect("fg", "# ")
+ dutPorts = self.dut.get_ports(self.nic)
+ txPort = self.tester.get_local_port(dutPorts[0])
+ rxPort = self.tester.get_local_port(dutPorts[1])
+ mac = self.tester.get_mac(txPort)
+
+ self.tester.scapy_append('dmac="%s"' % self.dut.get_mac_address(dutPorts[0]))
+ self.tester.scapy_append('smac="%s"' % mac)
+ if not self.dut.want_perf_tests:
+ self.tester.scapy_append('flows = [Ether(src=smac, dst=dmac)/IP(src="192.168.1.%s" % src, dst="192.168.1.%s" % dst)/("X"*26) for src in range(64) for dst in range(64)]')
+ else:
+ self.tester.scapy_append('flows = [Ether(src=smac, dst=dmac)/IP(src="192.168.1.1", dst="192.168.1.1")/("X"*26)]')
+ self.tester.scapy_append('wrpcap("test.pcap", flows)')
+ self.tester.scapy_execute()
+
+ validExecutions = []
+ for execution in executions:
+ if len(self.dut.get_core_list(execution['cores'])) == execution['nprocs']:
+ validExecutions.append(execution)
+
+ for execution in validExecutions:
+ coreList = self.dut.get_core_list(execution['cores'])
+
+ coreMask = dcts.create_mask(self.dut.get_core_list('1S/1C/1T'))
+ portMask = dcts.create_mask([dutPorts[0], dutPorts[1]])
+ self.dut.send_expect("./examples/multi_process/client_server_mp/mp_server/client_server_mp/mp_server/%s/mp_server -n %d -c %s -- -p %s -n %d" % (self.target, self.dut.get_memory_channels(), "0xA0", portMask, execution['nprocs']), "Finished Process Init", 20)
+ self.dut.send_expect("^Z", "\r\n")
+ self.dut.send_expect("bg", "# ")
+
+ for n in range(execution['nprocs']):
+ time.sleep(5)
+ coreMask = dcts.create_mask([coreList[n]])
+ self.dut.send_expect("./examples/multi_process/client_server_mp/mp_client/client_server_mp/mp_client/%s/mp_client -n %d -c %s --proc-type=secondary -- -n %d" % (self.target, self.dut.get_memory_channels(), coreMask, n), "Finished Process Init")
+ self.dut.send_expect("^Z", "\r\n")
+ self.dut.send_expect("bg", "# ")
+
+ tgenInput = []
+ tgenInput.append([txPort, rxPort, "test.pcap"])
+ _, pps = self.tester.traffic_generator_throughput(tgenInput)
+ execution['pps'] = pps
+ self.dut.kill_all()
+ time.sleep(5)
+
+ for n in range(len(executions)):
+ self.verify(executions[n]['pps'] is not 0, "No traffic detected")
+
+ dcts.results_table_add_header(['Server threads', 'Server Cores/Threads', 'Num-procs', 'Sockets/Cores/Threads', 'Num Ports', 'Frame Size', '%-age Line Rate', 'Packet Rate(mpps)'])
+
+ for execution in validExecutions:
+ dcts.results_table_add_row([1, '1S/1C/1T', execution['nprocs'], execution['cores'], 2, 64, execution['pps'] / float(100000000 / (8 * 84)), execution['pps'] / float(1000000)])
+
+ dcts.results_table_print()
+
+ def ip(self, port, frag, src, proto, tos, dst, chksum, len, options, version, flags, ihl, ttl, id):
+ self.add_tcl_cmd("protocol config -name ip")
+ self.add_tcl_cmd('ip config -sourceIpAddr "%s"' % src)
+ self.add_tcl_cmd('ip config -sourceIpAddrMode ipIncrHost')
+ self.add_tcl_cmd('ip config -sourceIpAddrRepeatCount %d' % 64)
+ self.add_tcl_cmd('ip config -destIpAddr "%s"' % dst)
+ self.add_tcl_cmd('ip config -destIpAddrMode ipIncrHost')
+ self.add_tcl_cmd('ip config -destIpAddrRepeatCount %d' % 64)
+ self.add_tcl_cmd("ip config -ttl %d" % ttl)
+ self.add_tcl_cmd("ip config -totalLength %d" % len)
+ self.add_tcl_cmd("ip config -fragment %d" % frag)
+ self.add_tcl_cmd("ip config -ipProtocol %d" % proto)
+ self.add_tcl_cmd("ip config -identifier %d" % id)
+ self.add_tcl_cmd("stream config -framesize %d" % (len + 18))
+ self.add_tcl_cmd("ip set %d %d %d" % (self.chasId, port['card'], port['port']))
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ """
+ pass
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ self.dut.kill_all()
+
+ pass
diff --git a/tests/TestSuite_pmd.py b/tests/TestSuite_pmd.py
new file mode 100644
index 0000000..502ca79
--- /dev/null
+++ b/tests/TestSuite_pmd.py
@@ -0,0 +1,477 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+Test userland 10Gb PMD
+
+"""
+
+import dcts
+import re
+import time
+from test_case import TestCase
+from plotting import Plotting
+from time import sleep
+from settings import HEADER_SIZE
+
+#
+#
+# Test class.
+#
+
+
+class TestPmd(TestCase):
+
+ #
+ #
+ # Utility methods and other non-test code.
+ #
+
+ def plot_results(self, number_ports):
+
+ cores_configs = []
+ percent_values = []
+
+ # Append the percentage results for the all the cores configs
+ for test_cycle in self.test_cycles:
+ cores_configs.append(test_cycle['cores'])
+ config_results = []
+ for frame_size in self.frame_sizes:
+ config_results.append(test_cycle['pct'][frame_size])
+
+ percent_values.append(config_results)
+
+ image_path = self.plotting.create_bars_plot(
+ 'test_perf_pmd_%sports' % number_ports,
+ 'PMD, %d ports' % number_ports,
+ self.frame_sizes,
+ percent_values,
+ ylabel='% linerate',
+ legend=cores_configs)
+
+ dcts.results_plot_print(image_path)
+
+ #
+ #
+ #
+ # Test cases.
+ #
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+
+ PMD prerequisites.
+ """
+
+ self.frame_sizes = [64, 65, 128, 256, 512, 1024, 1280, 1518]
+
+ self.rxfreet_values = [0, 8, 16, 32, 64, 128]
+
+ self.test_cycles = [{'cores': '1S/1C/1T', 'Mpps': {}, 'pct': {}},
+ {'cores': '1S/1C/2T', 'Mpps': {}, 'pct': {}},
+ {'cores': '1S/2C/1T', 'Mpps': {}, 'pct': {}},
+ {'cores': '1S/2C/2T', 'Mpps': {}, 'pct': {}},
+ {'cores': '1S/4C/2T', 'Mpps': {}, 'pct': {}}
+ ]
+
+ self.table_header = ['Frame Size']
+ for test_cycle in self.test_cycles:
+ self.table_header.append("%s Mpps" % test_cycle['cores'])
+ self.table_header.append("% linerate")
+
+ self.needed_ports = {"niantic": 2,
+ "kawela_2": 2,
+ "bartonhills": 4,
+ "82545EM": 2,
+ "82540EM": 2}
+
+ self.blacklist = ""
+
+ self.verify(self.nic in ["kawela_2", "niantic", "bartonhills", "82545EM", "82540EM"],
+ "NIC Unsupported: " + str(self.nic))
+
+ # Based on h/w type, choose how many ports to use
+ self.dut_ports = self.dut.get_ports(self.nic)
+
+ # Verify that enough ports are available
+ self.verify(len(self.dut_ports) >= self.needed_ports[self.nic],
+ "Insufficient ports for speed testing")
+
+ self.headers_size = HEADER_SIZE['eth'] + HEADER_SIZE[
+ 'ip'] + HEADER_SIZE['udp']
+
+ self.ports_socket = self.dut.get_numa_id(self.dut_ports[0])
+
+ self.plotting = Plotting(self.dut.crb['name'], self.target, self.nic)
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ pass
+
+ def test_perf_pmd_performance_4ports(self):
+ """
+ PMD Performance Benchmarking with 4 ports.
+ """
+ all_cores_mask = dcts.create_mask(self.dut.get_core_list("all"))
+
+ # prepare traffic generator input
+ self.verify(len(self.dut_ports) >= 4,
+ "Insufficient ports for 4 ports performance")
+ tgen_input = []
+
+ tgen_input.append((self.tester.get_local_port(self.dut_ports[0]),
+ self.tester.get_local_port(self.dut_ports[1]),
+ "test.pcap"))
+ tgen_input.append((self.tester.get_local_port(self.dut_ports[2]),
+ self.tester.get_local_port(self.dut_ports[3]),
+ "test.pcap"))
+ tgen_input.append((self.tester.get_local_port(self.dut_ports[1]),
+ self.tester.get_local_port(self.dut_ports[0]),
+ "test.pcap"))
+ tgen_input.append((self.tester.get_local_port(self.dut_ports[3]),
+ self.tester.get_local_port(self.dut_ports[2]),
+ "test.pcap"))
+
+ # run testpmd for each core config
+ for test_cycle in self.test_cycles:
+ core_config = test_cycle['cores']
+
+ core_list = self.dut.get_core_list(core_config,
+ socket=self.ports_socket)
+
+ if len(core_list) > 4:
+ queues = len(core_list) / 4
+ else:
+ queues = 1
+
+ core_mask = dcts.create_mask(core_list)
+ port_mask = dcts.create_mask(self.dut.get_ports(self.nic))
+
+ commandLine = "./%s/app/testpmd -c %s -n %d %s-- -i \
+--coremask=%s --rxq=%d --txq=%d --rxd=512 --txd=512 --burst=32 --rxfreet=64 --mbcache=128 \
+--portmask=%s --txpt=36 --txht=0 --txwt=0 --txfreet=32 --txrst=32" % (self.target,
+ all_cores_mask,
+ self.dut.get_memory_channels(
+ ),
+ self.blacklist,
+ core_mask,
+ queues,
+ queues,
+ port_mask
+ )
+
+ info = "Executing PMD (mac fwd) using %s\n" % test_cycle['cores']
+ dcts.report(info, annex=True)
+ self.logger.info(info)
+
+ dcts.report(commandLine + "\n\n", frame=True, annex=True)
+
+ self.dut.send_expect(commandLine, "testpmd> ", 100)
+ # self.dut.send_expect("set fwd mac", "testpmd> ", 100)
+ self.dut.send_expect("start", "testpmd> ")
+
+ for frame_size in self.frame_sizes:
+ wirespeed = self.wirespeed(self.nic, frame_size, 4)
+
+ # create pcap file
+ self.logger.info("Running with frame size %d " % frame_size)
+ payload_size = frame_size - self.headers_size
+ self.tester.scapy_append(
+ 'wrpcap("test.pcap", [Ether(src="52:00:00:00:00:00")/IP()/UDP()/("X"*%d)])' % payload_size)
+ self.tester.scapy_execute()
+
+ # run traffic generator
+ _, pps = self.tester.traffic_generator_throughput(tgen_input)
+
+ pps /= 1000000.0
+ test_cycle['Mpps'][frame_size] = pps
+ test_cycle['pct'][frame_size] = pps * 100 / wirespeed
+
+ self.dut.send_expect("stop", "testpmd> ")
+ self.dut.send_expect("quit", "# ", 30)
+ sleep(5)
+
+ for n in range(len(self.test_cycles)):
+ for frame_size in self.frame_sizes:
+ self.verify(self.test_cycles[n]['Mpps'][
+ frame_size] is not 0, "No traffic detected")
+
+ # Print results
+ dcts.results_table_add_header(self.table_header)
+
+ for frame_size in self.frame_sizes:
+ table_row = [frame_size]
+
+ for test_cycle in self.test_cycles:
+ table_row.append(test_cycle['Mpps'][frame_size])
+ table_row.append(test_cycle['pct'][frame_size])
+
+ dcts.results_table_add_row(table_row)
+
+ self.plot_results(number_ports=4)
+ dcts.results_table_print()
+
+ def test_perf_pmd_performance_2ports(self):
+ """
+ PMD Performance Benchmarking with 2 ports.
+ """
+
+ all_cores_mask = dcts.create_mask(self.dut.get_core_list("all"))
+
+ # prepare traffic generator input
+ tgen_input = []
+ tgen_input.append((self.tester.get_local_port(self.dut_ports[0]),
+ self.tester.get_local_port(self.dut_ports[1]),
+ "test.pcap"))
+ tgen_input.append((self.tester.get_local_port(self.dut_ports[1]),
+ self.tester.get_local_port(self.dut_ports[0]),
+ "test.pcap"))
+
+ # run testpmd for each core config
+ for test_cycle in self.test_cycles:
+ core_config = test_cycle['cores']
+
+ core_list = self.dut.get_core_list(core_config,
+ socket=self.ports_socket)
+
+ if len(core_list) > 2:
+ queues = len(core_list) / 2
+ else:
+ queues = 1
+
+ core_mask = dcts.create_mask(core_list)
+ port_mask = dcts.create_mask([self.dut_ports[0], self.dut_ports[1]])
+
+ command_line = "./%s/app/testpmd -c %s -n %d %s-- -i --coremask=%s \
+--rxq=%d --txq=%d --rxd=512 --txd=512 --burst=32 --rxfreet=64 --mbcache=128 \
+--portmask=%s --txpt=36 --txht=0 --txwt=0 --txfreet=32 --txrst=32" % (self.target,
+ all_cores_mask,
+ self.dut.get_memory_channels(
+ ),
+ self.blacklist,
+ core_mask,
+ queues,
+ queues,
+ port_mask)
+
+ info = "Executing PMD using %s\n" % test_cycle['cores']
+ self.logger.info(info)
+ dcts.report(info, annex=True)
+ dcts.report(command_line + "\n\n", frame=True, annex=True)
+
+ self.dut.send_expect(command_line, "testpmd> ", 100)
+
+ self.dut.send_expect("start", "testpmd> ")
+ for frame_size in self.frame_sizes:
+ wirespeed = self.wirespeed(self.nic, frame_size, 2)
+
+ # create pcap file
+ self.logger.info("Running with frame size %d " % frame_size)
+ payload_size = frame_size - self.headers_size
+ self.tester.scapy_append(
+ 'wrpcap("test.pcap", [Ether(src="52:00:00:00:00:00")/IP()/UDP()/("X"*%d)])' % payload_size)
+ self.tester.scapy_execute()
+
+ # run traffic generator
+ _, pps = self.tester.traffic_generator_throughput(tgen_input)
+
+ pps /= 1000000.0
+ test_cycle['Mpps'][frame_size] = pps
+ test_cycle['pct'][frame_size] = pps * 100 / wirespeed
+
+ self.dut.send_expect("stop", "testpmd> ")
+ self.dut.send_expect("quit", "# ", 30)
+ sleep(5)
+
+ for n in range(len(self.test_cycles)):
+ for frame_size in self.frame_sizes:
+ self.verify(self.test_cycles[n]['Mpps'][
+ frame_size] > 0, "No traffic detected")
+
+ # Print results
+ dcts.results_table_add_header(self.table_header)
+ for frame_size in self.frame_sizes:
+ table_row = [frame_size]
+ for test_cycle in self.test_cycles:
+ table_row.append(test_cycle['Mpps'][frame_size])
+ table_row.append(test_cycle['pct'][frame_size])
+
+ dcts.results_table_add_row(table_row)
+
+ self.plot_results(number_ports=2)
+ dcts.results_table_print()
+
+ def test_checksum_checking(self):
+ """
+ Packet forwarding checking test
+ """
+
+ self.dut.kill_all()
+
+ all_cores_mask = dcts.create_mask(self.dut.get_core_list("all"))
+ core_mask = dcts.create_mask(self.dut.get_core_list('1S/1C/1T',
+ socket=self.ports_socket))
+ port_mask = dcts.create_mask([self.dut_ports[0], self.dut_ports[1]])
+
+ for rxfreet_value in self.rxfreet_values:
+
+ cmd = "./%s/app/testpmd -c %s -n %d %s-- \
+--coremask=%s --portmask=%s --nb-cores=2 --enable-rx-cksum --disable-hw-vlan \
+--disable-rss --crc-strip --rxd=1024 --txd=1024 --rxfreet=%d -i" % (self.target,
+ all_cores_mask,
+ self.dut.get_memory_channels(),
+ self.blacklist,
+ core_mask,
+ port_mask,
+ rxfreet_value
+ )
+
+ self.dut.send_expect(cmd, "testpmd> ", 120)
+ # self.dut.send_expect("set fwd csum", "testpmd> ")
+ self.dut.send_expect("start", "testpmd> ")
+
+ self.send_packet(self.frame_sizes[0], checksum_test=True)
+
+ l4csum_error = self.stop_and_get_l4csum_errors()
+
+ # Check the l4 checksum errors reported for Rx port
+ self.verify(1 == int(l4csum_error[1]),
+ "Wrong l4 checksum error count using rxfreet=%d (expected 1, reported %s)" %
+ (rxfreet_value, l4csum_error[1]))
+
+ self.dut.send_expect("quit", "# ", 30)
+ sleep(5)
+
+ def test_packet_checking(self):
+ """
+ Packet forwarding checking test
+ """
+
+ self.dut.kill_all()
+
+ all_cores_mask = dcts.create_mask(self.dut.get_core_list("all"))
+ core_mask = dcts.create_mask(self.dut.get_core_list('1S/1C/1T',
+ socket=self.ports_socket))
+ port_mask = dcts.create_mask([self.dut_ports[0], self.dut_ports[1]])
+
+ cmd = "./%s/app/testpmd -c %s -n %d %s-- -i \
+--coremask=%s --rxd=512 --txd=512 --burst=32 --rxfreet=64 --mbcache=128 \
+--portmask=%s --txpt=36 --txht=0 --txwt=0 --txfreet=32 --txrst=32" % (self.target,
+ all_cores_mask,
+ self.dut.get_memory_channels(
+ ),
+ self.blacklist,
+ core_mask,
+ port_mask
+ )
+
+ self.dut.send_expect(cmd, "testpmd> ", 120)
+ self.dut.send_expect("start", "testpmd> ")
+ for size in self.frame_sizes:
+ self.send_packet(size)
+
+ self.dut.send_expect("stop", "testpmd> ")
+ self.dut.send_expect("quit", "# ", 30)
+ sleep(5)
+
+ def stop_and_get_l4csum_errors(self):
+ """
+ Stop forwarding and get Bad-l4csum number from stop statistic
+ """
+
+ out = self.dut.send_expect("stop", "testpmd> ")
+ result_scanner = r"Bad-l4csum: ([0-9]+) \s*"
+ scanner = re.compile(result_scanner, re.DOTALL)
+ m = scanner.findall(out)
+
+ return m
+
+ def get_stat(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-errors: ([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 send_packet(self, frame_size, checksum_test=False):
+ """
+ Send 1 packet to portid
+ """
+
+ gp0tx_pkts, _, gp0tx_bytes = [int(
+ _) for _ in self.get_stat(self.dut_ports[0], "tx")]
+ gp1rx_pkts, gp1rx_err, gp1rx_bytes = [int(
+ _) for _ in self.get_stat(self.dut_ports[1], "rx")]
+
+ interface = self.tester.get_interface(
+ self.tester.get_local_port(self.dut_ports[1]))
+ mac = self.dut.get_mac_address(self.dut_ports[1])
+
+ load_size = frame_size - HEADER_SIZE['eth']
+ padding = frame_size - HEADER_SIZE['eth'] - HEADER_SIZE['ip'] - \
+ HEADER_SIZE['udp']
+
+ checksum = ''
+ if checksum_test:
+ checksum = 'chksum=0x0'
+
+ self.tester.scapy_foreground()
+ self.tester.scapy_append('nutmac="%s"' % mac)
+ self.tester.scapy_append('sendp([Ether(dst=nutmac, src="52:00:00:00:00:00")/IP(len=%s)/UDP(%s)/Raw(load="\x50"*%s)], iface="%s")' % (
+ load_size, checksum, padding, interface))
+
+ out = self.tester.scapy_execute()
+ time.sleep(.5)
+
+ p0tx_pkts, _, p0tx_bytes = [int(_) for _ in self.get_stat(
+ self.dut_ports[0], "tx")]
+ p1rx_pkts, p1rx_err, p1rx_bytes = [int(
+ _) for _ in self.get_stat(self.dut_ports[1], "rx")]
+
+ p0tx_pkts -= gp0tx_pkts
+ p0tx_bytes -= gp0tx_bytes
+ p1rx_pkts -= gp1rx_pkts
+ p1rx_bytes -= gp1rx_bytes
+ p1rx_err -= gp1rx_err
+
+ self.verify(p0tx_pkts == p1rx_pkts,
+ "packet pass assert error, %d RX packets, %d TX packets" % (p1rx_pkts, p0tx_pkts))
+
+ if checksum_test:
+ self.verify(p1rx_bytes == frame_size - 4,
+ "packet pass assert error, expected %d RX bytes, actual %d" % (frame_size - 4, p1rx_bytes))
+ else:
+ self.verify(p1rx_bytes == frame_size,
+ "packet pass assert error, expected %d RX bytes, actual %d" % (frame_size, p1rx_bytes))
+
+ self.verify(p0tx_bytes == frame_size,
+ "packet pass assert error, expected %d TX bytes, actual %d" % (frame_size, p0tx_bytes))
+
+ return out
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ """
+ pass
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ self.dut.kill_all()
diff --git a/tests/TestSuite_pmd_bonded.py b/tests/TestSuite_pmd_bonded.py
new file mode 100644
index 0000000..3553a5f
--- /dev/null
+++ b/tests/TestSuite_pmd_bonded.py
@@ -0,0 +1,1098 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+
+Test userland 10Gb PMD.
+
+"""
+
+import time
+import re
+import random
+from socket import htons, htonl
+import pdb
+
+import dcts
+from test_case import TestCase
+
+#
+#
+# Test class.
+#
+
+
+class TestPmdBonded(TestCase):
+
+ #
+ #
+ # Utility methods and other non-test code.
+ #
+ # Insert or move non-test functions here.
+
+ 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 send_packet(self, port_id, frame_size=64, count=1, reverse_verify=False, **ether_ip):
+ """
+ Send count packet to portid
+ 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
+ }
+ """
+
+ gp0rx_pkts, gp0rx_err, gp0rx_bytes = [int(_) for _ in self.get_stats(self.dut_ports[port_id], "rx")]
+
+ itf = self.tester.get_interface(self.tester.get_local_port(self.dut_ports[port_id]))
+
+ if not ether_ip.get('ether'):
+ dest_mac = self.dut.get_mac_address(self.dut_ports[port_id])
+ src_mac = "52:00:00:00:00:00"
+ else:
+ if not ether_ip['ether'].get('dest_mac'):
+ dest_mac = self.dut.get_mac_address(self.dut_ports[port_id])
+ else:
+ dest_mac = ether_ip['ether']['dest_mac']
+ if not ether_ip['ether'].get('src_mac'):
+ src_mac = "52:00:00:00:00:00"
+ else:
+ src_mac = ether_ip["ether"]["src_mac"]
+
+ if not ether_ip.get('dot1q'):
+ pass
+ else:
+ if not ether_ip['dot1q'].get('vlan'):
+ vlan = '1'
+ else:
+ vlan = ether_ip['dot1q']['vlan']
+
+ if not ether_ip.get('ip'):
+ dest_ip = "10.239.129.88"
+ src_ip = "10.239.129.65"
+ else:
+ if not ether_ip['ip'].get('dest_ip'):
+ dest_ip = "10.239.129.88"
+ else:
+ dest_ip = ether_ip['ip']['dest_ip']
+ if not ether_ip['ip'].get('src_ip'):
+ src_ip = "10.239.129.65"
+ else:
+ src_ip = ether_ip['ip']['src_ip']
+
+ if not ether_ip.get('udp'):
+ dest_port = 53
+ src_port = 53
+ else:
+ if not ether_ip['udp'].get('dest_port'):
+ dest_port = 53
+ else:
+ dest_port = ether_ip['udp']['dest_port']
+ if not ether_ip['udp'].get('src_port'):
+ src_port = 53
+ else:
+ src_port = ether_ip['udp']['src_port']
+
+ pktlen = frame_size - 18
+ padding = pktlen - 20
+
+ self.tester.scapy_foreground()
+ self.tester.scapy_append('nutmac="%s"' % dest_mac)
+ self.tester.scapy_append('srcmac="%s"' % src_mac)
+
+ if ether_ip.get('dot1q'):
+ self.tester.scapy_append('vlanvalue=%d' % vlan)
+ self.tester.scapy_append('destip="%s"' % dest_ip)
+ self.tester.scapy_append('srcip="%s"' % src_ip)
+ self.tester.scapy_append('destport=%d' % dest_port)
+ self.tester.scapy_append('srcport=%d' % src_port)
+ if not 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))
+
+ out = self.tester.scapy_execute()
+ time.sleep(.5)
+
+ p0rx_pkts, p0rx_err, p0rx_bytes = [int(_) for _ in self.get_stats(self.dut_ports[port_id], "rx")]
+
+ p0rx_pkts -= gp0rx_pkts
+
+ if not reverse_verify:
+ self.verify(p0rx_pkts == count, "Data not received by port")
+ else:
+ self.verify(p0rx_pkts == 0, "Data received by port,should not received")
+ return out
+
+ #
+ #
+ #
+ # 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.nic)
+
+ self.port_mask = dcts.create_mask(self.dut_ports)
+
+ self.verify(len(self.dut_ports) >= 4, "Insufficient ports")
+
+ self.ports_socket = self.dut.get_numa_id(self.dut_ports[0])
+
+ self.all_cores_mask = dcts.create_mask(self.dut.get_core_list("all"))
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ pass
+
+ def get_value_from_str(self, key_str, regx_str, string):
+ 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):
+ 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):
+ 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):
+ return self.get_detail_from_port_info("Connect to socket: ", "\d+", port_id)
+
+ def get_port_memory_socket(self, port_id):
+ return self.get_detail_from_port_info("memory allocation on the socket: ", "\d+", port_id)
+
+ def get_port_link_status(self, port_id):
+ return self.get_detail_from_port_info("Link status: ", "\d+", port_id)
+
+ def get_port_link_speed(self, port_id):
+ return self.get_detail_from_port_info("Link speed: ", "\d+", port_id)
+
+ def get_port_link_duplex(self, port_id):
+ return self.get_detail_from_port_info("Link duplex: ", "\S+", port_id)
+
+ def get_port_promiscuous_mode(self, port_id):
+ return self.get_detail_from_port_info("Promiscuous mode: ", "\S+", port_id)
+
+ def get_port_allmulticast_mode(self, port_id):
+ return self.get_detail_from_port_info("Allmulticast mode: ", "\S+", port_id)
+
+ def get_port_vlan_offload(self, port_id):
+ """
+ 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):
+ 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):
+ return self.get_info_from_bond_config("Bonding mode: ", "\d*", bond_port)
+
+ def get_bond_balance_policy(self, bond_port):
+ return self.get_info_from_bond_config("Balance Xmit Policy: ", "\S+", bond_port)
+
+ def get_bond_slaves(self, bond_port):
+ 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):
+ 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):
+ return self.get_info_from_bond_config("Primary: \[", "\d*", bond_port)
+
+ def launch_app(self, cmd_param="-c 0xf -n 4 -- -i"):
+ app_path = "./%s/app/testpmd" % self.target
+ self.dut.send_expect(app_path + ' ' + cmd_param, "testpmd> ", 120)
+
+ def create_bonded_device(self, mode=0, socket=0, verify_detail=False):
+ 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 eth_bond_testpmd_[\d] on \(port ", "\d+", out)
+ bond_port = int(bond_port)
+
+ if verify_detail:
+ out = self.dut.send_expect("show bonding config %d" % bond_port, "testpmd> ")
+ self.verify("Bonding mode: %d" % mode in out, "Bonding mode display error when create bonded device")
+ self.verify("Slaves: []" in out, "Slaves display error when create bonded device")
+ self.verify("Active Slaves: []" in out, "Active Slaves display error when create bonded device")
+ self.verify("Primary: []" not in out, "Primary display error when create bonded device")
+
+ out = self.dut.send_expect("show port info %d" % bond_port, "testpmd> ")
+ self.verify("Connect to socket: %d" % socket in out, "Bonding port connect socket error")
+ self.verify("Link status: down" in out, "Bonding port default link status error")
+ self.verify("Link speed: 0 Mbps" in out, "Bonding port default link speed error")
+
+ return bond_port
+
+ def start_all_ports(self):
+ self.dut.send_expect("port start all", "testpmd> ")
+ time.sleep(5)
+
+ def add_slave_to_bonding_device(self, bond_port, reverse_verify=False, *slave_port):
+ if len(slave_port) <= 0:
+ dcts.RED("No port exist when add slave to bonded device")
+ for slave_id in slave_port:
+ self.dut.send_expect("add bonding slave %d %d" % (slave_id, bond_port), "testpmd> ")
+
+ slaves = self.get_info_from_bond_config("Slaves \(\d\): \[", "\d*( \d*)*", bond_port)
+ if not reverse_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, reverse_verify=False, *slave_port):
+ if len(slave_port) <= 0:
+ dcts.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" % (slave_id, bond_port), "testpmd> ")
+ out = self.get_info_from_bond_config("Slaves: \[", "\d*( \d*)*", bond_port)
+ if not reverse_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 set_primary_for_bonding_device(self, bond_port, slave_port, reverse_verify=False):
+ 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 reverse_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):
+ 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):
+ 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):
+ 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 test_create_bonded_devices_and_slaves(self):
+ """
+ Create bonded devices and slaves.
+ """
+ self.launch_app()
+ bond_port_0 = self.create_bonded_device(1, 0, True)
+ self.add_slave_to_bonding_device(bond_port_0, False, self.dut_ports[1])
+ self.start_all_ports()
+ mode_value = self.get_bond_mode(bond_port_0)
+ self.verify('1' in mode_value, "Bonding mode show error")
+ slaves = self.get_bond_slaves(bond_port_0)
+ self.verify(str(self.dut_ports[1]) in slaves, "Bonding slaves show error")
+ primary = self.get_bond_primary(bond_port_0)
+ self.verify(str(self.dut_ports[1]) in primary, "Bonding primary show error")
+
+ bond_port_1 = self.create_bonded_device(1, 0)
+ self.add_slave_to_bonding_device(bond_port_0, False, self.dut_ports[0])
+ self.add_slave_to_bonding_device(bond_port_1, True, self.dut_ports[0])
+
+ self.set_mode_for_bonding_device(bond_port_0, 3)
+ self.add_slave_to_bonding_device(bond_port_0, False, self.dut_ports[2])
+ time.sleep(5)
+ self.set_primary_for_bonding_device(bond_port_0, self.dut_ports[2])
+
+ self.remove_slave_from_bonding_device(bond_port_0, False, self.dut_ports[1])
+ self.remove_slave_from_bonding_device(bond_port_0, False, self.dut_ports[0])
+ self.remove_slave_from_bonding_device(bond_port_0, False, self.dut_ports[2])
+
+ def test_bonded_mac_address(self):
+ """
+ Create bonded device, add one slave, verify bonded device MAC address is the slave's MAC.
+ """
+ self.launch_app()
+ bond_port = self.create_bonded_device(3, 1)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[1])
+ mac_address_0_orig = self.get_port_mac(self.dut_ports[0])
+ mac_address_1_orig = self.get_port_mac(self.dut_ports[1])
+ mac_address_2_orig = self.get_port_mac(self.dut_ports[2])
+ mac_address_3_orig = self.get_port_mac(self.dut_ports[3])
+ 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.dut_ports[2])
+ mac_address_2_now = self.get_port_mac(self.dut_ports[2])
+ mac_address_bond_now = self.get_port_mac(bond_port)
+ 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")
+
+ new_mac = "00:11:22:00:33:44"
+ self.set_mac_for_bonding_device(bond_port, new_mac)
+ mac_address_1_now = self.get_port_mac(self.dut_ports[1])
+ mac_address_2_now = self.get_port_mac(self.dut_ports[2])
+ mac_address_bond_now = self.get_port_mac(bond_port)
+ self.verify(mac_address_1_now == mac_address_2_now == mac_address_bond_now == new_mac,
+ "Set mac failed for bonding device")
+
+ self.dut.send_expect("port start %d" % bond_port, "testpmd> ")
+ time.sleep(5)
+ self.set_primary_for_bonding_device(bond_port, self.dut_ports[2], False)
+ mac_address_1_now = self.get_port_mac(self.dut_ports[1])
+ mac_address_2_now = self.get_port_mac(self.dut_ports[2])
+ mac_address_bond_now = self.get_port_mac(bond_port)
+ self.verify(mac_address_1_now == mac_address_2_now == mac_address_bond_now == new_mac,
+ "Slave MAC changed when set primary slave")
+ self.remove_slave_from_bonding_device(bond_port, False, self.dut_ports[2])
+ primary_now = self.get_bond_primary(bond_port)
+ self.verify(int(primary_now) == self.dut_ports[1], "Reset primary slave failed after removing primary slave")
+ mac_address_2_now = self.get_port_mac(self.dut_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.dut_ports[1])
+ mac_address_bond_now = self.get_port_mac(bond_port)
+ self.verify(mac_address_1_now == mac_address_bond_now == new_mac,
+ "Bonding device and slave MAC changed after removing the primary slave")
+
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[3])
+ self.remove_slave_from_bonding_device(bond_port, False, self.dut_ports[3])
+ mac_address_3_now = self.get_port_mac(self.dut_ports[3])
+ self.verify(mac_address_3_now == mac_address_3_orig, "Slave MAC not back to original after removing it")
+
+ def test_device_promiscuous_mode(self):
+ self.launch_app()
+ bond_port = self.create_bonded_device(3, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[1], self.dut_ports[2])
+ port_enabled_num = 0
+ for port_id in [0, 1, 2, 4]:
+ value = self.get_detail_from_port_info("Promiscuous mode: ", "enabled", port_id)
+ if value:
+ port_enabled_num += 1
+ self.verify(port_enabled_num == 4, "Not all slaves of bonded device changed to promiscuous mode.")
+
+ ether_ip = {}
+ ether = {}
+ ether['dest_mac'] = "00:11:22:33:44:55"
+ ether_ip['ether'] = ether
+
+ pkt_count = 1
+
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.start_all_ports()
+ self.dut.send_expect("start", "testpmd> ")
+ gp0rx_pkts, gp0rx_err, gp0rx_bytes = [int(_) for _ in self.get_stats(self.dut_ports[0], "rx")]
+ gp4rx_pkts, gp4rx_err, gp4rx_bytes = [int(_) for _ in self.get_stats(bond_port, "rx")]
+ self.send_packet(self.dut_ports[0], 64, pkt_count, False, **ether_ip)
+ p0rx_pkts, p0rx_err, p0rx_bytes = [int(_) for _ in self.get_stats(self.dut_ports[0], "rx")]
+ p4rx_pkts, p4rx_err, p4rx_bytes = [int(_) for _ in self.get_stats(bond_port, "rx")]
+ p0rx_pkts -= gp0rx_pkts
+ p4rx_pkts -= gp4rx_pkts
+ self.verify(p0rx_pkts == pkt_count and p4rx_pkts == pkt_count, "Data not received by slave or bonding device when promiscuous state")
+
+ self.dut.send_expect("set promisc 4 off", "testpmd> ")
+ port_disabled_num = 0
+ for port_id in [0, 1, 2, 4]:
+ value = self.get_detail_from_port_info('Promiscuous mode: ', 'disabled', port_id)
+ if value:
+ port_disabled_num += 1
+ self.verify(port_disabled_num == 4, "Not all slaves of bonded device make promiscuous mode disabled.")
+
+ gp0rx_pkts, gp0rx_err, gp0rx_bytes = [int(_) for _ in self.get_stats(self.dut_ports[0], "rx")]
+ gp4rx_pkts, gp4rx_err, gp4rx_bytes = [int(_) for _ in self.get_stats(bond_port, "rx")]
+ self.send_packet(self.dut_ports[0], 64, pkt_count, True, **ether_ip)
+ p0rx_pkts, p0rx_err, p0rx_bytes = [int(_) for _ in self.get_stats(self.dut_ports[0], "rx")]
+ p4rx_pkts, p4rx_err, p4rx_bytes = [int(_) for _ in self.get_stats(bond_port, "rx")]
+ p0rx_pkts -= gp0rx_pkts
+ p4rx_pkts -= gp4rx_pkts
+ self.verify(p0rx_pkts == 0 and p4rx_pkts == 0, "Data received by slave or bonding device when promiscuous disabled")
+
+ gp0rx_pkts, gp0rx_err, gp0rx_bytes = [int(_) for _ in self.get_stats(self.dut_ports[0], "rx")]
+ gp3tx_pkts, gp3tx_err, gp3tx_bytes = [int(_) for _ in self.get_stats(self.dut_ports[3], "tx")]
+ gp4rx_pkts, gp4rx_err, gp4rx_bytes = [int(_) for _ in self.get_stats(bond_port, "rx")]
+ self.send_packet(self.dut_ports[0], 64, pkt_count)
+ p0rx_pkts, p0rx_err, p0rx_bytes = [int(_) for _ in self.get_stats(self.dut_ports[0], "rx")]
+ p3tx_pkts, p3tx_err, p3tx_bytes = [int(_) for _ in self.get_stats(self.dut_ports[3], "tx")]
+ p4rx_pkts, p4rx_err, p4rx_bytes = [int(_) for _ in self.get_stats(bond_port, "rx")]
+ p0rx_pkts -= gp0rx_pkts
+ p3tx_pkts -= gp3tx_pkts
+ p4rx_pkts -= gp4rx_pkts
+ self.verify(p0rx_pkts == p4rx_pkts == p3tx_pkts == pkt_count, "RX or TX packet number not correct when promiscuous disabled")
+
+ def admin_tester_port(self, local_port, status):
+ 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(5)
+
+ def verify_round_robin_rx_tx(self, unbond_port, bond_port, **slaves):
+ """
+ slaves:
+ 'active' = []
+ 'inactive' = []
+ """
+ pkt_count = 300
+ tx_pkt_orig = {}
+ tx_pkt_now = {}
+
+ # send to unbonding port
+ for slave in slaves['active']:
+ tx_pkt_orig[slave] = [int(_) for _ in self.get_stats(slave, "tx")]
+ for slave in slaves['inactive']:
+ tx_pkt_orig[slave] = [int(_) for _ in self.get_stats(slave, "tx")]
+ tx_pkt_orig[bond_port] = [int(_) for _ in self.get_stats(bond_port, "tx")]
+
+ self.send_packet(unbond_port, 64, pkt_count)
+
+ for slave in slaves['active']:
+ tx_pkt_now[slave] = [int(_) for _ in self.get_stats(slave, "tx")]
+ tx_pkt_now[slave][0] -= tx_pkt_orig[slave][0]
+ for slave in slaves['inactive']:
+ tx_pkt_now[slave] = [int(_) for _ in self.get_stats(slave, "tx")]
+ tx_pkt_now[slave][0] -= tx_pkt_orig[slave][0]
+ tx_pkt_now[bond_port] = [int(_) for _ in self.get_stats(bond_port, "tx")]
+ tx_pkt_now[bond_port][0] -= tx_pkt_orig[bond_port][0]
+
+ if slaves['active'].__len__() == 0:
+ self.verify(tx_pkt_now[bond_port][0] == 0, "Bonding port should not have TX pkt in mode 0 when all slaves down")
+ else:
+ self.verify(tx_pkt_now[bond_port][0] == pkt_count, "Bonding port has error TX pkt count in mode 0")
+ for slave in slaves['active']:
+ self.verify(tx_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(tx_pkt_now[slave][0] == 0, "Inactive slave has error TX pkt count in mode 0")
+
+ # send to bonding slaves
+ pkt_orig = {}
+ pkt_now = {}
+ pkt_orig[unbond_port] = [int(_) for _ in self.get_stats(unbond_port, "tx")]
+ pkt_orig[bond_port] = [int(_) for _ in self.get_stats(bond_port, "rx")]
+
+ for slave in slaves['active']:
+ self.send_packet(slave, 64, pkt_count)
+ for slave in slaves['inactive']:
+ self.send_packet(slave, 64, pkt_count, True)
+
+ pkt_now[unbond_port] = [int(_) for _ in self.get_stats(unbond_port, "tx")]
+ pkt_now[bond_port] = [int(_) for _ in self.get_stats(bond_port, "rx")]
+ pkt_now[unbond_port][0] -= pkt_orig[unbond_port][0]
+ pkt_now[bond_port][0] -= pkt_orig[bond_port][0]
+
+ self.verify(pkt_now[unbond_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 test_round_robin_rx_tx(self):
+ self.launch_app()
+ bond_port = self.create_bonded_device(0, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[1], self.dut_ports[2])
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.start_all_ports()
+ self.dut.send_expect("start", "testpmd> ")
+
+ slaves = {}
+ slaves['active'] = [self.dut_ports[0], self.dut_ports[1], self.dut_ports[2]]
+ slaves['inactive'] = []
+ self.verify_round_robin_rx_tx(self.dut_ports[3], bond_port, **slaves)
+
+ def test_round_robin_one_slave_down(self):
+ self.launch_app()
+ bond_port = self.create_bonded_device(0, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[1], self.dut_ports[2])
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.start_all_ports()
+ 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.dut_ports[1], self.dut_ports[2]]
+ slaves['inactive'] = [self.dut_ports[0]]
+ self.verify_round_robin_rx_tx(self.dut_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_slave_down(self):
+ self.launch_app()
+ bond_port = self.create_bonded_device(0, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[1], self.dut_ports[2])
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.start_all_ports()
+ 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.dut_ports[0], self.dut_ports[1], self.dut_ports[2]]
+ self.verify_round_robin_rx_tx(self.dut_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, unbond_port, rx_tx, bond_port, **slaves):
+ """
+ unbond_port: pmd port id
+ rx_tx: '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[unbond_port] = [int(_) for _ in self.get_stats(unbond_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_tx(self, unbond_port, bond_port, **slaves):
+ """
+ slaves:
+ 'active' = []
+ 'inactive' = []
+ """
+ pkt_count = 100
+ pkt_orig = {}
+ pkt_now = {}
+
+ if slaves['active'].__len__() != 0:
+ primary_port = slaves['active'][0]
+ active_flag = 1
+ else:
+ reverse_verify = True
+ active_flag = 0
+
+ # send to unbond port
+ pkt_orig = self.get_all_stats(unbond_port, 'rx', bond_port, **slaves)
+ self.send_packet(unbond_port, 64, pkt_count)
+ pkt_now = self.get_all_stats(unbond_port, 'rx', bond_port, **slaves)
+
+ for key in pkt_now:
+ for num in [0, 1, 2]:
+ pkt_now[key][num] -= pkt_orig[key][num]
+
+ if active_flag == 1:
+ self.verify(pkt_now[primary_port][0] == pkt_count, "Active port not correct TX pkt in mode 1")
+ self.verify(pkt_now[bond_port][0] == pkt_count * active_flag, "Bond port not correct TX pkt in mode 1")
+ for slave in slaves['inactive']:
+ self.verify(pkt_now[slave][0] == 0, "Backup port not correct TX pkt in mode 1")
+
+ # send to primary slave
+ if active_flag == 1:
+ pkt_orig = self.get_all_stats(unbond_port, 'tx', bond_port, **slaves)
+ self.send_packet(primary_port, 64, pkt_count)
+ pkt_now = self.get_all_stats(unbond_port, 'tx', bond_port, **slaves)
+
+ pkt_now[bond_port][0] -= pkt_orig[bond_port][0]
+ pkt_now[unbond_port][0] -= pkt_orig[bond_port][0]
+ for key in pkt_now:
+ for num in [0, 1, 2]:
+ pkt_now[key][num] -= pkt_orig[key][num]
+
+ self.verify(pkt_now[bond_port][0] == pkt_count, "Bond port not correct RX pkt in mode 1")
+ self.verify(pkt_now[unbond_port][0] == pkt_count, "Unbond port not correct TX pkt in mode 1")
+ for slave in slaves['inactive']:
+ self.verify(pkt_now[slave][0] == 0, "Backup port not correct RX pkt in mode 1")
+
+ def test_active_backup_rx_tx(self):
+ self.launch_app()
+ bond_port = self.create_bonded_device(1, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[1], self.dut_ports[2])
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.start_all_ports()
+ self.dut.send_expect("start", "testpmd> ")
+ time.sleep(5)
+
+ slaves = {}
+ slaves['active'] = [self.dut_ports[0]]
+ slaves['inactive'] = [self.dut_ports[1], self.dut_ports[2]]
+ self.verify_active_backup_rx_tx(self.dut_ports[3], bond_port, **slaves)
+
+ def test_active_backup_change_primary(self):
+ self.launch_app()
+ bond_port = self.create_bonded_device(1, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[1], self.dut_ports[2])
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.start_all_ports()
+ self.dut.send_expect("start", "testpmd> ")
+ self.set_primary_for_bonding_device(bond_port, self.dut_ports[1])
+ time.sleep(5)
+
+ slaves = {}
+ slaves['active'] = [self.dut_ports[1]]
+ slaves['inactive'] = [self.dut_ports[0], self.dut_ports[2]]
+ self.verify_active_backup_rx_tx(self.dut_ports[3], bond_port, **slaves)
+
+ def test_active_backup_one_slave_down(self):
+ self.launch_app()
+ bond_port = self.create_bonded_device(1, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[1], self.dut_ports[2])
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.start_all_ports()
+ 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 = {}
+ slaves['active'] = [primary_port]
+ slaves['inactive'] = [self.dut_ports[0], self.dut_ports[1], self.dut_ports[2]]
+ slaves['inactive'].remove(primary_port)
+ self.verify_active_backup_rx_tx(self.dut_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_slave_down(self):
+ self.launch_app()
+ bond_port = self.create_bonded_device(1, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[1], self.dut_ports[2])
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.start_all_ports()
+ 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.dut_ports[0], self.dut_ports[1], self.dut_ports[2]]
+ self.verify_active_backup_rx_tx(self.dut_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):
+ 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):
+ 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):
+ 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):
+ 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):
+ return htons(dest_port ^ src_port)
+
+ def slave_map_hash(self, port, order_ports):
+ if len(order_ports) == 0:
+ return None
+ else:
+ order_ports = order_ports.split()
+ return order_ports.index(str(port))
+
+ def verify_xor_rx(self, unbond_port, bond_port, **slaves):
+ """
+ slaves:
+ 'active'=[]
+ 'inactive'=[]
+ """
+ pkt_count = 100
+ pkt_orig = {}
+ pkt_now = {}
+
+ # send to slave ports
+ pkt_orig = self.get_all_stats(unbond_port, 'tx', bond_port, **slaves)
+ for slave in slaves['active']:
+ self.send_packet(self.dut_ports[slave], 64, pkt_count)
+ pkt_now = self.get_all_stats(unbond_port, 'tx', bond_port, **slaves)
+
+ for key in pkt_now:
+ for num in [0, 1, 2]:
+ pkt_now[key][num] -= pkt_orig[key][num]
+
+ 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[unbond_port][0] == pkt_count * len(slaves['active']), "Unbonded device have error TX packet in XOR")
+
+ def verify_xor_tx(self, unbond_port, bond_port, policy, vlan_tag=False, **slaves):
+ """
+ vlan_tag:False or True
+ policy:'L2' , 'L23' or 'L34'
+ slaves:
+ 'active'=[]
+ 'inactive'=[]
+ """
+ pkt_count = 100
+ pkt_orig = {}
+ pkt_now = {}
+
+ # send to unbond_port
+ pkt_orig = self.get_all_stats(unbond_port, 'rx', bond_port, **slaves)
+
+ dest_mac = self.dut.get_mac_address(self.dut_ports[unbond_port])
+ dest_ip = "10.239.129.88"
+ dest_port = 53
+
+ ether_ip = {}
+ ether = {}
+ ip = {}
+ udp = {}
+
+ ether['dest_mac'] = False
+ ip['dest_ip'] = dest_ip
+ udp['dest_port'] = 53
+ if vlan_tag:
+ dot1q = {}
+ dot1q['vlan'] = random.randint(1, 50)
+ ether_ip['dot1q'] = dot1q
+
+ ether_ip['ether'] = ether
+ ether_ip['ip'] = ip
+ ether_ip['udp'] = udp
+
+ source = [('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)]
+
+ 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
+ self.send_packet(unbond_port, 64, pkt_count, False, **ether_ip)
+ pkt_now = self.get_all_stats(unbond_port, 'rx', bond_port, **slaves)
+
+ for key in pkt_now:
+ for num in [0, 1, 2]:
+ pkt_now[key][num] -= pkt_orig[key][num]
+
+ 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)
+
+ 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):
+ self.launch_app()
+ bond_port = self.create_bonded_device(2, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[1], self.dut_ports[2])
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.start_all_ports()
+ self.dut.send_expect("start", "testpmd> ")
+
+ slaves = {}
+ slaves['active'] = [self.dut_ports[0], self.dut_ports[1], self.dut_ports[2]]
+ slaves['inactive'] = []
+
+ self.verify_xor_tx(self.dut_ports[3], bond_port, "L2", False, **slaves)
+
+ def test_xor_tx_one_slave_down(self):
+ self.launch_app()
+ bond_port = self.create_bonded_device(2, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[2], self.dut_ports[1])
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.start_all_ports()
+ 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.dut_ports[1], self.dut_ports[2]]
+ slaves['inactive'] = [self.dut_ports[0]]
+
+ self.verify_xor_tx(self.dut_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_slave_down(self):
+ self.launch_app()
+ bond_port = self.create_bonded_device(2, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[1], self.dut_ports[2])
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.start_all_ports()
+ 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.dut_ports[0], self.dut_ports[1], self.dut_ports[2]]
+
+ self.verify_xor_tx(self.dut_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):
+ 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):
+ self.launch_app()
+ bond_port = self.create_bonded_device(2, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[1], self.dut_ports[2])
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.set_balance_policy_for_bonding_device(bond_port, "l34")
+ self.start_all_ports()
+ self.dut.send_expect("start", "testpmd> ")
+
+ slaves = {}
+ slaves['active'] = [self.dut_ports[0], self.dut_ports[1], self.dut_ports[2]]
+ slaves['inactive'] = []
+
+ self.verify_xor_tx(self.dut_ports[3], bond_port, "L34", False, **slaves)
+ self.vlan_strip_and_filter('off', self.dut_ports[0], self.dut_ports[1], self.dut_ports[2], self.dut_ports[3], bond_port)
+ self.verify_xor_tx(self.dut_ports[3], bond_port, "L34", True, **slaves)
+
+ def test_xor_rx(self):
+ self.launch_app()
+ bond_port = self.create_bonded_device(2, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[1], self.dut_ports[2])
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.start_all_ports()
+ self.dut.send_expect("start", "testpmd> ")
+
+ slaves = {}
+ slaves['active'] = [self.dut_ports[0], self.dut_ports[1], self.dut_ports[2]]
+ slaves['inactive'] = []
+
+ self.verify_xor_rx(self.dut_ports[3], bond_port, **slaves)
+
+ def verify_broadcast_bonded_rx(self, unbond_port, bond_port, **slaves):
+ """
+ slaves:
+ 'active':[]
+ 'inactive':[]
+ """
+ pkt_count = 100
+ pkt_orig = {}
+ pkt_now = {}
+
+ pkt_orig = self.get_all_stats(unbond_port, 'tx', bond_port, **slaves)
+ for slave in slaves['active']:
+ self.send_packet(slave, 64, pkt_count)
+ pkt_now = self.get_all_stats(unbond_port, 'tx', bond_port, **slaves)
+
+ for key in pkt_now:
+ for num in [0, 1, 2]:
+ pkt_now[key][num] -= pkt_orig[key][num]
+
+ 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[unbond_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_bonded_tx(self, unbond_port, bond_port, **slaves):
+ """
+ slaves:
+ 'actvie':[]
+ 'inactive':[]
+ """
+ pkt_count = 100
+ pkt_orig = {}
+ pkt_now = {}
+
+ # send to unbonded device
+ pkt_orig = self.get_all_stats(unbond_port, 'rx', bond_port, **slaves)
+ self.send_packet(unbond_port, 64, pkt_count)
+ pkt_now = self.get_all_stats(unbond_port, 'rx', bond_port, **slaves)
+
+ for key in pkt_now:
+ for num in [0, 1, 2]:
+ pkt_now[key][num] -= pkt_orig[key][num]
+
+ 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[unbond_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):
+ self.launch_app()
+ bond_port = self.create_bonded_device(3, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[1], self.dut_ports[2])
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.start_all_ports()
+ self.dut.send_expect("start", "testpmd> ")
+
+ slaves = {}
+ slaves['active'] = [self.dut_ports[0], self.dut_ports[1], self.dut_ports[2]]
+ slaves['inactive'] = []
+
+ self.verify_broadcast_bonded_rx(self.dut_ports[3], bond_port, **slaves)
+ self.verify_broadcast_bonded_tx(self.dut_ports[3], bond_port, **slaves)
+
+ def test_broadcast_tx_one_slave_down(self):
+ self.launch_app()
+ bond_port = self.create_bonded_device(3, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[1], self.dut_ports[2])
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.start_all_ports()
+ 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.dut_ports[1], self.dut_ports[2]]
+ slaves['inactive'] = [self.dut_ports[0]]
+
+ self.verify_broadcast_bonded_tx(self.dut_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_slave_down(self):
+ self.launch_app()
+ bond_port = self.create_bonded_device(3, 0)
+ self.add_slave_to_bonding_device(bond_port, False, self.dut_ports[0], self.dut_ports[1], self.dut_ports[2])
+ self.dut.send_expect("set portlist %d,%d" % (self.dut_ports[3], bond_port), "testpmd> ")
+ self.start_all_ports()
+ 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.dut_ports[0], self.dut_ports[1], self.dut_ports[2]]
+
+ self.verify_broadcast_bonded_tx(self.dut_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.dut.send_expect("quit", "# ")
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ pass
diff --git a/tests/TestSuite_timer.py b/tests/TestSuite_timer.py
new file mode 100644
index 0000000..f144bea
--- /dev/null
+++ b/tests/TestSuite_timer.py
@@ -0,0 +1,86 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+Test Timer.
+
+"""
+
+import dcts
+import re
+import time
+
+
+from test_case import TestCase
+
+#
+#
+# Test class.
+#
+
+
+class TestTimer(TestCase):
+
+ #
+ #
+ #
+ # Test cases.
+ #
+
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+
+
+ timer prerequistites
+ """
+ out = self.dut.build_dpdk_apps('examples/timer')
+
+ self.verify("Error" not in out, "compilation error 1")
+ self.verify("No such file" not in out, "compilation error 2")
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ pass
+
+ def test_timer_callbacks_verify(self):
+ """
+ Timer callbacks running on targeted cores
+ """
+
+ # get the mask for the first core
+ cores = self.dut.get_core_list('1S/1C/1T')
+ coreMask = dcts.create_mask(cores)
+
+ # run timer on the background
+ cmdline = "./examples/timer/build/app/timer -n 1 -c " + coreMask + " &"
+
+ self.dut.send_expect(cmdline, "# ", 1)
+ time.sleep(15)
+ out = self.dut.send_expect("killall timer", "# ", 5)
+
+ # verify timer0
+ dcts.regexp(out, r'timer0_cb\(\) on lcore (\d+)')
+ pat = re.compile(r'timer0_cb\(\) on lcore (\d+)')
+ match = pat.findall(out)
+ self.verify(match or match[0] == 0, "timer0 error")
+
+ # verify timer1
+ pat = re.compile(r'timer1_cb\(\) on lcore (\d+)')
+ matchlist = sorted(pat.findall(out))
+ self.verify(cmp(list(set(matchlist)), cores) == 0, "timer1 error")
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ """
+ pass
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ pass
diff --git a/tests/TestSuite_vlan.py b/tests/TestSuite_vlan.py
new file mode 100644
index 0000000..11ef94f
--- /dev/null
+++ b/tests/TestSuite_vlan.py
@@ -0,0 +1,182 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+Test the support of VLAN Offload Features by Poll Mode Drivers.
+
+"""
+
+import dcts
+import time
+
+
+from test_case import TestCase
+
+#
+#
+# Test class.
+#
+
+
+class TestVlan(TestCase):
+
+ #
+ #
+ #
+ # Test cases.
+ #
+
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+
+
+ Vlan Prerequistites
+ """
+
+ # Based on h/w type, choose how many ports to use
+ ports = self.dut.get_ports(self.nic)
+
+ # Verify that enough ports are available
+ self.verify(len(ports) >= 2, "Insufficient ports")
+
+ cores = self.dut.get_core_list('1S/2C/2T')
+ coreMask = dcts.create_mask(cores)
+
+ ports = self.dut.get_ports(self.nic)
+ global valports
+ valports = [_ for _ in ports if self.tester.get_local_port(_) != -1]
+
+ portMask = dcts.create_mask(valports[:2])
+
+ cmd = "./%s/build/app/test-pmd/testpmd -c %s -n 3 -- -i --burst=1 \
+ --mbcache=250 --portmask=%s" % (self.target, coreMask, portMask)
+
+ self.dut.send_expect("%s" % cmd, "testpmd> ", 120)
+ self.dut.send_expect("set verbose 1", "testpmd> ")
+ out = self.dut.send_expect("set fwd mac", "testpmd> ")
+ self.dut.send_expect("vlan set strip off %s" % valports[0], "testpmd> ")
+ self.verify('Set mac packet forwarding mode' in out, "set fwd rxonly error")
+
+ def vlan_send_packet(self, vid, num=1):
+ """
+ Send $num of packet to portid
+ """
+
+ port = self.tester.get_local_port(valports[0])
+ txItf = self.tester.get_interface(port)
+
+ port = self.tester.get_local_port(valports[1])
+ rxItf = self.tester.get_interface(port)
+
+ mac = self.dut.get_mac_address(valports[0])
+
+ # FIXME send a burst with only num packet
+ self.tester.scapy_background()
+ self.tester.scapy_append('p=sniff(iface="%s",count=1,timeout=5)' % rxItf)
+ self.tester.scapy_append('RESULT=str(p)')
+
+ self.tester.scapy_foreground()
+ self.tester.scapy_append('sendp([Ether(dst="%s")/Dot1Q(vlan=%s)/IP(len=46)], iface="%s")' % (mac, vid, txItf))
+
+ self.tester.scapy_execute()
+
+ def set_up(self):
+ """
+ Run before each test case.
+ """
+ pass
+
+ def test_vlan_enable_receipt(self):
+ """
+ Enable receipt of VLAN packets
+ """
+ self.dut.send_expect("set promisc all off", "testpmd> ")
+ self.dut.send_expect("rx_vlan add 1 %s" % valports[0], "testpmd> ")
+ self.dut.send_expect("start", "testpmd> ", 120)
+
+ self.vlan_send_packet(1)
+ out = self.tester.scapy_get_result()
+ self.verify("vlan=1L" in out, "Wrong vlan:" + out)
+
+ self.dut.send_expect("stop", "testpmd> ")
+
+ def test_vlan_disable_receipt(self):
+ """
+ Disable receipt of VLAN packets
+ """
+
+ self.dut.send_expect("rx_vlan rm 1 %s" % valports[0], "testpmd> ")
+ self.dut.send_expect("start", "testpmd> ", 120)
+
+ self.vlan_send_packet(1)
+
+ out = self.tester.scapy_get_result()
+ self.verify("vlan=1L" not in out, "Wrong vlan:" + out)
+
+ out = self.dut.send_expect("stop", "testpmd> ")
+
+ def test_vlan_strip_config_on(self):
+ self.dut.send_expect("vlan set strip on %s" % valports[0], "testpmd> ", 20)
+ self.dut.send_expect("set promisc all off", "testpmd> ", 20)
+ out = self.dut.send_expect("vlan set strip on %s" % valports[0], "testpmd> ", 20)
+ self.verify("strip on" in out, "Wrong strip:" + out)
+
+ self.dut.send_expect("start", "testpmd> ", 120)
+ self.vlan_send_packet(1)
+ out = self.tester.scapy_get_result()
+ self.verify("vlan=1L" not in out, "Wrong vlan:" + out)
+ out = self.dut.send_expect("quit", "#", 120)
+
+ def test_vlan_strip_config_off(self):
+ self.dut.send_expect("vlan set strip off %s" % valports[0], "testpmd> ", 20)
+ out = self.dut.send_expect("show port info %s" % valports[0], "testpmd> ", 20)
+ self.verify("strip off" in out, "Wrong strip:" + out)
+ self.dut.send_expect("set nbport 2", "testpmd> ")
+ self.dut.send_expect("start", "testpmd> ", 120)
+ self.vlan_send_packet(1)
+ out = self.tester.scapy_get_result()
+ self.verify("vlan=1L" in out, "Wrong strip vlan:" + out)
+ out = self.dut.send_expect("stop", "testpmd> ", 120)
+
+ def FAILING_test_vlan_enable_vlan_insertion(self):
+ """
+ Enable VLAN header insertion in transmitted packets
+ """
+
+ port = self.tester.get_local_port(valports[0])
+ intf = self.tester.get_interface(port)
+
+ self.dut.send_expect("set nbport 2", "testpmd> ")
+ self.dut.send_expect("tx_vlan set 1 %s" % valports[0], "testpmd> ")
+
+ self.dut.send_expect("set promisc all on", "testpmd> ")
+ if self.nic == 'hartwell':
+ self.dut.send_expect("vlan set strip on %s" % valports[0], "testpmd> ")
+
+ self.tester.scapy_background()
+ self.tester.scapy_append('p = sniff(iface="%s", count=1, timeout=5)' % intf)
+ self.tester.scapy_append('RESULT=str(p)')
+ self.tester.scapy_foreground()
+
+ self.tester.scapy_execute()
+ time.sleep(2)
+ self.dut.send_expect("start tx_first", "testpmd> ")
+ time.sleep(2)
+
+ out = self.tester.scapy_get_result()
+ self.verify("vlan=1L" in out, "Wrong vlan: " + out)
+ self.dut.send_expect("quit", "# ", 30)
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ """
+ pass
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ pass
diff --git a/tests/TestSuite_whitelist.py b/tests/TestSuite_whitelist.py
new file mode 100644
index 0000000..3ef1756
--- /dev/null
+++ b/tests/TestSuite_whitelist.py
@@ -0,0 +1,197 @@
+# <COPYRIGHT_TAG>
+
+"""
+DPDK Test suite.
+
+Test the support of Whitelist Features by Poll Mode Drivers
+
+"""
+
+import dcts
+import time
+
+
+from test_case import TestCase
+
+#
+#
+# Test class.
+#
+
+
+class TestWhitelist(TestCase):
+
+ #
+ #
+ #
+ # Test cases.
+ #
+
+ def set_up_all(self):
+ """
+ Run at the start of each test suite.
+ Whitelist Prerequistites:
+ Two Ports
+ testpmd can normally started
+ """
+
+ self.frames_to_send = 1
+
+ # Based on h/w type, choose how many ports to use
+ self.dutPorts = self.dut.get_ports(self.nic)
+
+ # Verify that enough ports are available
+ self.verify(len(self.dutPorts) >= 1, "Insufficient ports")
+
+ cores = self.dut.get_core_list('1S/2C/1T')
+ coreMask = dcts.create_mask(cores)
+
+ portMask = dcts.create_mask(self.dutPorts[:2])
+
+ cmd = "./%s/build/app/test-pmd/testpmd -c %s -n 3 -- -i --burst=1 --rxpt=0 \
+ --rxht=0 --rxwt=0 --txpt=36 --txht=0 --txwt=0 --txrst=32 --txfreet=32 --rxfreet=64 --mbcache=250 --portmask=%s" % (self.target, coreMask, portMask)
+ self.dut.send_expect("%s" % cmd, "testpmd> ", 120)
+ self.dut.send_expect("set verbose 1", "testpmd> ")
+
+ # get dest address from self.target port
+ out = self.dut.send_expect("show port info %d" % self.dutPorts[0], "testpmd> ")
+
+ self.dest = self.dut.get_mac_address(self.dutPorts[0])
+ mac_scanner = r"MAC address: (([\dA-F]{2}:){5}[\dA-F]{2})"
+
+ ret = dcts.regexp(out, mac_scanner)
+ self.verify(ret is not None, "MAC address not found")
+ self.verify(cmp(ret.lower(), self.dest) == 0, "MAC address wrong")
+
+ self.max_mac_addr = dcts.regexp(out, "Maximum number of MAC addresses: ([0-9]+)")
+
+ def set_up(self):
+ """
+ Run before each test case.
+ Nothing to do.
+ """
+ pass
+
+ def whitelist_send_packet(self, portid, destMac="00:11:22:33:44:55"):
+ """
+ Send 1 packet to portid.
+ """
+
+ itf = self.tester.get_interface(self.tester.get_local_port(portid))
+
+ self.tester.scapy_foreground()
+ self.tester.scapy_append('sendp([Ether(dst="%s", src="52:00:00:00:00:00")], iface="%s", count=%d)' % (destMac,
+ itf,
+ self.frames_to_send))
+ self.tester.scapy_execute()
+
+ time.sleep(5)
+
+ def test_whitelist_add_remove_mac_address(self):
+ """
+ Add mac address and check packet can received
+ Remove mac address and check packet can't received
+ """
+ # initialise first port without promiscuous mode
+ fake_mac_addr = "01:01:01:00:00:00"
+ portid = self.dutPorts[0]
+ self.dut.send_expect("set promisc %d off" % portid, "testpmd> ")
+
+ out = self.dut.send_expect("show port stats %d" % portid, "testpmd> ")
+ pre_rxpkt = dcts.regexp(out, "RX-packets: ([0-9]+)")
+
+ # send one packet with the portid MAC address
+ self.whitelist_send_packet(portid, self.dest)
+ out = self.dut.send_expect("show port stats %d" % portid, "testpmd> ")
+ cur_rxpkt = dcts.regexp(out, "RX-packets: ([0-9]+)")
+ # check the packet increase
+ self.verify(int(cur_rxpkt) == int(pre_rxpkt) + self.frames_to_send,
+ "Packet has not been received on default address")
+ # send one packet to a different MAC address
+ # new_mac = self.dut.get_mac_address(portid)
+ self.whitelist_send_packet(portid, fake_mac_addr)
+
+ pre_rxpkt = cur_rxpkt
+ out = self.dut.send_expect("show port stats %d" % portid, "testpmd> ")
+ cur_rxpkt = dcts.regexp(out, "RX-packets: ([0-9]+)")
+
+ # check the packet DO NOT increase
+ self.verify(int(cur_rxpkt) == int(pre_rxpkt),
+ "Packet has been received on a new MAC address that has not been added yet")
+ # add the different MAC address
+ out = self.dut.send_expect("mac_addr add %d" % portid + " %s" % fake_mac_addr, "testpmd>")
+
+ # send again one packet to a different MAC address
+ self.whitelist_send_packet(portid, fake_mac_addr)
+
+ pre_rxpkt = cur_rxpkt
+ out = self.dut.send_expect("show port stats %d" % portid, "testpmd> ")
+ cur_rxpkt = dcts.regexp(out, "RX-packets: ([0-9]+)")
+
+ # check the packet increase
+ self.verify(int(cur_rxpkt) == int(pre_rxpkt) + self.frames_to_send,
+ "Packet has not been received on a new MAC address that has been added to the port")
+
+ # remove the fake MAC address
+ out = self.dut.send_expect("mac_addr remove %d" % portid + " %s" % fake_mac_addr, "testpmd>")
+
+ # send again one packet to a different MAC address
+ self.whitelist_send_packet(portid, fake_mac_addr)
+
+ pre_rxpkt = cur_rxpkt
+ out = self.dut.send_expect("show port stats %d" % portid, "testpmd> ")
+ cur_rxpkt = dcts.regexp(out, "RX-packets: ([0-9]+)")
+
+ # check the packet increase
+ self.verify(int(cur_rxpkt) == int(pre_rxpkt),
+ "Packet has been received on a new MAC address that has been removed from the port")
+ self.dut.send_expect("stop", "testpmd> ")
+
+ def test_whitelist_invalid_addresses(self):
+ """
+ Invalid operation:
+ Add NULL MAC should not be added
+ Remove using MAC will be failed
+ Add Same MAC twice will be failed
+ Add more than MAX number will be failed
+ """
+
+ portid = self.dutPorts[0]
+ fake_mac_addr = "00:00:00:00:00:00"
+
+ # add an address with all zeroes to the port (-EINVAL)
+ out = self.dut.send_expect("mac_addr add %d" % portid + " %s" % fake_mac_addr, "testpmd>")
+ self.verify("Invalid argument" in out, "Added a NULL MAC address")
+
+ # remove the default MAC address (-EADDRINUSE)
+ out = self.dut.send_expect("mac_addr remove %d" % portid + " %s" % self.dest, "testpmd>")
+ self.verify("Address already in use" in out, "default address removed")
+
+ # add same address 2 times
+ fake_mac_addr = "00:00:00:00:00:01"
+ out = self.dut.send_expect("mac_addr add %d" % portid + " %s" % fake_mac_addr, "testpmd>")
+ out = self.dut.send_expect("mac_addr add %d" % portid + " %s" % fake_mac_addr, "testpmd>")
+ self.verify("error" not in out, "added 2 times the same address with an error")
+
+ # add 1 address more that max number
+ i = 0
+ base_addr = "01:00:00:00:00:"
+ while i <= int(self.max_mac_addr):
+ new_addr = base_addr + "%0.2X" % i
+ out = self.dut.send_expect("mac_addr add %d" % portid + " %s" % new_addr, "testpmd>")
+ i = i + 1
+
+ self.verify("No space left on device" in out, "added 1 address more than max MAC addresses")
+
+ def tear_down(self):
+ """
+ Run after each test case.
+ Nothing to do.
+ """
+ pass
+
+ def tear_down_all(self):
+ """
+ Run after each test suite.
+ """
+ self.dut.send_expect("quit", "# ", 10)