mirror of
https://github.com/tailscale/tailscale.git
synced 2025-10-09 08:01:31 +00:00
control/controlknobs, all: add plumbed Knobs type, not global variables
Previously two tsnet nodes in the same process couldn't have disjoint sets of controlknob settings from control as both would overwrite each other's global variables. This plumbs a new controlknobs.Knobs type around everywhere and hangs the knobs sent by control on that instead. Updates #9351 Change-Id: I75338646d36813ed971b4ffad6f9a8b41ec91560 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:

committed by
Brad Fitzpatrick

parent
d050700a3b
commit
4e91cf20a8
@@ -14,6 +14,7 @@ import (
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
|
||||
"tailscale.com/control/controlknobs"
|
||||
"tailscale.com/net/netaddr"
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
@@ -249,7 +250,7 @@ func (d *TestIGD) handlePCPQuery(pkt []byte, src netip.AddrPort) {
|
||||
|
||||
func newTestClient(t *testing.T, igd *TestIGD) *Client {
|
||||
var c *Client
|
||||
c = NewClient(t.Logf, nil, nil, func() {
|
||||
c = NewClient(t.Logf, nil, nil, new(controlknobs.Knobs), func() {
|
||||
t.Logf("port map changed")
|
||||
t.Logf("have mapping: %v", c.HaveMapping())
|
||||
})
|
||||
|
@@ -18,6 +18,7 @@ import (
|
||||
"time"
|
||||
|
||||
"go4.org/mem"
|
||||
"tailscale.com/control/controlknobs"
|
||||
"tailscale.com/net/interfaces"
|
||||
"tailscale.com/net/netaddr"
|
||||
"tailscale.com/net/neterror"
|
||||
@@ -66,6 +67,7 @@ const trustServiceStillAvailableDuration = 10 * time.Minute
|
||||
type Client struct {
|
||||
logf logger.Logf
|
||||
netMon *netmon.Monitor // optional; nil means interfaces will be looked up on-demand
|
||||
controlKnobs *controlknobs.Knobs
|
||||
ipAndGateway func() (gw, ip netip.Addr, ok bool)
|
||||
onChange func() // or nil
|
||||
debug DebugKnobs
|
||||
@@ -166,15 +168,19 @@ func (m *pmpMapping) Release(ctx context.Context) {
|
||||
// The debug argument allows configuring the behaviour of the portmapper for
|
||||
// debugging; if nil, a sensible set of defaults will be used.
|
||||
//
|
||||
// The optional onChange argument specifies a func to run in a new
|
||||
// goroutine whenever the port mapping status has changed. If nil,
|
||||
// it doesn't make a callback.
|
||||
func NewClient(logf logger.Logf, netMon *netmon.Monitor, debug *DebugKnobs, onChange func()) *Client {
|
||||
// The controlKnobs, if non-nil, specifies the control knobs from the control
|
||||
// plane that might disable portmapping.
|
||||
//
|
||||
// The optional onChange argument specifies a func to run in a new goroutine
|
||||
// whenever the port mapping status has changed. If nil, it doesn't make a
|
||||
// callback.
|
||||
func NewClient(logf logger.Logf, netMon *netmon.Monitor, debug *DebugKnobs, controlKnobs *controlknobs.Knobs, onChange func()) *Client {
|
||||
ret := &Client{
|
||||
logf: logf,
|
||||
netMon: netMon,
|
||||
ipAndGateway: interfaces.LikelyHomeRouterIP,
|
||||
onChange: onChange,
|
||||
controlKnobs: controlKnobs,
|
||||
}
|
||||
if debug != nil {
|
||||
ret.debug = *debug
|
||||
|
@@ -10,13 +10,15 @@ import (
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"tailscale.com/control/controlknobs"
|
||||
)
|
||||
|
||||
func TestCreateOrGetMapping(t *testing.T) {
|
||||
if v, _ := strconv.ParseBool(os.Getenv("HIT_NETWORK")); !v {
|
||||
t.Skip("skipping test without HIT_NETWORK=1")
|
||||
}
|
||||
c := NewClient(t.Logf, nil, nil, nil)
|
||||
c := NewClient(t.Logf, nil, nil, new(controlknobs.Knobs), nil)
|
||||
defer c.Close()
|
||||
c.SetLocalPort(1234)
|
||||
for i := 0; i < 2; i++ {
|
||||
@@ -32,7 +34,7 @@ func TestClientProbe(t *testing.T) {
|
||||
if v, _ := strconv.ParseBool(os.Getenv("HIT_NETWORK")); !v {
|
||||
t.Skip("skipping test without HIT_NETWORK=1")
|
||||
}
|
||||
c := NewClient(t.Logf, nil, nil, nil)
|
||||
c := NewClient(t.Logf, nil, nil, new(controlknobs.Knobs), nil)
|
||||
defer c.Close()
|
||||
for i := 0; i < 3; i++ {
|
||||
if i > 0 {
|
||||
@@ -47,7 +49,7 @@ func TestClientProbeThenMap(t *testing.T) {
|
||||
if v, _ := strconv.ParseBool(os.Getenv("HIT_NETWORK")); !v {
|
||||
t.Skip("skipping test without HIT_NETWORK=1")
|
||||
}
|
||||
c := NewClient(t.Logf, nil, nil, nil)
|
||||
c := NewClient(t.Logf, nil, nil, new(controlknobs.Knobs), nil)
|
||||
defer c.Close()
|
||||
c.SetLocalPort(1234)
|
||||
res, err := c.Probe(context.Background())
|
||||
|
@@ -24,7 +24,7 @@ import (
|
||||
|
||||
"github.com/tailscale/goupnp"
|
||||
"github.com/tailscale/goupnp/dcps/internetgateway2"
|
||||
"tailscale.com/control/controlknobs"
|
||||
"tailscale.com/envknob"
|
||||
"tailscale.com/net/netns"
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
@@ -192,7 +192,7 @@ func addAnyPortMapping(
|
||||
// The provided ctx is not retained in the returned upnpClient, but
|
||||
// its associated HTTP client is (if set via goupnp.WithHTTPClient).
|
||||
func getUPnPClient(ctx context.Context, logf logger.Logf, debug DebugKnobs, gw netip.Addr, meta uPnPDiscoResponse) (client upnpClient, err error) {
|
||||
if controlknobs.DisableUPnP() || debug.DisableUPnP {
|
||||
if debug.DisableUPnP {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -270,6 +270,10 @@ func (c *Client) upnpHTTPClientLocked() *http.Client {
|
||||
return c.uPnPHTTPClient
|
||||
}
|
||||
|
||||
var (
|
||||
disableUPnpEnv = envknob.RegisterBool("TS_DISABLE_UPNP")
|
||||
)
|
||||
|
||||
// getUPnPPortMapping attempts to create a port-mapping over the UPnP protocol. On success,
|
||||
// it will return the externally exposed IP and port. Otherwise, it will return a zeroed IP and
|
||||
// port and an error.
|
||||
@@ -279,7 +283,7 @@ func (c *Client) getUPnPPortMapping(
|
||||
internal netip.AddrPort,
|
||||
prevPort uint16,
|
||||
) (external netip.AddrPort, ok bool) {
|
||||
if controlknobs.DisableUPnP() || c.debug.DisableUPnP {
|
||||
if disableUPnpEnv() || c.debug.DisableUPnP || (c.controlKnobs != nil && c.controlKnobs.DisableUPnP.Load()) {
|
||||
return netip.AddrPort{}, false
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user