|
1 | 1 | // Copyright (c) Tailscale Inc & AUTHORS |
2 | 2 | // SPDX-License-Identifier: BSD-3-Clause |
3 | | - |
4 | 3 | package tstun |
5 | 4 |
|
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 |
| 5 | +import "tailscale.com/envknob" |
67 | 6 |
|
68 | 7 | const ( |
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 |
| 8 | + maxMTU uint32 = 65536 |
| 9 | + defaultMTU uint32 = 1280 |
80 | 10 | ) |
81 | 11 |
|
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) |
139 | | - } |
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. |
| 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. |
146 | 14 | 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()) |
| 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 |
| 31 | + } |
| 32 | + return tunMTU |
154 | 33 | } |
0 commit comments