[PATCH 02/11] nvmet-tcp: implement accept mptcp proto
Geliang Tang
geliang at kernel.org
Wed May 27 20:10:36 PDT 2026
From: Geliang Tang <tanggeliang at kylinos.cn>
An MPTCP-specific version of struct nvmet_tcp_proto is implemented for
accept sockets. It is assigned to queue->proto when the accepted socket
protocol is IPPROTO_MPTCP.
Dedicated MPTCP helpers are introduced for setting accept socket options.
These helpers (no_linger, set_priority, set_tos) set the values on all
existing subflows using mptcp_for_each_subflow(). The values are then
synchronized to other newly created subflows in sync_socket_options().
Cc: Hannes Reinecke <hare at suse.de>
Cc: John Meneghini <jmeneghi at redhat.com>
Cc: Randy Jennings <randyj at purestorage.com>
Cc: Nilay Shroff <nilay at linux.ibm.com>
Co-developed-by: zhenwei pi <zhenwei.pi at linux.dev>
Signed-off-by: zhenwei pi <zhenwei.pi at linux.dev>
Co-developed-by: Hui Zhu <zhuhui at kylinos.cn>
Signed-off-by: Hui Zhu <zhuhui at kylinos.cn>
Co-developed-by: Gang Yan <yangang at kylinos.cn>
Signed-off-by: Gang Yan <yangang at kylinos.cn>
Signed-off-by: Geliang Tang <tanggeliang at kylinos.cn>
---
drivers/nvme/target/tcp.c | 16 ++++++++
include/net/mptcp.h | 12 ++++++
net/mptcp/sockopt.c | 79 +++++++++++++++++++++++++++++++++++++++
3 files changed, 107 insertions(+)
diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
index 01c23fb15b79..16f153a9772b 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -220,6 +220,9 @@ static DEFINE_MUTEX(nvmet_tcp_queue_mutex);
static struct workqueue_struct *nvmet_tcp_wq;
static const struct nvmet_fabrics_ops nvmet_tcp_ops;
+#ifdef CONFIG_MPTCP
+static const struct nvmet_fabrics_ops nvmet_mptcp_ops;
+#endif
static void nvmet_tcp_free_cmd(struct nvmet_tcp_cmd *c);
static void nvmet_tcp_free_cmd_buffers(struct nvmet_tcp_cmd *cmd);
@@ -1928,6 +1931,15 @@ static const struct nvmet_tcp_proto nvmet_tcp_proto = {
.ops = &nvmet_tcp_ops,
};
+#ifdef CONFIG_MPTCP
+static const struct nvmet_tcp_proto nvmet_mptcp_proto = {
+ .no_linger = mptcp_sock_no_linger,
+ .set_priority = mptcp_sock_set_priority,
+ .set_tos = mptcp_sock_set_tos,
+ .ops = &nvmet_mptcp_ops,
+};
+#endif
+
static void nvmet_tcp_alloc_queue(struct nvmet_tcp_port *port,
struct socket *newsock)
{
@@ -1947,6 +1959,10 @@ static void nvmet_tcp_alloc_queue(struct nvmet_tcp_port *port,
queue->sock = newsock;
if (newsock->sk->sk_protocol == IPPROTO_TCP) {
queue->proto = &nvmet_tcp_proto;
+#ifdef CONFIG_MPTCP
+ } else if (newsock->sk->sk_protocol == IPPROTO_MPTCP) {
+ queue->proto = &nvmet_mptcp_proto;
+#endif
} else {
ret = -EINVAL;
goto out_free_queue;
diff --git a/include/net/mptcp.h b/include/net/mptcp.h
index aef2dbeb847b..bf74dedc578d 100644
--- a/include/net/mptcp.h
+++ b/include/net/mptcp.h
@@ -233,6 +233,12 @@ static inline __be32 mptcp_reset_option(const struct sk_buff *skb)
}
void mptcp_active_detect_blackhole(struct sock *sk, bool expired);
+
+void mptcp_sock_no_linger(struct sock *sk);
+
+void mptcp_sock_set_priority(struct sock *sk, u32 priority);
+
+void mptcp_sock_set_tos(struct sock *sk);
#else
static inline void mptcp_init(void)
@@ -319,6 +325,12 @@ static inline struct request_sock *mptcp_subflow_reqsk_alloc(const struct reques
static inline __be32 mptcp_reset_option(const struct sk_buff *skb) { return htonl(0u); }
static inline void mptcp_active_detect_blackhole(struct sock *sk, bool expired) { }
+
+static inline void mptcp_sock_no_linger(struct sock *sk) { }
+
+static inline void mptcp_sock_set_priority(struct sock *sk, u32 priority) { }
+
+static inline void mptcp_sock_set_tos(struct sock *sk) { }
#endif /* CONFIG_MPTCP */
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
index 87b5796d0135..359b1eb2d0a9 100644
--- a/net/mptcp/sockopt.c
+++ b/net/mptcp/sockopt.c
@@ -1662,3 +1662,82 @@ int mptcp_set_rcvlowat(struct sock *sk, int val)
}
return 0;
}
+
+void mptcp_sock_no_linger(struct sock *sk)
+{
+ struct mptcp_sock *msk = mptcp_sk(sk);
+ struct mptcp_subflow_context *subflow;
+ struct sock *ssk;
+
+ lock_sock(sk);
+ sockopt_seq_inc(msk);
+ WRITE_ONCE(sk->sk_lingertime, 0);
+ sock_set_flag(sk, SOCK_LINGER);
+ mptcp_for_each_subflow(msk, subflow) {
+ ssk = mptcp_subflow_tcp_sock(subflow);
+ if (ssk) {
+ lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
+ WRITE_ONCE(ssk->sk_lingertime, 0);
+ sock_set_flag(ssk, SOCK_LINGER);
+ release_sock(ssk);
+ }
+ }
+ release_sock(sk);
+}
+EXPORT_SYMBOL(mptcp_sock_no_linger);
+
+void mptcp_sock_set_priority(struct sock *sk, u32 priority)
+{
+ struct mptcp_sock *msk = mptcp_sk(sk);
+ struct mptcp_subflow_context *subflow;
+ struct sock *ssk;
+
+ lock_sock(sk);
+ sockopt_seq_inc(msk);
+ sock_set_priority(sk, priority);
+ mptcp_for_each_subflow(msk, subflow) {
+ ssk = mptcp_subflow_tcp_sock(subflow);
+ if (ssk) {
+ lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
+ sock_set_priority(ssk, priority);
+ release_sock(ssk);
+ }
+ }
+ release_sock(sk);
+}
+EXPORT_SYMBOL(mptcp_sock_set_priority);
+
+static void __mptcp_sock_set_tos(struct sock *sk, int val)
+{
+ struct mptcp_sock *msk = mptcp_sk(sk);
+ struct mptcp_subflow_context *subflow;
+ struct sock *ssk;
+
+ lock_sock(sk);
+ sockopt_seq_inc(msk);
+ __ip_sock_set_tos(sk, val);
+ mptcp_for_each_subflow(msk, subflow) {
+ ssk = mptcp_subflow_tcp_sock(subflow);
+ if (ssk) {
+ lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
+ __ip_sock_set_tos(ssk, val);
+ release_sock(ssk);
+ }
+ }
+ release_sock(sk);
+}
+
+void mptcp_sock_set_tos(struct sock *sk)
+{
+ struct mptcp_sock *msk = mptcp_sk(sk);
+ int val = 0;
+
+ lock_sock(sk);
+ if (msk->first)
+ val = inet_sk(msk->first)->rcv_tos;
+ release_sock(sk);
+
+ if (val > 0)
+ __mptcp_sock_set_tos(sk, val);
+}
+EXPORT_SYMBOL(mptcp_sock_set_tos);
--
2.53.0
More information about the Linux-nvme
mailing list