iwd has at time of writing two major issues:
- requiring a (to time of writing) comparatively recent Linux version (<= 4.20) due to upstream bugfixes in its crypto subsystem
- being so fast that it might bring up the wireless interface before in can be renamed by udev
While the first issue will resolve itself over time, the second one is a little harder to tackle.
When a Linux system boots up, all the interfaces get initialized.
They are named by linux in order of showing up, typically to
eth1, etc. for wired cards and
wlan1 etc. for wireless cards.
Which card gets which identifier depends solely on the order of getting noticed by Linux and it isn’t even guaranteed that wireless cards will be named
wlan*, on some systems they also end up with a
Therefore every piece of software doing things with interfaces based on their names is at risk of picking the wrong network card at some point.
To tackle this problem, systemd introduced persistent naming.
Now your network cards are no longer named
enp2s5 or something like that, generated from properties of the network card.
Much less beautiful, but persistent and therefore very desirable, fixing the race condition described above – however, doing so by introducing another race condition.
The reason for this is that this rename can only happen when the network interface is down. iwd, however, being much faster than other alternatives (namely wpa_supplicant and everything that’s built on it) might already bring the wireless interface up before udev had the chance to rename the interface, which is then no longer possible, leaving it with the (race condition afflicted) kernel name.
To solve this issue, we can delay starting iwd until the rename has happened, removing the second race condition from the mix.
To do so we first need to find the name of our wireless interface via
ip link, yielding something like
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT ... link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: wlp3s2: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN ... link/ether 8c:7b:83:7d:04:82 brd ff:ff:ff:ff:ff:ff 3: enp4s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode ... link/ether e4:2d:9a:bb:e4:f4 brd ff:ff:ff:ff:ff:ff
The wireless device here is named
wlp3s2, the wired one is
In systemd, both cards get a device-unit upon appearance, for the wireless device this is
They can be found in the unit list one gets from
iwd is only started after the wireless card was renamed to
wlp3s2, we just need to make the unit starting it wait for said device-unit.
This is easiest accomplished by issuing a
systemctl edit iwd.service and entering:
[Unit] Requires=sys-subsystem-net-devices-wlp3s2.device After=sys-subsystem-net-devices-wlp3s2.device
systemd will then add those options dynamically to the loaded
iwd.service-file when loading it, making it wait for the device
wlp3s2 and start after that unit is done setting up, by when the rename has already been performed.
This, of course, requires manual intervention and only works for a single wireless network card, but should suffice for most setups and while not removing the root of the race condition resolves its symptoms with