From nobody Fri Apr 10 18:09:52 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 19DE9318B9C for ; Mon, 6 Apr 2026 12:20:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775478007; cv=none; b=iP3TB+37W0OAxP5/zFrLOaVVF43wjPNUKae0BqiFSjJOk7ie66FVrGMeisedfIkLK1C+/phun9GyjA8YX93XiM0kP4XuxzALOZocnlCinc4iMN2bsB7uiac+Yrdr8mTG/E1SCQkdVxxW5kLXGBYkCZ6O4Ov19jC2q3wf1pF+2jw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775478007; c=relaxed/simple; bh=7ZkrGvPcpgvQIvFdIyY5IFps1ph7I9VusEiFQQ2aoXQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HJU9Jw0opAReoHuyPDo6m0rhb2ao9VeTBvhQKSzbvmnX/1z3uPdn6BxvLFPNhegVF/1SspWs9IhlRApYwwXB9Ytp21Io2d3BP6a8DcIpgGw2iYs7MMmHKjLS+LJfw8/ZY388Oqk7kIZCVagIDRlvmKe2/V4H/bqdM/6Ter4shlE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FKpWyr3a; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FKpWyr3a" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 70ED1C4CEF7; Mon, 6 Apr 2026 12:20:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1775478006; bh=7ZkrGvPcpgvQIvFdIyY5IFps1ph7I9VusEiFQQ2aoXQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FKpWyr3axAdKhlocCX2/TaW5YUFfCvlp0cIhTBlr0gODw7V6EZzXYXzkD0jsQL81y tc2/mK8aBM0P6hMmY/JQTBV6sxW5DAoijjPpfhJ7tS+BOfOU0v3pIMACLTDApsZeY9 XvZsOMjr/ZWBudq/jVEtOnJtnl7iuSiRxDrgBtXdyDaJi0fktyoi2WSq9SyOklqZ5U SajjA8HQghdnNnzW7GdCU8cbyqCwKXPrdQK05IE/qbGG2a0HudZUKU0vuob2826Fwb OOhWq0Y/HQCHnG0UZgOFe4ugSKUQ3LGykZhewGyHHJ5eNY2nV/itgd1Eil9UFEeaJ1 2UGV7yxclwOYQ== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Geliang Tang , Gang Yan Subject: [RFC mptcp-next v14 05/15] mptcp: implement tls_mptcp_ops Date: Mon, 6 Apr 2026 20:18:45 +0800 Message-ID: X-Mailer: git-send-email 2.51.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 MPTCP-specific struct tls_prot_ops, named 'tls_mptcp_ops'. Note that there is a slight difference between mptcp_inq() and mptcp_inq_hint(), it does not return 1 when the socket is closed or shut down; instead, it returns 0. Otherwise, it would break the condition "inq < 1" in tls_strp_read_sock(). Passing an MPTCP socket to tcp_sock_rate_check_app_limited() can trigger a crash. Here, an MPTCP version of check_app_limited() is implemented, which calls tcp_sock_rate_check_app_limited() for each subflow. When MPTCP implements lock_is_held interface, it not only checks sock_owned_by_user_nocheck(sk) as TCP does, but also needs to check whether the MPTCP data lock is held. Co-developed-by: Gang Yan Signed-off-by: Gang Yan Signed-off-by: Geliang Tang --- include/net/mptcp.h | 2 + include/net/tcp.h | 1 + net/ipv4/tcp.c | 9 +++- net/mptcp/protocol.c | 107 ++++++++++++++++++++++++++++++++++++++++--- net/mptcp/protocol.h | 1 + net/tls/tls_main.c | 6 +++ 6 files changed, 118 insertions(+), 8 deletions(-) diff --git a/include/net/mptcp.h b/include/net/mptcp.h index 4cf59e83c1c5..02564eceeb7e 100644 --- a/include/net/mptcp.h +++ b/include/net/mptcp.h @@ -132,6 +132,8 @@ struct mptcp_pm_ops { void (*release)(struct mptcp_sock *msk); } ____cacheline_aligned_in_smp; =20 +extern struct tls_prot_ops tls_mptcp_ops; + #ifdef CONFIG_MPTCP void mptcp_init(void); =20 diff --git a/include/net/tcp.h b/include/net/tcp.h index 6156d1d068e1..2a10bfffebf6 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -851,6 +851,7 @@ static inline int tcp_bound_to_half_wnd(struct tcp_sock= *tp, int pktsize) =20 /* tcp.c */ void tcp_get_info(struct sock *, struct tcp_info *); +void tcp_sock_rate_check_app_limited(struct tcp_sock *tp); void tcp_rate_check_app_limited(struct sock *sk); =20 /* Read 'sendfile()'-style from a TCP socket */ diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f2d2884652ea..4b8cf7ca2695 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1100,9 +1100,9 @@ int tcp_sendmsg_fastopen(struct sock *sk, struct msgh= dr *msg, int *copied, } =20 /* If a gap is detected between sends, mark the socket application-limited= . */ -void tcp_rate_check_app_limited(struct sock *sk) +void tcp_sock_rate_check_app_limited(struct tcp_sock *tp) { - struct tcp_sock *tp =3D tcp_sk(sk); + struct sock *sk =3D (struct sock *)tp; =20 if (/* We have less than one packet to send. */ tp->write_seq - tp->snd_nxt < tp->mss_cache && @@ -1115,6 +1115,11 @@ void tcp_rate_check_app_limited(struct sock *sk) tp->app_limited =3D (tp->delivered + tcp_packets_in_flight(tp)) ? : 1; } + +void tcp_rate_check_app_limited(struct sock *sk) +{ + tcp_sock_rate_check_app_limited(tcp_sk(sk)); +} EXPORT_SYMBOL_GPL(tcp_rate_check_app_limited); =20 int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index f0afd06e2494..d780989679a1 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -24,11 +24,12 @@ #include #include #include +#include #include #include "protocol.h" #include "mib.h" =20 -static unsigned int mptcp_inq_hint(const struct sock *sk); +static unsigned int mptcp_inq_hint(struct sock *sk); =20 #define CREATE_TRACE_POINTS #include @@ -1895,7 +1896,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) +static int mptcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_= t len) { struct mptcp_sock *msk =3D mptcp_sk(sk); struct page_frag *pfrag; @@ -1907,8 +1908,6 @@ static int mptcp_sendmsg(struct sock *sk, struct msgh= dr *msg, size_t len) msg->msg_flags &=3D MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL | MSG_FASTOPEN | MSG_EOR; =20 - lock_sock(sk); - mptcp_rps_record_subflows(msk); =20 if (unlikely(inet_test_bit(DEFER_CONNECT, sk) || @@ -2024,7 +2023,6 @@ static int mptcp_sendmsg(struct sock *sk, struct msgh= dr *msg, size_t len) } =20 out: - release_sock(sk); return copied; =20 do_error: @@ -2035,6 +2033,17 @@ static int mptcp_sendmsg(struct sock *sk, struct msg= hdr *msg, size_t len) goto out; } =20 +static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) +{ + int ret; + + lock_sock(sk); + ret =3D mptcp_sendmsg_locked(sk, msg, len); + release_sock(sk); + + return ret; +} + static void mptcp_rcv_space_adjust(struct mptcp_sock *msk, int copied); =20 static void mptcp_eat_recv_skb(struct sock *sk, struct sk_buff *skb) @@ -2265,7 +2274,7 @@ static bool mptcp_move_skbs(struct sock *sk) return enqueued; } =20 -static unsigned int mptcp_inq_hint(const struct sock *sk) +static int mptcp_inq(struct sock *sk) { const struct mptcp_sock *msk =3D mptcp_sk(sk); const struct sk_buff *skb; @@ -2280,6 +2289,16 @@ static unsigned int mptcp_inq_hint(const struct sock= *sk) return (unsigned int)hint_val; } =20 + return 0; +} + +static unsigned int mptcp_inq_hint(struct sock *sk) +{ + unsigned int inq =3D mptcp_inq(sk); + + if (inq) + return inq; + if (sk->sk_state =3D=3D TCP_CLOSE || (sk->sk_shutdown & RCV_SHUTDOWN)) return 1; =20 @@ -4708,3 +4727,79 @@ int __init mptcp_proto_v6_init(void) return err; } #endif + +static bool mptcp_lock_is_held(struct sock *sk) +{ + return sock_owned_by_user_nocheck(sk) || + mptcp_data_is_locked(sk); +} + +static void mptcp_read_done(struct sock *sk, size_t len) +{ + struct mptcp_sock *msk =3D mptcp_sk(sk); + struct sk_buff *skb; + size_t left; + u32 offset; + + msk_owned_by_me(msk); + + if (sk->sk_state =3D=3D TCP_LISTEN) + return; + + left =3D len; + while (left && (skb =3D mptcp_recv_skb(sk, &offset)) !=3D NULL) { + int used; + + used =3D min_t(size_t, skb->len - offset, left); + msk->bytes_consumed +=3D used; + MPTCP_SKB_CB(skb)->offset +=3D used; + MPTCP_SKB_CB(skb)->map_seq +=3D used; + left -=3D used; + + if (skb->len > offset + used) + break; + + mptcp_eat_recv_skb(sk, skb); + } + + mptcp_rcv_space_adjust(msk, len - left); + + /* Clean up data we have read: This will do ACK frames. */ + if (left !=3D len) + mptcp_cleanup_rbuf(msk, len - left); +} + +static u32 mptcp_get_skb_seq(struct sk_buff *skb) +{ + return MPTCP_SKB_CB(skb)->map_seq - MPTCP_SKB_CB(skb)->offset; +} + +static void mptcp_check_app_limited(struct sock *sk) +{ + struct mptcp_sock *msk =3D mptcp_sk(sk); + struct mptcp_subflow_context *subflow; + + mptcp_for_each_subflow(msk, subflow) { + struct sock *ssk =3D mptcp_subflow_tcp_sock(subflow); + bool slow; + + slow =3D lock_sock_fast(ssk); + tcp_sock_rate_check_app_limited(tcp_sk(ssk)); + unlock_sock_fast(ssk, slow); + } +} + +struct tls_prot_ops tls_mptcp_ops =3D { + .protocol =3D IPPROTO_MPTCP, + .inq =3D mptcp_inq, + .sendmsg_locked =3D mptcp_sendmsg_locked, + .recv_skb =3D mptcp_recv_skb, + .lock_is_held =3D mptcp_lock_is_held, + .read_sock =3D mptcp_read_sock, + .read_done =3D mptcp_read_done, + .get_skb_seq =3D mptcp_get_skb_seq, + .poll =3D mptcp_poll, + .epollin_ready =3D mptcp_epollin_ready, + .check_app_limited =3D mptcp_check_app_limited, +}; +EXPORT_SYMBOL(tls_mptcp_ops); diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 740f9d975719..8ca7230633ca 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -380,6 +380,7 @@ struct mptcp_sock { =20 #define mptcp_data_lock(sk) spin_lock_bh(&(sk)->sk_lock.slock) #define mptcp_data_unlock(sk) spin_unlock_bh(&(sk)->sk_lock.slock) +#define mptcp_data_is_locked(sk) spin_is_locked(&(sk)->sk_lock.slock) =20 #define mptcp_for_each_subflow(__msk, __subflow) \ list_for_each_entry(__subflow, &((__msk)->conn_list), node) diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index 637cb6aa8288..22625855213e 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c @@ -1379,6 +1379,9 @@ static int __init tls_register(void) tcp_register_ulp(&tcp_tls_ulp_ops); =20 tls_register_prot_ops(&tls_tcp_ops); +#ifdef CONFIG_MPTCP + tls_register_prot_ops(&tls_mptcp_ops); +#endif =20 return 0; err_strp: @@ -1391,6 +1394,9 @@ static int __init tls_register(void) static void __exit tls_unregister(void) { tls_proto_cleanup(); +#ifdef CONFIG_MPTCP + tls_unregister_prot_ops(&tls_mptcp_ops); +#endif tls_unregister_prot_ops(&tls_tcp_ops); tcp_unregister_ulp(&tcp_tls_ulp_ops); tls_strp_dev_exit(); --=20 2.51.0