forked from mirrors/linux
		
	netns: notify netns id events
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 <nicolas.dichtel@6wind.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									b111e4e111
								
							
						
					
					
						commit
						9a9634545c
					
				
					 2 changed files with 48 additions and 8 deletions
				
			
		|  | @ -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 | ||||
| 
 | ||||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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(); | ||||
| 
 | ||||
|  | @ -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
 | ||||
|  | @ -359,9 +365,11 @@ 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); | ||||
| 
 | ||||
| 	} | ||||
|  | @ -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; | ||||
|  | @ -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; | ||||
| 
 | ||||
| 	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; | ||||
| 
 | ||||
|  | @ -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; | ||||
| 
 | ||||
|  | @ -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; | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Nicolas Dichtel
						Nicolas Dichtel