Our simulated environment was really only meant to test air-to-air
communication by using mac80211_hwsim. Protocols like DHCP use IP
communication which starts to fall apart when using hwsim radios.
Mainly unicast sockets do not work since there is no underlying
network infrastructure.
In order to simulate a more realistic environment network namespaces
are introduced in this patch. This allows wireless phy's to be added
to a network namespace and unique IWD instances manage those phys.
This is done automatically when 'NameSpaces' entries are configured
in hw.conf:
[SETUP]
num_radios=2
[NameSpaces]
ns0=rad1,...
This will create a namespace named ns0, and add rad1 to that
namespace. rad1 will not appear as a phy in what's being called the
'root' namespace (the default namespace).
As far as a test is concerned you can create a new IWD() class and
pass the namespace in. This will start a new IWD instance in that
namespace:
ns0 = ctx.get_namespace('ns0')
wd_ns0 = IWD(start_iwd=True, namespace=ns0)
'wd_ns0' can now be used to interact with IWD in that namespace, just
like any other IWD class object.
This also changes the resolve API a little bit to act as a 'set' API
instead of an incremental 'add' API. This is actually easier to manage
in the resolve module since both systemd and resolvconf want changes
wholesale and not incrementally.
Both these tests create many radios which sometimes causes timing
problems when hwsim is running. Since hwsim is not required for
these tests we can disable it and increase test reliability.
Waiting to request neighbor reports until we are in need of a roam
delays the roam time, and probably isn't as reliable since we are
most likely in a low RSSI state. Instead the neighbor report can
be requested immediately after connecting, saved, and used if/when
a roam is needed. The existing behavior is maintained if the early
neighbor report fails where a neighbor report is requested at the
time of the roam.
The code which parses the reports was factored out and shared
between the existing (late) neighbor report callback and the early
neighbor report callback.
Sometimes improperly written tests can end up causing future tests
to fail. For faster debugging you can now add a '+' after a given
autotest which will start that test and run all tests which come
alphabetically after it (as if you are running a full autotest suite).
Example:
./test-runner -A testWPA+
This will run testWPA, testWPA2, testWPA2-no-CCMP, testWPA2-SHA256,
and testWPA2withMFP.
This can result in strange test results since there was no less
than zero checks before subtracting the total tests from failed
tests. In case of an internal exception we can just set all values
to zero. This will be handled specially as we do for timeout
errors.
When network namespaces are introduced there may be multiple
IWD class instances. This makes IWD.get_instance ambiguous
when namespaces are involved. iwd.py has been refactored to
not use IWD.get_instance, but testutil still needs it since
its purely based off interface names. Rather than remove it
and modify every test to pass the IWD object we can just
maintain the existing behavior for only the root namespace.
You can now specify a limited list of subtests to run out of a
full auto-test using --sub-tests,-S. This option is limited in
that it is only meant to be used with a single autotest (since
it doesn't make much sense otherwise).
The subtest can be specified both with or without the file
extension.
Example usage:
./test-runner -A testAP -S failure_test,dhcp_test.py
This will only run the two subtests and exclude any other *.py
tests present in the test directory.
handshake_state_set_authenticator_ie must be called to set group_cipher
in struct handshake_shake before handshake_set_gtk_state, otherwise
handshake_set_gtk_state is unable to determine the key length to set
handshake state gtk.
Fixes: 4bc20a0979 ("ap: Start EAP-WSC authentication with WSC enrollees")
For now the RA client is ran automatically when DHCPv6 client starts.
RA takes care of installing / deleting prefix routes and installing the
default gateway. If Router Advertisements indicate support DHCPv6, then
DHCPv6 transactions are kicked off and the address is set / removed
automatically.
Stateless configuration is not yet supported.
Modern kernels ~5.4+ have changed the way lost beacons are
reported and effectively make the lost beacon event useless
because it is immediately followed by a disconnect event. This
does not allow IWD enough time to do much of anything before
the disconnect comes in and we are forced to fully re-connect
to a different AP.
The agent path was generated based on the current time which
sometimes yielded duplicate paths if agents were created quickly
after one another. Instead a simple iterator removes any chance
of a duplicate path.
If running multiple tests testNetconfig would fail due to the
hardcoded wln0 in the dhcpd.conf file. dhcpd can actually start
by passing in the interface to the run command rather than
inside the config file.
If EnableNetworkConfiguration was enabled ap.c required that
APRanges also be set. This prevents IWD from starting which
effects a perfectly valid station configuration. Instead if
APRanges is not provided IWD still allows ap_init to pass but
DHCP just will not be enabled.
Code was added with commit 04487f575b which passes a radio object
to the Interface class constructor and stores it in the Interface
object. The radio class also stores each Interface object which
creates a circular reference and causes the Radio to stick around
long after the tests finishes.
I cannot see why the Interface needs to keep track of the Radio
object. None of the wpa_supplicant utilities use this so it has
been removed.
Users can now supply an AP provisioning file containing an [IPv4]
section and define various DHCP settings:
[IPv4]
Address=<address>
Netmask=<netmask>
Gateway=<gateway>
IPRange=<start_address>,<end_address>
DNSList=<dns1>,<dns2>,...<dnsN>
LeaseTime=<lease_time>
There are a few notes/requirements to keep in mind when using a
provisioning file:
- All settings are optional but [IPv4].Address is required if the
interface does not already have an address set.
- If no [IPv4].Address is defined in the provisioning file and the AP
interface does not already have an address set, StartWithConfig()
will fail with -EINVAL.
- If a provisioning file is provided it will take precedence, and the
AP will not pull from the IP pool.
- A provisioning file containing an IPv4 section assumes DHCP is being
enabled and will override [General].EnableNetworkConfiguration.
- Any address that AP sets on the interface will be deleted when the AP
is stopped.
Users can now start an AP from settings based on a profile
on disk. The only argument is the SSID which will be used to
lookup the profile. If no profile is found a NotFound error
will be returned. Any invalid profiles will result in an
Invalid return.
This seems to happen occationally with testAP (potentially others).
The invalid read appears to happen when the frame_xchg_tx_cb detects
an early status and no ACK. In this particular case there is no
retry interval so we reach the retry limit and 'done' the frame.
This frees the 'fx' data all before the destroy callback can get
called. Once we finally return and the destroy callback is called
'fx' is freed and we see the invalid write.
==206== Memcheck, a memory error detector
==206== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==206== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==206== Command: iwd -p rad1,rad2,rad3,rad4 -d
==206== Parent PID: 140
==206==
==206== Invalid write of size 4
==206== at 0x4493A0: frame_xchg_tx_destroy (frame-xchg.c:941)
==206== by 0x46DAF6: destroy_request (genl.c:673)
==206== by 0x46DAF6: process_unicast (genl.c:1002)
==206== by 0x46DAF6: received_data (genl.c:1101)
==206== by 0x46AA4B: io_callback (io.c:118)
==206== by 0x469D6C: l_main_iterate (main.c:477)
==206== by 0x469E1B: l_main_run (main.c:524)
==206== by 0x469E1B: l_main_run (main.c:506)
==206== by 0x46A02B: l_main_run_with_signal (main.c:646)
==206== by 0x403E78: main (main.c:490)
==206== Address 0x4c59c6c is 172 bytes inside a block of size 176 free'd
==206== at 0x483B9F5: free (vg_replace_malloc.c:538)
==206== by 0x40F14C: destroy_work (wiphy.c:248)
==206== by 0x40F14C: wiphy_radio_work_done (wiphy.c:1578)
==206== by 0x44A916: frame_xchg_tx_cb (frame-xchg.c:930)
==206== by 0x46DAD9: process_unicast (genl.c:993)
==206== by 0x46DAD9: received_data (genl.c:1101)
==206== by 0x46AA4B: io_callback (io.c:118)
==206== by 0x469D6C: l_main_iterate (main.c:477)
==206== by 0x469E1B: l_main_run (main.c:524)
==206== by 0x469E1B: l_main_run (main.c:506)
==206== by 0x46A02B: l_main_run_with_signal (main.c:646)
==206== by 0x403E78: main (main.c:490)
==206== Block was alloc'd at
==206== at 0x483A809: malloc (vg_replace_malloc.c:307)
==206== by 0x4643CD: l_malloc (util.c:61)
==206== by 0x44AF8C: frame_xchg_startv (frame-xchg.c:1155)
==206== by 0x44B2A4: frame_xchg_start (frame-xchg.c:1108)
==206== by 0x42BC55: ap_send_mgmt_frame (ap.c:709)
==206== by 0x42F513: ap_probe_req_cb (ap.c:1869)
==206== by 0x449752: frame_watch_unicast_notify (frame-xchg.c:233)
==206== by 0x46DA2F: dispatch_unicast_watches (genl.c:961)
==206== by 0x46DA2F: process_unicast (genl.c:980)
==206== by 0x46DA2F: received_data (genl.c:1101)
==206== by 0x46AA4B: io_callback (io.c:118)
==206== by 0x469D6C: l_main_iterate (main.c:477)
==206== by 0x469E1B: l_main_run (main.c:524)
==206== by 0x469E1B: l_main_run (main.c:506)
==206== by 0x46A02B: l_main_run_with_signal (main.c:646)
==206==