From dda65d2b94f11f69537bed3c46d3c6e80234291b Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Sat, 29 Nov 2008 20:46:26 +0000 Subject: [PATCH] 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 --- libs/core/luasrc/ip.lua | 50 ++++---- libs/sys/luasrc/sys.lua | 108 ++++++++++++------ .../luasrc/model/cbi/admin_network/routes.lua | 14 +-- .../luasrc/controller/freifunk/freifunk.lua | 37 ++---- .../model/cbi/freifunk/public_status.lua | 68 ++++++++--- 5 files changed, 165 insertions(+), 112 deletions(-) diff --git a/libs/core/luasrc/ip.lua b/libs/core/luasrc/ip.lua index 590ea76b2..98666e5a5 100644 --- a/libs/core/luasrc/ip.lua +++ b/libs/core/luasrc/ip.lua @@ -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 diff --git a/libs/sys/luasrc/sys.lua b/libs/sys/luasrc/sys.lua index b7e374d7c..2b9d9a3c5 100644 --- a/libs/sys/luasrc/sys.lua +++ b/libs/sys/luasrc/sys.lua @@ -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 diff --git a/modules/admin-full/luasrc/model/cbi/admin_network/routes.lua b/modules/admin-full/luasrc/model/cbi/admin_network/routes.lua index a236e8c19..aa22cf63f 100644 --- a/modules/admin-full/luasrc/model/cbi/admin_network/routes.lua +++ b/modules/admin-full/luasrc/model/cbi/admin_network/routes.lua @@ -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")) diff --git a/modules/freifunk/luasrc/controller/freifunk/freifunk.lua b/modules/freifunk/luasrc/controller/freifunk/freifunk.lua index 9399d5093..533211b00 100644 --- a/modules/freifunk/luasrc/controller/freifunk/freifunk.lua +++ b/modules/freifunk/luasrc/controller/freifunk/freifunk.lua @@ -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 \ No newline at end of file diff --git a/modules/freifunk/luasrc/model/cbi/freifunk/public_status.lua b/modules/freifunk/luasrc/model/cbi/freifunk/public_status.lua index 08201f703..5971e2a2f 100644 --- a/modules/freifunk/luasrc/model/cbi/freifunk/public_status.lua +++ b/modules/freifunk/luasrc/model/cbi/freifunk/public_status.lua @@ -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")) +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 -metric = v:option(DummyValue, "Metric", translate("metric")) +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 -- 2.25.1