aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGavin McCullagh <gavin.mccullagh@nuim.ie>2007-12-29 22:11:21 -0500
committerDavid S. Miller <davem@davemloft.net>2007-12-29 22:11:21 -0500
commit2072c228c9a05c004a230620196da7607cdcc5b6 (patch)
tree86516b5ea185dddb64734d2ea4e310118be13284
parent9cecd07c3f7a818a5865daad8cb5be408508dc99 (diff)
[TCP]: use non-delayed ACK for congestion control RTT
When a delayed ACK representing two packets arrives, there are two RTT samples available, one for each packet. The first (in order of seq number) will be artificially long due to the delay waiting for the second packet, the second will trigger the ACK and so will not itself be delayed. According to rfc1323, the SRTT used for RTO calculation should use the first rtt, so receivers echo the timestamp from the first packet in the delayed ack. For congestion control however, it seems measuring delayed ack delay is not desirable as it varies independently of congestion. The patch below causes seq_rtt and last_ackt to be updated with any available later packet rtts which should have less (and hopefully zero) delack delay. The rtt value then gets passed to ca_ops->pkts_acked(). Where TCP_CONG_RTT_STAMP was set, effort was made to supress RTTs from within a TSO chunk (!fully_acked), using only the final ACK (which includes any TSO delay) to generate RTTs. This patch removes these checks so RTTs are passed for each ACK to ca_ops->pkts_acked(). For non-delay based congestion control (cubic, h-tcp), rtt is sometimes used for rtt-scaling. In shortening the RTT, this may make them a little less aggressive. Delay-based schemes (eg vegas, veno, illinois) should get a cleaner, more accurate congestion signal, particularly for small cwnds. The congestion control module can potentially also filter out bad RTTs due to the delayed ack alarm by looking at the associated cnt which (where delayed acking is in use) should probably be 1 if the alarm went off or greater if the ACK was triggered by a packet. Signed-off-by: Gavin McCullagh <gavin.mccullagh@nuim.ie> Acked-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/tcp_input.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 889c89362bfc..b39f0d86e44c 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2651,6 +2651,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p,
2651 u32 cnt = 0; 2651 u32 cnt = 0;
2652 u32 reord = tp->packets_out; 2652 u32 reord = tp->packets_out;
2653 s32 seq_rtt = -1; 2653 s32 seq_rtt = -1;
2654 s32 ca_seq_rtt = -1;
2654 ktime_t last_ackt = net_invalid_timestamp(); 2655 ktime_t last_ackt = net_invalid_timestamp();
2655 2656
2656 while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) { 2657 while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) {
@@ -2659,6 +2660,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p,
2659 u32 packets_acked; 2660 u32 packets_acked;
2660 u8 sacked = scb->sacked; 2661 u8 sacked = scb->sacked;
2661 2662
2663 /* Determine how many packets and what bytes were acked, tso and else */
2662 if (after(scb->end_seq, tp->snd_una)) { 2664 if (after(scb->end_seq, tp->snd_una)) {
2663 if (tcp_skb_pcount(skb) == 1 || 2665 if (tcp_skb_pcount(skb) == 1 ||
2664 !after(tp->snd_una, scb->seq)) 2666 !after(tp->snd_una, scb->seq))
@@ -2686,15 +2688,16 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p,
2686 if (sacked & TCPCB_SACKED_RETRANS) 2688 if (sacked & TCPCB_SACKED_RETRANS)
2687 tp->retrans_out -= packets_acked; 2689 tp->retrans_out -= packets_acked;
2688 flag |= FLAG_RETRANS_DATA_ACKED; 2690 flag |= FLAG_RETRANS_DATA_ACKED;
2691 ca_seq_rtt = -1;
2689 seq_rtt = -1; 2692 seq_rtt = -1;
2690 if ((flag & FLAG_DATA_ACKED) || 2693 if ((flag & FLAG_DATA_ACKED) ||
2691 (packets_acked > 1)) 2694 (packets_acked > 1))
2692 flag |= FLAG_NONHEAD_RETRANS_ACKED; 2695 flag |= FLAG_NONHEAD_RETRANS_ACKED;
2693 } else { 2696 } else {
2697 ca_seq_rtt = now - scb->when;
2698 last_ackt = skb->tstamp;
2694 if (seq_rtt < 0) { 2699 if (seq_rtt < 0) {
2695 seq_rtt = now - scb->when; 2700 seq_rtt = ca_seq_rtt;
2696 if (fully_acked)
2697 last_ackt = skb->tstamp;
2698 } 2701 }
2699 if (!(sacked & TCPCB_SACKED_ACKED)) 2702 if (!(sacked & TCPCB_SACKED_ACKED))
2700 reord = min(cnt, reord); 2703 reord = min(cnt, reord);
@@ -2709,10 +2712,10 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p,
2709 !before(end_seq, tp->snd_up)) 2712 !before(end_seq, tp->snd_up))
2710 tp->urg_mode = 0; 2713 tp->urg_mode = 0;
2711 } else { 2714 } else {
2715 ca_seq_rtt = now - scb->when;
2716 last_ackt = skb->tstamp;
2712 if (seq_rtt < 0) { 2717 if (seq_rtt < 0) {
2713 seq_rtt = now - scb->when; 2718 seq_rtt = ca_seq_rtt;
2714 if (fully_acked)
2715 last_ackt = skb->tstamp;
2716 } 2719 }
2717 reord = min(cnt, reord); 2720 reord = min(cnt, reord);
2718 } 2721 }
@@ -2772,8 +2775,8 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p,
2772 net_invalid_timestamp())) 2775 net_invalid_timestamp()))
2773 rtt_us = ktime_us_delta(ktime_get_real(), 2776 rtt_us = ktime_us_delta(ktime_get_real(),
2774 last_ackt); 2777 last_ackt);
2775 else if (seq_rtt > 0) 2778 else if (ca_seq_rtt > 0)
2776 rtt_us = jiffies_to_usecs(seq_rtt); 2779 rtt_us = jiffies_to_usecs(ca_seq_rtt);
2777 } 2780 }
2778 2781
2779 ca_ops->pkts_acked(sk, pkts_acked, rtt_us); 2782 ca_ops->pkts_acked(sk, pkts_acked, rtt_us);