From: Paul Donald Date: Mon, 8 Dec 2025 14:02:53 +0000 (+0100) Subject: luci-mod-status: add odhcp6c stats to network include X-Git-Url: http://git.openwrt.org/?a=commitdiff_plain;h=HEAD;p=project%2Fluci.git luci-mod-status: add odhcp6c stats to network include Provides odhcp6c statistics of DHCPv6 request and response traffic, for dhcpv6 client interfaces only. This appends to IPv6 Upstream network interface boxes: DHCPv6 solicit: x pkts DHCPv6 advertise: x pkts DHCPv6 request: x pkts DHCPv6 confirm: x pkts ... Signed-off-by: Paul Donald --- diff --git a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js index 6c06c4905c..621cdab26d 100644 --- a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js +++ b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js @@ -2,6 +2,16 @@ 'require baseclass'; 'require fs'; 'require network'; +'require rpc'; + + +/* returns per odhcp6c active interface JSON like: +{"result":{"eth1":{"dhcp_solicit":3,"dhcp_advertise":3,"dhcp_request":3,...}}} */ +const callOdhcp6cStats = rpc.declare({ + object: 'luci', + method: 'getOdhcp6cStats', + expect: { '': {} }, +}); function progressbar(value, max, byte) { const vn = parseInt(value) || 0; @@ -16,7 +26,7 @@ function progressbar(value, max, byte) { }, E('div', { 'style': 'width:%.2f%%'.format(pc) })); } -function renderbox(ifc, ipv6) { +function renderbox(ifc, ipv6, dhcpv6_stats) { const dev = ifc.getL3Device(); const active = (dev && ifc.getProtocol() != 'none'); const addrs = (ipv6 ? ifc.getIP6Addrs() : ifc.getIPAddrs()) || []; @@ -28,6 +38,16 @@ function renderbox(ifc, ipv6) { return Array.isArray(array) ? array.flatMap((item) => [label, item]) : [label, null]; } + function addDhcpv6Stats() { + if (ipv6 && ifc.getProtocol() === 'dhcpv6' && dhcpv6_stats && dhcpv6_stats[dev.device]) { + const arr = []; + for (const [pkt_type, count] of Object.entries(dhcpv6_stats[dev.device])) + arr.push(pkt_type.replace('dhcp_', _('DHCPv6') + ' '), `${count} ${_('pkts', 'packets, abbreviated')}`); + return arr; + } + return ['', null]; + } + return E('div', { class: 'ifacebox' }, [ E('div', { class: 'ifacebox-head center ' + (active ? 'active' : '') }, E('strong', ipv6 ? _('IPv6 Upstream') : _('IPv4 Upstream'))), @@ -40,6 +60,7 @@ function renderbox(ifc, ipv6) { ...addEntries(_('DNS'), dnssrv), _('Expires'), (expires != null && expires > -1) ? '%t'.format(expires) : null, _('Connected'), (uptime > 0) ? '%t'.format(uptime) : null, + ...addDhcpv6Stats(), ]), E('div', {}, renderBadge( L.resource('icons/%s.svg').format(dev ? dev.getType() : 'ethernet_disabled'), null, @@ -59,10 +80,11 @@ return baseclass.extend({ fs.trimmed('/proc/sys/net/netfilter/nf_conntrack_max'), network.getWANNetworks(), network.getWAN6Networks(), + callOdhcp6cStats(), ]); }, - render([ct_count, ct_max, wan_nets, wan6_nets]) { + render([ct_count, ct_max, wan_nets, wan6_nets, dhcpv6_stats]) { const fields = [ { label: _('Active Connections'), value: ct_max ? ct_count : null } @@ -85,7 +107,7 @@ return baseclass.extend({ netstatus.appendChild(renderbox(wan_net, false)); for (const wan6_net of wan6_nets) - netstatus.appendChild(renderbox(wan6_net, true)); + netstatus.appendChild(renderbox(wan6_net, true, dhcpv6_stats?.result)); return E([ netstatus, diff --git a/modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status-index.json b/modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status-index.json index f2253f39c0..b3f2cefb4b 100644 --- a/modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status-index.json +++ b/modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status-index.json @@ -9,7 +9,7 @@ "/www/luci-static/resources/view/status/include": [ "list" ] }, "ubus": { - "luci": [ "getVersion", "getUnixtime" ], + "luci": [ "getVersion", "getUnixtime", "getOdhcp6cStats" ], "file": [ "list", "read" ], "system": [ "board", "info" ] }