@@ -17,6 +17,14 @@ use talpid_wireguard;
17
17
const OPENVPN_LOG_FILENAME : & str = "openvpn.log" ;
18
18
const WIREGUARD_LOG_FILENAME : & str = "wireguard.log" ;
19
19
20
+ /// Set the MTU to the lowest possible whilst still allowing for IPv6 to help with wireless
21
+ /// carriers that do a lot of encapsulation.
22
+ const DEFAULT_MTU : u16 = if cfg ! ( target_os = "android" ) {
23
+ 1280
24
+ } else {
25
+ 1380
26
+ } ;
27
+
20
28
/// Results from operations in the tunnel module.
21
29
pub type Result < T > = std:: result:: Result < T , Error > ;
22
30
@@ -154,13 +162,25 @@ impl TunnelMonitor {
154
162
+ Clone
155
163
+ ' static ,
156
164
{
165
+ let default_mtu = DEFAULT_MTU ;
166
+
157
167
#[ cfg( any( target_os = "linux" , target_os = "windows" ) ) ]
158
- args. runtime
159
- . block_on ( Self :: assign_mtu ( & args. route_manager , params) ) ;
160
- let config = talpid_wireguard:: config:: Config :: from_parameters ( params) ?;
168
+ // Detects the MTU of the device and sets the default tunnel MTU to that minus headers and
169
+ // the safety margin
170
+ let default_mtu = args
171
+ . runtime
172
+ . block_on (
173
+ args. route_manager
174
+ . get_mtu_for_route ( params. connection . peer . endpoint . ip ( ) ) ,
175
+ )
176
+ . map ( |mtu| Self :: clamp_mtu ( params, mtu) )
177
+ . unwrap_or ( default_mtu) ;
178
+ let config = talpid_wireguard:: config:: Config :: from_parameters ( params, default_mtu) ?;
161
179
let monitor = talpid_wireguard:: WireguardMonitor :: start (
162
180
config,
163
181
params. options . quantum_resistant ,
182
+ #[ cfg( target_os = "linux" ) ]
183
+ detect_mtu,
164
184
log. as_deref ( ) ,
165
185
args,
166
186
) ?;
@@ -169,58 +189,36 @@ impl TunnelMonitor {
169
189
} )
170
190
}
171
191
172
- /// Set the MTU in the tunnel parameters based on the inputted device MTU and some
173
- /// calculations. `peer_mtu` is the detected device MTU.
192
+ /// Calculates and appropriate tunnel MTU based on the given peer MTU minus header sizes
174
193
#[ cfg( any( target_os = "linux" , target_os = "windows" ) ) ]
175
- fn set_mtu ( params : & mut wireguard_types:: TunnelParameters , peer_mtu : u16 ) {
194
+ fn clamp_mtu ( params : & wireguard_types:: TunnelParameters , peer_mtu : u16 ) -> u16 {
195
+ use talpid_tunnel:: {
196
+ IPV4_HEADER_SIZE , IPV6_HEADER_SIZE , MIN_IPV4_MTU , MIN_IPV6_MTU , WIREGUARD_HEADER_SIZE ,
197
+ } ;
176
198
// Some users experience fragmentation issues even when we take the interface MTU and
177
199
// subtract the header sizes. This is likely due to some program that they use which does
178
200
// not change the interface MTU but adds its own header onto the outgoing packets. For this
179
201
// reason we subtract some extra bytes from our MTU in order to give other programs some
180
202
// safety margin.
181
203
const MTU_SAFETY_MARGIN : u16 = 60 ;
182
- const IPV4_HEADER_SIZE : u16 = 20 ;
183
- const IPV6_HEADER_SIZE : u16 = 40 ;
184
- const WIREGUARD_HEADER_SIZE : u16 = 40 ;
204
+
185
205
let total_header_size = WIREGUARD_HEADER_SIZE
186
206
+ match params. connection . peer . endpoint . is_ipv6 ( ) {
187
207
false => IPV4_HEADER_SIZE ,
188
208
true => IPV6_HEADER_SIZE ,
189
209
} ;
210
+
190
211
// The largest peer MTU that we allow
191
- const MAX_PEER_MTU : u16 = 1500 - MTU_SAFETY_MARGIN ;
192
- // The minimum allowed MTU size for our tunnel in IPv6 is 1280 and 576 for IPv4
193
- const MIN_IPV4_MTU : u16 = 576 ;
194
- const MIN_IPV6_MTU : u16 = 1280 ;
212
+ let max_peer_mtu: u16 = 1500 - MTU_SAFETY_MARGIN - total_header_size;
213
+
195
214
let min_mtu = match params. generic_options . enable_ipv6 {
196
215
false => MIN_IPV4_MTU ,
197
216
true => MIN_IPV6_MTU ,
198
217
} ;
199
- let tunnel_mtu = peer_mtu
200
- . saturating_sub ( total_header_size)
201
- . clamp ( min_mtu, MAX_PEER_MTU - total_header_size) ;
202
- params. options . mtu = Some ( tunnel_mtu) ;
203
- }
204
218
205
- /// Detects the MTU of the device, calculates what the virtual device MTU should be and sets
206
- /// that in the tunnel parameters.
207
- #[ cfg( any( target_os = "linux" , target_os = "windows" ) ) ]
208
- async fn assign_mtu (
209
- route_manager : & RouteManagerHandle ,
210
- params : & mut wireguard_types:: TunnelParameters ,
211
- ) {
212
- // Only calculate the mtu automatically if the user has not set any
213
- if params. options . mtu . is_none ( ) {
214
- match route_manager
215
- . get_mtu_for_route ( params. connection . peer . endpoint . ip ( ) )
216
- . await
217
- {
218
- Ok ( mtu) => Self :: set_mtu ( params, mtu) ,
219
- Err ( e) => {
220
- log:: error!( "Could not get the MTU for route {}" , e) ;
221
- }
222
- }
223
- }
219
+ peer_mtu
220
+ . saturating_sub ( total_header_size)
221
+ . clamp ( min_mtu, max_peer_mtu)
224
222
}
225
223
226
224
#[ cfg( not( target_os = "android" ) ) ]
0 commit comments