You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(netwatch): reconcile interface state periodically
The netmon actor only re-enumerated interfaces in response to events
from the OS route monitor (or a detected wall-time jump). Those events
can be missed or stop entirely with no error:
- Routing sockets are best-effort. On receive-buffer overflow the
kernel drops the overflowing RTM_* messages, and on macOS (XNU
raw_input/sbappendaddr) the drop is silent: so_error is not set and
there is no SO_RERROR option, so the reader cannot tell a message was
lost. A change can be missed on an otherwise-working socket.
- In production we additionally observed the macOS AF_ROUTE read stop
delivering events entirely (no further reads, no error) for the rest
of the process lifetime. macOS PF_ROUTE is independently documented
to be unreliable (it can fail to emit some interface-change events at
all), and the socket is read through a tokio UnixStream over a
SOCK_RAW fd, so a lost edge-triggered readiness wakeup is also
possible; the exact cause was not determined and the fix does not
depend on it.
With no fallback the actor never recomputes State, so the interface
state freezes at whatever it was when the last event was processed. In
practice a brief interface change (a DHCP renew or link blip) made an
endpoint permanently lose an interface and its addresses even though
the interface was up and its address returned immediately; a fresh
enumeration reflected the correct state the whole time. This matches
iroh#3449.
Re-enumerate on the existing periodic wake-up in addition to wall-time
jumps, so a missed or absent event self-heals within one interval (15s
on desktop). handle_potential_change already diffs against the current
state, so this only emits a change when something actually changed.
This is the same event-plus-periodic-reconcile pattern Tailscale uses
(15s pollWallTimeInterval backstop) and complements the existing
error-path socket rebind (net-tools#105) by covering the no-error case.
The interface enumeration is made injectable and the poll interval
configurable so the recovery path can be tested deterministically
without a route monitor. Adds a regression test that drives the actor
with no route-monitor events and asserts the state still converges to
a changed enumeration.
0 commit comments