[PATCH v2] scan: Sort scan_requests by wiphy work item priority
by Denis Kenzior
Periodic scan requests are meant to be performed with a lower priority
than normal scan requests. They're thus given a different priority when
inserting them into the wiphy work queue. Unfortunately, the priority
is not taken into account when they are inserted into the
sr->requests queue. This can result in the scanning code being confused
since it assumes the top of the queue is always the next scheduled or
currently ongoing scan. As a result any further wiphy_work might never be
started properly.
Apr 27 16:34:40 iwd[5117]: ../iwd-1.26/src/wiphy.c:wiphy_radio_work_insert() Inserting work item 3
Apr 27 16:34:40 iwd[5117]: ../iwd-1.26/src/wiphy.c:wiphy_radio_work_next() Starting work item 3
Apr 27 16:34:40 iwd[5117]: ../iwd-1.26/src/scan.c:scan_periodic_timeout() 1
Apr 27 16:34:40 iwd[5117]: ../iwd-1.26/src/wiphy.c:wiphy_radio_work_insert() Inserting work item 4
Apr 27 16:34:43 iwd[5117]: ../iwd-1.26/src/wiphy.c:wiphy_radio_work_insert() Inserting work item 5
Apr 27 16:34:43 iwd[5117]: ../iwd-1.26/src/wiphy.c:wiphy_radio_work_done() Work item 3 done
Apr 27 16:34:43 iwd[5117]: ../iwd-1.26/src/wiphy.c:wiphy_radio_work_next() Starting work item 5
Apr 27 16:34:43 iwd[5117]: ../iwd-1.26/src/scan.c:scan_notify() Scan notification Trigger Scan(33)
Apr 27 16:34:43 iwd[5117]: ../iwd-1.26/src/scan.c:scan_request_triggered() Passive scan triggered for wdev 1
Apr 27 16:34:43 iwd[5117]: ../iwd-1.26/src/scan.c:scan_periodic_triggered() Periodic scan triggered for wdev 1
In the above log, scan request 5 (triggered by dbus) is started before
scan request 4 (periodic scan). Yet the scanning code thinks scan
request 4 was triggered.
Fix this by using the wiphy_work priority to sort the sr->requests queue
so that the scans are ordered in the same manner.
Reported-by: Alvin Šipraga <ALSI(a)bang-olufsen.dk>
---
v2 - Send priority as user_data since wiphy_radio_work_item part of the
request hasn't been initialized yet (not inserted onto the wiphy work
queue) and can't be compared.
src/scan.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/src/scan.c b/src/scan.c
index b0824e72ebaf..cc6e682c93ee 100644
--- a/src/scan.c
+++ b/src/scan.c
@@ -611,6 +611,17 @@ static struct scan_request *scan_request_new(struct scan_context *sc,
return sr;
}
+static int insert_by_priority(const void *a, const void *b, void *user_data)
+{
+ const struct scan_request *cur = b;
+ int priority = L_PTR_TO_INT(user_data);
+
+ if (cur->work.priority <= priority)
+ return 1;
+
+ return -1;
+}
+
static uint32_t scan_common(uint64_t wdev_id, bool passive,
const struct scan_parameters *params,
int priority,
@@ -630,7 +641,12 @@ static uint32_t scan_common(uint64_t wdev_id, bool passive,
scan_cmds_add(sr->cmds, sc, passive, params);
- l_queue_push_tail(sc->requests, sr);
+ /*
+ * sr->work isn't initialized yet, it will be done by
+ * wiphy_radio_work_insert(). Pass the priority as user_data instead
+ */
+ l_queue_insert(sc->requests, sr, insert_by_priority,
+ L_INT_TO_PTR(priority));
return wiphy_radio_work_insert(sc->wiphy, &sr->work,
priority, &work_ops);
@@ -801,7 +817,8 @@ uint32_t scan_owe_hidden(uint64_t wdev_id, struct l_queue *list,
}
done:
- l_queue_push_tail(sc->requests, sr);
+ l_queue_insert(sc->requests, sr, insert_by_priority,
+ L_INT_TO_PTR(WIPHY_WORK_PRIORITY_SCAN));
return wiphy_radio_work_insert(sc->wiphy, &sr->work,
WIPHY_WORK_PRIORITY_SCAN, &work_ops);
--
2.32.0
2 months
[PATCH] scan: Sort scan_requests by wiphy work item priority
by Denis Kenzior
Periodic scan requests are meant to be performed with a lower priority
than normal scan requests. They're thus given a different priority when
inserting them into the wiphy work queue. Unfortunately, the priority
is not taken into account when they are inserted into the
sr->requests queue. This can result in the scanning code being confused
since it assumes the top of the queue is always the next scheduled or
currently ongoing scan. As a result any further wiphy_work might never be
started properly.
Apr 27 16:34:40 iwd[5117]: ../iwd-1.26/src/wiphy.c:wiphy_radio_work_insert() Inserting work item 3
Apr 27 16:34:40 iwd[5117]: ../iwd-1.26/src/wiphy.c:wiphy_radio_work_next() Starting work item 3
Apr 27 16:34:40 iwd[5117]: ../iwd-1.26/src/scan.c:scan_periodic_timeout() 1
Apr 27 16:34:40 iwd[5117]: ../iwd-1.26/src/wiphy.c:wiphy_radio_work_insert() Inserting work item 4
Apr 27 16:34:43 iwd[5117]: ../iwd-1.26/src/wiphy.c:wiphy_radio_work_insert() Inserting work item 5
Apr 27 16:34:43 iwd[5117]: ../iwd-1.26/src/wiphy.c:wiphy_radio_work_done() Work item 3 done
Apr 27 16:34:43 iwd[5117]: ../iwd-1.26/src/wiphy.c:wiphy_radio_work_next() Starting work item 5
Apr 27 16:34:43 iwd[5117]: ../iwd-1.26/src/scan.c:scan_notify() Scan notification Trigger Scan(33)
Apr 27 16:34:43 iwd[5117]: ../iwd-1.26/src/scan.c:scan_request_triggered() Passive scan triggered for wdev 1
Apr 27 16:34:43 iwd[5117]: ../iwd-1.26/src/scan.c:scan_periodic_triggered() Periodic scan triggered for wdev 1
In the above log, scan request 5 (triggered by dbus) is started before
scan request 4 (periodic scan). Yet the scanning code thinks scan
request 4 was triggered.
Fix this by using the wiphy_work priority to sort the sr->requests queue
so that the scans are ordered in the same manner.
Reported-by: Alvin Šipraga <ALSI(a)bang-olufsen.dk>
---
src/scan.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/src/scan.c b/src/scan.c
index b0824e72ebaf..dd4fca531b36 100644
--- a/src/scan.c
+++ b/src/scan.c
@@ -611,6 +611,17 @@ static struct scan_request *scan_request_new(struct scan_context *sc,
return sr;
}
+static int insert_by_priority(const void *a, const void *b, void *user_data)
+{
+ const struct scan_request *new = a;
+ const struct scan_request *cur = b;
+
+ if (cur->work.priority <= new->work.priority)
+ return 1;
+
+ return -1;
+}
+
static uint32_t scan_common(uint64_t wdev_id, bool passive,
const struct scan_parameters *params,
int priority,
@@ -630,7 +641,7 @@ static uint32_t scan_common(uint64_t wdev_id, bool passive,
scan_cmds_add(sr->cmds, sc, passive, params);
- l_queue_push_tail(sc->requests, sr);
+ l_queue_insert(sc->requests, sr, insert_by_priority, NULL);
return wiphy_radio_work_insert(sc->wiphy, &sr->work,
priority, &work_ops);
@@ -801,7 +812,7 @@ uint32_t scan_owe_hidden(uint64_t wdev_id, struct l_queue *list,
}
done:
- l_queue_push_tail(sc->requests, sr);
+ l_queue_insert(sc->requests, sr, insert_by_priority, NULL);
return wiphy_radio_work_insert(sc->wiphy, &sr->work,
WIPHY_WORK_PRIORITY_SCAN, &work_ops);
--
2.32.0
2 months, 1 week
iwd stuck 'connecting', out-of-order wiphy work queue?
by Alvin Šipraga
Hi,
While running some automated tests for our product, I managed to make iwd get
stuck in 'connecting' state. I haven't cracked open gdb just yet, but I would
like to report my findings here in case somebody can give me some pointers as I
continue looking into it tomorrow.
The automated test essentially does some scans and requests iwd to connect to a
particular network. The network is not known, as iwd's saved data is erased at
the start of the test sequence. I invoke instances of iwctl to run the scans and
request the connection.
The bug: sometimes the connect request will get stuck and iwd will stay in
'connecting' state until I issue a disconnect.
Looking closely at the logs, and also with iwmon, I noticed that no connect
command is actually sent over netlink to the kernel. So iwd is getting stuck
before then.
Moreover, it seems like it might be getting stuck because the wiphy work queue
goes out-of-order somehow? Check this snippet from the logs:
../iwd-1.26/src/wiphy.c:wiphy_radio_work_next() Starting work item 1
../iwd-1.26/src/wiphy.c:wiphy_radio_work_done() Work item 1 done
../iwd-1.26/src/wiphy.c:wiphy_radio_work_insert() Inserting work item 2
../iwd-1.26/src/wiphy.c:wiphy_radio_work_next() Starting work item 2
../iwd-1.26/src/wiphy.c:wiphy_radio_work_insert() Inserting work item 3
../iwd-1.26/src/wiphy.c:wiphy_radio_work_done() Work item 2 done
../iwd-1.26/src/wiphy.c:wiphy_radio_work_next() Starting work item 3
../iwd-1.26/src/wiphy.c:wiphy_radio_work_insert() Inserting work item 4
../iwd-1.26/src/wiphy.c:wiphy_radio_work_insert() Inserting work item 5
../iwd-1.26/src/wiphy.c:wiphy_radio_work_done() Work item 3 done
../iwd-1.26/src/wiphy.c:wiphy_radio_work_next() Starting work item 5 <--- 5 is started...
../iwd-1.26/src/wiphy.c:wiphy_radio_work_done() Work item 4 done <--- 4 is done?!
../iwd-1.26/src/wiphy.c:wiphy_radio_work_insert() Inserting work item 6
A brief look at the code and I can't really understand how work item 4 could be
done when it was never started. Moreover, work item 5 gets started, but is never
done. Meanwhile, work item 6 (which I suspect to be the connect command) never
starts.
I've attached the logs, so any hints are very welcome. This is with iwd v1.26.
Kind regards,
Alvin
2 months, 1 week
WiFi interface stuck in 'Powered off' (link down) mode after suspend
by Toke Høiland-Jørgensen
Hi everyone
I am encountering a strange problem with my WiFi not coming back after a
suspend. Specifically, after a suspend-resume cycle, iwd will report,
when issuing a 'station list' in iwctl:
No devices in Station mode available.
But when issuing a 'device list' it shows up:
wlan0 7a:e2:f0:31:a5:ae off phy0 station
which is a bit confusing, IMO. Issuing a 'device wlan0 show' gets me:
Name wlan0
Mode station
Powered off
Address 7a:e2:f0:31:a5:ae
Adapter phy0
And issuing a 'device wlan0 set-property Powered on' restores the device
to working order and reconnects.
I went looking in the iwd source code, and it looks like that 'Powered'
in iwd lingo translates to 'link up' in the kernel, right? Indeed,
issuing an 'ip link up' on the wlan device after coming back from
suspend is enough to get me back online.
I'm honestly not really sure if this is a bug in the kernel, or in iwd.
I mean, it seems like iwd should be able to just set 'link up' and
continue on its merry way (and indeed if I restart iwd entirely it will
do this). But am also fairly sure it used to work on previous kernels,
so maybe the kernel behaviour changed? (I have not had a chance to test
this as bisecting is a bit cumbersome on my daily driver laptop; so
figured I'd ask y'all's opinion first).
This happens on a 5.17 kernel with an Intel AX201 device (using the
iwlwifi) driver.
Hoping someone can help me get this fixed, whether that be by fixing iwd
or telling me to go bisect the kernel :)
-Toke
2 months, 1 week
Ace Aqua Casa | 2/3 BHK Luxury Apartments Noida Extension
by aceaquacasa02@gmail.com
Ace Aqua Casa New launch Residence Project in Noida Extension 2/3 BHK lake View Apartments. Ace Aqua Casa Noida Extension is an insightfully planned project found only 5 minutes from Murti Chowk. It is a superior private advancement spread over 10.76 sections of land and has over 75% open spaces. visit:- <a href="https://www.aceaqua.in/">Ace Aqua Casa</a>
2 months, 2 weeks
[PATCH] test-runner: mount testhome rather than assume location
by James Prestwood
Usually the test home directory is a git repo somewhere e.g. under
/home. But if the home directory is located under /tmp this poses
a problem since UML remounts /tmp. To handle both cases mount
the home directory explicity.
---
tools/runner.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tools/runner.py b/tools/runner.py
index 7c177f1f..ac063c32 100644
--- a/tools/runner.py
+++ b/tools/runner.py
@@ -451,6 +451,9 @@ class QemuRunner(RunnerAbstract):
def prepare_environment(self):
mounts = [ MountInfo('debugfs', 'debugfs', '/sys/kernel/debug', '', 0) ]
+ mounts.append(MountInfo('hostfs', 'hostfs', self.args.testhome,
+ self.args.testhome, 0))
+
if self.args.log:
mounts.append(MountInfo('9p', 'logdir', self.args.log,
'trans=virtio,version=9p2000.L,msize=10240', 0))
--
2.34.1
2 months, 2 weeks
[PATCH] test-runner: remove root user requirement from log/monitor/result
by James Prestwood
Certain aspects of QEMU like mounting host directories may still require
root access but for UML this is not the case. To handle both cases first
check if SUDO_UID/GID are set and use those to obtain the actual users
ID's. Otherwise if running as non-root use the UID/GID of the user
directly.
---
tools/runner.py | 18 ++----------------
1 file changed, 2 insertions(+), 16 deletions(-)
diff --git a/tools/runner.py b/tools/runner.py
index 1739b786..7c177f1f 100644
--- a/tools/runner.py
+++ b/tools/runner.py
@@ -305,18 +305,12 @@ class RunnerAbstract:
# For QEMU/UML --log, --monitor, --result
def _prepare_outfiles(self):
- gid = None
append_gid_uid = False
- if os.environ.get('SUDO_GID', None):
- uid = int(os.environ['SUDO_UID'])
- gid = int(os.environ['SUDO_GID'])
+ uid = int(os.environ.get('SUDO_UID', os.getuid()))
+ gid = int(os.environ.get('SUDO_GID', os.getgid()))
if self.args.log:
- if os.getuid() != 0:
- print("--log can only be used as root user")
- quit()
-
append_gid_uid = True
if not os.path.exists(self.args.log):
@@ -326,20 +320,12 @@ class RunnerAbstract:
os.chown(self.args.log, uid, gid)
if self.args.monitor:
- if os.getuid() != 0:
- print("--monitor can only be used as root user")
- quit()
-
append_gid_uid = True
self.args.monitor_parent = os.path.abspath(
os.path.join(self.args.monitor, os.pardir))
if self.args.result:
- if os.getuid() != 0:
- print("--result can only be used as root user")
- quit()
-
append_gid_uid = True
self.args.result_parent = os.path.abspath(
--
2.34.1
2 months, 2 weeks
How to run separate iwd for every wifi dongle on the same host?
by zlinuxboy@outlook.com
I am trying to plug 3 wifi dongle into one SBC(odroid c2 running armbian 22.01), wish to run separate iwd instance for each wifi dongle, in order to connect different ssid and acquire dhcp ip address and assign to them.
I have successfully implement with systemd-networkd+vrf+iwd, assign three wifi dongle to different vrf. start iwd, all three wifi dongle could connect to the same ssid and get different ip with dhcp, including default route.
but when I assign different wifi dongle to the same ssid with different psk(my ap is aerohive, support ppsk, everything user have a different private key. cisco, ruckus, aruba has such the same feature), iwd could not save the multiple config for the same ssid, because the same ssid share one config. so any possible to run separate iwd for every wifi dongle?
2 months, 2 weeks
Possible bug when /var/lib/iwd is a symlink
by Joakim Lotsengård
Hi,
Possible bug when /var/lib/iwd is a symlink:
I ran across a problem when the ending part of /var/lib/iwd is a symlink.
In my case it points to /mnt/persistent/iwd. We are an IoT device that runs
on UBIFS (+ tmpfs) and the entire rootfs partition of the NAND will be
updated on FOTA. Hence anything we want to save in an upgrade must be on a
persistent partition. Our target is a Freescale i.MX6 Ultralite module
running an ARM A7 core (if that matters).
Problem seems to be that the l_dir_watch_new() call in knownnetworks.c never
follows symlink. l_dir_watch_new() uses IN_DONT_FOLLOW in its call to
inotify_add_watch() in ell.
This will make the known network list misbehave. If one forgets a
known-network via iwctl, the list doesn't get updated. The same goes for
connecting to a not already known network. It is easy to reproduce. Just
symlink /var/lib/iwd to another location and run some connect + forget in
iwctl. One can also note that adding a new /var/lib/iwd/my_ssid.psk, by
manually creating the file, is not picked up by iwd automatically.
I've only tested this with iwd 1.17 and ell 0.43 due to the complexity to
build another version using Yocto. However, I've checked the source code
for iwd on master and they don't seem to handle the fact that /var/lib/iwd
is a symlink. I've tried to search the mailing-list and google, but can't
find anything about this. It seems I can change the /var/lib/iwd directory
during compilation by setting DAEMON_STORAGEDIR during configure/build.
However, that is a bit unflexible as my system is Yocto based, and hacking
the Yocto recipes for this seems wrong. Normally you symlink things in your
file tree in IoT devices to point to persistent storage areas.
I don't have a solution, but at least iwd should detect that /var/lib/iwd is
a symlink and warn the user. The implication is that the known-network list
doesn't work at all. The internal known-network list should work even if
inotify doesn't.
Perhaps also it should be allowed to change the default storage dir in
/etc/iwd/main.conf.
--
Best regards,
Joakim Lotsengård
2 months, 2 weeks
[PATCH 1/4] dpp: handle sending a frame after ROC ends
by James Prestwood
There is a potential corner case of an offchannel frame callback
being called after ROC has ended.
This could happen in theory if a received frame is queued right as
the ROC session expires. If the ROC cancel event makes it to user
space before the frame IWD will schedule another ROC then receive
the frame. This doesn't prevent IWD from sending out another
frame since OFFCHANNEL_TX_OK is used, but it will prevent IWD from
receiving a response frame since no dwell duration is used with DPP.
To handle this an roc_started bool was added to the dpp_sm which
tracks the ROC state. If dpp_send_frame is called when roc_started
is false the frame will be saved and sent out once the ROC session
is started again.
---
src/dpp.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
diff --git a/src/dpp.c b/src/dpp.c
index 1719a89d..e817ca5a 100644
--- a/src/dpp.c
+++ b/src/dpp.c
@@ -138,12 +138,39 @@ struct dpp_sm {
uint32_t connect_scan_id;
uint64_t frame_cookie;
uint8_t frame_retry;
+ void *frame_pending;
+ size_t frame_size;
struct l_dbus_message *pending;
bool mcast_support : 1;
+ bool roc_started : 1;
};
+static void *dpp_serialize_iovec(struct iovec *iov, size_t iov_len,
+ size_t *out_len)
+{
+ unsigned int i;
+ size_t size = 0;
+ uint8_t *ret;
+
+ for (i = 0; i < iov_len; i++)
+ size += iov[i].iov_len;
+
+ ret = l_malloc(size);
+ size = 0;
+
+ for (i = 0; i < iov_len; i++) {
+ memcpy(ret + size, iov[i].iov_base, iov[i].iov_len);
+ size += iov[i].iov_len;
+ }
+
+ if (out_len)
+ *out_len = size;
+
+ return ret;
+}
+
static void dpp_free_auth_data(struct dpp_sm *dpp)
{
if (dpp->own_proto_public) {
@@ -209,6 +236,11 @@ static void dpp_reset(struct dpp_sm *dpp)
dpp->peer_asn1 = NULL;
}
+ if (dpp->frame_pending) {
+ l_free(dpp->frame_pending);
+ dpp->frame_pending = NULL;
+ }
+
dpp->state = DPP_STATE_NOTHING;
dpp->new_freq = 0;
dpp->frame_retry = 0;
@@ -267,6 +299,19 @@ static void dpp_send_frame(struct dpp_sm *dpp,
{
struct l_genl_msg *msg;
+ /*
+ * A received frame could potentially come in after the ROC session has
+ * ended. In this case the frame needs to be stored until ROC is started
+ * and sent at that time. The offchannel_id is also checked since
+ * this is not applicable when DPP is in a responder role waiting
+ * on the currently connected channel i.e. offchannel is never used.
+ */
+ if (!dpp->roc_started && dpp->offchannel_id) {
+ dpp->frame_pending = dpp_serialize_iovec(iov, iov_len,
+ &dpp->frame_size);
+ return;
+ }
+
msg = l_genl_msg_new_sized(NL80211_CMD_FRAME, 512);
l_genl_msg_append_attr(msg, NL80211_ATTR_WDEV, 8, &dpp->wdev_id);
l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY_FREQ, 4, &freq);
@@ -281,6 +326,20 @@ static void dpp_send_frame(struct dpp_sm *dpp,
}
}
+static void dpp_frame_retry(struct dpp_sm *dpp)
+{
+ struct iovec iov;
+
+ iov.iov_base = dpp->frame_pending;
+ iov.iov_len = dpp->frame_size;
+
+ dpp_send_frame(dpp, &iov, 1, dpp->current_freq);
+
+ l_free(dpp->frame_pending);
+ dpp->frame_pending = NULL;
+}
+
+
static size_t dpp_build_header(const uint8_t *src, const uint8_t *dest,
enum dpp_frame_type type,
uint8_t buf[static 32])
@@ -1360,6 +1419,13 @@ static void dpp_roc_started(void *user_data)
* the authenticate response now.
*/
+ dpp->roc_started = true;
+
+ if (dpp->frame_pending) {
+ dpp_frame_retry(dpp);
+ return;
+ }
+
switch (dpp->state) {
case DPP_STATE_PRESENCE:
if (dpp->role == DPP_CAPABILITY_CONFIGURATOR)
@@ -1409,6 +1475,7 @@ static void dpp_presence_timeout(int error, void *user_data)
struct dpp_sm *dpp = user_data;
dpp->offchannel_id = 0;
+ dpp->roc_started = false;
/*
* If cancelled this is likely due to netdev going down or from Stop().
--
2.34.1
2 months, 3 weeks