diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index 611a13999..93bc3dcec 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -45,10 +45,6 @@ "tailscale.com/version" ) -var ( - enableV6Overlay, _ = strconv.ParseBool(os.Getenv("TS_DEBUG_ENABLE_IPV6_OVERLAY")) -) - type Persist struct { _ structs.Incomparable @@ -111,6 +107,7 @@ type Direct struct { logf logger.Logf discoPubKey tailcfg.DiscoKey machinePrivKey wgcfg.PrivateKey + debugFlags []string mu sync.Mutex // mutex guards the following fields serverKey wgcfg.Key @@ -137,6 +134,7 @@ type Options struct { KeepAlive bool Logf logger.Logf HTTPTestClient *http.Client // optional HTTP client to use (for tests only) + DebugFlags []string // debug settings to send to control } type Decompressor interface { @@ -189,6 +187,7 @@ func NewDirect(opts Options) (*Direct, error) { persist: opts.Persist, authKey: opts.AuthKey, discoPubKey: opts.DiscoPublicKey, + debugFlags: opts.DebugFlags, } if opts.Hostinfo == nil { c.SetHostinfo(NewHostinfo()) @@ -531,16 +530,16 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM } request := tailcfg.MapRequest{ - Version: 4, - IncludeIPv6: true, - IncludeIPv6Overlay: enableV6Overlay, - DeltaPeers: true, - KeepAlive: c.keepAlive, - NodeKey: tailcfg.NodeKey(persist.PrivateNodeKey.Public()), - DiscoKey: c.discoPubKey, - Endpoints: ep, - Stream: allowStream, - Hostinfo: hostinfo, + Version: 4, + IncludeIPv6: true, + DeltaPeers: true, + KeepAlive: c.keepAlive, + NodeKey: tailcfg.NodeKey(persist.PrivateNodeKey.Public()), + DiscoKey: c.discoPubKey, + Endpoints: ep, + Stream: allowStream, + Hostinfo: hostinfo, + DebugFlags: c.debugFlags, } if c.newDecompressor != nil { request.Compress = "zstd" diff --git a/ipn/local.go b/ipn/local.go index ea28c8222..7487fd4fa 100644 --- a/ipn/local.go +++ b/ipn/local.go @@ -36,6 +36,10 @@ "tailscale.com/wgengine/tsdns" ) +var ( + controlDebugFlags = strings.Split(os.Getenv("TS_DEBUG_CONTROL_FLAGS"), ",") +) + // LocalBackend is the glue between the major pieces of the Tailscale // network software: the cloud control plane (via controlclient), the // network data plane (via wgengine), and the user-facing UIs and CLIs @@ -451,6 +455,7 @@ func (b *LocalBackend) Start(opts Options) error { NewDecompressor: b.newDecompressor, HTTPTestClient: opts.HTTPTestClient, DiscoPublicKey: discoPublic, + DebugFlags: controlDebugFlags, }) if err != nil { return err diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index eda215a58..424294e45 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -486,6 +486,14 @@ type MapRequest struct { // being omitted in the response. (For example, a client on // start up using ReadOnly to get the DERP map.) OmitPeers bool `json:",omitempty"` + + // DebugFlags is a list of strings specifying debugging and + // development features to enable in handling this map + // request. The values are deliberately unspecified, as they get + // added and removed all the time during development, and offer no + // compatibility promise. To roll out semantic changes, bump + // Version instead. + DebugFlags []string `json:",omitempty"` } // PortRange represents a range of UDP or TCP port numbers.