[LEDE-DEV] [PATCH] mac80211: Fix race condition leading to wifi interfaces not coming up at boot sometimes.

Vittorio G (VittGam) openwrt at vittgam.net
Mon Mar 13 22:59:37 PDT 2017


If you're wondering where the -ENFILE error comes from...

At first I thought it was obviously related to fs.file-max that
defaults to "just" 8192.

But it was not. It took me a while to figure out that the error
came from here instead...

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/core/dev.c?id=13baa00ad01bb3a9f893e3a08cbc2d072fc0c15d#n1070

In fact, -ENFILE is returned every time one tries to add a wireless
virtual interface with the same name as another existing one.
(Maybe the error code should be changed to -EEXIST when an explicit
interface name is requested and it turns out to be already taken,
like in this case... Time for a kernel patch, maybe!)

This issue was also very time-sensitive; when I added some debug
prints to iw, it disappeared...

On 14/03/2017 06:19:44 CET, Vittorio Gambaletta (VittGam) wrote:
> 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>
> 
> ---
>  .../mac80211/files/lib/netifd/wireless/mac80211.sh |   35 +++++++++++++++++---
>  1 file changed, 30 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 baa023e..5058b01 100644
> --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
> +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
> @@ -411,6 +411,31 @@ mac80211_check_ap() {
>  	has_ap=1
>  }
>  
> +mac80211_iw_interface_add() {
> +	local phy="$1"
> +	local ifname="$2"
> +	local type="$3"
> +	local wdsflag="$4"
> +
> +	iw phy "$phy" interface add "$ifname" type "$type" $wdsflag
> +	ret="$?"
> +
> +	[ "$ret" = 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
> +		ret="$?"
> +	}
> +
> +	[ "$ret" != 0 ] && {
> +		wireless_setup_failed INTERFACE_CREATION_FAILED
> +		return 1
> +	}
> +
> +	return 0
> +}
> +
>  mac80211_prepare_vif() {
>  	json_select config
>  
> @@ -437,7 +462,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 +476,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"
>  		;;
> 
> 
> _______________________________________________
> Lede-dev mailing list
> Lede-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/lede-dev



More information about the Lede-dev mailing list