如果H1打开到H2的TCP连接,则H1向H2发送一个小数据包(< MSS)(H2不响应数据),H2发送延迟ACK需要多长时间?
TCP如何确保H1上的RTO定时器在收到延迟的ACK之前不会到期?
是否正确理解Linux默认情况下RTO最小为200ms,因此如果网络速度很快(RTO保持在最小200ms)并且数据包在从H1到H2的途中丢失,那么H1将在200ms内重试?如果网络速度慢,那么H1可能会等待超过200毫秒?
答案 0 :(得分:0)
关于延迟的ACK时序,RFC 1122说:
TCP应该实现延迟的ACK,但ACK不应该 被过度推迟;特别是延迟必须 小于0.5秒,并在一个全尺寸的流 那里的段应该至少每秒都是一个ACK 段。
因此,它取决于实施,当然如果可以降低应用程序性能
在Linux内核中,它们不会通过计时器或固定间隔发送延迟的ACK,正如您在下面的代码中看到的那样,它们的行为因条件而异。
正如您在net/ipv4/tcp_input.c
中所看到的,他们在评论中说:
分析时,您必须记住一些事项 tp-> ato延迟ack超时间隔的行为。当一个 连接启动,我们希望尽快恢复。该 问题是"好" TCP在数据开始时做起缓慢 传输。这意味着在我们发送前几个ACK之前 发件人将坐在他的最后,只排队他的大部分数据,因为 他只能在任何给定时间发送snd_cwnd未包装的数据包。对于 我们发送的每个ACK,他增加snd_cwnd并传输更多他的 队列。 -DaveM
static void tcp_event_data_recv(struct sock *sk, struct sk_buff *skb)
{
struct tcp_sock *tp = tcp_sk(sk);
struct inet_connection_sock *icsk = inet_csk(sk);
u32 now;
inet_csk_schedule_ack(sk);
tcp_measure_rcv_mss(sk, skb);
tcp_rcv_rtt_measure(tp);
now = tcp_time_stamp;
if (!icsk->icsk_ack.ato) {
/* The _first_ data packet received, initialize
* delayed ACK engine.
*/
tcp_incr_quickack(sk);
icsk->icsk_ack.ato = TCP_ATO_MIN;
} else {
int m = now - icsk->icsk_ack.lrcvtime;
if (m <= TCP_ATO_MIN / 2) {
/* The fastest case is the first. */
icsk->icsk_ack.ato = (icsk->icsk_ack.ato >> 1) + TCP_ATO_MIN / 2;
} else if (m < icsk->icsk_ack.ato) {
icsk->icsk_ack.ato = (icsk->icsk_ack.ato >> 1) + m;
if (icsk->icsk_ack.ato > icsk->icsk_rto)
icsk->icsk_ack.ato = icsk->icsk_rto;
} else if (m > icsk->icsk_rto) {
/* Too long gap. Apparently sender failed to
* restart window, so that we send ACKs quickly.
*/
tcp_incr_quickack(sk);
sk_mem_reclaim(sk);
}
}
icsk->icsk_ack.lrcvtime = now;
tcp_ecn_check_ce(tp, skb);
if (skb->len >= 128)
tcp_grow_window(sk, skb);
}