Skip to content

Commit 6869897

Browse files
yuchungchengdavem330
authored andcommitted
tcp: simplify tcp_mark_skb_lost
This patch consolidates and simplifes the loss marking logic used by a few loss detections (RACK, RFC6675, NewReno). Previously each detection uses a subset of several intertwined subroutines. This unncessary complexity has led to bugs (and fixes of bug fixes). tcp_mark_skb_lost now is the single one routine to mark a packet loss when a loss detection caller deems an skb ist lost: 1. rewind tp->retransmit_hint_skb if skb has lower sequence or all lost ones have been retransmitted. 2. book-keeping: adjust flags and counts depending on if skb was retransmitted or not. Signed-off-by: Yuchung Cheng <[email protected]> Signed-off-by: Neal Cardwell <[email protected]> Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent fd21467 commit 6869897

File tree

1 file changed

+22
-37
lines changed

1 file changed

+22
-37
lines changed

net/ipv4/tcp_input.c

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,11 @@ static void tcp_check_sack_reordering(struct sock *sk, const u32 low_seq,
10061006
ts ? LINUX_MIB_TCPTSREORDER : LINUX_MIB_TCPSACKREORDER);
10071007
}
10081008

1009-
/* This must be called before lost_out is incremented */
1009+
/* This must be called before lost_out or retrans_out are updated
1010+
* on a new loss, because we want to know if all skbs previously
1011+
* known to be lost have already been retransmitted, indicating
1012+
* that this newly lost skb is our next skb to retransmit.
1013+
*/
10101014
static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb)
10111015
{
10121016
if ((!tp->retransmit_skb_hint && tp->retrans_out >= tp->lost_out) ||
@@ -1018,32 +1022,25 @@ static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb)
10181022

10191023
void tcp_mark_skb_lost(struct sock *sk, struct sk_buff *skb)
10201024
{
1025+
__u8 sacked = TCP_SKB_CB(skb)->sacked;
10211026
struct tcp_sock *tp = tcp_sk(sk);
10221027

1023-
tcp_skb_mark_lost_uncond_verify(tp, skb);
1024-
if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) {
1025-
/* Account for retransmits that are lost again */
1026-
TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
1027-
tp->retrans_out -= tcp_skb_pcount(skb);
1028-
NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPLOSTRETRANSMIT,
1029-
tcp_skb_pcount(skb));
1030-
}
1031-
}
1032-
1033-
/* Sum the number of packets on the wire we have marked as lost.
1034-
* There are two cases we care about here:
1035-
* a) Packet hasn't been marked lost (nor retransmitted),
1036-
* and this is the first loss.
1037-
* b) Packet has been marked both lost and retransmitted,
1038-
* and this means we think it was lost again.
1039-
*/
1040-
static void tcp_sum_lost(struct tcp_sock *tp, struct sk_buff *skb)
1041-
{
1042-
__u8 sacked = TCP_SKB_CB(skb)->sacked;
1028+
if (sacked & TCPCB_SACKED_ACKED)
1029+
return;
10431030

1044-
if (!(sacked & TCPCB_LOST) ||
1045-
((sacked & TCPCB_LOST) && (sacked & TCPCB_SACKED_RETRANS)))
1046-
tp->lost += tcp_skb_pcount(skb);
1031+
tcp_verify_retransmit_hint(tp, skb);
1032+
if (sacked & TCPCB_LOST) {
1033+
if (sacked & TCPCB_SACKED_RETRANS) {
1034+
/* Account for retransmits that are lost again */
1035+
TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
1036+
tp->retrans_out -= tcp_skb_pcount(skb);
1037+
NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPLOSTRETRANSMIT,
1038+
tcp_skb_pcount(skb));
1039+
}
1040+
} else {
1041+
tp->lost_out += tcp_skb_pcount(skb);
1042+
TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
1043+
}
10471044
}
10481045

10491046
static void tcp_skb_mark_lost(struct tcp_sock *tp, struct sk_buff *skb)
@@ -1057,17 +1054,6 @@ static void tcp_skb_mark_lost(struct tcp_sock *tp, struct sk_buff *skb)
10571054
}
10581055
}
10591056

1060-
void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, struct sk_buff *skb)
1061-
{
1062-
tcp_verify_retransmit_hint(tp, skb);
1063-
1064-
tcp_sum_lost(tp, skb);
1065-
if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_ACKED))) {
1066-
tp->lost_out += tcp_skb_pcount(skb);
1067-
TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
1068-
}
1069-
}
1070-
10711057
/* Updates the delivered and delivered_ce counts */
10721058
static void tcp_count_delivered(struct tcp_sock *tp, u32 delivered,
10731059
bool ece_ack)
@@ -2688,8 +2674,7 @@ void tcp_simple_retransmit(struct sock *sk)
26882674
unsigned int mss = tcp_current_mss(sk);
26892675

26902676
skb_rbtree_walk(skb, &sk->tcp_rtx_queue) {
2691-
if (tcp_skb_seglen(skb) > mss &&
2692-
!(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED))
2677+
if (tcp_skb_seglen(skb) > mss)
26932678
tcp_mark_skb_lost(sk, skb);
26942679
}
26952680

0 commit comments

Comments
 (0)