}
 }
 
-static int ipv4_pdp_add(struct gtp_dev *gtp, struct sock *sk,
-                       struct genl_info *info)
+static int gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk,
+                      struct genl_info *info)
 {
+       struct pdp_ctx *pctx, *pctx_tid = NULL;
        struct net_device *dev = gtp->dev;
        u32 hash_ms, hash_tid = 0;
-       struct pdp_ctx *pctx;
+       unsigned int version;
        bool found = false;
        __be32 ms_addr;
 
        ms_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]);
        hash_ms = ipv4_hashfn(ms_addr) % gtp->hash_size;
+       version = nla_get_u32(info->attrs[GTPA_VERSION]);
 
-       hlist_for_each_entry_rcu(pctx, >p->addr_hash[hash_ms], hlist_addr) {
-               if (pctx->ms_addr_ip4.s_addr == ms_addr) {
-                       found = true;
-                       break;
-               }
-       }
+       pctx = ipv4_pdp_find(gtp, ms_addr);
+       if (pctx)
+               found = true;
+       if (version == GTP_V0)
+               pctx_tid = gtp0_pdp_find(gtp,
+                                        nla_get_u64(info->attrs[GTPA_TID]));
+       else if (version == GTP_V1)
+               pctx_tid = gtp1_pdp_find(gtp,
+                                        nla_get_u32(info->attrs[GTPA_I_TEI]));
+       if (pctx_tid)
+               found = true;
 
        if (found) {
                if (info->nlhdr->nlmsg_flags & NLM_F_EXCL)
                if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE)
                        return -EOPNOTSUPP;
 
+               if (pctx && pctx_tid)
+                       return -EEXIST;
+               if (!pctx)
+                       pctx = pctx_tid;
+
                ipv4_pdp_fill(pctx, info);
 
                if (pctx->gtp_version == GTP_V0)
                goto out_unlock;
        }
 
-       err = ipv4_pdp_add(gtp, sk, info);
+       err = gtp_pdp_add(gtp, sk, info);
 
 out_unlock:
        rcu_read_unlock();