From 0da60862c5a9abac6f104358fc5d084bc30d51be Mon Sep 17 00:00:00 2001 From: Daniel Ehlers Date: Sat, 12 May 2018 17:11:13 +0200 Subject: [PATCH] roamguide: add package --- net/roamguide/Makefile | 33 ++++++ net/roamguide/README | 47 ++++++++ net/roamguide/files/etc/config/roamguide | 11 ++ net/roamguide/files/usr/bin/roamguide | 106 ++++++++++++++++++ net/roamguide/files/usr/bin/roamguide-loop | 13 +++ .../files/usr/lib/micron.d/roamguide | 1 + 6 files changed, 211 insertions(+) create mode 100644 net/roamguide/Makefile create mode 100644 net/roamguide/README create mode 100644 net/roamguide/files/etc/config/roamguide create mode 100755 net/roamguide/files/usr/bin/roamguide create mode 100755 net/roamguide/files/usr/bin/roamguide-loop create mode 100644 net/roamguide/files/usr/lib/micron.d/roamguide diff --git a/net/roamguide/Makefile b/net/roamguide/Makefile new file mode 100644 index 0000000..35acd9e --- /dev/null +++ b/net/roamguide/Makefile @@ -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)) diff --git a/net/roamguide/README b/net/roamguide/README new file mode 100644 index 0000000..e2bc478 --- /dev/null +++ b/net/roamguide/README @@ -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 + diff --git a/net/roamguide/files/etc/config/roamguide b/net/roamguide/files/etc/config/roamguide new file mode 100644 index 0000000..c5503eb --- /dev/null +++ b/net/roamguide/files/etc/config/roamguide @@ -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 diff --git a/net/roamguide/files/usr/bin/roamguide b/net/roamguide/files/usr/bin/roamguide new file mode 100755 index 0000000..4357522 --- /dev/null +++ b/net/roamguide/files/usr/bin/roamguide @@ -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' diff --git a/net/roamguide/files/usr/bin/roamguide-loop b/net/roamguide/files/usr/bin/roamguide-loop new file mode 100755 index 0000000..cb8134b --- /dev/null +++ b/net/roamguide/files/usr/bin/roamguide-loop @@ -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 '\.*\' |\ + while read line ; do + /usr/bin/roamguide + done diff --git a/net/roamguide/files/usr/lib/micron.d/roamguide b/net/roamguide/files/usr/lib/micron.d/roamguide new file mode 100644 index 0000000..ea503cf --- /dev/null +++ b/net/roamguide/files/usr/lib/micron.d/roamguide @@ -0,0 +1 @@ +* * * * * /usr/bin/roamguide \ No newline at end of file