aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@helsinki.fi>2009-02-27 23:44:28 -0500
committerDavid S. Miller <davem@davemloft.net>2009-03-02 06:00:09 -0500
commit59a08cba6a604a265e45e9b970e372554cf46627 (patch)
tree044bc6b23d3bd6a786dafb763363fa1da89afa65 /net
parentac11ba753f3aa839292c1a3b6c971c637ad2e839 (diff)
tcp: fix lost_cnt_hint miscounts
It is possible that lost_cnt_hint gets underflow in tcp_clean_rtx_queue because the cumulative ACK can cover the segment where lost_skb_hint points to only partially, which means that the hint is not cleared, opposite to what my (earlier) comment claimed. Also I don't agree what I ended up writing about non-trivial case there to be what I intented to say. It was not supposed to happen that the hint won't get cleared and we underflow in any scenario. In general, this is quite hard to trigger in practice. Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/tcp_input.c13
1 files changed, 5 insertions, 8 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index c28976a7e596..3f2f09091bcf 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3273,18 +3273,15 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
3273 if (tcp_is_reno(tp)) { 3273 if (tcp_is_reno(tp)) {
3274 tcp_remove_reno_sacks(sk, pkts_acked); 3274 tcp_remove_reno_sacks(sk, pkts_acked);
3275 } else { 3275 } else {
3276 int delta;
3277
3276 /* Non-retransmitted hole got filled? That's reordering */ 3278 /* Non-retransmitted hole got filled? That's reordering */
3277 if (reord < prior_fackets) 3279 if (reord < prior_fackets)
3278 tcp_update_reordering(sk, tp->fackets_out - reord, 0); 3280 tcp_update_reordering(sk, tp->fackets_out - reord, 0);
3279 3281
3280 /* No need to care for underflows here because 3282 delta = tcp_is_fack(tp) ? pkts_acked :
3281 * the lost_skb_hint gets NULLed if we're past it 3283 prior_sacked - tp->sacked_out;
3282 * (or something non-trivial happened) 3284 tp->lost_cnt_hint -= min(tp->lost_cnt_hint, delta);
3283 */
3284 if (tcp_is_fack(tp))
3285 tp->lost_cnt_hint -= pkts_acked;
3286 else
3287 tp->lost_cnt_hint -= prior_sacked - tp->sacked_out;
3288 } 3285 }
3289 3286
3290 tp->fackets_out -= min(pkts_acked, tp->fackets_out); 3287 tp->fackets_out -= min(pkts_acked, tp->fackets_out);