All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v5 0/7] gtp: misc improvements
@ 2017-03-09 16:42 Andreas Schultz
  2017-03-09 16:42 ` [PATCH net-next v5 1/7] gtp: switch from struct socket to struct sock for the GTP sockets Andreas Schultz
                   ` (8 more replies)
  0 siblings, 9 replies; 13+ messages in thread
From: Andreas Schultz @ 2017-03-09 16:42 UTC (permalink / raw)
  To: Harald Welte, Pablo Neira Ayuso; +Cc: osmocom-net-gprs, netdev

Hi Pablo,

This is a resent of last series that missed the merge window. There
are no changes compared to v4.

v4: Compared to v3 it contains mostly smallish naming and spelling fixes.
It also drops the documentation patch, Harald did a better job with the
documentation and the some things I described do not yet match the implementation.
I'll readd the relevant parts with a follow up series.

This series lays the groundwork for removing the socket references from
the GTP netdevice by removing duplicate code and simplifying the logic on
some code paths.

It slighly changes the GTP genl API by making the socket parameters optional
(though one of them is still required).

The removal of the socket references will break the 1:1 releation between
GTP netdevice and GTP socket that prevents us to support multiple VRFs with
overlapping IP addresse spaces attached to the same GTP-U entity (needed for
multi APN support, coming a follow up series).

Pablo found a socket hold problem in v2. In order to solve that I had to
switch the socket references from the struct socket to the internal
struct sock. This should have no functionl impact, but we can now hang
on to the reference without blocking user space from closing the GTP socket.

v4->v5:
 * resent for new merge window
v3->v4:
 * drop the documentation patch
 * spelling fixes
 * pass nlattr instead of genl_info into gtp_find_dev,
   makes the code slightly more compact and readable
v2->v3:
 * add documentation to explain the goal of all these changes
 * incorporate review comments
 * switch from struct socket to struct sock

Regards
Andreas

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH net-next v5 1/7] gtp: switch from struct socket to struct sock for the GTP sockets
  2017-03-09 16:42 [PATCH net-next v5 0/7] gtp: misc improvements Andreas Schultz
@ 2017-03-09 16:42 ` Andreas Schultz
  2017-03-09 16:42 ` [PATCH net-next v5 2/7] gtp: make GTP sockets in gtp_newlink optional Andreas Schultz
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Andreas Schultz @ 2017-03-09 16:42 UTC (permalink / raw)
  To: Harald Welte, Pablo Neira Ayuso; +Cc: osmocom-net-gprs, netdev

After enabling the UDP encapsulation, only the sk member is used.

Holding the socket would prevent user space from closing the socket,
but holding a reference to the sk member does not have the same
effect.

This change will make it simpler to later detach the sockets from
the netdevice.

Signed-off-by: Andreas Schultz <aschultz@tpip.net>
---
 drivers/net/gtp.c | 42 +++++++++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 19 deletions(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 8969874..e1b5af3 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -66,8 +66,8 @@ struct pdp_ctx {
 struct gtp_dev {
 	struct list_head	list;
 
-	struct socket		*sock0;
-	struct socket		*sock1u;
+	struct sock		*sk0;
+	struct sock		*sk1u;
 
 	struct net_device	*dev;
 
@@ -261,17 +261,19 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
 
 static void gtp_encap_disable(struct gtp_dev *gtp)
 {
-	if (gtp->sock0 && gtp->sock0->sk) {
-		udp_sk(gtp->sock0->sk)->encap_type = 0;
-		rcu_assign_sk_user_data(gtp->sock0->sk, NULL);
+	if (gtp->sk0) {
+		udp_sk(gtp->sk0)->encap_type = 0;
+		rcu_assign_sk_user_data(gtp->sk0, NULL);
+		sock_put(gtp->sk0);
 	}
-	if (gtp->sock1u && gtp->sock1u->sk) {
-		udp_sk(gtp->sock1u->sk)->encap_type = 0;
-		rcu_assign_sk_user_data(gtp->sock1u->sk, NULL);
+	if (gtp->sk1u) {
+		udp_sk(gtp->sk1u)->encap_type = 0;
+		rcu_assign_sk_user_data(gtp->sk1u, NULL);
+		sock_put(gtp->sk1u);
 	}
 
-	gtp->sock0 = NULL;
-	gtp->sock1u = NULL;
+	gtp->sk0 = NULL;
+	gtp->sk1u = NULL;
 }
 
 static void gtp_encap_destroy(struct sock *sk)
@@ -484,14 +486,14 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
 
 	switch (pctx->gtp_version) {
 	case GTP_V0:
-		if (gtp->sock0)
-			sk = gtp->sock0->sk;
+		if (gtp->sk0)
+			sk = gtp->sk0;
 		else
 			sk = NULL;
 		break;
 	case GTP_V1:
-		if (gtp->sock1u)
-			sk = gtp->sock1u->sk;
+		if (gtp->sk1u)
+			sk = gtp->sk1u;
 		else
 			sk = NULL;
 		break;
@@ -504,7 +506,7 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
 		return -ENOENT;
 	}
 
-	rt = ip4_route_output_gtp(sock_net(sk), &fl4, gtp->sock0->sk,
+	rt = ip4_route_output_gtp(sock_net(sk), &fl4, gtp->sk0,
 				  pctx->sgsn_addr_ip4.s_addr);
 	if (IS_ERR(rt)) {
 		netdev_dbg(dev, "no route to SSGN %pI4\n",
@@ -839,18 +841,20 @@ static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
 
 	netdev_dbg(dev, "enable gtp on %p, %p\n", sock0, sock1u);
 
-	gtp->sock0 = sock0;
-	gtp->sock1u = sock1u;
+	sock_hold(sock0->sk);
+	gtp->sk0 = sock0->sk;
+	sock_hold(sock1u->sk);
+	gtp->sk1u = sock1u->sk;
 
 	tuncfg.sk_user_data = gtp;
 	tuncfg.encap_rcv = gtp_encap_recv;
 	tuncfg.encap_destroy = gtp_encap_destroy;
 
 	tuncfg.encap_type = UDP_ENCAP_GTP0;
-	setup_udp_tunnel_sock(sock_net(gtp->sock0->sk), gtp->sock0, &tuncfg);
+	setup_udp_tunnel_sock(sock_net(gtp->sk0), sock0, &tuncfg);
 
 	tuncfg.encap_type = UDP_ENCAP_GTP1U;
-	setup_udp_tunnel_sock(sock_net(gtp->sock1u->sk), gtp->sock1u, &tuncfg);
+	setup_udp_tunnel_sock(sock_net(gtp->sk1u), sock1u, &tuncfg);
 
 	err = 0;
 err2:
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next v5 2/7] gtp: make GTP sockets in gtp_newlink optional
  2017-03-09 16:42 [PATCH net-next v5 0/7] gtp: misc improvements Andreas Schultz
  2017-03-09 16:42 ` [PATCH net-next v5 1/7] gtp: switch from struct socket to struct sock for the GTP sockets Andreas Schultz
@ 2017-03-09 16:42 ` Andreas Schultz
  2017-03-09 16:42 ` [PATCH net-next v5 3/7] gtp: merge gtp_get_net and gtp_genl_find_dev Andreas Schultz
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Andreas Schultz @ 2017-03-09 16:42 UTC (permalink / raw)
  To: Harald Welte, Pablo Neira Ayuso; +Cc: osmocom-net-gprs, netdev

Having both GTPv0-U and GTPv1-U is not always desirable.
Fallback from GTPv1-U to GTPv0-U was depreciated from 3GPP
Rel-8 onwards. Post Rel-8 implementation are discuraged
from listening on the v0 port (see 3GPP TS 29.281, Sect. 1).

A future change will completely decouple the sockets from the
network device. Till then, at least one of the sockets needs to
be specified (either v0 or v1), the other is optional.

Signed-off-by: Andreas Schultz <aschultz@tpip.net>
---
 drivers/net/gtp.c | 148 ++++++++++++++++++++++++++++--------------------------
 1 file changed, 78 insertions(+), 70 deletions(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index e1b5af3..9aa2b35 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -259,30 +259,30 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
 	return iptunnel_pull_header(skb, hdrlen, skb->protocol, xnet);
 }
 
-static void gtp_encap_disable(struct gtp_dev *gtp)
-{
-	if (gtp->sk0) {
-		udp_sk(gtp->sk0)->encap_type = 0;
-		rcu_assign_sk_user_data(gtp->sk0, NULL);
-		sock_put(gtp->sk0);
-	}
-	if (gtp->sk1u) {
-		udp_sk(gtp->sk1u)->encap_type = 0;
-		rcu_assign_sk_user_data(gtp->sk1u, NULL);
-		sock_put(gtp->sk1u);
-	}
-
-	gtp->sk0 = NULL;
-	gtp->sk1u = NULL;
-}
-
 static void gtp_encap_destroy(struct sock *sk)
 {
 	struct gtp_dev *gtp;
 
 	gtp = rcu_dereference_sk_user_data(sk);
-	if (gtp)
-		gtp_encap_disable(gtp);
+	if (gtp) {
+		udp_sk(sk)->encap_type = 0;
+		rcu_assign_sk_user_data(sk, NULL);
+		sock_put(sk);
+	}
+}
+
+static void gtp_encap_disable_sock(struct sock *sk)
+{
+	if (!sk)
+		return;
+
+	gtp_encap_destroy(sk);
+}
+
+static void gtp_encap_disable(struct gtp_dev *gtp)
+{
+	gtp_encap_disable_sock(gtp->sk0);
+	gtp_encap_disable_sock(gtp->sk1u);
 }
 
 /* UDP encapsulation receive handler. See net/ipv4/udp.c.
@@ -642,27 +642,23 @@ static void gtp_link_setup(struct net_device *dev)
 
 static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize);
 static void gtp_hashtable_free(struct gtp_dev *gtp);
-static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
-			    int fd_gtp0, int fd_gtp1);
+static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[]);
 
 static int gtp_newlink(struct net *src_net, struct net_device *dev,
 			struct nlattr *tb[], struct nlattr *data[])
 {
-	int hashsize, err, fd0, fd1;
 	struct gtp_dev *gtp;
 	struct gtp_net *gn;
+	int hashsize, err;
 
-	if (!data[IFLA_GTP_FD0] || !data[IFLA_GTP_FD1])
+	if (!data[IFLA_GTP_FD0] && !data[IFLA_GTP_FD1])
 		return -EINVAL;
 
 	gtp = netdev_priv(dev);
 
-	fd0 = nla_get_u32(data[IFLA_GTP_FD0]);
-	fd1 = nla_get_u32(data[IFLA_GTP_FD1]);
-
-	err = gtp_encap_enable(dev, gtp, fd0, fd1);
+	err = gtp_encap_enable(gtp, data);
 	if (err < 0)
-		goto out_err;
+		return err;
 
 	if (!data[IFLA_GTP_PDP_HASHSIZE])
 		hashsize = 1024;
@@ -690,7 +686,6 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
 	gtp_hashtable_free(gtp);
 out_encap:
 	gtp_encap_disable(gtp);
-out_err:
 	return err;
 }
 
@@ -805,63 +800,76 @@ static void gtp_hashtable_free(struct gtp_dev *gtp)
 	kfree(gtp->tid_hash);
 }
 
-static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
-			    int fd_gtp0, int fd_gtp1)
+static struct sock *gtp_encap_enable_socket(int fd, int type,
+					    struct gtp_dev *gtp)
 {
 	struct udp_tunnel_sock_cfg tuncfg = {NULL};
-	struct socket *sock0, *sock1u;
+	struct socket *sock;
+	struct sock *sk;
 	int err;
 
-	netdev_dbg(dev, "enable gtp on %d, %d\n", fd_gtp0, fd_gtp1);
+	pr_debug("enable gtp on %d, %d\n", fd, type);
 
-	sock0 = sockfd_lookup(fd_gtp0, &err);
-	if (sock0 == NULL) {
-		netdev_dbg(dev, "socket fd=%d not found (gtp0)\n", fd_gtp0);
-		return -ENOENT;
+	sock = sockfd_lookup(fd, &err);
+	if (!sock) {
+		pr_debug("gtp socket fd=%d not found\n", fd);
+		return NULL;
 	}
 
-	if (sock0->sk->sk_protocol != IPPROTO_UDP) {
-		netdev_dbg(dev, "socket fd=%d not UDP\n", fd_gtp0);
-		err = -EINVAL;
-		goto err1;
+	if (sock->sk->sk_protocol != IPPROTO_UDP) {
+		pr_debug("socket fd=%d not UDP\n", fd);
+		sk = ERR_PTR(-EINVAL);
+		goto out_sock;
 	}
 
-	sock1u = sockfd_lookup(fd_gtp1, &err);
-	if (sock1u == NULL) {
-		netdev_dbg(dev, "socket fd=%d not found (gtp1u)\n", fd_gtp1);
-		err = -ENOENT;
-		goto err1;
+	if (rcu_dereference_sk_user_data(sock->sk)) {
+		sk = ERR_PTR(-EBUSY);
+		goto out_sock;
 	}
 
-	if (sock1u->sk->sk_protocol != IPPROTO_UDP) {
-		netdev_dbg(dev, "socket fd=%d not UDP\n", fd_gtp1);
-		err = -EINVAL;
-		goto err2;
-	}
-
-	netdev_dbg(dev, "enable gtp on %p, %p\n", sock0, sock1u);
-
-	sock_hold(sock0->sk);
-	gtp->sk0 = sock0->sk;
-	sock_hold(sock1u->sk);
-	gtp->sk1u = sock1u->sk;
+	sk = sock->sk;
+	sock_hold(sk);
 
 	tuncfg.sk_user_data = gtp;
+	tuncfg.encap_type = type;
 	tuncfg.encap_rcv = gtp_encap_recv;
 	tuncfg.encap_destroy = gtp_encap_destroy;
 
-	tuncfg.encap_type = UDP_ENCAP_GTP0;
-	setup_udp_tunnel_sock(sock_net(gtp->sk0), sock0, &tuncfg);
-
-	tuncfg.encap_type = UDP_ENCAP_GTP1U;
-	setup_udp_tunnel_sock(sock_net(gtp->sk1u), sock1u, &tuncfg);
-
-	err = 0;
-err2:
-	sockfd_put(sock1u);
-err1:
-	sockfd_put(sock0);
-	return err;
+	setup_udp_tunnel_sock(sock_net(sock->sk), sock, &tuncfg);
+
+out_sock:
+	sockfd_put(sock);
+	return sk;
+}
+
+static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[])
+{
+	struct sock *sk1u = NULL;
+	struct sock *sk0 = NULL;
+
+	if (data[IFLA_GTP_FD0]) {
+		u32 fd0 = nla_get_u32(data[IFLA_GTP_FD0]);
+
+		sk0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, gtp);
+		if (IS_ERR(sk0))
+			return PTR_ERR(sk0);
+	}
+
+	if (data[IFLA_GTP_FD1]) {
+		u32 fd1 = nla_get_u32(data[IFLA_GTP_FD1]);
+
+		sk1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp);
+		if (IS_ERR(sk1u)) {
+			if (sk0)
+				gtp_encap_disable_sock(sk0);
+			return PTR_ERR(sk1u);
+		}
+	}
+
+	gtp->sk0 = sk0;
+	gtp->sk1u = sk1u;
+
+	return 0;
 }
 
 static struct net_device *gtp_find_dev(struct net *net, int ifindex)
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next v5 3/7] gtp: merge gtp_get_net and gtp_genl_find_dev
  2017-03-09 16:42 [PATCH net-next v5 0/7] gtp: misc improvements Andreas Schultz
  2017-03-09 16:42 ` [PATCH net-next v5 1/7] gtp: switch from struct socket to struct sock for the GTP sockets Andreas Schultz
  2017-03-09 16:42 ` [PATCH net-next v5 2/7] gtp: make GTP sockets in gtp_newlink optional Andreas Schultz
@ 2017-03-09 16:42 ` Andreas Schultz
  2017-03-09 16:42 ` [PATCH net-next v5 4/7] gtp: consolidate gtp socket rx path Andreas Schultz
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Andreas Schultz @ 2017-03-09 16:42 UTC (permalink / raw)
  To: Harald Welte, Pablo Neira Ayuso; +Cc: osmocom-net-gprs, netdev

Both function are always used together with the final goal to
get the gtp_dev. This simplifies the code by merging them together.

The netdevice lookup is changed to use the regular dev_get_by_index.
The gtp netdevice list is now only used to find the PDP contexts for
imcomming packets. It can be completely eliminated Once the TEID
hash is moved into the GTP socket.

Signed-off-by: Andreas Schultz <aschultz@tpip.net>
---
 drivers/net/gtp.c | 146 ++++++++++++++++++++++++++----------------------------
 1 file changed, 69 insertions(+), 77 deletions(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 9aa2b35..74018eb 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -744,21 +744,6 @@ static struct rtnl_link_ops gtp_link_ops __read_mostly = {
 	.fill_info	= gtp_fill_info,
 };
 
-static struct net *gtp_genl_get_net(struct net *src_net, struct nlattr *tb[])
-{
-	struct net *net;
-
-	/* Examine the link attributes and figure out which network namespace
-	 * we are talking about.
-	 */
-	if (tb[GTPA_NET_NS_FD])
-		net = get_net_ns_by_fd(nla_get_u32(tb[GTPA_NET_NS_FD]));
-	else
-		net = get_net(src_net);
-
-	return net;
-}
-
 static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize)
 {
 	int i;
@@ -872,16 +857,30 @@ static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[])
 	return 0;
 }
 
-static struct net_device *gtp_find_dev(struct net *net, int ifindex)
+static struct gtp_dev *gtp_find_dev(struct net *src_net, struct nlattr *nla[])
 {
-	struct gtp_net *gn = net_generic(net, gtp_net_id);
-	struct gtp_dev *gtp;
-
-	list_for_each_entry_rcu(gtp, &gn->gtp_dev_list, list) {
-		if (ifindex == gtp->dev->ifindex)
-			return gtp->dev;
-	}
-	return NULL;
+	struct gtp_dev *gtp = NULL;
+	struct net_device *dev;
+	struct net *net;
+
+	/* Examine the link attributes and figure out which network namespace
+	 * we are talking about.
+	 */
+	if (nla[GTPA_NET_NS_FD])
+		net = get_net_ns_by_fd(nla_get_u32(nla[GTPA_NET_NS_FD]));
+	else
+		net = get_net(src_net);
+
+	if (IS_ERR(net))
+		return NULL;
+
+	/* Check if there's an existing gtpX device to configure */
+	dev = dev_get_by_index_rcu(net, nla_get_u32(nla[GTPA_LINK]));
+	if (dev->netdev_ops == &gtp_netdev_ops)
+		gtp = netdev_priv(dev);
+
+	put_net(net);
+	return gtp;
 }
 
 static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info)
@@ -911,9 +910,9 @@ 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 gtp_dev *gtp, struct genl_info *info)
 {
-	struct gtp_dev *gtp = netdev_priv(dev);
+	struct net_device *dev = gtp->dev;
 	u32 hash_ms, hash_tid = 0;
 	struct pdp_ctx *pctx;
 	bool found = false;
@@ -990,8 +989,8 @@ static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info)
 
 static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
 {
-	struct net_device *dev;
-	struct net *net;
+	struct gtp_dev *gtp;
+	int err;
 
 	if (!info->attrs[GTPA_VERSION] ||
 	    !info->attrs[GTPA_LINK] ||
@@ -1015,77 +1014,79 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
 		return -EINVAL;
 	}
 
-	net = gtp_genl_get_net(sock_net(skb->sk), info->attrs);
-	if (IS_ERR(net))
-		return PTR_ERR(net);
+	rcu_read_lock();
 
-	/* Check if there's an existing gtpX device to configure */
-	dev = gtp_find_dev(net, nla_get_u32(info->attrs[GTPA_LINK]));
-	if (dev == NULL) {
-		put_net(net);
-		return -ENODEV;
+	gtp = gtp_find_dev(sock_net(skb->sk), info->attrs);
+	if (!gtp) {
+		err = -ENODEV;
+		goto out_unlock;
 	}
-	put_net(net);
 
-	return ipv4_pdp_add(dev, info);
+	err = ipv4_pdp_add(gtp, info);
+
+out_unlock:
+	rcu_read_unlock();
+	return err;
 }
 
 static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info)
 {
-	struct net_device *dev;
 	struct pdp_ctx *pctx;
 	struct gtp_dev *gtp;
-	struct net *net;
+	int err = 0;
 
 	if (!info->attrs[GTPA_VERSION] ||
 	    !info->attrs[GTPA_LINK])
 		return -EINVAL;
 
-	net = gtp_genl_get_net(sock_net(skb->sk), info->attrs);
-	if (IS_ERR(net))
-		return PTR_ERR(net);
+	rcu_read_lock();
 
-	/* Check if there's an existing gtpX device to configure */
-	dev = gtp_find_dev(net, nla_get_u32(info->attrs[GTPA_LINK]));
-	if (dev == NULL) {
-		put_net(net);
-		return -ENODEV;
+	gtp = gtp_find_dev(sock_net(skb->sk), info->attrs);
+	if (!gtp) {
+		err = -ENODEV;
+		goto out_unlock;
 	}
-	put_net(net);
-
-	gtp = netdev_priv(dev);
 
 	switch (nla_get_u32(info->attrs[GTPA_VERSION])) {
 	case GTP_V0:
-		if (!info->attrs[GTPA_TID])
-			return -EINVAL;
+		if (!info->attrs[GTPA_TID]) {
+			err = -EINVAL;
+			goto out_unlock;
+		}
 		pctx = gtp0_pdp_find(gtp, nla_get_u64(info->attrs[GTPA_TID]));
 		break;
 	case GTP_V1:
-		if (!info->attrs[GTPA_I_TEI])
-			return -EINVAL;
+		if (!info->attrs[GTPA_I_TEI]) {
+			err = -EINVAL;
+			goto out_unlock;
+		}
 		pctx = gtp1_pdp_find(gtp, nla_get_u64(info->attrs[GTPA_I_TEI]));
 		break;
 
 	default:
-		return -EINVAL;
+		err = -EINVAL;
+		goto out_unlock;
 	}
 
-	if (pctx == NULL)
-		return -ENOENT;
+	if (!pctx) {
+		err = -ENOENT;
+		goto out_unlock;
+	}
 
 	if (pctx->gtp_version == GTP_V0)
-		netdev_dbg(dev, "GTPv0-U: deleting tunnel id = %llx (pdp %p)\n",
+		netdev_dbg(gtp->dev, "GTPv0-U: deleting tunnel id = %llx (pdp %p)\n",
 			   pctx->u.v0.tid, pctx);
 	else if (pctx->gtp_version == GTP_V1)
-		netdev_dbg(dev, "GTPv1-U: deleting tunnel id = %x/%x (pdp %p)\n",
+		netdev_dbg(gtp->dev, "GTPv1-U: deleting tunnel id = %x/%x (pdp %p)\n",
 			   pctx->u.v1.i_tei, pctx->u.v1.o_tei, pctx);
 
 	hlist_del_rcu(&pctx->hlist_tid);
 	hlist_del_rcu(&pctx->hlist_addr);
 	kfree_rcu(pctx, rcu_head);
 
-	return 0;
+out_unlock:
+	rcu_read_unlock();
+	return err;
 }
 
 static struct genl_family gtp_genl_family;
@@ -1129,11 +1130,9 @@ static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq,
 static int gtp_genl_get_pdp(struct sk_buff *skb, struct genl_info *info)
 {
 	struct pdp_ctx *pctx = NULL;
-	struct net_device *dev;
 	struct sk_buff *skb2;
 	struct gtp_dev *gtp;
 	u32 gtp_version;
-	struct net *net;
 	int err;
 
 	if (!info->attrs[GTPA_VERSION] ||
@@ -1149,21 +1148,14 @@ static int gtp_genl_get_pdp(struct sk_buff *skb, struct genl_info *info)
 		return -EINVAL;
 	}
 
-	net = gtp_genl_get_net(sock_net(skb->sk), info->attrs);
-	if (IS_ERR(net))
-		return PTR_ERR(net);
-
-	/* Check if there's an existing gtpX device to configure */
-	dev = gtp_find_dev(net, nla_get_u32(info->attrs[GTPA_LINK]));
-	if (dev == NULL) {
-		put_net(net);
-		return -ENODEV;
-	}
-	put_net(net);
-
-	gtp = netdev_priv(dev);
-
 	rcu_read_lock();
+
+	gtp = gtp_find_dev(sock_net(skb->sk), info->attrs);
+	if (!gtp) {
+		err = -ENODEV;
+		goto err_unlock;
+	}
+
 	if (gtp_version == GTP_V0 &&
 	    info->attrs[GTPA_TID]) {
 		u64 tid = nla_get_u64(info->attrs[GTPA_TID]);
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next v5 4/7] gtp: consolidate gtp socket rx path
  2017-03-09 16:42 [PATCH net-next v5 0/7] gtp: misc improvements Andreas Schultz
                   ` (2 preceding siblings ...)
  2017-03-09 16:42 ` [PATCH net-next v5 3/7] gtp: merge gtp_get_net and gtp_genl_find_dev Andreas Schultz
@ 2017-03-09 16:42 ` Andreas Schultz
  2017-03-09 16:43 ` [PATCH net-next v5 5/7] gtp: unify genl_find_pdp and prepare for per socket lookup Andreas Schultz
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Andreas Schultz @ 2017-03-09 16:42 UTC (permalink / raw)
  To: Harald Welte, Pablo Neira Ayuso; +Cc: osmocom-net-gprs, netdev

Add network device to gtp context in preparation for splitting
the TEID from the network device.

Use this to rework the socker rx path. Move the common RX part
of v0 and v1 into a helper. Also move the final rx part into
that helper as well.

Signed-off-by: Andreas Schultz <aschultz@tpip.net>
---
 drivers/net/gtp.c | 80 ++++++++++++++++++++++++++++++-------------------------
 1 file changed, 44 insertions(+), 36 deletions(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 74018eb..0c6707a 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 net_device       *dev;
+
 	atomic_t		tx_seq;
 	struct rcu_head		rcu_head;
 };
@@ -175,6 +177,40 @@ static bool gtp_check_src_ms(struct sk_buff *skb, struct pdp_ctx *pctx,
 	return false;
 }
 
+static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, unsigned int hdrlen,
+		  bool xnet)
+{
+	struct pcpu_sw_netstats *stats;
+
+	if (!gtp_check_src_ms(skb, pctx, hdrlen)) {
+		netdev_dbg(pctx->dev, "No PDP ctx for this MS\n");
+		return 1;
+	}
+
+	/* Get rid of the GTP + UDP headers. */
+	if (iptunnel_pull_header(skb, hdrlen, skb->protocol, xnet))
+		return -1;
+
+	netdev_dbg(pctx->dev, "forwarding packet from GGSN to uplink\n");
+
+	/* Now that the UDP and the GTP header have been removed, set up the
+	 * new network header. This is required by the upper layer to
+	 * calculate the transport header.
+	 */
+	skb_reset_network_header(skb);
+
+	skb->dev = pctx->dev;
+
+	stats = this_cpu_ptr(pctx->dev->tstats);
+	u64_stats_update_begin(&stats->syncp);
+	stats->rx_packets++;
+	stats->rx_bytes += skb->len;
+	u64_stats_update_end(&stats->syncp);
+
+	netif_rx(skb);
+	return 0;
+}
+
 /* 1 means pass up to the stack, -1 means drop and 0 means decapsulated. */
 static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
 			       bool xnet)
@@ -201,13 +237,7 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
 		return 1;
 	}
 
-	if (!gtp_check_src_ms(skb, pctx, hdrlen)) {
-		netdev_dbg(gtp->dev, "No PDP ctx for this MS\n");
-		return 1;
-	}
-
-	/* Get rid of the GTP + UDP headers. */
-	return iptunnel_pull_header(skb, hdrlen, skb->protocol, xnet);
+	return gtp_rx(pctx, skb, hdrlen, xnet);
 }
 
 static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
@@ -250,13 +280,7 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
 		return 1;
 	}
 
-	if (!gtp_check_src_ms(skb, pctx, hdrlen)) {
-		netdev_dbg(gtp->dev, "No PDP ctx for this MS\n");
-		return 1;
-	}
-
-	/* Get rid of the GTP + UDP headers. */
-	return iptunnel_pull_header(skb, hdrlen, skb->protocol, xnet);
+	return gtp_rx(pctx, skb, hdrlen, xnet);
 }
 
 static void gtp_encap_destroy(struct sock *sk)
@@ -290,10 +314,9 @@ static void gtp_encap_disable(struct gtp_dev *gtp)
  */
 static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb)
 {
-	struct pcpu_sw_netstats *stats;
 	struct gtp_dev *gtp;
+	int ret = 0;
 	bool xnet;
-	int ret;
 
 	gtp = rcu_dereference_sk_user_data(sk);
 	if (!gtp)
@@ -319,33 +342,17 @@ static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb)
 	switch (ret) {
 	case 1:
 		netdev_dbg(gtp->dev, "pass up to the process\n");
-		return 1;
+		break;
 	case 0:
-		netdev_dbg(gtp->dev, "forwarding packet from GGSN to uplink\n");
 		break;
 	case -1:
 		netdev_dbg(gtp->dev, "GTP packet has been dropped\n");
 		kfree_skb(skb);
-		return 0;
+		ret = 0;
+		break;
 	}
 
-	/* Now that the UDP and the GTP header have been removed, set up the
-	 * new network header. This is required by the upper layer to
-	 * calculate the transport header.
-	 */
-	skb_reset_network_header(skb);
-
-	skb->dev = gtp->dev;
-
-	stats = this_cpu_ptr(gtp->dev->tstats);
-	u64_stats_update_begin(&stats->syncp);
-	stats->rx_packets++;
-	stats->rx_bytes += skb->len;
-	u64_stats_update_end(&stats->syncp);
-
-	netif_rx(skb);
-
-	return 0;
+	return ret;
 }
 
 static int gtp_dev_init(struct net_device *dev)
@@ -951,6 +958,7 @@ static int ipv4_pdp_add(struct gtp_dev *gtp, struct genl_info *info)
 	if (pctx == NULL)
 		return -ENOMEM;
 
+	pctx->dev = gtp->dev;
 	ipv4_pdp_fill(pctx, info);
 	atomic_set(&pctx->tx_seq, 0);
 
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next v5 5/7] gtp: unify genl_find_pdp and prepare for per socket lookup
  2017-03-09 16:42 [PATCH net-next v5 0/7] gtp: misc improvements Andreas Schultz
                   ` (3 preceding siblings ...)
  2017-03-09 16:42 ` [PATCH net-next v5 4/7] gtp: consolidate gtp socket rx path Andreas Schultz
@ 2017-03-09 16:43 ` Andreas Schultz
  2017-03-09 16:43 ` [PATCH net-next v5 6/7] gtp: consolidate pdp context destruction into helper Andreas Schultz
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Andreas Schultz @ 2017-03-09 16:43 UTC (permalink / raw)
  To: Harald Welte, Pablo Neira Ayuso; +Cc: osmocom-net-gprs, netdev

This unifies duplicate code into a helper. It also prepares the
groundwork to add a lookup version that uses the socket to find
attached pdp contexts.

Signed-off-by: Andreas Schultz <aschultz@tpip.net>
---
 drivers/net/gtp.c | 121 ++++++++++++++++++++++--------------------------------
 1 file changed, 50 insertions(+), 71 deletions(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 0c6707a..bf4b352 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -1037,55 +1037,67 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
 	return err;
 }
 
+static struct pdp_ctx *gtp_find_pdp_by_link(struct net *net,
+					    struct nlattr *nla[])
+{
+	struct gtp_dev *gtp;
+
+	gtp = gtp_find_dev(net, nla);
+	if (!gtp)
+		return ERR_PTR(-ENODEV);
+
+	if (nla[GTPA_MS_ADDRESS]) {
+		__be32 ip = nla_get_be32(nla[GTPA_MS_ADDRESS]);
+
+		return ipv4_pdp_find(gtp, ip);
+	} else if (nla[GTPA_VERSION]) {
+		u32 gtp_version = nla_get_u32(nla[GTPA_VERSION]);
+
+		if (gtp_version == GTP_V0 && nla[GTPA_TID])
+			return gtp0_pdp_find(gtp, nla_get_u64(nla[GTPA_TID]));
+		else if (gtp_version == GTP_V1 && nla[GTPA_I_TEI])
+			return gtp1_pdp_find(gtp, nla_get_u32(nla[GTPA_I_TEI]));
+	}
+
+	return ERR_PTR(-EINVAL);
+}
+
+static struct pdp_ctx *gtp_find_pdp(struct net *net, struct nlattr *nla[])
+{
+	struct pdp_ctx *pctx;
+
+	if (nla[GTPA_LINK])
+		pctx = gtp_find_pdp_by_link(net, nla);
+	else
+		pctx = ERR_PTR(-EINVAL);
+
+	if (!pctx)
+		pctx = ERR_PTR(-ENOENT);
+
+	return pctx;
+}
+
 static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info)
 {
 	struct pdp_ctx *pctx;
-	struct gtp_dev *gtp;
 	int err = 0;
 
-	if (!info->attrs[GTPA_VERSION] ||
-	    !info->attrs[GTPA_LINK])
+	if (!info->attrs[GTPA_VERSION])
 		return -EINVAL;
 
 	rcu_read_lock();
 
-	gtp = gtp_find_dev(sock_net(skb->sk), info->attrs);
-	if (!gtp) {
-		err = -ENODEV;
-		goto out_unlock;
-	}
-
-	switch (nla_get_u32(info->attrs[GTPA_VERSION])) {
-	case GTP_V0:
-		if (!info->attrs[GTPA_TID]) {
-			err = -EINVAL;
-			goto out_unlock;
-		}
-		pctx = gtp0_pdp_find(gtp, nla_get_u64(info->attrs[GTPA_TID]));
-		break;
-	case GTP_V1:
-		if (!info->attrs[GTPA_I_TEI]) {
-			err = -EINVAL;
-			goto out_unlock;
-		}
-		pctx = gtp1_pdp_find(gtp, nla_get_u64(info->attrs[GTPA_I_TEI]));
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out_unlock;
-	}
-
-	if (!pctx) {
-		err = -ENOENT;
+	pctx = gtp_find_pdp(sock_net(skb->sk), info->attrs);
+	if (IS_ERR(pctx)) {
+		err = PTR_ERR(pctx);
 		goto out_unlock;
 	}
 
 	if (pctx->gtp_version == GTP_V0)
-		netdev_dbg(gtp->dev, "GTPv0-U: deleting tunnel id = %llx (pdp %p)\n",
+		netdev_dbg(pctx->dev, "GTPv0-U: deleting tunnel id = %llx (pdp %p)\n",
 			   pctx->u.v0.tid, pctx);
 	else if (pctx->gtp_version == GTP_V1)
-		netdev_dbg(gtp->dev, "GTPv1-U: deleting tunnel id = %x/%x (pdp %p)\n",
+		netdev_dbg(pctx->dev, "GTPv1-U: deleting tunnel id = %x/%x (pdp %p)\n",
 			   pctx->u.v1.i_tei, pctx->u.v1.o_tei, pctx);
 
 	hlist_del_rcu(&pctx->hlist_tid);
@@ -1139,49 +1151,16 @@ static int gtp_genl_get_pdp(struct sk_buff *skb, struct genl_info *info)
 {
 	struct pdp_ctx *pctx = NULL;
 	struct sk_buff *skb2;
-	struct gtp_dev *gtp;
-	u32 gtp_version;
 	int err;
 
-	if (!info->attrs[GTPA_VERSION] ||
-	    !info->attrs[GTPA_LINK])
+	if (!info->attrs[GTPA_VERSION])
 		return -EINVAL;
 
-	gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]);
-	switch (gtp_version) {
-	case GTP_V0:
-	case GTP_V1:
-		break;
-	default:
-		return -EINVAL;
-	}
-
 	rcu_read_lock();
 
-	gtp = gtp_find_dev(sock_net(skb->sk), info->attrs);
-	if (!gtp) {
-		err = -ENODEV;
-		goto err_unlock;
-	}
-
-	if (gtp_version == GTP_V0 &&
-	    info->attrs[GTPA_TID]) {
-		u64 tid = nla_get_u64(info->attrs[GTPA_TID]);
-
-		pctx = gtp0_pdp_find(gtp, tid);
-	} else if (gtp_version == GTP_V1 &&
-		 info->attrs[GTPA_I_TEI]) {
-		u32 tid = nla_get_u32(info->attrs[GTPA_I_TEI]);
-
-		pctx = gtp1_pdp_find(gtp, tid);
-	} else if (info->attrs[GTPA_MS_ADDRESS]) {
-		__be32 ip = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]);
-
-		pctx = ipv4_pdp_find(gtp, ip);
-	}
-
-	if (pctx == NULL) {
-		err = -ENOENT;
+	pctx = gtp_find_pdp(sock_net(skb->sk), info->attrs);
+	if (IS_ERR(pctx)) {
+		err = PTR_ERR(pctx);
 		goto err_unlock;
 	}
 
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next v5 6/7] gtp: consolidate pdp context destruction into helper
  2017-03-09 16:42 [PATCH net-next v5 0/7] gtp: misc improvements Andreas Schultz
                   ` (4 preceding siblings ...)
  2017-03-09 16:43 ` [PATCH net-next v5 5/7] gtp: unify genl_find_pdp and prepare for per socket lookup Andreas Schultz
@ 2017-03-09 16:43 ` Andreas Schultz
  2017-03-09 16:43 ` [PATCH net-next v5 7/7] gtp: add socket to pdp context Andreas Schultz
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Andreas Schultz @ 2017-03-09 16:43 UTC (permalink / raw)
  To: Harald Welte, Pablo Neira Ayuso; +Cc: osmocom-net-gprs, netdev

Consolidate duplicate code into helper.

Signed-off-by: Andreas Schultz <aschultz@tpip.net>
---
 drivers/net/gtp.c | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index bf4b352..d58f46f 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -86,6 +86,8 @@ struct gtp_net {
 
 static u32 gtp_h_initval;
 
+static void pdp_context_delete(struct pdp_ctx *pctx);
+
 static inline u32 gtp0_hashfn(u64 tid)
 {
 	u32 *tid32 = (u32 *) &tid;
@@ -780,13 +782,10 @@ static void gtp_hashtable_free(struct gtp_dev *gtp)
 	struct pdp_ctx *pctx;
 	int i;
 
-	for (i = 0; i < gtp->hash_size; i++) {
-		hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i], hlist_tid) {
-			hlist_del_rcu(&pctx->hlist_tid);
-			hlist_del_rcu(&pctx->hlist_addr);
-			kfree_rcu(pctx, rcu_head);
-		}
-	}
+	for (i = 0; i < gtp->hash_size; i++)
+		hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i], hlist_tid)
+			pdp_context_delete(pctx);
+
 	synchronize_rcu();
 	kfree(gtp->addr_hash);
 	kfree(gtp->tid_hash);
@@ -995,6 +994,13 @@ static int ipv4_pdp_add(struct gtp_dev *gtp, struct genl_info *info)
 	return 0;
 }
 
+static void pdp_context_delete(struct pdp_ctx *pctx)
+{
+	hlist_del_rcu(&pctx->hlist_tid);
+	hlist_del_rcu(&pctx->hlist_addr);
+	kfree_rcu(pctx, rcu_head);
+}
+
 static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
 {
 	struct gtp_dev *gtp;
@@ -1100,9 +1106,7 @@ static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info)
 		netdev_dbg(pctx->dev, "GTPv1-U: deleting tunnel id = %x/%x (pdp %p)\n",
 			   pctx->u.v1.i_tei, pctx->u.v1.o_tei, pctx);
 
-	hlist_del_rcu(&pctx->hlist_tid);
-	hlist_del_rcu(&pctx->hlist_addr);
-	kfree_rcu(pctx, rcu_head);
+	pdp_context_delete(pctx);
 
 out_unlock:
 	rcu_read_unlock();
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next v5 7/7] gtp: add socket to pdp context
  2017-03-09 16:42 [PATCH net-next v5 0/7] gtp: misc improvements Andreas Schultz
                   ` (5 preceding siblings ...)
  2017-03-09 16:43 ` [PATCH net-next v5 6/7] gtp: consolidate pdp context destruction into helper Andreas Schultz
@ 2017-03-09 16:43 ` Andreas Schultz
  2017-03-11 21:51 ` [PATCH net-next v5 0/7] gtp: misc improvements Harald Welte
  2017-03-13 16:48 ` Pablo Neira Ayuso
  8 siblings, 0 replies; 13+ messages in thread
From: Andreas Schultz @ 2017-03-09 16:43 UTC (permalink / raw)
  To: Harald Welte, Pablo Neira Ayuso; +Cc: osmocom-net-gprs, netdev

Having the socket present in context simplifies the sending logic.
It also fixes the invalid assumption that we have to use the same
sending socket for all client IP's on a specific gtp interface.

Signed-off-by: Andreas Schultz <aschultz@tpip.net>
---
 drivers/net/gtp.c | 94 +++++++++++++++++++++++++++----------------------------
 1 file changed, 47 insertions(+), 47 deletions(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index d58f46f..3e1854f 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -58,6 +58,7 @@ struct pdp_ctx {
 	struct in_addr		ms_addr_ip4;
 	struct in_addr		sgsn_addr_ip4;
 
+	struct sock		*sk;
 	struct net_device       *dev;
 
 	atomic_t		tx_seq;
@@ -179,8 +180,7 @@ static bool gtp_check_src_ms(struct sk_buff *skb, struct pdp_ctx *pctx,
 	return false;
 }
 
-static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, unsigned int hdrlen,
-		  bool xnet)
+static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, unsigned int hdrlen)
 {
 	struct pcpu_sw_netstats *stats;
 
@@ -190,7 +190,8 @@ static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, unsigned int hdrlen
 	}
 
 	/* Get rid of the GTP + UDP headers. */
-	if (iptunnel_pull_header(skb, hdrlen, skb->protocol, xnet))
+	if (iptunnel_pull_header(skb, hdrlen, skb->protocol,
+				 !net_eq(sock_net(pctx->sk), dev_net(pctx->dev))))
 		return -1;
 
 	netdev_dbg(pctx->dev, "forwarding packet from GGSN to uplink\n");
@@ -214,8 +215,7 @@ static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, unsigned int hdrlen
 }
 
 /* 1 means pass up to the stack, -1 means drop and 0 means decapsulated. */
-static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
-			       bool xnet)
+static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
 {
 	unsigned int hdrlen = sizeof(struct udphdr) +
 			      sizeof(struct gtp0_header);
@@ -239,11 +239,10 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
 		return 1;
 	}
 
-	return gtp_rx(pctx, skb, hdrlen, xnet);
+	return gtp_rx(pctx, skb, hdrlen);
 }
 
-static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
-				bool xnet)
+static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
 {
 	unsigned int hdrlen = sizeof(struct udphdr) +
 			      sizeof(struct gtp1_header);
@@ -282,7 +281,7 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
 		return 1;
 	}
 
-	return gtp_rx(pctx, skb, hdrlen, xnet);
+	return gtp_rx(pctx, skb, hdrlen);
 }
 
 static void gtp_encap_destroy(struct sock *sk)
@@ -318,7 +317,6 @@ static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb)
 {
 	struct gtp_dev *gtp;
 	int ret = 0;
-	bool xnet;
 
 	gtp = rcu_dereference_sk_user_data(sk);
 	if (!gtp)
@@ -326,16 +324,14 @@ static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb)
 
 	netdev_dbg(gtp->dev, "encap_recv sk=%p\n", sk);
 
-	xnet = !net_eq(sock_net(sk), dev_net(gtp->dev));
-
 	switch (udp_sk(sk)->encap_type) {
 	case UDP_ENCAP_GTP0:
 		netdev_dbg(gtp->dev, "received GTP0 packet\n");
-		ret = gtp0_udp_encap_recv(gtp, skb, xnet);
+		ret = gtp0_udp_encap_recv(gtp, skb);
 		break;
 	case UDP_ENCAP_GTP1U:
 		netdev_dbg(gtp->dev, "received GTP1U packet\n");
-		ret = gtp1u_udp_encap_recv(gtp, skb, xnet);
+		ret = gtp1u_udp_encap_recv(gtp, skb);
 		break;
 	default:
 		ret = -1; /* Shouldn't happen. */
@@ -378,8 +374,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;
@@ -388,7 +385,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)
@@ -477,7 +474,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;
 
@@ -493,30 +489,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->sk0)
-			sk = gtp->sk0;
-		else
-			sk = NULL;
-		break;
-	case GTP_V1:
-		if (gtp->sk1u)
-			sk = gtp->sk1u;
-		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->sk0,
-				  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);
@@ -561,7 +534,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;
@@ -916,7 +889,8 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info)
 	}
 }
 
-static int ipv4_pdp_add(struct gtp_dev *gtp, struct genl_info *info)
+static int ipv4_pdp_add(struct gtp_dev *gtp, struct sock *sk,
+			struct genl_info *info)
 {
 	struct net_device *dev = gtp->dev;
 	u32 hash_ms, hash_tid = 0;
@@ -957,6 +931,8 @@ static int ipv4_pdp_add(struct gtp_dev *gtp, struct genl_info *info)
 	if (pctx == NULL)
 		return -ENOMEM;
 
+	sock_hold(sk);
+	pctx->sk = sk;
 	pctx->dev = gtp->dev;
 	ipv4_pdp_fill(pctx, info);
 	atomic_set(&pctx->tx_seq, 0);
@@ -994,16 +970,26 @@ static int ipv4_pdp_add(struct gtp_dev *gtp, struct genl_info *info)
 	return 0;
 }
 
+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);
+}
+
 static void pdp_context_delete(struct pdp_ctx *pctx)
 {
 	hlist_del_rcu(&pctx->hlist_tid);
 	hlist_del_rcu(&pctx->hlist_addr);
-	kfree_rcu(pctx, rcu_head);
+	call_rcu(&pctx->rcu_head, pdp_context_free);
 }
 
 static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
 {
+	unsigned int version;
 	struct gtp_dev *gtp;
+	struct sock *sk;
 	int err;
 
 	if (!info->attrs[GTPA_VERSION] ||
@@ -1012,7 +998,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 +1024,19 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
 		goto out_unlock;
 	}
 
-	err = ipv4_pdp_add(gtp, info);
+	if (version == GTP_V0)
+		sk = gtp->sk0;
+	else if (version == GTP_V1)
+		sk = gtp->sk1u;
+	else
+		sk = NULL;
+
+	if (!sk) {
+		err = -ENODEV;
+		goto out_unlock;
+	}
+
+	err = ipv4_pdp_add(gtp, sk, info);
 
 out_unlock:
 	rcu_read_unlock();
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next v5 0/7] gtp: misc improvements
  2017-03-09 16:42 [PATCH net-next v5 0/7] gtp: misc improvements Andreas Schultz
                   ` (6 preceding siblings ...)
  2017-03-09 16:43 ` [PATCH net-next v5 7/7] gtp: add socket to pdp context Andreas Schultz
@ 2017-03-11 21:51 ` Harald Welte
  2017-03-13 16:48 ` Pablo Neira Ayuso
  8 siblings, 0 replies; 13+ messages in thread
From: Harald Welte @ 2017-03-11 21:51 UTC (permalink / raw)
  To: Andreas Schultz; +Cc: Pablo Neira Ayuso, osmocom-net-gprs, netdev

Hi Andreas,

> Andreas Schultz (7):
>   gtp: switch from struct socket to struct sock for the GTP sockets
>   gtp: make GTP sockets in gtp_newlink optional
>   gtp: merge gtp_get_net and gtp_genl_find_dev
>   gtp: consolidate gtp socket rx path
>   gtp: unify genl_find_pdp and prepare for per socket lookup
>   gtp: consolidate pdp context destruction into helper
>   gtp: add socket to pdp context


I agree with the conceptual and architectural direction that you're
taking the code, and I also think your current patchset is good to go
ahead, so feel free to add my "Acked-By: Harald Welte <laforge@gnumonks.org>".

However, the usual disclaimer: I've been out of kernel networking land
for a long time, so my review skills are clearly not the best anymore.
I'm happy for any input others can give from that point of view.

There are some minor typos in the commit logs, but at the rate my typos
increase over the years, I am the last one to complain about wasting
time on fixing these ;)

Regards,
	Harald

-- 
- Harald Welte <laforge@gnumonks.org>           http://laforge.gnumonks.org/
============================================================================
"Privacy in residential applications is a desirable marketing option."
                                                  (ETSI EN 300 175-7 Ch. A6)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next v5 0/7] gtp: misc improvements
  2017-03-09 16:42 [PATCH net-next v5 0/7] gtp: misc improvements Andreas Schultz
                   ` (7 preceding siblings ...)
  2017-03-11 21:51 ` [PATCH net-next v5 0/7] gtp: misc improvements Harald Welte
@ 2017-03-13 16:48 ` Pablo Neira Ayuso
  2017-03-13 17:12   ` Harald Welte
                     ` (2 more replies)
  8 siblings, 3 replies; 13+ messages in thread
From: Pablo Neira Ayuso @ 2017-03-13 16:48 UTC (permalink / raw)
  To: Andreas Schultz; +Cc: Harald Welte, osmocom-net-gprs, netdev

On Thu, Mar 09, 2017 at 05:42:55PM +0100, Andreas Schultz wrote:
> Hi Pablo,
> 
> This is a resent of last series that missed the merge window. There
> are no changes compared to v4.
> 
> v4: Compared to v3 it contains mostly smallish naming and spelling fixes.
> It also drops the documentation patch, Harald did a better job with the
> documentation and the some things I described do not yet match the implementation.
> I'll readd the relevant parts with a follow up series.
> 
> This series lays the groundwork for removing the socket references from
> the GTP netdevice by removing duplicate code and simplifying the logic on
> some code paths.
> 
> It slighly changes the GTP genl API by making the socket parameters optional
> (though one of them is still required).
> 
> The removal of the socket references will break the 1:1 releation between
> GTP netdevice and GTP socket that prevents us to support multiple VRFs with
> overlapping IP addresse spaces attached to the same GTP-U entity (needed for
> multi APN support, coming a follow up series).
> 
> Pablo found a socket hold problem in v2. In order to solve that I had to
> switch the socket references from the struct socket to the internal
> struct sock. This should have no functionl impact, but we can now hang
> on to the reference without blocking user space from closing the GTP socket.

Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>

I personally don't like this podge hodge unsorted submissions, I don't
think they belong to the same series but you keep pushing with this
patchset in this same way, which is annoying.

In your follow up patchsets, please split them in smaller series that
are related.

I would like you take the time to develop the VRF idea that you want
to introduce, I just would like that we avoid bloating the GTP tunnel
with features that we can just achieve via composite of different
subsystems.

Thank you.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next v5 0/7] gtp: misc improvements
  2017-03-13 16:48 ` Pablo Neira Ayuso
@ 2017-03-13 17:12   ` Harald Welte
  2017-03-13 18:45   ` Andreas Schultz
  2017-03-13 20:06   ` David Miller
  2 siblings, 0 replies; 13+ messages in thread
From: Harald Welte @ 2017-03-13 17:12 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Andreas Schultz, osmocom-net-gprs, netdev

Hi Pablo,

On Mon, Mar 13, 2017 at 05:48:12PM +0100, Pablo Neira Ayuso wrote:
> I would like you take the time to develop the VRF idea that you want
> to introduce, I just would like that we avoid bloating the GTP tunnel
> with features that we can just achieve via composite of different
> subsystems.

I presume you're talking about the "several APN behind one GGSN IP"
which requires the de-coupling of the UDP socket from the gtp
net-device?

I actually think it is a very straight forward idea what Andreas is
proposing, and I see no bloat associated.  It's rather like splitting
existing combined functionality in two parts, which can still be used
together, but also be used separately.

Or are you referring to something else?

In any case, I'm looking forward to the related technical discussion on
this mailing list[s] :)

Regards,
	Harald
-- 
- Harald Welte <laforge@gnumonks.org>           http://laforge.gnumonks.org/
============================================================================
"Privacy in residential applications is a desirable marketing option."
                                                  (ETSI EN 300 175-7 Ch. A6)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next v5 0/7] gtp: misc improvements
  2017-03-13 16:48 ` Pablo Neira Ayuso
  2017-03-13 17:12   ` Harald Welte
@ 2017-03-13 18:45   ` Andreas Schultz
  2017-03-13 20:06   ` David Miller
  2 siblings, 0 replies; 13+ messages in thread
From: Andreas Schultz @ 2017-03-13 18:45 UTC (permalink / raw)
  To: pablo; +Cc: laforge, osmocom-net-gprs, netdev

Hi Pablo,

----- On Mar 13, 2017, at 5:48 PM, pablo pablo@netfilter.org wrote:

> On Thu, Mar 09, 2017 at 05:42:55PM +0100, Andreas Schultz wrote:
>> Hi Pablo,
>> 
>> This is a resent of last series that missed the merge window. There
>> are no changes compared to v4.
>> 
>> v4: Compared to v3 it contains mostly smallish naming and spelling fixes.
>> It also drops the documentation patch, Harald did a better job with the
>> documentation and the some things I described do not yet match the
>> implementation.
>> I'll readd the relevant parts with a follow up series.
>> 
>> This series lays the groundwork for removing the socket references from
>> the GTP netdevice by removing duplicate code and simplifying the logic on
>> some code paths.
>> 
>> It slighly changes the GTP genl API by making the socket parameters optional
>> (though one of them is still required).
>> 
>> The removal of the socket references will break the 1:1 releation between
>> GTP netdevice and GTP socket that prevents us to support multiple VRFs with
>> overlapping IP addresse spaces attached to the same GTP-U entity (needed for
>> multi APN support, coming a follow up series).
>> 
>> Pablo found a socket hold problem in v2. In order to solve that I had to
>> switch the socket references from the struct socket to the internal
>> struct sock. This should have no functionl impact, but we can now hang
>> on to the reference without blocking user space from closing the GTP socket.
> 
> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>

Thanks, Pablo.
 
> I personally don't like this podge hodge unsorted submissions, I don't
> think they belong to the same series but you keep pushing with this
> patchset in this same way, which is annoying.

I don't think this a podge hodge series. There is a clear goal behind all
those changes and every patch is a step towards this. When I tried to
send the full series including the final change that ties everything
together, I got told that this was way too much. Now, that I split it into
a smaller series, I get told that there is no clear idea connecting those
changes.

Frankly, between the two options, I had no idea how else to submit this
work.

> In your follow up patchsets, please split them in smaller series that
> are related.

Now that the basic infrastructure changes are in place, the followup
changes are much more focused.

The IPv6 transport change might be challenge later one, but that will be
a separate series anyway.

> I would like you take the time to develop the VRF idea that you want
> to introduce, I just would like that we avoid bloating the GTP tunnel
> with features that we can just achieve via composite of different
> subsystems.

The VRF change is more about moving stuff around, it doesn't add much.
But you'll see that for yourself when I send the changes.

> Thank you.

Thank you,
Andreas

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next v5 0/7] gtp: misc improvements
  2017-03-13 16:48 ` Pablo Neira Ayuso
  2017-03-13 17:12   ` Harald Welte
  2017-03-13 18:45   ` Andreas Schultz
@ 2017-03-13 20:06   ` David Miller
  2 siblings, 0 replies; 13+ messages in thread
From: David Miller @ 2017-03-13 20:06 UTC (permalink / raw)
  To: pablo; +Cc: aschultz, laforge, osmocom-net-gprs, netdev

From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Mon, 13 Mar 2017 17:48:12 +0100

> On Thu, Mar 09, 2017 at 05:42:55PM +0100, Andreas Schultz wrote:
>> Hi Pablo,
>> 
>> This is a resent of last series that missed the merge window. There
>> are no changes compared to v4.
>> 
>> v4: Compared to v3 it contains mostly smallish naming and spelling fixes.
>> It also drops the documentation patch, Harald did a better job with the
>> documentation and the some things I described do not yet match the implementation.
>> I'll readd the relevant parts with a follow up series.
>> 
>> This series lays the groundwork for removing the socket references from
>> the GTP netdevice by removing duplicate code and simplifying the logic on
>> some code paths.
>> 
>> It slighly changes the GTP genl API by making the socket parameters optional
>> (though one of them is still required).
>> 
>> The removal of the socket references will break the 1:1 releation between
>> GTP netdevice and GTP socket that prevents us to support multiple VRFs with
>> overlapping IP addresse spaces attached to the same GTP-U entity (needed for
>> multi APN support, coming a follow up series).
>> 
>> Pablo found a socket hold problem in v2. In order to solve that I had to
>> switch the socket references from the struct socket to the internal
>> struct sock. This should have no functionl impact, but we can now hang
>> on to the reference without blocking user space from closing the GTP socket.
> 
> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
> 
> I personally don't like this podge hodge unsorted submissions, I don't
> think they belong to the same series but you keep pushing with this
> patchset in this same way, which is annoying.
> 
> In your follow up patchsets, please split them in smaller series that
> are related.

Series applied, and I agree with Pablo.

If the best you can come up with for a Subject line in your series
header posting is "misc improvements" it absolutely means you are
putting unrelated changes together in a series and you need to refine
the submission such that only related changes are submitted together.

Then you can say "gtp: Adjust GTP socket handling", for example, in
your header posting of a 2 patch series that includes only patches
#1 and #2.

Then you patiently wait for that patch series to be accepted, and then
you can move onwards to the other aspects of this series.

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2017-03-13 20:06 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-09 16:42 [PATCH net-next v5 0/7] gtp: misc improvements Andreas Schultz
2017-03-09 16:42 ` [PATCH net-next v5 1/7] gtp: switch from struct socket to struct sock for the GTP sockets Andreas Schultz
2017-03-09 16:42 ` [PATCH net-next v5 2/7] gtp: make GTP sockets in gtp_newlink optional Andreas Schultz
2017-03-09 16:42 ` [PATCH net-next v5 3/7] gtp: merge gtp_get_net and gtp_genl_find_dev Andreas Schultz
2017-03-09 16:42 ` [PATCH net-next v5 4/7] gtp: consolidate gtp socket rx path Andreas Schultz
2017-03-09 16:43 ` [PATCH net-next v5 5/7] gtp: unify genl_find_pdp and prepare for per socket lookup Andreas Schultz
2017-03-09 16:43 ` [PATCH net-next v5 6/7] gtp: consolidate pdp context destruction into helper Andreas Schultz
2017-03-09 16:43 ` [PATCH net-next v5 7/7] gtp: add socket to pdp context Andreas Schultz
2017-03-11 21:51 ` [PATCH net-next v5 0/7] gtp: misc improvements Harald Welte
2017-03-13 16:48 ` Pablo Neira Ayuso
2017-03-13 17:12   ` Harald Welte
2017-03-13 18:45   ` Andreas Schultz
2017-03-13 20:06   ` David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.