@@ -70,6 +70,57 @@ fn test_so_buf() {
70
70
assert ! ( actual >= bufsize) ;
71
71
}
72
72
73
+ #[ test]
74
+ fn test_so_tcp_maxseg ( ) {
75
+ use std:: net:: SocketAddr ;
76
+ use std:: str:: FromStr ;
77
+ use nix:: sys:: socket:: { accept, bind, connect, listen, InetAddr , SockAddr } ;
78
+ use nix:: unistd:: { close, write} ;
79
+
80
+ let std_sa = SocketAddr :: from_str ( "127.0.0.1:4001" ) . unwrap ( ) ;
81
+ let inet_addr = InetAddr :: from_std ( & std_sa) ;
82
+ let sock_addr = SockAddr :: new_inet ( inet_addr) ;
83
+
84
+ let rsock = socket ( AddressFamily :: Inet , SockType :: Stream , SockFlag :: empty ( ) , SockProtocol :: Tcp )
85
+ . unwrap ( ) ;
86
+ bind ( rsock, & sock_addr) . unwrap ( ) ;
87
+ listen ( rsock, 10 ) . unwrap ( ) ;
88
+ let initial = getsockopt ( rsock, sockopt:: TcpMaxSeg ) . unwrap ( ) ;
89
+ // Initial MSS is expected to be 536 (https://tools.ietf.org/html/rfc879#section-1) but some
90
+ // platforms keep it even lower. This might fail if you've tuned your initial MSS to be larger
91
+ // than 700
92
+ cfg_if ! {
93
+ if #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ] {
94
+ let segsize: u32 = 873 ;
95
+ assert!( initial < segsize) ;
96
+ setsockopt( rsock, sockopt:: TcpMaxSeg , & segsize) . unwrap( ) ;
97
+ } else {
98
+ assert!( initial < 700 ) ;
99
+ }
100
+ }
101
+
102
+ // Connect and check the MSS that was advertised
103
+ let ssock = socket ( AddressFamily :: Inet , SockType :: Stream , SockFlag :: empty ( ) , SockProtocol :: Tcp )
104
+ . unwrap ( ) ;
105
+ connect ( ssock, & sock_addr) . unwrap ( ) ;
106
+ let rsess = accept ( rsock) . unwrap ( ) ;
107
+ write ( rsess, b"hello" ) . unwrap ( ) ;
108
+ let actual = getsockopt ( ssock, sockopt:: TcpMaxSeg ) . unwrap ( ) ;
109
+ // Actual max segment size takes header lengths into account, max IPv4 options (60 bytes) + max
110
+ // TCP options (40 bytes) are subtracted from the requested maximum as a lower boundary.
111
+ cfg_if ! {
112
+ if #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ] {
113
+ assert!( ( segsize - 100 ) <= actual) ;
114
+ assert!( actual <= segsize) ;
115
+ } else {
116
+ assert!( initial < actual) ;
117
+ assert!( 536 < actual) ;
118
+ }
119
+ }
120
+ close ( rsock) . unwrap ( ) ;
121
+ close ( ssock) . unwrap ( ) ;
122
+ }
123
+
73
124
// The CI doesn't supported getsockopt and setsockopt on emulated processors.
74
125
// It's beleived that a QEMU issue, the tests run ok on a fully emulated system.
75
126
// Current CI just run the binary with QEMU but the Kernel remains the same as the host.
0 commit comments