From b61aab069d13670dce8eb06cb92a5de70061bd6f Mon Sep 17 00:00:00 2001 From: Sergey Nazaryev Date: Wed, 7 Nov 2018 02:09:36 +0000 Subject: =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20=D0=BD=D0=BE?= =?UTF-8?q?=D1=80=D0=BC=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20=D0=B2=D1=8B?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=20=D0=B4=D0=BB=D1=8F=20ifstat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 29 ++++++++----- ifstat.lua | 134 ++++++++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 124 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index dd305bb..be91236 100644 --- a/README.md +++ b/README.md @@ -111,17 +111,24 @@ eBPF вешается на XDP-хук (eXpress Data Path), что позволя ## Пример вывода утилиты ifstat ``` -filter0 -======= -≤ 64: 36 -65 .. 127: 18 -128 .. 255: 10 -256 .. 511: 13 -512 .. 1023: 3 -1024 .. 1512: 10 -≥ 1513: 0 -Bytes received: 27100 -Packetes received: 90 +------------------------------------------------------------------------------- +# <= 64 65-127 128-255 256-511 512-1023 1024-151 >= 1513 Bytes Packets +------------------------------------------------------------------------------- +0 0 0 202 0 0 2 0 31708 204 +Δ 0 0 0 0 0 0 0 0 0 +------------------------------------------------------------------------------- +1 0 0 202 0 0 2 0 31708 204 +Δ 0 0 0 0 0 0 0 0 0 +------------------------------------------------------------------------------- +2 0 0 202 0 0 2 0 31708 204 +Δ 0 0 0 0 0 0 0 0 0 +------------------------------------------------------------------------------- +3 0 0 202 0 0 2 0 31708 204 +Δ 0 0 0 0 0 0 0 0 0 +------------------------------------------------------------------------------- +4 0 0 202 0 0 2 0 31708 204 +Δ 0 0 0 0 0 0 0 0 0 +------------------------------------------------------------------------------- ``` [ubus]: https://oldwiki.archive.openwrt.org/doc/techref/ubus diff --git a/ifstat.lua b/ifstat.lua index a5b34a3..1431acf 100755 --- a/ifstat.lua +++ b/ifstat.lua @@ -1,45 +1,123 @@ -#!/usr/bin/env lua5.1 +#!/usr/bin/env luajit require "ubus" require "uloop" -uloop.init() +local filter_prev_value = {} +local printed_lines_count = 0 -local conn = ubus.connect() -if not conn then - error("Failed to connect to ubus") +function replace_char(str, pos, r) + return str:sub(1, pos-1) .. r .. str:sub(pos+1) +end + +function print_line(line) + io.stdout:write("\27[K") + print(line) + printed_lines_count = printed_lines_count + 1 +end + +function clear_screen() + if printed_lines_count > 0 then + io.stdout:write("\27[" .. tostring( printed_lines_count ) .. "A") + printed_lines_count = 0 + end +end + +function fit_value_in_column(value, width) + local value_str = string.format("%d", value) + if #value_str > width then + return string.format("%." .. tostring(width-6) .."e ", value) + else + return string.format("%" .. tostring(width) .."s ", value_str) + end end function print_ifstat_data(data) + local filter_stat = {} local filter_data_columns = { - {"pkts_64", "≤ 64"}, - {"pkts_65_127", "65 .. 127"}, - {"pkts_128_255", "128 .. 255"}, - {"pkts_256_511", "256 .. 511"}, - {"pkts_512_1023", "512 .. 1023"}, - {"pkts_1024_1512", "1024 .. 1512"}, - {"pkts_1513", "≥ 1513"}, - {"pkts_bytes", "Bytes received"}, - {"pkts_cnt", "Packetes received"} + {key="filter_num", title="#", width=1}, + {key="pkts_64", title="<= 64", width=7}, + {key="pkts_65_127", title="65-127", width=7}, + {key="pkts_128_255", title="128-255", width=7}, + {key="pkts_256_511", title="256-511", width=7}, + {key="pkts_512_1023", title="512-1023", width=8}, + {key="pkts_1024_1512", title="1024-1512", width=8}, + {key="pkts_1513", title=">= 1513", width=7}, + {key="pkts_bytes", title="Bytes", width=10}, + {key="pkts_cnt", title="Packets", width=8} } for filter_name, filter_data in pairs(data) do - print(filter_name) - print("=======") - for idx, pair in ipairs(filter_data_columns) do - local key = pair[1] - local title = pair[2] - print(title .. ": " .. filter_data[key]) + local filter_num = filter_name:gsub("filter","") + + -- В Lua массивы индексируются с единицы, а приходящие от демона + -- фильтры индексируются с 0 + filter_num = tonumber(filter_num) + 1 + + if filter_prev_value[filter_num] == nil then + filter_prev_value[filter_num] = {} + end + + -- Отображать в таблице нужно настоящие индексы фильтров, а не + -- увеличенные на 1 + filter_data["filter_num"] = filter_num - 1 + filter_stat[filter_num] = { absolute = '', relative = '' } + + for idx, column in ipairs(filter_data_columns) do + local value = tonumber(filter_data[column.key]) + local delta = value - (filter_prev_value[filter_num][column.key] or 0) + + filter_prev_value[filter_num][column.key] = value + filter_stat[filter_num].absolute = filter_stat[filter_num].absolute .. fit_value_in_column(value, column.width) + filter_stat[filter_num].relative = filter_stat[filter_num].relative .. fit_value_in_column(delta, column.width) + + if column.key == 'filter_num' then + filter_stat[filter_num].relative = string.format("%" .. column.width+1 .. "s ", 'Δ') + end end - print("") + end + + clear_screen() + + local header = '' + for idx, column in ipairs(filter_data_columns) do + local title = string.format("%" .. tostring(column.width) .. "s ", column.title) + title = replace_char(title:sub(1, column.width), column.width+1, ' ') + header = header .. title + end + header = header:sub(1, #header-1) + + local frame = '' + for i=1,#header do + frame = frame .. '-' + end + print_line(frame) + print_line(header) + print_line(frame) + + for idx, stat in ipairs(filter_stat) do + print_line(stat.absolute) + print_line(stat.relative) + print_line(frame) end end -local sub = { - notify = function( msg, name ) - print_ifstat_data(msg) - end, -} +function main() + uloop.init() + + local conn = ubus.connect() + if not conn then + error("Failed to connect to ubus") + end + + local sub = { + notify = function( msg, name ) + print_ifstat_data(msg) + end, + } + + conn:subscribe("ifstat", sub) + uloop.run() +end -conn:subscribe("ifstat", sub) -uloop.run() +main() -- cgit v1.1