Expand description
Determinize the statistics counters carried by NETLINK_ROUTE link dumps.
A guest that resolves a hostname or enumerates interfaces reaches
NETLINK_ROUTE through glibc, which issues RTM_GETLINK and receives one
RTM_NEWLINK message per interface. Those messages carry LIVE COUNTERS that
advance continuously on a running host, so two executions of the same guest
milliseconds apart receive byte-different payloads of IDENTICAL LENGTH.
MEASURED NATIVELY, outside Hermit, on two consecutive RTM_GETLINK dumps:
both replies were 3060 bytes, 47 bytes differed, and of the first twelve
64-bit fields that moved, TWELVE INCREASED AND ZERO DECREASED โ monotonic
counters. Every differing byte was attributed to an attribute; none fell
outside one:
AF_SPEC -> AF_INET6 -> IFLA_INET6_STATS 30 bytes
AF_SPEC -> AF_INET6 -> IFLA_INET6_CACHEINFO 4 bytes (guest payload only)
IFLA_STATS64 8 bytes
IFLA_STATS 8 bytesTHE ATTRIBUTION IS WHY THIS ZEROES THREE ATTRIBUTES RATHER THAN ONE. The
obvious fix โ zero IFLA_STATS64 โ addresses 8 of 47 differing bytes and
leaves the guest still diverging on the other 39. The nested IPv6 SNMP block
inside AF_SPEC is the LARGEST contributor and is easy to miss because it is
two levels of nesting below the message.
Nothing else in the dump moved: no timestamps, no sequence numbers, no addresses, no interface indices. Zeroing exactly these three makes the reply byte-stable without touching anything a guest legitimately reads for identity or topology.
The counters are ZEROED rather than virtualized to advance. Freezing them is
the same choice crate::sock_diag already makes for socket inodes, and a
guest under Hermit has no deterministic clock against which advancing
counters would mean anything. A guest that reads interface statistics sees
zeros; that is a deliberate and stated consequence.
Functionsยง
- sanitize_
route_ link_ stats - Zero the live counters in a
NETLINK_ROUTEreply, in place.