mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	net: add fdb generic dump routine
This adds a generic dump routine drivers can call. It
should be sufficient to handle any bridging model that
uses the unicast address list. This should be most SR-IOV
enabled NICs.
v2: return error on nlmsg_put and use -EMSGSIZE instead
    of -ENOMEM this is inline other usages
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									12a9463445
								
							
						
					
					
						commit
						d83b060360
					
				
					 1 changed files with 84 additions and 0 deletions
				
			
		| 
						 | 
					@ -1980,6 +1980,37 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change)
 | 
				
			||||||
		rtnl_set_sk_err(net, RTNLGRP_LINK, err);
 | 
							rtnl_set_sk_err(net, RTNLGRP_LINK, err);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int nlmsg_populate_fdb_fill(struct sk_buff *skb,
 | 
				
			||||||
 | 
									   struct net_device *dev,
 | 
				
			||||||
 | 
									   u8 *addr, u32 pid, u32 seq,
 | 
				
			||||||
 | 
									   int type, unsigned int flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nlmsghdr *nlh;
 | 
				
			||||||
 | 
						struct ndmsg *ndm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), NLM_F_MULTI);
 | 
				
			||||||
 | 
						if (!nlh)
 | 
				
			||||||
 | 
							return -EMSGSIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ndm = nlmsg_data(nlh);
 | 
				
			||||||
 | 
						ndm->ndm_family  = AF_BRIDGE;
 | 
				
			||||||
 | 
						ndm->ndm_pad1	 = 0;
 | 
				
			||||||
 | 
						ndm->ndm_pad2    = 0;
 | 
				
			||||||
 | 
						ndm->ndm_flags	 = flags;
 | 
				
			||||||
 | 
						ndm->ndm_type	 = 0;
 | 
				
			||||||
 | 
						ndm->ndm_ifindex = dev->ifindex;
 | 
				
			||||||
 | 
						ndm->ndm_state   = NUD_PERMANENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr))
 | 
				
			||||||
 | 
							goto nla_put_failure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nlmsg_end(skb, nlh);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nla_put_failure:
 | 
				
			||||||
 | 
						nlmsg_cancel(skb, nlh);
 | 
				
			||||||
 | 
						return -EMSGSIZE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 | 
					static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net *net = sock_net(skb->sk);
 | 
						struct net *net = sock_net(skb->sk);
 | 
				
			||||||
| 
						 | 
					@ -2101,6 +2132,59 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int nlmsg_populate_fdb(struct sk_buff *skb,
 | 
				
			||||||
 | 
								      struct netlink_callback *cb,
 | 
				
			||||||
 | 
								      struct net_device *dev,
 | 
				
			||||||
 | 
								      int *idx,
 | 
				
			||||||
 | 
								      struct netdev_hw_addr_list *list)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct netdev_hw_addr *ha;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
						u32 pid, seq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pid = NETLINK_CB(cb->skb).pid;
 | 
				
			||||||
 | 
						seq = cb->nlh->nlmsg_seq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry(ha, &list->list, list) {
 | 
				
			||||||
 | 
							if (*idx < cb->args[0])
 | 
				
			||||||
 | 
								goto skip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = nlmsg_populate_fdb_fill(skb, dev, ha->addr,
 | 
				
			||||||
 | 
										      pid, seq, 0, NTF_SELF);
 | 
				
			||||||
 | 
							if (err < 0)
 | 
				
			||||||
 | 
								return err;
 | 
				
			||||||
 | 
					skip:
 | 
				
			||||||
 | 
							*idx += 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ndo_dflt_fdb_dump: default netdevice operation to dump an FDB table.
 | 
				
			||||||
 | 
					 * @nlh: netlink message header
 | 
				
			||||||
 | 
					 * @dev: netdevice
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Default netdevice operation to dump the existing unicast address list.
 | 
				
			||||||
 | 
					 * Returns zero on success.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int ndo_dflt_fdb_dump(struct sk_buff *skb,
 | 
				
			||||||
 | 
							      struct netlink_callback *cb,
 | 
				
			||||||
 | 
							      struct net_device *dev,
 | 
				
			||||||
 | 
							      int idx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						netif_addr_lock_bh(dev);
 | 
				
			||||||
 | 
						err = nlmsg_populate_fdb(skb, cb, dev, &idx, &dev->uc);
 | 
				
			||||||
 | 
						if (err)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						nlmsg_populate_fdb(skb, cb, dev, &idx, &dev->mc);
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						netif_addr_unlock_bh(dev);
 | 
				
			||||||
 | 
						return idx;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL(ndo_dflt_fdb_dump);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
 | 
					static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int idx = 0;
 | 
						int idx = 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue