2023-01-27 21:37:20 +00:00
|
|
|
// Copyright (c) Tailscale Inc & AUTHORS
|
|
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
2020-02-05 22:16:58 +00:00
|
|
|
|
2022-06-07 19:50:12 +01:00
|
|
|
//go:build !js
|
|
|
|
|
2020-02-05 22:16:58 +00:00
|
|
|
package wgengine
|
|
|
|
|
|
|
|
import (
|
2022-08-28 03:06:18 +01:00
|
|
|
"fmt"
|
2020-02-05 22:16:58 +00:00
|
|
|
"log"
|
all: convert more code to use net/netip directly
perl -i -npe 's,netaddr.IPPrefixFrom,netip.PrefixFrom,' $(git grep -l -F netaddr.)
perl -i -npe 's,netaddr.IPPortFrom,netip.AddrPortFrom,' $(git grep -l -F netaddr. )
perl -i -npe 's,netaddr.IPPrefix,netip.Prefix,g' $(git grep -l -F netaddr. )
perl -i -npe 's,netaddr.IPPort,netip.AddrPort,g' $(git grep -l -F netaddr. )
perl -i -npe 's,netaddr.IP\b,netip.Addr,g' $(git grep -l -F netaddr. )
perl -i -npe 's,netaddr.IPv6Raw\b,netip.AddrFrom16,g' $(git grep -l -F netaddr. )
goimports -w .
Then delete some stuff from the net/netaddr shim package which is no
longer neeed.
Updates #5162
Change-Id: Ia7a86893fe21c7e3ee1ec823e8aba288d4566cd8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2022-07-26 05:14:09 +01:00
|
|
|
"net/netip"
|
2020-02-05 22:16:58 +00:00
|
|
|
"runtime/pprof"
|
2020-02-11 23:21:24 +00:00
|
|
|
"strings"
|
2022-08-28 03:06:18 +01:00
|
|
|
"sync"
|
2020-02-05 22:16:58 +00:00
|
|
|
"time"
|
|
|
|
|
2022-01-24 18:52:57 +00:00
|
|
|
"tailscale.com/envknob"
|
2020-03-26 05:57:46 +00:00
|
|
|
"tailscale.com/ipn/ipnstate"
|
2021-04-02 08:34:32 +01:00
|
|
|
"tailscale.com/net/dns"
|
2020-05-17 17:51:38 +01:00
|
|
|
"tailscale.com/tailcfg"
|
2024-02-28 15:33:15 +00:00
|
|
|
"tailscale.com/types/key"
|
2021-02-05 23:44:46 +00:00
|
|
|
"tailscale.com/types/netmap"
|
2023-02-08 23:48:27 +00:00
|
|
|
"tailscale.com/wgengine/capture"
|
2020-02-05 22:16:58 +00:00
|
|
|
"tailscale.com/wgengine/filter"
|
2020-05-11 22:02:12 +01:00
|
|
|
"tailscale.com/wgengine/router"
|
2021-01-29 20:16:36 +00:00
|
|
|
"tailscale.com/wgengine/wgcfg"
|
2024-02-28 15:33:15 +00:00
|
|
|
"tailscale.com/wgengine/wgint"
|
2020-02-05 22:16:58 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// NewWatchdog wraps an Engine and makes sure that all methods complete
|
|
|
|
// within a reasonable amount of time.
|
|
|
|
//
|
|
|
|
// If they do not, the watchdog crashes the process.
|
|
|
|
func NewWatchdog(e Engine) Engine {
|
2022-01-24 18:52:57 +00:00
|
|
|
if envknob.Bool("TS_DEBUG_DISABLE_WATCHDOG") {
|
2020-07-25 20:59:53 +01:00
|
|
|
return e
|
|
|
|
}
|
2020-02-05 22:16:58 +00:00
|
|
|
return &watchdogEngine{
|
2022-08-28 03:06:18 +01:00
|
|
|
wrap: e,
|
|
|
|
logf: log.Printf,
|
|
|
|
fatalf: log.Fatalf,
|
|
|
|
maxWait: 45 * time.Second,
|
|
|
|
inFlight: make(map[inFlightKey]time.Time),
|
2020-02-05 22:16:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-28 03:06:18 +01:00
|
|
|
type inFlightKey struct {
|
|
|
|
op string
|
|
|
|
ctr uint64
|
|
|
|
}
|
|
|
|
|
2020-02-05 22:16:58 +00:00
|
|
|
type watchdogEngine struct {
|
|
|
|
wrap Engine
|
2022-03-16 23:27:57 +00:00
|
|
|
logf func(format string, args ...any)
|
|
|
|
fatalf func(format string, args ...any)
|
2020-02-05 22:16:58 +00:00
|
|
|
maxWait time.Duration
|
2022-08-28 03:06:18 +01:00
|
|
|
|
|
|
|
// Track the start time(s) of in-flight operations
|
|
|
|
inFlightMu sync.Mutex
|
|
|
|
inFlight map[inFlightKey]time.Time
|
|
|
|
inFlightCtr uint64
|
2020-02-05 22:16:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (e *watchdogEngine) watchdogErr(name string, fn func() error) error {
|
2022-08-28 03:06:18 +01:00
|
|
|
// Track all in-flight operations so we can print more useful error
|
|
|
|
// messages on watchdog failure
|
|
|
|
e.inFlightMu.Lock()
|
|
|
|
key := inFlightKey{
|
|
|
|
op: name,
|
|
|
|
ctr: e.inFlightCtr,
|
|
|
|
}
|
|
|
|
e.inFlightCtr++
|
|
|
|
e.inFlight[key] = time.Now()
|
|
|
|
e.inFlightMu.Unlock()
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
e.inFlightMu.Lock()
|
|
|
|
defer e.inFlightMu.Unlock()
|
|
|
|
delete(e.inFlight, key)
|
|
|
|
}()
|
|
|
|
|
2020-02-05 22:16:58 +00:00
|
|
|
errCh := make(chan error)
|
|
|
|
go func() {
|
|
|
|
errCh <- fn()
|
|
|
|
}()
|
|
|
|
t := time.NewTimer(e.maxWait)
|
|
|
|
select {
|
|
|
|
case err := <-errCh:
|
|
|
|
t.Stop()
|
|
|
|
return err
|
|
|
|
case <-t.C:
|
2020-02-11 23:21:24 +00:00
|
|
|
buf := new(strings.Builder)
|
2020-02-05 22:16:58 +00:00
|
|
|
pprof.Lookup("goroutine").WriteTo(buf, 1)
|
|
|
|
e.logf("wgengine watchdog stacks:\n%s", buf.String())
|
2022-08-28 03:06:18 +01:00
|
|
|
|
|
|
|
// Collect the list of in-flight operations for debugging.
|
|
|
|
var (
|
|
|
|
b []byte
|
|
|
|
now = time.Now()
|
|
|
|
)
|
|
|
|
e.inFlightMu.Lock()
|
|
|
|
for k, t := range e.inFlight {
|
|
|
|
dur := now.Sub(t).Round(time.Millisecond)
|
|
|
|
b = fmt.Appendf(b, "in-flight[%d]: name=%s duration=%v start=%s\n", k.ctr, k.op, dur, t.Format(time.RFC3339Nano))
|
|
|
|
}
|
|
|
|
e.inFlightMu.Unlock()
|
|
|
|
|
|
|
|
// Print everything as a single string to avoid log
|
|
|
|
// rate limits.
|
|
|
|
e.logf("wgengine watchdog in-flight:\n%s", b)
|
2020-02-05 22:16:58 +00:00
|
|
|
e.fatalf("wgengine: watchdog timeout on %s", name)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *watchdogEngine) watchdog(name string, fn func()) {
|
|
|
|
e.watchdogErr(name, func() error {
|
|
|
|
fn()
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-08-18 01:29:15 +01:00
|
|
|
func (e *watchdogEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config, dnsCfg *dns.Config) error {
|
|
|
|
return e.watchdogErr("Reconfig", func() error { return e.wrap.Reconfig(cfg, routerCfg, dnsCfg) })
|
2020-02-05 22:16:58 +00:00
|
|
|
}
|
2020-03-25 07:47:55 +00:00
|
|
|
func (e *watchdogEngine) GetFilter() *filter.Filter {
|
2021-03-01 20:56:03 +00:00
|
|
|
return e.wrap.GetFilter()
|
2020-03-25 07:47:55 +00:00
|
|
|
}
|
2020-02-05 22:16:58 +00:00
|
|
|
func (e *watchdogEngine) SetFilter(filt *filter.Filter) {
|
|
|
|
e.watchdog("SetFilter", func() { e.wrap.SetFilter(filt) })
|
|
|
|
}
|
|
|
|
func (e *watchdogEngine) SetStatusCallback(cb StatusCallback) {
|
|
|
|
e.watchdog("SetStatusCallback", func() { e.wrap.SetStatusCallback(cb) })
|
|
|
|
}
|
2020-03-26 05:57:46 +00:00
|
|
|
func (e *watchdogEngine) UpdateStatus(sb *ipnstate.StatusBuilder) {
|
|
|
|
e.watchdog("UpdateStatus", func() { e.wrap.UpdateStatus(sb) })
|
|
|
|
}
|
2020-02-05 22:16:58 +00:00
|
|
|
func (e *watchdogEngine) RequestStatus() {
|
|
|
|
e.watchdog("RequestStatus", func() { e.wrap.RequestStatus() })
|
|
|
|
}
|
2021-02-05 23:44:46 +00:00
|
|
|
func (e *watchdogEngine) SetNetworkMap(nm *netmap.NetworkMap) {
|
2020-06-25 19:04:52 +01:00
|
|
|
e.watchdog("SetNetworkMap", func() { e.wrap.SetNetworkMap(nm) })
|
|
|
|
}
|
2023-08-08 13:11:28 +01:00
|
|
|
func (e *watchdogEngine) Ping(ip netip.Addr, pingType tailcfg.PingType, size int, cb func(*ipnstate.PingResult)) {
|
|
|
|
e.watchdog("Ping", func() { e.wrap.Ping(ip, pingType, size, cb) })
|
2020-08-09 22:49:42 +01:00
|
|
|
}
|
2020-02-05 22:16:58 +00:00
|
|
|
func (e *watchdogEngine) Close() {
|
|
|
|
e.watchdog("Close", e.wrap.Close)
|
|
|
|
}
|
all: convert more code to use net/netip directly
perl -i -npe 's,netaddr.IPPrefixFrom,netip.PrefixFrom,' $(git grep -l -F netaddr.)
perl -i -npe 's,netaddr.IPPortFrom,netip.AddrPortFrom,' $(git grep -l -F netaddr. )
perl -i -npe 's,netaddr.IPPrefix,netip.Prefix,g' $(git grep -l -F netaddr. )
perl -i -npe 's,netaddr.IPPort,netip.AddrPort,g' $(git grep -l -F netaddr. )
perl -i -npe 's,netaddr.IP\b,netip.Addr,g' $(git grep -l -F netaddr. )
perl -i -npe 's,netaddr.IPv6Raw\b,netip.AddrFrom16,g' $(git grep -l -F netaddr. )
goimports -w .
Then delete some stuff from the net/netaddr shim package which is no
longer neeed.
Updates #5162
Change-Id: Ia7a86893fe21c7e3ee1ec823e8aba288d4566cd8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2022-07-26 05:14:09 +01:00
|
|
|
func (e *watchdogEngine) PeerForIP(ip netip.Addr) (ret PeerForIP, ok bool) {
|
2021-11-30 18:30:44 +00:00
|
|
|
e.watchdog("PeerForIP", func() { ret, ok = e.wrap.PeerForIP(ip) })
|
|
|
|
return ret, ok
|
|
|
|
}
|
|
|
|
|
2024-02-24 01:55:08 +00:00
|
|
|
func (e *watchdogEngine) Done() <-chan struct{} {
|
|
|
|
return e.wrap.Done()
|
2020-02-05 22:16:58 +00:00
|
|
|
}
|
2023-01-19 22:28:49 +00:00
|
|
|
|
2023-02-08 23:48:27 +00:00
|
|
|
func (e *watchdogEngine) InstallCaptureHook(cb capture.Callback) {
|
2023-01-19 22:28:49 +00:00
|
|
|
e.wrap.InstallCaptureHook(cb)
|
|
|
|
}
|
2024-02-28 15:33:15 +00:00
|
|
|
|
|
|
|
func (e *watchdogEngine) PeerByKey(pubKey key.NodePublic) (_ wgint.Peer, ok bool) {
|
|
|
|
return e.wrap.PeerByKey(pubKey)
|
|
|
|
}
|