Commit d83b0603 authored by John Fastabend's avatar John Fastabend Committed by David S. Miller

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: default avatarJohn Fastabend <john.r.fastabend@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 12a94634
...@@ -1980,6 +1980,37 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change) ...@@ -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) ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment