libs/core/ip: optmizations

libs/sys:		implement defaultroute6(), change return values of routes() and routes6()
modules/admin-full:	adept route config page to new api
modules/freifunk:	adept overview page to new routes api
This commit is contained in:
Jo-Philipp Wich 2008-11-29 20:46:26 +00:00
parent 82f08a4a1d
commit dda65d2b94
5 changed files with 165 additions and 112 deletions

View file

@ -227,7 +227,7 @@ function IPv6(address, netmask)
block = tonumber(address:sub(borderl, borderh - 1), 16)
if block and block <= 0xFFFF then
table.insert(data, block)
data[#data+1] = block
else
if zeroh or borderh - borderl > 1 then return nil end
zeroh = #data + 1
@ -241,7 +241,7 @@ function IPv6(address, netmask)
block = tonumber(chunk, 16)
if not block or block > 0xFFFF then return nil end
table.insert(data, block)
data[#data+1] = block
elseif #chunk > 4 then
if #data == 7 or #chunk > 15 then return nil end
borderl = 1
@ -254,7 +254,7 @@ function IPv6(address, netmask)
if not block or block > 255 then return nil end
if i == 1 or i == 3 then
table.insert(data, block * 256)
data[#data+1] = block * 256
else
data[#data] = data[#data] + block
end
@ -308,7 +308,7 @@ function Hex( hex, prefix, family, swap )
for i = 1, ( len / 4 ), 4 do
local n = tonumber( hex:sub( i, i+3 ), 16 )
if n then
table.insert( data, n )
data[#data+1] = n
else
return nil
end
@ -421,26 +421,24 @@ function cidr.prefix( self, mask )
if mask then
prefix = 0
local stop = false
local obj = self:is4() and IPv4(mask) or IPv6(mask)
local obj = type(mask) ~= "table"
and ( self:is4() and IPv4(mask) or IPv6(mask) ) or mask
if not obj then
return nil
end
if not obj then return nil end
for i, block in ipairs(obj[2]) do
local pos = bit.lshift(1, 15)
for i=15, 0, -1 do
if bit.band(block, pos) == pos then
if not stop then
prefix = prefix + 1
else
return nil
end
else
stop = true
for _, word in ipairs(obj[2]) do
if word == 0xFFFF then
prefix = prefix + 16
else
local bitmask = bit.lshift(1, 15)
while bit.band(word, bitmask) == bitmask do
prefix = prefix + 1
bitmask = bit.lshift(1, 15 - (prefix % 16))
end
pos = bit.rshift(pos, 1)
break
end
end
end
@ -460,14 +458,14 @@ function cidr.network( self, bits )
bits = bits or self[3]
for i = 1, math.floor( bits / 16 ) do
table.insert( data, self[2][i] )
data[#data+1] = self[2][i]
end
if #data < #self[2] then
table.insert( data, bit.band( self[2][1+#data], __mask16(bits) ) )
data[#data+1] = bit.band( self[2][1+#data], __mask16(bits) )
for i = #data + 1, #self[2] do
table.insert( data, 0 )
data[#data+1] = 0
end
end
@ -495,14 +493,14 @@ function cidr.mask( self, bits )
bits = bits or self[3]
for i = 1, math.floor( bits / 16 ) do
table.insert( data, 0xFFFF )
data[#data+1] = 0xFFFF
end
if #data < #self[2] then
table.insert( data, __mask16(bits) )
data[#data+1] = __mask16(bits)
for i = #data + 1, #self[2] do
table.insert( data, 0 )
data[#data+1] = 0
end
end

View file

@ -294,21 +294,35 @@ function net.conntrack()
return connt
end
--- Determine the current default route.
--- Determine the current IPv4 default route. If multiple default routes exist,
-- return the one with the lowest metric.
-- @return Table with the properties of the current default route.
-- The following fields are defined:
-- { "Mask", "RefCnt", "Iface", "Flags", "Window", "IRTT",
-- "MTU", "Gateway", "Destination", "Metric", "Use" }
-- { "dest", "gateway", "metric", "refcount", "usecount", "irtt",
-- "flags", "device" }
function net.defaultroute()
local routes = net.routes()
local route = nil
for i, r in pairs(luci.sys.net.routes()) do
if r.Destination == "00000000" and (not route or route.Metric > r.Metric) then
for _, r in pairs(net.routes()) do
if r.dest:prefix() == 0 and (not route or route.metric > r.metric) then
route = r
end
end
return route
end
--- Determine the current IPv6 default route. If multiple default routes exist,
-- return the one with the lowest metric.
-- @return Table with the properties of the current default route.
-- The following fields are defined:
-- { "source", "dest", "nexthop", "metric", "refcount", "usecount",
-- "flags", "device" }
function net.defaultroute6()
local route = nil
for _, r in pairs(net.routes6()) do
if r.dest:prefix() == 0 and (not route or route.metric > r.metric) then
route = r
end
end
return route
end
@ -355,17 +369,49 @@ end
--- Returns the current kernel routing table entries.
-- @return Table of tables with properties of the corresponding routes.
-- The following fields are defined for route entry tables:
-- { "Mask", "RefCnt", "Iface", "Flags", "Window", "IRTT",
-- "MTU", "Gateway", "Destination", "Metric", "Use" }
-- { "dest", "gateway", "metric", "refcount", "usecount", "irtt",
-- "flags", "device" }
function net.routes()
return _parse_delimited_table(io.lines("/proc/net/route"))
local routes = { }
for line in io.lines("/proc/net/route") do
local dev, dst_ip, gateway, flags, refcnt, usecnt, metric,
dst_mask, mtu, win, irtt = line:match(
"([^%s]+)\t([A-F0-9]+)\t([A-F0-9]+)\t([A-F0-9]+)\t" ..
"(%d+)\t(%d+)\t(%d+)\t([A-F0-9]+)\t(%d+)\t(%d+)\t(%d+)"
)
if dev then
gateway = luci.ip.Hex( gateway, 32, luci.ip.FAMILY_INET4 )
dst_mask = luci.ip.Hex( dst_mask, 32, luci.ip.FAMILY_INET4 )
dst_ip = luci.ip.Hex(
dst_ip, dst_mask:prefix(dst_mask), luci.ip.FAMILY_INET4
)
routes[#routes+1] = {
dest = dst_ip,
gateway = gateway,
metric = tonumber(metric),
refcount = tonumber(refcnt),
usecount = tonumber(usecnt),
mtu = tonumber(mtu),
window = tonumber(window),
irtt = tonumber(irtt),
flags = tonumber(flags, 16),
device = dev
}
end
end
return routes
end
--- Returns the current ipv6 kernel routing table entries.
-- @return Table of tables with properties of the corresponding routes.
-- The following fields are defined for route entry tables:
-- { "src_ip", "src_prefix", "dst_ip", "dst_prefix", "nexthop_ip",
-- "metric", "refcount", "usecount", "flags", "device" }
-- { "source", "dest", "nexthop", "metric", "refcount", "usecount",
-- "flags", "device" }
function net.routes6()
local routes = { }
@ -377,32 +423,28 @@ function net.routes6()
"([a-f0-9]+) ([a-f0-9]+) " ..
"([a-f0-9]+) ([a-f0-9]+) " ..
"([a-f0-9]+) ([a-f0-9]+) " ..
"([^%s]+) +([^%s]+)"
"([a-f0-9]+) +([^%s]+)"
)
src_ip = luci.ip.Hex(
src_ip, tonumber(src_prefix, 16),
luci.ip.FAMILY_INET6, false
src_ip, tonumber(src_prefix, 16), luci.ip.FAMILY_INET6, false
)
dst_ip = luci.ip.Hex(
dst_ip, tonumber(dst_prefix, 16),
luci.ip.FAMILY_INET6, false
dst_ip, tonumber(dst_prefix, 16), luci.ip.FAMILY_INET6, false
)
nexthop = luci.ip.Hex( nexthop, 128, luci.ip.FAMILY_INET6, false )
routes[#routes+1] = {
src_ip = src_ip:host():string(),
src_prefix = src_ip:prefix(),
dst_ip = dst_ip:host():string(),
dst_prefix = dst_ip:prefix(),
nexthop_ip = nexthop:string(),
metric = tonumber(metric, 16),
refcount = tonumber(refcnt, 16),
usecount = tonumber(usecnt, 16),
flags = tonumber(flags), -- hex?
device = dev
source = src_ip,
dest = dst_ip,
nexthop = nexthop,
metric = tonumber(metric, 16),
refcount = tonumber(refcnt, 16),
usecount = tonumber(usecnt, 16),
flags = tonumber(flags, 16),
device = dev
}
end
@ -715,17 +757,17 @@ function _parse_mixed_record(cnt, delimiter)
for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n")) do
for j, f in pairs(luci.util.split(luci.util.trim(l), delimiter, nil, true)) do
local k, x, v = f:match('([^%s][^:=]+) *([:=]*) *"*([^\n"]*)"*')
local k, x, v = f:match('([^%s][^:=]+) *([:=]*) *"*([^\n"]*)"*')
if k then
if k then
if x == "" then
table.insert(flags, k)
else
data[k] = v
data[k] = v
end
end
end
end
end
end
return data, flags
return data, flags
end

View file

@ -21,23 +21,23 @@ if not arg or not arg[1] then
net = v:option(DummyValue, "iface", translate("network"))
function net.cfgvalue(self, section)
return luci.tools.webadmin.iface_get_network(routes[section].Iface)
or routes[section].Iface
return luci.tools.webadmin.iface_get_network(routes[section].device)
or routes[section].device
end
target = v:option(DummyValue, "target", translate("target"))
function target.cfgvalue(self, section)
return luci.ip.Hex(routes[section].Destination, 32):string()
return routes[section].dest:network():string()
end
netmask = v:option(DummyValue, "netmask", translate("netmask"))
function netmask.cfgvalue(self, section)
return luci.ip.Hex(routes[section].Mask, 32):string()
return routes[section].dest:mask():string()
end
gateway = v:option(DummyValue, "gateway", translate("gateway"))
function gateway.cfgvalue(self, section)
return luci.ip.Hex(routes[section].Gateway, 32):string()
return routes[section].gateway:string()
end
metric = v:option(DummyValue, "Metric", translate("metric"))
@ -55,12 +55,12 @@ if not arg or not arg[1] then
target = v:option(DummyValue, "target", translate("target"))
function target.cfgvalue(self, section)
return routes6[section].dst_ip .. "/" .. routes6[section].dst_prefix
return routes6[section].dest:string()
end
gateway = v:option(DummyValue, "gateway", translate("gateway6"))
function gateway.cfgvalue(self, section)
return routes6[section].src_ip .. "/" .. routes6[section].src_prefix
return routes6[section].source:string()
end
metric = v:option(DummyValue, "Metric", translate("metric"))

View file

@ -30,18 +30,18 @@ function index()
page.setgroup = "nogroup"
page.i18n = "freifunk"
page.index = true
local page = node("freifunk", "index")
page.target = template("freifunk/index")
page.title = "Übersicht"
page.order = 10
page.indexignore = true
local page = node("freifunk", "index", "contact")
page.target = template("freifunk/contact")
page.title = "Kontakt"
local page = node("freifunk", "status")
page.target = form("freifunk/public_status")
page.title = "Status"
@ -49,43 +49,22 @@ function index()
page.i18n = "admin-core"
page.setuser = false
page.setgroup = false
assign({"freifunk", "olsr"}, {"admin", "status", "olsr"}, "OLSR", 30)
if luci.fs.isfile("/etc/config/luci_statistics") then
assign({"freifunk", "graph"}, {"admin", "statistics", "graph"}, i18n("stat_statistics", "Statistiken"), 40)
end
assign({"mini", "freifunk"}, {"admin", "freifunk"}, "Freifunk", 15)
entry({"admin", "freifunk"}, alias("admin", "freifunk", "index"), "Freifunk", 15)
local page = node("admin", "freifunk", "index")
page.target = cbi("freifunk/freifunk")
page.title = "Freifunk"
page.order = 30
local page = node("admin", "freifunk", "contact")
page.target = cbi("freifunk/contact")
page.title = "Kontakt"
page.order = 40
end
function action_status()
local data = {}
data.system, data.model, data.memtotal, data.memcached, data.membuffers, data.memfree = luci.sys.sysinfo()
data.perc_memfree = math.floor((data.memfree/data.memtotal)*100)
data.perc_membuffers = math.floor((data.membuffers/data.memtotal)*100)
data.perc_memcached = math.floor((data.memcached/data.memtotal)*100)
data.wifi = luci.sys.wifi.getiwconfig()
data.routes = {}
for i, r in pairs(luci.sys.net.routes()) do
if r.Destination == "00000000" then
table.insert(data.routes, r)
end
end
luci.template.render("public_status/index", data)
end

View file

@ -19,23 +19,23 @@ f:field(DummyValue, "_system", translate("system")).value = system
f:field(DummyValue, "_cpu", translate("m_i_processor")).value = model
local load1, load5, load15 = luci.sys.loadavg()
f:field(DummyValue, "_la", translate("load")).value =
f:field(DummyValue, "_la", translate("load")).value =
string.format("%.2f, %.2f, %.2f", load1, load5, load15)
f:field(DummyValue, "_memtotal", translate("m_i_memory")).value =
f:field(DummyValue, "_memtotal", translate("m_i_memory")).value =
string.format("%.2f MB (%.0f%% %s, %.0f%% %s, %.0f%% %s)",
tonumber(memtotal) / 1024,
100 * memcached / memtotal,
translate("mem_cached") or "",
100 * membuffers / memtotal,
translate("mem_buffered") or "",
100 * memfree / memtotal,
translate("mem_free") or "")
translate("mem_buffered") or "",
100 * memfree / memtotal,
translate("mem_free") or "")
f:field(DummyValue, "_systime", translate("m_i_systemtime")).value =
os.date("%c")
f:field(DummyValue, "_uptime", translate("m_i_uptime")).value =
f:field(DummyValue, "_uptime", translate("m_i_uptime")).value =
luci.tools.webadmin.date_format(tonumber(uptime))
@ -69,7 +69,7 @@ essid = s:option(DummyValue, "ssid", "ESSID")
bssid = s:option(DummyValue, "_bsiid", "BSSID")
function bssid.cfgvalue(self, section)
local ifname = self.map:get(section, "ifname")
return (wifidata[ifname] and (wifidata[ifname].Cell
return (wifidata[ifname] and (wifidata[ifname].Cell
or wifidata[ifname]["Access Point"])) or "-"
end
@ -124,7 +124,7 @@ function chan.cfgvalue(self, section)
return self.map:get(section, "Channel")
or self.map:get(section, "Frequency")
or "-"
end
end
t2:option(DummyValue, "Encryption key", translate("iwscan_encr"))
@ -137,37 +137,71 @@ t2:option(DummyValue, "Noise level", translate("iwscan_noise"))
r = SimpleForm("routes", "Standardrouten")
r.submit = false
r.reset = false
local routes = {}
for i, route in ipairs(luci.sys.net.routes()) do
if route.Destination == "00000000" then
if route.dest:prefix() == 0 then
routes[#routes+1] = route
end
end
v = r:section(Table, routes)
net = v:option(DummyValue, "iface", translate("network"))
function net.cfgvalue(self, section)
return luci.tools.webadmin.iface_get_network(routes[section].Iface)
or routes[section].Iface
return luci.tools.webadmin.iface_get_network(routes[section].device)
or routes[section].device
end
target = v:option(DummyValue, "target", translate("target"))
function target.cfgvalue(self, section)
return luci.ip.Hex(routes[section].Destination, 32):string()
return routes[section].dest:network():string()
end
netmask = v:option(DummyValue, "netmask", translate("netmask"))
function netmask.cfgvalue(self, section)
return luci.ip.Hex(routes[section].Mask, 32):string()
return routes[section].dest:mask():string()
end
gateway = v:option(DummyValue, "gateway", translate("gateway"))
function gateway.cfgvalue(self, section)
return luci.ip.Hex(routes[section].Gateway, 32):string()
return routes[section].gateway:string()
end
metric = v:option(DummyValue, "Metric", translate("metric"))
metric = v:option(DummyValue, "metric", translate("metric"))
function metric.cfgvalue(self, section)
return routes[section].metric
end
local routes6 = {}
for i, route in ipairs(luci.sys.net.routes6()) do
if route.dest:prefix() == 0 then
routes6[#routes6+1] = route
end
end
v6 = r:section(Table, routes6)
net = v6:option(DummyValue, "iface", translate("network"))
function net.cfgvalue(self, section)
return luci.tools.webadmin.iface_get_network(routes[section].device)
or routes6[section].device
end
target = v6:option(DummyValue, "target", translate("target"))
function target.cfgvalue(self, section)
return routes6[section].dest:string()
end
gateway = v6:option(DummyValue, "gateway6", translate("gateway6"))
function gateway.cfgvalue(self, section)
return routes6[section].source:string()
end
metric = v6:option(DummyValue, "metric", translate("metric"))
function metric.cfgvalue(self, section)
return string.format("%X", routes6[section].metric)
end
return f, m, r