diff options
author | John Fastabend <john.r.fastabend@intel.com> | 2012-04-15 02:44:08 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-04-15 13:06:04 -0400 |
commit | d83b060360485454fcd6870340ec01d6f96f2295 (patch) | |
tree | 585401410d99166000ebfe0aceedd426edb3622d /net | |
parent | 12a94634453c61fd9a11c4702002e3db6d4feb70 (diff) |
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/rtnetlink.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index b348b7fbf53a..e8488c7b092c 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -1980,6 +1980,37 @@ errout: | |||
1980 | rtnl_set_sk_err(net, RTNLGRP_LINK, err); | 1980 | rtnl_set_sk_err(net, RTNLGRP_LINK, err); |
1981 | } | 1981 | } |
1982 | 1982 | ||
1983 | static int nlmsg_populate_fdb_fill(struct sk_buff *skb, | ||
1984 | struct net_device *dev, | ||
1985 | u8 *addr, u32 pid, u32 seq, | ||
1986 | int type, unsigned int flags) | ||
1987 | { | ||
1988 | struct nlmsghdr *nlh; | ||
1989 | struct ndmsg *ndm; | ||
1990 | |||
1991 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), NLM_F_MULTI); | ||
1992 | if (!nlh) | ||
1993 | return -EMSGSIZE; | ||
1994 | |||
1995 | ndm = nlmsg_data(nlh); | ||
1996 | ndm->ndm_family = AF_BRIDGE; | ||
1997 | ndm->ndm_pad1 = 0; | ||
1998 | ndm->ndm_pad2 = 0; | ||
1999 | ndm->ndm_flags = flags; | ||
2000 | ndm->ndm_type = 0; | ||
2001 | ndm->ndm_ifindex = dev->ifindex; | ||
2002 | ndm->ndm_state = NUD_PERMANENT; | ||
2003 | |||
2004 | if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr)) | ||
2005 | goto nla_put_failure; | ||
2006 | |||
2007 | return nlmsg_end(skb, nlh); | ||
2008 | |||
2009 | nla_put_failure: | ||
2010 | nlmsg_cancel(skb, nlh); | ||
2011 | return -EMSGSIZE; | ||
2012 | } | ||
2013 | |||
1983 | static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 2014 | static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
1984 | { | 2015 | { |
1985 | struct net *net = sock_net(skb->sk); | 2016 | struct net *net = sock_net(skb->sk); |
@@ -2101,6 +2132,59 @@ out: | |||
2101 | return err; | 2132 | return err; |
2102 | } | 2133 | } |
2103 | 2134 | ||
2135 | static int nlmsg_populate_fdb(struct sk_buff *skb, | ||
2136 | struct netlink_callback *cb, | ||
2137 | struct net_device *dev, | ||
2138 | int *idx, | ||
2139 | struct netdev_hw_addr_list *list) | ||
2140 | { | ||
2141 | struct netdev_hw_addr *ha; | ||
2142 | int err; | ||
2143 | u32 pid, seq; | ||
2144 | |||
2145 | pid = NETLINK_CB(cb->skb).pid; | ||
2146 | seq = cb->nlh->nlmsg_seq; | ||
2147 | |||
2148 | list_for_each_entry(ha, &list->list, list) { | ||
2149 | if (*idx < cb->args[0]) | ||
2150 | goto skip; | ||
2151 | |||
2152 | err = nlmsg_populate_fdb_fill(skb, dev, ha->addr, | ||
2153 | pid, seq, 0, NTF_SELF); | ||
2154 | if (err < 0) | ||
2155 | return err; | ||
2156 | skip: | ||
2157 | *idx += 1; | ||
2158 | } | ||
2159 | return 0; | ||
2160 | } | ||
2161 | |||
2162 | /** | ||
2163 | * ndo_dflt_fdb_dump: default netdevice operation to dump an FDB table. | ||
2164 | * @nlh: netlink message header | ||
2165 | * @dev: netdevice | ||
2166 | * | ||
2167 | * Default netdevice operation to dump the existing unicast address list. | ||
2168 | * Returns zero on success. | ||
2169 | */ | ||
2170 | int ndo_dflt_fdb_dump(struct sk_buff *skb, | ||
2171 | struct netlink_callback *cb, | ||
2172 | struct net_device *dev, | ||
2173 | int idx) | ||
2174 | { | ||
2175 | int err; | ||
2176 | |||
2177 | netif_addr_lock_bh(dev); | ||
2178 | err = nlmsg_populate_fdb(skb, cb, dev, &idx, &dev->uc); | ||
2179 | if (err) | ||
2180 | goto out; | ||
2181 | nlmsg_populate_fdb(skb, cb, dev, &idx, &dev->mc); | ||
2182 | out: | ||
2183 | netif_addr_unlock_bh(dev); | ||
2184 | return idx; | ||
2185 | } | ||
2186 | EXPORT_SYMBOL(ndo_dflt_fdb_dump); | ||
2187 | |||
2104 | static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) | 2188 | static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) |
2105 | { | 2189 | { |
2106 | int idx = 0; | 2190 | int idx = 0; |