WIP: rebase fork onto upstream/main (v1.103.0) #15

Closed
codinget wants to merge 670 commits from webnet into save/webnet-2026-07-29
13 changed files with 180 additions and 83 deletions
Showing only changes of commit 8f210454dd - Show all commits
+1 -1
View File
@@ -919,7 +919,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
tailscale.com/wgengine/filter from tailscale.com/control/controlclient+
tailscale.com/wgengine/filter/filtertype from tailscale.com/types/netmap+
💣 tailscale.com/wgengine/magicsock from tailscale.com/ipn/ipnlocal+
tailscale.com/wgengine/netlog from tailscale.com/wgengine
tailscale.com/wgengine/netlog from tailscale.com/wgengine+
tailscale.com/wgengine/netstack from tailscale.com/tsnet
tailscale.com/wgengine/netstack/gro from tailscale.com/net/tstun+
tailscale.com/wgengine/router from tailscale.com/ipn/ipnlocal+
+1 -1
View File
@@ -194,7 +194,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
tailscale.com/wgengine/filter from tailscale.com/control/controlclient+
tailscale.com/wgengine/filter/filtertype from tailscale.com/types/netmap+
💣 tailscale.com/wgengine/magicsock from tailscale.com/ipn/ipnlocal+
tailscale.com/wgengine/netlog from tailscale.com/wgengine
tailscale.com/wgengine/netlog from tailscale.com/wgengine+
tailscale.com/wgengine/netstack/gro from tailscale.com/net/tstun+
tailscale.com/wgengine/router from tailscale.com/cmd/tailscaled+
tailscale.com/wgengine/wgcfg from tailscale.com/ipn/ipnlocal+
+1 -1
View File
@@ -215,7 +215,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
tailscale.com/wgengine/filter from tailscale.com/control/controlclient+
tailscale.com/wgengine/filter/filtertype from tailscale.com/types/netmap+
💣 tailscale.com/wgengine/magicsock from tailscale.com/ipn/ipnlocal+
tailscale.com/wgengine/netlog from tailscale.com/wgengine
tailscale.com/wgengine/netlog from tailscale.com/wgengine+
tailscale.com/wgengine/netstack/gro from tailscale.com/net/tstun+
tailscale.com/wgengine/router from tailscale.com/cmd/tailscaled+
tailscale.com/wgengine/wgcfg from tailscale.com/ipn/ipnlocal+
+1 -1
View File
@@ -503,7 +503,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
tailscale.com/wgengine/filter from tailscale.com/control/controlclient+
tailscale.com/wgengine/filter/filtertype from tailscale.com/types/netmap+
💣 tailscale.com/wgengine/magicsock from tailscale.com/ipn/ipnlocal+
tailscale.com/wgengine/netlog from tailscale.com/wgengine
tailscale.com/wgengine/netlog from tailscale.com/wgengine+
tailscale.com/wgengine/netstack from tailscale.com/cmd/tailscaled
tailscale.com/wgengine/netstack/gro from tailscale.com/net/tstun+
tailscale.com/wgengine/router from tailscale.com/cmd/tailscaled+
+1 -1
View File
@@ -317,7 +317,7 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
tailscale.com/wgengine/filter from tailscale.com/control/controlclient+
tailscale.com/wgengine/filter/filtertype from tailscale.com/types/netmap+
💣 tailscale.com/wgengine/magicsock from tailscale.com/ipn/ipnlocal+
tailscale.com/wgengine/netlog from tailscale.com/wgengine
tailscale.com/wgengine/netlog from tailscale.com/wgengine+
tailscale.com/wgengine/netstack from tailscale.com/tsnet
tailscale.com/wgengine/netstack/gro from tailscale.com/net/tstun+
tailscale.com/wgengine/router from tailscale.com/ipn/ipnlocal+
+36
View File
@@ -105,6 +105,7 @@ import (
"tailscale.com/wgengine"
"tailscale.com/wgengine/filter"
"tailscale.com/wgengine/magicsock"
"tailscale.com/wgengine/netlog"
"tailscale.com/wgengine/router"
"tailscale.com/wgengine/wgcfg"
"tailscale.com/wgengine/wgcfg/nmcfg"
@@ -645,6 +646,7 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, sys *tsd.System, lo
e.SetPeerByIPPacketFunc(b.lookupPeerByIP)
e.SetPeerSessionStateFunc(b.onPeerWireGuardState)
e.SetNetLogNodeSource(netLogNodeSource{b})
if sys.InitialConfig != nil {
if err := b.initPrefsFromConfig(sys.InitialConfig); err != nil {
@@ -8046,6 +8048,40 @@ func (n noiseRoundTripper) RoundTrip(req *http.Request) (*http.Response, error)
return n.lb.DoNoiseRequest(req)
}
// netLogNodeSource adapts LocalBackend's nodeBackend to [netlog.NodeSource].
// Each method consults [LocalBackend.currentNode] so that profile rotations
// are picked up automatically without re-installing the source.
type netLogNodeSource struct {
b *LocalBackend
}
func (s netLogNodeSource) SelfNode() (tailcfg.NodeView, tailcfg.UserProfileView) {
nb := s.b.currentNode()
self := nb.Self()
if !self.Valid() {
return tailcfg.NodeView{}, tailcfg.UserProfileView{}
}
up, _ := nb.UserByID(self.User())
return self, up
}
func (s netLogNodeSource) NodeByAddr(addr netip.Addr) (_ tailcfg.NodeView, _ tailcfg.UserProfileView, ok bool) {
nb := s.b.currentNode()
nid, ok := nb.NodeByAddr(addr)
if !ok {
return tailcfg.NodeView{}, tailcfg.UserProfileView{}, false
}
nv, ok := nb.NodeByID(nid)
if !ok {
return tailcfg.NodeView{}, tailcfg.UserProfileView{}, false
}
up, _ := nb.UserByID(nv.User())
return nv, up, true
}
// Compile-time assertion that netLogNodeSource implements [netlog.NodeSource].
var _ netlog.NodeSource = netLogNodeSource{}
// ActiveSSHConns returns the number of active SSH connections,
// or 0 if SSH is not linked into the binary or available on the platform.
func (b *LocalBackend) ActiveSSHConns() int {
+2
View File
@@ -47,6 +47,7 @@ import (
"tailscale.com/wgengine"
"tailscale.com/wgengine/filter"
"tailscale.com/wgengine/magicsock"
"tailscale.com/wgengine/netlog"
"tailscale.com/wgengine/router"
"tailscale.com/wgengine/wgcfg"
"tailscale.com/wgengine/wgint"
@@ -1984,6 +1985,7 @@ func (e *mockEngine) InstallCaptureHook(packet.CaptureCallback) {}
func (e *mockEngine) SetPeerByIPPacketFunc(func(netip.Addr) (_ key.NodePublic, ok bool)) {}
func (e *mockEngine) SetPeerSessionStateFunc(func(key.NodePublic, wgengine.PeerWireGuardState)) {
}
func (e *mockEngine) SetNetLogNodeSource(netlog.NodeSource) {}
func (e *mockEngine) Close() {
e.mu.Lock()
+1 -1
View File
@@ -312,7 +312,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
tailscale.com/wgengine/filter from tailscale.com/control/controlclient+
tailscale.com/wgengine/filter/filtertype from tailscale.com/types/netmap+
💣 tailscale.com/wgengine/magicsock from tailscale.com/ipn/ipnlocal+
tailscale.com/wgengine/netlog from tailscale.com/wgengine
tailscale.com/wgengine/netlog from tailscale.com/wgengine+
tailscale.com/wgengine/netstack from tailscale.com/tsnet
tailscale.com/wgengine/netstack/gro from tailscale.com/net/tstun+
tailscale.com/wgengine/router from tailscale.com/ipn/ipnlocal+
+39 -56
View File
@@ -24,12 +24,12 @@ import (
"tailscale.com/net/sockstats"
"tailscale.com/net/tsaddr"
"tailscale.com/syncs"
"tailscale.com/tailcfg"
"tailscale.com/types/ipproto"
"tailscale.com/types/logger"
"tailscale.com/types/logid"
"tailscale.com/types/netlogfunc"
"tailscale.com/types/netlogtype"
"tailscale.com/types/netmap"
"tailscale.com/util/eventbus"
"tailscale.com/util/set"
"tailscale.com/wgengine/router"
@@ -51,6 +51,19 @@ type noopDevice struct{}
func (noopDevice) SetConnectionCounter(netlogfunc.ConnectionCounter) {}
// NodeSource provides node lookups for the network logger.
// Methods may be called concurrently.
type NodeSource interface {
// SelfNode returns the local node and its owning user profile.
// Both views may be invalid if no self node is known yet.
SelfNode() (node tailcfg.NodeView, user tailcfg.UserProfileView)
// NodeByAddr returns the node assigned the given address along with
// its owning user profile.
// ok is false if no node is known to own addr.
NodeByAddr(addr netip.Addr) (node tailcfg.NodeView, user tailcfg.UserProfileView, ok bool)
}
// Logger logs statistics about every connection.
// At present, it only logs connections within a tailscale network.
// By default, exit node traffic is not logged for privacy reasons
@@ -69,10 +82,8 @@ type Logger struct {
recordsChan chan record // set to nil when shutdown
flushTimer *time.Timer // fires when record should flush to recordsChan
// Information about Tailscale nodes.
// These are read-only once updated by ReconfigNetworkMap.
selfNode nodeUser
allNodes map[netip.Addr]nodeUser // includes selfNode; nodeUser values are always valid
// source provides node lookups. Set by Startup, cleared by shutdownLocked.
source NodeSource
// Information about routes.
// These are read-only once updated by ReconfigRoutes.
@@ -115,14 +126,20 @@ var testClient *http.Client
// The sock is used to populated the PhysicalTraffic field in [netlogtype.Message].
//
// The netMon parameter is optional; if non-nil it's used to do faster interface lookups.
func (nl *Logger) Startup(logf logger.Logf, nm *netmap.NetworkMap, nodeLogID, domainLogID logid.PrivateID, tun, sock Device, netMon *netmon.Monitor, health *health.Tracker, bus *eventbus.Bus, logExitFlowEnabledEnabled bool) error {
//
// source provides on-demand node lookups for connections seen by the logger.
// It must be non-nil.
func (nl *Logger) Startup(logf logger.Logf, source NodeSource, nodeLogID, domainLogID logid.PrivateID, tun, sock Device, netMon *netmon.Monitor, health *health.Tracker, bus *eventbus.Bus, logExitFlowEnabledEnabled bool) error {
nl.mu.Lock()
defer nl.mu.Unlock()
if nl.shutdownLocked != nil {
return fmt.Errorf("network logger already running")
}
nl.selfNode, nl.allNodes = makeNodeMaps(nm)
if source == nil {
return fmt.Errorf("network logger requires a non-nil NodeSource")
}
nl.source = source
// Startup a log stream to Tailscale's logging service.
if logf == nil {
@@ -194,8 +211,7 @@ func (nl *Logger) Startup(logf logger.Logf, nm *netmap.NetworkMap, nodeLogID, do
// Purge state.
nl.shutdownLocked = nil
nl.selfNode = nodeUser{}
nl.allNodes = nil
nl.source = nil
nl.routeAddrs = nil
nl.routePrefixes = nil
@@ -249,15 +265,15 @@ func (nl *Logger) addNewVirtConnLocked(c netlogtype.Connection) connType {
var srcNodeLen, dstNodeLen int
srcNode, srcSeen := nl.record.seenNodes[c.Src.Addr()]
if !srcSeen {
srcNode = nl.allNodes[c.Src.Addr()]
if srcNode.Valid() {
if node, user, ok := nl.source.NodeByAddr(c.Src.Addr()); ok {
srcNode = nodeUser{node, user}
srcNodeLen = srcNode.jsonLen()
}
}
dstNode, dstSeen := nl.record.seenNodes[c.Dst.Addr()]
if !dstSeen {
dstNode = nl.allNodes[c.Dst.Addr()]
if dstNode.Valid() {
if node, user, ok := nl.source.NodeByAddr(c.Dst.Addr()); ok {
dstNode = nodeUser{node, user}
dstNodeLen = dstNode.jsonLen()
}
}
@@ -279,12 +295,10 @@ func (nl *Logger) addNewVirtConnLocked(c netlogtype.Connection) connType {
nl.recordLen += netlogtype.MaxConnectionCountsJSONSize + srcNodeLen + dstNodeLen
// Classify the traffic type.
var srcIsSelfNode bool
if nl.selfNode.Valid() {
srcIsSelfNode = nl.selfNode.Addresses().ContainsFunc(func(p netip.Prefix) bool {
return c.Src.Addr() == p.Addr() && p.IsSingleIP()
})
}
// srcNode == self iff NodeByAddr resolved the source to the same node as
// the current record's self.
srcIsSelfNode := srcNode.Valid() && nl.record.selfNode.Valid() &&
srcNode.ID() == nl.record.selfNode.ID()
switch {
case srcIsSelfNode && dstNode.Valid():
return virtualTraffic
@@ -335,8 +349,8 @@ func (nl *Logger) addNewPhysConnLocked(c netlogtype.Connection) {
var srcNodeLen int
srcNode, srcSeen := nl.record.seenNodes[c.Src.Addr()]
if !srcSeen {
srcNode = nl.allNodes[c.Src.Addr()]
if srcNode.Valid() {
if node, user, ok := nl.source.NodeByAddr(c.Src.Addr()); ok {
srcNode = nodeUser{node, user}
srcNodeLen = srcNode.jsonLen()
}
}
@@ -361,14 +375,16 @@ func (nl *Logger) initRecordLocked() {
if nl.recordLen != 0 {
return
}
node, user := nl.source.SelfNode()
self := nodeUser{node, user}
nl.record = record{
selfNode: nl.selfNode,
selfNode: self,
start: time.Now().UTC(),
seenNodes: make(map[netip.Addr]nodeUser),
virtConns: make(map[netlogtype.Connection]countsType),
physConns: make(map[netlogtype.Connection]netlogtype.Counts),
}
nl.recordLen = netlogtype.MinMessageJSONSize + nl.selfNode.jsonLen()
nl.recordLen = netlogtype.MinMessageJSONSize + self.jsonLen()
// Start a time to auto-flush the record.
// Avoid tickers since continually waking up a goroutine
@@ -406,39 +422,6 @@ func (nl *Logger) flushRecordLocked() {
nl.recordLen = 0
}
func makeNodeMaps(nm *netmap.NetworkMap) (selfNode nodeUser, allNodes map[netip.Addr]nodeUser) {
if nm == nil {
return
}
allNodes = make(map[netip.Addr]nodeUser)
if nm.SelfNode.Valid() {
selfNode = nodeUser{nm.SelfNode, nm.UserProfiles[nm.SelfNode.User()]}
for _, addr := range nm.SelfNode.Addresses().All() {
if addr.IsSingleIP() {
allNodes[addr.Addr()] = selfNode
}
}
}
for _, peer := range nm.Peers {
if peer.Valid() {
for _, addr := range peer.Addresses().All() {
if addr.IsSingleIP() {
allNodes[addr.Addr()] = nodeUser{peer, nm.UserProfiles[peer.User()]}
}
}
}
}
return selfNode, allNodes
}
// ReconfigNetworkMap configures the network logger with an updated netmap.
func (nl *Logger) ReconfigNetworkMap(nm *netmap.NetworkMap) {
selfNode, allNodes := makeNodeMaps(nm) // avoid holding lock while making maps
nl.mu.Lock()
nl.selfNode, nl.allNodes = selfNode, allNodes
nl.mu.Unlock()
}
func makeRouteMaps(cfg *router.Config) (addrs set.Set[netip.Addr], prefixes []netip.Prefix) {
addrs = make(set.Set[netip.Addr])
insertPrefixes := func(rs []netip.Prefix) {
+8 -5
View File
@@ -7,8 +7,11 @@ package netlog
type Logger struct{}
func (*Logger) Startup(...any) error { return nil }
func (*Logger) Running() bool { return false }
func (*Logger) Shutdown(any) error { return nil }
func (*Logger) ReconfigNetworkMap(any) {}
func (*Logger) ReconfigRoutes(any) {}
// NodeSource is a stub kept so the omit build does not break consumers that
// reference the type. It has no methods.
type NodeSource any
func (*Logger) Startup(...any) error { return nil }
func (*Logger) Running() bool { return false }
func (*Logger) Shutdown(any) error { return nil }
func (*Logger) ReconfigRoutes(any) {}
+66 -12
View File
@@ -21,22 +21,74 @@ import (
"tailscale.com/types/bools"
"tailscale.com/types/ipproto"
"tailscale.com/types/netlogtype"
"tailscale.com/types/netmap"
"tailscale.com/wgengine/router"
)
// nodeAndUser pairs a [tailcfg.NodeView] with its owning user profile.
type nodeAndUser struct {
node tailcfg.NodeView
user tailcfg.UserProfileView
}
// fakeNodeSource is a [NodeSource] implementation backed by static maps,
// for tests.
type fakeNodeSource struct {
self tailcfg.NodeView
selfUser tailcfg.UserProfileView
byAddr map[netip.Addr]nodeAndUser
}
func (s *fakeNodeSource) SelfNode() (tailcfg.NodeView, tailcfg.UserProfileView) {
return s.self, s.selfUser
}
func (s *fakeNodeSource) NodeByAddr(a netip.Addr) (_ tailcfg.NodeView, _ tailcfg.UserProfileView, ok bool) {
nu, ok := s.byAddr[a]
return nu.node, nu.user, ok
}
// newFakeNodeSource builds a [fakeNodeSource] from a self [tailcfg.NodeView],
// a list of peer [tailcfg.NodeView] values, and a UserProfile map.
// All single-IP addresses on self and the peers are indexed for NodeByAddr.
func newFakeNodeSource(self tailcfg.NodeView, peers []tailcfg.NodeView, users map[tailcfg.UserID]tailcfg.UserProfileView) *fakeNodeSource {
s := &fakeNodeSource{
byAddr: map[netip.Addr]nodeAndUser{},
}
if self.Valid() {
s.self = self
s.selfUser = users[self.User()]
for _, p := range self.Addresses().All() {
if p.IsSingleIP() {
s.byAddr[p.Addr()] = nodeAndUser{self, s.selfUser}
}
}
}
for _, peer := range peers {
if !peer.Valid() {
continue
}
pu := users[peer.User()]
for _, p := range peer.Addresses().All() {
if p.IsSingleIP() {
s.byAddr[p.Addr()] = nodeAndUser{peer, pu}
}
}
}
return s
}
func TestEmbedNodeInfo(t *testing.T) {
// Initialize the logger with a particular view of the netmap.
// Initialize the logger with a particular view of the node state.
var logger Logger
logger.ReconfigNetworkMap(&netmap.NetworkMap{
SelfNode: (&tailcfg.Node{
logger.source = newFakeNodeSource(
(&tailcfg.Node{
StableID: "n123456CNTL",
ID: 123456,
Name: "test.tail123456.ts.net",
Addresses: []netip.Prefix{prefix("100.1.2.3")},
Tags: []string{"tag:foo", "tag:bar"},
}).View(),
Peers: []tailcfg.NodeView{
[]tailcfg.NodeView{
(&tailcfg.Node{
StableID: "n123457CNTL",
ID: 123457,
@@ -52,10 +104,10 @@ func TestEmbedNodeInfo(t *testing.T) {
User: 54321,
}).View(),
},
UserProfiles: map[tailcfg.UserID]tailcfg.UserProfileView{
map[tailcfg.UserID]tailcfg.UserProfileView{
54321: (&tailcfg.UserProfile{ID: 54321, LoginName: "peer@example.com"}).View(),
},
})
)
logger.ReconfigRoutes(&router.Config{
SubnetRoutes: []netip.Prefix{
prefix("172.16.1.1/16"),
@@ -148,6 +200,9 @@ func TestEmbedNodeInfo(t *testing.T) {
func TestUpdateRace(t *testing.T) {
var logger Logger
// Install an empty fake source so NodeByAddr / SelfNode are exercised on
// the lookup path without returning any matches.
logger.source = &fakeNodeSource{}
logger.recordsChan = make(chan record, 1)
go func(recordsChan chan record) {
for range recordsChan {
@@ -167,11 +222,6 @@ func TestUpdateRace(t *testing.T) {
}
}
})
group.Go(func() {
for range 1000 {
logger.ReconfigNetworkMap(new(netmap.NetworkMap))
}
})
group.Go(func() {
for range 1000 {
logger.ReconfigRoutes(new(router.Config))
@@ -194,6 +244,7 @@ func randAddrPort() netip.AddrPort {
func TestAutoFlushMaxConns(t *testing.T) {
var logger Logger
logger.source = &fakeNodeSource{}
logger.recordsChan = make(chan record, 1)
for i := 0; len(logger.recordsChan) == 0; i++ {
logger.updateVirtConn(0, netip.AddrPortFrom(netip.Addr{}, uint16(i)), netip.AddrPort{}, 1, 1, false)
@@ -206,6 +257,7 @@ func TestAutoFlushMaxConns(t *testing.T) {
func TestAutoFlushTimeout(t *testing.T) {
var logger Logger
logger.source = &fakeNodeSource{}
logger.recordsChan = make(chan record, 1)
synctest.Test(t, func(t *testing.T) {
logger.updateVirtConn(0, netip.AddrPort{}, netip.AddrPort{}, 1, 1, false)
@@ -222,6 +274,7 @@ func TestAutoFlushTimeout(t *testing.T) {
func BenchmarkUpdateSameConn(b *testing.B) {
var logger Logger
logger.source = &fakeNodeSource{}
b.ReportAllocs()
for range b.N {
logger.updateVirtConn(0, netip.AddrPort{}, netip.AddrPort{}, 1, 1, false)
@@ -230,6 +283,7 @@ func BenchmarkUpdateSameConn(b *testing.B) {
func BenchmarkUpdateNewConns(b *testing.B) {
var logger Logger
logger.source = &fakeNodeSource{}
b.ReportAllocs()
for i := range b.N {
logger.updateVirtConn(0, netip.AddrPortFrom(netip.Addr{}, uint16(i)), netip.AddrPort{}, 1, 1, false)
+15 -4
View File
@@ -157,6 +157,11 @@ type userspaceEngine struct {
// networkLogger logs statistics about network connections.
networkLogger netlog.Logger
// netLogSource is the [netlog.NodeSource] installed via
// [Engine.SetNetLogNodeSource]; it is read when starting up the network
// logger from inside Reconfig. It may be nil if no source was installed.
netLogSource syncs.AtomicValue[netlog.NodeSource]
// tsmpLearnedDisco tracks per node key if a peer disco key was learned via TSMP.
// wgLock must be held when using this map.
tsmpLearnedDisco map[key.NodePublic]key.DiscoPublic
@@ -735,6 +740,12 @@ func (e *userspaceEngine) SetPeerSessionStateFunc(fn func(key.NodePublic, PeerWi
})
}
// SetNetLogNodeSource installs the [netlog.NodeSource] used by the engine's
// network logger.
func (e *userspaceEngine) SetNetLogNodeSource(src netlog.NodeSource) {
e.netLogSource.Store(src)
}
func peerWireGuardStateFromDevice(state device.PeerSessionState) PeerWireGuardState {
switch state {
case device.PeerSessionNone:
@@ -969,7 +980,10 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config,
tid := cfg.NetworkLogging.DomainID
logExitFlowEnabled := cfg.NetworkLogging.LogExitFlowEnabled
e.logf("wgengine: Reconfig: starting up network logger (node:%s tailnet:%s)", nid.Public(), tid.Public())
if err := e.networkLogger.Startup(e.logf, nm, nid, tid, e.tundev, e.magicConn, e.netMon, e.health, e.eventBus, logExitFlowEnabled); err != nil {
src := e.netLogSource.Load()
if src == nil {
e.logf("wgengine: Reconfig: no NodeSource installed; network logger not started")
} else if err := e.networkLogger.Startup(e.logf, src, nid, tid, e.tundev, e.magicConn, e.netMon, e.health, e.eventBus, logExitFlowEnabled); err != nil {
e.logf("wgengine: Reconfig: error starting up network logger: %v", err)
}
e.networkLogger.ReconfigRoutes(routerCfg)
@@ -1309,9 +1323,6 @@ func (e *userspaceEngine) SetNetworkMap(nm *netmap.NetworkMap) {
curUDP, curTCP)
e.tundev.ApplyGROKnobs(e.controlKnobs)
}
if e.networkLogger.Running() {
e.networkLogger.ReconfigNetworkMap(nm)
}
}
func (e *userspaceEngine) UpdateStatus(sb *ipnstate.StatusBuilder) {
+8
View File
@@ -16,6 +16,7 @@ import (
"tailscale.com/types/key"
"tailscale.com/types/netmap"
"tailscale.com/wgengine/filter"
"tailscale.com/wgengine/netlog"
"tailscale.com/wgengine/router"
"tailscale.com/wgengine/wgcfg"
"tailscale.com/wgengine/wgint"
@@ -164,6 +165,13 @@ type Engine interface {
// look up which peer should handle an outbound packet by destination IP.
SetPeerByIPPacketFunc(func(netip.Addr) (_ key.NodePublic, ok bool))
// SetNetLogNodeSource installs the [netlog.NodeSource] used by the engine's
// network logger to look up Tailscale node info on demand.
//
// It is expected to be called once during LocalBackend construction,
// before any [Engine.Reconfig] call that starts up the network logger.
SetNetLogNodeSource(netlog.NodeSource)
// SetPeerSessionStateFunc installs a callback used to observe WireGuard
// peer session state transitions.
//