diff options
author | Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> | 2007-10-09 04:24:15 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:52:08 -0400 |
commit | 91fed7a15c9222af29a653ecb0ee72cff178fdd8 (patch) | |
tree | 53c72bd6c1bf3216e46565761bc34ea066f5b995 | |
parent | 0dde7b5404a3d52dcd9ce66d46197f6c3ca97dda (diff) |
[TCP]: Make fackets_out accurate
Substraction for fackets_out is unconditional when snd_una
advances, thus there's no need to do it inside the loop. Just
make sure correct bounds are honored.
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/tcp_input.c | 10 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 44 |
2 files changed, 29 insertions, 25 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index f9e4d7ad68b7..46aedd6ca020 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2299,8 +2299,8 @@ tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag) | |||
2299 | * 1. Reno does not count dupacks (sacked_out) automatically. */ | 2299 | * 1. Reno does not count dupacks (sacked_out) automatically. */ |
2300 | if (!tp->packets_out) | 2300 | if (!tp->packets_out) |
2301 | tp->sacked_out = 0; | 2301 | tp->sacked_out = 0; |
2302 | /* 2. SACK counts snd_fack in packets inaccurately. */ | 2302 | |
2303 | if (tp->sacked_out == 0) | 2303 | if (WARN_ON(!tp->sacked_out && tp->fackets_out)) |
2304 | tp->fackets_out = 0; | 2304 | tp->fackets_out = 0; |
2305 | 2305 | ||
2306 | /* Now state machine starts. | 2306 | /* Now state machine starts. |
@@ -2568,10 +2568,6 @@ static int tcp_tso_acked(struct sock *sk, struct sk_buff *skb, | |||
2568 | } else if (*seq_rtt < 0) | 2568 | } else if (*seq_rtt < 0) |
2569 | *seq_rtt = now - scb->when; | 2569 | *seq_rtt = now - scb->when; |
2570 | 2570 | ||
2571 | if (tp->fackets_out) { | ||
2572 | __u32 dval = min(tp->fackets_out, packets_acked); | ||
2573 | tp->fackets_out -= dval; | ||
2574 | } | ||
2575 | /* hint's skb might be NULL but we don't need to care */ | 2571 | /* hint's skb might be NULL but we don't need to care */ |
2576 | tp->fastpath_cnt_hint -= min_t(u32, packets_acked, | 2572 | tp->fastpath_cnt_hint -= min_t(u32, packets_acked, |
2577 | tp->fastpath_cnt_hint); | 2573 | tp->fastpath_cnt_hint); |
@@ -2657,7 +2653,6 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p) | |||
2657 | seq_rtt = now - scb->when; | 2653 | seq_rtt = now - scb->when; |
2658 | last_ackt = skb->tstamp; | 2654 | last_ackt = skb->tstamp; |
2659 | } | 2655 | } |
2660 | tcp_dec_pcount_approx(&tp->fackets_out, skb); | ||
2661 | tp->packets_out -= tcp_skb_pcount(skb); | 2656 | tp->packets_out -= tcp_skb_pcount(skb); |
2662 | tcp_unlink_write_queue(skb, sk); | 2657 | tcp_unlink_write_queue(skb, sk); |
2663 | sk_stream_free_skb(sk, skb); | 2658 | sk_stream_free_skb(sk, skb); |
@@ -2672,6 +2667,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p) | |||
2672 | tcp_ack_update_rtt(sk, acked, seq_rtt); | 2667 | tcp_ack_update_rtt(sk, acked, seq_rtt); |
2673 | tcp_rearm_rto(sk); | 2668 | tcp_rearm_rto(sk); |
2674 | 2669 | ||
2670 | tp->fackets_out -= min(pkts_acked, tp->fackets_out); | ||
2675 | if (tcp_is_reno(tp)) | 2671 | if (tcp_is_reno(tp)) |
2676 | tcp_remove_reno_sacks(sk, pkts_acked); | 2672 | tcp_remove_reno_sacks(sk, pkts_acked); |
2677 | 2673 | ||
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 9df5b2a4da6e..cbe8bf6dab5f 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -652,6 +652,26 @@ static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned | |||
652 | } | 652 | } |
653 | } | 653 | } |
654 | 654 | ||
655 | /* When a modification to fackets out becomes necessary, we need to check | ||
656 | * skb is counted to fackets_out or not. Another important thing is to | ||
657 | * tweak SACK fastpath hint too as it would overwrite all changes unless | ||
658 | * hint is also changed. | ||
659 | */ | ||
660 | static void tcp_adjust_fackets_out(struct tcp_sock *tp, struct sk_buff *skb, | ||
661 | int decr) | ||
662 | { | ||
663 | if (!tp->sacked_out) | ||
664 | return; | ||
665 | |||
666 | if (!before(tp->highest_sack, TCP_SKB_CB(skb)->seq)) | ||
667 | tp->fackets_out -= decr; | ||
668 | |||
669 | /* cnt_hint is "off-by-one" compared with fackets_out (see sacktag) */ | ||
670 | if (tp->fastpath_skb_hint != NULL && | ||
671 | after(TCP_SKB_CB(tp->fastpath_skb_hint)->seq, TCP_SKB_CB(skb)->seq)) | ||
672 | tp->fastpath_cnt_hint -= decr; | ||
673 | } | ||
674 | |||
655 | /* Function to create two new TCP segments. Shrinks the given segment | 675 | /* Function to create two new TCP segments. Shrinks the given segment |
656 | * to the specified size and appends a new segment with the rest of the | 676 | * to the specified size and appends a new segment with the rest of the |
657 | * packet to the list. This won't be called frequently, I hope. | 677 | * packet to the list. This won't be called frequently, I hope. |
@@ -746,21 +766,12 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss | |||
746 | if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) | 766 | if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) |
747 | tp->lost_out -= diff; | 767 | tp->lost_out -= diff; |
748 | 768 | ||
749 | if (diff > 0) { | 769 | /* Adjust Reno SACK estimate. */ |
750 | /* Adjust Reno SACK estimate. */ | 770 | if (tcp_is_reno(tp) && diff > 0) { |
751 | if (tcp_is_reno(tp)) { | 771 | tcp_dec_pcount_approx_int(&tp->sacked_out, diff); |
752 | tcp_dec_pcount_approx_int(&tp->sacked_out, diff); | 772 | tcp_verify_left_out(tp); |
753 | tcp_verify_left_out(tp); | ||
754 | } | ||
755 | |||
756 | tcp_dec_pcount_approx_int(&tp->fackets_out, diff); | ||
757 | /* SACK fastpath might overwrite it unless dealt with */ | ||
758 | if (tp->fastpath_skb_hint != NULL && | ||
759 | after(TCP_SKB_CB(tp->fastpath_skb_hint)->seq, | ||
760 | TCP_SKB_CB(skb)->seq)) { | ||
761 | tcp_dec_pcount_approx_int(&tp->fastpath_cnt_hint, diff); | ||
762 | } | ||
763 | } | 773 | } |
774 | tcp_adjust_fackets_out(tp, skb, diff); | ||
764 | } | 775 | } |
765 | 776 | ||
766 | /* Link BUFF into the send queue. */ | 777 | /* Link BUFF into the send queue. */ |
@@ -1746,10 +1757,7 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m | |||
1746 | if (tcp_is_reno(tp) && tp->sacked_out) | 1757 | if (tcp_is_reno(tp) && tp->sacked_out) |
1747 | tcp_dec_pcount_approx(&tp->sacked_out, next_skb); | 1758 | tcp_dec_pcount_approx(&tp->sacked_out, next_skb); |
1748 | 1759 | ||
1749 | /* Not quite right: it can be > snd.fack, but | 1760 | tcp_adjust_fackets_out(tp, skb, tcp_skb_pcount(next_skb)); |
1750 | * it is better to underestimate fackets. | ||
1751 | */ | ||
1752 | tcp_dec_pcount_approx(&tp->fackets_out, next_skb); | ||
1753 | tp->packets_out -= tcp_skb_pcount(next_skb); | 1761 | tp->packets_out -= tcp_skb_pcount(next_skb); |
1754 | sk_stream_free_skb(sk, next_skb); | 1762 | sk_stream_free_skb(sk, next_skb); |
1755 | } | 1763 | } |