[source] mac80211: Fix race condition leading to wifi interfaces not coming up at boot sometimes.

LEDE Commits lede-commits at lists.infradead.org
Thu Dec 14 09:43:40 PST 2017


jow pushed a commit to source.git, branch lede-17.01:
https://git.lede-project.org/62a8252a0f32d6c148e4565354fd6a99da13fa41

commit 62a8252a0f32d6c148e4565354fd6a99da13fa41
Author: Vittorio Gambaletta <openwrt at vittgam.net>
AuthorDate: Tue Mar 14 14:45:15 2017 +0100

    mac80211: Fix race condition leading to wifi interfaces not coming up at boot sometimes.
    
    In the drv_mac80211_setup function, mac80211_interface_cleanup
    is called to ask the kernel to delete all existing interfaces
    for the phy that is being configured via netlink.
    
    Later in the first function, mac80211_prepare_vif is called to
    set up the new interfaces as required.
    
    But sometimes, when mac80211_prepare_vif (and so the relevant
    `iw phy x interface add y` command) runs, the kernel might still
    be cleaning up the old interface with the same ifname. It usually
    takes very few time to do that; possibly a few milliseconds of
    sleep in the script after detecting this error condition could be
    enough, but the busybox sh does not support sub-second sleep
    intervals.
    
    When this happens, iw obviously fails to create the new interface;
    and the following message is printed in the system log, followed by
    subsequent failure messages from hostapd in case this would have been
    an AP interface.
    
    Tue Mar 14 04:21:57 2017 daemon.notice netifd: radio1 (2767): command failed: Too many open files in system (-23)
    
    This was a long-standing issue existing since at least OpenWrt Backfire,
    and today I finally managed to debug and (hopefully) solve it.
    It was happening very few times on most devices; but it was happening
    a lot more frequently on fast platforms with multiple radios, such as
    the powerpc-based dual-ath9k-radio tl-wdr4900-v1.
    
    Signed-off-by: Vittorio Gambaletta <openwrt at vittgam.net>
    (cherry picked from commit 8301e613655c2d95fa5430a1a57d92d966fdc70b)
---
 .../mac80211/files/lib/netifd/wireless/mac80211.sh | 32 ++++++++++++++++++----
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
index 82c3743..cda6f9f 100644
--- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
+++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
@@ -411,6 +411,28 @@ mac80211_check_ap() {
 	has_ap=1
 }
 
+mac80211_iw_interface_add() {
+	local phy="$1"
+	local ifname="$2"
+	local type="$3"
+	local wdsflag="$4"
+	local rc
+
+	iw phy "$phy" interface add "$ifname" type "$type" $wdsflag
+	rc="$?"
+
+	[ "$rc" = 233 ] && {
+		# Device might have just been deleted, give the kernel some time to finish cleaning it up
+		sleep 1
+
+		iw phy "$phy" interface add "$ifname" type "$type" $wdsflag
+		rc="$?"
+	}
+
+	[ "$rc" != 0 ] && wireless_setup_failed INTERFACE_CREATION_FAILED
+	return $rc
+}
+
 mac80211_prepare_vif() {
 	json_select config
 
@@ -437,7 +459,7 @@ mac80211_prepare_vif() {
 	# It is far easier to delete and create the desired interface
 	case "$mode" in
 		adhoc)
-			iw phy "$phy" interface add "$ifname" type adhoc
+			mac80211_iw_interface_add "$phy" "$ifname" adhoc || return
 		;;
 		ap)
 			# Hostapd will handle recreating the interface and
@@ -451,21 +473,21 @@ mac80211_prepare_vif() {
 			mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return
 
 			[ -n "$hostapd_ctrl" ] || {
-				iw phy "$phy" interface add "$ifname" type __ap
+				mac80211_iw_interface_add "$phy" "$ifname" __ap || return
 				hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}"
 			}
 		;;
 		mesh)
-			iw phy "$phy" interface add "$ifname" type mp
+			mac80211_iw_interface_add "$phy" "$ifname" mp || return
 		;;
 		monitor)
-			iw phy "$phy" interface add "$ifname" type monitor
+			mac80211_iw_interface_add "$phy" "$ifname" monitor || return
 		;;
 		sta)
 			local wdsflag=
 			staidx="$(($staidx + 1))"
 			[ "$wds" -gt 0 ] && wdsflag="4addr on"
-			iw phy "$phy" interface add "$ifname" type managed $wdsflag
+			mac80211_iw_interface_add "$phy" "$ifname" managed "$wdsflag" || return
 			[ "$powersave" -gt 0 ] && powersave="on" || powersave="off"
 			iw "$ifname" set power_save "$powersave"
 		;;



More information about the lede-commits mailing list