162306a36Sopenharmony_citdc - Linux Traffic Control (tc) unit testing suite 262306a36Sopenharmony_ci 362306a36Sopenharmony_ciAuthor: Lucas Bates - lucasb@mojatatu.com 462306a36Sopenharmony_ci 562306a36Sopenharmony_citdc is a Python script to load tc unit tests from a separate JSON file and 662306a36Sopenharmony_ciexecute them inside a network namespace dedicated to the task. 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci 962306a36Sopenharmony_ciREQUIREMENTS 1062306a36Sopenharmony_ci------------ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci* Minimum Python version of 3.4. Earlier 3.X versions may work but are not 1362306a36Sopenharmony_ci guaranteed. 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci* The kernel must have network namespace support if using nsPlugin 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci* The kernel must have veth support available, as a veth pair is created 1862306a36Sopenharmony_ci prior to running the tests when using nsPlugin. 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci* The kernel must have the appropriate infrastructure enabled to run all tdc 2162306a36Sopenharmony_ci unit tests. See the config file in this directory for minimum required 2262306a36Sopenharmony_ci features. As new tests will be added, config options list will be updated. 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci* All tc-related features being tested must be built in or available as 2562306a36Sopenharmony_ci modules. To check what is required in current setup run: 2662306a36Sopenharmony_ci ./tdc.py -c 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci Note: 2962306a36Sopenharmony_ci In the current release, tdc run will abort due to a failure in setup or 3062306a36Sopenharmony_ci teardown commands - which includes not being able to run a test simply 3162306a36Sopenharmony_ci because the kernel did not support a specific feature. (This will be 3262306a36Sopenharmony_ci handled in a future version - the current workaround is to run the tests 3362306a36Sopenharmony_ci on specific test categories that your kernel supports) 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ciBEFORE YOU RUN 3762306a36Sopenharmony_ci-------------- 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ciThe path to the tc executable that will be most commonly tested can be defined 4062306a36Sopenharmony_ciin the tdc_config.py file. Find the 'TC' entry in the NAMES dictionary and 4162306a36Sopenharmony_cidefine the path. 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ciIf you need to test a different tc executable on the fly, you can do so by 4462306a36Sopenharmony_ciusing the -p option when running tdc: 4562306a36Sopenharmony_ci ./tdc.py -p /path/to/tc 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ciRUNNING TDC 4962306a36Sopenharmony_ci----------- 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ciTo use tdc, root privileges are required. This is because the 5262306a36Sopenharmony_cicommands being tested must be run as root. The code that enforces 5362306a36Sopenharmony_ciexecution by root uid has been moved into a plugin (see PLUGIN 5462306a36Sopenharmony_ciARCHITECTURE, below). 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ciTests that use a network device should have nsPlugin.py listed as a 5762306a36Sopenharmony_cirequirement for that test. nsPlugin executes all commands within a 5862306a36Sopenharmony_cinetwork namespace and creates a veth pair which may be used in those test 5962306a36Sopenharmony_cicases. To disable execution within the namespace, pass the -N option 6062306a36Sopenharmony_cito tdc when starting a test run; the veth pair will still be created 6162306a36Sopenharmony_ciby the plugin. 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ciRunning tdc without any arguments will run all tests. Refer to the section 6462306a36Sopenharmony_cion command line arguments for more information, or run: 6562306a36Sopenharmony_ci ./tdc.py -h 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_citdc will list the test names as they are being run, and print a summary in 6862306a36Sopenharmony_ciTAP (Test Anything Protocol) format when they are done. If tests fail, 6962306a36Sopenharmony_cioutput captured from the failing test will be printed immediately following 7062306a36Sopenharmony_cithe failed test in the TAP output. 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ciOVERVIEW OF TDC EXECUTION 7462306a36Sopenharmony_ci------------------------- 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ciOne run of tests is considered a "test suite" (this will be refined in the 7762306a36Sopenharmony_cifuture). A test suite has one or more test cases in it. 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ciA test case has four stages: 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci - setup 8262306a36Sopenharmony_ci - execute 8362306a36Sopenharmony_ci - verify 8462306a36Sopenharmony_ci - teardown 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ciThe setup and teardown stages can run zero or more commands. The setup 8762306a36Sopenharmony_cistage does some setup if the test needs it. The teardown stage undoes 8862306a36Sopenharmony_cithe setup and returns the system to a "neutral" state so any other test 8962306a36Sopenharmony_cican be run next. These two stages require any commands run to return 9062306a36Sopenharmony_cisuccess, but do not otherwise verify the results. 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ciThe execute and verify stages each run one command. The execute stage 9362306a36Sopenharmony_citests the return code against one or more acceptable values. The 9462306a36Sopenharmony_civerify stage checks the return code for success, and also compares 9562306a36Sopenharmony_cithe stdout with a regular expression. 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ciEach of the commands in any stage will run in a shell instance. 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ciUSER-DEFINED CONSTANTS 10162306a36Sopenharmony_ci---------------------- 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ciThe tdc_config.py file contains multiple values that can be altered to suit 10462306a36Sopenharmony_ciyour needs. Any value in the NAMES dictionary can be altered without affecting 10562306a36Sopenharmony_cithe tests to be run. These values are used in the tc commands that will be 10662306a36Sopenharmony_ciexecuted as part of the test. More will be added as test cases require. 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ciExample: 10962306a36Sopenharmony_ci $TC qdisc add dev $DEV1 ingress 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ciThe NAMES values are used to substitute into the commands in the test cases. 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ciCOMMAND LINE ARGUMENTS 11562306a36Sopenharmony_ci---------------------- 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ciRun tdc.py -h to see the full list of available arguments. 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ciusage: tdc.py [-h] [-p PATH] [-D DIR [DIR ...]] [-f FILE [FILE ...]] 12062306a36Sopenharmony_ci [-c [CATG [CATG ...]]] [-e ID [ID ...]] [-l] [-s] [-i] [-v] [-N] 12162306a36Sopenharmony_ci [-d DEVICE] [-P] [-n] [-V] 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ciLinux TC unit tests 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cioptional arguments: 12662306a36Sopenharmony_ci -h, --help show this help message and exit 12762306a36Sopenharmony_ci -p PATH, --path PATH The full path to the tc executable to use 12862306a36Sopenharmony_ci -v, --verbose Show the commands that are being run 12962306a36Sopenharmony_ci -N, --notap Suppress tap results for command under test 13062306a36Sopenharmony_ci -d DEVICE, --device DEVICE 13162306a36Sopenharmony_ci Execute test cases that use a physical device, where 13262306a36Sopenharmony_ci DEVICE is its name. (If not defined, tests that require 13362306a36Sopenharmony_ci a physical device will be skipped) 13462306a36Sopenharmony_ci -P, --pause Pause execution just before post-suite stage 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ciselection: 13762306a36Sopenharmony_ci select which test cases: files plus directories; filtered by categories 13862306a36Sopenharmony_ci plus testids 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci -D DIR [DIR ...], --directory DIR [DIR ...] 14162306a36Sopenharmony_ci Collect tests from the specified directory(ies) 14262306a36Sopenharmony_ci (default [tc-tests]) 14362306a36Sopenharmony_ci -f FILE [FILE ...], --file FILE [FILE ...] 14462306a36Sopenharmony_ci Run tests from the specified file(s) 14562306a36Sopenharmony_ci -c [CATG [CATG ...]], --category [CATG [CATG ...]] 14662306a36Sopenharmony_ci Run tests only from the specified category/ies, or if 14762306a36Sopenharmony_ci no category/ies is/are specified, list known 14862306a36Sopenharmony_ci categories. 14962306a36Sopenharmony_ci -e ID [ID ...], --execute ID [ID ...] 15062306a36Sopenharmony_ci Execute the specified test cases with specified IDs 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ciaction: 15362306a36Sopenharmony_ci select action to perform on selected test cases 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci -l, --list List all test cases, or those only within the 15662306a36Sopenharmony_ci specified category 15762306a36Sopenharmony_ci -s, --show Display the selected test cases 15862306a36Sopenharmony_ci -i, --id Generate ID numbers for new test cases 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cinetns: 16162306a36Sopenharmony_ci options for nsPlugin (run commands in net namespace) 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci -N, --no-namespace 16462306a36Sopenharmony_ci Do not run commands in a network namespace. 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_civalgrind: 16762306a36Sopenharmony_ci options for valgrindPlugin (run command under test under Valgrind) 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci -V, --valgrind Run commands under valgrind 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ciPLUGIN ARCHITECTURE 17362306a36Sopenharmony_ci------------------- 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ciThere is now a plugin architecture, and some of the functionality that 17662306a36Sopenharmony_ciwas in the tdc.py script has been moved into the plugins. 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ciThe plugins are in the directory plugin-lib. The are executed from 17962306a36Sopenharmony_cidirectory plugins. Put symbolic links from plugins to plugin-lib, 18062306a36Sopenharmony_ciand name them according to the order you want them to run. This is not 18162306a36Sopenharmony_cinecessary if a test case being run requires a specific plugin to work. 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ciExample: 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cibjb@bee:~/work/tc-testing$ ls -l plugins 18662306a36Sopenharmony_citotal 4 18762306a36Sopenharmony_cilrwxrwxrwx 1 bjb bjb 27 Oct 4 16:12 10-rootPlugin.py -> ../plugin-lib/rootPlugin.py 18862306a36Sopenharmony_cilrwxrwxrwx 1 bjb bjb 25 Oct 12 17:55 20-nsPlugin.py -> ../plugin-lib/nsPlugin.py 18962306a36Sopenharmony_ci-rwxr-xr-x 1 bjb bjb 0 Sep 29 15:56 __init__.py 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ciThe plugins are a subclass of TdcPlugin, defined in TdcPlugin.py and 19262306a36Sopenharmony_cimust be called "SubPlugin" so tdc can find them. They are 19362306a36Sopenharmony_cidistinguished from each other in the python program by their module 19462306a36Sopenharmony_ciname. 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ciThis base class supplies "hooks" to run extra functions. These hooks are as follows: 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cipre- and post-suite 19962306a36Sopenharmony_cipre- and post-case 20062306a36Sopenharmony_cipre- and post-execute stage 20162306a36Sopenharmony_ciadjust-command (runs in all stages and receives the stage name) 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ciThe pre-suite hook receives the number of tests and an array of test ids. 20462306a36Sopenharmony_ciThis allows you to dump out the list of skipped tests in the event of a 20562306a36Sopenharmony_cifailure during setup or teardown stage. 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ciThe pre-case hook receives the ordinal number and test id of the current test. 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ciThe adjust-command hook receives the stage id (see list below) and the 21062306a36Sopenharmony_cifull command to be executed. This allows for last-minute adjustment 21162306a36Sopenharmony_ciof the command. 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ciThe stages are identified by the following strings: 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci - pre (pre-suite) 21662306a36Sopenharmony_ci - setup 21762306a36Sopenharmony_ci - command 21862306a36Sopenharmony_ci - verify 21962306a36Sopenharmony_ci - teardown 22062306a36Sopenharmony_ci - post (post-suite) 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ciTo write a plugin, you need to inherit from TdcPlugin in 22462306a36Sopenharmony_ciTdcPlugin.py. To use the plugin, you have to put the 22562306a36Sopenharmony_ciimplementation file in plugin-lib, and add a symbolic link to it from 22662306a36Sopenharmony_ciplugins. It will be detected at run time and invoked at the 22762306a36Sopenharmony_ciappropriate times. There are a few examples in the plugin-lib 22862306a36Sopenharmony_cidirectory: 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci - rootPlugin.py: 23162306a36Sopenharmony_ci implements the enforcement of running as root 23262306a36Sopenharmony_ci - nsPlugin.py: 23362306a36Sopenharmony_ci sets up a network namespace and runs all commands in that namespace, 23462306a36Sopenharmony_ci while also setting up dummy devices to be used in testing. 23562306a36Sopenharmony_ci - valgrindPlugin.py 23662306a36Sopenharmony_ci runs each command in the execute stage under valgrind, 23762306a36Sopenharmony_ci and checks for leaks. 23862306a36Sopenharmony_ci This plugin will output an extra test for each test in the test file, 23962306a36Sopenharmony_ci one is the existing output as to whether the test passed or failed, 24062306a36Sopenharmony_ci and the other is a test whether the command leaked memory or not. 24162306a36Sopenharmony_ci (This one is a preliminary version, it may not work quite right yet, 24262306a36Sopenharmony_ci but the overall template is there and it should only need tweaks.) 24362306a36Sopenharmony_ci - buildebpfPlugin.py: 24462306a36Sopenharmony_ci builds all programs in $EBPFDIR. 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ciACKNOWLEDGEMENTS 24862306a36Sopenharmony_ci---------------- 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ciThanks to: 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ciJamal Hadi Salim, for providing valuable test cases 25362306a36Sopenharmony_ciKeara Leibovitz, who wrote the CLI test driver that I used as a base for the 25462306a36Sopenharmony_ci first version of the tc testing suite. This work was presented at 25562306a36Sopenharmony_ci Netdev 1.2 Tokyo in October 2016. 25662306a36Sopenharmony_ciSamir Hussain, for providing help while I dove into Python for the first time 25762306a36Sopenharmony_ci and being a second eye for this code. 258