LinuxのTCPカーネルで再送信タイマーが実行されているかどうかを確認するにはどうすればよいですか?
3 に答える
送信者と受信者の2つのホストを設定できます。2つの間に接続を設定し、大きなファイルを転送するなど、トラフィックを送信します。両側のトラフィックをスニッフィングします。
トラフィックが送信されている間に、一部のパケットをドロップするファイアウォールルールを設定します。次に、x%をランダムにドロップする例を示します。
# for randomly dropping 10% of incoming packets:
iptables -A INPUT -m statistic --mode random \
--probability 0.1 -j DROP
掃除:
# for the incoming packets:
iptables -D INPUT -m statistic --mode random \
--probability 0.1 -j DROP
キャプチャを見ると、ドロップされたパケットを克服するために、送信者がパケットを複数回送信したことがわかります。これは、再送信が機能していることを示しています。
ドロップを100%まで上げると、タイムアウトのみが原因の再送信が表示されます。
私は問題を解決しました、そして私は解決策を共有するべきだと思います。つまり、ACKを受信すると、inet_csk_clear_xmit_timerを呼び出して再送タイマーをオフにします。icsk_pendingは、inet_connection_sock構造内のフラグです。このフラグは、最も古い未処理データのACKが受信され、その結果、再送信タイマーがオフになると設定されません。Linux3.7カーネルから
static inline void inet_csk_clear_xmit_timer(struct sock *sk, const int what)
{
struct inet_connection_sock *icsk = inet_csk(sk);
**if (what == ICSK_TIME_RETRANS || what == ICSK_TIME_PROBE0) {
icsk->icsk_pending = 0;**
#ifdef INET_CSK_CLEAR_TIMERS
sk_stop_timer(sk, &icsk->icsk_retransmit_timer);
#endif
} else if (what == ICSK_TIME_DACK) {
icsk->icsk_ack.blocked = icsk->icsk_ack.pending = 0;
#ifdef INET_CSK_CLEAR_TIMERS
sk_stop_timer(sk, &icsk->icsk_delack_timer);
#endif
}
#ifdef INET_CSK_DEBUG
else {
pr_debug("%s", inet_csk_timer_bug_msg);
}
#endif
}
それ以外の場合はTCPの実装ではありません。RFCを参照してください。
システムの一部が機能していないことに誰かが気付いたと想像する人もいるかもしれません。
調整については、以下の構成パラメーターを参照してください。/proc/sys/net/ipv4