mirror of https://github.com/aredn/aredn.git
Avoid cutting off leaf nodes (#1211)
* Avoid cutting off leaf nodes * Use OLSR broadcast with pending nodes
This commit is contained in:
parent
2509ebdf3b
commit
fbaa54bb23
|
@ -52,6 +52,7 @@ local speed_time = 10 --
|
|||
local speed_limit = 1000 -- close connection if it's too slow (< 1kB/s for 10 seconds)
|
||||
local default_short_retries = 20 -- More link-level retries helps overall tcp performance (factory default is 7)
|
||||
local default_long_retries = 20 -- (factory default is 4)
|
||||
local default_min_routes = 8 -- Minimum number of routes (nodes x2 usually) on a link which *must* be left active. Avoids cutting off poorly behaving leaf nodes.
|
||||
|
||||
local NFT = "/usr/sbin/nft"
|
||||
local IW = "/usr/sbin/iw"
|
||||
|
@ -62,6 +63,9 @@ local IPCMD = "/sbin/ip"
|
|||
local now = 0
|
||||
local config = {}
|
||||
|
||||
local total_node_route_count = 0
|
||||
local minroutes_count = 0
|
||||
|
||||
function update_config()
|
||||
local c = uci.cursor() -- each time as /etc/config/aredn may have changed
|
||||
config = {
|
||||
|
@ -75,6 +79,7 @@ function update_config()
|
|||
min_quality = tonumber(c:get("aredn", "@lqm[0]", "min_quality")),
|
||||
margin_quality = tonumber(c:get("aredn", "@lqm[0]", "margin_quality")),
|
||||
ping_penalty = tonumber(c:get("aredn", "@lqm[0]", "ping_penalty")),
|
||||
min_routes = tonumber(c:get("aredn", "@lqm[0]", "min_routes") or default_min_routes),
|
||||
user_blocks = c:get("aredn", "@lqm[0]", "user_blocks") or "",
|
||||
user_allows = c:get("aredn", "@lqm[0]", "user_allows") or ""
|
||||
}
|
||||
|
@ -112,6 +117,8 @@ function should_block(track)
|
|||
return track.blocks.user
|
||||
elseif is_pending(track) then
|
||||
return track.blocks.dtd or track.blocks.user
|
||||
elseif track.minroutes then
|
||||
return false
|
||||
else
|
||||
return track.blocks.dtd or track.blocks.signal or track.blocks.distance or track.blocks.user or track.blocks.dup or track.blocks.quality
|
||||
end
|
||||
|
@ -229,6 +236,13 @@ function round(v)
|
|||
return math.floor(v + 0.5)
|
||||
end
|
||||
|
||||
function set_minroutes(track)
|
||||
if track.node_route_count <= config.min_routes or (total_node_route_count - track.node_route_count) <= config.min_routes then
|
||||
track.minroutes = true
|
||||
minroutes_count = minroutes_count + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Canonical hostname
|
||||
function canonical_hostname(hostname)
|
||||
return hostname and hostname:lower():gsub("^dtdlink%.",""):gsub("^mid%d+%.",""):gsub("^xlink%d+%.",""):gsub("%.local%.mesh$", "")
|
||||
|
@ -304,6 +318,7 @@ function lqm()
|
|||
local last_coverage = -1
|
||||
local last_short_retries = -1
|
||||
local last_long_retries = -1
|
||||
local pending_count = 0
|
||||
while true
|
||||
do
|
||||
now = nixio.sysinfo().uptime
|
||||
|
@ -523,7 +538,9 @@ function lqm()
|
|||
last_tx_retries = nil,
|
||||
avg_tx = nil,
|
||||
avg_tx_retries = nil,
|
||||
avg_tx_fail = nil
|
||||
avg_tx_fail = nil,
|
||||
node_route_count = 0,
|
||||
minroutes = false
|
||||
}
|
||||
end
|
||||
local track = tracker[station.mac]
|
||||
|
@ -568,10 +585,17 @@ function lqm()
|
|||
end
|
||||
|
||||
-- Update link tracking state
|
||||
local ip2tracker = {}
|
||||
pending_count = 0
|
||||
for _, track in pairs(tracker)
|
||||
do
|
||||
if not track.ip then
|
||||
track.routable = false
|
||||
else
|
||||
ip2tracker[track.ip] = track
|
||||
|
||||
-- Update if link is routable
|
||||
local rt = track.ip and ip.route(track.ip) or nil
|
||||
local rt = ip.route(track.ip)
|
||||
if rt and tostring(rt.gw) == track.ip then
|
||||
track.routable = true
|
||||
else
|
||||
|
@ -579,7 +603,7 @@ function lqm()
|
|||
end
|
||||
|
||||
-- Refresh remote attributes periodically as this is expensive
|
||||
if track.ip and now > track.refresh then
|
||||
if now > track.refresh then
|
||||
|
||||
-- Refresh the hostname periodically as it can change
|
||||
track.hostname = canonical_hostname(nixio.getnameinfo(track.ip)) or track.hostname
|
||||
|
@ -669,6 +693,7 @@ function lqm()
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Update avg snr using both ends (if we have them)
|
||||
if track.snr then
|
||||
|
@ -681,6 +706,11 @@ function lqm()
|
|||
track.avg_snr = null
|
||||
end
|
||||
|
||||
-- Count number of pending trackers
|
||||
if is_pending(track) then
|
||||
pending_count = pending_count + 1
|
||||
end
|
||||
|
||||
-- Ping addresses and penalize quality for excessively slow links
|
||||
if should_ping(track) then
|
||||
local success = 100
|
||||
|
@ -748,13 +778,32 @@ function lqm()
|
|||
if track.quality and track.quality == 0 and not track.quality0_seen then
|
||||
track.quality0_seen = now
|
||||
end
|
||||
|
||||
track.node_route_count = 0
|
||||
end
|
||||
|
||||
--
|
||||
-- Pull in the routing table to see how many node routes are associated with each tracker.
|
||||
--
|
||||
total_node_route_count = 0
|
||||
for _, route in ipairs(aredn.olsr.getOLSRRoutes())
|
||||
do
|
||||
-- Count routes to nodes. There are two routes to most nodes, the node's primary address
|
||||
-- and the node's dtdlink address.
|
||||
if route.genmask == 32 and route.destination:match("^10%.") then
|
||||
local track = ip2tracker[route.gateway];
|
||||
if track then
|
||||
track.node_route_count = track.node_route_count + 1
|
||||
total_node_route_count = total_node_route_count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- At this point we have gather all the data we need to determine which links are best to use and
|
||||
-- which links should be blocked.
|
||||
--
|
||||
|
||||
minroutes_count = 0
|
||||
for _, track in pairs(tracker)
|
||||
do
|
||||
for _ = 1,1
|
||||
|
@ -768,6 +817,7 @@ function lqm()
|
|||
pair = false,
|
||||
quality = false
|
||||
}
|
||||
track.minroutes = false
|
||||
|
||||
-- Always allow if user requested it
|
||||
for val in string.gmatch(config.user_allows, "([^,]+)")
|
||||
|
@ -799,6 +849,7 @@ function lqm()
|
|||
-- Block any nodes which are too distant
|
||||
if track.distance and (track.distance < config.min_distance or track.distance > config.max_distance) then
|
||||
track.blocks.distance = true
|
||||
set_minroutes(track)
|
||||
break
|
||||
end
|
||||
|
||||
|
@ -819,12 +870,14 @@ function lqm()
|
|||
if not oldblocks.signal then
|
||||
if track.snr < config.low or (track.rev_snr and track.rev_snr < config.low) then
|
||||
track.blocks.signal = true
|
||||
set_minroutes(track)
|
||||
break
|
||||
end
|
||||
-- when blocked link becomes (low+margin) again, unblock
|
||||
-- when blocked link becomes (low+margin) again, dont maintain block
|
||||
else
|
||||
if track.snr < config.low + config.margin or (track.rev_snr and track.rev_snr < config.low + config.margin) then
|
||||
track.blocks.signal = true
|
||||
set_minroutes(track)
|
||||
break
|
||||
else
|
||||
-- When signal is good enough to unblock a link but the quality is low, artificially bump
|
||||
|
@ -842,10 +895,12 @@ function lqm()
|
|||
if not oldblocks.quality then
|
||||
if track.quality < config.min_quality then
|
||||
track.blocks.quality = true
|
||||
set_minroutes(track)
|
||||
end
|
||||
else
|
||||
if track.quality < config.min_quality + config.margin_quality then
|
||||
track.blocks.quality = true
|
||||
set_minroutes(track)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -906,7 +961,6 @@ function lqm()
|
|||
-- Reflect this state with the firewall and various other
|
||||
-- node parameters (e.g. rts, coverage)
|
||||
--
|
||||
|
||||
local distance = -1
|
||||
-- Update the block state and calculate the routable distance
|
||||
for _, track in pairs(tracker)
|
||||
|
@ -1000,13 +1054,17 @@ function lqm()
|
|||
trackers = tracker,
|
||||
distance = distance,
|
||||
coverage = coverage,
|
||||
hidden_nodes = hidden_nodes
|
||||
hidden_nodes = hidden_nodes,
|
||||
total_node_route_count = total_node_route_count
|
||||
}, true))
|
||||
f:close()
|
||||
end
|
||||
|
||||
-- Save valid (unblocked) rf mac list for use by OLSR
|
||||
if config.enable and phy ~= "none" then
|
||||
if minroutes_count > 0 or pending_count > 0 then
|
||||
os.remove( "/tmp/lqm." .. phy .. ".macs")
|
||||
else
|
||||
local tmpfile = "/tmp/lqm." .. phy .. ".macs.tmp"
|
||||
f = io.open(tmpfile, "w")
|
||||
if f then
|
||||
|
@ -1021,6 +1079,7 @@ function lqm()
|
|||
os.remove(tmpfile)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wait_for_ticks(60) -- 1 minute
|
||||
end
|
||||
|
|
|
@ -761,6 +761,9 @@ do
|
|||
else
|
||||
lqmstatus = "idle"
|
||||
end
|
||||
if track.minroutes then
|
||||
lqmstatus = "minroutes"
|
||||
end
|
||||
if track.snr then
|
||||
c4b = track.snr
|
||||
if track.rev_snr then
|
||||
|
|
Loading…
Reference in New Issue