diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/tstun/mtu.go | 65 | ||||
| -rw-r--r-- | net/tstun/mtu_test.go | 14 | ||||
| -rw-r--r-- | net/tstun/tun.go | 2 |
3 files changed, 66 insertions, 15 deletions
diff --git a/net/tstun/mtu.go b/net/tstun/mtu.go index 2307d47f9..43bbc28ec 100644 --- a/net/tstun/mtu.go +++ b/net/tstun/mtu.go @@ -4,15 +4,66 @@ package tstun import "tailscale.com/envknob" +// There are several kinds of MTU. +// +// On-the-wire MTU: This what the network device advertises as the +// maximum packet size available above the physical link layer. This +// includes IP headers and everything at a higher level. For Ethernet, +// this is typically 1500 bytes but can be larger or smaller. +// +// Tailscale interface MTU: This is what we advertise to userspace as +// the largest possible packet it can send through the tailscale +// interface. This is 80 bytes lower than the largest interface we +// have available to send things on, which is the size of the headers +// Wireguard adds (80 for IPv6, 60 for IPv4, but we don't know which +// it will be so we always subtract 80). E.g. if the largest interface +// MTU is 1500, we set the tailscale interface MTU to 1420. +// +// Peer MTU: The MTU that we have probed for the path to a specific +// peer's various endpoints. If this is smaller than the advertised +// tailscale interface, and the packet is larger than the peer MTU, +// then we generate ICMP Packet Too Big (IPv6) or Fragmentation Needed +// (IPv4) packets inside tailscale and drop the packet. +// +// Historically, we set the tailscale interface MTU to 1280. This +// means we treated the "on the wire" MTU as 1360. This is now the +// "Safe" value we use when we do not know what the path MTU is. +// +// Internally, we store the peer MTU as the MTU advertised to the user. +// +// We have to call these by different names or it is way way too confusing. +// +// Wire MTU +// User MTU +// Peer MTU +// +// What should happen when we set TS_DEBUG_MTU? It should set the +// interface to that, but we should not assume that the path MTU is +// this. So distinguish between what we set the interface MTU to and +// what we assume the path MTU is in the absence of probe information. + const ( - maxMTU uint32 = 65536 - defaultMTU uint32 = 1280 + maxMTU uint32 = 65536 + wireguardOverhead = 80 + DefaultUserMTU uint32 = 1280 + DefaultWireMTU uint32 = 1280 + wireguardOverhead ) -// DefaultMTU returns either the constant default MTU of 1280, or the value set -// in TS_DEBUG_MTU clamped to a maximum of 65536. -func DefaultMTU() uint32 { - // DefaultMTU is the Tailscale default MTU for now. +func userMTUToWireMTU(userMTU uint32) uint32 { + return userMTU + wireguardOverhead +} + +func wireMTUToUserMTU(wireMTU uint32) uint32 { + if wireMTU < wireguardOverhead { + return 0 + } + return wireMTU - wireguardOverhead +} + +// TunMTU returns either the constant default user MTU of 1280, or the +// value set in TS_DEBUG_MTU clamped to a maximum of 65536. +func TunMTU() uint32 { + // TunMTU is the Tailscale default MTU for now. // // wireguard-go defaults to 1420 bytes, which only works if the // "outer" MTU is 1500 bytes. This breaks on DSL connections @@ -21,7 +72,7 @@ func DefaultMTU() uint32 { // 1280 is the smallest MTU allowed for IPv6, which is a sensible // "probably works everywhere" setting until we develop proper PMTU // discovery. - tunMTU := defaultMTU + tunMTU := DefaultUserMTU if mtu, ok := envknob.LookupUintSized("TS_DEBUG_MTU", 10, 32); ok { mtu := uint32(mtu) if mtu > maxMTU { diff --git a/net/tstun/mtu_test.go b/net/tstun/mtu_test.go index f3aea4697..1e01c5b12 100644 --- a/net/tstun/mtu_test.go +++ b/net/tstun/mtu_test.go @@ -7,22 +7,22 @@ import ( "testing" ) -func TestDefaultMTU(t *testing.T) { +func TestTunMTU(t *testing.T) { orig := os.Getenv("TS_DEBUG_MTU") defer os.Setenv("TS_DEBUG_MTU", orig) os.Setenv("TS_DEBUG_MTU", "") - if DefaultMTU() != 1280 { - t.Errorf("DefaultMTU() = %d, want 1280", DefaultMTU()) + if TunMTU() != 1280 { + t.Errorf("TunMTU() = %d, want 1280", TunMTU()) } os.Setenv("TS_DEBUG_MTU", "9000") - if DefaultMTU() != 9000 { - t.Errorf("DefaultMTU() = %d, want 9000", DefaultMTU()) + if TunMTU() != 9000 { + t.Errorf("TunMTU() = %d, want 9000", TunMTU()) } os.Setenv("TS_DEBUG_MTU", "123456789") - if DefaultMTU() != maxMTU { - t.Errorf("DefaultMTU() = %d, want %d", DefaultMTU(), maxMTU) + if TunMTU() != maxMTU { + t.Errorf("TunMTU() = %d, want %d", TunMTU(), maxMTU) } } diff --git a/net/tstun/tun.go b/net/tstun/tun.go index b31ffa7ca..0373c7400 100644 --- a/net/tstun/tun.go +++ b/net/tstun/tun.go @@ -44,7 +44,7 @@ func New(logf logger.Logf, tunName string) (tun.Device, string, error) { } dev, err = createTAP(tapName, bridgeName) } else { - dev, err = tun.CreateTUN(tunName, int(DefaultMTU())) + dev, err = tun.CreateTUN(tunName, int(TunMTU())) } if err != nil { return nil, "", err |
