From nobody Sat Sep 26 12:28:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B602B3B38B8 for ; Mon, 24 Aug 2026 07:09:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787555392; cv=none; b=stB4iqjr5RofhT6o3NsxV1EQfqf0e7Jal8nfzM/Rk4+ejIt92yBCBL9qgiMQZZyRNtf6Awd3sLf6+yA0atWMUlUh8vmR++VwN4lp6PLoZ90greCGLT7pVSX7eSgB05mOK6P/oZ2LAqKb2/fpYHNLhkXQbp11XAZKPQk/pLneSRg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787555392; c=relaxed/simple; bh=WNinlTC6l5aJkklnVvmXzVfYe39Y3p+v11qQ5jvFHwE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PVv/GP2oI4h4IygOlUG3vXpIKa1MA8sMUld0OEuM2lEyCEb5d2hPE7smfCrTVfJb6QIJOz5ASP2ds40MelZKDhZUdva7E8cYwr70MRKy7V/XMxAbagRmxPrb5AUPBLkAiooZiDtByTrVCK47u1q4YE6Jhcab6GM4WIh0xDmYGRs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=a5bRtyEm; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="a5bRtyEm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B29411F00A3A; Mon, 24 Aug 2026 07:09:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787555391; bh=f6RhVjLJ14gSo6WNMgM09WSZMaFCjDVBirOC4KjoxLs=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=a5bRtyEm4S0+yq/5fChByvxojoFtUwMQSVm/OKVS21uuFcSXgzv4X2EjHfYhmTxNB tiu4lPgMjb+TQ28Py6Wr4ZVjjf7RrJDs6rPsNSIfh/hoKJ+Yh07tMSQB+8zgWLYRsk fnJoHhbQArigDU+n7SZ7KrUEWg4e8DHbdUhCFHA2bhX/Ib4SkPyyTfHn6gnkW3M9ao tcan4X65s9XHXzkpzXjwzDigLv8QpggMVtVBSvROJvvaS1waVr2VUZ/tRJkgDScGo0 3A329yA4OwFd7qAZeA/D89uOCrnaX/JGyjO/8EA26lVQcI4/G/xm7nr3Xt5HfbDc1A 8YW2Y+8lnzDBw== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Geliang Tang , Matthieu Baerts Subject: [PATCH mptcp-next v4 1/5] mptcp: implement .splice_eof Date: Mon, 24 Aug 2026 15:09:35 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Geliang Tang This patch implements the .splice_eof interface for MPTCP, namely mptcp_splice_eof(), to flush any pending data when a sendfile() operation reaches end-of-file. The implementation first calls __mptcp_push_pending() to push all unsent data from the MPTCP layer's write queue to the TCP subflows. Then, for each active subflow that still has data in its send queue, it acquires the subflow socket lock with lock_sock_nested(, SINGLE_DEPTH_NESTING) to avoid lockdep false positives (the MPTCP socket lock is already held). After that, it calls tcp_send_mss() and tcp_push() to flush the subflow's send buffer. Without this .splice_eof support, MPTCP did not flush its pending data immediately when sendfile() reached EOF. While the data would eventually be sent after a short delay, this patch makes the behavior consistent with TCP. Note: the .splice_eof field of mptcp_stream_ops is set to inet_splice_eof, which redirects to the protocol-specific .splice_eof (here, mptcp_splice_eof). Suggested-by: Matthieu Baerts Signed-off-by: Geliang Tang --- net/mptcp/protocol.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index f22d64ab1c53..265a07e73a52 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -4249,6 +4249,34 @@ static int mptcp_connect(struct sock *sk, struct soc= kaddr_unsized *uaddr, return 0; } =20 +static void mptcp_splice_eof(struct socket *sock) +{ + struct mptcp_subflow_context *subflow; + struct sock *sk =3D sock->sk, *ssk; + struct mptcp_sock *msk; + int mss_now, size_goal; + struct tcp_sock *tp; + + msk =3D mptcp_sk(sk); + + lock_sock(sk); + __mptcp_push_pending(sk, 0); + mptcp_rps_record_subflows(msk); + mptcp_for_each_subflow(msk, subflow) { + ssk =3D mptcp_subflow_tcp_sock(subflow); + if (ssk->sk_state =3D=3D TCP_CLOSE || + !tcp_write_queue_tail(ssk)) + continue; + + lock_sock_nested(ssk, SINGLE_DEPTH_NESTING); + tp =3D tcp_sk(ssk); + mss_now =3D tcp_send_mss(ssk, &size_goal, 0); + tcp_push(ssk, 0, mss_now, tp->nonagle, size_goal); + release_sock(ssk); + } + release_sock(sk); +} + static struct proto mptcp_prot =3D { .name =3D "MPTCP", .owner =3D THIS_MODULE, @@ -4280,6 +4308,7 @@ static struct proto mptcp_prot =3D { .obj_size =3D sizeof(struct mptcp_sock), .slab_flags =3D SLAB_TYPESAFE_BY_RCU, .no_autobind =3D true, + .splice_eof =3D mptcp_splice_eof, }; =20 static int mptcp_bind(struct socket *sock, struct sockaddr_unsized *uaddr,= int addr_len) @@ -4773,6 +4802,7 @@ static const struct proto_ops mptcp_stream_ops =3D { .set_rcvlowat =3D mptcp_set_rcvlowat, .read_sock =3D mptcp_read_sock, .splice_read =3D mptcp_splice_read, + .splice_eof =3D inet_splice_eof, }; =20 static struct inet_protosw mptcp_protosw =3D { @@ -4885,6 +4915,7 @@ static const struct proto_ops mptcp_v6_stream_ops =3D= { .set_rcvlowat =3D mptcp_set_rcvlowat, .read_sock =3D mptcp_read_sock, .splice_read =3D mptcp_splice_read, + .splice_eof =3D inet_splice_eof, }; =20 static struct proto mptcp_v6_prot; --=20 2.53.0 From nobody Sat Sep 26 12:28:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 383343EB815 for ; Mon, 24 Aug 2026 07:09:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787555395; cv=none; b=VxN8TIgYnYgOG1CX3Xv9Ay2bFkk3Ld5DR1PN9bwvoQIrk+hEK0tROSq0PLaBpVYwEpDZEWzT3wVN11oHEdDfPOTviaXoWHRibSh8Bwbc8Wu/qEWV3AH83OkiEcguScGVH+29s8h8y0AAnxOeorem1d9xXLUYZjf+fGuHu2F9fqQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787555395; c=relaxed/simple; bh=Tmw0lOI8Ze7FEBjC9WUN/mQJyxYpBTgIxNxJQ3EhqF4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DTJtAhGyZIZC7DjmI+RA8p2cHSP2Nsj+Atb6qtgeE6PDNyStUEr/jGREd8KynVXgZUREviJQT0SxfIQyZ71N473MvfM+JyrwtHbA5m0QWRzznV8+4L4cBOKFXe793jMyEuqSe7hM7QB/6cRCoVx9xHaah7UNZPMW1mAPu4S/44o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QcRUyb4K; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QcRUyb4K" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 91FAB1F000E9; Mon, 24 Aug 2026 07:09:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787555393; bh=96CSdpH7OkqFOKZscA/69I+xKE3GdDtX8UcIsDLaco0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=QcRUyb4KHBWEiIUxk6wVRnW0MdtcYDR967BF/c4Gy5lw0zLe3d1PUnKC4yFlC1KZc zfxmCAIGaAJdBtW1biPw3zDYPjHYiFfuHvl172HXOQT1UY/uym+LvHzWcUTW2bpbH0 M1HpbkFEwsAs57xrHaagOtVcQVrsHFPSDSDCikiCzfASHUQiyVIEYQr+XzJ8REWrwR zZSTE9GmoXG1YtmphzINx6PHDfbc8rnsCDOi8Hp5dj9YIrSHCpDLpQcLDWOq7+VhJW qGKJLpTyv0gQKLal1w3cJ+x2s4RxjLcVX0wZuo7i6rZt43tHEnrabm2ebAylJLJkPh oN395vYiO4e2Q== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Geliang Tang Subject: [PATCH mptcp-next v4 2/5] selftests: mptcp: connect: trigger splice_eof Date: Mon, 24 Aug 2026 15:09:36 +0800 Message-ID: <58c55d194f1191085788313896c00b382aec62c1.1787554581.git.tanggeliang@kylinos.cn> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Geliang Tang Increase the sendfile count by one to ensure the transmission size exceeds the actual data length. This triggers the splice_eof path in the kernel, allowing the newly implemented MPTCP splice_eof interface to be exercised during testing. The change from 'count' to 'count + 1' forces the sendfile operation to attempt sending one more byte than available, which activates the end-of-file handling in the splicing logic and ensures coverage of the related MPTCP code paths. Additionally, handle cases where sendfile returns 0 (no more data) or a value larger than the remaining count (e.g., due to concurrent file growth). In such cases, break out of the loop to prevent unsigned integer underflow and potential infinite loop. Signed-off-by: Geliang Tang --- tools/testing/selftests/net/mptcp/mptcp_connect.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/test= ing/selftests/net/mptcp/mptcp_connect.c index 178d98d91fea..fca5d4606625 100644 --- a/tools/testing/selftests/net/mptcp/mptcp_connect.c +++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c @@ -872,12 +872,15 @@ static int do_sendfile(int infd, int outfd, unsigned = int count, while (count > 0) { ssize_t r; =20 - r =3D sendfile(outfd, infd, NULL, count); + r =3D sendfile(outfd, infd, NULL, count + 1); if (r < 0) { perror("sendfile"); return 3; } =20 + if (r =3D=3D 0 || r > count) + break; + count -=3D r; } =20 --=20 2.53.0 From nobody Sat Sep 26 12:28:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9BBE93B38B8 for ; Mon, 24 Aug 2026 07:09:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787555397; cv=none; b=WyTZpqDF/6D3XE+W4TS5id+fQp+nVlgnSHGmQcD12rpY01WuLC2x/laSEq0sCwH4Rw5tNCyO7GztJ4M5Puyo480gWVqnDCMAYWgMzjos6oTr/AQC3XXlUmEC3BbGxekd+CLFJfq1SQUg0mAQF8Qt9MUu4CNT+XcZ9+IhYcCwCN8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787555397; c=relaxed/simple; bh=MLPpCFnlVHdKH0YT4JNQqgaXXA/asFo2bBHJc9ZrGbg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hge3TZ7W29jg5UEEzbRztRwsvE94dKo+BvrI5CFRD5xkkg6ZsmknlqjyAKVyp+ASa4Gn0GO1cwVlB+mjwo5we83PoMVUDt4m5D/gY0SLdLqiJJF2MD8GR4HNrVRSEyGiOgmy5+dP2bkWJZbfZtaZyvmHxZzh3Bo/bBurL/L0qwQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DDuYKo2C; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DDuYKo2C" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 847951F00A3A; Mon, 24 Aug 2026 07:09:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787555396; bh=gnLT7DFSG0k5UFIBMm5gjr+AKwluIYqbAvHgDXeLbY4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=DDuYKo2CmcFVp1H7NVhlELVekm+e5PRhw6dAljZFxJK5Oz+TZfU99wE/Lxx+v494Z ZvthNk2xsMrcrnlIfscmGBJ1SDRgcZhKvOesWINYrgu3jmcOgEF+S5TucEYgIuBHcV tItaXKkW244EzeVCtYZdGCKKDev7VK7FqoExHHofpk/JaC4srmjY88NXrd+iVnT8SJ uLLte10Fmd881pDzFkOw0f3XbG4lKi9wUa3poQgdUdRYcJAWPvDOWbPxxQbFtYrUPT O7LtjLHoMRdRZVeLb38TpYeKQm+NXnGX6r+GhVbg+H21YJKwWHip3dSzkwoe3u82op z4mVBBNBsaRHQ== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Geliang Tang Subject: [PATCH mptcp-next v4 3/5] mptcp: implement read_skb for sockmap stream verdict Date: Mon, 24 Aug 2026 15:09:37 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Geliang Tang BPF sockmap's stream verdict path (sk_psock_verdict_data_ready) calls ops->read_skb() to dequeue skbs from the socket and pass them to the verdict BPF program. MPTCP's proto_ops (mptcp_stream_ops and mptcp_v6_stream_ops) did not define .read_skb, causing sk_psock_verdict_data_ready() to return early without processing any data. This made the stream verdict redirect completely non-functional for MPTCP sockets. Add mptcp_read_skb() as the skb_read_actor_t callback. It uses mptcp_recv_skb() to peek skbs from the MPTCP receive queue with the correct offset, adjusts the skb via skb_pull to skip already consumed data, unlinks it, and passes it to the recv_actor. bytes_consumed is updated after each skb is consumed. This follows the same pattern as tcp_read_skb() in net/ipv4/tcp.c, adapted for MPTCP's receive queue semantics. Signed-off-by: Geliang Tang --- net/mptcp/protocol.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 265a07e73a52..c1e26c6e5c17 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -4780,6 +4780,36 @@ static ssize_t mptcp_splice_read(struct socket *sock= , loff_t *ppos, return ret; } =20 +static int mptcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) +{ + struct mptcp_sock *msk =3D mptcp_sk(sk); + struct sk_buff *skb; + int copied =3D 0; + u32 offset; + + if (sk->sk_state =3D=3D TCP_LISTEN) + return -ENOTCONN; + + while ((skb =3D mptcp_recv_skb(sk, &offset)) !=3D NULL) { + int used; + + if (offset) + skb_pull(skb, offset); + + __skb_unlink(skb, &sk->sk_receive_queue); + WARN_ON_ONCE(!skb_set_owner_sk_safe(skb, sk)); + used =3D recv_actor(sk, skb); + if (used < 0) { + if (!copied) + copied =3D used; + break; + } + copied +=3D used; + msk->bytes_consumed +=3D used; + } + return copied; +} + static const struct proto_ops mptcp_stream_ops =3D { .family =3D PF_INET, .owner =3D THIS_MODULE, @@ -4803,6 +4833,7 @@ static const struct proto_ops mptcp_stream_ops =3D { .read_sock =3D mptcp_read_sock, .splice_read =3D mptcp_splice_read, .splice_eof =3D inet_splice_eof, + .read_skb =3D mptcp_read_skb, }; =20 static struct inet_protosw mptcp_protosw =3D { @@ -4916,6 +4947,7 @@ static const struct proto_ops mptcp_v6_stream_ops =3D= { .read_sock =3D mptcp_read_sock, .splice_read =3D mptcp_splice_read, .splice_eof =3D inet_splice_eof, + .read_skb =3D mptcp_read_skb, }; =20 static struct proto mptcp_v6_prot; --=20 2.53.0 From nobody Sat Sep 26 12:28:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 386E13EB7FE for ; Mon, 24 Aug 2026 07:09:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787555400; cv=none; b=AQUInb3a5Ba9P5Gm+aNrV6H9spTxSjQ/iIaSVI84Ciyw5dRNBuCCJAKmvpHR5QnlBf7FMGEtfGt1ge5MPLi4Y/Zy63NYAJnykGz2DdLdS+aQ/ySlcpSkKrZscBj2Is4Jf1aGsAgn7jqLOljnnF45L7Kqig7+F5zLpR4JA8+n9tk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787555400; c=relaxed/simple; bh=2dFPEMf9rZlNbHc96HwtCYgyUDee0DJF6TNw0sNNAoo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NPfDvUhnZI1X6vizMrZCzy35L/xJS0YS+g3BfS10gCiC+Y5Aaufy7HkyW7O1xYsPMiHruLIV8yjP2PUcYMHRj1yDOXp/kHisRbJmzUA53q7VK3VGJ6+K/7RbBaH9oY/kNc8D6/AsPlv/ROVlhmAL9IPjnprhCyRjHaqF6ybsGcU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RS3jKlZH; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RS3jKlZH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C147C1F000E9; Mon, 24 Aug 2026 07:09:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787555398; bh=8h+Bdzro69nU+po6hmoBXlafBKmqlWJln6C5cFZc1n8=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=RS3jKlZHNx/0smrnO8OQc+AAQMFBLBz4zK7oazqNb/z87/5bibmgodMoDODgzMla6 iuzUcEeVxOmlZ4ax7SYYowfPtjJR6/RuNJ2BV2JyOWzKznOsGT1ZuiuJNIQoLTVkxi 8UeSTi/S6iVeOZIojY84p2NblRce1SUT4xYXYsak5mXzPRnfugFCeoWPJYzjzUwDuH ujQg6vBmOGs5IqIoOGD5oSax8Yl9AYuXGGyIuC+nOXYvf7mJBDnOPgyJtPwcOYYG4w ER1SsezayLVo6BB5kQUJ9L9v4gJxZFqjlVzEDyQ4Jp2YdJ1XUmkEE3Aeo/cnj4/0mU QgvkDjDIzlybQ== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Geliang Tang , kernel test robot , Cong Wang Subject: [PATCH mptcp-next v4 4/5] mptcp: implement psock_update_sk_prot Date: Mon, 24 Aug 2026 15:09:38 +0800 Message-ID: <7b7000bec51e276ef4cdb575f02ac5913656b325.1787554581.git.tanggeliang@kylinos.cn> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Geliang Tang This patch adds basic MPTCP support for BPF sockmap by implementing the psock_update_sk_prot callback (mptcp_bpf_update_proto). This allows MPTCP sockets to be added to sockmap and enables the sk_skb stream_verdict redirect path via the read_skb callback. Separate protocol structures are maintained for IPv4/IPv6 and BASE/TX/RX/TXRX configurations, mirroring tcp_bpf_update_proto(). The IPv6 variant is lazily rebuilt via mptcp_bpf_check_v6_needs_rebuild() when the underlying protocol ops change. Note that unlike TCP, this implementation does not override sendmsg and recvmsg for the BPF variants. TCP replaces sendmsg with tcp_bpf_sendmsg to support sk_msg redirect (outbound message-level redirect) and recvmsg with tcp_bpf_recvmsg to read from the psock ingress queue. MPTCP does not override these because: - sendmsg: MPTCP sendmsg dispatches data across multiple subflows via the scheduler. Intercepting at the MPTCP level would require coordinating sk_msg processing with multi-path scheduling, which is non-trivial. - recvmsg: MPTCP recvmsg reassembles ordered data from the receive queue with sequence tracking. Overriding it to also check the psock ingress queue would duplicate significant MPTCP-specific logic. As a result, sk_msg redirect (msg_parser / msg_verdict) is not supported for MPTCP sockets. Only sk_skb stream_verdict redirect via the read_skb / sk_data_ready path is functional. Export mptcp_sendmsg, mptcp_recvmsg and mptcp_prot from protocol.c so they can be referenced by bpf.c. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202512261144.DxrvwMS3-lkp@int= el.com/ Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/521 Cc: Cong Wang Signed-off-by: Geliang Tang --- net/mptcp/bpf.c | 106 +++++++++++++++++++++++++++++++++++++++++++ net/mptcp/protocol.c | 10 ++-- net/mptcp/protocol.h | 9 ++++ 3 files changed, 121 insertions(+), 4 deletions(-) diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c index 82b0ad25f700..df41f72603c0 100644 --- a/net/mptcp/bpf.c +++ b/net/mptcp/bpf.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "protocol.h" =20 @@ -361,3 +362,108 @@ static int __init bpf_mptcp_kfunc_init(void) return ret; } late_initcall(bpf_mptcp_kfunc_init); + +enum { + MPTCP_BPF_IPV4, + MPTCP_BPF_IPV6, + MPTCP_BPF_NUM_PROTS, +}; + +enum { + MPTCP_BPF_BASE, + MPTCP_BPF_TX, + MPTCP_BPF_RX, + MPTCP_BPF_TXRX, + MPTCP_BPF_NUM_CFGS, +}; + +static struct proto mptcp_bpf_prots[MPTCP_BPF_NUM_PROTS][MPTCP_BPF_NUM_CFG= S]; + +static void mptcp_bpf_rebuild_protos(struct proto prot[MPTCP_BPF_NUM_CFGS], + struct proto *base) +{ + prot[MPTCP_BPF_BASE] =3D *base; + prot[MPTCP_BPF_BASE].destroy =3D sock_map_destroy; + prot[MPTCP_BPF_BASE].close =3D sock_map_close; + prot[MPTCP_BPF_BASE].sock_is_readable =3D sk_msg_is_readable; + + prot[MPTCP_BPF_TX] =3D prot[MPTCP_BPF_BASE]; + prot[MPTCP_BPF_RX] =3D prot[MPTCP_BPF_BASE]; + prot[MPTCP_BPF_TXRX] =3D prot[MPTCP_BPF_BASE]; +} + +#if IS_ENABLED(CONFIG_MPTCP_IPV6) +static struct proto *mptcpv6_prot_saved __read_mostly; +static DEFINE_SPINLOCK(mptcpv6_prot_lock); + +static void mptcp_bpf_check_v6_needs_rebuild(struct proto *ops) +{ + /* Load with acquire semantics to ensure we see the latest protocol + * structure before checking for rebuild. + */ + if (unlikely(ops !=3D smp_load_acquire(&mptcpv6_prot_saved))) { + spin_lock_bh(&mptcpv6_prot_lock); + if (likely(ops !=3D mptcpv6_prot_saved)) { + struct proto *v6_prots; + + v6_prots =3D mptcp_bpf_prots[MPTCP_BPF_IPV6]; + mptcp_bpf_rebuild_protos(v6_prots, ops); + /* Ensure mptcpv6_prot_saved update is visible before + * releasing lock + */ + smp_store_release(&mptcpv6_prot_saved, ops); + } + spin_unlock_bh(&mptcpv6_prot_lock); + } +} + +static int mptcp_bpf_assert_proto_ops(struct proto *ops) +{ + /* In order to avoid retpoline, we make assumptions when we call + * into ops if e.g. a psock is not present. Make sure they are + * indeed valid assumptions. + */ + return ops->recvmsg =3D=3D mptcp_recvmsg && + ops->sendmsg =3D=3D mptcp_sendmsg ? 0 : -EOPNOTSUPP; +} +#endif + +int mptcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, + bool restore) +{ + int family =3D sk->sk_family =3D=3D AF_INET6 ? MPTCP_BPF_IPV6 : + MPTCP_BPF_IPV4; + int config =3D psock->progs.msg_parser ? MPTCP_BPF_TX : + MPTCP_BPF_BASE; + + if (psock->progs.stream_verdict || psock->progs.skb_verdict) + config =3D (config =3D=3D MPTCP_BPF_TX) ? MPTCP_BPF_TXRX : + MPTCP_BPF_RX; + + if (restore) { + WRITE_ONCE(sk->sk_write_space, psock->saved_write_space); + /* Pairs with lockless read in sk_clone() */ + sock_replace_proto(sk, psock->sk_proto); + return 0; + } + +#if IS_ENABLED(CONFIG_MPTCP_IPV6) + if (sk->sk_family =3D=3D AF_INET6) { + if (mptcp_bpf_assert_proto_ops(psock->sk_proto)) + return -EINVAL; + + mptcp_bpf_check_v6_needs_rebuild(psock->sk_proto); + } +#endif + + /* Pairs with lockless read in sk_clone() */ + sock_replace_proto(sk, &mptcp_bpf_prots[family][config]); + return 0; +} + +static int __init mptcp_bpf_v4_build_proto(void) +{ + mptcp_bpf_rebuild_protos(mptcp_bpf_prots[MPTCP_BPF_IPV4], &mptcp_prot); + return 0; +} +late_initcall(mptcp_bpf_v4_build_proto); diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index c1e26c6e5c17..7d36dc4fab6e 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -2030,7 +2030,7 @@ static void mptcp_rps_record_subflows(const struct mp= tcp_sock *msk) } } =20 -static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) +int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) { struct mptcp_sock *msk =3D mptcp_sk(sk); struct page_frag *pfrag; @@ -2410,8 +2410,7 @@ static unsigned int mptcp_inq_hint(const struct sock = *sk) return 0; } =20 -static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, - int flags) +int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int fla= gs) { struct mptcp_sock *msk =3D mptcp_sk(sk); struct scm_timestamping_internal tss; @@ -4277,7 +4276,7 @@ static void mptcp_splice_eof(struct socket *sock) release_sock(sk); } =20 -static struct proto mptcp_prot =3D { +struct proto mptcp_prot =3D { .name =3D "MPTCP", .owner =3D THIS_MODULE, .init =3D mptcp_init_sock, @@ -4309,6 +4308,9 @@ static struct proto mptcp_prot =3D { .slab_flags =3D SLAB_TYPESAFE_BY_RCU, .no_autobind =3D true, .splice_eof =3D mptcp_splice_eof, +#ifdef CONFIG_BPF_SYSCALL + .psock_update_sk_prot =3D mptcp_bpf_update_proto, +#endif }; =20 static int mptcp_bind(struct socket *sock, struct sockaddr_unsized *uaddr,= int addr_len) diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 3d250e8204d5..cc7adeb0b7f6 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -1377,4 +1377,13 @@ mptcp_token_join_cookie_init_state(struct mptcp_subf= low_request_sock *subflow_re static inline void mptcp_join_cookie_init(void) {} #endif =20 +extern struct proto mptcp_prot; +int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len); +int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int fla= gs); + +#ifdef CONFIG_BPF_SYSCALL +int mptcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, + bool restore); +#endif + #endif /* __MPTCP_PROTOCOL_H */ --=20 2.53.0 From nobody Sat Sep 26 12:28:31 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7E5CC3B38B8 for ; Mon, 24 Aug 2026 07:10:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787555401; cv=none; b=p+mzi+JWi6J+UNjDEzcNFKy+RkZ6KGUkljSiG0OZFeyF7rnmnhKIDDuQdW6zv6JKT+bnDNaUbHbZS9CTJPqnPX4uAgIL8nXAwig10UOe+r+6WlN39JfSrk4MIgN1xEg2npRWq8qmQgUaDHg5zNRpKbyffyJQ+HYcCY08LgMjgW0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787555401; c=relaxed/simple; bh=/tCoiBHpivRnikKO1bIiybH6nP8R+8xASbKgHCCeUzM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dIouCUP8xENh6ejG7ALuY70vBWX8U6qyjMq5xspA4swDN3ezHePhQSYTnmkLC9Mlbp3X9kSMiZCFTicrYRPMWYmCLbgttxLCS78/2MkALbkgWhCsUrW0JyKewvxpKHw82e3dzbFlqC7kgMhBfysZ4Gd2oSSh0YDIPpWBrmkb3K8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RDSG0dL9; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RDSG0dL9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E6C261F00A3A; Mon, 24 Aug 2026 07:09:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787555400; bh=j+91zr+WaWKxIxWsKH8Avon/OEwxyZkzT/WmWOxqpao=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=RDSG0dL9SxFFXDTSX+2LVTJjzB3FkxOeEy17GiR5Pay3fBjOqzTDE0NkPf0h2StUo xBtIuy6w4v9WOkH932Cgam0S9gYczJIKLXGp/8vILRshIqOiGYcWXUd9n9ZPx21OMu RnW6p5DIgJFpwxyAkt1HpMggCgK1Rk8p/6ie1Jjz6+XEMjk0VTPJpJKy86QSJZEUMC M7nU8Br/1tbO7mg/oqiHQ7QO9ubwW5A5gefIXOxr/o8Qp1nvEeqvsygHhwNzsAhWm7 Wj3odtI9M8uabCovCa7ZAO170ejMajiRZ+0h7oD9jiQCIuakTfITp7ST9meIci/X7s 3G4qXxY6rtP8g== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Geliang Tang Subject: [PATCH mptcp-next v4 5/5] selftests/bpf: Update sockmap tests for MPTCP Date: Mon, 24 Aug 2026 15:09:39 +0800 Message-ID: <1cb449fc7531df4bade69ee95cbbe217db85c1cb.1787554581.git.tanggeliang@kylinos.cn> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Geliang Tang Update sockmap tests to reflect new MPTCP support. MPTCP sockets are now allowed in sockmap, so test expectations are adjusted accordingly. Use a different key (1) for MPTCP client sockets to validate sockmap. In test_sockmap_with_mptcp, client_fd1 is changed from TCP fallback to MPTCP. Since sockops fires on TCP subflows which have psock_update_sk_prot set to NULL, bpf_sock_map_update() returns -EOPNOTSUPP for MPTCP connections. Add server_fd1 and server_fd2 to the sockmap explicitly from userspace via bpf_map_update_elem() instead of relying on the sockops program. Signed-off-by: Geliang Tang --- .../testing/selftests/bpf/prog_tests/mptcp.c | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/mptcp.c b/tools/testing= /selftests/bpf/prog_tests/mptcp.c index d77c9f8c53c7..4f8727dbcbfd 100644 --- a/tools/testing/selftests/bpf/prog_tests/mptcp.c +++ b/tools/testing/selftests/bpf/prog_tests/mptcp.c @@ -500,30 +500,36 @@ static void test_subflow(void) close(cgroup_fd); } =20 -/* Test sockmap on MPTCP server handling non-mp-capable clients. */ -static void test_sockmap_with_mptcp_fallback(struct mptcp_sockmap *skel) +/* Test sockmap on MPTCP server handling MPTCP clients. */ +static void test_sockmap_with_mptcp(struct mptcp_sockmap *skel) { int listen_fd =3D -1, client_fd1 =3D -1, client_fd2 =3D -1; int server_fd1 =3D -1, server_fd2 =3D -1, sent, recvd; char snd[9] =3D "123456789"; + int zero =3D 0, err; char rcv[10]; =20 /* start server with MPTCP enabled */ listen_fd =3D start_mptcp_server(AF_INET, NULL, 0, 0); - if (!ASSERT_OK_FD(listen_fd, "sockmap-fb:start_mptcp_server")) + if (!ASSERT_OK_FD(listen_fd, "sockmap:start_mptcp_server")) return; =20 skel->bss->trace_port =3D ntohs(get_socket_local_port(listen_fd)); skel->bss->sk_index =3D 0; - /* create client without MPTCP enabled */ - client_fd1 =3D connect_to_fd_opts(listen_fd, NULL); - if (!ASSERT_OK_FD(client_fd1, "sockmap-fb:connect_to_fd")) + /* create client with MPTCP enabled */ + client_fd1 =3D connect_to_fd(listen_fd, 0); + if (!ASSERT_OK_FD(client_fd1, "sockmap:connect_to_fd")) goto end; =20 server_fd1 =3D accept(listen_fd, NULL, 0); + err =3D bpf_map_update_elem(bpf_map__fd(skel->maps.sock_map), + &zero, &server_fd1, BPF_NOEXIST); + if (!ASSERT_OK(err, "sockmap:add server_fd1")) + goto end; + skel->bss->sk_index =3D 1; client_fd2 =3D connect_to_fd_opts(listen_fd, NULL); - if (!ASSERT_OK_FD(client_fd2, "sockmap-fb:connect_to_fd")) + if (!ASSERT_OK_FD(client_fd2, "sockmap:connect_to_fd")) goto end; =20 server_fd2 =3D accept(listen_fd, NULL, 0); @@ -532,12 +538,12 @@ static void test_sockmap_with_mptcp_fallback(struct m= ptcp_sockmap *skel) */ skel->bss->redirect_idx =3D 1; sent =3D send(client_fd1, snd, sizeof(snd), 0); - if (!ASSERT_EQ(sent, sizeof(snd), "sockmap-fb:send(client_fd1)")) + if (!ASSERT_EQ(sent, sizeof(snd), "sockmap:send(client_fd1)")) goto end; =20 /* try to recv more bytes to avoid truncation check */ recvd =3D recv(client_fd2, rcv, sizeof(rcv), 0); - if (!ASSERT_EQ(recvd, sizeof(snd), "sockmap-fb:recv(client_fd2)")) + if (!ASSERT_EQ(recvd, sizeof(snd), "sockmap:recv(client_fd2)")) goto end; =20 end: @@ -552,11 +558,11 @@ static void test_sockmap_with_mptcp_fallback(struct m= ptcp_sockmap *skel) close(listen_fd); } =20 -/* Test sockmap rejection of MPTCP sockets - both server and client sides.= */ -static void test_sockmap_reject_mptcp(struct mptcp_sockmap *skel) +/* Test sockmap of MPTCP sockets - both server and client sides. */ +static void test_sockmap_mptcp_support(struct mptcp_sockmap *skel) { int listen_fd =3D -1, server_fd =3D -1, client_fd1 =3D -1; - int err, zero =3D 0; + int err, zero =3D 0, one =3D 1; =20 /* start server with MPTCP enabled */ listen_fd =3D start_mptcp_server(AF_INET, NULL, 0, 0); @@ -577,13 +583,13 @@ static void test_sockmap_reject_mptcp(struct mptcp_so= ckmap *skel) server_fd =3D accept(listen_fd, NULL, 0); err =3D bpf_map_update_elem(bpf_map__fd(skel->maps.sock_map), &zero, &server_fd, BPF_NOEXIST); - if (!ASSERT_EQ(err, -EOPNOTSUPP, "server should be disallowed")) + if (!ASSERT_EQ(err, 0, "server should be allowed")) goto end; =20 - /* MPTCP client should also be disallowed */ + /* MPTCP client should also be allowed */ err =3D bpf_map_update_elem(bpf_map__fd(skel->maps.sock_map), - &zero, &client_fd1, BPF_NOEXIST); - if (!ASSERT_EQ(err, -EOPNOTSUPP, "client should be disallowed")) + &one, &client_fd1, BPF_NOEXIST); + if (!ASSERT_EQ(err, 0, "client should be allowed")) goto end; end: if (client_fd1 >=3D 0) @@ -625,8 +631,8 @@ static void test_mptcp_sockmap(void) if (endpoint_init("subflow", 2) < 0) goto close_netns; =20 - test_sockmap_with_mptcp_fallback(skel); - test_sockmap_reject_mptcp(skel); + test_sockmap_with_mptcp(skel); + test_sockmap_mptcp_support(skel); =20 close_netns: netns_free(netns); --=20 2.53.0