|
|
|
|
@ -6,12 +6,15 @@ package wgengine |
|
|
|
|
import ( |
|
|
|
|
"fmt" |
|
|
|
|
"net/netip" |
|
|
|
|
"os" |
|
|
|
|
"reflect" |
|
|
|
|
"runtime" |
|
|
|
|
"testing" |
|
|
|
|
|
|
|
|
|
"go4.org/mem" |
|
|
|
|
"tailscale.com/cmd/testwrapper/flakytest" |
|
|
|
|
"tailscale.com/control/controlknobs" |
|
|
|
|
"tailscale.com/envknob" |
|
|
|
|
"tailscale.com/net/dns" |
|
|
|
|
"tailscale.com/net/netaddr" |
|
|
|
|
"tailscale.com/net/tstun" |
|
|
|
|
@ -20,6 +23,7 @@ import ( |
|
|
|
|
"tailscale.com/tstime/mono" |
|
|
|
|
"tailscale.com/types/key" |
|
|
|
|
"tailscale.com/types/netmap" |
|
|
|
|
"tailscale.com/types/opt" |
|
|
|
|
"tailscale.com/wgengine/router" |
|
|
|
|
"tailscale.com/wgengine/wgcfg" |
|
|
|
|
) |
|
|
|
|
@ -227,6 +231,86 @@ func TestUserspaceEnginePortReconfig(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test that enabling and disabling peer path MTU discovery works correctly.
|
|
|
|
|
func TestUserspaceEnginePeerMTUReconfig(t *testing.T) { |
|
|
|
|
if runtime.GOOS != "linux" && runtime.GOOS != "darwin" { |
|
|
|
|
t.Skipf("skipping on %q; peer MTU not supported", runtime.GOOS) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
defer os.Setenv("TS_DEBUG_ENABLE_PMTUD", os.Getenv("TS_DEBUG_ENABLE_PMTUD")) |
|
|
|
|
envknob.Setenv("TS_DEBUG_ENABLE_PMTUD", "") |
|
|
|
|
// Turn on debugging to help diagnose problems.
|
|
|
|
|
defer os.Setenv("TS_DEBUG_PMTUD", os.Getenv("TS_DEBUG_PMTUD")) |
|
|
|
|
envknob.Setenv("TS_DEBUG_PMTUD", "true") |
|
|
|
|
|
|
|
|
|
var knobs controlknobs.Knobs |
|
|
|
|
|
|
|
|
|
e, err := NewFakeUserspaceEngine(t.Logf, 0, &knobs) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
t.Cleanup(e.Close) |
|
|
|
|
ue := e.(*userspaceEngine) |
|
|
|
|
|
|
|
|
|
if ue.magicConn.PeerMTUEnabled() != false { |
|
|
|
|
t.Error("peer MTU enabled by default, should not be") |
|
|
|
|
} |
|
|
|
|
osDefaultDF, err := ue.magicConn.DontFragSetting() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Errorf("get don't fragment bit failed: %v", err) |
|
|
|
|
} |
|
|
|
|
t.Logf("Info: OS default don't fragment bit(s) setting: %v", osDefaultDF) |
|
|
|
|
|
|
|
|
|
// Build a set of configs to use as we change the peer MTU settings.
|
|
|
|
|
nodeKey, err := key.ParseNodePublicUntyped(mem.S("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
cfg := &wgcfg.Config{ |
|
|
|
|
Peers: []wgcfg.Peer{ |
|
|
|
|
{ |
|
|
|
|
PublicKey: nodeKey, |
|
|
|
|
AllowedIPs: []netip.Prefix{ |
|
|
|
|
netip.PrefixFrom(netaddr.IPv4(100, 100, 99, 1), 32), |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
routerCfg := &router.Config{} |
|
|
|
|
|
|
|
|
|
tests := []struct { |
|
|
|
|
desc string // test description
|
|
|
|
|
wantP bool // desired value of PMTUD setting
|
|
|
|
|
wantDF bool // desired value of don't fragment bits
|
|
|
|
|
shouldP opt.Bool // if set, force peer MTU to this value
|
|
|
|
|
}{ |
|
|
|
|
{desc: "after_first_reconfig", wantP: false, wantDF: osDefaultDF, shouldP: ""}, |
|
|
|
|
{desc: "enabling_PMTUD_first_time", wantP: true, wantDF: true, shouldP: "true"}, |
|
|
|
|
{desc: "disabling_PMTUD", wantP: false, wantDF: false, shouldP: "false"}, |
|
|
|
|
{desc: "enabling_PMTUD_second_time", wantP: true, wantDF: true, shouldP: "true"}, |
|
|
|
|
{desc: "returning_to_default_PMTUD", wantP: false, wantDF: false, shouldP: ""}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for _, tt := range tests { |
|
|
|
|
t.Run(tt.desc, func(t *testing.T) { |
|
|
|
|
if v, ok := tt.shouldP.Get(); ok { |
|
|
|
|
knobs.PeerMTUEnable.Store(v) |
|
|
|
|
} else { |
|
|
|
|
knobs.PeerMTUEnable.Store(false) |
|
|
|
|
} |
|
|
|
|
if err := ue.Reconfig(cfg, routerCfg, &dns.Config{}); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
if v := ue.magicConn.PeerMTUEnabled(); v != tt.wantP { |
|
|
|
|
t.Errorf("peer MTU set to %v, want %v", v, tt.wantP) |
|
|
|
|
} |
|
|
|
|
if v, err := ue.magicConn.DontFragSetting(); v != tt.wantDF || err != nil { |
|
|
|
|
t.Errorf("don't fragment bit set to %v, want %v, err %v", v, tt.wantP, err) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func nkFromHex(hex string) key.NodePublic { |
|
|
|
|
if len(hex) != 64 { |
|
|
|
|
panic(fmt.Sprintf("%q is len %d; want 64", hex, len(hex))) |
|
|
|
|
|