aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/tcp.h6
-rw-r--r--include/net/tcp.h10
-rw-r--r--net/ipv4/tcp_input.c12
-rw-r--r--net/ipv4/tcp_output.c19
4 files changed, 30 insertions, 17 deletions
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index bac17c59b24e..34acee662230 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -332,8 +332,10 @@ struct tcp_sock {
332 332
333 struct tcp_sack_block_wire recv_sack_cache[4]; 333 struct tcp_sack_block_wire recv_sack_cache[4];
334 334
335 u32 highest_sack; /* Start seq of globally highest revd SACK 335 struct sk_buff *highest_sack; /* highest skb with SACK received
336 * (validity guaranteed only if sacked_out > 0) */ 336 * (validity guaranteed only if
337 * sacked_out > 0)
338 */
337 339
338 /* from STCP, retrans queue hinting */ 340 /* from STCP, retrans queue hinting */
339 struct sk_buff* lost_skb_hint; 341 struct sk_buff* lost_skb_hint;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index d893b4480769..0ede804b16d4 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1312,6 +1312,16 @@ static inline int tcp_write_queue_empty(struct sock *sk)
1312 return skb_queue_empty(&sk->sk_write_queue); 1312 return skb_queue_empty(&sk->sk_write_queue);
1313} 1313}
1314 1314
1315/* Start sequence of the highest skb with SACKed bit, valid only if
1316 * sacked > 0 or when the caller has ensured validity by itself.
1317 */
1318static inline u32 tcp_highest_sack_seq(struct tcp_sock *tp)
1319{
1320 if (!tp->sacked_out)
1321 return tp->snd_una;
1322 return TCP_SKB_CB(tp->highest_sack)->seq;
1323}
1324
1315/* /proc */ 1325/* /proc */
1316enum tcp_seq_states { 1326enum tcp_seq_states {
1317 TCP_SEQ_STATE_LISTENING, 1327 TCP_SEQ_STATE_LISTENING,
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index c0e8f2b1fa7e..31294b52ad42 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1245,7 +1245,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
1245 int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3; 1245 int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3;
1246 int reord = tp->packets_out; 1246 int reord = tp->packets_out;
1247 int prior_fackets; 1247 int prior_fackets;
1248 u32 highest_sack_end_seq = tp->lost_retrans_low; 1248 u32 highest_sack_end_seq;
1249 int flag = 0; 1249 int flag = 0;
1250 int found_dup_sack = 0; 1250 int found_dup_sack = 0;
1251 int cached_fack_count; 1251 int cached_fack_count;
@@ -1256,7 +1256,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
1256 if (!tp->sacked_out) { 1256 if (!tp->sacked_out) {
1257 if (WARN_ON(tp->fackets_out)) 1257 if (WARN_ON(tp->fackets_out))
1258 tp->fackets_out = 0; 1258 tp->fackets_out = 0;
1259 tp->highest_sack = tp->snd_una; 1259 tp->highest_sack = tcp_write_queue_head(sk);
1260 } 1260 }
1261 prior_fackets = tp->fackets_out; 1261 prior_fackets = tp->fackets_out;
1262 1262
@@ -1483,10 +1483,9 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
1483 if (fack_count > tp->fackets_out) 1483 if (fack_count > tp->fackets_out)
1484 tp->fackets_out = fack_count; 1484 tp->fackets_out = fack_count;
1485 1485
1486 if (after(TCP_SKB_CB(skb)->seq, tp->highest_sack)) { 1486 if (after(TCP_SKB_CB(skb)->seq, tcp_highest_sack_seq(tp)))
1487 tp->highest_sack = TCP_SKB_CB(skb)->seq; 1487 tp->highest_sack = skb;
1488 highest_sack_end_seq = TCP_SKB_CB(skb)->end_seq; 1488
1489 }
1490 } else { 1489 } else {
1491 if (dup_sack && (sacked&TCPCB_RETRANS)) 1490 if (dup_sack && (sacked&TCPCB_RETRANS))
1492 reord = min(fack_count, reord); 1491 reord = min(fack_count, reord);
@@ -1514,6 +1513,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
1514 flag &= ~FLAG_ONLY_ORIG_SACKED; 1513 flag &= ~FLAG_ONLY_ORIG_SACKED;
1515 } 1514 }
1516 1515
1516 highest_sack_end_seq = TCP_SKB_CB(tp->highest_sack)->end_seq;
1517 if (tcp_is_fack(tp) && tp->retrans_out && 1517 if (tcp_is_fack(tp) && tp->retrans_out &&
1518 after(highest_sack_end_seq, tp->lost_retrans_low) && 1518 after(highest_sack_end_seq, tp->lost_retrans_low) &&
1519 icsk->icsk_ca_state == TCP_CA_Recovery) 1519 icsk->icsk_ca_state == TCP_CA_Recovery)
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index f4c1eef89af0..ce506af5ce07 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -657,13 +657,15 @@ static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned
657 * tweak SACK fastpath hint too as it would overwrite all changes unless 657 * tweak SACK fastpath hint too as it would overwrite all changes unless
658 * hint is also changed. 658 * hint is also changed.
659 */ 659 */
660static void tcp_adjust_fackets_out(struct tcp_sock *tp, struct sk_buff *skb, 660static void tcp_adjust_fackets_out(struct sock *sk, struct sk_buff *skb,
661 int decr) 661 int decr)
662{ 662{
663 struct tcp_sock *tp = tcp_sk(sk);
664
663 if (!tp->sacked_out || tcp_is_reno(tp)) 665 if (!tp->sacked_out || tcp_is_reno(tp))
664 return; 666 return;
665 667
666 if (!before(tp->highest_sack, TCP_SKB_CB(skb)->seq)) 668 if (!before(tcp_highest_sack_seq(tp), TCP_SKB_CB(skb)->seq))
667 tp->fackets_out -= decr; 669 tp->fackets_out -= decr;
668 670
669 /* cnt_hint is "off-by-one" compared with fackets_out (see sacktag) */ 671 /* cnt_hint is "off-by-one" compared with fackets_out (see sacktag) */
@@ -712,9 +714,8 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
712 TCP_SKB_CB(buff)->end_seq = TCP_SKB_CB(skb)->end_seq; 714 TCP_SKB_CB(buff)->end_seq = TCP_SKB_CB(skb)->end_seq;
713 TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(buff)->seq; 715 TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(buff)->seq;
714 716
715 if (tcp_is_sack(tp) && tp->sacked_out && 717 if (tcp_is_sack(tp) && tp->sacked_out && (skb == tp->highest_sack))
716 (TCP_SKB_CB(skb)->seq == tp->highest_sack)) 718 tp->highest_sack = buff;
717 tp->highest_sack = TCP_SKB_CB(buff)->seq;
718 719
719 /* PSH and FIN should only be set in the second packet. */ 720 /* PSH and FIN should only be set in the second packet. */
720 flags = TCP_SKB_CB(skb)->flags; 721 flags = TCP_SKB_CB(skb)->flags;
@@ -772,7 +773,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
772 tcp_dec_pcount_approx_int(&tp->sacked_out, diff); 773 tcp_dec_pcount_approx_int(&tp->sacked_out, diff);
773 tcp_verify_left_out(tp); 774 tcp_verify_left_out(tp);
774 } 775 }
775 tcp_adjust_fackets_out(tp, skb, diff); 776 tcp_adjust_fackets_out(sk, skb, diff);
776 } 777 }
777 778
778 /* Link BUFF into the send queue. */ 779 /* Link BUFF into the send queue. */
@@ -1712,7 +1713,7 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m
1712 tcp_skb_pcount(next_skb) != 1); 1713 tcp_skb_pcount(next_skb) != 1);
1713 1714
1714 if (WARN_ON(tcp_is_sack(tp) && tp->sacked_out && 1715 if (WARN_ON(tcp_is_sack(tp) && tp->sacked_out &&
1715 (TCP_SKB_CB(next_skb)->seq == tp->highest_sack))) 1716 (next_skb == tp->highest_sack)))
1716 return; 1717 return;
1717 1718
1718 /* Ok. We will be able to collapse the packet. */ 1719 /* Ok. We will be able to collapse the packet. */
@@ -1747,7 +1748,7 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m
1747 if (tcp_is_reno(tp) && tp->sacked_out) 1748 if (tcp_is_reno(tp) && tp->sacked_out)
1748 tcp_dec_pcount_approx(&tp->sacked_out, next_skb); 1749 tcp_dec_pcount_approx(&tp->sacked_out, next_skb);
1749 1750
1750 tcp_adjust_fackets_out(tp, next_skb, tcp_skb_pcount(next_skb)); 1751 tcp_adjust_fackets_out(sk, next_skb, tcp_skb_pcount(next_skb));
1751 tp->packets_out -= tcp_skb_pcount(next_skb); 1752 tp->packets_out -= tcp_skb_pcount(next_skb);
1752 1753
1753 /* changed transmit queue under us so clear hints */ 1754 /* changed transmit queue under us so clear hints */
@@ -2028,7 +2029,7 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
2028 break; 2029 break;
2029 tp->forward_skb_hint = skb; 2030 tp->forward_skb_hint = skb;
2030 2031
2031 if (after(TCP_SKB_CB(skb)->seq, tp->highest_sack)) 2032 if (after(TCP_SKB_CB(skb)->seq, tcp_highest_sack_seq(tp)))
2032 break; 2033 break;
2033 2034
2034 if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) 2035 if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)