diff --git a/wgengine/router/callback.go b/wgengine/router/callback.go index 1d7f32846..c1838539b 100644 --- a/wgengine/router/callback.go +++ b/wgengine/router/callback.go @@ -24,9 +24,16 @@ type CallbackRouter struct { // will return ErrGetBaseConfigNotSupported. GetBaseConfigFunc func() (dns.OSConfig, error) - mu sync.Mutex // protects all the following - rcfg *Config // last applied router config - dcfg *dns.OSConfig // last applied DNS config + // InitialMTU is the MTU the tun should be initialized with. + // Zero means don't change the MTU from the default. This MTU + // is applied only once, shortly after the TUN is created, and + // ignored thereafter. + InitialMTU uint32 + + mu sync.Mutex // protects all the following + didSetMTU bool // if we set the MTU already + rcfg *Config // last applied router config + dcfg *dns.OSConfig // last applied DNS config } // Up implements Router. @@ -41,6 +48,10 @@ func (r *CallbackRouter) Set(rcfg *Config) error { if r.rcfg.Equal(rcfg) { return nil } + if r.didSetMTU == false { + r.didSetMTU = true + rcfg.NewMTU = int(r.InitialMTU) + } r.rcfg = rcfg return r.SetBoth(r.rcfg, r.dcfg) } diff --git a/wgengine/router/router.go b/wgengine/router/router.go index 11668a70e..ecea521ad 100644 --- a/wgengine/router/router.go +++ b/wgengine/router/router.go @@ -67,6 +67,11 @@ type Config struct { // routing rules apply. LocalRoutes []netip.Prefix + // NewMTU is currently only used by the MacOS network extension + // app to set the MTU of the tun in the router configuration + // callback. If zero, the MTU is unchanged. + NewMTU int + // Linux-only things below, ignored on other platforms. SubnetRoutes []netip.Prefix // subnets being advertised to other Tailscale nodes SNATSubnetRoutes bool // SNAT traffic to local subnets diff --git a/wgengine/router/router_test.go b/wgengine/router/router_test.go index 413de5742..d06033ba8 100644 --- a/wgengine/router/router_test.go +++ b/wgengine/router/router_test.go @@ -21,8 +21,8 @@ func mustCIDRs(ss ...string) []netip.Prefix { func TestConfigEqual(t *testing.T) { testedFields := []string{ - "LocalAddrs", "Routes", "LocalRoutes", "SubnetRoutes", - "SNATSubnetRoutes", "NetfilterMode", + "LocalAddrs", "Routes", "LocalRoutes", "NewMTU", + "SubnetRoutes", "SNATSubnetRoutes", "NetfilterMode", } configType := reflect.TypeOf(Config{}) configFields := []string{} @@ -134,6 +134,16 @@ func TestConfigEqual(t *testing.T) { &Config{NetfilterMode: preftype.NetfilterNoDivert}, true, }, + { + &Config{NewMTU: 0}, + &Config{NewMTU: 0}, + true, + }, + { + &Config{NewMTU: 1280}, + &Config{NewMTU: 0}, + false, + }, } for i, tt := range tests { got := tt.a.Equal(tt.b)