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 <open...@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@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/lede-dev

Reply via email to