summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-base/luasrc
diff options
context:
space:
mode:
authorJo-Philipp Wich <jow@openwrt.org>2015-12-09 15:53:26 +0100
committerJo-Philipp Wich <jow@openwrt.org>2015-12-09 15:54:43 +0100
commit397294ab06b2f228263ceb3d1435db3d282e715f (patch)
tree5a2b6a14c42bd8ffab4538b98840502fc24a92a2 /modules/luci-base/luasrc
parentc18a0e447fa0fd0ee74dab2ed27c1d261c0efe4d (diff)
luci-base: rewrite luci.sys.net.conntrack()
The new function is twice as fast as the old implementation and properly summarizes outgoing and incoming byte and packet counters. Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
Diffstat (limited to 'modules/luci-base/luasrc')
-rw-r--r--modules/luci-base/luasrc/sys.lua97
1 files changed, 38 insertions, 59 deletions
diff --git a/modules/luci-base/luasrc/sys.lua b/modules/luci-base/luasrc/sys.lua
index 77f4d44a54..31c3e12095 100644
--- a/modules/luci-base/luasrc/sys.lua
+++ b/modules/luci-base/luasrc/sys.lua
@@ -293,47 +293,51 @@ function net.ipv6_hints(callback)
end
function net.conntrack(callback)
- local connt = {}
- if fs.access("/proc/net/nf_conntrack", "r") then
- for line in io.lines("/proc/net/nf_conntrack") do
- line = line:match "^(.-( [^ =]+=).-)%2"
- local entry, flags = _parse_mixed_record(line, " +")
- if flags[6] ~= "TIME_WAIT" then
- entry.layer3 = flags[1]
- entry.layer4 = flags[3]
- for i=1, #entry do
- entry[i] = nil
- end
+ local ok, nfct = pcall(io.lines, "/proc/net/nf_conntrack")
+ if not ok or not nfct then
+ return nil
+ end
- if callback then
- callback(entry)
- else
- connt[#connt+1] = entry
+ local line, connt = nil, (not callback) and { }
+ for line in nfct do
+ local fam, l3, l4, timeout, state, tuples =
+ line:match("^(ipv[46]) +(%d+) +%S+ +(%d+) +(%d+) +([A-Z_]+) +(.+)$")
+
+ if fam and l3 and l4 and timeout and state and tuples and
+ state ~= "TIME_WAIT"
+ then
+ l4 = nixio.getprotobynumber(l4)
+
+ local entry = {
+ bytes = 0,
+ packets = 0,
+ layer3 = fam,
+ layer4 = l4 and l4.name or "unknown",
+ timeout = tonumber(timeout, 10)
+ }
+
+ local key, val
+ for key, val in tuples:gmatch("(%w+)=(%S+)") do
+ if key == "bytes" or key == "packets" then
+ entry[key] = entry[key] + tonumber(val, 10)
+ elseif key == "src" or key == "dst" or key == "sport" or key == "dport" then
+ if entry[key] == nil then
+ entry[key] = val
+ end
+ elseif val then
+ entry[key] = val
end
end
- end
- elseif fs.access("/proc/net/ip_conntrack", "r") then
- for line in io.lines("/proc/net/ip_conntrack") do
- line = line:match "^(.-( [^ =]+=).-)%2"
- local entry, flags = _parse_mixed_record(line, " +")
- if flags[4] ~= "TIME_WAIT" then
- entry.layer3 = "ipv4"
- entry.layer4 = flags[1]
- for i=1, #entry do
- entry[i] = nil
- end
- if callback then
- callback(entry)
- else
- connt[#connt+1] = entry
- end
+ if callback then
+ callback(entry)
+ else
+ connt[#connt+1] = entry
end
end
- else
- return nil
end
- return connt
+
+ return callback and true or connt
end
function net.devices()
@@ -655,28 +659,3 @@ end
function init.stop(name)
return (init_action("stop", name) == 0)
end
-
-
--- Internal functions
-
-function _parse_mixed_record(cnt, delimiter)
- delimiter = delimiter or " "
- local data = {}
- local flags = {}
-
- 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"]*)"*')
-
- if k then
- if x == "" then
- table.insert(flags, k)
- else
- data[k] = v
- end
- end
- end
- end
-
- return data, flags
-end