Skip to content

Commit e5afd58

Browse files
ws-yangpcSasha Levin
authored andcommitted
tcp: ensure to use the most recently sent skb when filling the rate sample
[ Upstream commit b253a06 ] If an ACK (s)acks multiple skbs, we favor the information from the most recently sent skb by choosing the skb with the highest prior_delivered count. But in the interval between receiving ACKs, we send multiple skbs with the same prior_delivered, because the tp->delivered only changes when we receive an ACK. We used RACK's solution, copying tcp_rack_sent_after() as tcp_skb_sent_after() helper to determine "which packet was sent last?". Later, we will use tcp_skb_sent_after() instead in RACK. Fixes: b9f6482 ("tcp: track data delivery rate for a TCP connection") Signed-off-by: Pengcheng Yang <[email protected]> Cc: Paolo Abeni <[email protected]> Acked-by: Neal Cardwell <[email protected]> Tested-by: Neal Cardwell <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent abdd188 commit e5afd58

File tree

2 files changed

+14
-3
lines changed

2 files changed

+14
-3
lines changed

include/net/tcp.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,7 @@ struct rate_sample {
10261026
int losses; /* number of packets marked lost upon ACK */
10271027
u32 acked_sacked; /* number of packets newly (S)ACKed upon ACK */
10281028
u32 prior_in_flight; /* in flight before this ACK */
1029+
u32 last_end_seq; /* end_seq of most recently ACKed packet */
10291030
bool is_app_limited; /* is sample from packet with bubble in pipe? */
10301031
bool is_retrans; /* is sample from retransmission? */
10311032
bool is_ack_delayed; /* is this (likely) a delayed ACK? */
@@ -1148,6 +1149,11 @@ void tcp_rate_gen(struct sock *sk, u32 delivered, u32 lost,
11481149
bool is_sack_reneg, struct rate_sample *rs);
11491150
void tcp_rate_check_app_limited(struct sock *sk);
11501151

1152+
static inline bool tcp_skb_sent_after(u64 t1, u64 t2, u32 seq1, u32 seq2)
1153+
{
1154+
return t1 > t2 || (t1 == t2 && after(seq1, seq2));
1155+
}
1156+
11511157
/* These functions determine how the current flow behaves in respect of SACK
11521158
* handling. SACK is negotiated with the peer, and therefore it can vary
11531159
* between different flows.

net/ipv4/tcp_rate.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,26 +73,31 @@ void tcp_rate_skb_sent(struct sock *sk, struct sk_buff *skb)
7373
*
7474
* If an ACK (s)acks multiple skbs (e.g., stretched-acks), this function is
7575
* called multiple times. We favor the information from the most recently
76-
* sent skb, i.e., the skb with the highest prior_delivered count.
76+
* sent skb, i.e., the skb with the most recently sent time and the highest
77+
* sequence.
7778
*/
7879
void tcp_rate_skb_delivered(struct sock *sk, struct sk_buff *skb,
7980
struct rate_sample *rs)
8081
{
8182
struct tcp_sock *tp = tcp_sk(sk);
8283
struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
84+
u64 tx_tstamp;
8385

8486
if (!scb->tx.delivered_mstamp)
8587
return;
8688

89+
tx_tstamp = tcp_skb_timestamp_us(skb);
8790
if (!rs->prior_delivered ||
88-
after(scb->tx.delivered, rs->prior_delivered)) {
91+
tcp_skb_sent_after(tx_tstamp, tp->first_tx_mstamp,
92+
scb->end_seq, rs->last_end_seq)) {
8993
rs->prior_delivered = scb->tx.delivered;
9094
rs->prior_mstamp = scb->tx.delivered_mstamp;
9195
rs->is_app_limited = scb->tx.is_app_limited;
9296
rs->is_retrans = scb->sacked & TCPCB_RETRANS;
97+
rs->last_end_seq = scb->end_seq;
9398

9499
/* Record send time of most recently ACKed packet: */
95-
tp->first_tx_mstamp = tcp_skb_timestamp_us(skb);
100+
tp->first_tx_mstamp = tx_tstamp;
96101
/* Find the duration of the "send phase" of this window: */
97102
rs->interval_us = tcp_stamp_us_delta(tp->first_tx_mstamp,
98103
scb->tx.first_tx_mstamp);

0 commit comments

Comments
 (0)