[PATCH v4 1/2] auto-t: add optional scan argument to get_ordered_network(s)
by James Prestwood
There is a very common block of code inside many autotests
which goes something like:
device.scan()
condition = 'obj.scanning'
wd.wait_for_object_condition(device, condition)
condition = 'not obj.scanning'
wd.wait_for_object_condition(device, condition)
network = device.get_ordered_network('an-ssid')
When you see the same pattern in nearly all the tests this shows
we need a helper. Basic autotests which merely check that a
connection succeeded should not need to write the same code again
and again. This code ends up being copy-pasted which can lead to
bugs.
There is also a code pattern which attempts to get ordered
networks, and if this fails it scans and tries again. This, while
not optimal, does prevent unneeded scanning by first checking if
any networks already exist.
This patch solves both the code reuse issue as well as the recovery
if get_ordered_network(s) fails. A new optional parameter was
added to get_ordered_network(s) which is False by default. If True
get_ordered_network(s) will perform a scan if the initial call
yields no networks. Tests will now be able to simply call
get_ordered_network(s) without performing a scan before hand.
---
autotests/util/iwd.py | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/autotests/util/iwd.py b/autotests/util/iwd.py
index 9bbb7278..c8d11f91 100755
--- a/autotests/util/iwd.py
+++ b/autotests/util/iwd.py
@@ -360,7 +360,7 @@ class Device(IWDDBusAbstract):
self._wait_for_async_op()
- def get_ordered_networks(self):
+ def get_ordered_networks(self, scan_if_needed = False):
'''Return the list of networks found in the most recent
scan, sorted by their user interface importance
score as calculated by iwd. If the device is
@@ -377,17 +377,32 @@ class Device(IWDDBusAbstract):
ordered_network = OrderedNetwork(bus_obj)
ordered_networks.append(ordered_network)
- if len(ordered_networks) == 0:
+ if len(ordered_networks) > 0:
+ return ordered_networks
+ elif not scan_if_needed:
return None
+ iwd = IWD.get_instance()
+
+ self.scan()
+
+ condition = 'obj.scanning'
+ iwd.wait_for_object_condition(self, condition)
+ condition = 'not obj.scanning'
+ iwd.wait_for_object_condition(self, condition)
+
+ for bus_obj in self._station.GetOrderedNetworks():
+ ordered_network = OrderedNetwork(bus_obj)
+ ordered_networks.append(ordered_network)
+
return ordered_networks
- def get_ordered_network(self, network):
+ def get_ordered_network(self, network, scan_if_needed = False):
'''Returns a single network from ordered network call, or None if the
network wasn't found. If the network is not found an exception is
raised, this removes the need to extra asserts in autotests.
'''
- ordered_networks = self.get_ordered_networks()
+ ordered_networks = self.get_ordered_networks(scan_if_needed)
if not ordered_networks:
raise Exception('Network %s not found' % network)
--
2.21.1
9 months, 4 weeks
[PATCH v3 1/2] auto-t: add optional scan argument to get_ordered_network(s)
by James Prestwood
There is a very common block of code inside many autotests
which goes something like:
device.scan()
condition = 'obj.scanning'
wd.wait_for_object_condition(device, condition)
condition = 'not obj.scanning'
wd.wait_for_object_condition(device, condition)
network = device.get_ordered_network('an-ssid')
When you see the same pattern in nearly all the tests this shows
we need a helper. Basic autotests which merely check that a
connection succeeded should not need to write the same code again
and again. This code ends up being copy-pasted which can lead to
bugs.
There is also a code pattern which attempts to get ordered
networks, and if this fails it scans and tries again. This, while
not optimal, does prevent unneeded scanning by first checking if
any networks already exist.
This patch solves both the code reuse issue as well as the recovery
if get_ordered_network(s) fails. A new optional parameter was
added to get_ordered_network(s) which is False by default. If True
get_ordered_network(s) will perform a scan if the initial call
yields no networks. Tests will now be able to simply call
get_ordered_network(s) without performing a scan before hand.
---
autotests/util/iwd.py | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/autotests/util/iwd.py b/autotests/util/iwd.py
index 9bbb7278..7716b766 100755
--- a/autotests/util/iwd.py
+++ b/autotests/util/iwd.py
@@ -360,7 +360,7 @@ class Device(IWDDBusAbstract):
self._wait_for_async_op()
- def get_ordered_networks(self):
+ def get_ordered_networks(self, scan_if_needed = False):
'''Return the list of networks found in the most recent
scan, sorted by their user interface importance
score as calculated by iwd. If the device is
@@ -377,17 +377,30 @@ class Device(IWDDBusAbstract):
ordered_network = OrderedNetwork(bus_obj)
ordered_networks.append(ordered_network)
- if len(ordered_networks) == 0:
+ if len(ordered_networks) == 0 and not scan_if_needed:
return None
+ iwd = IWD.get_instance()
+
+ self.scan()
+
+ condition = 'obj.scanning'
+ iwd.wait_for_object_condition(self, condition)
+ condition = 'not obj.scanning'
+ iwd.wait_for_object_condition(self, condition)
+
+ for bus_obj in self._station.GetOrderedNetworks():
+ ordered_network = OrderedNetwork(bus_obj)
+ ordered_networks.append(ordered_network)
+
return ordered_networks
- def get_ordered_network(self, network):
+ def get_ordered_network(self, network, scan_if_needed = False):
'''Returns a single network from ordered network call, or None if the
network wasn't found. If the network is not found an exception is
raised, this removes the need to extra asserts in autotests.
'''
- ordered_networks = self.get_ordered_networks()
+ ordered_networks = self.get_ordered_networks(scan_if_needed)
if not ordered_networks:
raise Exception('Network %s not found' % network)
--
2.21.1
9 months, 4 weeks
[PATCH v2] auto-t: explicitly scan in testConnectAutoconnect
by James Prestwood
In certain cases the autoconnect portion of each subtest was connecting
to the network so fast that the check for obj.scanning was never successful
since IWD was already connected (and in turn not scanning). Since the
autoconnect path will wait for the device to be connected there really isn't
a reason to wait for any scanning conditions. The normal connect path does
need to wait for scanning though, and for this an explicit call to scan was
added to ensure the network list gets populated.
---
autotests/testConnectAutoconnect/validation.py | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/autotests/testConnectAutoconnect/validation.py b/autotests/testConnectAutoconnect/validation.py
index 43cbaf02..757a88ab 100644
--- a/autotests/testConnectAutoconnect/validation.py
+++ b/autotests/testConnectAutoconnect/validation.py
@@ -12,6 +12,14 @@ from iwd import NetworkType
class TestConnectAutoConnect(unittest.TestCase):
def check_connect(self, wd, device, ssid, throws):
+ device.scan()
+
+ condition = 'obj.scanning'
+ wd.wait_for_object_condition(device, condition)
+
+ condition = 'not obj.scanning'
+ wd.wait_for_object_condition(device, condition)
+
ordered_network = device.get_ordered_network(ssid)
condition = 'not obj.connected'
@@ -54,12 +62,6 @@ class TestConnectAutoConnect(unittest.TestCase):
self.assertIsNotNone(devices)
device = devices[0]
- condition = 'obj.scanning'
- wd.wait_for_object_condition(device, condition)
-
- condition = 'not obj.scanning'
- wd.wait_for_object_condition(device, condition)
-
if autoconnect:
self.check_autoconnect(wd, device, ssid, throws)
else:
--
2.21.1
9 months, 4 weeks
[PATCH 1/2] auto-t: remove scanning wait from testConnectAutoconnect
by James Prestwood
In certain cases the test was reaching this point once already finished
with a scan. This caused the wait for 'scanning' to time out. At this point
in the test we don't need to wait for scanning and only need to wait for
scanning to finish. If scanning is already finished before validation we
can simply validate at that time.
---
autotests/testConnectAutoconnect/validation.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/autotests/testConnectAutoconnect/validation.py b/autotests/testConnectAutoconnect/validation.py
index 43cbaf02..b1e3accc 100644
--- a/autotests/testConnectAutoconnect/validation.py
+++ b/autotests/testConnectAutoconnect/validation.py
@@ -54,9 +54,6 @@ class TestConnectAutoConnect(unittest.TestCase):
self.assertIsNotNone(devices)
device = devices[0]
- condition = 'obj.scanning'
- wd.wait_for_object_condition(device, condition)
-
condition = 'not obj.scanning'
wd.wait_for_object_condition(device, condition)
--
2.21.1
9 months, 4 weeks
[PATCH] auto-t: fix failing adhoc test
by James Prestwood
There appears to be a race condition in the kernel where if two stations
(using the same kernel) do a join IBSS at the same time the New Station
event never comes in (as if no other station has joined the IBSS).
Until this is sorted out, a sleep between starting the IBSS fixes the
issue for the test.
---
autotests/testAdHoc/adhoc_test.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/autotests/testAdHoc/adhoc_test.py b/autotests/testAdHoc/adhoc_test.py
index 119c6c7e..27c87a82 100644
--- a/autotests/testAdHoc/adhoc_test.py
+++ b/autotests/testAdHoc/adhoc_test.py
@@ -8,6 +8,7 @@ sys.path.append('../util')
import iwd
from iwd import IWD
import testutil
+from time import sleep
class Test(unittest.TestCase):
@@ -18,6 +19,7 @@ class Test(unittest.TestCase):
self.assertIsNotNone(dev2)
dev1.start_adhoc("AdHocNetwork", "secret123")
+ sleep(1)
dev2.start_adhoc("AdHocNetwork", "secret123")
dev1.adhoc_wait_for_connected(dev2.address)
--
2.21.1
10 months
[PATCH 1/2] test-runner: run iwmon per-subtest
by James Prestwood
Previously iwmon was running per-test, which would jumble any subtests
together into the same log file making it hard to parse. Now create
a separate directory for each subtest and put the monitor log and
pcap there.
---
tools/test-runner.c | 35 ++++++++++++++++++++++++++++-------
1 file changed, 28 insertions(+), 7 deletions(-)
diff --git a/tools/test-runner.c b/tools/test-runner.c
index 88bb50e1..5874421c 100644
--- a/tools/test-runner.c
+++ b/tools/test-runner.c
@@ -1847,6 +1847,7 @@ static void run_py_tests(struct l_settings *hw_settings,
unsigned int max_exec_interval;
char *py_test = NULL;
struct test_stats *test_stats;
+ pid_t monitor_pid = -1;
if (!l_settings_get_uint(hw_settings, HW_CONFIG_GROUP_SETUP,
HW_CONFIG_SETUP_MAX_EXEC_SEC,
@@ -1865,6 +1866,28 @@ start_next_test:
if (!py_test)
return;
+ if (log) {
+ char *test_path;
+ char *ext;
+ char *full_path;
+
+ test_path = l_strdup_printf("%s/%s", test_name, py_test);
+ ext = strchr(test_path, '.');
+ ext[0] = '\0';
+
+ full_path = l_strdup_printf("%s/%s", log_dir, test_path);
+
+ mkdir(full_path, 0755);
+ if (chown(full_path, log_uid, log_gid) < 0)
+ l_error("chown failed %s", full_path);
+
+ l_free(full_path);
+
+ monitor_pid = start_monitor(test_path);
+
+ l_free(test_path);
+ }
+
argv[0] = "python3";
argv[1] = py_test;
argv[2] = NULL;
@@ -1928,6 +1951,11 @@ start_next_test:
l_free(py_test);
py_test = NULL;
+ if (monitor_pid != -1) {
+ kill_process(monitor_pid);
+ monitor_pid = -1;
+ }
+
goto start_next_test;
}
@@ -2040,7 +2068,6 @@ static void create_network_and_run_tests(void *data, void *user_data)
pid_t medium_pid = -1;
pid_t ofono_pid = -1;
pid_t phonesim_pid = -1;
- pid_t monitor_pid = -1;
char *config_dir_path;
char *iwd_config_dir;
char **tmpfs_extra_stuff = NULL;
@@ -2186,9 +2213,6 @@ static void create_network_and_run_tests(void *data, void *user_data)
l_queue_foreach(wiphy_list, wiphy_up, NULL);
}
- if (log)
- monitor_pid = start_monitor(test_name);
-
if (check_verbosity("tls"))
setenv("IWD_TLS_DEBUG", "on", true);
@@ -2277,9 +2301,6 @@ static void create_network_and_run_tests(void *data, void *user_data)
stop_phonesim(phonesim_pid);
}
- if (monitor_pid > 0)
- kill_process(monitor_pid);
-
exit_hostapd:
destroy_hostapd_instances(hostapd_pids);
--
2.21.1
10 months
[PATCH v2] netdev: fix segfault due to roaming before connected
by James Prestwood
In this situation the kernel is sending a low RSSI event which netdev
picks up, but since we set netdev->connected so early the event is
forwarded to station before IWD has fully connected. Station then
tries to get a neighbor report, which may fail and cause a known
frequency scan. If this is a new network the frequency scan tries to
get any known frequencies in network_info which will be unset and
cause a segfault.
This can be avoided by only sending RSSI events when netdev->operational
is set rather than netdev->connected.
---
src/netdev.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/netdev.c b/src/netdev.c
index 69f9ab85..b3c3bf73 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -678,7 +678,7 @@ static void netdev_cqm_event_rssi_threshold(struct netdev *netdev,
{
int event;
- if (!netdev->connected)
+ if (!netdev->operational)
return;
if (rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
--
2.21.1
10 months
[PATCH] tools: delay hwsim sending frame
by James Prestwood
Using mac80211_hwsim can sometimes result in out of order messages
coming from the kernel. Since mac80211_hwsim immediately sends out
frames and the kernel keeps command responses in a separate queue,
bad scheduling can result in these messages being out of order.
In some cases we receive Auth/Assoc frames before the response to
our original CMD_CONNECT. This causes autotests to fail randomly,
some more often than others.
To fix this we can introduce a small delay into hwsim. Just a 1ms
delay makes the random failures disappear in the tests. This delay
is also makes hwsim more realistic since actual hardware will always
introduce some kind of delay when sending or receiving frames.
---
tools/hwsim.c | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/tools/hwsim.c b/tools/hwsim.c
index 951ead36..d066f814 100644
--- a/tools/hwsim.c
+++ b/tools/hwsim.c
@@ -1350,6 +1350,19 @@ static bool interface_info_match_dst(const void *a, const void *b)
!memcmp(rec->addr, dst->addr, ETH_ALEN);
}
+static void frame_delay_callback(struct l_timeout *timeout, void *user_data)
+{
+ struct send_frame_info *send_info = user_data;
+
+ if (send_frame(send_info, send_frame_callback,
+ send_frame_destroy))
+ send_info->frame->pending_callback_count++;
+ else
+ send_frame_destroy(send_info);
+
+ l_timeout_remove(timeout);
+}
+
/*
* Process frames in a similar way to how the kernel built-in hwsim medium
* does this, with an additional optimization for unicast frames and
@@ -1409,11 +1422,11 @@ static void process_frame(struct hwsim_frame *frame)
send_info->radio = radio;
send_info->frame = hwsim_frame_ref(frame);
- if (send_frame(send_info, send_frame_callback,
- send_frame_destroy))
- frame->pending_callback_count++;
- else
+ if (!l_timeout_create_ms(1, frame_delay_callback,
+ send_info, NULL)) {
+ l_error("Error delaying frame, frame will be dropped");
send_frame_destroy(send_info);
+ }
}
hwsim_frame_unref(frame);
--
2.21.1
10 months
[PATCH] station: fix segfault due to roaming before connected
by James Prestwood
In this situation the kernel is sending a low RSSI event which netdev
picks up, but since we set netdev->connected so early the event is
forwarded to station before IWD has fully connected. Station then
tries to get a neighbor report, which may fail and cause a known
frequency scan. If this is a new network the frequency scan tries to
get any known frequencies in network_info which will be unset and
cause a segfault.
This can be avoided by ensuring that we are connected inside
station_cannot_roam() rather than checking that we aren't roaming.
This modification will ensure both connected and not roaming before
doing a roam.
---
src/station.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/station.c b/src/station.c
index c532319a..5b0e7fd4 100644
--- a/src/station.c
+++ b/src/station.c
@@ -2007,7 +2007,7 @@ static bool station_cannot_roam(struct station *station)
disabled = false;
return disabled || station->preparing_roam ||
- station->state == STATION_STATE_ROAMING;
+ station->state != STATION_STATE_CONNECTED;
}
static void station_lost_beacon(struct station *station)
--
2.21.1
10 months
[PATCH 1/4] manager: move debug print in dump callback
by James Prestwood
This callback gets called way to many times to have a debug print
in the location that it was. Instead only print if a NEW wiphy is
found, and also print the name/id.
---
src/manager.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/manager.c b/src/manager.c
index f351c780..5462418b 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -519,8 +519,6 @@ static void manager_wiphy_dump_callback(struct l_genl_msg *msg, void *user_data)
struct wiphy *wiphy;
struct wiphy_setup_state *state;
- l_debug("");
-
if (nl80211_parse_attrs(msg, NL80211_ATTR_WIPHY, &id,
NL80211_ATTR_WIPHY_NAME, &name,
NL80211_ATTR_UNSPEC) < 0)
@@ -543,6 +541,8 @@ static void manager_wiphy_dump_callback(struct l_genl_msg *msg, void *user_data)
state->id = id;
state->wiphy = wiphy;
+ l_debug("New wiphy %s added (%d)", name, id);
+
l_queue_push_tail(pending_wiphys, state);
done:
--
2.21.1
10 months