|
1 | 1 | // Copyright (c) Tailscale Inc & AUTHORS |
2 | 2 | // SPDX-License-Identifier: BSD-3-Clause |
| 3 | + |
3 | 4 | package tstun |
4 | 5 |
|
5 | | -import "tailscale.com/envknob" |
| 6 | +import ( |
| 7 | + "tailscale.com/envknob" |
| 8 | +) |
| 9 | + |
| 10 | +// The MTU (Maximum Transmission Unit) of a network interface is the largest |
| 11 | +// packet that can be sent or received through that interface, including all |
| 12 | +// headers above the link layer (e.g. IP headers, UDP headers, Wireguard |
| 13 | +// headers, etc.). We have to think about several different values of MTU: |
| 14 | +// |
| 15 | +// Wire MTU: The MTU of an interface underneath the tailscale TUN, e.g. an |
| 16 | +// Ethernet network card will default to a 1500 byte MTU. The user may change |
| 17 | +// this MTU at any time. |
| 18 | +// |
| 19 | +// TUN MTU: The current MTU of the tailscale TUN. This MTU is adjusted downward |
| 20 | +// to make room for the wireguard/tailscale headers. For example, if the |
| 21 | +// underlying network interface's MTU is 1500 bytes, the maximum size of a |
| 22 | +// packet entering the tailscale TUN is 1420 bytes. The user may change this MTU |
| 23 | +// at any time via the OS's tools (ifconfig, ip, etc.). |
| 24 | +// |
| 25 | +// User configured initial MTU: The MTU the tailscale TUN should be created |
| 26 | +// with, set by the user via TS_DEBUG_MTU. It should be adjusted down from the |
| 27 | +// underlying interface MTU by 80 bytes to make room for the wireguard |
| 28 | +// headers. This envknob is mostly for debugging. This value is used once at TUN |
| 29 | +// creation and ignored thereafter. |
| 30 | +// |
| 31 | +// User configured current MTU: The MTU set via the OS's tools (ifconfig, ip, |
| 32 | +// etc.). This MTU can change at any time. Setting the MTU this way goes through |
| 33 | +// the MTU() method of tailscale's TUN wrapper. |
| 34 | +// |
| 35 | +// Maximum probed MTU: This is the largest MTU size that we send probe packets |
| 36 | +// for. |
| 37 | +// |
| 38 | +// Safe MTU: If the tailscale TUN MTU is set to this value, almost all packets |
| 39 | +// will get to their destination. Tailscale defaults to this MTU in the absence |
| 40 | +// of path MTU probe information or user MTU configuration. We may occasionally |
| 41 | +// find a path that needs a smaller MTU but it is very rare. |
| 42 | +// |
| 43 | +// Peer MTU: This is the path MTU to a peer's current best endpoint. It defaults |
| 44 | +// to the Safe MTU unless we have path MTU probe results that tell us otherwise. |
| 45 | +// |
| 46 | +// Initial MTU: This is the MTU tailscaled creates the TUN with. In order of |
| 47 | +// priority, it is: |
| 48 | +// |
| 49 | +// 1. If set, the value of TS_DEBUG_MTU clamped to a maximum of 65536 |
| 50 | +// 2. If TS_DEBUG_ENABLE_PMTUD is set, the maximum size MTU we probe, minus wg |
| 51 | +// overhead |
| 52 | +// 3. If TS_DEBUG_ENABLE_PMTUD is not set, the Safe MTU |
| 53 | +// |
| 54 | +// Current MTU: This the MTU of the tailscale TUN at any given moment |
| 55 | +// after TUN creation. In order of priority, it is: |
| 56 | +// |
| 57 | +// 1. The MTU set by the user via the OS, if it has ever been set |
| 58 | +// 2. If TS_DEBUG_ENABLE_PMTUD is set, the maximum size MTU we probe, minus wg |
| 59 | +// overhead |
| 60 | +// 4. If TS_DEBUG_ENABLE_PMTUD is not set, the Safe MTU |
| 61 | + |
| 62 | +// TUNMTU is the MTU for the tailscale TUN. |
| 63 | +type TUNMTU uint32 |
| 64 | + |
| 65 | +// WireMTU is the MTU for the underlying network devices. |
| 66 | +type WireMTU uint32 |
6 | 67 |
|
7 | 68 | const ( |
8 | | - maxMTU uint32 = 65536 |
9 | | - defaultMTU uint32 = 1280 |
| 69 | + // maxTUNMTU is the largest MTU we will consider for the Tailscale |
| 70 | + // TUN. This is inherited from wireguard-go and can be surprisingly |
| 71 | + // small; on Windows it is currently 2048 - 32 bytes and iOS it is 1700 |
| 72 | + // - 32 bytes. |
| 73 | + // TODO(val,raggi): On Windows this seems to derive from RIO driver |
| 74 | + // constraints in Wireguard but we don't use RIO so could probably make |
| 75 | + // this bigger. |
| 76 | + maxTUNMTU TUNMTU = TUNMTU(MaxPacketSize) |
| 77 | + // safeTUNMTU is the default "safe" MTU for the Tailscale TUN that we |
| 78 | + // use in the absence of other information such as path MTU probes. |
| 79 | + safeTUNMTU TUNMTU = 1280 |
10 | 80 | ) |
11 | 81 |
|
12 | | -// DefaultMTU returns either the constant default MTU of 1280, or the value set |
13 | | -// in TS_DEBUG_MTU clamped to a maximum of 65536. |
14 | | -func DefaultMTU() uint32 { |
15 | | - // DefaultMTU is the Tailscale default MTU for now. |
16 | | - // |
17 | | - // wireguard-go defaults to 1420 bytes, which only works if the |
18 | | - // "outer" MTU is 1500 bytes. This breaks on DSL connections |
19 | | - // (typically 1492 MTU) and on GCE (1460 MTU?!). |
20 | | - // |
21 | | - // 1280 is the smallest MTU allowed for IPv6, which is a sensible |
22 | | - // "probably works everywhere" setting until we develop proper PMTU |
23 | | - // discovery. |
24 | | - tunMTU := defaultMTU |
25 | | - if mtu, ok := envknob.LookupUintSized("TS_DEBUG_MTU", 10, 32); ok { |
26 | | - mtu := uint32(mtu) |
27 | | - if mtu > maxMTU { |
28 | | - mtu = maxMTU |
29 | | - } |
30 | | - tunMTU = mtu |
| 82 | +// MaxProbedWireMTU is the largest MTU we will test for path MTU |
| 83 | +// discovery. |
| 84 | +var MaxProbedWireMTU WireMTU = 9000 |
| 85 | + |
| 86 | +func init() { |
| 87 | + if MaxProbedWireMTU > WireMTU(maxTUNMTU) { |
| 88 | + MaxProbedWireMTU = WireMTU(maxTUNMTU) |
| 89 | + } |
| 90 | +} |
| 91 | + |
| 92 | +// wgHeaderLen is the length of all the headers Wireguard adds to a packet |
| 93 | +// in the worst case (IPv6). This constant is for use when we can't or |
| 94 | +// shouldn't use information about the IP version of a specific packet |
| 95 | +// (e.g., calculating the MTU for the Tailscale interface. |
| 96 | +// |
| 97 | +// A Wireguard header includes: |
| 98 | +// |
| 99 | +// - 20-byte IPv4 header or 40-byte IPv6 header |
| 100 | +// - 8-byte UDP header |
| 101 | +// - 4-byte type |
| 102 | +// - 4-byte key index |
| 103 | +// - 8-byte nonce |
| 104 | +// - 16-byte authentication tag |
| 105 | +const wgHeaderLen = 40 + 8 + 4 + 4 + 8 + 16 |
| 106 | + |
| 107 | +// TUNToWireMTU takes the MTU that the Tailscale TUN presents to the user and |
| 108 | +// returns the on-the-wire MTU necessary to transmit the largest packet that |
| 109 | +// will fit through the TUN, given that we have to add wireguard headers. |
| 110 | +func TUNToWireMTU(t TUNMTU) WireMTU { |
| 111 | + return WireMTU(t + wgHeaderLen) |
| 112 | +} |
| 113 | + |
| 114 | +// WireToTUNMTU takes the MTU of an underlying network device and returns the |
| 115 | +// largest possible MTU for a Tailscale TUN operating on top of that device, |
| 116 | +// given that we have to add wireguard headers. |
| 117 | +func WireToTUNMTU(w WireMTU) TUNMTU { |
| 118 | + if w < wgHeaderLen { |
| 119 | + return 0 |
| 120 | + } |
| 121 | + return TUNMTU(w - wgHeaderLen) |
| 122 | +} |
| 123 | + |
| 124 | +// DefaultTUNMTU returns the MTU we use to set the Tailscale TUN |
| 125 | +// MTU. It is also the path MTU that we default to if we have no |
| 126 | +// information about the path to a peer. |
| 127 | +// |
| 128 | +// 1. If set, the value of TS_DEBUG_MTU clamped to a maximum of MaxTunMTU |
| 129 | +// 2. If TS_DEBUG_ENABLE_PMTUD is set, the maximum size MTU we probe, minus wg overhead |
| 130 | +// 3. If TS_DEBUG_ENABLE_PMTUD is not set, the Safe MTU |
| 131 | +func DefaultTUNMTU() TUNMTU { |
| 132 | + if m, ok := envknob.LookupUintSized("TS_DEBUG_MTU", 10, 32); ok { |
| 133 | + return min(TUNMTU(m), maxTUNMTU) |
| 134 | + } |
| 135 | + |
| 136 | + debugPMTUD, _ := envknob.LookupBool("TS_DEBUG_ENABLE_PMTUD") |
| 137 | + if debugPMTUD { |
| 138 | + return WireToTUNMTU(MaxProbedWireMTU) |
31 | 139 | } |
32 | | - return tunMTU |
| 140 | + |
| 141 | + return safeTUNMTU |
| 142 | +} |
| 143 | + |
| 144 | +// Temporary workaround for code on corp that uses this function name. |
| 145 | +// TODO(val): Remove as soon as corp OSS is updated. |
| 146 | +func DefaultMTU() uint32 { |
| 147 | + return uint32(DefaultTUNMTU()) |
| 148 | +} |
| 149 | + |
| 150 | +// DefaultWireMTU returns the default TUN MTU, adjusted for wireguard |
| 151 | +// overhead. |
| 152 | +func DefaultWireMTU() WireMTU { |
| 153 | + return TUNToWireMTU(DefaultTUNMTU()) |
33 | 154 | } |
0 commit comments