Skip to content

Commit d9a83fc

Browse files
authored
fix: Refactor tailnet conn AwaitReachable to allow for pings >1s RTT (#5096)
1 parent eda7c66 commit d9a83fc

File tree

1 file changed

+27
-7
lines changed

1 file changed

+27
-7
lines changed

tailnet/conn.go

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"sync"
1212
"time"
1313

14+
"github.com/cenkalti/backoff/v4"
1415
"github.com/google/uuid"
1516
"go4.org/netipx"
1617
"golang.org/x/xerrors"
@@ -424,24 +425,43 @@ func (c *Conn) Ping(ctx context.Context, ip netip.Addr) (time.Duration, error) {
424425
// address is reachable. It's the callers responsibility to provide
425426
// a timeout, otherwise this function will block forever.
426427
func (c *Conn) AwaitReachable(ctx context.Context, ip netip.Addr) bool {
427-
ticker := time.NewTicker(time.Millisecond * 100)
428-
defer ticker.Stop()
429-
completedCtx, completed := context.WithCancel(ctx)
428+
ctx, cancel := context.WithCancel(ctx)
429+
defer cancel() // Cancel all pending pings on exit.
430+
431+
completedCtx, completed := context.WithCancel(context.Background())
432+
defer completed()
433+
430434
run := func() {
431-
ctx, cancelFunc := context.WithTimeout(completedCtx, time.Second)
432-
defer cancelFunc()
435+
// Safety timeout, initially we'll have around 10-20 goroutines
436+
// running in parallel. The exponential backoff will converge
437+
// around ~1 ping / 30s, this means we'll have around 10-20
438+
// goroutines pending towards the end as well.
439+
ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
440+
defer cancel()
441+
433442
_, err := c.Ping(ctx, ip)
434443
if err == nil {
435444
completed()
436445
}
437446
}
447+
448+
eb := backoff.NewExponentialBackOff()
449+
eb.MaxElapsedTime = 0
450+
eb.InitialInterval = 50 * time.Millisecond
451+
eb.MaxInterval = 30 * time.Second
452+
// Consume the first interval since
453+
// we'll fire off a ping immediately.
454+
_ = eb.NextBackOff()
455+
456+
t := backoff.NewTicker(eb)
457+
defer t.Stop()
458+
438459
go run()
439-
defer completed()
440460
for {
441461
select {
442462
case <-completedCtx.Done():
443463
return true
444-
case <-ticker.C:
464+
case <-t.C:
445465
// Pings can take a while, so we can run multiple
446466
// in parallel to return ASAP.
447467
go run()

0 commit comments

Comments
 (0)