Skip to content

Commit 1e3a3ab

Browse files
Andreas Schultzdavem330
Andreas Schultz
authored andcommitted
gtp: make GTP sockets in gtp_newlink optional
Having both GTPv0-U and GTPv1-U is not always desirable. Fallback from GTPv1-U to GTPv0-U was depreciated from 3GPP Rel-8 onwards. Post Rel-8 implementation are discuraged from listening on the v0 port (see 3GPP TS 29.281, Sect. 1). A future change will completely decouple the sockets from the network device. Till then, at least one of the sockets needs to be specified (either v0 or v1), the other is optional. Signed-off-by: Andreas Schultz <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 17886c4 commit 1e3a3ab

File tree

1 file changed

+75
-67
lines changed

1 file changed

+75
-67
lines changed

drivers/net/gtp.c

Lines changed: 75 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -259,30 +259,30 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
259259
return iptunnel_pull_header(skb, hdrlen, skb->protocol, xnet);
260260
}
261261

262-
static void gtp_encap_disable(struct gtp_dev *gtp)
262+
static void gtp_encap_destroy(struct sock *sk)
263263
{
264-
if (gtp->sk0) {
265-
udp_sk(gtp->sk0)->encap_type = 0;
266-
rcu_assign_sk_user_data(gtp->sk0, NULL);
267-
sock_put(gtp->sk0);
268-
}
269-
if (gtp->sk1u) {
270-
udp_sk(gtp->sk1u)->encap_type = 0;
271-
rcu_assign_sk_user_data(gtp->sk1u, NULL);
272-
sock_put(gtp->sk1u);
273-
}
264+
struct gtp_dev *gtp;
274265

275-
gtp->sk0 = NULL;
276-
gtp->sk1u = NULL;
266+
gtp = rcu_dereference_sk_user_data(sk);
267+
if (gtp) {
268+
udp_sk(sk)->encap_type = 0;
269+
rcu_assign_sk_user_data(sk, NULL);
270+
sock_put(sk);
271+
}
277272
}
278273

279-
static void gtp_encap_destroy(struct sock *sk)
274+
static void gtp_encap_disable_sock(struct sock *sk)
280275
{
281-
struct gtp_dev *gtp;
276+
if (!sk)
277+
return;
282278

283-
gtp = rcu_dereference_sk_user_data(sk);
284-
if (gtp)
285-
gtp_encap_disable(gtp);
279+
gtp_encap_destroy(sk);
280+
}
281+
282+
static void gtp_encap_disable(struct gtp_dev *gtp)
283+
{
284+
gtp_encap_disable_sock(gtp->sk0);
285+
gtp_encap_disable_sock(gtp->sk1u);
286286
}
287287

288288
/* UDP encapsulation receive handler. See net/ipv4/udp.c.
@@ -642,27 +642,23 @@ static void gtp_link_setup(struct net_device *dev)
642642

643643
static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize);
644644
static void gtp_hashtable_free(struct gtp_dev *gtp);
645-
static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
646-
int fd_gtp0, int fd_gtp1);
645+
static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[]);
647646

648647
static int gtp_newlink(struct net *src_net, struct net_device *dev,
649648
struct nlattr *tb[], struct nlattr *data[])
650649
{
651-
int hashsize, err, fd0, fd1;
652650
struct gtp_dev *gtp;
653651
struct gtp_net *gn;
652+
int hashsize, err;
654653

655-
if (!data[IFLA_GTP_FD0] || !data[IFLA_GTP_FD1])
654+
if (!data[IFLA_GTP_FD0] && !data[IFLA_GTP_FD1])
656655
return -EINVAL;
657656

658657
gtp = netdev_priv(dev);
659658

660-
fd0 = nla_get_u32(data[IFLA_GTP_FD0]);
661-
fd1 = nla_get_u32(data[IFLA_GTP_FD1]);
662-
663-
err = gtp_encap_enable(dev, gtp, fd0, fd1);
659+
err = gtp_encap_enable(gtp, data);
664660
if (err < 0)
665-
goto out_err;
661+
return err;
666662

667663
if (!data[IFLA_GTP_PDP_HASHSIZE])
668664
hashsize = 1024;
@@ -690,7 +686,6 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
690686
gtp_hashtable_free(gtp);
691687
out_encap:
692688
gtp_encap_disable(gtp);
693-
out_err:
694689
return err;
695690
}
696691

@@ -805,63 +800,76 @@ static void gtp_hashtable_free(struct gtp_dev *gtp)
805800
kfree(gtp->tid_hash);
806801
}
807802

808-
static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
809-
int fd_gtp0, int fd_gtp1)
803+
static struct sock *gtp_encap_enable_socket(int fd, int type,
804+
struct gtp_dev *gtp)
810805
{
811806
struct udp_tunnel_sock_cfg tuncfg = {NULL};
812-
struct socket *sock0, *sock1u;
807+
struct socket *sock;
808+
struct sock *sk;
813809
int err;
814810

815-
netdev_dbg(dev, "enable gtp on %d, %d\n", fd_gtp0, fd_gtp1);
811+
pr_debug("enable gtp on %d, %d\n", fd, type);
816812

817-
sock0 = sockfd_lookup(fd_gtp0, &err);
818-
if (sock0 == NULL) {
819-
netdev_dbg(dev, "socket fd=%d not found (gtp0)\n", fd_gtp0);
820-
return -ENOENT;
813+
sock = sockfd_lookup(fd, &err);
814+
if (!sock) {
815+
pr_debug("gtp socket fd=%d not found\n", fd);
816+
return NULL;
821817
}
822818

823-
if (sock0->sk->sk_protocol != IPPROTO_UDP) {
824-
netdev_dbg(dev, "socket fd=%d not UDP\n", fd_gtp0);
825-
err = -EINVAL;
826-
goto err1;
819+
if (sock->sk->sk_protocol != IPPROTO_UDP) {
820+
pr_debug("socket fd=%d not UDP\n", fd);
821+
sk = ERR_PTR(-EINVAL);
822+
goto out_sock;
827823
}
828824

829-
sock1u = sockfd_lookup(fd_gtp1, &err);
830-
if (sock1u == NULL) {
831-
netdev_dbg(dev, "socket fd=%d not found (gtp1u)\n", fd_gtp1);
832-
err = -ENOENT;
833-
goto err1;
834-
}
835-
836-
if (sock1u->sk->sk_protocol != IPPROTO_UDP) {
837-
netdev_dbg(dev, "socket fd=%d not UDP\n", fd_gtp1);
838-
err = -EINVAL;
839-
goto err2;
825+
if (rcu_dereference_sk_user_data(sock->sk)) {
826+
sk = ERR_PTR(-EBUSY);
827+
goto out_sock;
840828
}
841829

842-
netdev_dbg(dev, "enable gtp on %p, %p\n", sock0, sock1u);
843-
844-
sock_hold(sock0->sk);
845-
gtp->sk0 = sock0->sk;
846-
sock_hold(sock1u->sk);
847-
gtp->sk1u = sock1u->sk;
830+
sk = sock->sk;
831+
sock_hold(sk);
848832

849833
tuncfg.sk_user_data = gtp;
834+
tuncfg.encap_type = type;
850835
tuncfg.encap_rcv = gtp_encap_recv;
851836
tuncfg.encap_destroy = gtp_encap_destroy;
852837

853-
tuncfg.encap_type = UDP_ENCAP_GTP0;
854-
setup_udp_tunnel_sock(sock_net(gtp->sk0), sock0, &tuncfg);
838+
setup_udp_tunnel_sock(sock_net(sock->sk), sock, &tuncfg);
855839

856-
tuncfg.encap_type = UDP_ENCAP_GTP1U;
857-
setup_udp_tunnel_sock(sock_net(gtp->sk1u), sock1u, &tuncfg);
840+
out_sock:
841+
sockfd_put(sock);
842+
return sk;
843+
}
858844

859-
err = 0;
860-
err2:
861-
sockfd_put(sock1u);
862-
err1:
863-
sockfd_put(sock0);
864-
return err;
845+
static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[])
846+
{
847+
struct sock *sk1u = NULL;
848+
struct sock *sk0 = NULL;
849+
850+
if (data[IFLA_GTP_FD0]) {
851+
u32 fd0 = nla_get_u32(data[IFLA_GTP_FD0]);
852+
853+
sk0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, gtp);
854+
if (IS_ERR(sk0))
855+
return PTR_ERR(sk0);
856+
}
857+
858+
if (data[IFLA_GTP_FD1]) {
859+
u32 fd1 = nla_get_u32(data[IFLA_GTP_FD1]);
860+
861+
sk1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp);
862+
if (IS_ERR(sk1u)) {
863+
if (sk0)
864+
gtp_encap_disable_sock(sk0);
865+
return PTR_ERR(sk1u);
866+
}
867+
}
868+
869+
gtp->sk0 = sk0;
870+
gtp->sk1u = sk1u;
871+
872+
return 0;
865873
}
866874

867875
static struct net_device *gtp_find_dev(struct net *net, int ifindex)

0 commit comments

Comments
 (0)