From patchwork Mon Nov 16 15:06:44 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Schultz X-Patchwork-Id: 545056 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.osmocom.org (unknown [IPv6:2a01:4f8:191:444b::2:7]) by ozlabs.org (Postfix) with ESMTP id ABE02140D97 for ; Tue, 17 Nov 2015 02:07:11 +1100 (AEDT) Received: from lists.osmocom.org (lists.osmocom.org [144.76.43.76]) by lists.osmocom.org (Postfix) with ESMTP id 69A7C9BF5; Mon, 16 Nov 2015 15:07:10 +0000 (UTC) X-Original-To: openbsc@lists.osmocom.org Delivered-To: openbsc@lists.osmocom.org Received: from mail.tpip.net (mail.tpip.net [92.43.49.48]) by lists.osmocom.org (Postfix) with ESMTP id EA5369BE8 for ; Mon, 16 Nov 2015 15:07:09 +0000 (UTC) Received: from office.tpip.net (office.tpip.net [92.43.51.2]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.tpip.net (Postfix) with ESMTPS id 9F1B84F417; Mon, 16 Nov 2015 15:07:04 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by office.tpip.net (Postfix) with ESMTP id DE330A2C9A; Mon, 16 Nov 2015 16:07:05 +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 dhdt98evurIv; Mon, 16 Nov 2015 16:07:05 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by office.tpip.net (Postfix) with ESMTP id 6882DA2CA9; Mon, 16 Nov 2015 16:07:05 +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 w05zEQm0KrOZ; Mon, 16 Nov 2015 16:07:05 +0100 (CET) Received: from alice.tpip.org (unknown [192.168.13.53]) by office.tpip.net (Postfix) with ESMTPSA id 072C6A2CAA; Mon, 16 Nov 2015 16:07:04 +0100 (CET) From: Andreas Schultz To: openbsc@lists.osmocom.org Subject: [PATCH 03/16] gtp: convert the global gtp_instance_list to a per netns list Date: Mon, 16 Nov 2015 16:06:44 +0100 Message-Id: <1447686417-3979-4-git-send-email-aschultz@tpip.net> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1447686417-3979-1-git-send-email-aschultz@tpip.net> References: <1447686417-3979-1-git-send-email-aschultz@tpip.net> X-BeenThere: openbsc@lists.osmocom.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Development of the OpenBSC GSM base station controller List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Pablo Neira Ayuso Errors-To: openbsc-bounces@lists.osmocom.org Sender: "OpenBSC" This add basic network namespace support by changing to global gtp_instance_list into a pre namespace list. Before this change all pdp context would be visible from all network namespaces, now only the namespace that they belong too, can see them. Also selectively destroy all gtp devices when a namespace is destroyed. Signed-off-by: Andreas Schultz --- gtp.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/gtp.c b/gtp.c index 7e615f3..7c61e61 100644 --- a/gtp.c +++ b/gtp.c @@ -20,13 +20,15 @@ #include #include +#include #include #include #include #include #include #include - +#include +# #include "gtp.h" #include "gtp_nl.h" @@ -72,7 +74,11 @@ struct gtp_instance { struct hlist_head *addr_hash; }; -static LIST_HEAD(gtp_instance_list); /* XXX netns */ +static int gtp_net_id __read_mostly; + +struct gtp_net { + struct list_head gtp_instance_list; +}; static inline u32 gtp0_hashfn(u64 tid) { @@ -732,6 +738,7 @@ static int gtp_encap_enable(struct net_device *dev, struct gtp_instance *gti, static int gtp_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { + struct gtp_net *gn = net_generic(src_net, gtp_net_id); struct net_device *real_dev; struct gtp_instance *gti; int hashsize, err, fd0, fd1; @@ -771,7 +778,7 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, if (err < 0) goto err1; - list_add_rcu(>i->list, >p_instance_list); + list_add_rcu(>i->list, &gn->gtp_instance_list); netdev_dbg(dev, "registered new interface\n"); @@ -941,11 +948,12 @@ static void gtp_encap_disable(struct gtp_instance *gti) sockfd_put(gti->sock0); } -static struct net_device *gtp_find_dev(int ifindex) +static struct net_device *gtp_find_dev(struct net *net, int ifindex) { + struct gtp_net *gn = net_generic(net, gtp_net_id); struct gtp_instance *gti; - list_for_each_entry_rcu(gti, >p_instance_list, list) { + list_for_each_entry_rcu(gti, &gn->gtp_instance_list, list) { if (ifindex == gti->dev->ifindex) return gti->dev; } @@ -1051,6 +1059,7 @@ static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info) static int gtp_genl_tunnel_new(struct sk_buff *skb, struct genl_info *info) { + struct net *net = sock_net(skb->sk); struct net_device *dev; if (!info->attrs[GTPA_VERSION] || @@ -1061,7 +1070,7 @@ static int gtp_genl_tunnel_new(struct sk_buff *skb, struct genl_info *info) return -EINVAL; /* Check if there's an existing gtpX device to configure */ - dev = gtp_find_dev(nla_get_u32(info->attrs[GTPA_LINK])); + dev = gtp_find_dev(net, nla_get_u32(info->attrs[GTPA_LINK])); if (dev == NULL) return -ENODEV; @@ -1070,6 +1079,7 @@ static int gtp_genl_tunnel_new(struct sk_buff *skb, struct genl_info *info) static int gtp_genl_tunnel_delete(struct sk_buff *skb, struct genl_info *info) { + struct net *net = sock_net(skb->sk); struct gtp_instance *gti; struct net_device *dev; struct pdp_ctx *pctx; @@ -1098,7 +1108,7 @@ static int gtp_genl_tunnel_delete(struct sk_buff *skb, struct genl_info *info) return -EINVAL; /* Check if there's an existing gtpX device to configure */ - dev = gtp_find_dev(nla_get_u32(info->attrs[GTPA_LINK])); + dev = gtp_find_dev(net, nla_get_u32(info->attrs[GTPA_LINK])); if (dev == NULL) return -ENODEV; @@ -1165,6 +1175,7 @@ nla_put_failure: static int gtp_genl_tunnel_get(struct sk_buff *skb, struct genl_info *info) { + struct net *net = sock_net(skb->sk); struct net_device *dev; struct gtp_instance *gti; struct pdp_ctx *pctx = NULL; @@ -1186,7 +1197,7 @@ static int gtp_genl_tunnel_get(struct sk_buff *skb, struct genl_info *info) } /* Check if there's an existing gtpX device to configure */ - dev = gtp_find_dev(nla_get_u32(info->attrs[GTPA_LINK])); + dev = gtp_find_dev(net, nla_get_u32(info->attrs[GTPA_LINK])); if (dev == NULL) return -ENODEV; @@ -1249,11 +1260,13 @@ gtp_genl_tunnel_dump(struct sk_buff *skb, struct netlink_callback *cb) unsigned long tid = cb->args[1]; struct gtp_instance *last_gti = (struct gtp_instance *)cb->args[2], *gti; struct pdp_ctx *pctx; + struct net *net = sock_net(skb->sk); + struct gtp_net *gn = net_generic(net, gtp_net_id); if (cb->args[4]) return 0; - list_for_each_entry_rcu(gti, >p_instance_list, list) { + list_for_each_entry_rcu(gti, &gn->gtp_instance_list, list) { if (last_gti && last_gti != gti) continue; else @@ -1315,6 +1328,37 @@ static const struct genl_ops gtp_genl_ops[] = { }, }; +static int __net_init gtp_net_init(struct net *net) +{ + struct gtp_net *gn = net_generic(net, gtp_net_id); + + INIT_LIST_HEAD(&gn->gtp_instance_list); + + return 0; +} + +static void __net_exit gtp_net_exit(struct net *net) +{ + struct gtp_net *gn = net_generic(net, gtp_net_id); + struct gtp_instance *gti; + LIST_HEAD(list); + + rtnl_lock(); + list_for_each_entry_rcu(gti, &gn->gtp_instance_list, list) { + gtp_dellink(gti->dev, &list); + } + + unregister_netdevice_many(&list); + rtnl_unlock(); +} + +static struct pernet_operations gtp_net_ops = { + .init = gtp_net_init, + .exit = gtp_net_exit, + .id = >p_net_id, + .size = sizeof(struct gtp_net), +}; + static int __init gtp_init(void) { int err; @@ -1329,10 +1373,17 @@ static int __init gtp_init(void) if (err < 0) goto unreg_rtnl_link; + err = register_pernet_subsys(>p_net_ops); + if (err < 0) + goto unreg_genl_family; + pr_info("GTP module loaded (pdp ctx size %Zd bytes)\n", sizeof(struct pdp_ctx)); return 0; +unreg_genl_family: + genl_unregister_family(>p_genl_family); + unreg_rtnl_link: rtnl_link_unregister(>p_link_ops); @@ -1344,6 +1395,7 @@ late_initcall(gtp_init); static void __exit gtp_fini(void) { + unregister_pernet_subsys(>p_net_ops); genl_unregister_family(>p_genl_family); rtnl_link_unregister(>p_link_ops);