struct in_addr          ms_addr_ip4;
        struct in_addr          sgsn_addr_ip4;
 
+       struct sock             *sk;
        struct net_device       *dev;
 
        atomic_t                tx_seq;
        return false;
 }
 
-static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, unsigned int hdrlen,
-                 bool xnet)
+static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, unsigned int hdrlen)
 {
        struct pcpu_sw_netstats *stats;
 
        }
 
        /* Get rid of the GTP + UDP headers. */
-       if (iptunnel_pull_header(skb, hdrlen, skb->protocol, xnet))
+       if (iptunnel_pull_header(skb, hdrlen, skb->protocol,
+                                !net_eq(sock_net(pctx->sk), dev_net(pctx->dev))))
                return -1;
 
        netdev_dbg(pctx->dev, "forwarding packet from GGSN to uplink\n");
 }
 
 /* 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);
                return 1;
        }
 
-       return gtp_rx(pctx, skb, hdrlen, xnet);
+       return gtp_rx(pctx, skb, hdrlen);
 }
 
-static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
-                               bool xnet)
+static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
 {
        unsigned int hdrlen = sizeof(struct udphdr) +
                              sizeof(struct gtp1_header);
                return 1;
        }
 
-       return gtp_rx(pctx, skb, hdrlen, xnet);
+       return gtp_rx(pctx, skb, hdrlen);
 }
 
 static void gtp_encap_destroy(struct sock *sk)
 {
        struct gtp_dev *gtp;
        int ret = 0;
-       bool xnet;
 
        gtp = rcu_dereference_sk_user_data(sk);
        if (!gtp)
 
        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. */
        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;
        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)
        struct rtable *rt;
        struct flowi4 fl4;
        struct iphdr *iph;
-       struct sock *sk;
        __be16 df;
        int mtu;
 
        }
        netdev_dbg(dev, "found PDP context %p\n", pctx);
 
-       switch (pctx->gtp_version) {
-       case GTP_V0:
-               if (gtp->sk0)
-                       sk = gtp->sk0;
-               else
-                       sk = NULL;
-               break;
-       case GTP_V1:
-               if (gtp->sk1u)
-                       sk = gtp->sk1u;
-               else
-                       sk = NULL;
-               break;
-       default:
-               return -ENOENT;
-       }
-
-       if (!sk) {
-               netdev_dbg(dev, "no userspace socket is available, skip\n");
-               return -ENOENT;
-       }
-
-       rt = ip4_route_output_gtp(sock_net(sk), &fl4, gtp->sk0,
-                                 pctx->sgsn_addr_ip4.s_addr);
+       rt = ip4_route_output_gtp(&fl4, pctx->sk, pctx->sgsn_addr_ip4.s_addr);
        if (IS_ERR(rt)) {
                netdev_dbg(dev, "no route to SSGN %pI4\n",
                           &pctx->sgsn_addr_ip4.s_addr);
                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;
        }
 }
 
-static int ipv4_pdp_add(struct gtp_dev *gtp, struct genl_info *info)
+static int ipv4_pdp_add(struct gtp_dev *gtp, struct sock *sk,
+                       struct genl_info *info)
 {
        struct net_device *dev = gtp->dev;
        u32 hash_ms, hash_tid = 0;
        if (pctx == NULL)
                return -ENOMEM;
 
+       sock_hold(sk);
+       pctx->sk = sk;
        pctx->dev = gtp->dev;
        ipv4_pdp_fill(pctx, info);
        atomic_set(&pctx->tx_seq, 0);
        return 0;
 }
 
+static void pdp_context_free(struct rcu_head *head)
+{
+       struct pdp_ctx *pctx = container_of(head, struct pdp_ctx, rcu_head);
+
+       sock_put(pctx->sk);
+       kfree(pctx);
+}
+
 static void pdp_context_delete(struct pdp_ctx *pctx)
 {
        hlist_del_rcu(&pctx->hlist_tid);
        hlist_del_rcu(&pctx->hlist_addr);
-       kfree_rcu(pctx, rcu_head);
+       call_rcu(&pctx->rcu_head, pdp_context_free);
 }
 
 static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
 {
+       unsigned int version;
        struct gtp_dev *gtp;
+       struct sock *sk;
        int err;
 
        if (!info->attrs[GTPA_VERSION] ||
            !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])
                goto out_unlock;
        }
 
-       err = ipv4_pdp_add(gtp, info);
+       if (version == GTP_V0)
+               sk = gtp->sk0;
+       else if (version == GTP_V1)
+               sk = gtp->sk1u;
+       else
+               sk = NULL;
+
+       if (!sk) {
+               err = -ENODEV;
+               goto out_unlock;
+       }
+
+       err = ipv4_pdp_add(gtp, sk, info);
 
 out_unlock:
        rcu_read_unlock();