roamguide: add package

This commit is contained in:
Daniel Ehlers 2018-05-12 17:11:13 +02:00
parent 6c38a5dd63
commit 0da60862c5
6 changed files with 211 additions and 0 deletions

33
net/roamguide/Makefile Normal file
View File

@ -0,0 +1,33 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=roamguide
PKG_VERSION:=0.0.4
PKG_RELEASE:=$(GLUON_BRANCH)
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
include $(TOPDIR)/../package/gluon.mk
define Package/roamguide
SECTION:=net
CATEGORY:=Network
DEPENDS:=+micrond
TITLE:=Helps your client to search for a better AP and have a nice roam experience.
endef
define Package/roamguide/description
Helps your client to search for a better AP and have a nice roam experience.
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
endef
define Build/Compile
endef
define Package/roamguide/install
$(CP) ./files/* $(1)
endef
$(eval $(call BuildPackage,roamguide))

47
net/roamguide/README Normal file
View File

@ -0,0 +1,47 @@
ROAM-Guide
----------
Helps your clients to search for a better AP and to have a nice roaming experience.
The roaming guide runs as a cronjob every minute on your ap and verifies that clients
have an acceptable TQ towards the AP. If that isn't the case it will deauth the client
by stating that the AP is full, enabling the client to look for an alternative AP.
This is happening in three definable stages depending on the TQ of the client.
When a client has decided to come back after the ban-time it will not be bothered
again unless it depletes to the next TQ level or it has been kicked $stage times.
For every stage the client is guided, the ban time will be increased. So by default
the first stage has a bantime of 500ms, the second 2775ms and the third 10000ms.
When a client is away for some definable time or is below the first stages TQ,
it will be forgotten, and the guiding will be re-enable.
Configuration
-------------
In '/etc/config/roamguide' the following default configuration is available,
to activate it you need to set enabled to '1'.
config roamguide
option device "client0" # wireless AP device we like to guide
list signal '-60' # first penality level, in dBm
list signal '-77' # second penality level, in dBm
list signal '-85' # final penality level. in dBm
option bantime_base '500' # on the first level ban for 500ms
option bantime_factor '2375' # on the second one for 2775ms,
# and in the final 10000ms
option forget_time '600' # Forget about a client after 10s
option enabled '0' # set to '1' to enable this profile
This module creates a cronjob calling /usr/bin/roamguide once a minute.
If you want to make roamguide more reactive (but also stress your device) you can add some more cron jobs with sleep timers in /usr/lib/micron.d/root:
* * * * * sleep 20 & /usr/bin/roamguide
* * * * * sleep 40 & /usr/bin/roamguide
### Testing tools
This will show you the stats, where you are connected to on your client:
watch -d -n0,5 iw dev $(ip -o -4 route show to default | awk '{print $5}') station dump

View File

@ -0,0 +1,11 @@
# repeat the following for every wireless AP device you like to guide.
config roamguide
option device "client0" # wireless AP device we like to guide
list signal '-60' # first penality level
list signal '-77' # second penality level
list signal '-85' # final penality level
option bantime_base '500' # on the first level ban for 500ms
option bantime_factor '2375' # on the second one for 2775ms,
# and in the final 10000ms
option forget_time '600' # Forget about a client after 10s
option enabled '1' # set to '0' to disable this profile

View File

@ -0,0 +1,106 @@
#!/bin/sh
. /lib/functions.
LOCK="/tmp/ide.lock"
try_lock(){
mkdir "$LOCK" || echo "Already running!"
trap "ir $LOCK" EXIT
}
wifi_kick(){
local dev="$1" ; shift
local mac="$1" ; shift
local bantime="$1" ; shift
ubus call hostapd.${dev} del_client '{ "addr" : "'${mac}'", "reason" : "assoc toomany", "ban_time" : '${bantime}' }'
}
count_file(){
echo "/tmp/roam-${1}-${2}"
}
count_get(){
local fn=$(count_file $@)
if [ -e "$fn" ] ; then
touch "$fn"
cat $fn
else
echo 0
fi
}
count_inc(){
expr $(count_get $@) + 1 > $(count_file $@)
}
count_dec(){
$(expr $(count_get $@) - 1) > $(count_file $@)
}
count_rm(){
local fn=$(count_file $@)
if [ -e $fn ] ; then
logger -s -t roamguide "forget" $@
rm $fn
fi
}
count_cleanup() {
local device="$1" ; shift
local current_time=$(date +%s)
for file in $(find /tmp -maxdepth 1 -name "roam-${device}-*" -type f ); do
[ "$(expr "$current_time" - $(date +%s -r $file))" -gt "$forget_time" ] && rm $file
done
}
client_macs() {
local dev="$1"
iw dev "${dev}" station dump | grep Station | sed -e 's/^[^ ]\+ \([0-9a-z:]*\) .*/\1/'
}
client_tq() {
local dev="$1"
local mac="$2"
iw dev "${dev}" station get "${mac}" | grep "signal avg" | xargs | cut -d' ' -f 3
}
roamguide() {
local s="$1"
config_get_bool enabled "$s" 'enabled' 0
[ $enabled -ne 0 ] || return 0
config_get device "$s" device
config_get forget_time "$s" forget_time 600
config_get bantime_base "$s" bantime_base 500
config_get bantime_factor "$s" bantime_factor 2375
for mac in $(client_macs "${device}") ; do
tq=$(client_tq "${device}" "${mac}")
level=1
config_list_foreach "$s" signal roamlevel "${tq}" "${device}" "${mac}"
done
count_cleanup ${device}
}
roamlevel(){
local roam_tq="$1" ; shift
local tq="$1" ; shift
local device="$1" ; shift
local mac="$1" ; shift
if [ ${tq} -le ${roam_tq} ]; then
mac_count=$(count_get "${device}" "${mac}")
if [ $mac_count -lt $level ] ; then
count_inc ${device} ${mac}
local bantime=$(expr $bantime_base + $(expr $mac_count \* $mac_count) \* $bantime_factor)
logger -s -t roamguide "${device}: ban ${mac} ${tq}dBm for ${bantime}ms"
wifi_kick "${device}" "${mac}" "${bantime}"
break # quits config_list_foreach
fi
fi
level=$(expr $level + 1)
}
try_lock
config_load 'roamguide'
config_foreach roamguide 'roamguide'

View File

@ -0,0 +1,13 @@
#!/bin/sh
LOCK="/tmp/roamguide-loop.lock"
try_lock(){
mkdir "$LOCK" || echo "Already running!"
trap "rmdir $LOCK" EXIT
}
/sbin/logread -f -e '\<hostapd\>.*\<associated\>' |\
while read line ; do
/usr/bin/roamguide
done

View File

@ -0,0 +1 @@
* * * * * /usr/bin/roamguide