aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/tcp.h6
-rw-r--r--net/ipv4/tcp_input.c14
-rw-r--r--net/ipv4/tcp_output.c12
3 files changed, 21 insertions, 11 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h
index d78ad9bfcfa7..456983d1fcec 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1067,11 +1067,15 @@ static inline void tcp_mib_init(void)
1067} 1067}
1068 1068
1069/* from STCP */ 1069/* from STCP */
1070static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp) { 1070static inline void tcp_clear_retrans_hints_partial(struct tcp_sock *tp) {
1071 tp->lost_skb_hint = NULL; 1071 tp->lost_skb_hint = NULL;
1072 tp->scoreboard_skb_hint = NULL; 1072 tp->scoreboard_skb_hint = NULL;
1073 tp->retransmit_skb_hint = NULL; 1073 tp->retransmit_skb_hint = NULL;
1074 tp->forward_skb_hint = NULL; 1074 tp->forward_skb_hint = NULL;
1075}
1076
1077static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp) {
1078 tcp_clear_retrans_hints_partial(tp);
1075 tp->fastpath_skb_hint = NULL; 1079 tp->fastpath_skb_hint = NULL;
1076} 1080}
1077 1081
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 65b9f274a774..4c10d9cad20f 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1671,7 +1671,7 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag)
1671 tp->high_seq = tp->frto_highmark; 1671 tp->high_seq = tp->frto_highmark;
1672 TCP_ECN_queue_cwr(tp); 1672 TCP_ECN_queue_cwr(tp);
1673 1673
1674 tcp_clear_all_retrans_hints(tp); 1674 tcp_clear_retrans_hints_partial(tp);
1675} 1675}
1676 1676
1677void tcp_clear_retrans(struct tcp_sock *tp) 1677void tcp_clear_retrans(struct tcp_sock *tp)
@@ -1711,10 +1711,14 @@ void tcp_enter_loss(struct sock *sk, int how)
1711 tp->bytes_acked = 0; 1711 tp->bytes_acked = 0;
1712 tcp_clear_retrans(tp); 1712 tcp_clear_retrans(tp);
1713 1713
1714 /* Push undo marker, if it was plain RTO and nothing 1714 if (!how) {
1715 * was retransmitted. */ 1715 /* Push undo marker, if it was plain RTO and nothing
1716 if (!how) 1716 * was retransmitted. */
1717 tp->undo_marker = tp->snd_una; 1717 tp->undo_marker = tp->snd_una;
1718 tcp_clear_retrans_hints_partial(tp);
1719 } else {
1720 tcp_clear_all_retrans_hints(tp);
1721 }
1718 1722
1719 tcp_for_write_queue(skb, sk) { 1723 tcp_for_write_queue(skb, sk) {
1720 if (skb == tcp_send_head(sk)) 1724 if (skb == tcp_send_head(sk))
@@ -1741,8 +1745,6 @@ void tcp_enter_loss(struct sock *sk, int how)
1741 TCP_ECN_queue_cwr(tp); 1745 TCP_ECN_queue_cwr(tp);
1742 /* Abort FRTO algorithm if one is in progress */ 1746 /* Abort FRTO algorithm if one is in progress */
1743 tp->frto_counter = 0; 1747 tp->frto_counter = 0;
1744
1745 tcp_clear_all_retrans_hints(tp);
1746} 1748}
1747 1749
1748static int tcp_check_sack_reneging(struct sock *sk) 1750static int tcp_check_sack_reneging(struct sock *sk)
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index f46d24b8410f..cbb83acd830a 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -687,7 +687,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
687 687
688 BUG_ON(len > skb->len); 688 BUG_ON(len > skb->len);
689 689
690 tcp_clear_all_retrans_hints(tp); 690 tcp_clear_retrans_hints_partial(tp);
691 nsize = skb_headlen(skb) - len; 691 nsize = skb_headlen(skb) - len;
692 if (nsize < 0) 692 if (nsize < 0)
693 nsize = 0; 693 nsize = 0;
@@ -1718,9 +1718,6 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m
1718 BUG_ON(tcp_skb_pcount(skb) != 1 || 1718 BUG_ON(tcp_skb_pcount(skb) != 1 ||
1719 tcp_skb_pcount(next_skb) != 1); 1719 tcp_skb_pcount(next_skb) != 1);
1720 1720
1721 /* changing transmit queue under us so clear hints */
1722 tcp_clear_all_retrans_hints(tp);
1723
1724 /* Ok. We will be able to collapse the packet. */ 1721 /* Ok. We will be able to collapse the packet. */
1725 tcp_unlink_write_queue(next_skb, sk); 1722 tcp_unlink_write_queue(next_skb, sk);
1726 1723
@@ -1759,6 +1756,13 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m
1759 1756
1760 tcp_adjust_fackets_out(tp, skb, tcp_skb_pcount(next_skb)); 1757 tcp_adjust_fackets_out(tp, skb, tcp_skb_pcount(next_skb));
1761 tp->packets_out -= tcp_skb_pcount(next_skb); 1758 tp->packets_out -= tcp_skb_pcount(next_skb);
1759
1760 /* changed transmit queue under us so clear hints */
1761 tcp_clear_retrans_hints_partial(tp);
1762 /* manually tune sacktag skb hint */
1763 if (tp->fastpath_skb_hint == next_skb)
1764 tp->fastpath_skb_hint = skb;
1765
1762 sk_stream_free_skb(sk, next_skb); 1766 sk_stream_free_skb(sk, next_skb);
1763 } 1767 }
1764} 1768}