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
