Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2cba6355 authored by Pengcheng Yang's avatar Pengcheng Yang Committed by Greg Kroah-Hartman
Browse files

tcp: ensure to use the most recently sent skb when filling the rate sample



[ Upstream commit b253a0680ceadc5d7b4acca7aa2d870326cad8ad ]

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: b9f64820 ("tcp: track data delivery rate for a TCP connection")
Signed-off-by: default avatarPengcheng Yang <yangpc@wangsu.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Acked-by: default avatarNeal Cardwell <ncardwell@google.com>
Tested-by: default avatarNeal Cardwell <ncardwell@google.com>
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/1650422081-22153-1-git-send-email-yangpc@wangsu.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 3ea6190b
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -1030,6 +1030,7 @@ struct rate_sample {
	int  losses;		/* number of packets marked lost upon ACK */
	int  losses;		/* number of packets marked lost upon ACK */
	u32  acked_sacked;	/* number of packets newly (S)ACKed upon ACK */
	u32  acked_sacked;	/* number of packets newly (S)ACKed upon ACK */
	u32  prior_in_flight;	/* in flight before this ACK */
	u32  prior_in_flight;	/* in flight before this ACK */
	u32  last_end_seq;	/* end_seq of most recently ACKed packet */
	bool is_app_limited;	/* is sample from packet with bubble in pipe? */
	bool is_app_limited;	/* is sample from packet with bubble in pipe? */
	bool is_retrans;	/* is sample from retransmission? */
	bool is_retrans;	/* is sample from retransmission? */
	bool is_ack_delayed;	/* is this (likely) a delayed ACK? */
	bool is_ack_delayed;	/* is this (likely) a delayed ACK? */
@@ -1139,6 +1140,11 @@ void tcp_rate_gen(struct sock *sk, u32 delivered, u32 lost,
		  bool is_sack_reneg, struct rate_sample *rs);
		  bool is_sack_reneg, struct rate_sample *rs);
void tcp_rate_check_app_limited(struct sock *sk);
void tcp_rate_check_app_limited(struct sock *sk);


static inline bool tcp_skb_sent_after(u64 t1, u64 t2, u32 seq1, u32 seq2)
{
	return t1 > t2 || (t1 == t2 && after(seq1, seq2));
}

/* These functions determine how the current flow behaves in respect of SACK
/* These functions determine how the current flow behaves in respect of SACK
 * handling. SACK is negotiated with the peer, and therefore it can vary
 * handling. SACK is negotiated with the peer, and therefore it can vary
 * between different flows.
 * between different flows.
+8 −3
Original line number Original line Diff line number Diff line
@@ -73,26 +73,31 @@ void tcp_rate_skb_sent(struct sock *sk, struct sk_buff *skb)
 *
 *
 * If an ACK (s)acks multiple skbs (e.g., stretched-acks), this function is
 * If an ACK (s)acks multiple skbs (e.g., stretched-acks), this function is
 * called multiple times. We favor the information from the most recently
 * called multiple times. We favor the information from the most recently
 * sent skb, i.e., the skb with the highest prior_delivered count.
 * sent skb, i.e., the skb with the most recently sent time and the highest
 * sequence.
 */
 */
void tcp_rate_skb_delivered(struct sock *sk, struct sk_buff *skb,
void tcp_rate_skb_delivered(struct sock *sk, struct sk_buff *skb,
			    struct rate_sample *rs)
			    struct rate_sample *rs)
{
{
	struct tcp_sock *tp = tcp_sk(sk);
	struct tcp_sock *tp = tcp_sk(sk);
	struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
	struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
	u64 tx_tstamp;


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


	tx_tstamp = tcp_skb_timestamp_us(skb);
	if (!rs->prior_delivered ||
	if (!rs->prior_delivered ||
	    after(scb->tx.delivered, rs->prior_delivered)) {
	    tcp_skb_sent_after(tx_tstamp, tp->first_tx_mstamp,
			       scb->end_seq, rs->last_end_seq)) {
		rs->prior_delivered  = scb->tx.delivered;
		rs->prior_delivered  = scb->tx.delivered;
		rs->prior_mstamp     = scb->tx.delivered_mstamp;
		rs->prior_mstamp     = scb->tx.delivered_mstamp;
		rs->is_app_limited   = scb->tx.is_app_limited;
		rs->is_app_limited   = scb->tx.is_app_limited;
		rs->is_retrans	     = scb->sacked & TCPCB_RETRANS;
		rs->is_retrans	     = scb->sacked & TCPCB_RETRANS;
		rs->last_end_seq     = scb->end_seq;


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