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を無効にすれば解決するけど
現象として気になるのでもう少しデータ集めて調査続行かな。