aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/tcp.h15
-rw-r--r--net/ipv4/tcp_output.c66
2 files changed, 34 insertions, 47 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h
index e54c76d75495..1b94b9bfe2dc 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -616,21 +616,6 @@ static inline int tcp_skb_mss(const struct sk_buff *skb)
616 return skb_shinfo(skb)->gso_size; 616 return skb_shinfo(skb)->gso_size;
617} 617}
618 618
619static inline void tcp_dec_pcount_approx_int(__u32 *count, const int decr)
620{
621 if (*count) {
622 *count -= decr;
623 if ((int)*count < 0)
624 *count = 0;
625 }
626}
627
628static inline void tcp_dec_pcount_approx(__u32 *count,
629 const struct sk_buff *skb)
630{
631 tcp_dec_pcount_approx_int(count, tcp_skb_pcount(skb));
632}
633
634/* Events passed to congestion control interface */ 619/* Events passed to congestion control interface */
635enum tcp_ca_event { 620enum tcp_ca_event {
636 CA_EVENT_TX_START, /* first transmit when no packets in flight */ 621 CA_EVENT_TX_START, /* first transmit when no packets in flight */
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index c1f259d2d33b..f1db89bb3aa7 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -754,6 +754,36 @@ static void tcp_adjust_fackets_out(struct sock *sk, struct sk_buff *skb,
754 tp->fackets_out -= decr; 754 tp->fackets_out -= decr;
755} 755}
756 756
757/* Pcount in the middle of the write queue got changed, we need to do various
758 * tweaks to fix counters
759 */
760static void tcp_adjust_pcount(struct sock *sk, struct sk_buff *skb, int decr)
761{
762 struct tcp_sock *tp = tcp_sk(sk);
763
764 tp->packets_out -= decr;
765
766 if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)
767 tp->sacked_out -= decr;
768 if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
769 tp->retrans_out -= decr;
770 if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST)
771 tp->lost_out -= decr;
772
773 /* Reno case is special. Sigh... */
774 if (tcp_is_reno(tp) && decr > 0)
775 tp->sacked_out -= min_t(u32, tp->sacked_out, decr);
776
777 tcp_adjust_fackets_out(sk, skb, decr);
778
779 if (tp->lost_skb_hint &&
780 before(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(tp->lost_skb_hint)->seq) &&
781 (tcp_is_fack(tp) || TCP_SKB_CB(skb)->sacked))
782 tp->lost_cnt_hint -= decr;
783
784 tcp_verify_left_out(tp);
785}
786
757/* Function to create two new TCP segments. Shrinks the given segment 787/* Function to create two new TCP segments. Shrinks the given segment
758 * to the specified size and appends a new segment with the rest of the 788 * to the specified size and appends a new segment with the rest of the
759 * packet to the list. This won't be called frequently, I hope. 789 * packet to the list. This won't be called frequently, I hope.
@@ -836,28 +866,8 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len,
836 int diff = old_factor - tcp_skb_pcount(skb) - 866 int diff = old_factor - tcp_skb_pcount(skb) -
837 tcp_skb_pcount(buff); 867 tcp_skb_pcount(buff);
838 868
839 tp->packets_out -= diff; 869 if (diff)
840 870 tcp_adjust_pcount(sk, skb, diff);
841 if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)
842 tp->sacked_out -= diff;
843 if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
844 tp->retrans_out -= diff;
845
846 if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST)
847 tp->lost_out -= diff;
848
849 /* Adjust Reno SACK estimate. */
850 if (tcp_is_reno(tp) && diff > 0) {
851 tcp_dec_pcount_approx_int(&tp->sacked_out, diff);
852 tcp_verify_left_out(tp);
853 }
854 tcp_adjust_fackets_out(sk, skb, diff);
855
856 if (tp->lost_skb_hint &&
857 before(TCP_SKB_CB(skb)->seq,
858 TCP_SKB_CB(tp->lost_skb_hint)->seq) &&
859 (tcp_is_fack(tp) || TCP_SKB_CB(skb)->sacked))
860 tp->lost_cnt_hint -= diff;
861 } 871 }
862 872
863 /* Link BUFF into the send queue. */ 873 /* Link BUFF into the send queue. */
@@ -1768,22 +1778,14 @@ static void tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb)
1768 * packet counting does not break. 1778 * packet counting does not break.
1769 */ 1779 */
1770 TCP_SKB_CB(skb)->sacked |= TCP_SKB_CB(next_skb)->sacked & TCPCB_EVER_RETRANS; 1780 TCP_SKB_CB(skb)->sacked |= TCP_SKB_CB(next_skb)->sacked & TCPCB_EVER_RETRANS;
1771 if (TCP_SKB_CB(next_skb)->sacked & TCPCB_SACKED_RETRANS)
1772 tp->retrans_out -= tcp_skb_pcount(next_skb);
1773 if (TCP_SKB_CB(next_skb)->sacked & TCPCB_LOST)
1774 tp->lost_out -= tcp_skb_pcount(next_skb);
1775 /* Reno case is special. Sigh... */
1776 if (tcp_is_reno(tp) && tp->sacked_out)
1777 tcp_dec_pcount_approx(&tp->sacked_out, next_skb);
1778
1779 tcp_adjust_fackets_out(sk, next_skb, tcp_skb_pcount(next_skb));
1780 tp->packets_out -= tcp_skb_pcount(next_skb);
1781 1781
1782 /* changed transmit queue under us so clear hints */ 1782 /* changed transmit queue under us so clear hints */
1783 tcp_clear_retrans_hints_partial(tp); 1783 tcp_clear_retrans_hints_partial(tp);
1784 if (next_skb == tp->retransmit_skb_hint) 1784 if (next_skb == tp->retransmit_skb_hint)
1785 tp->retransmit_skb_hint = skb; 1785 tp->retransmit_skb_hint = skb;
1786 1786
1787 tcp_adjust_pcount(sk, next_skb, tcp_skb_pcount(next_skb));
1788
1787 sk_wmem_free_skb(sk, next_skb); 1789 sk_wmem_free_skb(sk, next_skb);
1788} 1790}
1789 1791