All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v6 1/7] gtp: Allow to create GTP device without FDs
@ 2022-02-18 14:51 Marcin Szycik
  2022-02-18 15:04 ` Marcin Szycik
  0 siblings, 1 reply; 3+ messages in thread
From: Marcin Szycik @ 2022-02-18 14:51 UTC (permalink / raw)
  To: netdev
  Cc: michal.swiatkowski, wojciech.drewek, davem, kuba, pablo, laforge,
	osmocom-net-gprs

From: Wojciech Drewek <wojciech.drewek@intel.com>

Currently, when the user wants to create GTP device, he has to
provide file handles to the sockets created in userspace (IFLA_GTP_FD0,
IFLA_GTP_FD1). This behaviour is not ideal, considering the option of
adding support for GTP device creation through ip link. Ip link
application is not a good place to create such sockets.

This patch allows to create GTP device without providing
IFLA_GTP_FD0 and IFLA_GTP_FD1 arguments. If the user sets
IFLA_GTP_CREATE_SOCKETS attribute, then GTP module takes care
of creating UDP sockets by itself. Sockets are created with the
commonly known UDP ports used for GTP protocol (GTP0_PORT and
GTP1U_PORT). In this case we don't have to provide encap_destroy
because no extra deinitialization is needed, everything is covered
by udp_tunnel_sock_release.

Note: GTP instance created with only this change applied, does
not handle GTP Echo Requests. This is implemented in the following
patch.

Signed-off-by: Wojciech Drewek <wojciech.drewek@intel.com>
---
v4: use ntohs when creating UDP socket
v5: IFLA_GTP_CREATE_SOCKETS introduced, gtp_newlink refactor
v6: reordering refactor removed
---
 drivers/net/gtp.c            | 101 +++++++++++++++++++++++++++++------
 include/uapi/linux/if_link.h |   1 +
 2 files changed, 85 insertions(+), 17 deletions(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index bf087171bcf0..25d8521897b3 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -66,8 +66,10 @@ struct gtp_dev {
 
 	struct sock		*sk0;
 	struct sock		*sk1u;
+	u8			sk_created;
 
 	struct net_device	*dev;
+	struct net		*net;
 
 	unsigned int		role;
 	unsigned int		hash_size;
@@ -320,8 +322,16 @@ static void gtp_encap_disable_sock(struct sock *sk)
 
 static void gtp_encap_disable(struct gtp_dev *gtp)
 {
-	gtp_encap_disable_sock(gtp->sk0);
-	gtp_encap_disable_sock(gtp->sk1u);
+	if (gtp->sk_created) {
+		udp_tunnel_sock_release(gtp->sk0->sk_socket);
+		udp_tunnel_sock_release(gtp->sk1u->sk_socket);
+		gtp->sk_created = false;
+		gtp->sk0 = NULL;
+		gtp->sk1u = NULL;
+	} else {
+		gtp_encap_disable_sock(gtp->sk0);
+		gtp_encap_disable_sock(gtp->sk1u);
+	}
 }
 
 /* UDP encapsulation receive handler. See net/ipv4/udp.c.
@@ -656,17 +666,69 @@ static void gtp_destructor(struct net_device *dev)
 	kfree(gtp->tid_hash);
 }
 
+static struct sock *gtp_create_sock(int type, struct gtp_dev *gtp)
+{
+	struct udp_tunnel_sock_cfg tuncfg = {};
+	struct udp_port_cfg udp_conf = {
+		.local_ip.s_addr	= htonl(INADDR_ANY),
+		.family			= AF_INET,
+	};
+	struct net *net = gtp->net;
+	struct socket *sock;
+	int err;
+
+	if (type == UDP_ENCAP_GTP0)
+		udp_conf.local_udp_port = htons(GTP0_PORT);
+	else if (type == UDP_ENCAP_GTP1U)
+		udp_conf.local_udp_port = htons(GTP1U_PORT);
+	else
+		return ERR_PTR(-EINVAL);
+
+	err = udp_sock_create(net, &udp_conf, &sock);
+	if (err)
+		return ERR_PTR(err);
+
+	tuncfg.sk_user_data = gtp;
+	tuncfg.encap_type = type;
+	tuncfg.encap_rcv = gtp_encap_recv;
+	tuncfg.encap_destroy = NULL;
+
+	setup_udp_tunnel_sock(net, sock, &tuncfg);
+
+	return sock->sk;
+}
+
+static int gtp_create_sockets(struct gtp_dev *gtp, struct nlattr *data[])
+{
+	struct sock *sk1u = NULL;
+	struct sock *sk0 = NULL;
+
+	sk0 = gtp_create_sock(UDP_ENCAP_GTP0, gtp);
+	if (IS_ERR(sk0))
+		return PTR_ERR(sk0);
+
+	sk1u = gtp_create_sock(UDP_ENCAP_GTP1U, gtp);
+	if (IS_ERR(sk1u)) {
+		udp_tunnel_sock_release(sk0->sk_socket);
+		return PTR_ERR(sk1u);
+	}
+
+	gtp->sk_created = true;
+	gtp->sk0 = sk0;
+	gtp->sk1u = sk1u;
+
+	return 0;
+}
+
 static int gtp_newlink(struct net *src_net, struct net_device *dev,
 		       struct nlattr *tb[], struct nlattr *data[],
 		       struct netlink_ext_ack *extack)
 {
+	unsigned int role = GTP_ROLE_GGSN;
 	struct gtp_dev *gtp;
 	struct gtp_net *gn;
 	int hashsize, err;
 
-	if (!data[IFLA_GTP_FD0] && !data[IFLA_GTP_FD1])
-		return -EINVAL;
-
 	gtp = netdev_priv(dev);
 
 	if (!data[IFLA_GTP_PDP_HASHSIZE]) {
@@ -677,11 +739,23 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
 			hashsize = 1024;
 	}
 
+	if (data[IFLA_GTP_ROLE]) {
+		role = nla_get_u32(data[IFLA_GTP_ROLE]);
+		if (role > GTP_ROLE_SGSN)
+			return -EINVAL;
+	}
+	gtp->role = role;
+
+	gtp->net = src_net;
+
 	err = gtp_hashtable_new(gtp, hashsize);
 	if (err < 0)
 		return err;
 
-	err = gtp_encap_enable(gtp, data);
+	if (data[IFLA_GTP_CREATE_SOCKETS])
+		err = gtp_create_sockets(gtp, data);
+	else
+		err = gtp_encap_enable(gtp, data);
 	if (err < 0)
 		goto out_hashtable;
 
@@ -726,6 +800,7 @@ static const struct nla_policy gtp_policy[IFLA_GTP_MAX + 1] = {
 	[IFLA_GTP_FD1]			= { .type = NLA_U32 },
 	[IFLA_GTP_PDP_HASHSIZE]		= { .type = NLA_U32 },
 	[IFLA_GTP_ROLE]			= { .type = NLA_U32 },
+	[IFLA_GTP_CREATE_SOCKETS]	= { .type = NLA_U8 },
 };
 
 static int gtp_validate(struct nlattr *tb[], struct nlattr *data[],
@@ -848,7 +923,9 @@ static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[])
 {
 	struct sock *sk1u = NULL;
 	struct sock *sk0 = NULL;
-	unsigned int role = GTP_ROLE_GGSN;
+
+	if (!data[IFLA_GTP_FD0] && !data[IFLA_GTP_FD1])
+		return -EINVAL;
 
 	if (data[IFLA_GTP_FD0]) {
 		u32 fd0 = nla_get_u32(data[IFLA_GTP_FD0]);
@@ -868,18 +945,8 @@ static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[])
 		}
 	}
 
-	if (data[IFLA_GTP_ROLE]) {
-		role = nla_get_u32(data[IFLA_GTP_ROLE]);
-		if (role > GTP_ROLE_SGSN) {
-			gtp_encap_disable_sock(sk0);
-			gtp_encap_disable_sock(sk1u);
-			return -EINVAL;
-		}
-	}
-
 	gtp->sk0 = sk0;
 	gtp->sk1u = sk1u;
-	gtp->role = role;
 
 	return 0;
 }
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 6218f93f5c1a..42f3fb097271 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -822,6 +822,7 @@ enum {
 	IFLA_GTP_FD1,
 	IFLA_GTP_PDP_HASHSIZE,
 	IFLA_GTP_ROLE,
+	IFLA_GTP_CREATE_SOCKETS,
 	__IFLA_GTP_MAX,
 };
 #define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1)
-- 
2.31.1


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

* Re: [PATCH net-next v6 1/7] gtp: Allow to create GTP device without FDs
  2022-02-18 14:51 [PATCH net-next v6 1/7] gtp: Allow to create GTP device without FDs Marcin Szycik
@ 2022-02-18 15:04 ` Marcin Szycik
  0 siblings, 0 replies; 3+ messages in thread
From: Marcin Szycik @ 2022-02-18 15:04 UTC (permalink / raw)
  To: netdev

Please ignore, sent a duplicate by mistake.

On 18-Feb-22 15:51, Marcin Szycik wrote:
> From: Wojciech Drewek <wojciech.drewek@intel.com>
> 
> Currently, when the user wants to create GTP device, he has to
> provide file handles to the sockets created in userspace (IFLA_GTP_FD0,
> IFLA_GTP_FD1). This behaviour is not ideal, considering the option of
> adding support for GTP device creation through ip link. Ip link
> application is not a good place to create such sockets.
> 
> This patch allows to create GTP device without providing
> IFLA_GTP_FD0 and IFLA_GTP_FD1 arguments. If the user sets
> IFLA_GTP_CREATE_SOCKETS attribute, then GTP module takes care
> of creating UDP sockets by itself. Sockets are created with the
> commonly known UDP ports used for GTP protocol (GTP0_PORT and
> GTP1U_PORT). In this case we don't have to provide encap_destroy
> because no extra deinitialization is needed, everything is covered
> by udp_tunnel_sock_release.
> 
> Note: GTP instance created with only this change applied, does
> not handle GTP Echo Requests. This is implemented in the following
> patch.
> 
> Signed-off-by: Wojciech Drewek <wojciech.drewek@intel.com>
> ---
> v4: use ntohs when creating UDP socket
> v5: IFLA_GTP_CREATE_SOCKETS introduced, gtp_newlink refactor
> v6: reordering refactor removed
> ---
>  drivers/net/gtp.c            | 101 +++++++++++++++++++++++++++++------
>  include/uapi/linux/if_link.h |   1 +
>  2 files changed, 85 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
> index bf087171bcf0..25d8521897b3 100644
> --- a/drivers/net/gtp.c
> +++ b/drivers/net/gtp.c
> @@ -66,8 +66,10 @@ struct gtp_dev {
>  
>  	struct sock		*sk0;
>  	struct sock		*sk1u;
> +	u8			sk_created;
>  
>  	struct net_device	*dev;
> +	struct net		*net;
>  
>  	unsigned int		role;
>  	unsigned int		hash_size;
> @@ -320,8 +322,16 @@ static void gtp_encap_disable_sock(struct sock *sk)
>  
>  static void gtp_encap_disable(struct gtp_dev *gtp)
>  {
> -	gtp_encap_disable_sock(gtp->sk0);
> -	gtp_encap_disable_sock(gtp->sk1u);
> +	if (gtp->sk_created) {
> +		udp_tunnel_sock_release(gtp->sk0->sk_socket);
> +		udp_tunnel_sock_release(gtp->sk1u->sk_socket);
> +		gtp->sk_created = false;
> +		gtp->sk0 = NULL;
> +		gtp->sk1u = NULL;
> +	} else {
> +		gtp_encap_disable_sock(gtp->sk0);
> +		gtp_encap_disable_sock(gtp->sk1u);
> +	}
>  }
>  
>  /* UDP encapsulation receive handler. See net/ipv4/udp.c.
> @@ -656,17 +666,69 @@ static void gtp_destructor(struct net_device *dev)
>  	kfree(gtp->tid_hash);
>  }
>  
> +static struct sock *gtp_create_sock(int type, struct gtp_dev *gtp)
> +{
> +	struct udp_tunnel_sock_cfg tuncfg = {};
> +	struct udp_port_cfg udp_conf = {
> +		.local_ip.s_addr	= htonl(INADDR_ANY),
> +		.family			= AF_INET,
> +	};
> +	struct net *net = gtp->net;
> +	struct socket *sock;
> +	int err;
> +
> +	if (type == UDP_ENCAP_GTP0)
> +		udp_conf.local_udp_port = htons(GTP0_PORT);
> +	else if (type == UDP_ENCAP_GTP1U)
> +		udp_conf.local_udp_port = htons(GTP1U_PORT);
> +	else
> +		return ERR_PTR(-EINVAL);
> +
> +	err = udp_sock_create(net, &udp_conf, &sock);
> +	if (err)
> +		return ERR_PTR(err);
> +
> +	tuncfg.sk_user_data = gtp;
> +	tuncfg.encap_type = type;
> +	tuncfg.encap_rcv = gtp_encap_recv;
> +	tuncfg.encap_destroy = NULL;
> +
> +	setup_udp_tunnel_sock(net, sock, &tuncfg);
> +
> +	return sock->sk;
> +}
> +
> +static int gtp_create_sockets(struct gtp_dev *gtp, struct nlattr *data[])
> +{
> +	struct sock *sk1u = NULL;
> +	struct sock *sk0 = NULL;
> +
> +	sk0 = gtp_create_sock(UDP_ENCAP_GTP0, gtp);
> +	if (IS_ERR(sk0))
> +		return PTR_ERR(sk0);
> +
> +	sk1u = gtp_create_sock(UDP_ENCAP_GTP1U, gtp);
> +	if (IS_ERR(sk1u)) {
> +		udp_tunnel_sock_release(sk0->sk_socket);
> +		return PTR_ERR(sk1u);
> +	}
> +
> +	gtp->sk_created = true;
> +	gtp->sk0 = sk0;
> +	gtp->sk1u = sk1u;
> +
> +	return 0;
> +}
> +
>  static int gtp_newlink(struct net *src_net, struct net_device *dev,
>  		       struct nlattr *tb[], struct nlattr *data[],
>  		       struct netlink_ext_ack *extack)
>  {
> +	unsigned int role = GTP_ROLE_GGSN;
>  	struct gtp_dev *gtp;
>  	struct gtp_net *gn;
>  	int hashsize, err;
>  
> -	if (!data[IFLA_GTP_FD0] && !data[IFLA_GTP_FD1])
> -		return -EINVAL;
> -
>  	gtp = netdev_priv(dev);
>  
>  	if (!data[IFLA_GTP_PDP_HASHSIZE]) {
> @@ -677,11 +739,23 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
>  			hashsize = 1024;
>  	}
>  
> +	if (data[IFLA_GTP_ROLE]) {
> +		role = nla_get_u32(data[IFLA_GTP_ROLE]);
> +		if (role > GTP_ROLE_SGSN)
> +			return -EINVAL;
> +	}
> +	gtp->role = role;
> +
> +	gtp->net = src_net;
> +
>  	err = gtp_hashtable_new(gtp, hashsize);
>  	if (err < 0)
>  		return err;
>  
> -	err = gtp_encap_enable(gtp, data);
> +	if (data[IFLA_GTP_CREATE_SOCKETS])
> +		err = gtp_create_sockets(gtp, data);
> +	else
> +		err = gtp_encap_enable(gtp, data);
>  	if (err < 0)
>  		goto out_hashtable;
>  
> @@ -726,6 +800,7 @@ static const struct nla_policy gtp_policy[IFLA_GTP_MAX + 1] = {
>  	[IFLA_GTP_FD1]			= { .type = NLA_U32 },
>  	[IFLA_GTP_PDP_HASHSIZE]		= { .type = NLA_U32 },
>  	[IFLA_GTP_ROLE]			= { .type = NLA_U32 },
> +	[IFLA_GTP_CREATE_SOCKETS]	= { .type = NLA_U8 },
>  };
>  
>  static int gtp_validate(struct nlattr *tb[], struct nlattr *data[],
> @@ -848,7 +923,9 @@ static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[])
>  {
>  	struct sock *sk1u = NULL;
>  	struct sock *sk0 = NULL;
> -	unsigned int role = GTP_ROLE_GGSN;
> +
> +	if (!data[IFLA_GTP_FD0] && !data[IFLA_GTP_FD1])
> +		return -EINVAL;
>  
>  	if (data[IFLA_GTP_FD0]) {
>  		u32 fd0 = nla_get_u32(data[IFLA_GTP_FD0]);
> @@ -868,18 +945,8 @@ static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[])
>  		}
>  	}
>  
> -	if (data[IFLA_GTP_ROLE]) {
> -		role = nla_get_u32(data[IFLA_GTP_ROLE]);
> -		if (role > GTP_ROLE_SGSN) {
> -			gtp_encap_disable_sock(sk0);
> -			gtp_encap_disable_sock(sk1u);
> -			return -EINVAL;
> -		}
> -	}
> -
>  	gtp->sk0 = sk0;
>  	gtp->sk1u = sk1u;
> -	gtp->role = role;
>  
>  	return 0;
>  }
> diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
> index 6218f93f5c1a..42f3fb097271 100644
> --- a/include/uapi/linux/if_link.h
> +++ b/include/uapi/linux/if_link.h
> @@ -822,6 +822,7 @@ enum {
>  	IFLA_GTP_FD1,
>  	IFLA_GTP_PDP_HASHSIZE,
>  	IFLA_GTP_ROLE,
> +	IFLA_GTP_CREATE_SOCKETS,
>  	__IFLA_GTP_MAX,
>  };
>  #define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1)

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

* [PATCH net-next v6 1/7] gtp: Allow to create GTP device without FDs
  2022-02-18 14:50 [PATCH net-next v6 0/7] ice: GTP support in switchdev Marcin Szycik
@ 2022-02-18 14:53 ` Marcin Szycik
  0 siblings, 0 replies; 3+ messages in thread
From: Marcin Szycik @ 2022-02-18 14:53 UTC (permalink / raw)
  To: netdev
  Cc: michal.swiatkowski, wojciech.drewek, davem, kuba, pablo, laforge,
	osmocom-net-gprs

From: Wojciech Drewek <wojciech.drewek@intel.com>

Currently, when the user wants to create GTP device, he has to
provide file handles to the sockets created in userspace (IFLA_GTP_FD0,
IFLA_GTP_FD1). This behaviour is not ideal, considering the option of
adding support for GTP device creation through ip link. Ip link
application is not a good place to create such sockets.

This patch allows to create GTP device without providing
IFLA_GTP_FD0 and IFLA_GTP_FD1 arguments. If the user sets
IFLA_GTP_CREATE_SOCKETS attribute, then GTP module takes care
of creating UDP sockets by itself. Sockets are created with the
commonly known UDP ports used for GTP protocol (GTP0_PORT and
GTP1U_PORT). In this case we don't have to provide encap_destroy
because no extra deinitialization is needed, everything is covered
by udp_tunnel_sock_release.

Note: GTP instance created with only this change applied, does
not handle GTP Echo Requests. This is implemented in the following
patch.

Signed-off-by: Wojciech Drewek <wojciech.drewek@intel.com>
---
v4: use ntohs when creating UDP socket
v5: IFLA_GTP_CREATE_SOCKETS introduced, gtp_newlink refactor
v6: reordering refactor removed
---
 drivers/net/gtp.c            | 101 +++++++++++++++++++++++++++++------
 include/uapi/linux/if_link.h |   1 +
 2 files changed, 85 insertions(+), 17 deletions(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index bf087171bcf0..25d8521897b3 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -66,8 +66,10 @@ struct gtp_dev {
 
 	struct sock		*sk0;
 	struct sock		*sk1u;
+	u8			sk_created;
 
 	struct net_device	*dev;
+	struct net		*net;
 
 	unsigned int		role;
 	unsigned int		hash_size;
@@ -320,8 +322,16 @@ static void gtp_encap_disable_sock(struct sock *sk)
 
 static void gtp_encap_disable(struct gtp_dev *gtp)
 {
-	gtp_encap_disable_sock(gtp->sk0);
-	gtp_encap_disable_sock(gtp->sk1u);
+	if (gtp->sk_created) {
+		udp_tunnel_sock_release(gtp->sk0->sk_socket);
+		udp_tunnel_sock_release(gtp->sk1u->sk_socket);
+		gtp->sk_created = false;
+		gtp->sk0 = NULL;
+		gtp->sk1u = NULL;
+	} else {
+		gtp_encap_disable_sock(gtp->sk0);
+		gtp_encap_disable_sock(gtp->sk1u);
+	}
 }
 
 /* UDP encapsulation receive handler. See net/ipv4/udp.c.
@@ -656,17 +666,69 @@ static void gtp_destructor(struct net_device *dev)
 	kfree(gtp->tid_hash);
 }
 
+static struct sock *gtp_create_sock(int type, struct gtp_dev *gtp)
+{
+	struct udp_tunnel_sock_cfg tuncfg = {};
+	struct udp_port_cfg udp_conf = {
+		.local_ip.s_addr	= htonl(INADDR_ANY),
+		.family			= AF_INET,
+	};
+	struct net *net = gtp->net;
+	struct socket *sock;
+	int err;
+
+	if (type == UDP_ENCAP_GTP0)
+		udp_conf.local_udp_port = htons(GTP0_PORT);
+	else if (type == UDP_ENCAP_GTP1U)
+		udp_conf.local_udp_port = htons(GTP1U_PORT);
+	else
+		return ERR_PTR(-EINVAL);
+
+	err = udp_sock_create(net, &udp_conf, &sock);
+	if (err)
+		return ERR_PTR(err);
+
+	tuncfg.sk_user_data = gtp;
+	tuncfg.encap_type = type;
+	tuncfg.encap_rcv = gtp_encap_recv;
+	tuncfg.encap_destroy = NULL;
+
+	setup_udp_tunnel_sock(net, sock, &tuncfg);
+
+	return sock->sk;
+}
+
+static int gtp_create_sockets(struct gtp_dev *gtp, struct nlattr *data[])
+{
+	struct sock *sk1u = NULL;
+	struct sock *sk0 = NULL;
+
+	sk0 = gtp_create_sock(UDP_ENCAP_GTP0, gtp);
+	if (IS_ERR(sk0))
+		return PTR_ERR(sk0);
+
+	sk1u = gtp_create_sock(UDP_ENCAP_GTP1U, gtp);
+	if (IS_ERR(sk1u)) {
+		udp_tunnel_sock_release(sk0->sk_socket);
+		return PTR_ERR(sk1u);
+	}
+
+	gtp->sk_created = true;
+	gtp->sk0 = sk0;
+	gtp->sk1u = sk1u;
+
+	return 0;
+}
+
 static int gtp_newlink(struct net *src_net, struct net_device *dev,
 		       struct nlattr *tb[], struct nlattr *data[],
 		       struct netlink_ext_ack *extack)
 {
+	unsigned int role = GTP_ROLE_GGSN;
 	struct gtp_dev *gtp;
 	struct gtp_net *gn;
 	int hashsize, err;
 
-	if (!data[IFLA_GTP_FD0] && !data[IFLA_GTP_FD1])
-		return -EINVAL;
-
 	gtp = netdev_priv(dev);
 
 	if (!data[IFLA_GTP_PDP_HASHSIZE]) {
@@ -677,11 +739,23 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
 			hashsize = 1024;
 	}
 
+	if (data[IFLA_GTP_ROLE]) {
+		role = nla_get_u32(data[IFLA_GTP_ROLE]);
+		if (role > GTP_ROLE_SGSN)
+			return -EINVAL;
+	}
+	gtp->role = role;
+
+	gtp->net = src_net;
+
 	err = gtp_hashtable_new(gtp, hashsize);
 	if (err < 0)
 		return err;
 
-	err = gtp_encap_enable(gtp, data);
+	if (data[IFLA_GTP_CREATE_SOCKETS])
+		err = gtp_create_sockets(gtp, data);
+	else
+		err = gtp_encap_enable(gtp, data);
 	if (err < 0)
 		goto out_hashtable;
 
@@ -726,6 +800,7 @@ static const struct nla_policy gtp_policy[IFLA_GTP_MAX + 1] = {
 	[IFLA_GTP_FD1]			= { .type = NLA_U32 },
 	[IFLA_GTP_PDP_HASHSIZE]		= { .type = NLA_U32 },
 	[IFLA_GTP_ROLE]			= { .type = NLA_U32 },
+	[IFLA_GTP_CREATE_SOCKETS]	= { .type = NLA_U8 },
 };
 
 static int gtp_validate(struct nlattr *tb[], struct nlattr *data[],
@@ -848,7 +923,9 @@ static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[])
 {
 	struct sock *sk1u = NULL;
 	struct sock *sk0 = NULL;
-	unsigned int role = GTP_ROLE_GGSN;
+
+	if (!data[IFLA_GTP_FD0] && !data[IFLA_GTP_FD1])
+		return -EINVAL;
 
 	if (data[IFLA_GTP_FD0]) {
 		u32 fd0 = nla_get_u32(data[IFLA_GTP_FD0]);
@@ -868,18 +945,8 @@ static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[])
 		}
 	}
 
-	if (data[IFLA_GTP_ROLE]) {
-		role = nla_get_u32(data[IFLA_GTP_ROLE]);
-		if (role > GTP_ROLE_SGSN) {
-			gtp_encap_disable_sock(sk0);
-			gtp_encap_disable_sock(sk1u);
-			return -EINVAL;
-		}
-	}
-
 	gtp->sk0 = sk0;
 	gtp->sk1u = sk1u;
-	gtp->role = role;
 
 	return 0;
 }
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 6218f93f5c1a..42f3fb097271 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -822,6 +822,7 @@ enum {
 	IFLA_GTP_FD1,
 	IFLA_GTP_PDP_HASHSIZE,
 	IFLA_GTP_ROLE,
+	IFLA_GTP_CREATE_SOCKETS,
 	__IFLA_GTP_MAX,
 };
 #define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1)
-- 
2.31.1


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

end of thread, other threads:[~2022-02-18 15:04 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-18 14:51 [PATCH net-next v6 1/7] gtp: Allow to create GTP device without FDs Marcin Szycik
2022-02-18 15:04 ` Marcin Szycik
  -- strict thread matches above, loose matches on Subject: below --
2022-02-18 14:50 [PATCH net-next v6 0/7] ice: GTP support in switchdev Marcin Szycik
2022-02-18 14:53 ` [PATCH net-next v6 1/7] gtp: Allow to create GTP device without FDs Marcin Szycik

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.