Ubiquitis airmax based gear does not fallback to original port after DFS event is over. This tool triggers the fallback automatically by soft-restarting unconditionally, whenever the configured freq differs from the running. Signed-off-by: Simon Polack <spolack+git@mailbox.org>lilik-openwrt-22.03
@ -0,0 +1,46 @@ | |||||
# SPDX-License-Identifier: GPL-2.0-only | |||||
# | |||||
# Copyright (C) 2021 Simon Polack <spolack+git@@mailbox.org> | |||||
# | |||||
include $(TOPDIR)/rules.mk | |||||
PKG_NAME:=airos-dfs-reset | |||||
PKG_VERSION:=1 | |||||
PKG_RELEASE:=$(AUTORELEASE) | |||||
PKG_MAINTAINER:=Simon Polack <spolack+git@mailbox.org> | |||||
PKG_LICENSE:=GPL-2.0-only | |||||
include $(INCLUDE_DIR)/package.mk | |||||
define Package/airos-dfs-reset | |||||
SECTION:=utils | |||||
CATEGORY:=Utilities | |||||
TITLE:=Companion app for Ubiquity AirOS to help with DFS | |||||
PKGARCH:=all | |||||
EXTRA_DEPENDS:=dropbear | |||||
endef | |||||
define Package/airos-dfs-reset/description | |||||
Companion app for Ubiquity AirOS Gear to enforce fallback to original frequency after DFS event is over. | |||||
It works by soft-rebooting if running-frequency doesnt match the configured frequency. | |||||
endef | |||||
define Package/airos-dfs-reset/conffiles | |||||
/etc/config/airos-dfs-reset | |||||
endef | |||||
define Build/Compile | |||||
endef | |||||
define Package/airos-dfs-reset/install | |||||
$(INSTALL_DIR) $(1)/etc/init.d | |||||
$(INSTALL_BIN) ./files/airos-dfs-reset.init $(1)/etc/init.d/airos-dfs-reset | |||||
$(INSTALL_DIR) $(1)/usr/bin | |||||
$(INSTALL_BIN) ./files/airos-dfs-reset $(1)/usr/bin/airos-dfs-reset | |||||
$(INSTALL_DIR) $(1)/etc/config | |||||
$(INSTALL_DATA) ./files/airos-dfs-reset.config $(1)/etc/config/airos-dfs-reset | |||||
endef | |||||
$(eval $(call BuildPackage,airos-dfs-reset)) |
@ -0,0 +1,114 @@ | |||||
#!/bin/sh | |||||
. /lib/functions.sh | |||||
log() { | |||||
local msg="$1" | |||||
logger -t airos-dfs-reset -s "$msg" | |||||
} | |||||
rexec() { | |||||
local target="$1" | |||||
local username="$2" | |||||
local password="$3" | |||||
local cmd="$4" | |||||
raw=$(DROPBEAR_PASSWORD="$password" ssh -y $username@$target "$cmd") | |||||
ssh_result=$? | |||||
} | |||||
reset_dfs() { | |||||
local cmd="/usr/etc/rc.d/rc.softrestart force" | |||||
rexec $* "$cmd" | |||||
} | |||||
get_running_freq() { | |||||
local cmd="iwconfig ath0 | grep Frequency | awk -F ':' '{print \$3}' | awk '{print \$1}' | sed 's/\.//'" | |||||
rexec $* "$cmd" | |||||
# Append zeroes which are then cut to 4, we have to convert GHz into MHz | |||||
raw="$raw"000 | |||||
running_freq=${raw:0:4} | |||||
} | |||||
get_target_freq() { | |||||
local cmd="grep 'radio.1.freq' /tmp/system.cfg | awk -F '=' '{ print \$2}'" | |||||
rexec $* "$cmd" | |||||
target_freq="$raw" | |||||
} | |||||
check_dfs() { | |||||
local target="$1" | |||||
local username="$2" | |||||
local password="$3" | |||||
get_running_freq $target $username $password | |||||
if [ "$ssh_result" != 0 ]; then | |||||
return | |||||
fi | |||||
get_target_freq $target $username $password | |||||
if [ "$ssh_result" != 0 ]; then | |||||
return | |||||
fi | |||||
log "Running freq: $running_freq - Target freq: $target_freq" | |||||
[ "$running_freq" == "$target_freq" ] | |||||
} | |||||
reset_allowed() { | |||||
local daytime_limit="$1" | |||||
local start="$(echo $daytime_limit | awk -F '-' '{print $1'})" | |||||
local end="$(echo $daytime_limit | awk -F '-' '{print $2'})" | |||||
local cur="$(date +%H)" | |||||
[ "$cur" -ge "$start" ] && [ "$cur" -le "$end" ] | |||||
} | |||||
handle_device() { | |||||
local device="$1" | |||||
config_get target "$device" target | |||||
config_get username "$device" username | |||||
config_get password "$device" password | |||||
config_get daytime_limit "$device" daytime_limit "0-23" | |||||
ssh_result=0 | |||||
log "Checking Device $device" | |||||
check_dfs $target $username $password | |||||
freqmatch=$? | |||||
if [ "$ssh_result" != 0 ]; then | |||||
log "ssh exited non-zero - connect timeout?" | |||||
return | |||||
elif [ "$freqmatch" == 0 ]; then | |||||
log "Frequency is matching. No radar event fired" | |||||
else | |||||
log "Frequency doesnt match. Looks like DFS activity :(" | |||||
if reset_allowed $daytime_limit; then | |||||
log "Initiating reset" | |||||
reset_dfs $target $username $password | |||||
log "Waiting $cfg_reset_sleep seconds after reset" | |||||
sleep $cfg_reset_sleep | |||||
else | |||||
log "Resetting is forbidden at this daytime" | |||||
fi | |||||
fi | |||||
} | |||||
main() { | |||||
log "started!" | |||||
config_load airos-dfs-reset | |||||
config_get cfg_interval general interval 600 | |||||
config_get cfg_reset_sleep general reset_sleep 120 | |||||
while :; | |||||
do | |||||
config_foreach handle_device device | |||||
sleep $cfg_interval | |||||
done | |||||
} | |||||
main |
@ -0,0 +1,15 @@ | |||||
config airos-dfs-reset general | |||||
option interval '600' # Check every x seconds | |||||
option reset_sleep '120' # Sleep after reset to let routing protocols reconverge | |||||
config device 'sample_ap' # make sure to not use dashes in name | |||||
option target '192.168.1.20' | |||||
option username 'ubnt' | |||||
option password 'ubnt' | |||||
option daytime_limit '2-7' # .. from 2:xx to 7:xx reset is allowed | |||||
#config device 'sample_ap1' | |||||
# option target '10.31.81.21' | |||||
# option username 'ubnt' | |||||
# option password '...' | |||||
# option daytime_limit '0-23' |
@ -0,0 +1,18 @@ | |||||
#!/bin/sh /etc/rc.common | |||||
USE_PROCD=1 | |||||
START=95 | |||||
STOP=01 | |||||
start_service() { | |||||
procd_open_instance | |||||
procd_set_param command /usr/bin/airos-dfs-reset | |||||
procd_set_param stdout 0 | |||||
procd_set_param stderr 0 | |||||
procd_set_param user nobody | |||||
procd_close_instance | |||||
} | |||||
service_stopped() { | |||||
echo "airos-dfs-reset stopped!" | |||||
} |