Skip to content

Commit 16620ac

Browse files
committed
Merge tag 'v1.88.4' into sunos-1.88
Release 1.88.4
2 parents 4f0d522 + 85f4267 commit 16620ac

File tree

5 files changed

+74
-13
lines changed

5 files changed

+74
-13
lines changed

VERSION.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.88.3
1+
1.88.4

wgengine/magicsock/magicsock.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,6 +1565,7 @@ func (c *Conn) maybeRebindOnError(err error) {
15651565

15661566
if c.lastErrRebind.Load().Before(time.Now().Add(-5 * time.Second)) {
15671567
c.logf("magicsock: performing rebind due to %q", reason)
1568+
c.lastErrRebind.Store(time.Now())
15681569
c.Rebind()
15691570
go c.ReSTUN(reason)
15701571
} else {

wgengine/magicsock/magicsock_test.go

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"sync/atomic"
2828
"syscall"
2929
"testing"
30+
"testing/synctest"
3031
"time"
3132
"unsafe"
3233

@@ -3116,18 +3117,35 @@ func TestMaybeRebindOnError(t *testing.T) {
31163117
}
31173118

31183119
t.Run("no-frequent-rebind", func(t *testing.T) {
3119-
if runtime.GOOS != "plan9" {
3120-
err := fmt.Errorf("outer err: %w", syscall.EPERM)
3121-
conn := newTestConn(t)
3122-
defer conn.Close()
3123-
conn.lastErrRebind.Store(time.Now().Add(-1 * time.Second))
3124-
before := metricRebindCalls.Value()
3125-
conn.maybeRebindOnError(err)
3126-
after := metricRebindCalls.Value()
3127-
if before != after {
3128-
t.Errorf("should not rebind within 5 seconds of last")
3120+
synctest.Test(t, func(t *testing.T) {
3121+
if runtime.GOOS != "plan9" {
3122+
err := fmt.Errorf("outer err: %w", syscall.EPERM)
3123+
conn := newTestConn(t)
3124+
defer conn.Close()
3125+
lastRebindTime := time.Now().Add(-1 * time.Second)
3126+
conn.lastErrRebind.Store(lastRebindTime)
3127+
before := metricRebindCalls.Value()
3128+
conn.maybeRebindOnError(err)
3129+
after := metricRebindCalls.Value()
3130+
if before != after {
3131+
t.Errorf("should not rebind within 5 seconds of last")
3132+
}
3133+
3134+
// ensure that rebinds are performed and store an updated last
3135+
// rebind time.
3136+
time.Sleep(6 * time.Second)
3137+
3138+
conn.maybeRebindOnError(err)
3139+
newTime := conn.lastErrRebind.Load()
3140+
if newTime == lastRebindTime {
3141+
t.Errorf("expected a rebind to occur")
3142+
}
3143+
if newTime.Sub(lastRebindTime) < 5*time.Second {
3144+
t.Errorf("expected at least 5 seconds between %s and %s", lastRebindTime, newTime)
3145+
}
31293146
}
3130-
}
3147+
3148+
})
31313149
})
31323150
}
31333151

wgengine/magicsock/relaymanager.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,10 @@ func (r *relayManager) handleNewServerEndpointRunLoop(newServerEndpoint newRelay
758758
ctx: ctx,
759759
cancel: cancel,
760760
}
761-
if byServerDisco == nil {
761+
// We must look up byServerDisco again. The previous value may have been
762+
// deleted from the outer map when cleaning up duplicate work.
763+
byServerDisco, ok = r.handshakeWorkByServerDiscoByEndpoint[newServerEndpoint.wlb.ep]
764+
if !ok {
762765
byServerDisco = make(map[key.DiscoPublic]*relayHandshakeWork)
763766
r.handshakeWorkByServerDiscoByEndpoint[newServerEndpoint.wlb.ep] = byServerDisco
764767
}

wgengine/magicsock/relaymanager_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"testing"
88

99
"tailscale.com/disco"
10+
udprelay "tailscale.com/net/udprelay/endpoint"
1011
"tailscale.com/types/key"
1112
"tailscale.com/util/set"
1213
)
@@ -78,3 +79,41 @@ func TestRelayManagerGetServers(t *testing.T) {
7879
t.Errorf("got %v != want %v", got, servers)
7980
}
8081
}
82+
83+
// Test for http://go/corp/32978
84+
func TestRelayManager_handleNewServerEndpointRunLoop(t *testing.T) {
85+
rm := relayManager{}
86+
rm.init()
87+
<-rm.runLoopStoppedCh // prevent runLoop() from starting, we will inject/handle events in the test
88+
ep := &endpoint{}
89+
conn := newConn(t.Logf)
90+
ep.c = conn
91+
serverDisco := key.NewDisco().Public()
92+
rm.handleNewServerEndpointRunLoop(newRelayServerEndpointEvent{
93+
wlb: endpointWithLastBest{
94+
ep: ep,
95+
},
96+
se: udprelay.ServerEndpoint{
97+
ServerDisco: serverDisco,
98+
LamportID: 1,
99+
VNI: 1,
100+
},
101+
})
102+
rm.handleNewServerEndpointRunLoop(newRelayServerEndpointEvent{
103+
wlb: endpointWithLastBest{
104+
ep: ep,
105+
},
106+
se: udprelay.ServerEndpoint{
107+
ServerDisco: serverDisco,
108+
LamportID: 2,
109+
VNI: 2,
110+
},
111+
})
112+
rm.stopWorkRunLoop(ep)
113+
if len(rm.handshakeWorkByServerDiscoByEndpoint) != 0 ||
114+
len(rm.handshakeWorkByServerDiscoVNI) != 0 ||
115+
len(rm.handshakeWorkAwaitingPong) != 0 ||
116+
len(rm.addrPortVNIToHandshakeWork) != 0 {
117+
t.Fatal("stranded relayHandshakeWork state")
118+
}
119+
}

0 commit comments

Comments
 (0)