@@ -15,7 +15,6 @@ use std::env;
15
15
16
16
use std:: {
17
17
convert:: Infallible ,
18
- io,
19
18
net:: IpAddr ,
20
19
path:: Path ,
21
20
pin:: Pin ,
@@ -359,7 +358,7 @@ impl WireguardMonitor {
359
358
gateway,
360
359
#[ cfg( any( target_os = "macos" , target_os = "linux" ) ) ]
361
360
iface_name_clone. clone ( ) ,
362
- dbg ! ( config. mtu) ,
361
+ dbg ! ( config. mtu as usize ) ,
363
362
)
364
363
. await
365
364
. unwrap ( ) ; // TODO: detect real MTU
@@ -948,61 +947,67 @@ impl WireguardMonitor {
948
947
async fn get_mtu (
949
948
gateway : std:: net:: Ipv4Addr ,
950
949
#[ cfg( any( target_os = "macos" , target_os = "linux" ) ) ] iface_name : String ,
951
- max_mtu : u16 ,
952
- ) -> Result < u16 > {
953
- let mut pinger = ping_monitor:: imp:: Pinger :: new (
954
- gateway,
955
- #[ cfg( any( target_os = "macos" , target_os = "linux" ) ) ]
956
- iface_name,
957
- )
958
- . unwrap ( ) ;
950
+ max_mtu : usize ,
951
+ ) -> Result < usize > {
952
+ use surge_ping:: { Client , Config , PingIdentifier , PingSequence } ;
953
+
954
+ let config_builder = Config :: builder ( ) . kind ( surge_ping:: ICMP :: V4 ) ;
955
+ // let addr = std::net::SocketAddr::new(gateway.into(), 0);
956
+ // let config_builder = config_builder.bind(addr);
957
+ #[ cfg( any( target_os = "macos" , target_os = "linux" ) ) ]
958
+ let config_builder = config_builder. interface ( & iface_name) ;
959
+ let config = config_builder. build ( ) ;
960
+
961
+ let client = Client :: new ( & config) . unwrap ( ) ;
962
+ let mut pinger = client
963
+ . pinger ( IpAddr :: V4 ( gateway) , PingIdentifier ( 111 ) )
964
+ . await ;
965
+ pinger. timeout ( Duration :: from_secs ( 5 ) ) ; // TODO: choose a good timeout
959
966
967
+ // let mut buf = vec![0; max_mtu as usize];
960
968
let step_size = 20 ;
961
969
let min_mtu = 576 ; // TODO: Account for IPv6?
962
970
let linspace = mtu_spacing ( min_mtu, max_mtu, step_size) ;
963
- for mtu in & linspace {
964
- log :: warn! ( "Sending {mtu}" ) ;
965
- ping_monitor :: Pinger :: send_icmp_sized ( & mut pinger , * mtu ) . map_err ( Error :: SetMtu ) ? ;
966
- }
971
+
972
+ const IPV4_HEADER_SIZE : usize = 20 ;
973
+ const ICMP_HEADER_SIZE : usize = 8 ;
974
+
967
975
let mut largest_verified_mtu = min_mtu;
968
- // tokio::time::sleep(Duration::from_millis(3000)).await; // TODO: Remove this
969
- let mut buf = vec ! [ 0 ; max_mtu as usize ] ;
970
- for _ in & linspace {
971
- let size = match pinger. receive_ping_response ( & mut buf) . await {
972
- Ok ( size) => size,
973
- Err ( ping_monitor:: imp:: Error :: Read ( e) ) if e. kind ( ) == io:: ErrorKind :: TimedOut => {
974
- // TODO: This can sometimes trigger with max_mtu == largest_verified_mtu,
975
- // investigate why
976
- log:: warn!( "Lowering MTU from {max_mtu} to {largest_verified_mtu} because of dropped packets" ) ;
977
- return Ok ( largest_verified_mtu) ;
976
+ for ( i, mtu) in linspace. iter ( ) . enumerate ( ) {
977
+ log:: warn!( "Sending {mtu}" ) ;
978
+ let buf = vec ! [ 0 ; * mtu - IPV4_HEADER_SIZE - ICMP_HEADER_SIZE ] ; // TODO: avoid allocating
979
+ match pinger. ping ( PingSequence ( i as u16 ) , & buf) . await {
980
+ Ok ( ( packet, rtt) ) => {
981
+ println ! ( "{:?} {:0.2?}" , packet, rtt) ;
982
+ let surge_ping:: IcmpPacket :: V4 ( packet) = packet else {
983
+ panic ! ( ) ;
984
+ } ;
985
+ let size = packet. get_size ( ) + IPV4_HEADER_SIZE ;
986
+ assert_eq ! ( size, * mtu) ;
987
+ if size > largest_verified_mtu {
988
+ largest_verified_mtu = size;
989
+ }
990
+ // TODO: Remove
991
+ log:: warn!( "Got response of size {size}" )
978
992
}
979
- Err ( e) => return Err ( Error :: SetMtu ( e ) ) ,
993
+ Err ( e) => println ! ( "{}" , e ) ,
980
994
} ;
981
- debug_assert ! (
982
- linspace. contains( & size. try_into( ) . unwrap( ) ) ,
983
- "Received PING response was not the size of any sent pings"
984
- ) ;
985
- if size > largest_verified_mtu. into ( ) {
986
- largest_verified_mtu = size as u16 ;
987
- }
988
- // TODO: Remove
989
- log:: warn!( "Got response of size {size}" )
990
995
}
991
- // TODO: Remove
996
+
992
997
log:: debug!( "MTU {largest_verified_mtu} verified" ) ;
993
998
994
999
Ok ( largest_verified_mtu)
995
1000
}
996
1001
997
1002
#[ cfg( target_os = "linux" ) ]
998
- fn mtu_spacing ( x_start : u16 , x_end : u16 , step_size : u16 ) -> Vec < u16 > {
1003
+ fn mtu_spacing ( x_start : usize , x_end : usize , step_size : usize ) -> Vec < usize > {
999
1004
if x_start > x_end {
1000
1005
log:: warn!( "Setting MTU to {x_end} which is lower than" ) ;
1001
1006
return vec ! [ x_end] ;
1002
1007
// todo!("Handle manual MTU lower that minimum")
1003
1008
}
1004
1009
let in_between = ( ( x_start + 1 ) ..x_end) . filter ( |x| x % step_size == 0 ) ;
1005
- let mut ret = Vec :: with_capacity ( ( ( x_end - x_start) / 3 + 2 ) as usize ) ;
1010
+ let mut ret = Vec :: with_capacity ( ( x_end - x_start) / 3 + 2 ) ;
1006
1011
ret. push ( x_start) ;
1007
1012
ret. extend ( in_between) ;
1008
1013
ret. push ( x_end) ;
@@ -1080,7 +1085,7 @@ pub enum TunnelError {
1080
1085
/// Failed to setup a tunnel device.
1081
1086
#[ cfg( windows) ]
1082
1087
#[ error( display = "Failed to config IP interfaces on tunnel device" ) ]
1083
- SetupIpInterfaces ( #[ error( source) ] io:: Error ) ,
1088
+ SetupIpInterfaces ( #[ error( source) ] std :: io:: Error ) ,
1084
1089
1085
1090
/// Failed to configure Wireguard sockets to bypass the tunnel.
1086
1091
#[ cfg( target_os = "android" ) ]
0 commit comments