Commit 25010bfd authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'mptcp-fix-duplicate-data-handling'



Matthieu Baerts says:

====================
mptcp: fix duplicate data handling

In some cases, the subflow-level's copied_seq counter was incorrectly
increased, leading to an unexpected subflow reset.

Patch 1/2 fixes the RCVPRUNED MIB counter that was attached to the wrong
event since its introduction in v5.14, backported to v5.11.

Patch 2/2 fixes the copied_seq counter issues, is present since v5.10.

Signed-off-by: default avatarMatthieu Baerts (NGI0) <matttbe@kernel.org>
====================

Link: https://patch.msgid.link/20240731-upstream-net-20240731-mptcp-dup-data-v1-0-bde833fa628a@kernel.org


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 2b4a32da 68cc9247
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -350,8 +350,10 @@ static bool __mptcp_move_skb(struct mptcp_sock *msk, struct sock *ssk,
	skb_orphan(skb);

	/* try to fetch required memory from subflow */
	if (!mptcp_rmem_schedule(sk, ssk, skb->truesize))
	if (!mptcp_rmem_schedule(sk, ssk, skb->truesize)) {
		MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RCVPRUNED);
		goto drop;
	}

	has_rxtstamp = TCP_SKB_CB(skb)->has_rxtstamp;

@@ -844,10 +846,8 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk)
		sk_rbuf = ssk_rbuf;

	/* over limit? can't append more skbs to msk, Also, no need to wake-up*/
	if (__mptcp_rmem(sk) > sk_rbuf) {
		MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RCVPRUNED);
	if (__mptcp_rmem(sk) > sk_rbuf)
		return;
	}

	/* Wake-up the reader only for in-sequence data */
	mptcp_data_lock(sk);
+12 −4
Original line number Diff line number Diff line
@@ -1230,14 +1230,22 @@ static void mptcp_subflow_discard_data(struct sock *ssk, struct sk_buff *skb,
{
	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
	bool fin = TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN;
	u32 incr;
	struct tcp_sock *tp = tcp_sk(ssk);
	u32 offset, incr, avail_len;

	incr = limit >= skb->len ? skb->len + fin : limit;
	offset = tp->copied_seq - TCP_SKB_CB(skb)->seq;
	if (WARN_ON_ONCE(offset > skb->len))
		goto out;

	avail_len = skb->len - offset;
	incr = limit >= avail_len ? avail_len + fin : limit;

	pr_debug("discarding=%d len=%d seq=%d", incr, skb->len,
		 subflow->map_subflow_seq);
	pr_debug("discarding=%d len=%d offset=%d seq=%d", incr, skb->len,
		 offset, subflow->map_subflow_seq);
	MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DUPDATA);
	tcp_sk(ssk)->copied_seq += incr;

out:
	if (!before(tcp_sk(ssk)->copied_seq, TCP_SKB_CB(skb)->end_seq))
		sk_eat_skb(ssk, skb);
	if (mptcp_subflow_get_map_offset(subflow) >= subflow->map_data_len)