LQM fixes 2 (#365)

This commit is contained in:
Tim Wilkinson 2022-05-20 19:23:57 -07:00 committed by GitHub
parent a8b7f8a216
commit 1ceb7b2140
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 26 deletions

View File

@ -24,6 +24,7 @@ CONFIG_BUSYBOX_CONFIG_TELNETD=y
CONFIG_BUSYBOX_DEFAULT_MKSWAP=n CONFIG_BUSYBOX_DEFAULT_MKSWAP=n
CONFIG_BUSYBOX_CONFIG_MKSWAP=n CONFIG_BUSYBOX_CONFIG_MKSWAP=n
CONFIG_BUSYBOX_CONFIG_FEATURE_TOP_INTERACTIVE=y CONFIG_BUSYBOX_CONFIG_FEATURE_TOP_INTERACTIVE=y
CONFIG_BUSYBOX_CONFIG_ARPING=y
CONFIG_PACKAGE_dnsmasq=y CONFIG_PACKAGE_dnsmasq=y
CONFIG_PACKAGE_dropbear=y CONFIG_PACKAGE_dropbear=y
CONFIG_PACKAGE_iperf3=y CONFIG_PACKAGE_iperf3=y

View File

@ -63,6 +63,14 @@ function get_config()
} }
end end
function is_connected(track)
if track.lastseen >= now then
return true
else
return false
end
end
function should_block(track) function should_block(track)
if now > track.pending then if now > track.pending then
return track.blocks.dtd or track.blocks.signal or track.blocks.distance or track.blocks.user or track.blocks.dup or track.blocks.quality return track.blocks.dtd or track.blocks.signal or track.blocks.distance or track.blocks.user or track.blocks.dup or track.blocks.quality
@ -81,6 +89,14 @@ function only_quality_block(track)
) )
end end
function should_ping(track)
if track.ip and is_connected(track) and not (track.blocks.dtd or track.blocks.distance or track.blocks.user) then
return true
else
return false
end
end
function update_block(track) function update_block(track)
if should_block(track) then if should_block(track) then
if not track.blocked then if not track.blocked then
@ -217,7 +233,7 @@ function lqm()
quality = false quality = false
}, },
blocked = false, blocked = false,
snr = snr, snr = 0,
rev_snr = nil, rev_snr = nil,
avg_snr = 0, avg_snr = 0,
links = {}, links = {},
@ -244,7 +260,11 @@ function lqm()
end end
-- Running average SNR -- Running average SNR
if track.snr == 0 then
track.snr = snr
else
track.snr = math.ceil(snr_run_avg * track.snr + (1 - snr_run_avg) * snr) track.snr = math.ceil(snr_run_avg * track.snr + (1 - snr_run_avg) * snr)
end
-- Running average estimate of link quality -- Running average estimate of link quality
local tx = station.tx_packets local tx = station.tx_packets
@ -274,12 +294,6 @@ function lqm()
-- Update link tracking state -- Update link tracking state
for _, track in pairs(tracker) for _, track in pairs(tracker)
do do
-- Clear snr when we've not seen the node this time (disconnected)
if track.lastseen < now then
track.snr = 0
track.rev_snr = nil
end
-- Only refresh remote attributes periodically -- Only refresh remote attributes periodically
if track.ip and (now > track.refresh or track.pending > now) then if track.ip and (now > track.refresh or track.pending > now) then
track.refresh = now + refresh_timeout track.refresh = now + refresh_timeout
@ -354,9 +368,9 @@ function lqm()
end end
end end
if is_connected(track) then
-- Update avg snr using both ends (if we have them) -- Update avg snr using both ends (if we have them)
track.avg_snr = (track.snr + (track.rev_snr or track.snr)) / 2 track.avg_snr = (track.snr + (track.rev_snr or track.snr)) / 2
-- Routable -- Routable
local rt = track.ip and ip.route(track.ip) or nil local rt = track.ip and ip.route(track.ip) or nil
if rt and tostring(rt.gw) == track.ip then if rt and tostring(rt.gw) == track.ip then
@ -364,21 +378,21 @@ function lqm()
else else
track.routable = false track.routable = false
end end
else
-- Clear snr when we've not seen the node this time (disconnected)
track.snr = 0
track.rev_snr = nil
track.routable = false
end
-- Ping addresses and penalize quality for excessively slow links -- Ping addresses and penalize quality for excessively slow links
if track.ip and not track.blocked then if should_ping(track) then
local sigsock = nixio.socket("inet", "dgram") -- Make an arp request to the target ip to see if we get a timely reply. By using ARP we avoid any
sigsock:setopt("socket", "bindtodevice", wlan) -- potential routing issues and avoid any firewall blocks on the other end.
sigsock:setopt("socket", "dontroute", 1) -- Take a penalty if we fail
sigsock:setopt("socket", "rcvtimeo", ping_timeout) if os.execute("/usr/sbin/arping -f -w " .. ping_timeout .. " -I " .. wlan .. " " .. track.ip .. " >/dev/null") ~= 0 then
sigsock:connect(track.ip, 8080)
sigsock:send("")
-- There's no actual UDP server at the other end so recv will either timeout and return 'false' if the link is slow,
-- or will error and return 'nil' if there is a node and it send back an ICMP error quickly (which for our purposes is a positive)
if sigsock:recv(0) == false then
track.tx_quality = math.max(0, math.ceil(track.tx_quality - config.ping_penalty)) track.tx_quality = math.max(0, math.ceil(track.tx_quality - config.ping_penalty))
end end
sigsock:close()
end end
-- Inject traffic into links with poor quality -- Inject traffic into links with poor quality