luci-mod-status: add odhcp6c stats to network include
authorPaul Donald <[email protected]>
Mon, 8 Dec 2025 14:02:53 +0000 (15:02 +0100)
committerPaul Donald <[email protected]>
Mon, 8 Dec 2025 14:02:53 +0000 (15:02 +0100)
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 <[email protected]>
modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js
modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status-index.json

index 6c06c4905cc7ca2607ec85759e6f453be0501570..621cdab26dfb131ae30c5a960c0d35ba24045ee8 100644 (file)
@@ -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,
index f2253f39c0ec2cf725d06349b4c7cd386d9add26..b3f2cefb4b30cc14afa52804deed69c9105640dc 100644 (file)
@@ -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" ]
                        }