ipn/ipnlocal: add netmap mutations to the ipn bus (#19120)

ipn/local: add netmap mutations to the ipn bus

updates tailscale/tailscale#1909

This adds a new new NotifyWatchOpt that allows watchers to
receive PeerChange events (derived from node mutations)
on the IPN bus in lieu of a complete netmap.  We'll continue
to send the full netmap for any map response that includes it,
but for  mutations, sending PeerChange events gives the client
the option to manage it's own models more selectively and cuts
way down on json serialization overhead.

On chatty tailnets, this will vastly reduce the amount of
chatter on the bus.

This change should be backwards compatible, it is
purely additive.  Clients that subscribe to NotifyNetmap will
get the full netmap for every delta.  New clients can
omit that and instead opt into NotifyPeerChanges.

Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
This commit is contained in:
Jonathan Nobels
2026-04-09 15:45:41 -04:00
committed by GitHub
parent 6b7caaf7ee
commit 03c3551ee5
4 changed files with 242 additions and 13 deletions
+17 -2
View File
@@ -87,6 +87,11 @@ const (
NotifyInitialSuggestedExitNode NotifyWatchOpt = 1 << 10 // if set, the first Notify message (sent immediately) will contain the current SuggestedExitNode if available
NotifyInitialClientVersion NotifyWatchOpt = 1 << 11 // if set, the first Notify message (sent immediately) will contain the current ClientVersion if available and if update checks are enabled
// NotifyPeerChanges, if set, causes netmap delta updates to be sent as [tailcfg.PeerChange] rather than a full NetMap.
// Full netmap responses from the control plane are still sent as a full NetMap. PeerChanges are only sent to sessions
// that have opted in to this mode.
NotifyPeerChanges NotifyWatchOpt = 1 << 12
)
// Notify is a communication from a backend (e.g. tailscaled) to a frontend
@@ -112,8 +117,15 @@ type Notify struct {
State *State // if non-nil, the new or current IPN state
Prefs *PrefsView // if non-nil && Valid, the new or current preferences
NetMap *netmap.NetworkMap // if non-nil, the new or current netmap
Engine *EngineStatus // if non-nil, the new or current wireguard stats
BrowseToURL *string // if non-nil, UI should open a browser right now
// PeerChanges, if non-nil, is a list of [tailcfg.PeerChange] that have occurred since the last
// full netmap update. This is sent in lieu of a full NetMap when [NotifyPeerChanges] is set in
// the session's mask and a netmap update is derived from an incremental MapResponse.
// Full MapResponse updates from the control plane are sent as a full NetMap.
PeerChanges []*tailcfg.PeerChange `json:",omitzero"`
Engine *EngineStatus // if non-nil, the new or current wireguard stats
BrowseToURL *string // if non-nil, UI should open a browser right now
// FilesWaiting if non-nil means that files are buffered in
// the Tailscale daemon and ready for local transfer to the
@@ -184,6 +196,9 @@ func (n Notify) String() string {
if n.NetMap != nil {
sb.WriteString("NetMap{...} ")
}
if n.PeerChanges != nil {
fmt.Fprintf(&sb, "PeerChanges(%d) ", len(n.PeerChanges))
}
if n.Engine != nil {
fmt.Fprintf(&sb, "wg=%v ", *n.Engine)
}