forked from Minki/linux
Merge branch 'simplify-TCP-loss-marking-code'
Yuchung Cheng says: ==================== simplify TCP loss marking code The TCP loss marking is implemented by a set of intertwined subroutines. TCP has several loss detection algorithms (RACK, RFC6675/FACK, NewReno, etc) each calls a subset of these routines to mark a packet lost. This has led to various bugs (and fixes and fixes of fixes). This patch set is to consolidate the loss marking code so all detection algorithms call the same routine tcp_mark_skb_lost(). ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
6fba737a93
@ -1006,7 +1006,11 @@ static void tcp_check_sack_reordering(struct sock *sk, const u32 low_seq,
|
||||
ts ? LINUX_MIB_TCPTSREORDER : LINUX_MIB_TCPSACKREORDER);
|
||||
}
|
||||
|
||||
/* This must be called before lost_out is incremented */
|
||||
/* This must be called before lost_out or retrans_out are updated
|
||||
* on a new loss, because we want to know if all skbs previously
|
||||
* known to be lost have already been retransmitted, indicating
|
||||
* that this newly lost skb is our next skb to retransmit.
|
||||
*/
|
||||
static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb)
|
||||
{
|
||||
if ((!tp->retransmit_skb_hint && tp->retrans_out >= tp->lost_out) ||
|
||||
@ -1016,39 +1020,24 @@ static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb)
|
||||
tp->retransmit_skb_hint = skb;
|
||||
}
|
||||
|
||||
/* Sum the number of packets on the wire we have marked as lost.
|
||||
* There are two cases we care about here:
|
||||
* a) Packet hasn't been marked lost (nor retransmitted),
|
||||
* and this is the first loss.
|
||||
* b) Packet has been marked both lost and retransmitted,
|
||||
* and this means we think it was lost again.
|
||||
*/
|
||||
static void tcp_sum_lost(struct tcp_sock *tp, struct sk_buff *skb)
|
||||
void tcp_mark_skb_lost(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
__u8 sacked = TCP_SKB_CB(skb)->sacked;
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
|
||||
if (!(sacked & TCPCB_LOST) ||
|
||||
((sacked & TCPCB_LOST) && (sacked & TCPCB_SACKED_RETRANS)))
|
||||
tp->lost += tcp_skb_pcount(skb);
|
||||
}
|
||||
if (sacked & TCPCB_SACKED_ACKED)
|
||||
return;
|
||||
|
||||
static void tcp_skb_mark_lost(struct tcp_sock *tp, struct sk_buff *skb)
|
||||
{
|
||||
if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_ACKED))) {
|
||||
tcp_verify_retransmit_hint(tp, skb);
|
||||
|
||||
tp->lost_out += tcp_skb_pcount(skb);
|
||||
tcp_sum_lost(tp, skb);
|
||||
TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
|
||||
}
|
||||
}
|
||||
|
||||
void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, struct sk_buff *skb)
|
||||
{
|
||||
tcp_verify_retransmit_hint(tp, skb);
|
||||
|
||||
tcp_sum_lost(tp, skb);
|
||||
if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_ACKED))) {
|
||||
if (sacked & TCPCB_LOST) {
|
||||
if (sacked & TCPCB_SACKED_RETRANS) {
|
||||
/* Account for retransmits that are lost again */
|
||||
TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
|
||||
tp->retrans_out -= tcp_skb_pcount(skb);
|
||||
NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPLOSTRETRANSMIT,
|
||||
tcp_skb_pcount(skb));
|
||||
}
|
||||
} else {
|
||||
tp->lost_out += tcp_skb_pcount(skb);
|
||||
TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
|
||||
}
|
||||
@ -2308,7 +2297,8 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head)
|
||||
if (cnt > packets)
|
||||
break;
|
||||
|
||||
tcp_skb_mark_lost(tp, skb);
|
||||
if (!(TCP_SKB_CB(skb)->sacked & TCPCB_LOST))
|
||||
tcp_mark_skb_lost(sk, skb);
|
||||
|
||||
if (mark_head)
|
||||
break;
|
||||
@ -2674,14 +2664,8 @@ void tcp_simple_retransmit(struct sock *sk)
|
||||
unsigned int mss = tcp_current_mss(sk);
|
||||
|
||||
skb_rbtree_walk(skb, &sk->tcp_rtx_queue) {
|
||||
if (tcp_skb_seglen(skb) > mss &&
|
||||
!(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) {
|
||||
if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) {
|
||||
TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
|
||||
tp->retrans_out -= tcp_skb_pcount(skb);
|
||||
}
|
||||
tcp_skb_mark_lost_uncond_verify(tp, skb);
|
||||
}
|
||||
if (tcp_skb_seglen(skb) > mss)
|
||||
tcp_mark_skb_lost(sk, skb);
|
||||
}
|
||||
|
||||
tcp_clear_retrans_hints_partial(tp);
|
||||
|
@ -2,20 +2,6 @@
|
||||
#include <linux/tcp.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
void tcp_mark_skb_lost(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
|
||||
tcp_skb_mark_lost_uncond_verify(tp, skb);
|
||||
if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) {
|
||||
/* Account for retransmits that are lost again */
|
||||
TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
|
||||
tp->retrans_out -= tcp_skb_pcount(skb);
|
||||
NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPLOSTRETRANSMIT,
|
||||
tcp_skb_pcount(skb));
|
||||
}
|
||||
}
|
||||
|
||||
static bool tcp_rack_sent_after(u64 t1, u64 t2, u32 seq1, u32 seq2)
|
||||
{
|
||||
return t1 > t2 || (t1 == t2 && after(seq1, seq2));
|
||||
@ -246,6 +232,6 @@ void tcp_newreno_mark_lost(struct sock *sk, bool snd_una_advanced)
|
||||
tcp_fragment(sk, TCP_FRAG_IN_RTX_QUEUE, skb,
|
||||
mss, mss, GFP_ATOMIC);
|
||||
|
||||
tcp_skb_mark_lost_uncond_verify(tp, skb);
|
||||
tcp_mark_skb_lost(sk, skb);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user