Summary
On a GL.iNet Flint 3 (GL-BE9300), the main 2.4, 5, and 6 GHz Wi-Fi networks advertise normally and accept client associations after a reboot, but the corresponding interfaces (wlan0, wlan1, and wlan2) are not attached to br-lan. DHCP broadcasts therefore do not reach the LAN DHCP server.
Guest, IoT, VPN, and MLO interfaces are attached to their respective bridges and continue to work.
A manual wifi reload restores bridge membership for all three main interfaces, but the problem returns after every reboot.
My investigation found that the qsdk-wifi setup handler throws a Lua exception during its first boot-time request and never replies to netifd. All three netifd workers wait for their explicit 600-second ubus timeout. The wireless driver then incorrectly marks each radio up despite the failed setup.
Device and firmware
| Field | Value |
|---|---|
| Device | GL.iNet Flint 3 / GL-BE9300 |
| Firmware base | OpenWrt 23.05-SNAPSHOT |
| OpenWrt revision | r0-3601c2a49 |
| Target | ipq53xx/generic |
| Architecture | aarch64_cortex-a53_neon-vfpv4 |
| Wireless stack | Qualcomm/QSDK, Wi-Fi 7/MLO |
gl-sdk4-qsdk-wifi |
git-2026.239.24451-38e5a78-1 |
netifd |
2024-01-04-c18cc79d-1 |
qca-wifi-scripts |
1 |
Network layout
| Interface | Purpose | Expected bridge | State after boot |
|---|---|---|---|
wlan0 |
Main 2.4 GHz AP | br-lan |
No bridge master |
wlan1 |
Main 5 GHz AP | br-lan |
No bridge master |
wlan2 |
Main 6 GHz AP | br-lan |
No bridge master |
mld0 |
Main MLO aggregate | br-lan |
Correctly attached |
wlan01 |
Guest AP | br-guest |
Correctly attached |
wlan06 |
IoT AP | br-iot |
Correctly attached |
ath12 |
VPN AP | br-vpnwifi |
Correctly attached |
eth1.1 |
Wired LAN | br-lan |
Correctly attached |
The main SSID is shared by the conventional and MLO APs. Credentials and unrelated private configuration have been omitted from this report.
Steps to reproduce
-
Configure the main AP interfaces on all three radios with
network='lan'. -
Reboot the router.
-
Wait for the main SSID to appear.
-
Connect a non-MLO client to the main SSID.
-
Observe that the client associates but does not obtain a DHCP lease.
-
Inspect bridge membership:
bridge link show dev wlan0
bridge link show dev wlan1
bridge link show dev wlan2
ubus call network.device status '{"name":"br-lan"}'
-
Run
wifi reload. -
Repeat the bridge queries and DHCP test.
Actual result
Immediately after boot, all three conventional main AP interfaces exist and are up, but none has a bridge master:
wlan0 UP <BROADCAST,MULTICAST,UP,LOWER_UP>
wlan1 UP <BROADCAST,MULTICAST,UP,LOWER_UP>
wlan2 UP <BROADCAST,MULTICAST,UP,LOWER_UP>
bridge link contains no entry for those interfaces.
Netifd's own bridge state confirms the same result:
{
"bridge-members": [
"eth1.1",
"mld0"
]
}
DHCP requests are visible on the affected wireless interface but do not reach br-lan. Manually attaching an affected VAP immediately restores connectivity:
ip link set wlan1 master br-lan
Running wifi reload restores the expected state for all three VAPs:
wlan0 master br-lan state forwarding
wlan1 master br-lan state forwarding
wlan2 master br-lan state forwarding
The failure returns after reboot.
Expected result
Every enabled AP VAP configured with network='lan' should be registered with netifd and attached to br-lan after boot:
wlan0 master br-lan state forwarding
wlan1 master br-lan state forwarding
wlan2 master br-lan state forwarding
mld0 master br-lan state forwarding
Clients connecting to any advertised main AP should receive DHCP service without requiring a wireless reload.
Relevant persistent configuration
The affected wireless sections contain the correct network assignment. For example:
wireless.wifi5g.device='wifi1'
wireless.wifi5g.network='lan'
wireless.wifi5g.mode='ap'
wireless.wifi5g.ifname='wlan1'
The LAN bridge is also configured correctly:
network.@device[0].name='br-lan'
network.@device[0].type='bridge'
network.@device[0].ports='eth1.1'
network.lan.device='br-lan'
network.lan.proto='static'
network.lan.ipaddr='192.168.1.1'
The netifd-generated QSDK setup request includes both:
"bridge": "br-lan",
"bridge_ifname": "br-lan"
and the VAP configuration contains:
"network": ["lan"]
This indicates that UCI-to-netifd translation recognizes the intended network.
Boot log evidence
At boot, the three netifd wireless workers report an MLO data warning:
12:09:57 netifd: wifi0 (...): WARNING: Variable 'mld' does not exist or is not an array/object
12:09:57 netifd: wifi1 (...): WARNING: Variable 'mld' does not exist or is not an array/object
12:09:57 netifd: wifi2 (...): WARNING: Variable 'mld' does not exist or is not an array/object
The QSDK configurator then enters its first-setup path and throws immediately:
12:09:58 qsdk-wifi: first setup
12:09:58 qsdk-wifi: .../gl-sdk4-qsdk-wifi/usr/sbin/qca-wifi-configurator:1316: table index is nil
Exactly one configured ubus timeout later, all three workers fail:
12:20:27 netifd: wifi0 (...): Command failed: ubus call qsdk-wifi setup { ... }
12:20:27 netifd: Wireless device 'wifi0' is now up
12:20:27 netifd: wifi1 (...): Command failed: ubus call qsdk-wifi setup { ... }
12:20:27 netifd: Wireless device 'wifi1' is now up
12:20:27 netifd: wifi2 (...): Command failed: ubus call qsdk-wifi setup { ... }
12:20:27 netifd: Wireless device 'wifi2' is now up
The ten-minute duration comes from /lib/netifd/wireless/qcawificfg80211.sh:
ubus -t 600 call qsdk-wifi setup "$(json_dump)"
echo "$(json_dump)" > /tmp/qcawificfg80211_${1}_bak
wireless_set_up
The Lua exception occurs almost immediately. The apparent 600-second “hang” is the ubus client waiting because the exception path does not return a success response or error response. The driver subsequently calls wireless_set_up without checking whether ubus ... setup succeeded.
The configurator process remains alive under procd after the exception, so it is not restarted:
/usr/bin/lua /usr/sbin/qca-wifi-configurator
Conflicting initialization paths
Two Qualcomm initialization paths run during boot:
| Component | Startup order | Role |
|---|---|---|
/etc/init.d/qca-wifi-configurator |
START=15 |
Provides the qsdk-wifi ubus service |
/etc/init.d/network |
START=20 |
Starts netifd and its qcawificfg80211 workers |
/etc/init.d/qcawifi-legacy |
START=22 |
Runs /sbin/wifi reload_legacy |
qcawifi-legacy contains bridge-attachment code:
add_bridge_iface() {
config_get ifname "$1" ifname
config_get mld "$1" mld
config_get disabled "$1" disabled
config_get network "$1" network
[ "$disabled" = "1" ] && return
if [ -n "$mld" ]; then
brctl addif br-$network $mld
else
brctl addif br-$network $ifname
fi
}
However, that code is called only from the service's reload() function. Its boot-time start() function performs wifi reload_legacy but never runs add_bridge_iface:
start() {
config_load wireless
config_foreach wait_for_mldphy_create wifi-iface
ubus -t 30 wait_for network.interface
/sbin/wifi reload_legacy "" "network_reload_legacy"
echo "Bringup wifi " > /dev/kmsg
}
The boot log also records:
procd: /etc/rc.d/S22qcawifi-legacy: sh: 1: unknown operand
The conventional APs are brought up through this overlapping initialization sequence, but their bridge attachment is omitted. MLO follows separate QSDK code that explicitly removes and re-adds mld0 through netifd, which explains why mld0 is attached correctly.
Suspected root cause
There appear to be three related defects:
- Invalid or incomplete MLO setup data: all three workers report that
mldis missing or not an object immediately before the configurator exception. - Unanswered ubus request after Lua exception:
qca-wifi-configuratorthrowstable index is nilin its first-setup handler and does not reply with an error, leaving clients blocked until-t 600expires. - Incorrect success state after setup failure:
qcawificfg80211.shcallswireless_set_upunconditionally after the failed ubus request.
Additionally, the netifd setup path and qcawifi-legacy run concurrently and appear to have overlapping ownership of VAP creation and bridge attachment.
The immediate demonstrated cause of the ten-minute delay is the unanswered ubus request following the Lua exception. The exact nil table key cannot be identified from the device because /usr/sbin/qca-wifi-configurator is installed as compiled Lua 5.1 bytecode and its matching source is not included.
Requested fixes
Please consider the following changes in gl-sdk4-qsdk-wifi:
-
Fix the
mldtable construction or validation leading to the exception atqca-wifi-configurator:1316. -
Wrap every
qsdk-wifiubus request handler so all failure paths return an explicit ubus error. -
Check the return status of:
ubus -t 600 call qsdk-wifi setup ...
and do not call wireless_set_up after failure.
-
Register each successfully created, non-MLO AP VAP with netifd, preferably through the standard
wireless_add_vif <section> <ifname>API. -
Register an MLO aggregate such as
mld0once rather than adding each MLO link VAP independently. -
Remove the overlapping ownership between
qcawifi-legacyand the newerqca-wifi-configurator, or serialize them with an explicit completion dependency. -
Avoid a fixed-delay workaround. Bridge registration should occur in response to successful VAP creation.
Equivalent explicit netifd device registration would be:
ubus call network.interface.<network> add_device '{"name":"<ifname>"}'
but using netifd's wireless-driver notification API is preferable because it preserves ownership and teardown semantics.
AI assistance disclosure
This report was prepared with the help of an AI assistant. The assistant helped organize the investigation, analyze the collected read-only diagnostics, and draft the report. The router observations, configuration excerpts, runtime state, and log messages cited above came from the affected device and were reviewed before submission.
