Commit 2072c228c9a05c004a230620196da7607cdcc5b6

Authored by Gavin McCullagh
Committed by David S. Miller
1 parent 9cecd07c3f

[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>

Showing 1 changed file with 11 additions and 8 deletions Side-by-side Diff

net/ipv4/tcp_input.c
... ... @@ -2651,6 +2651,7 @@
2651 2651 u32 cnt = 0;
2652 2652 u32 reord = tp->packets_out;
2653 2653 s32 seq_rtt = -1;
  2654 + s32 ca_seq_rtt = -1;
2654 2655 ktime_t last_ackt = net_invalid_timestamp();
2655 2656  
2656 2657 while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) {
... ... @@ -2659,6 +2660,7 @@
2659 2660 u32 packets_acked;
2660 2661 u8 sacked = scb->sacked;
2661 2662  
  2663 + /* Determine how many packets and what bytes were acked, tso and else */
2662 2664 if (after(scb->end_seq, tp->snd_una)) {
2663 2665 if (tcp_skb_pcount(skb) == 1 ||
2664 2666 !after(tp->snd_una, scb->seq))
2665 2667  
2666 2668  
... ... @@ -2686,15 +2688,16 @@
2686 2688 if (sacked & TCPCB_SACKED_RETRANS)
2687 2689 tp->retrans_out -= packets_acked;
2688 2690 flag |= FLAG_RETRANS_DATA_ACKED;
  2691 + ca_seq_rtt = -1;
2689 2692 seq_rtt = -1;
2690 2693 if ((flag & FLAG_DATA_ACKED) ||
2691 2694 (packets_acked > 1))
2692 2695 flag |= FLAG_NONHEAD_RETRANS_ACKED;
2693 2696 } else {
  2697 + ca_seq_rtt = now - scb->when;
  2698 + last_ackt = skb->tstamp;
2694 2699 if (seq_rtt < 0) {
2695   - seq_rtt = now - scb->when;
2696   - if (fully_acked)
2697   - last_ackt = skb->tstamp;
  2700 + seq_rtt = ca_seq_rtt;
2698 2701 }
2699 2702 if (!(sacked & TCPCB_SACKED_ACKED))
2700 2703 reord = min(cnt, reord);
2701 2704  
... ... @@ -2709,10 +2712,10 @@
2709 2712 !before(end_seq, tp->snd_up))
2710 2713 tp->urg_mode = 0;
2711 2714 } else {
  2715 + ca_seq_rtt = now - scb->when;
  2716 + last_ackt = skb->tstamp;
2712 2717 if (seq_rtt < 0) {
2713   - seq_rtt = now - scb->when;
2714   - if (fully_acked)
2715   - last_ackt = skb->tstamp;
  2718 + seq_rtt = ca_seq_rtt;
2716 2719 }
2717 2720 reord = min(cnt, reord);
2718 2721 }
... ... @@ -2772,8 +2775,8 @@
2772 2775 net_invalid_timestamp()))
2773 2776 rtt_us = ktime_us_delta(ktime_get_real(),
2774 2777 last_ackt);
2775   - else if (seq_rtt > 0)
2776   - rtt_us = jiffies_to_usecs(seq_rtt);
  2778 + else if (ca_seq_rtt > 0)
  2779 + rtt_us = jiffies_to_usecs(ca_seq_rtt);
2777 2780 }
2778 2781  
2779 2782 ca_ops->pkts_acked(sk, pkts_acked, rtt_us);