// SPDX-License-Identifier: GPL-2.0 /* Multipath TCP * * Copyright (c) 2017 - 2019, Intel Corporation. */ #include #include #include #include #include #include #include #include #include #include "protocol.h" int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock) { struct mptcp_subflow_context *subflow; struct net *net = sock_net(sk); struct socket *sf; int err; err = sock_create_kern(net, PF_INET, SOCK_STREAM, IPPROTO_TCP, &sf); if (err) return err; lock_sock(sf->sk); /* kernel sockets do not by default acquire net ref, but TCP timer * needs it. */ sf->sk->sk_net_refcnt = 1; get_net(net); this_cpu_add(*net->core.sock_inuse, 1); err = tcp_set_ulp(sf->sk, "mptcp"); release_sock(sf->sk); if (err) return err; subflow = mptcp_subflow_ctx(sf->sk); pr_debug("subflow=%p", subflow); *new_sock = sf; subflow->conn = sk; return 0; } static struct mptcp_subflow_context *subflow_create_ctx(struct sock *sk, gfp_t priority) { struct inet_connection_sock *icsk = inet_csk(sk); struct mptcp_subflow_context *ctx; ctx = kzalloc(sizeof(*ctx), priority); if (!ctx) return NULL; rcu_assign_pointer(icsk->icsk_ulp_data, ctx); pr_debug("subflow=%p", ctx); ctx->tcp_sock = sk; return ctx; } static int subflow_ulp_init(struct sock *sk) { struct mptcp_subflow_context *ctx; struct tcp_sock *tp = tcp_sk(sk); int err = 0; /* disallow attaching ULP to a socket unless it has been * created with sock_create_kern() */ if (!sk->sk_kern_sock) { err = -EOPNOTSUPP; goto out; } ctx = subflow_create_ctx(sk, GFP_KERNEL); if (!ctx) { err = -ENOMEM; goto out; } pr_debug("subflow=%p, family=%d", ctx, sk->sk_family); tp->is_mptcp = 1; out: return err; } static void subflow_ulp_release(struct sock *sk) { struct mptcp_subflow_context *ctx = mptcp_subflow_ctx(sk); if (!ctx) return; kfree_rcu(ctx, rcu); } static struct tcp_ulp_ops subflow_ulp_ops __read_mostly = { .name = "mptcp", .owner = THIS_MODULE, .init = subflow_ulp_init, .release = subflow_ulp_release, }; void mptcp_subflow_init(void) { if (tcp_register_ulp(&subflow_ulp_ops) != 0) panic("MPTCP: failed to register subflows to ULP\n"); }