Skip to content

Commit

Permalink
netns: notify netns id events
Browse files Browse the repository at this point in the history
With this patch, netns ids that are created and deleted are advertised into the
group RTNLGRP_NSID.

Because callers of rtnl_net_notifyid() already know the id of the peer, there is
no need to call __peernet2id() in rtnl_net_fill().

Signed-off-by: Nicolas Dichtel <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
NicolasDichtel authored and davem330 committed Apr 7, 2015
1 parent b111e4e commit 9a96345
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 8 deletions.
4 changes: 4 additions & 0 deletions include/uapi/linux/rtnetlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ enum {

RTM_NEWNSID = 88,
#define RTM_NEWNSID RTM_NEWNSID
RTM_DELNSID = 89,
#define RTM_DELNSID RTM_DELNSID
RTM_GETNSID = 90,
#define RTM_GETNSID RTM_GETNSID

Expand Down Expand Up @@ -635,6 +637,8 @@ enum rtnetlink_groups {
#define RTNLGRP_MDB RTNLGRP_MDB
RTNLGRP_MPLS_ROUTE,
#define RTNLGRP_MPLS_ROUTE RTNLGRP_MPLS_ROUTE
RTNLGRP_NSID,
#define RTNLGRP_NSID RTNLGRP_NSID
__RTNLGRP_MAX
};
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
Expand Down
52 changes: 44 additions & 8 deletions net/core/net_namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,11 @@ static void ops_free_list(const struct pernet_operations *ops,
}
}

static void rtnl_net_notifyid(struct net *net, struct net *peer, int cmd,
int id);
static int alloc_netid(struct net *net, struct net *peer, int reqid)
{
int min = 0, max = 0;
int min = 0, max = 0, id;

ASSERT_RTNL();

Expand All @@ -159,7 +161,11 @@ static int alloc_netid(struct net *net, struct net *peer, int reqid)
max = reqid + 1;
}

return idr_alloc(&net->netns_ids, peer, min, max, GFP_KERNEL);
id = idr_alloc(&net->netns_ids, peer, min, max, GFP_KERNEL);
if (id >= 0)
rtnl_net_notifyid(net, peer, RTM_NEWNSID, id);

return id;
}

/* This function is used by idr_for_each(). If net is equal to peer, the
Expand Down Expand Up @@ -359,8 +365,10 @@ static void cleanup_net(struct work_struct *work)
for_each_net(tmp) {
int id = __peernet2id(tmp, net, false);

if (id >= 0)
if (id >= 0) {
rtnl_net_notifyid(tmp, net, RTM_DELNSID, id);
idr_remove(&tmp->netns_ids, id);
}
}
idr_destroy(&net->netns_ids);

Expand Down Expand Up @@ -531,7 +539,8 @@ static int rtnl_net_get_size(void)
}

static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
int cmd, struct net *net, struct net *peer)
int cmd, struct net *net, struct net *peer,
int nsid)
{
struct nlmsghdr *nlh;
struct rtgenmsg *rth;
Expand All @@ -546,9 +555,13 @@ static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
rth = nlmsg_data(nlh);
rth->rtgen_family = AF_UNSPEC;

id = __peernet2id(net, peer, false);
if (id < 0)
id = NETNSA_NSID_NOT_ASSIGNED;
if (nsid >= 0) {
id = nsid;
} else {
id = __peernet2id(net, peer, false);
if (id < 0)
id = NETNSA_NSID_NOT_ASSIGNED;
}
if (nla_put_s32(skb, NETNSA_NSID, id))
goto nla_put_failure;

Expand Down Expand Up @@ -589,7 +602,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh)
}

err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
RTM_GETNSID, net, peer);
RTM_GETNSID, net, peer, -1);
if (err < 0)
goto err_out;

Expand All @@ -603,6 +616,29 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh)
return err;
}

static void rtnl_net_notifyid(struct net *net, struct net *peer, int cmd,
int id)
{
struct sk_buff *msg;
int err = -ENOMEM;

msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL);
if (!msg)
goto out;

err = rtnl_net_fill(msg, 0, 0, 0, cmd, net, peer, id);
if (err < 0)
goto err_out;

rtnl_notify(msg, net, 0, RTNLGRP_NSID, NULL, 0);
return;

err_out:
nlmsg_free(msg);
out:
rtnl_set_sk_err(net, RTNLGRP_NSID, err);
}

static int __init net_ns_init(void)
{
struct net_generic *ng;
Expand Down

0 comments on commit 9a96345

Please sign in to comment.