mirror of https://github.com/aredn/aredn.git
aredn: add auto distance setting option
contributing author lua code: dman776 <dman776@gmail.com>
This commit is contained in:
parent
71325a91d2
commit
f134465edb
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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*#/;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 "</select> <a href=\"/help.html\#power\" target=\"_blank\"><img src=\"/qmark.png\"></a></td></tr>\n";
|
||||
|
||||
print "<tr id='dist' class='dist-norm'><td>Distance to<br />FARTHEST Neighbor</td>\n";
|
||||
print "<tr id='dist' class='dist-norm'><td>Distance to<br/>FARTHEST Neighbor<br/><h3>'0' is auto</h3></td>\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 "<td><input disabled size=6 type=text name='wifi_distance_disp_miles' value='$wifi_distance_disp_miles' title='Distance to the farthest neighbor'> miles<br />";
|
||||
print "<input disabled size=6 type=text size=4 name='wifi_distance_disp_km' value='$wifi_distance_disp_km' title='Distance to the farthest neighbor'> kilometers<br />";
|
||||
print "<input disabled size=6 type=text size=4 name='wifi_distance_disp_meters' value='$wifi_distance' title='Distance to the farthest neighbor'> meters<br />";
|
||||
print "<td><input disabled size=6 type=text name='wifi_distance_disp_miles' value='$wifi_distance_disp_miles' title='Distance to the farthest neighbor'> mi<br />";
|
||||
print "<input disabled size=6 type=text size=4 name='wifi_distance_disp_km' value='$wifi_distance_disp_km' title='Distance to the farthest neighbor'> km<br />";
|
||||
print "<input disabled size=6 type=text size=4 name='wifi_distance_disp_meters' value='$wifi_distance' title='Distance to the farthest neighbor'> m<br />";
|
||||
|
||||
print "<input id='distance_slider' type='range' min='0' max='150' step='1' value='$wifi_distance_disp_km' oninput='updDist(this.value)' onchange='updDist(this.value)' /><br />";
|
||||
print "<input type='hidden' size='6' name='wifi_distance' value='$wifi_distance' />";
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -371,17 +371,40 @@ The <strong>Distance</strong> 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.
|
||||
</p>
|
||||
<p>
|
||||
The maximum distance settings the ath9k wireless driver allows is dependent on
|
||||
the Channel Width:
|
||||
<br>
|
||||
<li>20MHz: 46666 meters<br></li>
|
||||
<li>10MHz: 103030 meters<br></li>
|
||||
<li>5MHz: 215757 meters<br></li>
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
The <strong>LAN</strong> 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 <b>LAN Mode</b> is described in the next section.
|
||||
|
|
|
@ -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: <cover.1554035972.git.lorenzo@kernel.org>
|
||||
+References: <cover.1554035972.git.lorenzo@kernel.org>
|
||||
+From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
+Date: Sun, 31 Mar 2019 14:38:49 +0200
|
||||
+Subject: [PATCH] ath: dynack: set max timeout according to clockrate
|
||||
+
|
||||
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
+---
|
||||
+ 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
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue