From patchwork Tue Jan 24 15:28:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Schultz X-Patchwork-Id: 719203 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.osmocom.org (lists.osmocom.org [144.76.43.76]) by ozlabs.org (Postfix) with ESMTP id 3v7Btg1FZJz9t0G for ; Wed, 25 Jan 2017 02:29:31 +1100 (AEDT) Received: from lists.osmocom.org (lists.osmocom.org [144.76.43.76]) by lists.osmocom.org (Postfix) with ESMTP id EB9B428066; Tue, 24 Jan 2017 15:29:29 +0000 (UTC) Authentication-Results: lists.osmocom.org; dmarc=none header.from=tpip.net X-Original-To: openbsc@lists.osmocom.org Delivered-To: openbsc@lists.osmocom.org Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=92.43.49.48; helo=mail.tpip.net; envelope-from=aschultz@tpip.net; receiver=openbsc@lists.osmocom.org Authentication-Results: lists.osmocom.org; dmarc=none header.from=tpip.net Received: from mail.tpip.net (mail.tpip.net [92.43.49.48]) by lists.osmocom.org (Postfix) with ESMTP id DCDA829F25 for ; Tue, 24 Jan 2017 15:28:55 +0000 (UTC) Received: from office.tpip.net (unknown [153.92.65.89]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.tpip.net (Postfix) with ESMTPS id BD5594F40E; Tue, 24 Jan 2017 15:28:55 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by office.tpip.net (Postfix) with ESMTP id 95D76A2CC1; Tue, 24 Jan 2017 16:28:55 +0100 (CET) Received: from office.tpip.net ([127.0.0.1]) by localhost (office.tpip.net [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id YOETex1qw3NN; Tue, 24 Jan 2017 16:28:55 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by office.tpip.net (Postfix) with ESMTP id 26247A2CC0; Tue, 24 Jan 2017 16:28:55 +0100 (CET) X-Virus-Scanned: amavisd-new at tpip.net Received: from office.tpip.net ([127.0.0.1]) by localhost (office.tpip.net [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id vrcOvILN6MTj; Tue, 24 Jan 2017 16:28:55 +0100 (CET) Received: from localhost.localdomain (pd95c9392.dip0.t-ipconnect.de [217.92.147.146]) by office.tpip.net (Postfix) with ESMTPSA id D06E3A2CC2; Tue, 24 Jan 2017 16:28:54 +0100 (CET) From: Andreas Schultz To: Pablo Neira Subject: [PATCH v2 10/18] gtp: add socket to pdp context Date: Tue, 24 Jan 2017 16:28:40 +0100 Message-Id: <20170124152848.6120-11-aschultz@tpip.net> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20170124152848.6120-1-aschultz@tpip.net> References: <20170124152848.6120-1-aschultz@tpip.net> X-BeenThere: openbsc@lists.osmocom.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Development of OpenBSC, OsmoBSC, OsmoNITB, OsmoCSCN" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: netdev@vger.kernel.org, openbsc@lists.osmocom.org, Lionel Gauthier Errors-To: openbsc-bounces@lists.osmocom.org Sender: "OpenBSC" Having the socket present in context simplifies the sending logic. It also fixes the invalid assumtion that we have to use the same sending socket for all client IP's on a specific gtp interface. Signed-off-by: Andreas Schultz --- drivers/net/gtp.c | 70 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index c7e32a6..fb93468 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -58,6 +58,8 @@ struct pdp_ctx { struct in_addr ms_addr_ip4; struct in_addr sgsn_addr_ip4; + struct sock *sk; + atomic_t tx_seq; struct rcu_head rcu_head; }; @@ -353,8 +355,9 @@ static void gtp_dev_uninit(struct net_device *dev) free_percpu(dev->tstats); } -static struct rtable *ip4_route_output_gtp(struct net *net, struct flowi4 *fl4, - const struct sock *sk, __be32 daddr) +static struct rtable *ip4_route_output_gtp(struct flowi4 *fl4, + const struct sock *sk, + __be32 daddr) { memset(fl4, 0, sizeof(*fl4)); fl4->flowi4_oif = sk->sk_bound_dev_if; @@ -363,7 +366,7 @@ static struct rtable *ip4_route_output_gtp(struct net *net, struct flowi4 *fl4, fl4->flowi4_tos = RT_CONN_FLAGS(sk); fl4->flowi4_proto = sk->sk_protocol; - return ip_route_output_key(net, fl4); + return ip_route_output_key(sock_net(sk), fl4); } static inline void gtp0_push_header(struct sk_buff *skb, struct pdp_ctx *pctx) @@ -452,7 +455,6 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, struct rtable *rt; struct flowi4 fl4; struct iphdr *iph; - struct sock *sk; __be16 df; int mtu; @@ -468,30 +470,7 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, } netdev_dbg(dev, "found PDP context %p\n", pctx); - switch (pctx->gtp_version) { - case GTP_V0: - if (gtp->sock0) - sk = gtp->sock0->sk; - else - sk = NULL; - break; - case GTP_V1: - if (gtp->sock1u) - sk = gtp->sock1u->sk; - else - sk = NULL; - break; - default: - return -ENOENT; - } - - if (!sk) { - netdev_dbg(dev, "no userspace socket is available, skip\n"); - return -ENOENT; - } - - rt = ip4_route_output_gtp(sock_net(sk), &fl4, gtp->sock0->sk, - pctx->sgsn_addr_ip4.s_addr); + rt = ip4_route_output_gtp(&fl4, pctx->sk, pctx->sgsn_addr_ip4.s_addr); if (IS_ERR(rt)) { netdev_dbg(dev, "no route to SSGN %pI4\n", &pctx->sgsn_addr_ip4.s_addr); @@ -536,7 +515,7 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, goto err_rt; } - gtp_set_pktinfo_ipv4(pktinfo, sk, iph, pctx, rt, &fl4, dev); + gtp_set_pktinfo_ipv4(pktinfo, pctx->sk, iph, pctx, rt, &fl4, dev); gtp_push_header(skb, pktinfo); return 0; @@ -906,7 +885,8 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info) } } -static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info) +static int ipv4_pdp_add(struct net_device *dev, struct sock *sk, + struct genl_info *info) { struct gtp_dev *gtp = netdev_priv(dev); u32 hash_ms, hash_tid = 0; @@ -947,6 +927,8 @@ static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info) if (pctx == NULL) return -ENOMEM; + sock_hold(sk); + pctx->sk = sk; ipv4_pdp_fill(pctx, info); atomic_set(&pctx->tx_seq, 0); @@ -987,6 +969,7 @@ static void pdp_context_free(struct rcu_head *head) { struct pdp_ctx *pctx = container_of(head, struct pdp_ctx, rcu_head); + sock_put(pctx->sk); kfree(pctx); } @@ -997,10 +980,27 @@ static void pdp_context_delete(struct pdp_ctx *pctx) call_rcu(&pctx->rcu_head, pdp_context_free); } +static struct socket *gtp_genl_new_pdp_select_socket(int version, + struct net_device *dev) +{ + struct gtp_dev *gtp = netdev_priv(dev); + + switch (version) { + case GTP_V0: + return gtp->sock0; + case GTP_V1: + return gtp->sock1u; + default: + return NULL; + } +} + static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) { + unsigned int version; struct net_device *dev; struct net *net; + struct socket *sock; if (!info->attrs[GTPA_VERSION] || !info->attrs[GTPA_LINK] || @@ -1008,7 +1008,9 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) !info->attrs[GTPA_MS_ADDRESS]) return -EINVAL; - switch (nla_get_u32(info->attrs[GTPA_VERSION])) { + version = nla_get_u32(info->attrs[GTPA_VERSION]); + + switch (version) { case GTP_V0: if (!info->attrs[GTPA_TID] || !info->attrs[GTPA_FLOW]) @@ -1036,7 +1038,11 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) } put_net(net); - return ipv4_pdp_add(dev, info); + sock = gtp_genl_new_pdp_select_socket(version, dev); + if (!sock) + return -ENODEV; + + return ipv4_pdp_add(dev, sock->sk, info); } static struct pdp_ctx *gtp_genl_find_pdp_by_link(struct sk_buff *skb,