linuxのtcp_rmemの変更は何に影響するのか調べたのでメモっておく
大容量なファイル送信にかかる時間を短縮する為に色々調べていたら sysctlで送受信用ウィンドウ・サイズの最大値を変更するようアドバイスするサイトが多かったので 変更によって何が影響するのか調べてみた。
tcp_select_initial_window()のif (wscale_ok)の辺りが関係しそう。
#define TCP_MAX_WSCALE 14U
191 void tcp_select_initial_window(const struct sock *sk, int __space, __u32 mss, 192 __u32 *rcv_wnd, __u32 *window_clamp, 193 int wscale_ok, __u8 *rcv_wscale, 194 __u32 init_rcv_wnd) 195 { 196 unsigned int space = (__space < 0 ? 0 : __space); 197 198 /* If no clamp set the clamp to the max possible scaled window */ 199 if (*window_clamp == 0) 200 (*window_clamp) = (U16_MAX << TCP_MAX_WSCALE); 201 space = min(*window_clamp, space); 202 203 /* Quantize space offering to a multiple of mss if possible. */ 204 if (space > mss) 205 space = rounddown(space, mss); 206 207 /* NOTE: offering an initial window larger than 32767 208 * will break some buggy TCP stacks. If the admin tells us 209 * it is likely we could be speaking with such a buggy stack 210 * we will truncate our initial window offering to 32K-1 211 * unless the remote has sent us a window scaling option, 212 * which we interpret as a sign the remote TCP is not 213 * misinterpreting the window field as a signed quantity. 214 */ 215 if (sock_net(sk)->ipv4.sysctl_tcp_workaround_signed_windows) 216 (*rcv_wnd) = min(space, MAX_TCP_WINDOW); 217 else 218 (*rcv_wnd) = space; 219 220 (*rcv_wscale) = 0; 221 if (wscale_ok) { 222 /* Set window scaling on max possible window */ 223 space = max_t(u32, space, sock_net(sk)->ipv4.sysctl_tcp_rmem[2]); 224 space = max_t(u32, space, sysctl_rmem_max); 225 space = min_t(u32, space, *window_clamp); 226 while (space > U16_MAX && (*rcv_wscale) < TCP_MAX_WSCALE) { 227 space >>= 1; 228 (*rcv_wscale)++; 229 } 230 } 231 232 if (mss > (1 << *rcv_wscale)) { 233 if (!init_rcv_wnd) /* Use default unless specified otherwise */ 234 init_rcv_wnd = tcp_default_init_rwnd(mss); 235 *rcv_wnd = min(*rcv_wnd, init_rcv_wnd * mss); 236 } 237 238 /* Set the clamp no higher than max representable value */ 239 (*window_clamp) = min_t(__u32, U16_MAX << (*rcv_wscale), *window_clamp); 240 } 241 EXPORT_SYMBOL(tcp_select_initial_window);
TCP window scale オプションが有効だった場合、tcp_rmemの設定値に応じて 最大値14のTCP window scale の値が変更になる。
TCP window scale 値は3 Way ハンドシェイク時に通知され、Wireshark等で確認できる。
この画像ではWindow scale: 6
tcp_rmemの値を増やすと、このWindow scaleが最大14まで上昇する。
ssコマンドなんかでも確認できて、下の画像の wscale:5,6がそれ。
tcp_rmemが3839488だった場合のWindow scale値は6で、通信相手のWindow scale値が5。
tcp_rmemを増やすことによって、レイテンシーに影響する場合もあるようなので注意が必要ですね。 The story of one latency spike