Linux SYNパケット取りこぼし
Linuxで負荷も問題になるほど高くなくlisten及びsynのbacklogも溢れてないのに
特定のホストからのみSYNを吸い込んでSYN-ACKを返さない事がある場合があった。
必ず吸い込むというわけではなく、一発で通る場合と数回再送受けてから処理するのも
あったりして謎な感じ。tcpdumpで見てもパケット単位の不整合は特に見あたらない。
受け付けている環境で変更されていたTCPパラメータは以下で、syncookies以外は
IN/OUTどの部分の処理に関わるのかDocument読んでも良く解らないので、それぞれに
ついて参照箇所を調べてみた。(PATHはKERNELのnet/以下)
Outbound Connectionだけ影響
ipv4/tcp_ipv4.c:tcp_v4_connect
ipv4/tcp_ipv4.c:tcp_v4_hash_connect
ipv4/tcp_ipv4.c:__tcp_v4_check_established
Inbound/Outbound Connection両方に影響
ipv4/tcp_ipv4.c:tcp_v4_connect
ipv4/tcp_ipv4.c:tcp_v4_conn_request
Inbound Connectionだけ影響
ipv4/tcp_ipv4.c:tcp_v4_conn_request
今回のケースはSYN受けてもACK返さないので、発動条件に引っかかっていない
tcp_syncookiesは多分無罪。となるとtcp_tw_recycleが怪しいので処理してる箇所を
調べてみたら、ipv4/tcp_ipv4.cに以下の様な箇所があった。
if (tp.saw_tstamp && sysctl_tcp_tw_recycle && (dst = tcp_v4_route_req(sk, req)) != NULL && (peer = rt_get_peer((struct rtable*)dst)) != NULL && peer->v4daddr == saddr) { if (xtime.tv_sec < peer->tcp_ts_stamp + TCP_PAWS_MSL && (s32)(peer->tcp_ts - req->ts_recent) > TCP_PAWS_WINDOW) { NET_INC_STATS_BH(PAWSPassiveRejected); dst_release(dst); goto drop_and_free; } }
これに抵触すると零されるので確かに状況としては合っている。
PAWSPassiveRejectedでカウンタ取っているので、それぞれ以下で確認可能。
netstat -s passive connections rejected because of time stamp /prc/net/netstat PAWSPassive
該当箇所が問題ならば、sysctlでtcp_tw_recycleを無効にすれば解決するけど
現象として気になるのでもう少しデータ集めて調査続行かな。