mirror of https://github.com/aredn/aredn.git
Gather statistics about RF links (#684)
This commit is contained in:
parent
fdb9270617
commit
33684d22d2
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
local ip = require("luci.ip")
|
local ip = require("luci.ip")
|
||||||
local info = require("aredn.info")
|
local info = require("aredn.info")
|
||||||
|
local socket = require("socket")
|
||||||
|
|
||||||
local refresh_timeout = 15 * 60 -- refresh high cost data every 15 minutes
|
local refresh_timeout = 15 * 60 -- refresh high cost data every 15 minutes
|
||||||
local pending_timeout = 5 * 60 -- pending node wait 5 minutes before they are included
|
local pending_timeout = 5 * 60 -- pending node wait 5 minutes before they are included
|
||||||
|
@ -43,6 +44,8 @@ local quality_min_packets = 100 -- minimum number of tx packets before we can sa
|
||||||
local quality_injection_max = 10 -- number of packets to inject into poor links to update quality
|
local quality_injection_max = 10 -- number of packets to inject into poor links to update quality
|
||||||
local tx_quality_run_avg = 0.8 -- tx quality running average
|
local tx_quality_run_avg = 0.8 -- tx quality running average
|
||||||
local ping_timeout = 1.0 -- timeout before ping gives a qualtiy penalty
|
local ping_timeout = 1.0 -- timeout before ping gives a qualtiy penalty
|
||||||
|
local ping_time_run_avg = 0.8 -- ping time runnng average
|
||||||
|
local bitrate_run_avg = 0.8 -- rx/tx running average
|
||||||
local dtd_distance = 50 -- distance (meters) after which nodes connected with DtD links are considered different sites
|
local dtd_distance = 50 -- distance (meters) after which nodes connected with DtD links are considered different sites
|
||||||
local connect_timeout = 5 -- timeout (seconds) when fetching information from other nodes
|
local connect_timeout = 5 -- timeout (seconds) when fetching information from other nodes
|
||||||
local speed_time = 10 --
|
local speed_time = 10 --
|
||||||
|
@ -280,7 +283,9 @@ function lqm()
|
||||||
["signal avg:"] = "signal",
|
["signal avg:"] = "signal",
|
||||||
["tx packets:"] = "tx_packets",
|
["tx packets:"] = "tx_packets",
|
||||||
["tx retries:"] = "tx_retries",
|
["tx retries:"] = "tx_retries",
|
||||||
["tx failed:"] = "tx_fail"
|
["tx failed:"] = "tx_fail",
|
||||||
|
["tx bitrate:"] = "tx_bitrate",
|
||||||
|
["rx bitrate:"] = "rx_bitrate"
|
||||||
}
|
}
|
||||||
local station = {}
|
local station = {}
|
||||||
local cnoise = iwinfo.nl80211.noise(wlan)
|
local cnoise = iwinfo.nl80211.noise(wlan)
|
||||||
|
@ -297,7 +302,9 @@ function lqm()
|
||||||
mac = mac:upper(),
|
mac = mac:upper(),
|
||||||
signal = 0,
|
signal = 0,
|
||||||
noise = noise,
|
noise = noise,
|
||||||
ip = nil
|
ip = nil,
|
||||||
|
tx_bitrate = 0,
|
||||||
|
rx_bitrate = 0
|
||||||
}
|
}
|
||||||
local entry = arps[station.mac]
|
local entry = arps[station.mac]
|
||||||
if entry then
|
if entry then
|
||||||
|
@ -330,7 +337,9 @@ function lqm()
|
||||||
mac = nil,
|
mac = nil,
|
||||||
tx_packets = 0,
|
tx_packets = 0,
|
||||||
tx_fail = 0,
|
tx_fail = 0,
|
||||||
tx_retries = 0
|
tx_retries = 0,
|
||||||
|
tx_bitrate = 0,
|
||||||
|
rx_bitrate = 0
|
||||||
}
|
}
|
||||||
stations[#stations + 1] = tunnel
|
stations[#stations + 1] = tunnel
|
||||||
else
|
else
|
||||||
|
@ -361,7 +370,9 @@ function lqm()
|
||||||
mac = mac:upper(),
|
mac = mac:upper(),
|
||||||
tx_packets = 0,
|
tx_packets = 0,
|
||||||
tx_fail = 0,
|
tx_fail = 0,
|
||||||
tx_retries = 0
|
tx_retries = 0,
|
||||||
|
tx_bitrate = 0,
|
||||||
|
rx_bitrate = 0
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -388,7 +399,9 @@ function lqm()
|
||||||
mac = foundmac,
|
mac = foundmac,
|
||||||
tx_packets = 0,
|
tx_packets = 0,
|
||||||
tx_fail = 0,
|
tx_fail = 0,
|
||||||
tx_retries = 0
|
tx_retries = 0,
|
||||||
|
tx_bitrate = 0,
|
||||||
|
rx_bitrate = 0
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -429,6 +442,9 @@ function lqm()
|
||||||
last_tx_total = nil,
|
last_tx_total = nil,
|
||||||
tx_quality = 100,
|
tx_quality = 100,
|
||||||
ping_quality = 100,
|
ping_quality = 100,
|
||||||
|
ping_success_time = 0,
|
||||||
|
tx_bitrate = nil,
|
||||||
|
rx_bitrate = nil,
|
||||||
quality = 100,
|
quality = 100,
|
||||||
exposed = false
|
exposed = false
|
||||||
}
|
}
|
||||||
|
@ -471,6 +487,16 @@ function lqm()
|
||||||
track.last_quality = tx_quality
|
track.last_quality = tx_quality
|
||||||
track.tx_quality = math.min(100, math.max(0, math.ceil(tx_quality_run_avg * track.tx_quality + (1 - tx_quality_run_avg) * tx_quality)))
|
track.tx_quality = math.min(100, math.max(0, math.ceil(tx_quality_run_avg * track.tx_quality + (1 - tx_quality_run_avg) * tx_quality)))
|
||||||
end
|
end
|
||||||
|
if not track.tx_bitrate then
|
||||||
|
track.tx_bitrate = station.tx_bitrate
|
||||||
|
else
|
||||||
|
track.tx_bitrate = track.tx_bitrate * bitrate_run_avg + station.tx_bitrate * (1 - bitrate_run_avg)
|
||||||
|
end
|
||||||
|
if not track.rx_bitrate then
|
||||||
|
track.rx_bitrate = station.rx_bitrate
|
||||||
|
else
|
||||||
|
track.rx_bitrate = track.rx_bitrate * bitrate_run_avg + station.rx_bitrate * (1 - bitrate_run_avg)
|
||||||
|
end
|
||||||
|
|
||||||
track.lastseen = now
|
track.lastseen = now
|
||||||
end
|
end
|
||||||
|
@ -609,29 +635,37 @@ function lqm()
|
||||||
track.ping_quality = 100
|
track.ping_quality = 100
|
||||||
elseif should_ping(track) then
|
elseif should_ping(track) then
|
||||||
local success = 100
|
local success = 100
|
||||||
|
local ptime = ping_timeout
|
||||||
if track.type == "Tunnel" then
|
if track.type == "Tunnel" then
|
||||||
-- Tunnels have no MAC, so we can only use IP level pings.
|
-- Tunnels have no MAC, so we can only use IP level pings.
|
||||||
local sigsock = nixio.socket("inet", "dgram")
|
local sigsock = nixio.socket("inet", "dgram")
|
||||||
sigsock:setopt("socket", "rcvtimeo", ping_timeout)
|
sigsock:setopt("socket", "rcvtimeo", ping_timeout)
|
||||||
-- Must connect or we wont see the error
|
-- Must connect or we wont see the error
|
||||||
sigsock:connect(track.ip, 8080)
|
sigsock:connect(track.ip, 8080)
|
||||||
|
local pstart = socket.gettime(0)
|
||||||
sigsock:send("")
|
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,
|
-- 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)
|
-- 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
|
if sigsock:recv(0) == false then
|
||||||
success = 0
|
success = 0
|
||||||
end
|
end
|
||||||
|
ptime = socket.gettime(0) - pstart
|
||||||
sigsock:close()
|
sigsock:close()
|
||||||
else
|
else
|
||||||
-- Make an arp request to the target ip to see if we get a timely reply. By using ARP we avoid any
|
-- Make an arp request to the target ip to see if we get a timely reply. By using ARP we avoid any
|
||||||
-- potential routing issues and avoid any firewall blocks on the other end.
|
-- potential routing issues and avoid any firewall blocks on the other end.
|
||||||
-- As the request is broadcast, we avoid any potential distance/scope timing issues as we dont wait for the
|
-- As the request is broadcast, we avoid any potential distance/scope timing issues as we dont wait for the
|
||||||
-- packet to be acked. The reply will be unicast to us, and our ack to that is unimportant to the latency test.
|
-- packet to be acked. The reply will be unicast to us, and our ack to that is unimportant to the latency test.
|
||||||
|
local pstart = socket.gettime(0)
|
||||||
if os.execute(ARPING .. " -f -w " .. ping_timeout .. " -I " .. track.device .. " " .. track.ip .. " >/dev/null") ~= 0 then
|
if os.execute(ARPING .. " -f -w " .. ping_timeout .. " -I " .. track.device .. " " .. track.ip .. " >/dev/null") ~= 0 then
|
||||||
success = 0
|
success = 0
|
||||||
end
|
end
|
||||||
|
ptime = socket.gettime(0) - pstart
|
||||||
end
|
end
|
||||||
local ping_loss_run_avg = 1 - config.ping_penalty / 100
|
local ping_loss_run_avg = 1 - config.ping_penalty / 100
|
||||||
|
if success > 0 then
|
||||||
|
track.ping_success_time = track.ping_success_time * ping_time_run_avg + ptime * (1 - ping_time_run_avg)
|
||||||
|
end
|
||||||
track.ping_quality = math.ceil(ping_loss_run_avg * track.ping_quality + (1 - ping_loss_run_avg) * success)
|
track.ping_quality = math.ceil(ping_loss_run_avg * track.ping_quality + (1 - ping_loss_run_avg) * success)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue