wgengine/{magicsock,userspace,router}: move portupdates to the eventbus (#17423)

Also pull out interface method only needed in Linux.

Instead of having userspace do the call into the router, just let the
router pick up the change itself.

Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
This commit is contained in:
Claus Lensbøl
2025-10-07 09:30:27 -04:00
committed by GitHub
parent eabc62a9dd
commit 63f7a400a8
10 changed files with 83 additions and 122 deletions
+8 -11
View File
@@ -67,6 +67,7 @@ import (
"tailscale.com/util/testenv"
"tailscale.com/util/usermetric"
"tailscale.com/wgengine/filter"
"tailscale.com/wgengine/router"
"tailscale.com/wgengine/wgint"
)
@@ -179,6 +180,7 @@ type Conn struct {
// config changes between magicsock and wireguard.
syncPub *eventbus.Publisher[syncPoint]
allocRelayEndpointPub *eventbus.Publisher[UDPRelayAllocReq]
portUpdatePub *eventbus.Publisher[router.PortUpdate]
// pconn4 and pconn6 are the underlying UDP sockets used to
// send/receive packets for wireguard and other magicsock
@@ -393,10 +395,6 @@ type Conn struct {
// wgPinger is the WireGuard only pinger used for latency measurements.
wgPinger lazy.SyncValue[*ping.Pinger]
// onPortUpdate is called with the new port when magicsock rebinds to
// a new port.
onPortUpdate func(port uint16, network string)
// getPeerByKey optionally specifies a function to look up a peer's
// wireguard state by its public key. If nil, it's not used.
getPeerByKey func(key.NodePublic) (_ wgint.Peer, ok bool)
@@ -492,10 +490,6 @@ type Options struct {
// If nil, they're ignored and not updated.
ControlKnobs *controlknobs.Knobs
// OnPortUpdate is called with the new port when magicsock rebinds to
// a new port.
OnPortUpdate func(port uint16, network string)
// PeerByKeyFunc optionally specifies a function to look up a peer's
// WireGuard state by its public key. If nil, it's not used.
// In regular use, this will be wgengine.(*userspaceEngine).PeerByKey.
@@ -735,6 +729,7 @@ func NewConn(opts Options) (*Conn, error) {
cli := c.eventBus.Client("magicsock.Conn")
c.syncPub = eventbus.Publish[syncPoint](cli)
c.allocRelayEndpointPub = eventbus.Publish[UDPRelayAllocReq](cli)
c.portUpdatePub = eventbus.Publish[router.PortUpdate](cli)
c.eventSubs = cli.Monitor(c.consumeEventbusTopics(cli))
c.connCtx, c.connCtxCancel = context.WithCancel(context.Background())
@@ -759,7 +754,6 @@ func NewConn(opts Options) (*Conn, error) {
c.netMon = opts.NetMon
c.health = opts.HealthTracker
c.onPortUpdate = opts.OnPortUpdate
c.getPeerByKey = opts.PeerByKeyFunc
if err := c.rebind(keepCurrentPort); err != nil {
@@ -3533,7 +3527,7 @@ func (c *Conn) bindSocket(ruc *RebindingUDPConn, network string, curPortFate cur
c.logf("magicsock: unable to bind %v port %d: %v", network, port, err)
continue
}
if c.onPortUpdate != nil {
if c.portUpdatePub.ShouldPublish() {
_, gotPortStr, err := net.SplitHostPort(pconn.LocalAddr().String())
if err != nil {
c.logf("could not parse port from %s: %w", pconn.LocalAddr().String(), err)
@@ -3542,7 +3536,10 @@ func (c *Conn) bindSocket(ruc *RebindingUDPConn, network string, curPortFate cur
if err != nil {
c.logf("could not parse port from %s: %w", gotPort, err)
} else {
c.onPortUpdate(uint16(gotPort), network)
c.portUpdatePub.Publish(router.PortUpdate{
UDPPort: uint16(gotPort),
EndpointNetwork: network,
})
}
}
}