[PATCH 03/16] gtp: convert the global gtp_instance_list to a per netns list

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.

Andreas Schultz aschultz at tpip.net
Mon Nov 16 15:06:44 UTC 2015


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 <aschultz at tpip.net>
---
 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 <linux/net.h>
 #include <linux/file.h>
 
+#include <net/net_namespace.h>
 #include <net/protocol.h>
 #include <net/ip.h>
 #include <net/udp.h>
 #include <net/icmp.h>
 #include <net/xfrm.h>
 #include <net/genetlink.h>
-
+#include <net/netns/generic.h>
+#
 #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(&gti->list, &gtp_instance_list);
+	list_add_rcu(&gti->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, &gtp_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, &gtp_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   = &gtp_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(&gtp_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(&gtp_genl_family);
+
 unreg_rtnl_link:
 	rtnl_link_unregister(&gtp_link_ops);
 
@@ -1344,6 +1395,7 @@ late_initcall(gtp_init);
 
 static void __exit gtp_fini(void)
 {
+	unregister_pernet_subsys(&gtp_net_ops);
 	genl_unregister_family(&gtp_genl_family);
 	rtnl_link_unregister(&gtp_link_ops);
 
-- 
2.5.0




More information about the OpenBSC mailing list