[dts] [PATCH v1 2/2] tests: add test suite for elastic flow distributor

Marvin Liu yong.liu at intel.com
Thu Jul 27 16:19:37 CEST 2017


Signed-off-by: Marvin Liu <yong.liu at intel.com>

diff --git a/tests/TestSuite_efd.py b/tests/TestSuite_efd.py
new file mode 100644
index 0000000..991f99a
--- /dev/null
+++ b/tests/TestSuite_efd.py
@@ -0,0 +1,244 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#   * Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+#   * Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in
+#     the documentation and/or other materials provided with the
+#     distribution.
+#   * Neither the name of Intel Corporation nor the names of its
+#     contributors may be used to endorse or promote products derived
+#     from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""
+DPDK Test suite.
+"""
+import re
+import utils
+from test_case import TestCase
+from etgen import IxiaPacketGenerator
+
+
+class TestEFD(TestCase, IxiaPacketGenerator):
+    def set_up_all(self):
+        """
+        Run at the start of each test suite.
+        """
+        self.tester.extend_external_packet_generator(TestEFD, self)
+
+        out = self.dut.send_expect("make -C test -j", "#")
+        self.verify("Error" not in out, "Compilation error")
+        self.verify("No such" not in out, "Compilation error")
+
+        out = self.dut.build_dpdk_apps("./examples/server_node_efd")
+        self.verify("Error" not in out, "Compilation error")
+        self.verify("No such" not in out, "Compilation error")
+
+        self.dut_ports = self.dut.get_ports()
+        self.node_app = "./examples/server_node_efd/node/%s/node" % self.target
+        self.server_app = "./examples/server_node_efd/server/%s/server" % self.target
+
+    def set_up(self):
+        """
+        Run before each test case.
+        """
+        pass
+
+    def test_efd_unit(self):
+        """
+        Run EFD unit test
+        """
+        self.dut.send_expect("./test/test/test -n 1 -c f", "RTE>>", 60)
+        out = self.dut.send_expect("efd_autotest", "RTE>>", 60)
+        self.dut.send_expect("quit", "# ")
+        self.verify("Test OK" in out, "Test failed")
+
+    def test_efd_unit_perf(self):
+        """
+        Run EFD unit perf test
+        """
+        self.dut.send_expect("./test/test/test -n 1 -c f", "RTE>>", 60)
+        out = self.dut.send_expect("efd_perf_autotest", "RTE>>", 120)
+        self.logger.info(out)
+        self.dut.send_expect("quit", "# ")
+        self.verify("Test OK" in out, "Test failed")
+
+    def test_perf_efd_nodenum(self):
+        """
+        Run EFD perf evaluation for number of nodes
+        """
+        self.verify(len(self.dut_ports) >= 2, "Not enough ports")
+        node_nums = [1, 2, 3, 4, 5, 6, 7, 8]
+
+        flow_num = 1024 * 1024 * 2
+
+        table_header = ["Value Bits",
+                        "Nodes",
+                        "Flow Entries",
+                        "Throughput(mpps)"]
+
+        self.result_table_create(table_header)
+        # perf of different nodes
+        for node_num in node_nums:
+            pps = self._efd_perf_evaluate(node_num, flow_num)
+
+            self.result_table_add([8, node_num, "2M",  pps])
+
+        self.result_table_print()
+
+    def test_perf_efd_flownums(self):
+        """
+        Run EFD perf evaluation for millions of flows
+        """
+        self.logger.warning("Millions of flow required huge memory, please allocate 16G hugepage")
+        self.dut.setup_memory_linux(hugepages=8192)
+        self.verify(len(self.dut_ports) >= 2, "Not enough ports")
+        flow_nums = [1024 * 1024, 1024 * 1024 * 2, 1024 * 1024 * 4,
+                     1024 * 1024 * 8, 1024 * 1024 * 16, 1024 * 1024 * 32]
+
+        table_header = ["Value Bits",
+                        "Nodes",
+                        "Million Flows",
+                        "Throughput(mpps)"]
+
+        self.result_table_create(table_header)
+
+        # perf of different flow numbers
+        for flow_num in flow_nums:
+            pps = self._efd_perf_evaluate(2, flow_num)
+
+            self.result_table_add([8, 2, flow_num / (1024 * 1024),  pps])
+
+        self.result_table_print()
+
+    def test_perf_efd_valuesize(self):
+        """
+        Run EFD perf evaluation for different value size
+        """
+        self.verify(len(self.dut_ports) >= 2, "Not enough ports")
+        val_bitnums = [8, 16, 24, 32]
+        flow_num = 1024 * 1024 * 2
+
+        table_header = ["Value Bits",
+                        "Nodes",
+                        "Flow Entries",
+                        "Throughput(mpps)"]
+
+        self.result_table_create(table_header)
+        # perf of different value bit lengths
+        for val_bitnum in val_bitnums:
+            # change value length and rebuild dpdk
+            self.dut.send_expect("sed -i -e 's/#define RTE_EFD_VALUE_NUM_BITS .*$/#define RTE_EFD_VALUE_NUM_BITS (%d)/' lib/librte_efd/rte_efd.h" % val_bitnum, "#")
+            self.dut.build_install_dpdk(self.target)
+            out = self.dut.build_dpdk_apps("./examples/server_node_efd")
+            self.verify("Error" not in out, "Compilation error")
+            self.verify("No such" not in out, "Compilation error")
+
+            pps = self._efd_perf_evaluate(2, flow_num)
+            self.result_table_add([val_bitnum, 2, "2M",  pps])
+
+        self.result_table_print()
+        self.dut.send_expect("sed -i -e 's/#define RTE_EFD_VALUE_NUM_BITS .*$/#define RTE_EFD_VALUE_NUM_BITS (8)' lib/librte_efd/rte_efd.h", "#")
+        self.dut.build_install_dpdk(self.target)
+        out = self.dut.build_dpdk_apps("./examples/server_node_efd")
+        self.verify("Error" not in out, "Compilation error")
+        self.verify("No such" not in out, "Compilation error")
+
+    def _efd_perf_evaluate(self, node_num, flow_num):
+        # extended flow number into etgen module
+        self.tester.ixia_packet_gen.flow_num = flow_num
+
+        # output port is calculated from overall ports number
+        server_cmd_fmt = "%s -c %s -n %d -w %s -w %s -- -p 0x3 -n %d -f %s"
+        node_cmd_fmt = "%s -c %s -n %d --proc-type=secondary -- -n %d"
+        socket = self.dut.get_numa_id(self.dut_ports[0])
+
+        self.tester.scapy_append('wrpcap("efd.pcap", [Ether()/IP(src="0.0.0.0", dst="0.0.0.0")/("X"*26)])')
+        self.tester.scapy_execute()
+
+        tgen_input = []
+        rx_port = self.tester.get_local_port(self.dut_ports[0])
+        tx_port = self.tester.get_local_port(self.dut_ports[1])
+
+        tgen_input.append((tx_port, rx_port, "efd.pcap"))
+        tgen_input.append((rx_port, tx_port, "efd.pcap"))
+
+        cores = self.dut.get_core_list("1S/%dC/1T" % (node_num + 2), socket)
+
+        self.verify(len(cores), "Can't find enough cores")
+
+        server_cmd = server_cmd_fmt % (self.server_app, utils.create_mask(cores[0:2]),
+                                       self.dut.get_memory_channels(),
+                                       self.dut.get_port_pci(self.dut_ports[0]),
+                                       self.dut.get_port_pci(self.dut_ports[1]),
+                                       node_num, hex(flow_num))
+
+        # create table may need few minutes
+        self.dut.send_expect(server_cmd, "Finished Process Init", timeout=240)
+
+        node_sessions = []
+        for node in range(node_num):
+            node_cmd = node_cmd_fmt % (self.node_app, utils.create_mask([cores[2 + node]]),
+                                       self.dut.get_memory_channels(), node)
+            node_session = self.dut.new_session(suite="node%d" % node)
+            node_sessions.append(node_session)
+            node_session.send_expect(node_cmd, "Finished Process Init", timeout=30)
+
+        _, pps = self.tester.traffic_generator_throughput(tgen_input, delay=10)
+
+        for node_session in node_sessions:
+            node_session.send_expect("^C", "#")
+            self.dut.close_session(node_session)
+
+        self.dut.send_expect("^C", "#")
+
+        pps /= 1000000.0
+        return pps
+
+    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 ipIdle")
+        self.add_tcl_cmd('ip config -destIpAddr "%s"' % dst)
+        self.add_tcl_cmd("ip config -destIpAddrMode ipIncrHost")
+        # increase number equal to flow number
+        self.add_tcl_cmd("ip config -destIpAddrRepeatCount %d" % self.flow_num)
+        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 ipV4ProtocolReserved255")
+        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.
+        """
+        self.dut.kill_all()
+        pass
+
+    def tear_down_all(self):
+        """
+        Run after each test suite.
+        """
+        pass
-- 
1.9.3



More information about the dts mailing list