Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tcp: fix stretch ACK bugs in Yeah

Change Yeah to properly handle stretch ACKs in additive
increase mode by passing in the count of ACKed packets
to tcp_cong_avoid_ai().

In addition, we re-implemented the scalable path using
tcp_cong_avoid_ai() and removed the pkts_acked variable.

Signed-off-by: Pengcheng Yang <yangpc@wangsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Pengcheng Yang and committed by
David S. Miller
fa4cb9eb ca04f5d4

+11 -30
+11 -30
net/ipv4/tcp_yeah.c
··· 36 36 37 37 u32 reno_count; 38 38 u32 fast_count; 39 - 40 - u32 pkts_acked; 41 39 }; 42 40 43 41 static void tcp_yeah_init(struct sock *sk) ··· 55 57 tp->snd_cwnd_clamp = min_t(u32, tp->snd_cwnd_clamp, 0xffffffff/128); 56 58 } 57 59 58 - static void tcp_yeah_pkts_acked(struct sock *sk, 59 - const struct ack_sample *sample) 60 - { 61 - const struct inet_connection_sock *icsk = inet_csk(sk); 62 - struct yeah *yeah = inet_csk_ca(sk); 63 - 64 - if (icsk->icsk_ca_state == TCP_CA_Open) 65 - yeah->pkts_acked = sample->pkts_acked; 66 - 67 - tcp_vegas_pkts_acked(sk, sample); 68 - } 69 - 70 60 static void tcp_yeah_cong_avoid(struct sock *sk, u32 ack, u32 acked) 71 61 { 72 62 struct tcp_sock *tp = tcp_sk(sk); ··· 63 77 if (!tcp_is_cwnd_limited(sk)) 64 78 return; 65 79 66 - if (tcp_in_slow_start(tp)) 67 - tcp_slow_start(tp, acked); 80 + if (tcp_in_slow_start(tp)) { 81 + acked = tcp_slow_start(tp, acked); 82 + if (!acked) 83 + goto do_vegas; 84 + } 68 85 69 - else if (!yeah->doing_reno_now) { 86 + if (!yeah->doing_reno_now) { 70 87 /* Scalable */ 71 - 72 - tp->snd_cwnd_cnt += yeah->pkts_acked; 73 - if (tp->snd_cwnd_cnt > min(tp->snd_cwnd, TCP_SCALABLE_AI_CNT)) { 74 - if (tp->snd_cwnd < tp->snd_cwnd_clamp) 75 - tp->snd_cwnd++; 76 - tp->snd_cwnd_cnt = 0; 77 - } 78 - 79 - yeah->pkts_acked = 1; 80 - 88 + tcp_cong_avoid_ai(tp, min(tp->snd_cwnd, TCP_SCALABLE_AI_CNT), 89 + acked); 81 90 } else { 82 91 /* Reno */ 83 - tcp_cong_avoid_ai(tp, tp->snd_cwnd, 1); 92 + tcp_cong_avoid_ai(tp, tp->snd_cwnd, acked); 84 93 } 85 94 86 95 /* The key players are v_vegas.beg_snd_una and v_beg_snd_nxt. ··· 99 118 * of bytes we send in an RTT is often less than our cwnd will allow. 100 119 * So we keep track of our cwnd separately, in v_beg_snd_cwnd. 101 120 */ 102 - 121 + do_vegas: 103 122 if (after(ack, yeah->vegas.beg_snd_nxt)) { 104 123 /* We do the Vegas calculations only if we got enough RTT 105 124 * samples that we can be reasonably sure that we got ··· 213 232 .set_state = tcp_vegas_state, 214 233 .cwnd_event = tcp_vegas_cwnd_event, 215 234 .get_info = tcp_vegas_get_info, 216 - .pkts_acked = tcp_yeah_pkts_acked, 235 + .pkts_acked = tcp_vegas_pkts_acked, 217 236 218 237 .owner = THIS_MODULE, 219 238 .name = "yeah",