Strip out as many dependncies from Lua Manager as possible to save memory (#522)

This commit is contained in:
Tim Wilkinson 2022-10-13 10:07:36 -07:00 committed by GitHub
parent 1a0d51ff59
commit 93ad1f5ee7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 218 additions and 208 deletions

View File

@ -38,7 +38,6 @@ require("uci")
local aredn_uci = require("aredn.uci")
require("aredn.utils")
-- require("aredn.http")
local lip=require("luci.ip")
require("nixio")
require("ubus")

View File

@ -0,0 +1,175 @@
#!/usr/bin/lua
--[[
Part of AREDN -- Used for creating Amateur Radio Emergency Data Networks
Copyright (C) 2019 Darryl Quinn
See Contributors file for additional contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation version 3 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional Terms:
Additional use restrictions exist on the AREDN(TM) trademark and logo.
See AREDNLicense.txt for more info.
Attributions to the AREDN Project must be retained in the source code.
If importing this code into a new or existing project attribution
to the AREDN project must be added to the source code.
You must not misrepresent the origin of the material contained within.
Modified versions must be modified to attribute to the original source
and be marked in reasonable ways as differentiate it from the original
version.
--]]
require("aredn.utils")
require("luci.sys")
local tools = {}
-------------------------------------
-- Returns traceroute
-------------------------------------
function tools.getTraceroute(target)
local info={}
local routes={}
local trall=capture('/bin/traceroute -q1 ' .. target )
local lines = trall:splitNewLine()
table.remove(lines, 1) -- remove heading
table.remove(lines, #lines) -- remove blank last line
local data = {}
local priortime = 0
for i,v in pairs(lines) do
data = v:splitWhiteSpace()
entry = {}
if data[2] ~= "*" then
node = data[2]:gsub("^mid[0-9]*%.","") -- strip midXX.
node = node:gsub("^dtdlink%.","") -- strip dtdlink.
node = node:gsub("%.local%.mesh$","") -- strip .local.mesh
entry['nodename'] = node
ip = data[3]:match("%((.*)%)")
entry['ip'] = ip
entry['timeto'] = round2(data[4])
entry['timedelta'] = math.abs(round2(data[4] - priortime))
priortime = round2(data[4])
table.insert(routes, entry)
end
end
return routes
end
-------------------------------------
-- Returns ping
-------------------------------------
function tools.getPing(target)
local pings = {}
local summary = { tx = -1, rx = -1, lossPercentage = -1, ip = "not found", minMs = -1, maxMs = -1, avgMs = -1 }
local output = capture("/bin/ping -w 10 " .. target)
local foundip = "unknown"
for _, line in ipairs(output:splitNewLine())
do
local ip = line:match("^PING %S+ %(([%d%.]+)%):")
if ip then
summary.ip = ip
else
local ip, seq, ttl, time = line:match("bytes from ([%d%.]+): seq=(%d+) ttl=(%d+) time=(%S+) ms")
if ip then
pings[#pings + 1] = { ip = ip, seq = tonumber(seq), ttl = tonumber(ttl), timeMs = tonumber(time) }
else
local tx, rx, loss = line:match("^(%d+) packets transmitted, (%d+) packets received, (%d+)%% packet loss")
if tx then
summary.tx = tonumber(tx)
summary.rx = tonumber(rx)
summary.lossPercentage = tonumber(loss)
else
local min, avg, max = line:match("min/avg/max = ([%d%.]+)/([%d%.]+)/([%d%.]+) ms")
if min then
summary.minMs = tonumber(min)
summary.maxMs = tonumber(max)
summary.avgMs = tonumber(avg)
end
end
end
end
end
return { summary = summary, pings = pings }
end
-------------------------------------
-- Returns iperf3
-------------------------------------
function tools.getIperf3(target, protocol)
if protocol ~= "udp" then
protocol = "tcp"
end
function toK(value, unit)
return tonumber(value) * (unit == "M" and 1024 or 1)
end
function toM(value, unit)
return tonumber(value) / (unit == "K" and 1024 or 1)
end
local summary = { protocol = protocol, client = {}, server = {}, sender = {}, receiver = {} }
local trace = {}
-- start remote server
luci.sys.httpget("http://" .. target .. ":8080/cgi-bin/iperf?server=")
local output = capture("/usr/bin/iperf3 -b 0 -c " .. target .. (protocol == "udp" and " -u" or "") .. " 2>&1")
for _, line in ipairs(output:splitNewLine())
do
local chost, cport, shost, sport = line:match("local ([%d%.]+) port (%d+) connected to ([%d%.]+) port (%d+)")
if chost then
summary.client = { host = chost, port = tonumber(cport) }
summary.server = { host = shost, port = tonumber(sport) }
else
local from, to, transfer, tu, bitrate, bu, retr = line:match("([%d%.]+)-([%d%.]+)%s+sec%s+([%d%.]+) ([KM])Bytes%s+([%d%.]+) ([MK])bits/sec%s+(%d+)%s+sender")
if from then
summary.sender = { from = tonumber(from), to = tonumber(to), transferMB = toM(transfer, tu), bitrateMb = toM(bitrate, bu), retr = tonumber(retr) }
else
local from, to, transfer, tu, bitrate, bu = line:match("([%d%.]+)-([%d%.]+)%s+sec%s+([%d%.]+) ([KM])Bytes%s+([%d%.]+) ([MK])bits/sec%s+receiver")
if from then
summary.receiver = { from = tonumber(from), to = tonumber(to), transferMB = toM(transfer, tu), bitrateMb = toM(bitrate, bu) }
else
local from, to, transfer, tu, bitrate, bu, jitter, lost, total, percent = line:match("([%d%.]+)-([%d%.]+)%s+sec%s+([%d%.]+) ([KM])Bytes%s+([%d%.]+) ([MK])bits/sec%s+([%d%.]+) ms%s+(%d+)/(%d+) %(([%d%.]+)%%%)%s+sender")
if from then
summary.sender = { from = tonumber(from), to = tonumber(to), transferMB = toM(transfer, tu), bitrateMb = toM(bitrate, bu), jitterMs = tonumber(jitter), lostDgrams = tonumber(lost), totalDgrams = tonumber(total), lossPercentage = tonumber(precent) }
else
local from, to, transfer, tu, bitrate, bu, jitter, lost, total, percent = line:match("([%d%.]+)-([%d%.]+)%s+sec%s+([%d%.]+) ([KM])Bytes%s+([%d%.]+) ([MK])bits/sec%s+([%d%.]+) ms%s+(%d+)/(%d+) %(([%d%.]+)%%%)%s+receiver")
if from then
summary.receiver = { from = tonumber(from), to = tonumber(to), transferMB = toM(transfer, tu), bitrateMb = toM(bitrate, bu), jitterMs = tonumber(jitter), lostDgrams = tonumber(lost), totalDgrams = tonumber(total), lossPercentage = tonumber(precent) }
else
local from, to, transfer, tu, bitrate, bu, retr, cwnd, cu = line:match("([%d%.]+)-([%d%.]+)%s+sec%s+([%d%.]+) ([KM])Bytes%s+([%d%.]+) ([MK])bits/sec%s+(%d+)%s+([%d%.]+) ([KM])Bytes")
if from then
trace[#trace + 1] = { from = tonumber(from), to = tonumber(to), transferMB = toM(transfer, tu), bitrateMb = toM(bitrate, by), retr = tonumber(retr), cwndKB = toK(cwnd, cu) }
else
local from, to, transfer, tu, bitrate, bu, dgrams = line:match("([%d%.]+)-([%d%.]+)%s+sec%s+([%d%.]+) ([KM])Bytes%s+([%d%.]+) ([MK])bits/sec%s+(%d+)")
if from then
trace[#trace + 1] = { from = tonumber(from), to = tonumber(to), transferMB = toM(transfer, tu), bitrateMb = toM(bitrate, bu), dgrams = tonumber(dgrams) }
end
end
end
end
end
end
end
end
return { summary = summary, trace = trace }
end
if not aredn then
aredn = {}
end
aredn.nettools = tools
return tools

View File

@ -37,9 +37,7 @@
local nxo = require("nixio")
local ipc = require("luci.ip")
local auci = require("aredn.uci")
require("uci")
require("luci.sys")
function round2(num, idp)
return tonumber(string.format("%." .. (idp or 0) .. "f", num))
@ -57,15 +55,6 @@ function adjust_rate(r,b)
return ar
end
function starts_with(str, start)
return str:sub(1, #start) == start
end
function ends_with(str, ending)
return ending == "" or str:sub(-#ending) == ending
end
function string:split(delim)
local t = {}
local function helper(line) table.insert(t, line) return "" end
@ -124,12 +113,15 @@ 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
local device = nil
uci.cursor():foreach("wireless", "wifi-iface",
function(s)
if s.network == ifn then
device = s.device
end
end
)
return device
end
-------------------------------------
@ -163,14 +155,14 @@ end
function get_ifname(ifn)
local u=uci.cursor()
iface=u:get("network",ifn,"ifname")
local iface=u:get("network",ifn,"ifname")
return iface
end
-- Copyright 2009-2015 Jo-Philipp Wich <jow@openwrt.org>
-- Licensed to the public under the Apache License 2.0.
function get_interfaces()
_interfaces={}
local _interfaces={}
local n, i
for n, i in ipairs(nxo.getifaddrs()) do
local name = i.name:match("[^:]+")
@ -271,136 +263,6 @@ function iplookup(host)
return ip
end
-------------------------------------
-- Returns traceroute
-------------------------------------
function getTraceroute(target)
local info={}
local routes={}
trall=capture('/bin/traceroute -q1 ' .. target )
local lines = trall:splitNewLine()
table.remove(lines, 1) -- remove heading
table.remove(lines, #lines) -- remove blank last line
data = {}
priortime = 0
for i,v in pairs(lines) do
data = v:splitWhiteSpace()
entry = {}
if data[2] ~= "*" then
node = data[2]:gsub("^mid[0-9]*%.","") -- strip midXX.
node = node:gsub("^dtdlink%.","") -- strip dtdlink.
node = node:gsub("%.local%.mesh$","") -- strip .local.mesh
entry['nodename'] = node
ip = data[3]:match("%((.*)%)")
entry['ip'] = ip
entry['timeto'] = round2(data[4])
entry['timedelta'] = math.abs(round2(data[4] - priortime))
priortime = round2(data[4])
table.insert(routes, entry)
end
end
return routes
end
-------------------------------------
-- Returns ping
-------------------------------------
function getPing(target)
local pings = {}
local summary = { tx = -1, rx = -1, lossPercentage = -1, ip = "not found", minMs = -1, maxMs = -1, avgMs = -1 }
local output = capture("/bin/ping -w 10 " .. target)
local foundip = "unknown"
for _, line in ipairs(output:splitNewLine())
do
local ip = line:match("^PING %S+ %(([%d%.]+)%):")
if ip then
summary.ip = ip
else
local ip, seq, ttl, time = line:match("bytes from ([%d%.]+): seq=(%d+) ttl=(%d+) time=(%S+) ms")
if ip then
pings[#pings + 1] = { ip = ip, seq = tonumber(seq), ttl = tonumber(ttl), timeMs = tonumber(time) }
else
local tx, rx, loss = line:match("^(%d+) packets transmitted, (%d+) packets received, (%d+)%% packet loss")
if tx then
summary.tx = tonumber(tx)
summary.rx = tonumber(rx)
summary.lossPercentage = tonumber(loss)
else
local min, avg, max = line:match("min/avg/max = ([%d%.]+)/([%d%.]+)/([%d%.]+) ms")
if min then
summary.minMs = tonumber(min)
summary.maxMs = tonumber(max)
summary.avgMs = tonumber(avg)
end
end
end
end
end
return { summary = summary, pings = pings }
end
-------------------------------------
-- Returns iperf3
-------------------------------------
function getIperf3(target, protocol)
if protocol ~= "udp" then
protocol = "tcp"
end
function toK(value, unit)
return tonumber(value) * (unit == "M" and 1024 or 1)
end
function toM(value, unit)
return tonumber(value) / (unit == "K" and 1024 or 1)
end
local summary = { protocol = protocol, client = {}, server = {}, sender = {}, receiver = {} }
local trace = {}
-- start remote server
luci.sys.httpget("http://" .. target .. ":8080/cgi-bin/iperf?server=")
local output = capture("/usr/bin/iperf3 -b 0 -c " .. target .. (protocol == "udp" and " -u" or "") .. " 2>&1")
for _, line in ipairs(output:splitNewLine())
do
local chost, cport, shost, sport = line:match("local ([%d%.]+) port (%d+) connected to ([%d%.]+) port (%d+)")
if chost then
summary.client = { host = chost, port = tonumber(cport) }
summary.server = { host = shost, port = tonumber(sport) }
else
local from, to, transfer, tu, bitrate, bu, retr = line:match("([%d%.]+)-([%d%.]+)%s+sec%s+([%d%.]+) ([KM])Bytes%s+([%d%.]+) ([MK])bits/sec%s+(%d+)%s+sender")
if from then
summary.sender = { from = tonumber(from), to = tonumber(to), transferMB = toM(transfer, tu), bitrateMb = toM(bitrate, bu), retr = tonumber(retr) }
else
local from, to, transfer, tu, bitrate, bu = line:match("([%d%.]+)-([%d%.]+)%s+sec%s+([%d%.]+) ([KM])Bytes%s+([%d%.]+) ([MK])bits/sec%s+receiver")
if from then
summary.receiver = { from = tonumber(from), to = tonumber(to), transferMB = toM(transfer, tu), bitrateMb = toM(bitrate, bu) }
else
local from, to, transfer, tu, bitrate, bu, jitter, lost, total, percent = line:match("([%d%.]+)-([%d%.]+)%s+sec%s+([%d%.]+) ([KM])Bytes%s+([%d%.]+) ([MK])bits/sec%s+([%d%.]+) ms%s+(%d+)/(%d+) %(([%d%.]+)%%%)%s+sender")
if from then
summary.sender = { from = tonumber(from), to = tonumber(to), transferMB = toM(transfer, tu), bitrateMb = toM(bitrate, bu), jitterMs = tonumber(jitter), lostDgrams = tonumber(lost), totalDgrams = tonumber(total), lossPercentage = tonumber(precent) }
else
local from, to, transfer, tu, bitrate, bu, jitter, lost, total, percent = line:match("([%d%.]+)-([%d%.]+)%s+sec%s+([%d%.]+) ([KM])Bytes%s+([%d%.]+) ([MK])bits/sec%s+([%d%.]+) ms%s+(%d+)/(%d+) %(([%d%.]+)%%%)%s+receiver")
if from then
summary.receiver = { from = tonumber(from), to = tonumber(to), transferMB = toM(transfer, tu), bitrateMb = toM(bitrate, bu), jitterMs = tonumber(jitter), lostDgrams = tonumber(lost), totalDgrams = tonumber(total), lossPercentage = tonumber(precent) }
else
local from, to, transfer, tu, bitrate, bu, retr, cwnd, cu = line:match("([%d%.]+)-([%d%.]+)%s+sec%s+([%d%.]+) ([KM])Bytes%s+([%d%.]+) ([MK])bits/sec%s+(%d+)%s+([%d%.]+) ([KM])Bytes")
if from then
trace[#trace + 1] = { from = tonumber(from), to = tonumber(to), transferMB = toM(transfer, tu), bitrateMb = toM(bitrate, by), retr = tonumber(retr), cwndKB = toK(cwnd, cu) }
else
local from, to, transfer, tu, bitrate, bu, dgrams = line:match("([%d%.]+)-([%d%.]+)%s+sec%s+([%d%.]+) ([KM])Bytes%s+([%d%.]+) ([MK])bits/sec%s+(%d+)")
if from then
trace[#trace + 1] = { from = tonumber(from), to = tonumber(to), transferMB = toM(transfer, tu), bitrateMb = toM(bitrate, bu), dgrams = tonumber(dgrams) }
end
end
end
end
end
end
end
end
return { summary = summary, trace = trace }
end
function file_trim(filename, maxl)
local lines={}
local tmpfilename=filename..".tmp"
@ -436,41 +298,6 @@ function secondsToClock(seconds)
end
end
-- table.print = pretty prints a table
function print_r(t)
local print_r_cache={}
local function sub_print_r(t,indent)
if (print_r_cache[tostring(t)]) then
print(indent.."*"..tostring(t))
else
print_r_cache[tostring(t)]=true
if (type(t)=="table") then
for pos,val in pairs(t) do
if (type(val)=="table") then
print(indent.."["..pos.."] => "..tostring(t).." {")
sub_print_r(val,indent..string.rep(" ",string.len(pos)+8))
print(indent..string.rep(" ",string.len(pos)+6).."}")
elseif (type(val)=="string") then
print(indent.."["..pos..'] => "'..val..'"')
else
print(indent.."["..pos.."] => "..tostring(val))
end
end
else
print(indent..tostring(t))
end
end
end
if (type(t)=="table") then
print(tostring(t).." {")
sub_print_r(t," ")
print("}")
else
sub_print_r(t," ")
end
print()
end
-- os.capture = captures output from a shell command
function capture(cmd)
local handle= io.popen(cmd)

View File

@ -38,17 +38,14 @@ package.path = package.path .. ";/usr/local/bin/?.lua"
require("uci")
require("nixio")
socket = require("socket")
require("aredn.utils")
aredn_info = require("aredn.info")
require("iwinfo")
require("aredn.http")
require("aredn.hardware")
require("aredn.log")
require("luci.sys")
require("luci.jsonc")
-- aggressive gc on low memory devices
if aredn_info.getFreeMemory().totalram < 32768 then
if nixio.sysinfo().totalram < 32 * 1024 * 1024 then
collectgarbage("setstepmul", 1000)
end

View File

@ -34,9 +34,11 @@
--]]
local socket = require("socket")
function fccid()
local id = string.format("ID: %s", capture("uname -n"))
local ip = aredn_info.getInterfaceIPAddress("wifi")
local ip = uci.cursor():get("network", "wifi", "ipaddr")
local udp = socket.udp()
udp:setoption("broadcast", true)
udp:setsockname(ip, 4919)

View File

@ -50,7 +50,9 @@ function linkled()
while true
do
local nei = fetch_json("http://127.0.0.1:9090/neighbors")
local raw = io.popen("/usr/bin/wget -O - http://127.0.0.1:9090/neighbors 2> /dev/null")
local nei = luci.jsonc.parse(raw:read("*a"))
raw:close()
if nei and #nei.neighbors > 0 then
-- Led on when link established. Retest every 10 seconds
write_all(link .. "/brightness", "1")

View File

@ -32,9 +32,7 @@
--]]
local json = require("luci.jsonc")
local ip = require("luci.ip")
local sys = require("luci.sys")
local info = require("aredn.info")
local refresh_timeout = 15 * 60 -- refresh high cost data every 15 minutes
@ -232,11 +230,9 @@ function lqm()
-- Know our macs so we can exclude them
local our_macs = {}
for _, devname in ipairs(sys.net.devices())
do
local info = ip.link(devname)
if info and info.mac then
our_macs[tostring(info.mac)] = true
for _, i in ipairs(nixio.getifaddrs()) do
if i.family == "packet" then
our_macs[i.addr] = true
end
end
@ -425,7 +421,9 @@ function lqm()
track.rev_snr = null
dtdlinks[track.mac] = {}
local info = json.parse(luci.sys.httpget("http://" .. track.ip .. ":8080/cgi-bin/sysinfo.json?link_info=1&lqm=1"))
local raw = io.popen("/usr/bin/wget -O - 'http://" .. track.ip .. ":8080/cgi-bin/sysinfo.json?link_info=1&lqm=1' 2>/dev/null")
local info = luci.jsonc.parse(raw:read("*a"))
raw:close()
if info then
if tonumber(info.lat) and tonumber(info.lon) then
track.lat = tonumber(info.lat)
@ -761,7 +759,7 @@ function lqm()
-- Save this for the UI
f = io.open("/tmp/lqm.info", "w")
if f then
f:write(json.stringify({
f:write(luci.jsonc.stringify({
now = now,
trackers = tracker,
distance = distance,

View File

@ -80,7 +80,9 @@ function do_namechange()
end
-- Find the current neighbors
local links = fetch_json("http://127.0.0.1:9090/links")
local raw = io.popen("/usr/bin/wget -O - http://127.0.0.1:9090/links 2> /dev/null")
local links = luci.jsonc.parse(raw:read("*a"))
raw:close()
if not (links and links.links and #links.links > 0) then
return
end

View File

@ -83,7 +83,15 @@ function run_snrlog()
end)
-- get the current bandwidth setting
local bandwidth = aredn_info.getChannelBW(aredn_info.getMeshRadioDevice())
local radio = "radio0"
cursor:foreach("wireless", "wifi-iface",
function(i)
if i.mode == "adhoc" then
radio = i.device
end
end
)
local bandwidth = cursor:get("wireless", radio, "chanbw")
-- load the lasttime table
local lasttime = {}

View File

@ -42,12 +42,11 @@ local logfile = "/tmp/olsrd.log"
function olsrd_restart()
-- print "olsrd_restart"
-- This "luci.sys.init.restart("olsrd")" doesnt do the same thing so we have to call restart directly
os.execute("/etc/init.d/olsrd restart")
if nixio.fs.stat(logfile) then
local lines = read_all(logfile):splitNewLine()
lines[#lines + 1] = aredn_info.getUptime() .. " " .. os.date()
lines[#lines + 1] = secondsToClock(nixio.sysinfo().uptime) .. " " .. os.date()
local start = 1
if #lines > 300 then
start = #lines - 275

View File

@ -72,7 +72,7 @@ if wifi_mac == "" or mac2 == "" then
if phy then
break
end
sleep(5);
sleep(5)
end
for line in io.lines("/sys/class/ieee80211/" .. phy .. "/macaddress")
do

View File

@ -43,6 +43,7 @@ local aredn_info = require("aredn.info")
require("nixio")
local json = require("luci.jsonc")
require("iwinfo")
local nettools = require("aredn.nettools")
local API_VERSION="1.5"
@ -373,7 +374,7 @@ for page, comps in pairs(qsset) do
for i,tonode in pairs(comps:split(',')) do
-- Validate that input as ip or hostname inside the mesh
if tonode:match("^[%d%.]+$") or tonode:match("^[%d%a%-%.%_]+$") then
info['pages'][page][tonode]=getTraceroute(tonode)
info['pages'][page][tonode]=nettools.getTraceroute(tonode)
else
info['pages'][page][tonode]="Invalid input!"
end
@ -382,7 +383,7 @@ for page, comps in pairs(qsset) do
for i,tonode in pairs(comps:split(',')) do
-- Validate that input as ip or hostname inside the mesh
if tonode:match("^[%d%.]+$") or tonode:match("^[%d%a%-%.%_]+$") then
info['pages'][page][tonode]=getPing(tonode)
info['pages'][page][tonode]=nettools.getPing(tonode)
else
info['pages'][page][tonode]="Invalid input!"
end
@ -394,7 +395,7 @@ for page, comps in pairs(qsset) do
if tonode == "tcp" or tonode == "udp" then
protocol = tonode
elseif tonode:match("^[%d%.]+$") or tonode:match("^[%d%a%-%.%_]+$") then
info['pages'][page][tonode]=getIperf3(tonode, protocol)
info['pages'][page][tonode]=nettools.getIperf3(tonode, protocol)
else
info['pages'][page][tonode]="Invalid input!"
end