From: Geliang Tang <[email protected]>

An MPTCP-specific version of struct nvmet_tcp_proto_ops is implemented
for listen sockets. It is assigned to port->proto_ops when the transport
type is MPTCP.

Dedicated MPTCP helpers are introduced for setting listen socket options.
The set_nodelay and set_priority helpers set the values on all existing
subflows using mptcp_for_each_subflow(). The set_reuseaddr helper only
applies to the first 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 | 13 ++++++++++++
 include/net/mptcp.h       |  8 ++++++++
 net/mptcp/sockopt.c       | 42 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 63 insertions(+)

diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
index e2f3de364c2b..8c2dc4bcbcd3 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -2101,6 +2101,15 @@ static const struct nvmet_tcp_proto_ops 
nvmet_tcp_proto_ops = {
        .set_priority   = sock_set_priority,
 };
 
+#ifdef CONFIG_MPTCP
+static const struct nvmet_tcp_proto_ops nvmet_mptcp_proto_ops = {
+       .protocol       = IPPROTO_MPTCP,
+       .set_reuseaddr  = mptcp_sock_set_reuseaddr,
+       .set_nodelay    = mptcp_sock_set_nodelay,
+       .set_priority   = mptcp_sock_set_priority,
+};
+#endif
+
 static int nvmet_tcp_add_port(struct nvmet_port *nport)
 {
        const struct nvmet_tcp_proto_ops *ops;
@@ -2128,6 +2137,10 @@ static int nvmet_tcp_add_port(struct nvmet_port *nport)
 
        if (nport->disc_addr.trtype == NVMF_TRTYPE_TCP) {
                ops = &nvmet_tcp_proto_ops;
+#ifdef CONFIG_MPTCP
+       } else if (nport->disc_addr.trtype == NVMF_TRTYPE_MPTCP) {
+               ops = &nvmet_mptcp_proto_ops;
+#endif
        } else {
                ret = -EINVAL;
                goto err_port;
diff --git a/include/net/mptcp.h b/include/net/mptcp.h
index bf74dedc578d..b8ab214a7890 100644
--- a/include/net/mptcp.h
+++ b/include/net/mptcp.h
@@ -239,6 +239,10 @@ 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);
+
+void mptcp_sock_set_reuseaddr(struct sock *sk);
+
+void mptcp_sock_set_nodelay(struct sock *sk);
 #else
 
 static inline void mptcp_init(void)
@@ -331,6 +335,10 @@ 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) { }
+
+static inline void mptcp_sock_set_reuseaddr(struct sock *sk) { }
+
+static inline void mptcp_sock_set_nodelay(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 359b1eb2d0a9..0adbbe568f6e 100644
--- a/net/mptcp/sockopt.c
+++ b/net/mptcp/sockopt.c
@@ -1596,6 +1596,8 @@ static void sync_socket_options(struct mptcp_sock *msk, 
struct sock *ssk)
        inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
        inet_assign_bit(BIND_ADDRESS_NO_PORT, ssk, 
inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
        WRITE_ONCE(inet_sk(ssk)->local_port_range, 
READ_ONCE(inet_sk(sk)->local_port_range));
+
+       ssk->sk_reuse = sk->sk_reuse;
 }
 
 void mptcp_sockopt_sync_locked(struct mptcp_sock *msk, struct sock *ssk)
@@ -1741,3 +1743,43 @@ void mptcp_sock_set_tos(struct sock *sk)
                __mptcp_sock_set_tos(sk, val);
 }
 EXPORT_SYMBOL(mptcp_sock_set_tos);
+
+void mptcp_sock_set_reuseaddr(struct sock *sk)
+{
+       struct mptcp_sock *msk = mptcp_sk(sk);
+       struct sock *ssk;
+
+       lock_sock(sk);
+       sockopt_seq_inc(msk);
+       sk->sk_reuse = SK_CAN_REUSE;
+       ssk = __mptcp_nmpc_sk(msk);
+       if (IS_ERR(ssk))
+               goto unlock;
+       lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
+       ssk->sk_reuse = SK_CAN_REUSE;
+       release_sock(ssk);
+unlock:
+       release_sock(sk);
+}
+EXPORT_SYMBOL(mptcp_sock_set_reuseaddr);
+
+void mptcp_sock_set_nodelay(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);
+       msk->nodelay = true;
+       mptcp_for_each_subflow(msk, subflow) {
+               ssk = mptcp_subflow_tcp_sock(subflow);
+               if (ssk) {
+                       lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
+                       __tcp_sock_set_nodelay(ssk, true);
+                       release_sock(ssk);
+               }
+       }
+       release_sock(sk);
+}
+EXPORT_SYMBOL(mptcp_sock_set_nodelay);
-- 
2.53.0


Reply via email to