controlknobs.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Package controlknobs contains client options configurable from control which can be turned on
  4. // or off. The ability to turn options on and off is for incrementally adding features in.
  5. package controlknobs
  6. import (
  7. "slices"
  8. "sync/atomic"
  9. "tailscale.com/syncs"
  10. "tailscale.com/tailcfg"
  11. "tailscale.com/types/opt"
  12. )
  13. // Knobs is the set of knobs that the control plane's coordination server can
  14. // adjust at runtime.
  15. type Knobs struct {
  16. // DisableUPnP indicates whether to attempt UPnP mapping.
  17. DisableUPnP atomic.Bool
  18. // DisableDRPO is whether control says to disable the
  19. // DERP route optimization (Issue 150).
  20. DisableDRPO atomic.Bool
  21. // KeepFullWGConfig is whether we should disable the lazy wireguard
  22. // programming and instead give WireGuard the full netmap always, even for
  23. // idle peers.
  24. KeepFullWGConfig atomic.Bool
  25. // RandomizeClientPort is whether control says we should randomize
  26. // the client port.
  27. RandomizeClientPort atomic.Bool
  28. // OneCGNAT is whether the the node should make one big CGNAT route
  29. // in the OS rather than one /32 per peer.
  30. OneCGNAT syncs.AtomicValue[opt.Bool]
  31. // ForceBackgroundSTUN forces netcheck STUN queries to keep
  32. // running in magicsock, even when idle.
  33. ForceBackgroundSTUN atomic.Bool
  34. // DisableDeltaUpdates is whether the node should not process
  35. // incremental (delta) netmap updates and should treat all netmap
  36. // changes as "full" ones as tailscaled did in 1.48.x and earlier.
  37. DisableDeltaUpdates atomic.Bool
  38. // PeerMTUEnable is whether the node should do peer path MTU discovery.
  39. PeerMTUEnable atomic.Bool
  40. // DisableDNSForwarderTCPRetries is whether the DNS forwarder should
  41. // skip retrying truncated queries over TCP.
  42. DisableDNSForwarderTCPRetries atomic.Bool
  43. // SilentDisco is whether the node should suppress disco heartbeats to its
  44. // peers.
  45. SilentDisco atomic.Bool
  46. }
  47. // UpdateFromNodeAttributes updates k (if non-nil) based on the provided self
  48. // node attributes (Node.Capabilities).
  49. func (k *Knobs) UpdateFromNodeAttributes(selfNodeAttrs []tailcfg.NodeCapability, capMap tailcfg.NodeCapMap) {
  50. if k == nil {
  51. return
  52. }
  53. has := func(attr tailcfg.NodeCapability) bool {
  54. _, ok := capMap[attr]
  55. return ok || slices.Contains(selfNodeAttrs, attr)
  56. }
  57. var (
  58. keepFullWG = has(tailcfg.NodeAttrDebugDisableWGTrim)
  59. disableDRPO = has(tailcfg.NodeAttrDebugDisableDRPO)
  60. disableUPnP = has(tailcfg.NodeAttrDisableUPnP)
  61. randomizeClientPort = has(tailcfg.NodeAttrRandomizeClientPort)
  62. disableDeltaUpdates = has(tailcfg.NodeAttrDisableDeltaUpdates)
  63. oneCGNAT opt.Bool
  64. forceBackgroundSTUN = has(tailcfg.NodeAttrDebugForceBackgroundSTUN)
  65. peerMTUEnable = has(tailcfg.NodeAttrPeerMTUEnable)
  66. dnsForwarderDisableTCPRetries = has(tailcfg.NodeAttrDNSForwarderDisableTCPRetries)
  67. silentDisco = has(tailcfg.NodeAttrSilentDisco)
  68. )
  69. if has(tailcfg.NodeAttrOneCGNATEnable) {
  70. oneCGNAT.Set(true)
  71. } else if has(tailcfg.NodeAttrOneCGNATDisable) {
  72. oneCGNAT.Set(false)
  73. }
  74. k.KeepFullWGConfig.Store(keepFullWG)
  75. k.DisableDRPO.Store(disableDRPO)
  76. k.DisableUPnP.Store(disableUPnP)
  77. k.RandomizeClientPort.Store(randomizeClientPort)
  78. k.OneCGNAT.Store(oneCGNAT)
  79. k.ForceBackgroundSTUN.Store(forceBackgroundSTUN)
  80. k.DisableDeltaUpdates.Store(disableDeltaUpdates)
  81. k.PeerMTUEnable.Store(peerMTUEnable)
  82. k.DisableDNSForwarderTCPRetries.Store(dnsForwarderDisableTCPRetries)
  83. k.SilentDisco.Store(silentDisco)
  84. }
  85. // AsDebugJSON returns k as something that can be marshalled with json.Marshal
  86. // for debug.
  87. func (k *Knobs) AsDebugJSON() map[string]any {
  88. if k == nil {
  89. return nil
  90. }
  91. return map[string]any{
  92. "DisableUPnP": k.DisableUPnP.Load(),
  93. "DisableDRPO": k.DisableDRPO.Load(),
  94. "KeepFullWGConfig": k.KeepFullWGConfig.Load(),
  95. "RandomizeClientPort": k.RandomizeClientPort.Load(),
  96. "OneCGNAT": k.OneCGNAT.Load(),
  97. "ForceBackgroundSTUN": k.ForceBackgroundSTUN.Load(),
  98. "DisableDeltaUpdates": k.DisableDeltaUpdates.Load(),
  99. "PeerMTUEnable": k.PeerMTUEnable.Load(),
  100. "DisableDNSForwarderTCPRetries": k.DisableDNSForwarderTCPRetries.Load(),
  101. "SilentDisco": k.SilentDisco.Load(),
  102. }
  103. }