From 8ecf7870945dd6d0ffd7493c7ee65d743a9c6002 Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Tue, 2 Jun 2026 21:25:23 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20reordenar=20pesta=C3=B1as=20(Sistema=20?= =?UTF-8?q?por=20defecto)=20+=20stats=20de=20red?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Orden de pestañas: Sistema, Red, Docker. Sistema es la pestaña por defecto al arrancar. - Pestaña Red, bajo el gráfico: - Paquetes/s por protocolo (TCP/UDP/ICMP, in/out) calculados como delta de los contadores de /proc/net/snmp. - Top 4 hosts remotos por número de conexiones establecidas (ss), excluyendo loopback. - Botones de la pestaña Red reubicados (BTN_Y) y el hook de ratón ajustado al nuevo índice de pestaña. --- lua/widget.lua | 128 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 109 insertions(+), 19 deletions(-) diff --git a/lua/widget.lua b/lua/widget.lua index 1902d4c..1a58de6 100644 --- a/lua/widget.lua +++ b/lua/widget.lua @@ -27,7 +27,7 @@ local H = 545 local TAB_TOP = 4 local TAB_H = 24 local BTN_H = 26 -local BTN_Y = 242 -- fila de botones de la pestaña Red +local BTN_Y = 322 -- fila de botones de la pestaña Red -- Interfaz de red a monitorizar (enp5s0 es la fisica activa) ------------------ local NIF = "enp5s0" @@ -35,8 +35,8 @@ local NIF = "enp5s0" -- Helper de metricas (temps + GPU), portado del widget previo ----------------- local MET = os.getenv("HOME") .. "/.config/conky/conky_widget/metric.sh" --- Pestañas ------------------------------------------------------------------- -local TABS = { "Red", "Sistema", "Docker" } +-- Pestañas (Sistema por defecto) --------------------------------------------- +local TABS = { "Sistema", "Red", "Docker" } local current_tab = 1 -- Botones de la pestaña Red. bin se comprueba antes de lanzar; si falta, @@ -121,6 +121,70 @@ local function rate_kib(s) else return n / 1024 end end +-- Paquetes por intervalo y protocolo: delta de los contadores de /proc/net/snmp. +-- g_proto guarda los paquetes del ultimo intervalo (≈ por segundo con +-- update_interval=1). Se actualiza una vez por frame desde conky_draw. +local g_proto = { tcp_in = 0, tcp_out = 0, udp_in = 0, udp_out = 0, icmp_in = 0, icmp_out = 0 } +local snmp_prev = nil + +local function update_proto() + local f = io.open("/proc/net/snmp", "r") + if not f then return end + local hdr, cur = {}, {} + for line in f:lines() do + local proto, rest = line:match("^(%w+):%s+(.+)$") + if proto then + if hdr[proto] == nil then + local cols, i = {}, 0 + for tok in rest:gmatch("%S+") do i = i + 1; cols[tok] = i end + hdr[proto] = cols + else + local vals = {} + for tok in rest:gmatch("%S+") do vals[#vals + 1] = tok end + cur[proto] = vals + end + end + end + f:close() + local function get(proto, col) + local cols = hdr[proto]; local vals = cur[proto] + if not cols or not vals then return 0 end + local idx = cols[col]; if not idx then return 0 end + return tonumber(vals[idx]) or 0 + end + local c = { + tcp_in = get("Tcp", "InSegs"), tcp_out = get("Tcp", "OutSegs"), + udp_in = get("Udp", "InDatagrams"), udp_out = get("Udp", "OutDatagrams"), + icmp_in = get("Icmp", "InMsgs"), icmp_out = get("Icmp", "OutMsgs"), + } + if snmp_prev then + for k, v in pairs(c) do + local d = v - (snmp_prev[k] or v) + g_proto[k] = (d < 0) and 0 or d + end + end + snmp_prev = c +end + +-- Top hosts remotos por numero de conexiones TCP/UDP establecidas (ss) -------- +local function top_remotes() + local out = str("${execi 3 ss -tun state established 2>/dev/null}") + local counts = {} + for line in out:gmatch("[^\n]+") do + if not line:match("^Netid") and not line:match("^State") then + local ip = line:match("([%d%.]+):%d+%s*$") or line:match("%[([%x:]+)%]:%d+%s*$") + -- Excluir loopback: no son hosts "remotos" + if ip and not ip:match("^127%.") and ip ~= "::1" then + counts[ip] = (counts[ip] or 0) + 1 + end + end + end + local arr = {} + for ip, c in pairs(counts) do arr[#arr + 1] = { ip = ip, c = c } end + table.sort(arr, function(a, b) return a.c > b.c end) + return arr +end + -- Helpers de dibujo ---------------------------------------------------------- local function setcol(cr, c, a) cairo_set_source_rgba(cr, c[1], c[2], c[3], a or 1.0) @@ -208,27 +272,52 @@ end -- Panel: Red ----------------------------------------------------------------- local function draw_red(cr) - local y = 50 - text(cr, 12, y, "Interfaz " .. NIF, COL.dim, 11); y = y + 22 + local y = 46 + text(cr, 12, y + 10, "Interfaz " .. NIF, COL.dim, 11); y = y + 20 - text(cr, 12, y, "Down", COL.down, 12) - text(cr, 90, y, str("${downspeed " .. NIF .. "}"), COL.text, 13, true); y = y + 20 - text(cr, 12, y, "Up", COL.up, 12) - text(cr, 90, y, str("${upspeed " .. NIF .. "}"), COL.text, 13, true); y = y + 24 + text(cr, 12, y + 10, "Down", COL.down, 12) + text(cr, 90, y + 10, str("${downspeed " .. NIF .. "}"), COL.text, 13, true); y = y + 18 + text(cr, 12, y + 10, "Up", COL.up, 12) + text(cr, 90, y + 10, str("${upspeed " .. NIF .. "}"), COL.text, 13, true); y = y + 20 - graph(cr, 12, y, W - 24, 70, { + graph(cr, 12, y, W - 24, 56, { { data = hist.down, c = COL.down }, { data = hist.up, c = COL.up }, }) - y = y + 78 + y = y + 62 + + -- Paquetes por segundo y protocolo (delta de /proc/net/snmp) + text(cr, 12, y + 10, "PAQUETES/s", COL.snow, 10, true) + rtext(cr, W - 10, y + 10, "in / out", COL.dim, 9); y = y + 15 + local function prow(label, c, ipkt, opkt) + text(cr, 14, y + 10, label, c, 10) + rtext(cr, W - 10, y + 10, ipkt .. " / " .. opkt, COL.text, 10); y = y + 13 + end + prow("TCP", COL.cyan, g_proto.tcp_in, g_proto.tcp_out) + prow("UDP", COL.green, g_proto.udp_in, g_proto.udp_out) + prow("ICMP", COL.yellow, g_proto.icmp_in, g_proto.icmp_out) + y = y + 4 + + -- Top hosts remotos por numero de conexiones establecidas + text(cr, 12, y + 10, "TOP REMOTOS", COL.snow, 10, true) + rtext(cr, W - 10, y + 10, "conex.", COL.dim, 9); y = y + 15 + local arr = top_remotes() + if #arr == 0 then + text(cr, 14, y + 10, "sin conexiones establecidas", COL.dim, 9); y = y + 13 + else + for i = 1, math.min(4, #arr) do + text(cr, 14, y + 10, arr[i].ip, COL.text, 10) + rtext(cr, W - 10, y + 10, tostring(arr[i].c), COL.green, 10); y = y + 13 + end + end + y = y + 4 local conns = str("${execi 2 ss -tun state established 2>/dev/null | tail -n +2 | wc -l}") - text(cr, 12, y, "Conexiones activas: " .. conns, COL.text, 11); y = y + 16 - text(cr, 12, y, "Total ↓ " .. str("${totaldown " .. NIF .. "}") .. - " ↑ " .. str("${totalup " .. NIF .. "}"), COL.dim, 10) + text(cr, 12, y + 10, "Conexiones activas: " .. conns, COL.text, 10); y = y + 13 + text(cr, 12, y + 9, "Total ↓ " .. str("${totaldown " .. NIF .. "}") .. + " ↑ " .. str("${totalup " .. NIF .. "}"), COL.dim, 9) draw_buttons(cr) - text(cr, 12, BTN_Y + BTN_H + 18, "Wireshark abre el buffer de captura mas reciente.", COL.dim, 9) end @@ -334,14 +423,15 @@ function conky_draw() push(hist.diskio, rate_kib(str("${diskio}"))) push(hist.down, num("${downspeedf " .. NIF .. "}")) push(hist.up, num("${upspeedf " .. NIF .. "}")) + update_proto() setcol(cr, COL.bg, 0.86); rrect(cr, 0, 0, W, H, 10); cairo_fill(cr) draw_tabs(cr) if current_tab == 1 then - draw_red(cr) - elseif current_tab == 2 then draw_sys(cr) + elseif current_tab == 2 then + draw_red(cr) else draw_docker(cr) end @@ -376,8 +466,8 @@ function conky_mouse(event) return end - -- Botones de la pestaña Red - if current_tab == 1 and y >= BTN_Y and y <= BTN_Y + BTN_H then + -- Botones de la pestaña Red (ahora es la pestaña 2) + if current_tab == 2 and y >= BTN_Y and y <= BTN_Y + BTN_H then local bw = (W - 24) / 3 for i = 1, 3 do local bx = 8 + (i - 1) * (bw + 4)