mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-17 17:24:17 +08:00
gtp: add notification mechanism
Like all other network functions, let's notify gtp context on creation and deletion. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Tested-by: Gabriel Ganne <gabriel.ganne@6wind.com> Acked-by: Harald Welte <laforge@gnumonks.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
44771ea574
commit
50aba46c23
@ -928,8 +928,8 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info)
|
||||
}
|
||||
}
|
||||
|
||||
static int gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk,
|
||||
struct genl_info *info)
|
||||
static struct pdp_ctx *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;
|
||||
@ -956,12 +956,12 @@ static int gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk,
|
||||
|
||||
if (found) {
|
||||
if (info->nlhdr->nlmsg_flags & NLM_F_EXCL)
|
||||
return -EEXIST;
|
||||
return ERR_PTR(-EEXIST);
|
||||
if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE)
|
||||
return -EOPNOTSUPP;
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
if (pctx && pctx_tid)
|
||||
return -EEXIST;
|
||||
return ERR_PTR(-EEXIST);
|
||||
if (!pctx)
|
||||
pctx = pctx_tid;
|
||||
|
||||
@ -974,13 +974,13 @@ static int gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk,
|
||||
netdev_dbg(dev, "GTPv1-U: update tunnel id = %x/%x (pdp %p)\n",
|
||||
pctx->u.v1.i_tei, pctx->u.v1.o_tei, pctx);
|
||||
|
||||
return 0;
|
||||
return pctx;
|
||||
|
||||
}
|
||||
|
||||
pctx = kmalloc(sizeof(*pctx), GFP_ATOMIC);
|
||||
if (pctx == NULL)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
sock_hold(sk);
|
||||
pctx->sk = sk;
|
||||
@ -1018,7 +1018,7 @@ static int gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk,
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return pctx;
|
||||
}
|
||||
|
||||
static void pdp_context_free(struct rcu_head *head)
|
||||
@ -1036,9 +1036,12 @@ static void pdp_context_delete(struct pdp_ctx *pctx)
|
||||
call_rcu(&pctx->rcu_head, pdp_context_free);
|
||||
}
|
||||
|
||||
static int gtp_tunnel_notify(struct pdp_ctx *pctx, u8 cmd);
|
||||
|
||||
static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
unsigned int version;
|
||||
struct pdp_ctx *pctx;
|
||||
struct gtp_dev *gtp;
|
||||
struct sock *sk;
|
||||
int err;
|
||||
@ -1088,7 +1091,13 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
err = gtp_pdp_add(gtp, sk, info);
|
||||
pctx = gtp_pdp_add(gtp, sk, info);
|
||||
if (IS_ERR(pctx)) {
|
||||
err = PTR_ERR(pctx);
|
||||
} else {
|
||||
gtp_tunnel_notify(pctx, GTP_CMD_NEWPDP);
|
||||
err = 0;
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
@ -1159,6 +1168,7 @@ static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info)
|
||||
netdev_dbg(pctx->dev, "GTPv1-U: deleting tunnel id = %x/%x (pdp %p)\n",
|
||||
pctx->u.v1.i_tei, pctx->u.v1.o_tei, pctx);
|
||||
|
||||
gtp_tunnel_notify(pctx, GTP_CMD_DELPDP);
|
||||
pdp_context_delete(pctx);
|
||||
|
||||
out_unlock:
|
||||
@ -1168,6 +1178,14 @@ out_unlock:
|
||||
|
||||
static struct genl_family gtp_genl_family;
|
||||
|
||||
enum gtp_multicast_groups {
|
||||
GTP_GENL_MCGRP,
|
||||
};
|
||||
|
||||
static const struct genl_multicast_group gtp_genl_mcgrps[] = {
|
||||
[GTP_GENL_MCGRP] = { .name = GTP_GENL_MCGRP_NAME },
|
||||
};
|
||||
|
||||
static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq,
|
||||
int flags, u32 type, struct pdp_ctx *pctx)
|
||||
{
|
||||
@ -1204,6 +1222,26 @@ nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int gtp_tunnel_notify(struct pdp_ctx *pctx, u8 cmd)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
int ret;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = gtp_genl_fill_info(msg, 0, 0, 0, cmd, pctx);
|
||||
if (ret < 0) {
|
||||
nlmsg_free(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = genlmsg_multicast_netns(>p_genl_family, dev_net(pctx->dev), msg,
|
||||
0, GTP_GENL_MCGRP, GFP_ATOMIC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gtp_genl_get_pdp(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct pdp_ctx *pctx = NULL;
|
||||
@ -1334,6 +1372,8 @@ static struct genl_family gtp_genl_family __ro_after_init = {
|
||||
.module = THIS_MODULE,
|
||||
.ops = gtp_genl_ops,
|
||||
.n_ops = ARRAY_SIZE(gtp_genl_ops),
|
||||
.mcgrps = gtp_genl_mcgrps,
|
||||
.n_mcgrps = ARRAY_SIZE(gtp_genl_mcgrps),
|
||||
};
|
||||
|
||||
static int __net_init gtp_net_init(struct net *net)
|
||||
|
@ -2,6 +2,8 @@
|
||||
#ifndef _UAPI_LINUX_GTP_H_
|
||||
#define _UAPI_LINUX_GTP_H_
|
||||
|
||||
#define GTP_GENL_MCGRP_NAME "gtp"
|
||||
|
||||
enum gtp_genl_cmds {
|
||||
GTP_CMD_NEWPDP,
|
||||
GTP_CMD_DELPDP,
|
||||
|
Loading…
Reference in New Issue
Block a user