libs/core/ip: optmizations
authorJo-Philipp Wich <jow@openwrt.org>
Sat, 29 Nov 2008 20:46:26 +0000 (20:46 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Sat, 29 Nov 2008 20:46:26 +0000 (20:46 +0000)
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
libs/sys/luasrc/sys.lua
modules/admin-full/luasrc/model/cbi/admin_network/routes.lua
modules/freifunk/luasrc/controller/freifunk/freifunk.lua
modules/freifunk/luasrc/model/cbi/freifunk/public_status.lua

index 590ea76..98666e5 100644 (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
 
index b7e374d..2b9d9a3 100644 (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
index a236e8c..aa22cf6 100644 (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"))
index 9399d50..533211b 100644 (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
\ No newline at end of file
index 08201f7..5971e2a 100644 (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"))
+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