| Automated hostapd/wpa_supplicant testing with mac80211_hwsim | 
 | ------------------------------------------------------------ | 
 |  | 
 | This directory contains testing infrastructure and test cases to run | 
 | automated tests of full hostapd and wpa_supplicant functionality. This | 
 | testing is done with the help of mac80211_hwsim which is Linux kernel | 
 | driver that simulates IEEE 802.11 radios without requiring any | 
 | additional hardware. This setup most of the hostapd and wpa_supplicant | 
 | functionality (and large parts of the Linux cfg80211 and mac80211 | 
 | functionality for that matter) to be tested. | 
 |  | 
 | mac80211_hwsim is loaded with five simulated radios to allow different | 
 | device combinations to be tested. wlantest is used analyze raw packets | 
 | captured through the hwsim0 monitor interface that capture all frames | 
 | sent on all channels. wlantest is used to store the frames for | 
 | analysis. Three wpa_supplicant processes are used to control three | 
 | virtual radios and one hostapd process is used to dynamically control | 
 | the other two virtual radios. wpa_supplicant/hostapd test functionality | 
 | is used to verify that data connection (both unicast and broadcast) | 
 | works between two netdevs. | 
 |  | 
 | The python scripts and tools in this directory control test case | 
 | execution. They interact wpa_supplicant and hostapd through control | 
 | interfaces to perform the operations. In addition, wlantest_cli is used | 
 | to verify that operations have been performed correctly and that the | 
 | network connection works in the expected way. | 
 |  | 
 | These test cases are run automatically against the hostap.git commits | 
 | for regression testing and to help in keeping the hostap.git master | 
 | branch in stable state. Results from these tests are available here: | 
 | http://buildbot.w1.fi/hwsim/ | 
 |  | 
 |  | 
 | Building binaries for testing | 
 | ----------------------------- | 
 |  | 
 | You will need to build (or use already built) components to be | 
 | tested. These are available in the hostap.git repository and can be | 
 | built for example as follows: | 
 |  | 
 | cd ../../wpa_supplicant | 
 | cp ../tests/hwsim/example-wpa_supplicant.config .config | 
 | make clean | 
 | make | 
 | cd ../hostapd | 
 | cp ../tests/hwsim/example-hostapd.config .config | 
 | make clean | 
 | make hostapd hlr_auc_gw | 
 | cd ../wlantest | 
 | make clean | 
 | make | 
 |  | 
 | Alternatively, the build.sh script here can be used to run these steps | 
 | with conditional creation of .config files only if they do not exist. | 
 |  | 
 | The test scripts can find the binaries in the locations where they were | 
 | built. It is also possible to install wlantest_cli somewhere on the path | 
 | to use pre-built tools. | 
 |  | 
 | Please note that some of the configuration parameters used to enable | 
 | more testing coverage may require development packages that may not be | 
 | installed by default in many distributions. For example, following | 
 | Debian/Ubuntu packages are likely to be needed: | 
 | - binutils-dev | 
 | - libsqlite3-dev | 
 | - libpcap-dev | 
 |  | 
 | example-setup.txt provides more complete step-by-step example on how a | 
 | test setup can be built. | 
 |  | 
 |  | 
 | wpaspy | 
 | ------ | 
 |  | 
 | The python scripts use wpaspy.py to interact with the wpa_supplicant | 
 | control interface, but the run-tests.py script adds the (relative) | 
 | path into the environment so it doesn't need to be installed. | 
 |  | 
 |  | 
 | mac80211_hwsim | 
 | -------------- | 
 |  | 
 | mac80211_hwsim kernel module is available from the upstream Linux | 
 | kernel. Some Linux distributions enable it by default. If that's not the | 
 | case, you can either enable it in the kernel configuration | 
 | (CONFIG_MAC80211_HWSIM=m) and rebuild your kernel or use Backports with | 
 | CPTCFG_MAC80211_HWSIM=m to replace the wireless LAN components in the | 
 | base kernel. | 
 |  | 
 |  | 
 | sudo | 
 | ---- | 
 |  | 
 | Some parts of the testing process requires root privileges. The test | 
 | scripts are currently using sudo to achieve this. To be able to run the | 
 | tests, you'll probably want to enable sudo with a timeout to not expire | 
 | password entry very quickly. For example, use this in the sudoers file: | 
 |  | 
 | Defaults        env_reset,timestamp_timeout=180 | 
 |  | 
 | Or on a dedicated test system, you could even disable password prompting | 
 | with this in sudoers: | 
 |  | 
 | %sudo   ALL=NOPASSWD: ALL | 
 |  | 
 |  | 
 | Other network interfaces | 
 | ------------------------ | 
 |  | 
 | Some of the test scripts are still using hardcoded interface names, so | 
 | the easiest way of making things work is to avoid using other network | 
 | devices that may use conflicting interface names. For example, unload | 
 | any wireless LAN driver before running the tests and make sure that | 
 | wlan0..4 gets assigned as the interface names for the mac80211_hwsim | 
 | radios. It may also be possible to rename the interface expectations in | 
 | run-tests.py to allow other names to be used. | 
 |  | 
 | Please also note that some commonly enabled tools, like NetworkManager, | 
 | may end up trying to control new network interfaces automatically. This | 
 | can result in conflicts with the test scripts and you may need to | 
 | disable such network services or at least mark the mac80211_hwsim wlan# | 
 | interfaces as umanaged. As an example, this can be done in | 
 | /etc/NetworkManager/NetworkManager.conf with following addition: | 
 |  | 
 | [keyfile] | 
 | unmanaged-devices=mac:02:00:00:00:00:00;mac:02:00:00:00:01:00;mac:02:00:00:00:02:00;mac:02:00:00:00:03:00;mac:02:00:00:00:04:00 | 
 |  | 
 |  | 
 | Running tests | 
 | ------------- | 
 |  | 
 | Simplest way to run a full set of the test cases is by running | 
 | run-all.sh in tests/hwsim directory. This will use start.sh to load the | 
 | mac80211_hwsim module and start wpa_supplicant, hostapd, and various | 
 | test tools. run-tests.sh is then used to run through all the defined | 
 | test cases and stop.sh to stop the programs and unload the kernel | 
 | module. | 
 |  | 
 | run-all.sh can be used to run the same test cases under different | 
 | conditions: | 
 |  | 
 | # run normal test cases | 
 | ./run-all.sh | 
 |  | 
 | # run normal test cases under valgrind | 
 | ./run-all.sh valgrind | 
 |  | 
 | # run normal test cases with Linux tracing | 
 | ./run-all.sh trace | 
 |  | 
 | # run normal test cases with multi channel support (see details below) | 
 | ./run-all.sh channels=<num of channels> | 
 |  | 
 | run-all.sh directs debug logs into the logs subdirectory (or $LOGDIR if | 
 | present in the environment). Log file names include the current UNIX | 
 | timestamp and a postfix to identify the specific log: | 
 | - *.log0 = wpa_supplicant debug log for the first radio | 
 | - *.log1 = wpa_supplicant debug log for the second radio | 
 | - *.log2 = wpa_supplicant debug log for the third radio | 
 | - *.hostapd = hostapd debug log | 
 | - hwsim0 = wlantest debug log | 
 | - hwsim0.pcapng = capture with all frames exchanged during the tests | 
 | - *.log = debug prints from the test scripts | 
 | - trace.dat = Linux tracing record (if enabled) | 
 | - hlr_auc_gw - hlr_auc_gw (EAP-SIM/AKA/AKA' authentication) log | 
 | - auth_serv - hostapd as RADIUS authentication server log | 
 |  | 
 |  | 
 | For manual testing, ./start.sh can be used to initialize interfaces and | 
 | programs and run-tests.py to execute one or more test | 
 | cases. run-tests.py output verbosity can be controlled with -d (more | 
 | verbose debug output) and -q (less verbose output) on the command | 
 | line. "-f <module name>" (pointing to file test_<module name>.py) can be | 
 | used to specify that all test cases from a single file are to be | 
 | run. Test name as the last command line argument can be specified that a | 
 | single test case is to be run (e.g., "./run-tests.py ap_pmf_required"). | 
 |  | 
 | Notice that some tests require the driver to support concurrent | 
 | operation on multi channels in order to run. These tests will be skipped | 
 | in case the driver does not support multi channels. To enable support | 
 | for multi channel, the number of supported channel is passed as an | 
 | argument to run-all.sh or start.sh | 
 |  | 
 |  | 
 | Adding/modifying test cases | 
 | --------------------------- | 
 |  | 
 | All the test cases are defined in the test_*.py files. These are python | 
 | scripts that can use the local helper classes to interact with the test | 
 | components. While various python constructs can be used in the scripts, | 
 | only a minimal level of python knowledge should really be needed to | 
 | modify and add new test cases. The easiest starting point for this is | 
 | likely to take a look at some of the example scripts. When working on a | 
 | new test, run-tests.py with -d and the test case name on the command | 
 | line is a convenient way of verifying functionality. | 
 |  | 
 | run-tests.py will automatically import all test cases from the test_*.py | 
 | files in this directory. All functions starting with the "test_" prefix | 
 | in these files are assumed to be test cases. Each test case is named by | 
 | the function name following the "test_" prefix. | 
 |  | 
 |  | 
 | Results database | 
 | ---------------- | 
 |  | 
 | run-tests.py can be requested to write results from the execution of | 
 | each test case into an sqlite database. The "-S <path to database>" and | 
 | "-b <build id>" command line arguments can be used to do that. The | 
 | database must have been prepared before this, e.g., with following: | 
 |  | 
 | cat | sqlite3 /tmp/example.db <<EOF | 
 | CREATE TABLE results (test,result,run,time,duration,build,commitid); | 
 | CREATE INDEX results_idx ON results (test); | 
 | CREATE INDEX results_idx2 ON results (run); | 
 | CREATE TABLE tests (test,description); | 
 | CREATE UNIQUE INDEX tests_idx ON tests (test); | 
 | CREATE TABLE logs (test,run,type,contents); | 
 | CREATE INDEX logs_idx ON logs (test); | 
 | CREATE INDEX logs_idx2 ON logs (run); | 
 | EOF |