From: Owen Hilyard <ohilyard@iol.unh.edu>
To: dts@dpdk.org
Cc: nhorman@tuxdriver.com, jerinj@marvell.com, skori@marvell.com,
anatoly.burakov@intel.com, ferruh.yigit@intel.com,
lijuan.tu@intel.com, lylavoie@iol.unh.edu,
Owen Hilyard <ohilyard@iol.unh.edu>
Subject: [dts] [PATCH] linux kernel modules: add tests
Date: Wed, 5 Aug 2020 09:52:30 -0400 [thread overview]
Message-ID: <20200805135231.1579592-1-ohilyard@iol.unh.edu> (raw)
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UFT-8, Size: 18429 bytes --]
add vfio-pci test suite
add igb_uio test suite
add uio_pci_generic test suite
add test suite documentation
add new setting UNPRIVILEGED_USERNAME
add check for file existence when getting dpdk pids
dpdk processes run in memory will not create the expected files
add return to DPDKdut.bind_interfaces_linux to allow for error checking
Signed-off-by: Owen Hilyard <ohilyard@iol.unh.edu>
---
framework/crb.py | 40 +++---
framework/project_dpdk.py | 2 +-
framework/settings.py | 2 +
test_plans/linux_modules_test_plan.rst | 158 ++++++++++++++++++++++
tests/TestSuite_linux_modules.py | 173 +++++++++++++++++++++++++
5 files changed, 356 insertions(+), 19 deletions(-)
create mode 100644 test_plans/linux_modules_test_plan.rst
create mode 100644 tests/TestSuite_linux_modules.py
diff --git a/framework/crb.py b/framework/crb.py
index a47de2c..d456fab 100644
--- a/framework/crb.py
+++ b/framework/crb.py
@@ -499,27 +499,31 @@ class Crb(object):
pids = []
pid_reg = r'p(\d+)'
for config_file in file_directorys:
- cmd = 'lsof -Fp %s' % config_file
- out = self.send_expect(cmd, "# ", 20, alt_session)
- if len(out):
- lines = out.split('\r\n')
- for line in lines:
- m = re.match(pid_reg, line)
- if m:
- pids.append(m.group(1))
- for pid in pids:
- self.send_expect('kill -9 %s' % pid, '# ', 20, alt_session)
- self.get_session_output(timeout=2)
+ # Covers case where the process is run as a unprivileged user and does not generate the file
+ if os.path.isfile(config_file):
+ cmd = 'lsof -Fp %s' % config_file
+ out = self.send_expect(cmd, "# ", 20, alt_session)
+ if len(out):
+ lines = out.split('\r\n')
+ for line in lines:
+ m = re.match(pid_reg, line)
+ if m:
+ pids.append(m.group(1))
+ for pid in pids:
+ self.send_expect('kill -9 %s' % pid, '# ', 20, alt_session)
+ self.get_session_output(timeout=2)
hugepage_info = ['/var/run/dpdk/%s/hugepage_info' % file_prefix for file_prefix in prefix_list]
for hugepage in hugepage_info:
- cmd = 'lsof -Fp %s' % hugepage
- out = self.send_expect(cmd, "# ", 20, alt_session)
- if len(out) and "No such file or directory" not in out:
- self.logger.warning("There are some dpdk process not free hugepage")
- self.logger.warning("**************************************")
- self.logger.warning(out)
- self.logger.warning("**************************************")
+ # Covers case where the process is run as a unprivileged user and does not generate the file
+ if os.path.isfile(hugepage):
+ cmd = 'lsof -Fp %s' % hugepage
+ out = self.send_expect(cmd, "# ", 20, alt_session)
+ if len(out) and "No such file or directory" not in out:
+ self.logger.warning("There are some dpdk process not free hugepage")
+ self.logger.warning("**************************************")
+ self.logger.warning(out)
+ self.logger.warning("**************************************")
# remove directory
directorys = ['/var/run/dpdk/%s' % file_prefix for file_prefix in prefix_list]
diff --git a/framework/project_dpdk.py b/framework/project_dpdk.py
index 040d070..03ace46 100644
--- a/framework/project_dpdk.py
+++ b/framework/project_dpdk.py
@@ -434,7 +434,7 @@ class DPDKdut(Dut):
current_nic += 1
bind_script_path = self.get_dpdk_bind_script()
- self.send_expect('%s --force %s' % (bind_script_path, binding_list), '# ')
+ return self.send_expect('%s --force %s' % (bind_script_path, binding_list), '# ')
def unbind_interfaces_linux(self, nics_to_bind=None):
"""
diff --git a/framework/settings.py b/framework/settings.py
index f91452d..850fa89 100644
--- a/framework/settings.py
+++ b/framework/settings.py
@@ -197,6 +197,8 @@ SCAPY2IXIA = [
USERNAME = 'root'
+# A user used to test functionality for a non-root user
+UNPRIVILEGED_USERNAME = 'dtsunprivilegedtester'
"""
Helpful header sizes.
diff --git a/test_plans/linux_modules_test_plan.rst b/test_plans/linux_modules_test_plan.rst
new file mode 100644
index 0000000..c7bb2d0
--- /dev/null
+++ b/test_plans/linux_modules_test_plan.rst
@@ -0,0 +1,158 @@
+.. # BSD LICENSE
+ #
+ # Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ # Copyright © 2018[, 2019] The University of New Hampshire. 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.
+
+==================
+Linux Driver Tests
+==================
+
+This file contains multiple test suites to avoid a single unsupported
+kernel module causing the entire test suite to fail. These test suites
+cover a variety of kernel modules and are built to check their function
+both in use as root and as an unprivileged user. All of the test suites
+run the same tests. In the documentation for test cases, <MODULE> will
+represent the name of the module being tested. <DEV INTERFACE> will
+represent the character interface under /dev/ for the interface.
+
+Prerequisites
+=============
+
+There are two prerequisites. First, all of the drivers that you wish
+to test must be compiled and installed so that they are available through
+modprobe. Secondly, there should be a user on the dut which has the same
+password as the primary account for dts. This account will be used as the
+unprivileged user, but it still should have permission to lock at least
+1 GiB of memory to ensure that it can lock all of the process memory.
+
+Test Suites
+===========
+
+There is 1 test suite per module, the modules are as follows:
+
+ * VFIO-PCI
+ * UIO PCI GENERIC
+ * IGB UIO
+
+Test Case: TX RX
+====================
+This test case runs as root and is designed to check the basic functioning
+of the module. It checks whether packets can be sent and received.
+
+Remove old module ::
+
+ # rmmod <MODULE>
+
+Add the new one ::
+
+ # modprobe <MODULE>
+
+Bind the interface to the driver ::
+
+ # usertools/dpdk-devbind.py --force --bind=<MODULE> xxxx:xx:xx.x
+
+Start testpmd in a loop configuration ::
+
+ # x86_64-native-linux-gcc/app/testpmd -l 1,2 -n 4 -w xxxx:xx:xx.x \
+ -- -i --port-topology=loop
+
+Start packet forwarding ::
+
+ testpmd> start
+
+Start a packet capture on the tester::
+
+ # tcpdump -i (interface) ether src (tester mac address)
+
+Send some packets to the dut and check that they are properly sent back into
+the packet capture on the tester.
+
+Test Case: TX RX Userspace
+====================
+This test case runs as the unprivileged user and is designed to check the
+basic functioning of the module. It checks whether packets can be sent
+and received when running dpdk applications as a normal user. # means
+that a command is run as root. $ means that a command is run as the user.
+The igb_uio module requires that the iova mode is in virtual address mode,
+which can be done by adding the flag "--iova-mode va" as an eal option to
+testpmd.
+
+Remove old module ::
+
+ # rmmod <MODULE>
+
+Add the new one ::
+
+ # modprobe <MODULE>
+
+Bind the interface to the driver ::
+
+ # usertools/dpdk-devbind.py --force --bind=<MODULE> xxxx:xx:xx.x
+
+Grant permissions for all users to access the new character device ::
+
+ # setfacl -m u:dtsunprivilegedtester:rwx <DEV INTERFACE>
+
+Start testpmd in a loop configuration ::
+
+ $ x86_64-native-linux-gcc/app/testpmd -l 1,2 -n 4 -w xxxx:xx:xx.x --in-memory \
+ -- -i --port-topology=loop
+
+Start packet forwarding ::
+
+ testpmd> start
+
+Start a packet capture on the tester::
+
+ # tcpdump -i (interface) ether src (tester mac address)
+
+Send some packets to the dut and check that they are properly sent back into
+the packet capture on the tester.
+
+Test Case: Hello World
+====================
+This is a more basic test of functionality as a normal user than the
+TX RX Userspace case. It simply involves running a short, hello-world-like
+program on each core before shutting down. # means that a command is run
+as root. $ means that a command is run as the user. The igb_uio module
+requires that the iova mode is in virtual address mode, which can be done
+by adding the flag "--iova-mode va" as an eal option to the hello world
+application.
+
+Compile the application ::
+
+ # cd $RTE_SDK/examples/helloworld && make
+
+Run the application ::
+
+ $ $RTE_SDK/examples/helloworld/build/helloworld-shared --in-memory
+
+Check for any error states or reported errors.
+
diff --git a/tests/TestSuite_linux_modules.py b/tests/TestSuite_linux_modules.py
new file mode 100644
index 0000000..7cb479d
--- /dev/null
+++ b/tests/TestSuite_linux_modules.py
@@ -0,0 +1,173 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+# Copyright © 2018[, 2019] The University of New Hampshire. 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.
+Linux Kernel Modules example.
+"""
+import os
+import time
+
+from pmd_output import PmdOutput
+from test_case import TestCase
+
+from framework import settings
+
+ETHER_HEADER_LEN = 18
+IP_HEADER_LEN = 20
+ETHER_STANDARD_MTU = 1518
+ETHER_JUMBO_FRAME_MTU = 9000
+
+
+# A class like this is used because doing inheritance normally breaks the test case discovery process
+class LinuxModulesHelperMethods:
+ driver: str
+ dev_interface: str
+ additional_eal_options: str
+
+ def set_up_all(self):
+ """
+ Prerequisite steps for each test suit.
+ """
+ self.dut_ports = self.dut.get_ports()
+ self.pmdout = PmdOutput(self.dut)
+ pci_address = self.dut.ports_info[self.dut_ports[0]]['pci']
+ self.old_driver = settings.get_nic_driver(pci_address)
+ out = self.dut.bind_interfaces_linux(driver=self.driver)
+ self.verify("bind failed" not in out, f"Failed to bind {self.driver}")
+ self.verify("not loaded" not in out, f"{self.driver} was not loaded")
+
+ def send_scapy_packet(self, port_id: int, packet: str):
+ itf = self.tester.get_interface(port_id)
+
+ self.tester.scapy_foreground()
+ self.tester.scapy_append(f'sendp({packet}, iface="{itf}")')
+ return self.tester.scapy_execute()
+
+ def tear_down(self):
+ self.dut.kill_all()
+
+ def run_example_program_in_userspace(self, directory: str, program: str):
+ """
+ A function to run a given example program as an unprivileged user.
+ @param directory: The directory under examples where the app is
+ @param program: the name of the binary to run
+ """
+ out: str = self.dut.build_dpdk_apps(f"$RTE_SDK/examples/{directory}")
+ self.verify("Error" not in out, "Compilation error")
+ self.verify("No such" not in out, "Compilation error")
+
+ program_build_location = f"$RTE_SDK/examples/{directory}/build/{program}"
+ program_user_location = f"/tmp/dut/bin/{program}"
+
+ self.dut.send_expect(f"chmod +x {program_build_location}", "# ")
+ self.dut.send_expect("mkdir -p /tmp/dut/bin/", "# ")
+ user_home_dir = self.dut.send_expect(f"cp {program_build_location} {program_user_location}", "# ")
+
+ self.dut.alt_session.send_expect(f"su {settings.UNPRIVILEGED_USERNAME}", "# ")
+ self.dut.alt_session.send_expect(f"{program_user_location} --in-memory {self.additional_eal_options}", "# ")
+ out: str = self.dut.alt_session.send_expect("echo $?", "# ")
+ self.dut.alt_session.send_expect("exit", "# ") # Return to root session
+ self.verify(out.strip() == "0", f"{program} exited in an error state")
+
+ def tx_rx_test_helper(self, pmdout, param="", eal_param=""):
+ pmdout.start_testpmd("Default", param=f"--port-topology=loop {param}",
+ eal_param=f"{eal_param} {self.additional_eal_options}")
+ pmdout.execute_cmd("start")
+ dut_mac = self.dut.get_mac_address(self.dut_ports[0])
+ tester_mac = self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))
+ iface = self.tester.get_interface(self.dut_ports[0])
+ pcap_path: str = f"/tmp/tester/test-{self.driver}.pcap"
+ self.tester.send_expect(f"tcpdump -i {iface} -w /tmp/tester/test-{self.driver}.pcap ether src {tester_mac} &",
+ "# ")
+ self.tester.send_expect(f"TCPDUMP_PID=$!", "# ")
+ self.send_scapy_packet(self.dut_ports[0],
+ f"[Ether(dst='{dut_mac}', src='{tester_mac}')/IP()/TCP()/('a') for i in range(20)]")
+ time.sleep(.1)
+ self.tester.send_expect("kill -SIGINT $TCPDUMP_PID", "# ")
+ os.system(f"mkdir -p {settings.FOLDERS['Output']}/tmp/pcap/")
+ self.tester.session.copy_file_from(pcap_path, dst=os.path.join(settings.FOLDERS['Output'], "tmp/pcap/"))
+ out: str = self.tester.send_expect(f"tcpdump -r /tmp/tester/test-{self.driver}.pcap", "# ")
+ self.verify(len(out.splitlines()) >= 20, "Not all packets were received by the tester.")
+ pmdout.quit()
+
+ #
+ #
+ #
+ # Test cases.
+ #
+
+ def tear_down_all(self):
+ """
+ When the case of this test suite finished, the environment should
+ clear up.
+ """
+ self.dut.bind_interfaces_linux(driver=self.old_driver)
+ self.dut.kill_all()
+
+ def test_tx_rx(self):
+ """
+ Preforms the testing that needs to be done as root.
+ @param driver: The driver to test
+ """
+ self.tx_rx_test_helper(self.pmdout)
+
+ def test_helloworld(self):
+ self.run_example_program_in_userspace("helloworld", "helloworld-shared")
+
+ def test_tx_rx_userspace(self):
+ app_path = self.dut.apps_name['test-pmd']
+ self.dut.send_expect(f"chmod +rx {app_path}", "#")
+ path = self.dut.send_expect("pwd", "#")
+ self.dut.alt_session.send_expect(f"su {settings.UNPRIVILEGED_USERNAME}", "#")
+ self.dut.alt_session.send_expect(f"cd {path}", "#")
+ self.dut.send_expect(f"setfacl -m u:{settings.UNPRIVILEGED_USERNAME}:rwx {self.dev_interface}", "#")
+ self.tx_rx_test_helper(PmdOutput(self.dut, session=self.dut.alt_session), eal_param="--in-memory")
+ self.dut.alt_session.send_expect(f"exit", "#")
+
+
+class TestVfio(LinuxModulesHelperMethods, TestCase):
+ driver = "vfio-pci"
+ dev_interface = "/dev/vfio/*"
+ additional_eal_options = ""
+
+
+class TestIgbuio(LinuxModulesHelperMethods, TestCase):
+ driver = "igb_uio"
+ dev_interface = "/dev/uio*"
+ additional_eal_options = "--iova-mode va"
+
+
+class TestUioPciGeneric(LinuxModulesHelperMethods, TestCase):
+ driver = "uio_pci_generic"
+ dev_interface = "/dev/uio*"
+ additional_eal_options = ""
--
2.25.1
next reply other threads:[~2020-08-05 13:52 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-08-05 13:52 Owen Hilyard [this message]
2020-08-05 14:05 ` [dts] [PATCH] linux kernel module: fix typo Owen Hilyard
2020-08-05 14:56 ` [dts] [PATCH V2] " Owen Hilyard
2020-08-12 2:48 ` Tu, Lijuan
2020-08-12 2:46 ` [dts] [PATCH] linux kernel modules: add tests Tu, Lijuan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200805135231.1579592-1-ohilyard@iol.unh.edu \
--to=ohilyard@iol.unh.edu \
--cc=anatoly.burakov@intel.com \
--cc=dts@dpdk.org \
--cc=ferruh.yigit@intel.com \
--cc=jerinj@marvell.com \
--cc=lijuan.tu@intel.com \
--cc=lylavoie@iol.unh.edu \
--cc=nhorman@tuxdriver.com \
--cc=skori@marvell.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).