diff options
Diffstat (limited to 'net/ipv4/tcp_output.c')
| -rw-r--r-- | net/ipv4/tcp_output.c | 73 |
1 files changed, 40 insertions, 33 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index c1f259d2d33..53300fa2359 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 | */ | ||
| 760 | static 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 | ||
| @@ -1891,7 +1893,12 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
| 1891 | if (tcp_fragment(sk, skb, cur_mss, cur_mss)) | 1893 | if (tcp_fragment(sk, skb, cur_mss, cur_mss)) |
| 1892 | return -ENOMEM; /* We'll try again later. */ | 1894 | return -ENOMEM; /* We'll try again later. */ |
| 1893 | } else { | 1895 | } else { |
| 1894 | tcp_init_tso_segs(sk, skb, cur_mss); | 1896 | int oldpcount = tcp_skb_pcount(skb); |
| 1897 | |||
| 1898 | if (unlikely(oldpcount > 1)) { | ||
| 1899 | tcp_init_tso_segs(sk, skb, cur_mss); | ||
| 1900 | tcp_adjust_pcount(sk, skb, oldpcount - tcp_skb_pcount(skb)); | ||
| 1901 | } | ||
| 1895 | } | 1902 | } |
| 1896 | 1903 | ||
| 1897 | tcp_retrans_try_collapse(sk, skb, cur_mss); | 1904 | tcp_retrans_try_collapse(sk, skb, cur_mss); |
