From nobody Wed Apr 1 22:15:14 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 33CE6406297 for ; Wed, 1 Apr 2026 12:54:28 +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=1775048068; cv=none; b=Na2wlIv2LT3CI9pMycAWz20m06P4T68HcimPTfwc76f5Ek9I7t/Jydv20A9cxH9jslD75AxkMemrxJf/PQKWOCKbWsA4X9vgrRySUZkaU00JkWTSmqsjPsPcgh4yPWZP96mWU+pBKZet87a51ReEtvTR3bYJuXH/80UKcvnO0jg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775048068; c=relaxed/simple; bh=CvrKBWIacTzuM4sVKLfPAXsBK2tmuH3oC6bzXlhtyHI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=T4P7JpELFEfjAmz/0soghYWXP3ZKZmglqVnBsaT9QXh/OPELhMreEqcN+X+CKPL0k5vIqm9k873GOFX8lQ6cRLIsi9dDwh6Jf9fW3ndjUWql7zk10BkZ1ujWCmH2agxlZnETbkEN0VPLBNJ1Jj7499fBPvnSlQSW5IRVXUm2Kvs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kyM1zUgO; 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="kyM1zUgO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0E7E5C116C6; Wed, 1 Apr 2026 12:54:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1775048067; bh=CvrKBWIacTzuM4sVKLfPAXsBK2tmuH3oC6bzXlhtyHI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kyM1zUgOhumAZOIT29qb28NNocbWe+6LG7lp9P/GGHadu83zsa/6epOTGaGnJY+Y6 unST+yiyKTN6RHW/UxgdK/IeXCWMw2zvbvyG3gHXIYBMMvlC0mr6Yc3jEAmI72S2ak /dug78ruq5ZHFs1QdvDtk4OYiJvmHLi5trm9JMf2rlQwRSsSBGGo7Gggocoigi6APB leUJpkgsWpwQstcc81XRsu5j8nBgtxGPFGW6IZCRBfAH4X+2bMRRHB0/+N3HScbdcu LzamKTouFq+1C401eLTaliBwU7QFbpIuj7nc1epJwpV9XU3UoxRWqADUoXt5z2TpkM rBKIbBF4Wh+Vw== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Geliang Tang , Hannes Reinecke , zhenwei pi , Hui Zhu , Gang Yan Subject: [RFC mptcp-next v8 6/7] nvme-tcp: implement host mptcp proto Date: Wed, 1 Apr 2026 20:53:44 +0800 Message-ID: <809b0993a41df56f3d6627e6ebddd8b158551faa.1775047736.git.tanggeliang@kylinos.cn> 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 An MPTCP-specific version of struct nvme_tcp_proto is implemented, and it is assigned to ctrl->proto when the transport string is "mptcp". The socket option setting logic is similar to the target side, except that mptcp_sock_set_syncnt is newly defined for the host side. It sets the value on the first subflow socket of an MPTCP connection. The value is then synchronized to other newly created subflows in sync_socket_options(). A separate nvme_mptcp_ctrl_ops structure with .name =3D "mptcp" is defined and used for MPTCP controllers. Cc: Hannes Reinecke Co-developed-by: zhenwei pi Signed-off-by: zhenwei pi Co-developed-by: Hui Zhu Signed-off-by: Hui Zhu Co-developed-by: Gang Yan Signed-off-by: Gang Yan Signed-off-by: Geliang Tang --- drivers/nvme/host/tcp.c | 34 ++++++++++++++++++++++++++++++++++ include/net/mptcp.h | 7 +++++++ net/mptcp/protocol.h | 1 + net/mptcp/sockopt.c | 25 +++++++++++++++++++++++++ 4 files changed, 67 insertions(+) diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 30ff6e03b32f..54d27acdd4b5 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -2889,6 +2889,24 @@ static const struct nvme_ctrl_ops nvme_tcp_ctrl_ops = =3D { .get_virt_boundary =3D nvmf_get_virt_boundary, }; =20 +#ifdef CONFIG_MPTCP +static const struct nvme_ctrl_ops nvme_mptcp_ctrl_ops =3D { + .name =3D "mptcp", + .module =3D THIS_MODULE, + .flags =3D NVME_F_FABRICS | NVME_F_BLOCKING, + .reg_read32 =3D nvmf_reg_read32, + .reg_read64 =3D nvmf_reg_read64, + .reg_write32 =3D nvmf_reg_write32, + .subsystem_reset =3D nvmf_subsystem_reset, + .free_ctrl =3D nvme_tcp_free_ctrl, + .submit_async_event =3D nvme_tcp_submit_async_event, + .delete_ctrl =3D nvme_tcp_delete_ctrl, + .get_address =3D nvme_tcp_get_address, + .stop_ctrl =3D nvme_tcp_stop_ctrl, + .get_virt_boundary =3D nvmf_get_virt_boundary, +}; +#endif + static bool nvme_tcp_existing_controller(struct nvmf_ctrl_options *opts) { @@ -2916,6 +2934,18 @@ static const struct nvme_tcp_proto nvme_tcp_proto = =3D { .ops =3D &nvme_tcp_ctrl_ops, }; =20 +#ifdef CONFIG_MPTCP +static const struct nvme_tcp_proto nvme_mptcp_proto =3D { + .protocol =3D IPPROTO_MPTCP, + .set_syncnt =3D mptcp_sock_set_syncnt, + .set_nodelay =3D mptcp_sock_set_nodelay, + .no_linger =3D mptcp_sock_no_linger, + .set_priority =3D mptcp_sock_set_priority, + .set_tos =3D mptcp_sock_set_tos, + .ops =3D &nvme_mptcp_ctrl_ops, +}; +#endif + static struct nvme_tcp_ctrl *nvme_tcp_alloc_ctrl(struct device *dev, struct nvmf_ctrl_options *opts) { @@ -2982,6 +3012,10 @@ static struct nvme_tcp_ctrl *nvme_tcp_alloc_ctrl(str= uct device *dev, =20 if (!strcmp(ctrl->ctrl.opts->transport, "tcp")) { rcu_assign_pointer(ctrl->proto, &nvme_tcp_proto); +#ifdef CONFIG_MPTCP + } else if (!strcmp(ctrl->ctrl.opts->transport, "mptcp")) { + rcu_assign_pointer(ctrl->proto, &nvme_mptcp_proto); +#endif } else { ret =3D -EINVAL; goto out_free_ctrl; diff --git a/include/net/mptcp.h b/include/net/mptcp.h index 91ce7b9b639d..49031a111e69 100644 --- a/include/net/mptcp.h +++ b/include/net/mptcp.h @@ -247,6 +247,8 @@ void mptcp_sock_set_priority(struct sock *sk, u32 prior= ity); void mptcp_sock_no_linger(struct sock *sk); =20 void mptcp_sock_set_tos(struct sock *sk, int val); + +int mptcp_sock_set_syncnt(struct sock *sk, int val); #else =20 static inline void mptcp_init(void) @@ -343,6 +345,11 @@ static inline void mptcp_sock_set_priority(struct sock= *sk, u32 priority) { } static inline void mptcp_sock_no_linger(struct sock *sk) { } =20 static inline void mptcp_sock_set_tos(struct sock *sk, int val) { } + +static inline int mptcp_sock_set_syncnt(struct sock *sk, int val) +{ + return 0; +} #endif /* CONFIG_MPTCP */ =20 #if IS_ENABLED(CONFIG_MPTCP_IPV6) diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index f5d4d7d030f2..84e80816b2a4 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -335,6 +335,7 @@ struct mptcp_sock { int keepalive_idle; int keepalive_intvl; int maxseg; + int icsk_syn_retries; struct work_struct work; struct sk_buff *ooo_last_skb; struct rb_root out_of_order_queue; diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c index 0f18398932a0..814cebc9125f 100644 --- a/net/mptcp/sockopt.c +++ b/net/mptcp/sockopt.c @@ -1592,6 +1592,7 @@ static void sync_socket_options(struct mptcp_sock *ms= k, struct sock *ssk) priority =3D READ_ONCE(sk->sk_priority); if (priority > 0) sock_set_priority(ssk, priority); + tcp_sock_set_syncnt(ssk, msk->icsk_syn_retries); } =20 void mptcp_sockopt_sync_locked(struct mptcp_sock *msk, struct sock *ssk) @@ -1743,3 +1744,27 @@ void mptcp_sock_set_tos(struct sock *sk, int val) release_sock(sk); } EXPORT_SYMBOL(mptcp_sock_set_tos); + +int mptcp_sock_set_syncnt(struct sock *sk, int val) +{ + struct mptcp_sock *msk =3D mptcp_sk(sk); + struct sock *ssk; + int ret =3D 0; + + if (val < 1 || val > MAX_TCP_SYNCNT) + return -EINVAL; + + lock_sock(sk); + sockopt_seq_inc(msk); + msk->icsk_syn_retries =3D val; + ssk =3D __mptcp_nmpc_sk(msk); + if (IS_ERR(ssk)) { + ret =3D PTR_ERR(ssk); + goto unlock; + } + tcp_sock_set_syncnt(ssk, val); +unlock: + release_sock(sk); + return ret; +} +EXPORT_SYMBOL(mptcp_sock_set_syncnt); --=20 2.51.0