]> git.baikalelectronics.ru Git - kernel.git/commitdiff
mptcp: Add MPTCP socket stubs
authorMat Martineau <mathew.j.martineau@linux.intel.com>
Wed, 22 Jan 2020 00:56:15 +0000 (16:56 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 24 Jan 2020 12:44:07 +0000 (13:44 +0100)
Implements the infrastructure for MPTCP sockets.

MPTCP sockets open one in-kernel TCP socket per subflow. These subflow
sockets are only managed by the MPTCP socket that owns them and are not
visible from userspace. This commit allows a userspace program to open
an MPTCP socket with:

  sock = socket(AF_INET, SOCK_STREAM, IPPROTO_MPTCP);

The resulting socket is simply a wrapper around a single regular TCP
socket, without any of the MPTCP protocol implemented over the wire.

Co-developed-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Florian Westphal <fw@strlen.de>
Co-developed-by: Peter Krystad <peter.krystad@linux.intel.com>
Signed-off-by: Peter Krystad <peter.krystad@linux.intel.com>
Co-developed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Co-developed-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Christoph Paasch <cpaasch@apple.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
MAINTAINERS
include/net/mptcp.h
net/Kconfig
net/Makefile
net/ipv4/tcp.c
net/ipv6/tcp_ipv6.c
net/mptcp/Kconfig [new file with mode: 0644]
net/mptcp/Makefile [new file with mode: 0644]
net/mptcp/protocol.c [new file with mode: 0644]
net/mptcp/protocol.h [new file with mode: 0644]

index 702382b89c37f9a24a067199a7d21f6188bb3c2a..4be9c1b50183dc244583d4a8fe1ba83335572b0b 100644 (file)
@@ -11583,6 +11583,7 @@ W:      https://github.com/multipath-tcp/mptcp_net-next/wiki
 B:     https://github.com/multipath-tcp/mptcp_net-next/issues
 S:     Maintained
 F:     include/net/mptcp.h
+F:     net/mptcp/
 
 NETWORKING [TCP]
 M:     Eric Dumazet <edumazet@google.com>
index 0573ae75c3db3d4104e0212e140d95e6c715945c..98ba22379117e5f6404f805a87de983d96e3de09 100644 (file)
@@ -28,6 +28,8 @@ struct mptcp_ext {
 
 #ifdef CONFIG_MPTCP
 
+void mptcp_init(void);
+
 /* move the skb extension owership, with the assumption that 'to' is
  * newly allocated
  */
@@ -70,6 +72,10 @@ static inline bool mptcp_skb_can_collapse(const struct sk_buff *to,
 
 #else
 
+static inline void mptcp_init(void)
+{
+}
+
 static inline void mptcp_skb_ext_move(struct sk_buff *to,
                                      const struct sk_buff *from)
 {
@@ -82,4 +88,14 @@ static inline bool mptcp_skb_can_collapse(const struct sk_buff *to,
 }
 
 #endif /* CONFIG_MPTCP */
+
+#if IS_ENABLED(CONFIG_MPTCP_IPV6)
+int mptcpv6_init(void);
+#elif IS_ENABLED(CONFIG_IPV6)
+static inline int mptcpv6_init(void)
+{
+       return 0;
+}
+#endif
+
 #endif /* __NET_MPTCP_H */
index 54916b7adb9b3e4d3f7ae7c7a22dcbfd43126715..b0937a700f018323e5b1e8f0421ee42c825a02d7 100644 (file)
@@ -91,6 +91,7 @@ if INET
 source "net/ipv4/Kconfig"
 source "net/ipv6/Kconfig"
 source "net/netlabel/Kconfig"
+source "net/mptcp/Kconfig"
 
 endif # if INET
 
index 848303d98d3dddc07f56261a8233ba8abc0f5f7c..07ea48160874719ea90de3448df56941ee8645b4 100644 (file)
@@ -87,3 +87,4 @@ endif
 obj-$(CONFIG_QRTR)             += qrtr/
 obj-$(CONFIG_NET_NCSI)         += ncsi/
 obj-$(CONFIG_XDP_SOCKETS)      += xdp/
+obj-$(CONFIG_MPTCP)            += mptcp/
index 6711a97de3cedd74798eaac3f935e9cfafe083b8..7dfb78caedaf638064fa85063a152746200c4cfa 100644 (file)
 #include <net/icmp.h>
 #include <net/inet_common.h>
 #include <net/tcp.h>
+#include <net/mptcp.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
 #include <net/sock.h>
@@ -4021,4 +4022,5 @@ void __init tcp_init(void)
        tcp_metrics_init();
        BUG_ON(tcp_register_congestion_control(&tcp_reno) != 0);
        tcp_tasklet_init();
+       mptcp_init();
 }
index 5b5260103b650da2d716505a670cd137bc6dcf8d..60068ffde1d926240d3d9410d33b4ae9d25738e1 100644 (file)
@@ -2163,9 +2163,16 @@ int __init tcpv6_init(void)
        ret = register_pernet_subsys(&tcpv6_net_ops);
        if (ret)
                goto out_tcpv6_protosw;
+
+       ret = mptcpv6_init();
+       if (ret)
+               goto out_tcpv6_pernet_subsys;
+
 out:
        return ret;
 
+out_tcpv6_pernet_subsys:
+       unregister_pernet_subsys(&tcpv6_net_ops);
 out_tcpv6_protosw:
        inet6_unregister_protosw(&tcpv6_protosw);
 out_tcpv6_protocol:
diff --git a/net/mptcp/Kconfig b/net/mptcp/Kconfig
new file mode 100644 (file)
index 0000000..c1a99f0
--- /dev/null
@@ -0,0 +1,16 @@
+
+config MPTCP
+       bool "MPTCP: Multipath TCP"
+       depends on INET
+       select SKB_EXTENSIONS
+       help
+         Multipath TCP (MPTCP) connections send and receive data over multiple
+         subflows in order to utilize multiple network paths. Each subflow
+         uses the TCP protocol, and TCP options carry header information for
+         MPTCP.
+
+config MPTCP_IPV6
+       bool "MPTCP: IPv6 support for Multipath TCP"
+       depends on MPTCP
+       select IPV6
+       default y
diff --git a/net/mptcp/Makefile b/net/mptcp/Makefile
new file mode 100644 (file)
index 0000000..659129d
--- /dev/null
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_MPTCP) += mptcp.o
+
+mptcp-y := protocol.o
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
new file mode 100644 (file)
index 0000000..5e24e7c
--- /dev/null
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Multipath TCP
+ *
+ * Copyright (c) 2017 - 2019, Intel Corporation.
+ */
+
+#define pr_fmt(fmt) "MPTCP: " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <net/sock.h>
+#include <net/inet_common.h>
+#include <net/inet_hashtables.h>
+#include <net/protocol.h>
+#include <net/tcp.h>
+#include <net/mptcp.h>
+#include "protocol.h"
+
+static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+{
+       struct mptcp_sock *msk = mptcp_sk(sk);
+       struct socket *subflow = msk->subflow;
+
+       if (msg->msg_flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL))
+               return -EOPNOTSUPP;
+
+       return sock_sendmsg(subflow, msg);
+}
+
+static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
+                        int nonblock, int flags, int *addr_len)
+{
+       struct mptcp_sock *msk = mptcp_sk(sk);
+       struct socket *subflow = msk->subflow;
+
+       if (msg->msg_flags & ~(MSG_WAITALL | MSG_DONTWAIT))
+               return -EOPNOTSUPP;
+
+       return sock_recvmsg(subflow, msg, flags);
+}
+
+static int mptcp_init_sock(struct sock *sk)
+{
+       return 0;
+}
+
+static void mptcp_close(struct sock *sk, long timeout)
+{
+       struct mptcp_sock *msk = mptcp_sk(sk);
+
+       inet_sk_state_store(sk, TCP_CLOSE);
+
+       if (msk->subflow) {
+               pr_debug("subflow=%p", msk->subflow->sk);
+               sock_release(msk->subflow);
+       }
+
+       sock_orphan(sk);
+       sock_put(sk);
+}
+
+static int mptcp_connect(struct sock *sk, struct sockaddr *saddr, int len)
+{
+       struct mptcp_sock *msk = mptcp_sk(sk);
+       int err;
+
+       saddr->sa_family = AF_INET;
+
+       pr_debug("msk=%p, subflow=%p", msk, msk->subflow->sk);
+
+       err = kernel_connect(msk->subflow, saddr, len, 0);
+
+       sk->sk_state = TCP_ESTABLISHED;
+
+       return err;
+}
+
+static struct proto mptcp_prot = {
+       .name           = "MPTCP",
+       .owner          = THIS_MODULE,
+       .init           = mptcp_init_sock,
+       .close          = mptcp_close,
+       .accept         = inet_csk_accept,
+       .connect        = mptcp_connect,
+       .shutdown       = tcp_shutdown,
+       .sendmsg        = mptcp_sendmsg,
+       .recvmsg        = mptcp_recvmsg,
+       .hash           = inet_hash,
+       .unhash         = inet_unhash,
+       .get_port       = inet_csk_get_port,
+       .obj_size       = sizeof(struct mptcp_sock),
+       .no_autobind    = true,
+};
+
+static struct inet_protosw mptcp_protosw = {
+       .type           = SOCK_STREAM,
+       .protocol       = IPPROTO_MPTCP,
+       .prot           = &mptcp_prot,
+       .ops            = &inet_stream_ops,
+};
+
+void __init mptcp_init(void)
+{
+       if (proto_register(&mptcp_prot, 1) != 0)
+               panic("Failed to register MPTCP proto.\n");
+
+       inet_register_protosw(&mptcp_protosw);
+}
+
+#if IS_ENABLED(CONFIG_MPTCP_IPV6)
+static struct proto mptcp_v6_prot;
+
+static struct inet_protosw mptcp_v6_protosw = {
+       .type           = SOCK_STREAM,
+       .protocol       = IPPROTO_MPTCP,
+       .prot           = &mptcp_v6_prot,
+       .ops            = &inet6_stream_ops,
+       .flags          = INET_PROTOSW_ICSK,
+};
+
+int mptcpv6_init(void)
+{
+       int err;
+
+       mptcp_v6_prot = mptcp_prot;
+       strcpy(mptcp_v6_prot.name, "MPTCPv6");
+       mptcp_v6_prot.slab = NULL;
+       mptcp_v6_prot.obj_size = sizeof(struct mptcp_sock) +
+                                sizeof(struct ipv6_pinfo);
+
+       err = proto_register(&mptcp_v6_prot, 1);
+       if (err)
+               return err;
+
+       err = inet6_register_protosw(&mptcp_v6_protosw);
+       if (err)
+               proto_unregister(&mptcp_v6_prot);
+
+       return err;
+}
+#endif
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
new file mode 100644 (file)
index 0000000..ee04a01
--- /dev/null
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Multipath TCP
+ *
+ * Copyright (c) 2017 - 2019, Intel Corporation.
+ */
+
+#ifndef __MPTCP_PROTOCOL_H
+#define __MPTCP_PROTOCOL_H
+
+/* MPTCP connection sock */
+struct mptcp_sock {
+       /* inet_connection_sock must be the first member */
+       struct inet_connection_sock sk;
+       struct socket   *subflow; /* outgoing connect/listener/!mp_capable */
+};
+
+static inline struct mptcp_sock *mptcp_sk(const struct sock *sk)
+{
+       return (struct mptcp_sock *)sk;
+}
+
+#endif /* __MPTCP_PROTOCOL_H */