All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket
@ 2017-01-24 15:28 Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 01/18] gtp: add genl family modules alias Andreas Schultz
                   ` (18 more replies)
  0 siblings, 19 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

The current linking of GTP network devices and GTP enabled sockets means that
we can not have multiple VRF's per GTP socket. This series seperates the
sockets from network device, makes sockets attached to GTP network device
optional and adds a API function to enable GTP encapsulation on socket
without having to create a new GTP device.

It is still possible to use the old API. The network device attached socket is
then used when no socket is specified on PDP context creation.

During that work some smaller problems where found and fixes for them are
included.

v2 changes:

 * the socket that is hold by the pdp context has to be release in a rcu
   callback. Otherwise a stray GTP rx could end uo with an invalid socket.
 * accessing the skb->sk field in gtp_rx is invalid, that field has no
   been populated at that point
 * add dst_cache to speed up the routing

Regards
Andreas

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

* [PATCH v2 01/18] gtp: add genl family modules alias
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 02/18] gtp: clear DF bit on GTP packet tx Andreas Schultz
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

Auto-load the module when userspace asks for the gtp netlink
family.

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

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 8b6810b..7580ccc 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -1376,3 +1376,4 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <hwelte@sysmocom.de>");
 MODULE_DESCRIPTION("Interface driver for GTP encapsulated traffic");
 MODULE_ALIAS_RTNL_LINK("gtp");
+MODULE_ALIAS_GENL_FAMILY("gtp");
-- 
2.10.2

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

* [PATCH v2 02/18] gtp: clear DF bit on GTP packet tx
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 01/18] gtp: add genl family modules alias Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 03/18] gtp: make GTP sockets in gtp_newlink optional Andreas Schultz
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

3GPP TS 29.281 and 3GPP TS 29.060 imply that GTP-U packets should be
sent with the DF bit cleared. For example 3GPP TS 29.060, Release 8,
Section 13.2.2:

> Backbone router: Any router in the backbone may fragment the GTP
> packet if needed, according to IPv4.

Signed-off-by: Andreas Schultz <aschultz@tpip.net>
---
 drivers/net/gtp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 7580ccc..1df54d6 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -612,7 +612,7 @@ static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev)
 				    pktinfo.fl4.saddr, pktinfo.fl4.daddr,
 				    pktinfo.iph->tos,
 				    ip4_dst_hoplimit(&pktinfo.rt->dst),
-				    htons(IP_DF),
+				    0,
 				    pktinfo.gtph_port, pktinfo.gtph_port,
 				    true, false);
 		break;
-- 
2.10.2

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

* [PATCH v2 03/18] gtp: make GTP sockets in gtp_newlink optional
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 01/18] gtp: add genl family modules alias Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 02/18] gtp: clear DF bit on GTP packet tx Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 04/18] gtp: return error ptr in find pdp helpers Andreas Schultz
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

A fixed binding of gtp enabled socket to netdevice does not make
sense (GTP TEID are unique per socket and not per L3 IP device).

To untangle netdevice and gtp sockets without breaking the UAPI,
make per netdevice sockets optional.

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

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 1df54d6..60946b7 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -276,30 +276,6 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
 	return ret;
 }
 
-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->sock1u && gtp->sock1u->sk) {
-		udp_sk(gtp->sock1u->sk)->encap_type = 0;
-		rcu_assign_sk_user_data(gtp->sock1u->sk, NULL);
-	}
-
-	gtp->sock0 = NULL;
-	gtp->sock1u = 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);
-}
-
 /* UDP encapsulation receive handler. See net/ipv4/udp.c.
  * Return codes: 0: success, <0: error, >0: pass up to userspace UDP socket.
  */
@@ -363,6 +339,17 @@ static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb)
 	return 0;
 }
 
+static void gtp_encap_destroy(struct sock *sk)
+{
+	struct gtp_dev *gtp;
+
+	gtp = rcu_dereference_sk_user_data(sk);
+	if (gtp) {
+		udp_sk(sk)->encap_type = 0;
+		rcu_assign_sk_user_data(sk, NULL);
+	}
+}
+
 static int gtp_dev_init(struct net_device *dev)
 {
 	struct gtp_dev *gtp = netdev_priv(dev);
@@ -378,9 +365,6 @@ static int gtp_dev_init(struct net_device *dev)
 
 static void gtp_dev_uninit(struct net_device *dev)
 {
-	struct gtp_dev *gtp = netdev_priv(dev);
-
-	gtp_encap_disable(gtp);
 	free_percpu(dev->tstats);
 }
 
@@ -658,35 +642,32 @@ 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, struct net *src_net);
+			    struct net *src_net, struct nlattr *data[]);
+static void gtp_encap_disable(struct gtp_dev *gtp);
 
 static int gtp_newlink(struct net *src_net, struct net_device *dev,
 			struct nlattr *tb[], struct nlattr *data[])
 {
-	int hashsize, err, fd0, fd1;
+	int hashsize, err;
 	struct gtp_dev *gtp;
 	struct gtp_net *gn;
 
-	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, src_net);
-	if (err < 0)
-		goto out_err;
-
 	if (!data[IFLA_GTP_PDP_HASHSIZE])
 		hashsize = 1024;
 	else
 		hashsize = nla_get_u32(data[IFLA_GTP_PDP_HASHSIZE]);
 
+	if (data[IFLA_GTP_FD0] || data[IFLA_GTP_FD1]) {
+		err = gtp_encap_enable(dev, gtp, src_net, data);
+		if (err < 0)
+			goto out_err;
+	}
+
 	err = gtp_hashtable_new(gtp, hashsize);
 	if (err < 0)
-		goto out_encap;
+		goto out_socket;
 
 	err = register_netdevice(dev);
 	if (err < 0) {
@@ -703,7 +684,7 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
 
 out_hashtable:
 	gtp_hashtable_free(gtp);
-out_encap:
+out_socket:
 	gtp_encap_disable(gtp);
 out_err:
 	return err;
@@ -713,8 +694,11 @@ static void gtp_dellink(struct net_device *dev, struct list_head *head)
 {
 	struct gtp_dev *gtp = netdev_priv(dev);
 
-	gtp_encap_disable(gtp);
 	gtp_hashtable_free(gtp);
+	if (gtp->sock0)
+		sockfd_put(gtp->sock0);
+	if (gtp->sock1u)
+		sockfd_put(gtp->sock1u);
 	list_del_rcu(&gtp->list);
 	unregister_netdevice_queue(dev, head);
 }
@@ -820,38 +804,63 @@ 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, struct net *src_net)
+static struct socket *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;
 	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);
+	if (sock->sk->sk_protocol != IPPROTO_UDP) {
+		pr_debug("socket fd=%d not UDP\n", fd);
 		err = -EINVAL;
-		goto err1;
+		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;
+	tuncfg.sk_user_data = gtp;
+	tuncfg.encap_type = type;
+	tuncfg.encap_rcv = gtp_encap_recv;
+	tuncfg.encap_destroy = gtp_encap_destroy;
+
+	setup_udp_tunnel_sock(sock_net(sock->sk), sock, &tuncfg);
+	return sock;
+
+out_sock:
+	sockfd_put(sock);
+	return ERR_PTR(err);
+}
+
+static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
+			    struct net *src_net, struct nlattr *data[])
+{
+	struct socket *sock0 = NULL;
+	struct socket *sock1u = NULL;
+
+	if (data[IFLA_GTP_FD0]) {
+		u32 fd0 = nla_get_u32(data[IFLA_GTP_FD0]);
+
+		sock0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, gtp);
+		if (IS_ERR(sock0))
+			return PTR_ERR(sock0);
 	}
 
-	if (sock1u->sk->sk_protocol != IPPROTO_UDP) {
-		netdev_dbg(dev, "socket fd=%d not UDP\n", fd_gtp1);
-		err = -EINVAL;
-		goto err2;
+	if (data[IFLA_GTP_FD1]) {
+		u32 fd1 = nla_get_u32(data[IFLA_GTP_FD1]);
+
+		sock1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp);
+		if (IS_ERR(sock1u)) {
+			if (sock0)
+				sockfd_put(sock0);
+			return PTR_ERR(sock1u);
+		}
 	}
 
 	netdev_dbg(dev, "enable gtp on %p, %p\n", sock0, sock1u);
@@ -860,22 +869,21 @@ static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
 	gtp->sock1u = sock1u;
 	gtp->net = src_net;
 
-	tuncfg.sk_user_data = gtp;
-	tuncfg.encap_rcv = gtp_encap_recv;
-	tuncfg.encap_destroy = gtp_encap_destroy;
+	return 0;
+}
 
-	tuncfg.encap_type = UDP_ENCAP_GTP0;
-	setup_udp_tunnel_sock(sock_net(gtp->sock0->sk), gtp->sock0, &tuncfg);
+static void gtp_encap_disable_sock(struct socket *sock)
+{
+	if (!sock || !sock->sk)
+		return;
 
-	tuncfg.encap_type = UDP_ENCAP_GTP1U;
-	setup_udp_tunnel_sock(sock_net(gtp->sock1u->sk), gtp->sock1u, &tuncfg);
+	gtp_encap_destroy(sock->sk);
+}
 
-	err = 0;
-err2:
-	sockfd_put(sock1u);
-err1:
-	sockfd_put(sock0);
-	return err;
+static void gtp_encap_disable(struct gtp_dev *gtp)
+{
+	gtp_encap_disable_sock(gtp->sock0);
+	gtp_encap_disable_sock(gtp->sock1u);
 }
 
 static struct net_device *gtp_find_dev(struct net *net, int ifindex)
-- 
2.10.2

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

* [PATCH v2 04/18] gtp: return error ptr in find pdp helpers
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (2 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 03/18] gtp: make GTP sockets in gtp_newlink optional Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 05/18] gtp: unify genl_find_pdp and prepare for per socket lookup Andreas Schultz
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

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

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 60946b7..e95c856 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -114,7 +114,7 @@ static struct pdp_ctx *gtp0_pdp_find(struct gtp_dev *gtp, u64 tid)
 		    pdp->u.v0.tid == tid)
 			return pdp;
 	}
-	return NULL;
+	return ERR_PTR(-ENOENT);
 }
 
 /* Resolve a PDP context structure based on the 32bit TEI. */
@@ -130,7 +130,7 @@ static struct pdp_ctx *gtp1_pdp_find(struct gtp_dev *gtp, u32 tid)
 		    pdp->u.v1.i_tei == tid)
 			return pdp;
 	}
-	return NULL;
+	return ERR_PTR(-ENOENT);
 }
 
 /* Resolve a PDP context based on IPv4 address of MS. */
@@ -147,7 +147,7 @@ static struct pdp_ctx *ipv4_pdp_find(struct gtp_dev *gtp, __be32 ms_addr)
 			return pdp;
 	}
 
-	return NULL;
+	return ERR_PTR(-ENOENT);
 }
 
 static bool gtp_check_src_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx,
@@ -199,7 +199,7 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
 
 	rcu_read_lock();
 	pctx = gtp0_pdp_find(gtp, be64_to_cpu(gtp0->tid));
-	if (!pctx) {
+	if (IS_ERR(pctx)) {
 		netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb);
 		ret = -1;
 		goto out_rcu;
@@ -256,7 +256,7 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
 
 	rcu_read_lock();
 	pctx = gtp1_pdp_find(gtp, ntohl(gtp1->tid));
-	if (!pctx) {
+	if (IS_ERR(pctx)) {
 		netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb);
 		ret = -1;
 		goto out_rcu;
@@ -476,10 +476,10 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
 	 */
 	iph = ip_hdr(skb);
 	pctx = ipv4_pdp_find(gtp, iph->daddr);
-	if (!pctx) {
+	if (IS_ERR(pctx)) {
 		netdev_dbg(dev, "no PDP ctx found for %pI4, skip\n",
 			   &iph->daddr);
-		return -ENOENT;
+		return PTR_ERR(pctx);
 	}
 	netdev_dbg(dev, "found PDP context %p\n", pctx);
 
@@ -1085,8 +1085,8 @@ static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info)
 		return -EINVAL;
 	}
 
-	if (pctx == NULL)
-		return -ENOENT;
+	if (IS_ERR(pctx))
+		return PTR_ERR(pctx);
 
 	if (pctx->gtp_version == GTP_V0)
 		netdev_dbg(dev, "GTPv0-U: deleting tunnel id = %llx (pdp %p)\n",
@@ -1194,8 +1194,8 @@ static int gtp_genl_get_pdp(struct sk_buff *skb, struct genl_info *info)
 		pctx = ipv4_pdp_find(gtp, ip);
 	}
 
-	if (pctx == NULL) {
-		err = -ENOENT;
+	if (IS_ERR(pctx)) {
+		err = PTR_ERR(pctx);
 		goto err_unlock;
 	}
 
-- 
2.10.2

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

* [PATCH v2 05/18] gtp: unify genl_find_pdp and prepare for per socket lookup
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (3 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 04/18] gtp: return error ptr in find pdp helpers Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 06/18] gtp: fix cross netns recv on gtp socket Andreas Schultz
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

TEID are unique per socket and not per network device. Therefore
the API needs to be changed here.

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

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index e95c856..7a3c5f6 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -1044,56 +1044,61 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
 	return ipv4_pdp_add(dev, info);
 }
 
-static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info)
+static struct pdp_ctx *gtp_genl_find_pdp_by_link(struct sk_buff *skb,
+						 struct genl_info *info)
 {
 	struct net_device *dev;
-	struct pdp_ctx *pctx;
 	struct gtp_dev *gtp;
 	struct net *net;
+	__be32 ms_addr;
 
-	if (!info->attrs[GTPA_VERSION] ||
-	    !info->attrs[GTPA_LINK])
-		return -EINVAL;
+	if (!info->attrs[GTPA_MS_ADDRESS])
+		return ERR_PTR(-EINVAL);
+	ms_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]);
 
 	net = gtp_genl_get_net(sock_net(skb->sk), info->attrs);
 	if (IS_ERR(net))
-		return PTR_ERR(net);
+		return ERR_PTR(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;
+		return ERR_PTR(-ENODEV);
 	}
 	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;
-		pctx = gtp0_pdp_find(gtp, nla_get_u64(info->attrs[GTPA_TID]));
-		break;
-	case GTP_V1:
-		if (!info->attrs[GTPA_I_TEI])
-			return -EINVAL;
-		pctx = gtp1_pdp_find(gtp, nla_get_u64(info->attrs[GTPA_I_TEI]));
-		break;
+	return ipv4_pdp_find(gtp, ms_addr);
+}
 
-	default:
+static struct pdp_ctx *gtp_genl_find_pdp(struct sk_buff *skb,
+					 struct genl_info *info)
+{
+	if (info->attrs[GTPA_LINK])
+		return gtp_genl_find_pdp_by_link(skb, info);
+	else
+		return ERR_PTR(-EINVAL);
+}
+
+static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info)
+{
+	struct pdp_ctx *pctx;
+
+	if (!info->attrs[GTPA_VERSION])
 		return -EINVAL;
-	}
 
+	pctx = gtp_genl_find_pdp(skb, info);
 	if (IS_ERR(pctx))
 		return PTR_ERR(pctx);
 
 	if (pctx->gtp_version == GTP_V0)
-		netdev_dbg(dev, "GTPv0-U: deleting tunnel id = %llx (pdp %p)\n",
-			   pctx->u.v0.tid, pctx);
+		pr_debug("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",
-			   pctx->u.v1.i_tei, pctx->u.v1.o_tei, pctx);
+		pr_debug("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);
@@ -1143,57 +1148,15 @@ 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] ||
-	    !info->attrs[GTPA_LINK])
-		return -EINVAL;
-
-	gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]);
-	switch (gtp_version) {
-	case GTP_V0:
-	case GTP_V1:
-		break;
-	default:
+	if (!info->attrs[GTPA_VERSION])
 		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();
-	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);
-	}
 
+	pctx = gtp_genl_find_pdp(skb, info);
 	if (IS_ERR(pctx)) {
 		err = PTR_ERR(pctx);
 		goto err_unlock;
-- 
2.10.2

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

* [PATCH v2 06/18] gtp: fix cross netns recv on gtp socket
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (4 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 05/18] gtp: unify genl_find_pdp and prepare for per socket lookup Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 07/18] gtp: remove unnecessary rcu_read_lock Andreas Schultz
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

The use of the paassed through netlink src_net to check for a
cross netns operation was wrong. Using the GTP socket and the
GTP netdevice is always correct (even if the netdev has been
moved to new netns after link creation).

Remove the now obsolete net field from gtp_dev.

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

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 7a3c5f6..bc8734b7 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -69,7 +69,6 @@ struct gtp_dev {
 	struct socket		*sock0;
 	struct socket		*sock1u;
 
-	struct net		*net;
 	struct net_device	*dev;
 
 	unsigned int		hash_size;
@@ -292,7 +291,7 @@ 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(gtp->net, dev_net(gtp->dev));
+	xnet = !net_eq(sock_net(sk), dev_net(gtp->dev));
 
 	switch (udp_sk(sk)->encap_type) {
 	case UDP_ENCAP_GTP0:
@@ -642,7 +641,7 @@ 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,
-			    struct net *src_net, struct nlattr *data[]);
+			    struct nlattr *data[]);
 static void gtp_encap_disable(struct gtp_dev *gtp);
 
 static int gtp_newlink(struct net *src_net, struct net_device *dev,
@@ -660,7 +659,7 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
 		hashsize = nla_get_u32(data[IFLA_GTP_PDP_HASHSIZE]);
 
 	if (data[IFLA_GTP_FD0] || data[IFLA_GTP_FD1]) {
-		err = gtp_encap_enable(dev, gtp, src_net, data);
+		err = gtp_encap_enable(dev, gtp, data);
 		if (err < 0)
 			goto out_err;
 	}
@@ -839,7 +838,7 @@ static struct socket *gtp_encap_enable_socket(int fd, int type,
 }
 
 static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
-			    struct net *src_net, struct nlattr *data[])
+			    struct nlattr *data[])
 {
 	struct socket *sock0 = NULL;
 	struct socket *sock1u = NULL;
@@ -867,7 +866,6 @@ static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
 
 	gtp->sock0 = sock0;
 	gtp->sock1u = sock1u;
-	gtp->net = src_net;
 
 	return 0;
 }
-- 
2.10.2

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

* [PATCH v2 07/18] gtp: remove unnecessary rcu_read_lock
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (5 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 06/18] gtp: fix cross netns recv on gtp socket Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 08/18] gtp: consolidate pdp context destruction into helper Andreas Schultz
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

The rcu read lock is hold by default in the ip input path. There
is no need to hold it twice in the socket recv decapsulate code path.

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

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index bc8734b7..f434f84 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -183,7 +183,6 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
 			      sizeof(struct gtp0_header);
 	struct gtp0_header *gtp0;
 	struct pdp_ctx *pctx;
-	int ret = 0;
 
 	if (!pskb_may_pull(skb, hdrlen))
 		return -1;
@@ -196,26 +195,19 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
 	if (gtp0->type != GTP_TPDU)
 		return 1;
 
-	rcu_read_lock();
 	pctx = gtp0_pdp_find(gtp, be64_to_cpu(gtp0->tid));
 	if (IS_ERR(pctx)) {
 		netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb);
-		ret = -1;
-		goto out_rcu;
+		return -1;
 	}
 
 	if (!gtp_check_src_ms(skb, pctx, hdrlen)) {
 		netdev_dbg(gtp->dev, "No PDP ctx for this MS\n");
-		ret = -1;
-		goto out_rcu;
+		return -1;
 	}
-	rcu_read_unlock();
 
 	/* Get rid of the GTP + UDP headers. */
 	return iptunnel_pull_header(skb, hdrlen, skb->protocol, xnet);
-out_rcu:
-	rcu_read_unlock();
-	return ret;
 }
 
 static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
@@ -225,7 +217,6 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
 			      sizeof(struct gtp1_header);
 	struct gtp1_header *gtp1;
 	struct pdp_ctx *pctx;
-	int ret = 0;
 
 	if (!pskb_may_pull(skb, hdrlen))
 		return -1;
@@ -253,26 +244,19 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
 
 	gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr));
 
-	rcu_read_lock();
 	pctx = gtp1_pdp_find(gtp, ntohl(gtp1->tid));
 	if (IS_ERR(pctx)) {
 		netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb);
-		ret = -1;
-		goto out_rcu;
+		return -1;
 	}
 
 	if (!gtp_check_src_ms(skb, pctx, hdrlen)) {
 		netdev_dbg(gtp->dev, "No PDP ctx for this MS\n");
-		ret = -1;
-		goto out_rcu;
+		return -1;
 	}
-	rcu_read_unlock();
 
 	/* Get rid of the GTP + UDP headers. */
 	return iptunnel_pull_header(skb, hdrlen, skb->protocol, xnet);
-out_rcu:
-	rcu_read_unlock();
-	return ret;
 }
 
 /* UDP encapsulation receive handler. See net/ipv4/udp.c.
-- 
2.10.2

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

* [PATCH v2 08/18] gtp: consolidate pdp context destruction into helper
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (6 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 07/18] gtp: remove unnecessary rcu_read_lock Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 09/18] gtp: use addr_hash when traversing pdp contexts Andreas Schultz
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

Remove duplicate code and use a rcu helper to free the
structure to prepare for addition of PDP context members
that need to be handled in the rcu callcack.

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

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index f434f84..c117f63 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -84,6 +84,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;
@@ -775,13 +777,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);
@@ -984,6 +983,20 @@ static int ipv4_pdp_add(struct net_device *dev, 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);
+
+	kfree(pctx);
+}
+
+static void pdp_context_delete(struct pdp_ctx *pctx)
+{
+	hlist_del_rcu(&pctx->hlist_tid);
+	hlist_del_rcu(&pctx->hlist_addr);
+	call_rcu(&pctx->rcu_head, pdp_context_free);
+}
+
 static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
 {
 	struct net_device *dev;
@@ -1082,10 +1095,7 @@ static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info)
 		pr_debug("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);
 	return 0;
 }
 
-- 
2.10.2

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

* [PATCH v2 09/18] gtp: use addr_hash when traversing pdp contexts
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (7 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 08/18] gtp: consolidate pdp context destruction into helper Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 10/18] gtp: add socket to pdp context Andreas Schultz
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

This prepares for the removal of the tid_hash from the device.

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

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index c117f63..c7e32a6 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -778,7 +778,7 @@ static void gtp_hashtable_free(struct gtp_dev *gtp)
 	int i;
 
 	for (i = 0; i < gtp->hash_size; i++)
-		hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i], hlist_tid)
+		hlist_for_each_entry_rcu(pctx, &gtp->addr_hash[i], hlist_addr)
 			pdp_context_delete(pctx);
 
 	synchronize_rcu();
@@ -1195,7 +1195,7 @@ static int gtp_genl_dump_pdp(struct sk_buff *skb,
 			last_gtp = NULL;
 
 		for (i = k; i < gtp->hash_size; i++) {
-			hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i], hlist_tid) {
+			hlist_for_each_entry_rcu(pctx, &gtp->addr_hash[i], hlist_addr) {
 				if (tid && tid != pctx->u.tid)
 					continue;
 				else
-- 
2.10.2

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

* [PATCH v2 10/18] gtp: add socket to pdp context
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (8 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 09/18] gtp: use addr_hash when traversing pdp contexts Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 11/18] gtp: consolidate gtp socket rx path Andreas Schultz
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

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 <aschultz@tpip.net>
---
 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,
-- 
2.10.2

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

* [PATCH v2 11/18] gtp: consolidate gtp socket rx path
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (9 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 10/18] gtp: add socket to pdp context Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 12/18] gtp: let userspace handle packets for invalid tunnels Andreas Schultz
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

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 | 92 ++++++++++++++++++++++++++++---------------------------
 1 file changed, 47 insertions(+), 45 deletions(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index fb93468..ea97b49 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 net_device       *dev;
 	struct sock		*sk;
 
 	atomic_t		tx_seq;
@@ -179,9 +180,42 @@ static bool gtp_check_src_ms(struct sk_buff *skb, struct pdp_ctx *pctx,
 	return false;
 }
 
+static int gtp_rx(struct sk_buff *skb, struct pdp_ctx *pctx, unsigned int hdrlen)
+{
+	struct pcpu_sw_netstats *stats;
+
+	if (!gtp_check_src_ms(skb, pctx, hdrlen)) {
+		pr_debug("No PDP ctx for this MS\n");
+		return -1;
+	}
+
+	/* Get rid of the GTP + UDP headers. */
+	if (iptunnel_pull_header(skb, hdrlen, skb->protocol,
+				 !net_eq(sock_net(pctx->sk), dev_net(pctx->dev))))
+		return -1;
+
+	pr_debug("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)
+static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
 {
 	unsigned int hdrlen = sizeof(struct udphdr) +
 			      sizeof(struct gtp0_header);
@@ -205,17 +239,10 @@ 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(skb, pctx, 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);
@@ -254,13 +281,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(skb, pctx, hdrlen);
 }
 
 /* UDP encapsulation receive handler. See net/ipv4/udp.c.
@@ -268,10 +289,8 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
  */
 static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb)
 {
-	struct pcpu_sw_netstats *stats;
 	struct gtp_dev *gtp;
-	bool xnet;
-	int ret;
+	int ret = 0;
 
 	gtp = rcu_dereference_sk_user_data(sk);
 	if (!gtp)
@@ -279,16 +298,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. */
@@ -297,33 +314,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 void gtp_encap_destroy(struct sock *sk)
@@ -929,6 +930,7 @@ static int ipv4_pdp_add(struct net_device *dev, struct sock *sk,
 
 	sock_hold(sk);
 	pctx->sk = sk;
+	pctx->dev = dev;
 	ipv4_pdp_fill(pctx, info);
 	atomic_set(&pctx->tx_seq, 0);
 
-- 
2.10.2

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

* [PATCH v2 12/18] gtp: let userspace handle packets for invalid tunnels
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (10 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 11/18] gtp: consolidate gtp socket rx path Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 13/18] gtp: replace netdev_dbg and KERN_DEBUG printk with pr_debug Andreas Schultz
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

enable userspace to send error replies for invalid tunnels

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

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index ea97b49..8d74b7d 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -186,7 +186,7 @@ static int gtp_rx(struct sk_buff *skb, struct pdp_ctx *pctx, unsigned int hdrlen
 
 	if (!gtp_check_src_ms(skb, pctx, hdrlen)) {
 		pr_debug("No PDP ctx for this MS\n");
-		return -1;
+		return 1;
 	}
 
 	/* Get rid of the GTP + UDP headers. */
@@ -236,7 +236,7 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
 	pctx = gtp0_pdp_find(gtp, be64_to_cpu(gtp0->tid));
 	if (IS_ERR(pctx)) {
 		netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb);
-		return -1;
+		return 1;
 	}
 
 	return gtp_rx(skb, pctx, hdrlen);
@@ -278,7 +278,7 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
 	pctx = gtp1_pdp_find(gtp, ntohl(gtp1->tid));
 	if (IS_ERR(pctx)) {
 		netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb);
-		return -1;
+		return 1;
 	}
 
 	return gtp_rx(skb, pctx, hdrlen);
-- 
2.10.2

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

* [PATCH v2 13/18] gtp: replace netdev_dbg and KERN_DEBUG printk with pr_debug
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (11 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 12/18] gtp: let userspace handle packets for invalid tunnels Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 14/18] gtp: move TEID hash to per socket structure Andreas Schultz
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

pr_debug is more versatile for normal debugging.
Also replace netdev_dbg in in places where the network device
will be remove soon.

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

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 8d74b7d..7d82252 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -235,7 +235,7 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
 
 	pctx = gtp0_pdp_find(gtp, be64_to_cpu(gtp0->tid));
 	if (IS_ERR(pctx)) {
-		netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb);
+		pr_debug("No PDP ctx to decap skb=%p\n", skb);
 		return 1;
 	}
 
@@ -277,7 +277,7 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
 
 	pctx = gtp1_pdp_find(gtp, ntohl(gtp1->tid));
 	if (IS_ERR(pctx)) {
-		netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb);
+		pr_debug("No PDP ctx to decap skb=%p\n", skb);
 		return 1;
 	}
 
@@ -296,15 +296,15 @@ static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb)
 	if (!gtp)
 		return 1;
 
-	netdev_dbg(gtp->dev, "encap_recv sk=%p\n", sk);
+	pr_debug("encap_recv sk=%p\n", sk);
 
 	switch (udp_sk(sk)->encap_type) {
 	case UDP_ENCAP_GTP0:
-		netdev_dbg(gtp->dev, "received GTP0 packet\n");
+		pr_debug("received GTP0 packet\n");
 		ret = gtp0_udp_encap_recv(gtp, skb);
 		break;
 	case UDP_ENCAP_GTP1U:
-		netdev_dbg(gtp->dev, "received GTP1U packet\n");
+		pr_debug("received GTP1U packet\n");
 		ret = gtp1u_udp_encap_recv(gtp, skb);
 		break;
 	default:
@@ -313,12 +313,12 @@ 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");
+		pr_debug("pass up to the process\n");
 		break;
 	case 0:
 		break;
 	case -1:
-		netdev_dbg(gtp->dev, "GTP packet has been dropped\n");
+		pr_debug("GTP packet has been dropped\n");
 		kfree_skb(skb);
 		ret = 0;
 		break;
-- 
2.10.2

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

* [PATCH v2 14/18] gtp: move TEID hash to per socket structure
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (12 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 13/18] gtp: replace netdev_dbg and KERN_DEBUG printk with pr_debug Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 15/18] gtp: rename gtp hashtable helpers Andreas Schultz
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

Untangele the TEID information from the network device and move
it into a per socket structure.

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

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 7d82252..d2ba943 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -75,10 +75,15 @@ struct gtp_dev {
 	struct net_device	*dev;
 
 	unsigned int		hash_size;
-	struct hlist_head	*tid_hash;
 	struct hlist_head	*addr_hash;
 };
 
+/* One instance of the GTP socket. */
+struct gtp_sock {
+	unsigned int		hash_size;
+	struct hlist_head	tid_hash[];
+};
+
 static unsigned int gtp_net_id __read_mostly;
 
 struct gtp_net {
@@ -106,12 +111,12 @@ static inline u32 ipv4_hashfn(__be32 ip)
 }
 
 /* Resolve a PDP context structure based on the 64bit TID. */
-static struct pdp_ctx *gtp0_pdp_find(struct gtp_dev *gtp, u64 tid)
+static struct pdp_ctx *gtp0_pdp_find(struct gtp_sock *gsk, u64 tid)
 {
 	struct hlist_head *head;
 	struct pdp_ctx *pdp;
 
-	head = &gtp->tid_hash[gtp0_hashfn(tid) % gtp->hash_size];
+	head = &gsk->tid_hash[gtp0_hashfn(tid) % gsk->hash_size];
 
 	hlist_for_each_entry_rcu(pdp, head, hlist_tid) {
 		if (pdp->gtp_version == GTP_V0 &&
@@ -122,12 +127,12 @@ static struct pdp_ctx *gtp0_pdp_find(struct gtp_dev *gtp, u64 tid)
 }
 
 /* Resolve a PDP context structure based on the 32bit TEI. */
-static struct pdp_ctx *gtp1_pdp_find(struct gtp_dev *gtp, u32 tid)
+static struct pdp_ctx *gtp1_pdp_find(struct gtp_sock *gsk, u32 tid)
 {
 	struct hlist_head *head;
 	struct pdp_ctx *pdp;
 
-	head = &gtp->tid_hash[gtp1u_hashfn(tid) % gtp->hash_size];
+	head = &gsk->tid_hash[gtp1u_hashfn(tid) % gsk->hash_size];
 
 	hlist_for_each_entry_rcu(pdp, head, hlist_tid) {
 		if (pdp->gtp_version == GTP_V1 &&
@@ -215,7 +220,7 @@ static int gtp_rx(struct sk_buff *skb, struct pdp_ctx *pctx, 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)
+static int gtp0_udp_encap_recv(struct gtp_sock *gsk, struct sk_buff *skb)
 {
 	unsigned int hdrlen = sizeof(struct udphdr) +
 			      sizeof(struct gtp0_header);
@@ -233,7 +238,7 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
 	if (gtp0->type != GTP_TPDU)
 		return 1;
 
-	pctx = gtp0_pdp_find(gtp, be64_to_cpu(gtp0->tid));
+	pctx = gtp0_pdp_find(gsk, be64_to_cpu(gtp0->tid));
 	if (IS_ERR(pctx)) {
 		pr_debug("No PDP ctx to decap skb=%p\n", skb);
 		return 1;
@@ -242,7 +247,7 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
 	return gtp_rx(skb, pctx, hdrlen);
 }
 
-static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
+static int gtp1u_udp_encap_recv(struct gtp_sock *gsk, struct sk_buff *skb)
 {
 	unsigned int hdrlen = sizeof(struct udphdr) +
 			      sizeof(struct gtp1_header);
@@ -275,7 +280,7 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
 
 	gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr));
 
-	pctx = gtp1_pdp_find(gtp, ntohl(gtp1->tid));
+	pctx = gtp1_pdp_find(gsk, ntohl(gtp1->tid));
 	if (IS_ERR(pctx)) {
 		pr_debug("No PDP ctx to decap skb=%p\n", skb);
 		return 1;
@@ -289,11 +294,11 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
  */
 static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb)
 {
-	struct gtp_dev *gtp;
+	struct gtp_sock *gsk;
 	int ret = 0;
 
-	gtp = rcu_dereference_sk_user_data(sk);
-	if (!gtp)
+	gsk = rcu_dereference_sk_user_data(sk);
+	if (!gsk)
 		return 1;
 
 	pr_debug("encap_recv sk=%p\n", sk);
@@ -301,11 +306,11 @@ static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb)
 	switch (udp_sk(sk)->encap_type) {
 	case UDP_ENCAP_GTP0:
 		pr_debug("received GTP0 packet\n");
-		ret = gtp0_udp_encap_recv(gtp, skb);
+		ret = gtp0_udp_encap_recv(gsk, skb);
 		break;
 	case UDP_ENCAP_GTP1U:
 		pr_debug("received GTP1U packet\n");
-		ret = gtp1u_udp_encap_recv(gtp, skb);
+		ret = gtp1u_udp_encap_recv(gsk, skb);
 		break;
 	default:
 		ret = -1; /* Shouldn't happen. */
@@ -329,12 +334,21 @@ static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb)
 
 static void gtp_encap_destroy(struct sock *sk)
 {
-	struct gtp_dev *gtp;
+	struct gtp_sock *gsk;
+	struct pdp_ctx *pctx;
+	int i;
 
-	gtp = rcu_dereference_sk_user_data(sk);
-	if (gtp) {
+	gsk = rcu_dereference_sk_user_data(sk);
+	if (gsk) {
 		udp_sk(sk)->encap_type = 0;
 		rcu_assign_sk_user_data(sk, NULL);
+
+		for (i = 0; i < gsk->hash_size; i++)
+			hlist_for_each_entry_rcu(pctx, &gsk->tid_hash[i], hlist_tid)
+				pdp_context_delete(pctx);
+
+		synchronize_rcu();
+		kfree(gsk);
 	}
 }
 
@@ -607,7 +621,7 @@ 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,
-			    struct nlattr *data[]);
+			    int hsize, struct nlattr *data[]);
 static void gtp_encap_disable(struct gtp_dev *gtp);
 
 static int gtp_newlink(struct net *src_net, struct net_device *dev,
@@ -625,7 +639,7 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
 		hashsize = nla_get_u32(data[IFLA_GTP_PDP_HASHSIZE]);
 
 	if (data[IFLA_GTP_FD0] || data[IFLA_GTP_FD1]) {
-		err = gtp_encap_enable(dev, gtp, data);
+		err = gtp_encap_enable(dev, gtp, hashsize, data);
 		if (err < 0)
 			goto out_err;
 	}
@@ -736,20 +750,12 @@ static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize)
 	if (gtp->addr_hash == NULL)
 		return -ENOMEM;
 
-	gtp->tid_hash = kmalloc(sizeof(struct hlist_head) * hsize, GFP_KERNEL);
-	if (gtp->tid_hash == NULL)
-		goto err1;
-
 	gtp->hash_size = hsize;
 
-	for (i = 0; i < hsize; i++) {
+	for (i = 0; i < hsize; i++)
 		INIT_HLIST_HEAD(&gtp->addr_hash[i]);
-		INIT_HLIST_HEAD(&gtp->tid_hash[i]);
-	}
+
 	return 0;
-err1:
-	kfree(gtp->addr_hash);
-	return -ENOMEM;
 }
 
 static void gtp_hashtable_free(struct gtp_dev *gtp)
@@ -763,15 +769,14 @@ static void gtp_hashtable_free(struct gtp_dev *gtp)
 
 	synchronize_rcu();
 	kfree(gtp->addr_hash);
-	kfree(gtp->tid_hash);
 }
 
-static struct socket *gtp_encap_enable_socket(int fd, int type,
-					      struct gtp_dev *gtp)
+static struct socket *gtp_encap_enable_socket(int fd, int type, int hsize)
 {
 	struct udp_tunnel_sock_cfg tuncfg = {NULL};
+	struct gtp_sock *gsk;
 	struct socket *sock;
-	int err;
+	int err, i;
 
 	pr_debug("enable gtp on %d, %d\n", fd, type);
 
@@ -787,7 +792,17 @@ static struct socket *gtp_encap_enable_socket(int fd, int type,
 		goto out_sock;
 	}
 
-	tuncfg.sk_user_data = gtp;
+	gsk = kzalloc(sizeof(*gsk) + sizeof(struct hlist_head) * hsize, GFP_KERNEL);
+	if (!gsk) {
+		err = -ENOMEM;
+		goto out_sock;
+	}
+
+	gsk->hash_size = hsize;
+	for (i = 0; i < hsize; i++)
+		INIT_HLIST_HEAD(&gsk->tid_hash[i]);
+
+	tuncfg.sk_user_data = gsk;
 	tuncfg.encap_type = type;
 	tuncfg.encap_rcv = gtp_encap_recv;
 	tuncfg.encap_destroy = gtp_encap_destroy;
@@ -801,7 +816,7 @@ static struct socket *gtp_encap_enable_socket(int fd, int type,
 }
 
 static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
-			    struct nlattr *data[])
+			    int hsize, struct nlattr *data[])
 {
 	struct socket *sock0 = NULL;
 	struct socket *sock1u = NULL;
@@ -809,7 +824,7 @@ static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
 	if (data[IFLA_GTP_FD0]) {
 		u32 fd0 = nla_get_u32(data[IFLA_GTP_FD0]);
 
-		sock0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, gtp);
+		sock0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, hsize);
 		if (IS_ERR(sock0))
 			return PTR_ERR(sock0);
 	}
@@ -817,7 +832,7 @@ static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
 	if (data[IFLA_GTP_FD1]) {
 		u32 fd1 = nla_get_u32(data[IFLA_GTP_FD1]);
 
-		sock1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp);
+		sock1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, hsize);
 		if (IS_ERR(sock1u)) {
 			if (sock0)
 				sockfd_put(sock0);
@@ -890,11 +905,16 @@ static int ipv4_pdp_add(struct net_device *dev, struct sock *sk,
 			struct genl_info *info)
 {
 	struct gtp_dev *gtp = netdev_priv(dev);
+	struct gtp_sock *gsk;
 	u32 hash_ms, hash_tid = 0;
 	struct pdp_ctx *pctx;
 	bool found = false;
 	__be32 ms_addr;
 
+	gsk = rcu_dereference_sk_user_data(sk);
+	if (!gsk)
+		return -ENODEV;
+
 	ms_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]);
 	hash_ms = ipv4_hashfn(ms_addr) % gtp->hash_size;
 
@@ -941,15 +961,15 @@ static int ipv4_pdp_add(struct net_device *dev, struct sock *sk,
 		 * situation in which this doesn't unambiguosly identify the
 		 * PDP context.
 		 */
-		hash_tid = gtp0_hashfn(pctx->u.v0.tid) % gtp->hash_size;
+		hash_tid = gtp0_hashfn(pctx->u.v0.tid) % gsk->hash_size;
 		break;
 	case GTP_V1:
-		hash_tid = gtp1u_hashfn(pctx->u.v1.i_tei) % gtp->hash_size;
+		hash_tid = gtp1u_hashfn(pctx->u.v1.i_tei) % gsk->hash_size;
 		break;
 	}
 
 	hlist_add_head_rcu(&pctx->hlist_addr, &gtp->addr_hash[hash_ms]);
-	hlist_add_head_rcu(&pctx->hlist_tid, &gtp->tid_hash[hash_tid]);
+	hlist_add_head_rcu(&pctx->hlist_tid, &gsk->tid_hash[hash_tid]);
 
 	switch (pctx->gtp_version) {
 	case GTP_V0:
-- 
2.10.2

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

* [PATCH v2 15/18] gtp: rename gtp hashtable helpers
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (13 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 14/18] gtp: move TEID hash to per socket structure Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 16/18] gtp: add genl cmd to enable GTP encapsulation on UDP socket Andreas Schultz
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

The gtp_hashtable helper are now olny used for the per netdevice
address hashes. Rename them to make their purpose clearer.

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

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index d2ba943..9e5f858 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -618,8 +618,8 @@ static void gtp_link_setup(struct net_device *dev)
 				  sizeof(struct gtp0_header);
 }
 
-static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize);
-static void gtp_hashtable_free(struct gtp_dev *gtp);
+static int gtp_dev_hashtable_new(struct gtp_dev *gtp, int hsize);
+static void gtp_dev_hashtable_free(struct gtp_dev *gtp);
 static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
 			    int hsize, struct nlattr *data[]);
 static void gtp_encap_disable(struct gtp_dev *gtp);
@@ -644,7 +644,7 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
 			goto out_err;
 	}
 
-	err = gtp_hashtable_new(gtp, hashsize);
+	err = gtp_dev_hashtable_new(gtp, hashsize);
 	if (err < 0)
 		goto out_socket;
 
@@ -662,7 +662,7 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
 	return 0;
 
 out_hashtable:
-	gtp_hashtable_free(gtp);
+	gtp_dev_hashtable_free(gtp);
 out_socket:
 	gtp_encap_disable(gtp);
 out_err:
@@ -673,7 +673,7 @@ static void gtp_dellink(struct net_device *dev, struct list_head *head)
 {
 	struct gtp_dev *gtp = netdev_priv(dev);
 
-	gtp_hashtable_free(gtp);
+	gtp_dev_hashtable_free(gtp);
 	if (gtp->sock0)
 		sockfd_put(gtp->sock0);
 	if (gtp->sock1u)
@@ -742,7 +742,7 @@ static struct net *gtp_genl_get_net(struct net *src_net, struct nlattr *tb[])
 	return net;
 }
 
-static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize)
+static int gtp_dev_hashtable_new(struct gtp_dev *gtp, int hsize)
 {
 	int i;
 
@@ -758,7 +758,7 @@ static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize)
 	return 0;
 }
 
-static void gtp_hashtable_free(struct gtp_dev *gtp)
+static void gtp_dev_hashtable_free(struct gtp_dev *gtp)
 {
 	struct pdp_ctx *pctx;
 	int i;
-- 
2.10.2

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

* [PATCH v2 16/18] gtp: add genl cmd to enable GTP encapsulation on UDP socket
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (14 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 15/18] gtp: rename gtp hashtable helpers Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 17/18] gtp: add support to select a GTP socket during PDP context creation Andreas Schultz
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

Signed-off-by: Andreas Schultz <aschultz@tpip.net>
---
 drivers/net/gtp.c        | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/gtp.h |  4 ++++
 2 files changed, 52 insertions(+)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 9e5f858..c6c1f0d 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -1247,6 +1247,46 @@ static int gtp_genl_dump_pdp(struct sk_buff *skb,
 	return skb->len;
 }
 
+static int gtp_genl_enable_socket(struct sk_buff *skb, struct genl_info *info)
+{
+	u32 version, fd, hashsize;
+	struct socket *sock;
+
+	if (!info->attrs[GTPA_VERSION] ||
+	    !info->attrs[GTPA_FD])
+		return -EINVAL;
+
+	if (!info->attrs[GTPA_PDP_HASHSIZE])
+		hashsize = 1024;
+	else
+		hashsize = nla_get_u32(info->attrs[IFLA_GTP_PDP_HASHSIZE]);
+
+	version = nla_get_u32(info->attrs[GTPA_VERSION]);
+	fd = nla_get_u32(info->attrs[GTPA_FD]);
+
+	switch (version) {
+	case GTP_V0:
+		sock = gtp_encap_enable_socket(fd, UDP_ENCAP_GTP0, hashsize);
+		break;
+
+	case GTP_V1:
+		sock = gtp_encap_enable_socket(fd, UDP_ENCAP_GTP1U, hashsize);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (!sock)
+		return -EINVAL;
+
+	if (IS_ERR(sock))
+		return PTR_ERR(sock);
+
+	sockfd_put(sock);
+	return 0;
+}
+
 static struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = {
 	[GTPA_LINK]		= { .type = NLA_U32, },
 	[GTPA_VERSION]		= { .type = NLA_U32, },
@@ -1257,6 +1297,8 @@ static struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = {
 	[GTPA_NET_NS_FD]	= { .type = NLA_U32, },
 	[GTPA_I_TEI]		= { .type = NLA_U32, },
 	[GTPA_O_TEI]		= { .type = NLA_U32, },
+	[GTPA_PDP_HASHSIZE]	= { .type = NLA_U32, },
+	[GTPA_FD]		= { .type = NLA_U32, },
 };
 
 static const struct genl_ops gtp_genl_ops[] = {
@@ -1279,6 +1321,12 @@ static const struct genl_ops gtp_genl_ops[] = {
 		.policy = gtp_genl_policy,
 		.flags = GENL_ADMIN_PERM,
 	},
+	{
+		.cmd = GTP_CMD_ENABLE_SOCKET,
+		.doit = gtp_genl_enable_socket,
+		.policy = gtp_genl_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
 };
 
 static struct genl_family gtp_genl_family __ro_after_init = {
diff --git a/include/uapi/linux/gtp.h b/include/uapi/linux/gtp.h
index 72a04a0..a9e9fe0 100644
--- a/include/uapi/linux/gtp.h
+++ b/include/uapi/linux/gtp.h
@@ -6,6 +6,8 @@ enum gtp_genl_cmds {
 	GTP_CMD_DELPDP,
 	GTP_CMD_GETPDP,
 
+	GTP_CMD_ENABLE_SOCKET,
+
 	GTP_CMD_MAX,
 };
 
@@ -26,6 +28,8 @@ enum gtp_attrs {
 	GTPA_I_TEI,	/* for GTPv1 only */
 	GTPA_O_TEI,	/* for GTPv1 only */
 	GTPA_PAD,
+	GTPA_PDP_HASHSIZE,
+	GTPA_FD,
 	__GTPA_MAX,
 };
 #define GTPA_MAX (__GTPA_MAX + 1)
-- 
2.10.2

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

* [PATCH v2 17/18] gtp: add support to select a GTP socket during PDP context creation
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (15 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 16/18] gtp: add genl cmd to enable GTP encapsulation on UDP socket Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:28 ` [PATCH v2 18/18] gtp: add dst_cache support Andreas Schultz
  2017-01-24 15:39 ` [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Harald Welte
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

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

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index c6c1f0d..4637ce7 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -1023,6 +1023,7 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
 	struct net_device *dev;
 	struct net *net;
 	struct socket *sock;
+	int err;
 
 	if (!info->attrs[GTPA_VERSION] ||
 	    !info->attrs[GTPA_LINK] ||
@@ -1060,11 +1061,19 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
 	}
 	put_net(net);
 
-	sock = gtp_genl_new_pdp_select_socket(version, dev);
-	if (!sock)
+	if (info->attrs[GTPA_FD])
+		sock = sockfd_lookup(nla_get_u32(info->attrs[GTPA_FD]), &err);
+	else
+		sock = gtp_genl_new_pdp_select_socket(version, dev);
+	if (!sock || !sock->sk)
 		return -ENODEV;
 
-	return ipv4_pdp_add(dev, sock->sk, info);
+	err = ipv4_pdp_add(dev, sock->sk, info);
+
+	if (info->attrs[GTPA_FD])
+		sockfd_put(sock);
+
+	return err;
 }
 
 static struct pdp_ctx *gtp_genl_find_pdp_by_link(struct sk_buff *skb,
@@ -1096,11 +1105,64 @@ static struct pdp_ctx *gtp_genl_find_pdp_by_link(struct sk_buff *skb,
 	return ipv4_pdp_find(gtp, ms_addr);
 }
 
+static struct pdp_ctx *gtp_genl_find_pdp_by_socket(struct sk_buff *skb,
+						   struct genl_info *info)
+{
+	struct socket *sock;
+	struct gtp_sock *gsk;
+	struct pdp_ctx *pctx;
+	int fd, err = 0;
+
+	if (!info->attrs[GTPA_FD])
+		return ERR_PTR(-EINVAL);
+
+	fd = nla_get_u32(info->attrs[GTPA_FD]);
+	sock = sockfd_lookup(fd, &err);
+	if (!sock) {
+		pr_debug("gtp socket fd=%d not found\n", fd);
+		return ERR_PTR(-EBADF);
+	}
+
+	gsk = rcu_dereference_sk_user_data(sock->sk);
+	if (!gsk) {
+		pctx = ERR_PTR(-EINVAL);
+		goto out_sock;
+	}
+
+	switch (nla_get_u32(info->attrs[GTPA_VERSION])) {
+	case GTP_V0:
+		if (!info->attrs[GTPA_TID]) {
+			pctx = ERR_PTR(-EINVAL);
+			break;
+		}
+		pctx = gtp0_pdp_find(gsk, nla_get_u64(info->attrs[GTPA_TID]));
+		break;
+
+	case GTP_V1:
+		if (!info->attrs[GTPA_I_TEI]) {
+			pctx = ERR_PTR(-EINVAL);
+			break;
+		}
+		pctx = gtp1_pdp_find(gsk, nla_get_u64(info->attrs[GTPA_I_TEI]));
+		break;
+
+	default:
+		pctx = ERR_PTR(-EINVAL);
+		break;
+	}
+
+out_sock:
+	sockfd_put(sock);
+	return pctx;
+}
+
 static struct pdp_ctx *gtp_genl_find_pdp(struct sk_buff *skb,
 					 struct genl_info *info)
 {
 	if (info->attrs[GTPA_LINK])
 		return gtp_genl_find_pdp_by_link(skb, info);
+	else if (info->attrs[GTPA_FD])
+		return gtp_genl_find_pdp_by_socket(skb, info);
 	else
 		return ERR_PTR(-EINVAL);
 }
-- 
2.10.2

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

* [PATCH v2 18/18] gtp: add dst_cache support
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (16 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 17/18] gtp: add support to select a GTP socket during PDP context creation Andreas Schultz
@ 2017-01-24 15:28 ` Andreas Schultz
  2017-01-24 15:39 ` [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Harald Welte
  18 siblings, 0 replies; 21+ messages in thread
From: Andreas Schultz @ 2017-01-24 15:28 UTC (permalink / raw)
  To: Pablo Neira; +Cc: netdev, Lionel Gauthier, openbsc, Harald Welte

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

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 4637ce7..c3e40cc 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -61,6 +61,10 @@ struct pdp_ctx {
 	struct net_device       *dev;
 	struct sock		*sk;
 
+#ifdef CONFIG_DST_CACHE
+	struct dst_cache        dst_cache;
+#endif
+
 	atomic_t		tx_seq;
 	struct rcu_head		rcu_head;
 };
@@ -485,12 +489,18 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
 	}
 	netdev_dbg(dev, "found PDP context %p\n", pctx);
 
-	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);
-		dev->stats.tx_carrier_errors++;
-		goto err;
+	rt = dst_cache_get_ip4(&pctx->dst_cache, &pctx->sgsn_addr_ip4.s_addr);
+	if (!rt) {
+		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);
+			dev->stats.tx_carrier_errors++;
+			goto err;
+		}
+
+		dst_cache_set_ip4(&pctx->dst_cache, &rt->dst,
+				  pctx->sgsn_addr_ip4.s_addr);
 	}
 
 	if (rt->dst.dev == dev) {
@@ -883,6 +893,8 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info)
 	pctx->ms_addr_ip4.s_addr =
 		nla_get_be32(info->attrs[GTPA_MS_ADDRESS]);
 
+	dst_cache_reset(&pctx->dst_cache);
+
 	switch (pctx->gtp_version) {
 	case GTP_V0:
 		/* According to TS 09.60, sections 7.5.1 and 7.5.2, the flow
@@ -910,6 +922,7 @@ static int ipv4_pdp_add(struct net_device *dev, struct sock *sk,
 	struct pdp_ctx *pctx;
 	bool found = false;
 	__be32 ms_addr;
+	int err;
 
 	gsk = rcu_dereference_sk_user_data(sk);
 	if (!gsk)
@@ -948,6 +961,12 @@ static int ipv4_pdp_add(struct net_device *dev, struct sock *sk,
 	if (pctx == NULL)
 		return -ENOMEM;
 
+	err = dst_cache_init(&pctx->dst_cache, GFP_KERNEL);
+	if (err) {
+		kfree(pctx);
+		return err;
+	}
+
 	sock_hold(sk);
 	pctx->sk = sk;
 	pctx->dev = dev;
@@ -992,6 +1011,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);
+	dst_cache_destroy(&pctx->dst_cache);
 	kfree(pctx);
 }
 
-- 
2.10.2

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

* Re: [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket
  2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
                   ` (17 preceding siblings ...)
  2017-01-24 15:28 ` [PATCH v2 18/18] gtp: add dst_cache support Andreas Schultz
@ 2017-01-24 15:39 ` Harald Welte
  2017-01-24 16:46   ` David Miller
  18 siblings, 1 reply; 21+ messages in thread
From: Harald Welte @ 2017-01-24 15:39 UTC (permalink / raw)
  To: Andreas Schultz; +Cc: Pablo Neira, netdev, Lionel Gauthier, openbsc

Hi Andreas,

On Tue, Jan 24, 2017 at 04:28:30PM +0100, Andreas Schultz wrote:
> During that work some smaller problems where found and fixes for them are
> included.

As this is a rather large patch-set, and I think it might be better to
split it in clear bugfixes of the existing code (or no-brainers like the
module alias) and in introducing new featur regarding socket/netdev.
However, that's just my comment "from the side", I'm not the one who
needs to be convinced in terms of merging them :)

I would just assume that the clear fixes + no-brainers could go in right
away without any further review...

-- 
- Harald Welte <laforge@netfilter.org>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

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

* Re: [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket
  2017-01-24 15:39 ` [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Harald Welte
@ 2017-01-24 16:46   ` David Miller
  0 siblings, 0 replies; 21+ messages in thread
From: David Miller @ 2017-01-24 16:46 UTC (permalink / raw)
  To: laforge; +Cc: aschultz, pablo, netdev, Lionel.Gauthier, openbsc

From: Harald Welte <laforge@netfilter.org>
Date: Tue, 24 Jan 2017 16:39:19 +0100

> Hi Andreas,
> 
> On Tue, Jan 24, 2017 at 04:28:30PM +0100, Andreas Schultz wrote:
>> During that work some smaller problems where found and fixes for them are
>> included.
> 
> As this is a rather large patch-set, and I think it might be better to
> split it in clear bugfixes of the existing code (or no-brainers like the
> module alias) and in introducing new featur regarding socket/netdev.
> However, that's just my comment "from the side", I'm not the one who
> needs to be convinced in terms of merging them :)
> 
> I would just assume that the clear fixes + no-brainers could go in right
> away without any further review...

Yes, please split this stuff up, the patch series is _way_ too large.

Anything more than a dozen patches is way too much to burdon reviewers
with at one time.

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

end of thread, other threads:[~2017-01-24 16:46 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-24 15:28 [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 01/18] gtp: add genl family modules alias Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 02/18] gtp: clear DF bit on GTP packet tx Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 03/18] gtp: make GTP sockets in gtp_newlink optional Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 04/18] gtp: return error ptr in find pdp helpers Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 05/18] gtp: unify genl_find_pdp and prepare for per socket lookup Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 06/18] gtp: fix cross netns recv on gtp socket Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 07/18] gtp: remove unnecessary rcu_read_lock Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 08/18] gtp: consolidate pdp context destruction into helper Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 09/18] gtp: use addr_hash when traversing pdp contexts Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 10/18] gtp: add socket to pdp context Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 11/18] gtp: consolidate gtp socket rx path Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 12/18] gtp: let userspace handle packets for invalid tunnels Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 13/18] gtp: replace netdev_dbg and KERN_DEBUG printk with pr_debug Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 14/18] gtp: move TEID hash to per socket structure Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 15/18] gtp: rename gtp hashtable helpers Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 16/18] gtp: add genl cmd to enable GTP encapsulation on UDP socket Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 17/18] gtp: add support to select a GTP socket during PDP context creation Andreas Schultz
2017-01-24 15:28 ` [PATCH v2 18/18] gtp: add dst_cache support Andreas Schultz
2017-01-24 15:39 ` [PATCH v2 00/18] gtp: fixes and support multiple VRF's per GTP socket Harald Welte
2017-01-24 16:46   ` 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.