|
@@ -2831,36 +2831,6 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
-/* Check if we forward retransmits are possible in the current
|
|
|
|
- * window/congestion state.
|
|
|
|
- */
|
|
|
|
-static bool tcp_can_forward_retransmit(struct sock *sk)
|
|
|
|
-{
|
|
|
|
- const struct inet_connection_sock *icsk = inet_csk(sk);
|
|
|
|
- const struct tcp_sock *tp = tcp_sk(sk);
|
|
|
|
-
|
|
|
|
- /* Forward retransmissions are possible only during Recovery. */
|
|
|
|
- if (icsk->icsk_ca_state != TCP_CA_Recovery)
|
|
|
|
- return false;
|
|
|
|
-
|
|
|
|
- /* No forward retransmissions in Reno are possible. */
|
|
|
|
- if (tcp_is_reno(tp))
|
|
|
|
- return false;
|
|
|
|
-
|
|
|
|
- /* Yeah, we have to make difficult choice between forward transmission
|
|
|
|
- * and retransmission... Both ways have their merits...
|
|
|
|
- *
|
|
|
|
- * For now we do not retransmit anything, while we have some new
|
|
|
|
- * segments to send. In the other cases, follow rule 3 for
|
|
|
|
- * NextSeg() specified in RFC3517.
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
- if (tcp_may_send_now(sk))
|
|
|
|
- return false;
|
|
|
|
-
|
|
|
|
- return true;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/* This gets called after a retransmit timeout, and the initially
|
|
/* This gets called after a retransmit timeout, and the initially
|
|
* retransmitted data is acknowledged. It tries to continue
|
|
* retransmitted data is acknowledged. It tries to continue
|
|
* resending the rest of the retransmit queue, until either
|
|
* resending the rest of the retransmit queue, until either
|
|
@@ -2875,24 +2845,16 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
|
|
struct tcp_sock *tp = tcp_sk(sk);
|
|
struct tcp_sock *tp = tcp_sk(sk);
|
|
struct sk_buff *skb;
|
|
struct sk_buff *skb;
|
|
struct sk_buff *hole = NULL;
|
|
struct sk_buff *hole = NULL;
|
|
- u32 max_segs, last_lost;
|
|
|
|
|
|
+ u32 max_segs;
|
|
int mib_idx;
|
|
int mib_idx;
|
|
- int fwd_rexmitting = 0;
|
|
|
|
|
|
|
|
if (!tp->packets_out)
|
|
if (!tp->packets_out)
|
|
return;
|
|
return;
|
|
|
|
|
|
- if (!tp->lost_out)
|
|
|
|
- tp->retransmit_high = tp->snd_una;
|
|
|
|
-
|
|
|
|
if (tp->retransmit_skb_hint) {
|
|
if (tp->retransmit_skb_hint) {
|
|
skb = tp->retransmit_skb_hint;
|
|
skb = tp->retransmit_skb_hint;
|
|
- last_lost = TCP_SKB_CB(skb)->end_seq;
|
|
|
|
- if (after(last_lost, tp->retransmit_high))
|
|
|
|
- last_lost = tp->retransmit_high;
|
|
|
|
} else {
|
|
} else {
|
|
skb = tcp_write_queue_head(sk);
|
|
skb = tcp_write_queue_head(sk);
|
|
- last_lost = tp->snd_una;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
max_segs = tcp_tso_segs(sk, tcp_current_mss(sk));
|
|
max_segs = tcp_tso_segs(sk, tcp_current_mss(sk));
|
|
@@ -2915,31 +2877,14 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
|
|
*/
|
|
*/
|
|
segs = min_t(int, segs, max_segs);
|
|
segs = min_t(int, segs, max_segs);
|
|
|
|
|
|
- if (fwd_rexmitting) {
|
|
|
|
-begin_fwd:
|
|
|
|
- if (!before(TCP_SKB_CB(skb)->seq, tcp_highest_sack_seq(tp)))
|
|
|
|
- break;
|
|
|
|
- mib_idx = LINUX_MIB_TCPFORWARDRETRANS;
|
|
|
|
-
|
|
|
|
- } else if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) {
|
|
|
|
- tp->retransmit_high = last_lost;
|
|
|
|
- if (!tcp_can_forward_retransmit(sk))
|
|
|
|
- break;
|
|
|
|
- /* Backtrack if necessary to non-L'ed skb */
|
|
|
|
- if (hole) {
|
|
|
|
- skb = hole;
|
|
|
|
- hole = NULL;
|
|
|
|
- }
|
|
|
|
- fwd_rexmitting = 1;
|
|
|
|
- goto begin_fwd;
|
|
|
|
-
|
|
|
|
|
|
+ if (tp->retrans_out >= tp->lost_out) {
|
|
|
|
+ break;
|
|
} else if (!(sacked & TCPCB_LOST)) {
|
|
} else if (!(sacked & TCPCB_LOST)) {
|
|
if (!hole && !(sacked & (TCPCB_SACKED_RETRANS|TCPCB_SACKED_ACKED)))
|
|
if (!hole && !(sacked & (TCPCB_SACKED_RETRANS|TCPCB_SACKED_ACKED)))
|
|
hole = skb;
|
|
hole = skb;
|
|
continue;
|
|
continue;
|
|
|
|
|
|
} else {
|
|
} else {
|
|
- last_lost = TCP_SKB_CB(skb)->end_seq;
|
|
|
|
if (icsk->icsk_ca_state != TCP_CA_Loss)
|
|
if (icsk->icsk_ca_state != TCP_CA_Loss)
|
|
mib_idx = LINUX_MIB_TCPFASTRETRANS;
|
|
mib_idx = LINUX_MIB_TCPFASTRETRANS;
|
|
else
|
|
else
|