[OpenWrt-Devel] [PATCH 4/5] mac80211: add support for dynamically reconfiguring wifi

Daniel Golle daniel at makrotopia.org
Wed Oct 30 11:58:19 EDT 2019


From: John Crispin <john at phrozen.org>

Change scripts to use ubus interface of hostapd/wpa_supplicant to
add/remove/modify wireless interfaces instead of (re-)starting the
services.

Signed-off-by: Daniel Golle <daniel at makrotopia.org>
---
 .../files/lib/netifd/wireless/mac80211.sh     | 135 ++++++++++++++----
 1 file changed, 107 insertions(+), 28 deletions(-)

diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
index f9d5c0c6d5..e62a53f5be 100644
--- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
+++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
@@ -18,6 +18,11 @@ iw() {
 	command iw $@ || logger -t mac80211 "Failed command: iw $@"
 }
 
+NEWAPLIST=
+OLDAPLIST=
+NEWSPLIST=
+OLDSPLIST=
+
 drv_mac80211_init_device_config() {
 	hostapd_common_add_device_config
 
@@ -57,7 +62,7 @@ drv_mac80211_init_iface_config() {
 
 	config_add_string 'macaddr:macaddr' ifname
 
-	config_add_boolean wds powersave
+	config_add_boolean wds powersave enable
 	config_add_int maxassoc
 	config_add_int max_listen_int
 	config_add_int dtim_period
@@ -456,7 +461,7 @@ mac80211_iw_interface_add() {
 mac80211_prepare_vif() {
 	json_select config
 
-	json_get_vars ifname mode ssid wds powersave macaddr
+	json_get_vars ifname mode ssid wds powersave macaddr enable
 
 	[ -n "$ifname" ] || ifname="wlan${phy#phy}${if_idx:+-$if_idx}"
 	if_idx=$((${if_idx:-0} + 1))
@@ -492,8 +497,8 @@ mac80211_prepare_vif() {
 
 			mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return
 
+			NEWAPLIST="${NEWAPLIST}$ifname "
 			[ -n "$hostapd_ctrl" ] || {
-				mac80211_iw_interface_add "$phy" "$ifname" __ap || return
 				hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}"
 			}
 		;;
@@ -505,7 +510,7 @@ mac80211_prepare_vif() {
 		;;
 		sta)
 			local wdsflag=
-			staidx="$(($staidx + 1))"
+			[ "$enable" = 0 ] || staidx="$(($staidx + 1))"
 			[ "$wds" -gt 0 ] && wdsflag="4addr on"
 			mac80211_iw_interface_add "$phy" "$ifname" managed "$wdsflag" || return
 			[ "$powersave" -gt 0 ] && powersave="on" || powersave="off"
@@ -531,19 +536,51 @@ mac80211_prepare_vif() {
 }
 
 mac80211_setup_supplicant() {
+	local add_sp=0
+	local spobj="$(ubus -S list | grep wpa_supplicant.${ifname})"
+
 	wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1
+	wpa_supplicant_prepare_interface "$ifname" nl80211 || {
+		iw dev "$ifname" del
+		return 1
+	}
 	if [ "$mode" = "sta" ]; then
 		wpa_supplicant_add_network "$ifname"
 	else
 		wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan"
 	fi
-	wpa_supplicant_run "$ifname" ${hostapd_ctrl:+-H $hostapd_ctrl}
+
+	NEWSPLIST="${NEWSPLIST}$ifname "
+
+	if [ "${NEWAPLIST%% *}" != "${OLDAPLIST%% *}" ]; then
+		[ "$spobj" ] && ubus call wpa_supplicant.${phy} config_del "{\"iface\":\"$ifname\"}"
+		add_sp=1
+	fi
+	[ -z "$spobj" ] && add_sp=1
+
+	if [ "$add_sp" = "1" ]; then
+		wpa_supplicant_run "$ifname" "$hostapd_ctrl"
+	else
+		ubus call $spobj reload
+	fi
 }
 
 mac80211_setup_supplicant_noctl() {
-	wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1
+	local spobj="$(ubus -S list | grep wpa_supplicant.${ifname})"
+	wpa_supplicant_prepare_interface "$ifname" nl80211 || {
+		iw dev "$ifname" del
+		return 1
+	}
+
 	wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan"
-	wpa_supplicant_run "$ifname"
+
+	NEWSPLIST="${NEWSPLIST}$ifname "
+
+	if [ -z "$spobj" ]; then
+		wpa_supplicant_run "$ifname"
+	else
+		ubus call $spobj reload
+	fi
 }
 
 mac80211_setup_adhoc_htmode() {
@@ -581,7 +618,6 @@ mac80211_setup_adhoc_htmode() {
 		;;
 		*) ibss_htmode="" ;;
 	esac
-
 }
 
 mac80211_setup_adhoc() {
@@ -672,6 +708,7 @@ mac80211_setup_mesh() {
 mac80211_setup_vif() {
 	local name="$1"
 	local failed
+	local action=up
 
 	json_select data
 	json_get_vars ifname
@@ -680,13 +717,15 @@ mac80211_setup_vif() {
 	json_select config
 	json_get_vars mode
 	json_get_var vif_txpower txpower
+	json_get_var vif_enable enable 1
 
-	ip link set dev "$ifname" up || {
+	[ "$vif_enable" = 1 ] || action=down
+	logger ip link set dev "$ifname" $action
+	ip link set dev "$ifname" "$action" || {
 		wireless_setup_vif_failed IFUP_ERROR
 		json_select ..
 		return
 	}
-
 	set_default vif_txpower "$txpower"
 	[ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00"
 
@@ -736,15 +775,27 @@ chan_is_dfs() {
 	return $!
 }
 
-mac80211_interface_cleanup() {
-	local phy="$1"
+mac80211_vap_cleanup() {
+	local service="$1"
+	local vaps="$2"
 
-	for wdev in $(list_phy_interfaces "$phy"); do
+	for wdev in $vaps; do
+		ubus call ${service}.${phy} config_remove "{\"iface\":\"$wdev\"}"
 		ip link set dev "$wdev" down 2>/dev/null
 		iw dev "$wdev" del
 	done
 }
 
+mac80211_interface_cleanup() {
+	local phy="$1"
+	local primary_ap=$(uci -q -P /var/state get wireless._${phy}.aplist)
+	primary_ap=${primary_ap%% *}
+
+	mac80211_vap_cleanup hostapd "${primary_ap}"
+	mac80211_vap_cleanup wpa_supplicant "$(uci -q -P /var/state get wireless._${phy}.splist)"
+}
+
+
 mac80211_set_noscan() {
 	hostapd_noscan=1
 }
@@ -770,8 +821,10 @@ drv_mac80211_setup() {
 		return 1
 	}
 
-	wireless_set_data phy="$phy"
-	mac80211_interface_cleanup "$phy"
+	[ -z "$(uci -q -P /var/state show wireless._${phy})" ] && {
+		uci -q -P /var/state set wireless._${phy}=phy
+		wireless_set_data phy="$phy"
+	}
 
 	# convert channel to frequency
 	[ "$auto_channel" -gt 0 ] || freq="$(get_freq "$phy" "$channel")"
@@ -821,30 +874,55 @@ drv_mac80211_setup() {
 	[ -n "$has_ap" ] && mac80211_hostapd_setup_base "$phy"
 
 	for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif
+	NEWAPLIST=
 	for_each_interface "ap" mac80211_prepare_vif
-
+	OLDAPLIST=$(uci -q -P /var/state get wireless._${phy}.aplist)
+	NEW_MD5=$(md5sum ${hostapd_conf_file})
+	OLD_MD5=$(uci -q -P /var/state get wireless._${phy}.md5)
+	if [ "${NEWAPLIST}" != "${OLDAPLIST}" ]; then
+		mac80211_vap_cleanup hostapd "${OLDAPLIST}"
+		[ -n "${NEWAPLIST}" ] && mac80211_iw_interface_add "$phy" "${NEWAPLIST%% *}" __ap || return
+	fi
+	local add_ap=0
+	local primary_ap=${NEWAPLIST%% *}
 	[ -n "$hostapd_ctrl" ] && {
-		/usr/sbin/hostapd -s -P /var/run/wifi-$phy.pid -B "$hostapd_conf_file"
+		if [ -n "$(ubus list | grep hostapd.$primary_ap)" ]; then
+			[ "${NEW_MD5}" = "${OLD_MD5}" ] || {
+				ubus call hostapd.$primary_ap reload
+			}
+		else
+			add_ap=1
+			ubus call hostapd.${phy} config_add "{\"iface\":\"$primary_ap\", \"config\":\"${hostapd_conf_file}\"}"
+		fi
 		ret="$?"
-		wireless_add_process "$(cat /var/run/wifi-$phy.pid)" "/usr/sbin/hostapd" 1
 		[ "$ret" != 0 ] && {
 			wireless_setup_failed HOSTAPD_START_FAILED
 			return
 		}
 	}
+	uci -q -P /var/state set wireless._${phy}.aplist="${NEWAPLIST}"
+	uci -q -P /var/state set wireless._${phy}.md5="${NEW_MD5}"
 
-	for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif
+	[ "${add_ap}" = 1 ] && sleep 1
+	for_each_interface "ap" mac80211_setup_vif
 
-	wireless_set_up
-}
+	NEWSPLIST=
+	OLDSPLIST=$(uci -q -P /var/state get wireless._${phy}.splist)
+	for_each_interface "sta adhoc mesh monitor" mac80211_setup_vif
 
-list_phy_interfaces() {
-	local phy="$1"
-	if [ -d "/sys/class/ieee80211/${phy}/device/net" ]; then
-		ls "/sys/class/ieee80211/${phy}/device/net" 2>/dev/null;
-	else
-		ls "/sys/class/ieee80211/${phy}/device" 2>/dev/null | grep net: | sed -e 's,net:,,g'
-	fi
+	uci -q -P /var/state set wireless._${phy}.splist="${NEWSPLIST}"
+
+	local foundvap
+	local dropvap=""
+	for oldvap in $OLDSPLIST; do
+		foundvap=0
+		for newvap in $NEWSPLIST; do
+			[ "$oldvap" = "$newvap" ] && foundvap=1
+		done
+		[ "$foundvap" = "0" ] && dropvap="$dropvap $oldvap"
+	done
+	[ -n "$dropvap" ] && mac80211_vap_cleanup wpa_supplicant "$dropvap"
+	wireless_set_up
 }
 
 drv_mac80211_teardown() {
@@ -855,6 +933,7 @@ drv_mac80211_teardown() {
 	json_select ..
 
 	mac80211_interface_cleanup "$phy"
+	uci -q -P /var/state revert wireless._${phy}
 }
 
 add_driver mac80211
-- 
2.23.0


_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list