From f134465edb7256945629af0360b311031a9b127f Mon Sep 17 00:00:00 2001 From: Joe Ayers Date: Mon, 1 Apr 2019 20:48:41 -0700 Subject: [PATCH] aredn: add auto distance setting option contributing author lua code: dman776 --- configs/common.config | 2 + files/usr/lib/lua/aredn/uci.lua | 4 +- files/usr/lib/lua/aredn/utils.lua | 44 ++++++- files/usr/local/bin/bbhn-postupgrade | 5 - files/usr/local/bin/snrlog | 15 ++- files/www/cgi-bin/setup | 27 ++-- files/www/cgi-bin/supporttool | 3 + files/www/help.html | 27 +++- patches/712-auto-distance-settings.patch | 156 +++++++++++++++++++++++ patches/series | 1 + 10 files changed, 261 insertions(+), 23 deletions(-) create mode 100644 patches/712-auto-distance-settings.patch diff --git a/configs/common.config b/configs/common.config index 22f67e3f..f7cfe8ab 100644 --- a/configs/common.config +++ b/configs/common.config @@ -105,3 +105,5 @@ CONFIG_PACKAGE_kmod-ipip=y CONFIG_IMAGEOPT=y CONFIG_VERSIONOPT=y CONFIG_VERSION_DIST="AREDN" +CONFIG_PACKAGE_ATH_DYNACK=y +CONFIG_PACKAGE_ATH_DEBUG=y diff --git a/files/usr/lib/lua/aredn/uci.lua b/files/usr/lib/lua/aredn/uci.lua index ee5ab7d3..bf890a74 100755 --- a/files/usr/lib/lua/aredn/uci.lua +++ b/files/usr/lib/lua/aredn/uci.lua @@ -2,7 +2,7 @@ --[[ Part of AREDN -- Used for creating Amateur Radio Emergency Data Networks - Copyright (C) 2016 Darryl Quinn + Copyright (C) 2019 Darryl Quinn See Contributors file for additional contributors This program is free software: you can redistribute it and/or modify @@ -41,7 +41,7 @@ local api = {} function api.getUciConfType(conf,type) local curs=uci.cursor() local ifce={} - curs:foreach(conf,type,function(s) ifce[s[".index"]]=s end) + curs:foreach(conf,type,function(s) table.insert(ifce,s) end) return ifce end diff --git a/files/usr/lib/lua/aredn/utils.lua b/files/usr/lib/lua/aredn/utils.lua index 4111ed80..e9ee9f64 100755 --- a/files/usr/lib/lua/aredn/utils.lua +++ b/files/usr/lib/lua/aredn/utils.lua @@ -2,7 +2,7 @@ --[[ Part of AREDN -- Used for creating Amateur Radio Emergency Data Networks - Copyright (C) 2016 Darryl Quinn + Copyright (C) 2019 Darryl Quinn See Contributors file for additional contributors This program is free software: you can redistribute it and/or modify @@ -38,6 +38,7 @@ local nxo = require("nixio") local ipc = require("luci.ip") local posix = require("posix.unistd") +local auci = require("aredn.uci") require("uci") function round2(num, idp) @@ -108,6 +109,47 @@ function get_ip_type(ip) return R.STRING end +------------------------------------- +-- Returns name of the radio (radio0 or radio1) for the selected wifi interface (wifi or lan) +------------------------------------- +function get_radio(ifn) + local interfaces=auci.getUciConfType("wireless", "wifi-iface") + for n, i in ipairs(interfaces) do + if i.network==ifn then + return i.device + end + end +end + +------------------------------------- +-- Returns PHY name of the radio (phy0 or phy1) for the selected wifi interface (wifi or lan) +------------------------------------- +function get_radiophy(ifn) + local rname=get_radio(ifn) + return string.format("phy%d",string.sub(rname,-1)) +end + +------------------------------------- +-- Reset the auto-distance calculation for the radio +------------------------------------- +function reset_auto_distance() + local rc=0 + local radio = get_radio("wifi") -- get radio number from /etc/config/wireless and convert to -> phy0 or phy1 + local u=uci.cursor() + local distance=u:get("wireless",radio,"distance") + print("DISTANCE=" .. distance) + if distance=="0" then + local phyname = get_radiophy("wifi") -- get radio number from /etc/config/wireless and convert to -> phy0 or phy1 + print("iw phy " .. phyname .. " set distance 60000") + print("iw phy " .. phyname .. " set distance auto") + os.execute("iw phy " .. phyname .. " set distance 60000") + rc=os.execute("iw phy " .. phyname .. " set distance auto") + else + rc=-1 + end + return rc +end + function get_ifname(ifn) local u=uci.cursor() iface=u:get("network",ifn,"ifname") diff --git a/files/usr/local/bin/bbhn-postupgrade b/files/usr/local/bin/bbhn-postupgrade index a085679a..debc038d 100755 --- a/files/usr/local/bin/bbhn-postupgrade +++ b/files/usr/local/bin/bbhn-postupgrade @@ -36,11 +36,6 @@ foreach $line (`cat /etc/config.mesh/_setup`) $cfg{$1} = $2; } -# if distance is 0, set to 60km to ensure a tower node can be communicated with -# The 3.19.3.0 release does not have auto distance, but previous nightly builds did -# remove this statement when auto distance is put back in -$cfg{wifi_distance} = 60000 if $cfg{wifi_distance} eq '0'; - foreach $line (`cat /etc/config.mesh/_setup.default`) { next if $line =~ /^\s*#/; diff --git a/files/usr/local/bin/snrlog b/files/usr/local/bin/snrlog index 31317904..7739122e 100755 --- a/files/usr/local/bin/snrlog +++ b/files/usr/local/bin/snrlog @@ -2,7 +2,7 @@ --[[ Part of AREDN -- Used for creating Amateur Radio Emergency Data Networks - Copyright (C) 2016 Darryl Quinn + Copyright (C) 2019 Darryl Quinn See Contributors file for additional contributors This program is free software: you can redistribute it and/or modify @@ -54,6 +54,7 @@ local AGETIME=43200 local INACTIVETIMEOUT=10000 local tmpdir="/tmp/snrlog" local lastdat="/tmp/snr.dat" +local autolog="/tmp/AutoDistReset.log" local lasttime={} local lines={} local arpcache={} @@ -91,6 +92,18 @@ function Neighbor.create(macaddress) n.rx_mcs=n:findRxMcs() n.rx_rate=n:findRxRate() n.lastseen=n:findLastTime() + -- check if auto-distance reset is required (new node) + local efn=n:getExistingDataFileName() + if efn==nil or ((now-n.lastseen) > 100) then -- NEW or not recently seen node + reset_auto_distance() + f, err=assert(io.open(autolog, "a"),"Cannot open file (autolog) to write!") + if (f) then + f:write(now .. "\n") + f:close() + end + file_trim(autolog,MAXLINES) + end + n.datafile=n:generateDataFileName() return n end diff --git a/files/www/cgi-bin/setup b/files/www/cgi-bin/setup index e3a9d858..0a870151 100755 --- a/files/www/cgi-bin/setup +++ b/files/www/cgi-bin/setup @@ -189,12 +189,19 @@ $parms{wifi_txpower} = $wifi_txpower; if(($parms{button_apply} or $parms{button_save}) and $wifi_enable ) { - if($wifi_distance < 1 or $wifi_distance =~ /\D/) + if($wifi_distance < 0 or $wifi_distance =~ /\D/) { push (@errors, "invalid distance value"); } else { $cmd = ""; - $cmd .= "iw phy ${phy} set distance $wifi_distance >/dev/null 2>&1;"; + if ( $wifi_distance eq "0" ) + { + $cmd .= "iw phy ${phy} set distance auto >/dev/null 2>&1;"; + } + else + { + $cmd .= "iw phy ${phy} set distance $wifi_distance >/dev/null 2>&1;"; + } $cmd .= "iw dev $wifiintf set txpower fixed ${wifi_txpower}00 >/dev/null 2>&1;"; system $cmd; } @@ -555,12 +562,8 @@ function updDist(x) { document.getElementsByName('wifi_distance_disp_meters')[0].value = xc; dist_meters.value = xc; - // if default, then ALERT! - if(dist_meters.value==0) { - distBox.className = 'dist-alert'; - } else { - distBox.className = 'dist-norm'; - } + // default of 0 means 'auto', so full range is always dist-norm + distBox.className = 'dist-norm'; } @@ -757,15 +760,15 @@ if ( ${wifi_enable} ) for($i = wifi_maxpower($wifi_channel); $i >= 1; --$i) { selopt($i+$txpoweroffset ." dBm", $i, $wifi_txpower) } print "  \n"; - print "Distance to
FARTHEST Neighbor\n"; + print "Distance to
FARTHEST Neighbor

'0' is auto

\n"; $wifi_distance=int($wifi_distance); # in meters $wifi_distance_disp_km=int($wifi_distance/1000); $wifi_distance_disp_miles=sprintf("%.2f",$wifi_distance_disp_km*.621371192); - print " miles
"; - print " kilometers
"; - print " meters
"; + print " mi
"; + print " km
"; + print " m
"; print "
"; print ""; diff --git a/files/www/cgi-bin/supporttool b/files/www/cgi-bin/supporttool index 82360761..b0e26974 100755 --- a/files/www/cgi-bin/supporttool +++ b/files/www/cgi-bin/supporttool @@ -54,6 +54,9 @@ $phy=get_wlan2phy("${wifiif}"); "/tmp/rssi.log", "/tmp/zombie.log", "/tmp/olsrd.log", + "/tmp/AutoDistReset.log", + "/sys/kernel/debug/ieee80211/phy0/ath9k/ack_to", + "/sys/kernel/debug/ieee80211/phy1/ath9k/ack_to" ); @sensitive = ( "/etc/config/vtun", diff --git a/files/www/help.html b/files/www/help.html index ff9579c0..6450c95c 100644 --- a/files/www/help.html +++ b/files/www/help.html @@ -371,17 +371,40 @@ The Distance setting adjusts the RF retry timer to define how long the transmitter will wait for an acknowledgement from a Neighbor station. If the distance parameter is too short, then the transmitter will send duplicate data packets before the acknowledgement -has had time to return. This value is only applicable to nodes that can +has had time to return. If the distance parameter is too long, then the +transmitter will wait extra time before considering the data lost to re-transmit. +This value is only applicable to nodes that can be communicated with directly over RF and not multiple hop nodes on the greater mesh network. The value should be set to the distance in meters to the farthest direct RF node you expect to communicate with. Change the distance value by moving the slider. Distance values will be in multiples -of 1000 meters (approximately 0.62 miles). A value of zero is not allowed. +of 1000 meters (approximately 0.62 miles). A value of '0' will cause +the radio to auto determine the RF retry timer based on measuring the +actual time it takes acknowledgement packets to be received back. The +automatic timer is tracked using a Exponential Weighted Moving Average (EWMA) method. +'auto' is the default setting and in most all situations the optimal setting. The best way to test an optimal distance settings is to do an 'iperf' test directly between 2 nodes to measure the performance of this RF channel. Try different distance settings to peak out the iperf throughput.

+The maximum distance settings the ath9k wireless driver allows is dependent on +the Channel Width: +
+

  • 20MHz: 46666 meters
  • +
  • 10MHz: 103030 meters
  • +
  • 5MHz: 215757 meters
  • +

    +

    +The auto distance setting is best used on quality point to point links. +50% performance increases have been observed over static. Auto distance +settings does not work well with many nodes and marginal links. In this +senario, the round trip packet timing has a very wide range of time values. +Consequently the timeout value becomes inflated and inconsistent. Static settings +should be used in this situation. It is best to measure the link with iperf to +compare thoughput and determine the best distance setting. +

    +

    The LAN box allows you to set the LAN IP Address of the node and the address range of the DHCP server, and these should be self explanatory. The LAN Mode is described in the next section. diff --git a/patches/712-auto-distance-settings.patch b/patches/712-auto-distance-settings.patch new file mode 100644 index 00000000..1cb51184 --- /dev/null +++ b/patches/712-auto-distance-settings.patch @@ -0,0 +1,156 @@ +Index: openwrt/package/kernel/mac80211/patches/569-ath9k-dynack-set-max-timeout.patch +=================================================================== +--- /dev/null ++++ openwrt/package/kernel/mac80211/patches/569-ath9k-dynack-set-max-timeout.patch +@@ -0,0 +1,36 @@ ++--- a/drivers/net/wireless/ath/ath9k/dynack.c +++++ b/drivers/net/wireless/ath/ath9k/dynack.c ++@@ -103,9 +103,10 @@ ++ struct ath_dynack *da = &ah->dynack; ++ struct ath_node *an; ++ int to = 0; +++ u32 max_to = ath_dynack_get_max_to(ah); ++ ++ list_for_each_entry(an, &da->nodes, list) ++- if (an->ackto > to) +++ if (an->ackto > to && an->ackto < max_to) ++ to = an->ackto; ++ ++ if (to && da->ackto != to) { ++@@ -308,8 +309,8 @@ ++ */ ++ void ath_dynack_node_init(struct ath_hw *ah, struct ath_node *an) ++ { ++- /* ackto = slottime + sifs + air delay */ ++- u32 ackto = 9 + 16 + 64; +++ /* AREDN set ackto to max_to initialize */ +++ u32 ackto = ath_dynack_get_max_to(ah); ++ struct ath_dynack *da = &ah->dynack; ++ ++ an->ackto = ackto; ++@@ -343,8 +344,8 @@ ++ */ ++ void ath_dynack_reset(struct ath_hw *ah) ++ { ++- /* ackto = slottime + sifs + air delay */ ++- u32 ackto = 9 + 16 + 64; +++ /* AREDN set ackto to max_to initialize */ +++ u32 ackto = ath_dynack_get_max_to(ah); ++ struct ath_dynack *da = &ah->dynack; ++ ++ da->lto = jiffies; +Index: openwrt/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +=================================================================== +--- openwrt.orig/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh ++++ openwrt/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +@@ -788,7 +788,11 @@ drv_mac80211_setup() { + + iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1 + iw phy "$phy" set antenna_gain $antenna_gain +- iw phy "$phy" set distance "$distance" ++ if [ $distance -eq 0 -a -d /sys/kernel/debug/ieee80211/$phy/ath9k ]; then ++ iw phy "$phy" set distance auto ++ else ++ iw phy "$phy" set distance "$distance" ++ fi + + [ -n "$frag" ] && iw phy "$phy" set frag "${frag%%.*}" + [ -n "$rts" ] && iw phy "$phy" set rts "${rts%%.*}" +Index: openwrt/package/kernel/mac80211/patches/568-ath-dynack-set-max-timeout-according-to-clockrate.patch +=================================================================== +--- /dev/null ++++ openwrt/package/kernel/mac80211/patches/568-ath-dynack-set-max-timeout-according-to-clockrate.patch +@@ -0,0 +1,93 @@ ++From 72f4ba6f6b6021fcc48d07d03407c2fdb16a46c5 Mon Sep 17 00:00:00 2001 ++Message-Id: <72f4ba6f6b6021fcc48d07d03407c2fdb16a46c5.1554035972.git.lorenzo@kernel.org> ++In-Reply-To: ++References: ++From: Lorenzo Bianconi ++Date: Sun, 31 Mar 2019 14:38:49 +0200 ++Subject: [PATCH] ath: dynack: set max timeout according to clockrate ++ ++Signed-off-by: Lorenzo Bianconi ++--- ++ drivers/net/wireless/ath/ath9k/dynack.c | 36 ++++++++++++++++++------- ++ 1 file changed, 26 insertions(+), 10 deletions(-) ++ ++diff --git a/drivers/net/wireless/ath/ath9k/dynack.c b/drivers/net/wireless/ath/ath9k/dynack.c ++index f112fa5b2eac..0627111249dd 100644 ++--- a/drivers/net/wireless/ath/ath9k/dynack.c +++++ b/drivers/net/wireless/ath/ath9k/dynack.c ++@@ -20,11 +20,24 @@ ++ ++ #define COMPUTE_TO (5 * HZ) ++ #define LATEACK_DELAY (10 * HZ) ++-#define LATEACK_TO 256 ++-#define MAX_DELAY 300 ++ #define EWMA_LEVEL 96 ++ #define EWMA_DIV 128 ++ +++/** +++ * ath_dynack_get_max_to - set max timeout according to clockrate +++ * @ah: ath hw +++ * +++ */ +++static u32 ath_dynack_get_max_to(struct ath_hw *ah) +++{ +++ struct ath_common *common = ath9k_hw_common(ah); +++ +++ if (common->clockrate) +++ return AR_TIME_OUT_ACK / common->clockrate; +++ +++ return 300; +++} +++ ++ /** ++ * ath_dynack_ewma - EWMA (Exponentially Weighted Moving Average) calculation ++ * ++@@ -116,15 +129,16 @@ static void ath_dynack_compute_ackto(struct ath_hw *ah) ++ */ ++ static void ath_dynack_compute_to(struct ath_hw *ah) ++ { ++- u32 ackto, ack_ts; ++- u8 *dst, *src; +++ struct ath_dynack *da = &ah->dynack; +++ u32 ackto, ack_ts, max_to; ++ struct ieee80211_sta *sta; ++- struct ath_node *an; ++ struct ts_info *st_ts; ++- struct ath_dynack *da = &ah->dynack; +++ struct ath_node *an; +++ u8 *dst, *src; ++ ++ rcu_read_lock(); ++ +++ max_to = ath_dynack_get_max_to(ah); ++ while (da->st_rbf.h_rb != da->st_rbf.t_rb && ++ da->ack_rbf.h_rb != da->ack_rbf.t_rb) { ++ ack_ts = da->ack_rbf.tstamp[da->ack_rbf.h_rb]; ++@@ -140,7 +154,7 @@ static void ath_dynack_compute_to(struct ath_hw *ah) ++ if (ack_ts > st_ts->tstamp + st_ts->dur) { ++ ackto = ack_ts - st_ts->tstamp - st_ts->dur; ++ ++- if (ackto < MAX_DELAY) { +++ if (ackto < max_to) { ++ sta = ieee80211_find_sta_by_ifaddr(ah->hw, dst, ++ src); ++ if (sta) { ++@@ -197,11 +211,13 @@ void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb, ++ if (ieee80211_is_assoc_req(hdr->frame_control) || ++ ieee80211_is_assoc_resp(hdr->frame_control) || ++ ieee80211_is_auth(hdr->frame_control)) { +++ u32 max_to = ath_dynack_get_max_to(ah); +++ ++ ath_dbg(common, DYNACK, "late ack\n"); ++ ++- ath9k_hw_setslottime(ah, (LATEACK_TO - 3) / 2); ++- ath9k_hw_set_ack_timeout(ah, LATEACK_TO); ++- ath9k_hw_set_cts_timeout(ah, LATEACK_TO); +++ ath9k_hw_setslottime(ah, (max_to - 3) / 2); +++ ath9k_hw_set_ack_timeout(ah, max_to); +++ ath9k_hw_set_cts_timeout(ah, max_to); ++ if (sta) { ++ struct ath_node *an; ++ ++-- ++2.20.1 diff --git a/patches/series b/patches/series index 7e13bfaf..afef1101 100644 --- a/patches/series +++ b/patches/series @@ -23,4 +23,5 @@ 709-iperf-fw-restart.patch 710-no-ping6-traceroute6.patch 711-nano-xw-switch-config.patch +712-auto-distance-settings.patch 713-delay-snmpd-startup.patch