net: Add support for filtering neigh dump by master device
Add support for filtering neighbor dumps by master device by adding the NDA_MASTER attribute to the dump request. A new netlink flag, NLM_F_DUMP_FILTERED, is added to indicate the kernel supports the request and output is filtered as requested. Signed-off-by: David Ahern <dsa@cumulusnetworks.com> Acked-by: Roopa Prabhu <roopa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									5172393522
								
							
						
					
					
						commit
						21fdd092ac
					
				| @ -54,6 +54,7 @@ struct nlmsghdr { | ||||
| #define NLM_F_ACK		4	/* Reply with ack, with zero or error code */ | ||||
| #define NLM_F_ECHO		8	/* Echo this request 		*/ | ||||
| #define NLM_F_DUMP_INTR		16	/* Dump was inconsistent due to sequence change */ | ||||
| #define NLM_F_DUMP_FILTERED	32	/* Dump was filtered as requested */ | ||||
| 
 | ||||
| /* Modifiers to GET request */ | ||||
| #define NLM_F_ROOT	0x100	/* specify tree	root	*/ | ||||
|  | ||||
| @ -2235,14 +2235,42 @@ static void neigh_update_notify(struct neighbour *neigh) | ||||
| 	__neigh_notify(neigh, RTM_NEWNEIGH, 0); | ||||
| } | ||||
| 
 | ||||
| static bool neigh_master_filtered(struct net_device *dev, int master_idx) | ||||
| { | ||||
| 	struct net_device *master; | ||||
| 
 | ||||
| 	if (!master_idx) | ||||
| 		return false; | ||||
| 
 | ||||
| 	master = netdev_master_upper_dev_get(dev); | ||||
| 	if (!master || master->ifindex != master_idx) | ||||
| 		return true; | ||||
| 
 | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | ||||
| 			    struct netlink_callback *cb) | ||||
| { | ||||
| 	struct net *net = sock_net(skb->sk); | ||||
| 	const struct nlmsghdr *nlh = cb->nlh; | ||||
| 	struct nlattr *tb[NDA_MAX + 1]; | ||||
| 	struct neighbour *n; | ||||
| 	int rc, h, s_h = cb->args[1]; | ||||
| 	int idx, s_idx = idx = cb->args[2]; | ||||
| 	struct neigh_hash_table *nht; | ||||
| 	int filter_master_idx = 0; | ||||
| 	unsigned int flags = NLM_F_MULTI; | ||||
| 	int err; | ||||
| 
 | ||||
| 	err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL); | ||||
| 	if (!err) { | ||||
| 		if (tb[NDA_MASTER]) | ||||
| 			filter_master_idx = nla_get_u32(tb[NDA_MASTER]); | ||||
| 
 | ||||
| 		if (filter_master_idx) | ||||
| 			flags |= NLM_F_DUMP_FILTERED; | ||||
| 	} | ||||
| 
 | ||||
| 	rcu_read_lock_bh(); | ||||
| 	nht = rcu_dereference_bh(tbl->nht); | ||||
| @ -2255,12 +2283,14 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | ||||
| 		     n = rcu_dereference_bh(n->next)) { | ||||
| 			if (!net_eq(dev_net(n->dev), net)) | ||||
| 				continue; | ||||
| 			if (neigh_master_filtered(n->dev, filter_master_idx)) | ||||
| 				continue; | ||||
| 			if (idx < s_idx) | ||||
| 				goto next; | ||||
| 			if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid, | ||||
| 					    cb->nlh->nlmsg_seq, | ||||
| 					    RTM_NEWNEIGH, | ||||
| 					    NLM_F_MULTI) < 0) { | ||||
| 					    flags) < 0) { | ||||
| 				rc = -1; | ||||
| 				goto out; | ||||
| 			} | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user