Commit 8b2674f0 authored by David S. Miller's avatar David S. Miller

[TCP]: Fix packet counting during retransmission.

We run into a potential problem if we are doing
TSO and we reduce the congestion window.  We might
create a case where the TSO packet is what we need
to resend but the congestion window is not large
enough to allow it through.

The fix is very simple, since tcp_retransmit_skb()
is going to chop the size of the packet down to size
of the normal non-TSO MSS, we can pretend at the top
level that each SKB is composed of only one real MSS
worth of data.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f55cdc77
...@@ -1065,12 +1065,15 @@ void tcp_xmit_retransmit_queue(struct sock *sk) ...@@ -1065,12 +1065,15 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
if (packet_cnt) { if (packet_cnt) {
sk_stream_for_retrans_queue(skb, sk) { sk_stream_for_retrans_queue(skb, sk) {
__u8 sacked = TCP_SKB_CB(skb)->sacked; __u8 sacked = TCP_SKB_CB(skb)->sacked;
int pkts = TCP_SKB_CB(skb)->tso_factor;
BUG_ON(!pkts); /* Assume this retransmit will generate
* only one packet for congestion window
if ((tcp_packets_in_flight(tp) + (pkts-1)) >= * calculation purposes. This works because
tp->snd_cwnd) * tcp_retransmit_skb() will chop up the
* packet to be MSS sized and all the
* packet counting works out.
*/
if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
return; return;
if (sacked&TCPCB_LOST) { if (sacked&TCPCB_LOST) {
...@@ -1117,15 +1120,16 @@ void tcp_xmit_retransmit_queue(struct sock *sk) ...@@ -1117,15 +1120,16 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
packet_cnt = 0; packet_cnt = 0;
sk_stream_for_retrans_queue(skb, sk) { sk_stream_for_retrans_queue(skb, sk) {
int pkts = TCP_SKB_CB(skb)->tso_factor; /* Similar to the retransmit loop above we
* can pretend that the retransmitted SKB
BUG_ON(!pkts); * we send out here will be composed of one
* real MSS sized packet because tcp_retransmit_skb()
packet_cnt += pkts; * will fragment it if necessary.
if (packet_cnt > tcp_get_pcount(&tp->fackets_out)) */
if (++packet_cnt > tcp_get_pcount(&tp->fackets_out))
break; break;
if ((tcp_packets_in_flight(tp) + (pkts-1)) >= tp->snd_cwnd) if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
break; break;
if (TCP_SKB_CB(skb)->sacked & TCPCB_TAGBITS) if (TCP_SKB_CB(skb)->sacked & TCPCB_TAGBITS)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment