From: Geliang Tang <[email protected]>

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 <[email protected]>
Cc: John Meneghini <[email protected]>
Cc: Randy Jennings <[email protected]>
Cc: Nilay Shroff <[email protected]>
Co-developed-by: zhenwei pi <[email protected]>
Signed-off-by: zhenwei pi <[email protected]>
Co-developed-by: Hui Zhu <[email protected]>
Signed-off-by: Hui Zhu <[email protected]>
Co-developed-by: Gang Yan <[email protected]>
Signed-off-by: Gang Yan <[email protected]>
Signed-off-by: Geliang Tang <[email protected]>
---
 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


Reply via email to