Skip to content

Commit 5e6d243

Browse files
jhsmtdavem330
authored andcommitted
bridge: netlink dump interface at par with brctl
Actually better than brctl showmacs because we can filter by bridge port in the kernel. The current bridge netlink interface doesnt scale when you have many bridges each with large fdbs or even bridges with many bridge ports And now for the science non-fiction novel you have all been waiting for.. //lets see what bridge ports we have root@moja-1:/configs/may30-iprt/bridge# ./bridge link show 8: eth1 state DOWN : <BROADCAST,MULTICAST> mtu 1500 master br0 state disabled priority 32 cost 19 17: sw1-p1 state DOWN : <BROADCAST,NOARP> mtu 1500 master br0 state disabled priority 32 cost 100 // show all.. root@moja-1:/configs/may30-iprt/bridge# ./bridge fdb show 33:33:00:00:00:01 dev bond0 self permanent 33:33:00:00:00:01 dev dummy0 self permanent 33:33:00:00:00:01 dev ifb0 self permanent 33:33:00:00:00:01 dev ifb1 self permanent 33:33:00:00:00:01 dev eth0 self permanent 01:00:5e:00:00:01 dev eth0 self permanent 33:33:ff:22:01:01 dev eth0 self permanent 02:00:00:12:01:02 dev eth1 vlan 0 master br0 permanent 00:17:42:8a:b4:05 dev eth1 vlan 0 master br0 permanent 00:17:42:8a:b4:07 dev eth1 self permanent 33:33:00:00:00:01 dev eth1 self permanent 33:33:00:00:00:01 dev gretap0 self permanent da:ac:46:27:d9:53 dev sw1-p1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent //filter by bridge root@moja-1:/configs/may30-iprt/bridge# ./bridge fdb show br br0 02:00:00:12:01:02 dev eth1 vlan 0 master br0 permanent 00:17:42:8a:b4:05 dev eth1 vlan 0 master br0 permanent 00:17:42:8a:b4:07 dev eth1 self permanent 33:33:00:00:00:01 dev eth1 self permanent da:ac:46:27:d9:53 dev sw1-p1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent // bridge sw1 has no ports attached.. root@moja-1:/configs/may30-iprt/bridge# ./bridge fdb show br sw1 //filter by port root@moja-1:/configs/may30-iprt/bridge# ./bridge fdb show brport eth1 02:00:00:12:01:02 vlan 0 master br0 permanent 00:17:42:8a:b4:05 vlan 0 master br0 permanent 00:17:42:8a:b4:07 self permanent 33:33:00:00:00:01 self permanent // filter by port + bridge root@moja-1:/configs/may30-iprt/bridge# ./bridge fdb show br br0 brport sw1-p1 da:ac:46:27:d9:53 vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent // for shits and giggles (as they say in New Brunswick), lets // change the mac that br0 uses // Note: a magical fdb entry with no brport is added ... root@moja-1:/configs/may30-iprt/bridge# ip link set dev br0 address 02:00:00:12:01:04 // lets see if we can see the unicorn .. root@moja-1:/configs/may30-iprt/bridge# ./bridge fdb show 33:33:00:00:00:01 dev bond0 self permanent 33:33:00:00:00:01 dev dummy0 self permanent 33:33:00:00:00:01 dev ifb0 self permanent 33:33:00:00:00:01 dev ifb1 self permanent 33:33:00:00:00:01 dev eth0 self permanent 01:00:5e:00:00:01 dev eth0 self permanent 33:33:ff:22:01:01 dev eth0 self permanent 02:00:00:12:01:02 dev eth1 vlan 0 master br0 permanent 00:17:42:8a:b4:05 dev eth1 vlan 0 master br0 permanent 00:17:42:8a:b4:07 dev eth1 self permanent 33:33:00:00:00:01 dev eth1 self permanent 33:33:00:00:00:01 dev gretap0 self permanent 02:00:00:12:01:04 dev br0 vlan 0 master br0 permanent <=== there it is da:ac:46:27:d9:53 dev sw1-p1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent //can we see it if we filter by bridge? root@moja-1:/configs/may30-iprt/bridge# ./bridge fdb show br br0 02:00:00:12:01:02 dev eth1 vlan 0 master br0 permanent 00:17:42:8a:b4:05 dev eth1 vlan 0 master br0 permanent 00:17:42:8a:b4:07 dev eth1 self permanent 33:33:00:00:00:01 dev eth1 self permanent 02:00:00:12:01:04 dev br0 vlan 0 master br0 permanent <=== there it is da:ac:46:27:d9:53 dev sw1-p1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent Signed-off-by: Jamal Hadi Salim <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5d5eacb commit 5e6d243

File tree

2 files changed

+70
-19
lines changed

2 files changed

+70
-19
lines changed

net/bridge/br_fdb.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -692,9 +692,18 @@ int br_fdb_dump(struct sk_buff *skb,
692692
if (idx < cb->args[0])
693693
goto skip;
694694

695-
if (filter_dev && (!f->dst || !f->dst->dev ||
696-
f->dst->dev != filter_dev))
697-
goto skip;
695+
if (filter_dev &&
696+
(!f->dst || f->dst->dev != filter_dev)) {
697+
if (filter_dev != dev)
698+
goto skip;
699+
/* !f->dst is a speacial case for bridge
700+
* It means the MAC belongs to the bridge
701+
* Therefore need a little more filtering
702+
* we only want to dump the !f->dst case
703+
*/
704+
if (f->dst)
705+
goto skip;
706+
}
698707

699708
if (fdb_fill_info(skb, br, f,
700709
NETLINK_CB(cb->skb).portid,

net/core/rtnetlink.c

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2535,30 +2535,72 @@ EXPORT_SYMBOL(ndo_dflt_fdb_dump);
25352535

25362536
static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
25372537
{
2538-
int idx = 0;
2539-
struct net *net = sock_net(skb->sk);
25402538
struct net_device *dev;
2539+
struct nlattr *tb[IFLA_MAX+1];
2540+
struct net_device *bdev = NULL;
2541+
struct net_device *br_dev = NULL;
2542+
const struct net_device_ops *ops = NULL;
2543+
const struct net_device_ops *cops = NULL;
2544+
struct ifinfomsg *ifm = nlmsg_data(cb->nlh);
2545+
struct net *net = sock_net(skb->sk);
2546+
int brport_idx = 0;
2547+
int br_idx = 0;
2548+
int idx = 0;
2549+
2550+
if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
2551+
ifla_policy) == 0) {
2552+
if (tb[IFLA_MASTER])
2553+
br_idx = nla_get_u32(tb[IFLA_MASTER]);
2554+
}
2555+
2556+
brport_idx = ifm->ifi_index;
2557+
2558+
if (br_idx) {
2559+
br_dev = __dev_get_by_index(net, br_idx);
2560+
if (!br_dev)
2561+
return -ENODEV;
2562+
2563+
ops = br_dev->netdev_ops;
2564+
bdev = br_dev;
2565+
}
2566+
2567+
for_each_netdev(net, dev) {
2568+
if (brport_idx && (dev->ifindex != brport_idx))
2569+
continue;
2570+
2571+
if (!br_idx) { /* user did not specify a specific bridge */
2572+
if (dev->priv_flags & IFF_BRIDGE_PORT) {
2573+
br_dev = netdev_master_upper_dev_get(dev);
2574+
cops = br_dev->netdev_ops;
2575+
}
2576+
2577+
bdev = dev;
2578+
} else {
2579+
if (dev != br_dev &&
2580+
!(dev->priv_flags & IFF_BRIDGE_PORT))
2581+
continue;
2582+
2583+
if (br_dev != netdev_master_upper_dev_get(dev) &&
2584+
!(dev->priv_flags & IFF_EBRIDGE))
2585+
continue;
2586+
2587+
bdev = br_dev;
2588+
cops = ops;
2589+
}
25412590

2542-
rcu_read_lock();
2543-
for_each_netdev_rcu(net, dev) {
25442591
if (dev->priv_flags & IFF_BRIDGE_PORT) {
2545-
struct net_device *br_dev;
2546-
const struct net_device_ops *ops;
2547-
2548-
br_dev = netdev_master_upper_dev_get(dev);
2549-
ops = br_dev->netdev_ops;
2550-
if (ops->ndo_fdb_dump)
2551-
idx = ops->ndo_fdb_dump(skb, cb, dev, NULL,
2552-
idx);
2592+
if (cops && cops->ndo_fdb_dump)
2593+
idx = cops->ndo_fdb_dump(skb, cb, br_dev, dev,
2594+
idx);
25532595
}
25542596

2597+
idx = ndo_dflt_fdb_dump(skb, cb, dev, NULL, idx);
25552598
if (dev->netdev_ops->ndo_fdb_dump)
2556-
idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, NULL,
2599+
idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, bdev, dev,
25572600
idx);
2558-
else
2559-
idx = ndo_dflt_fdb_dump(skb, cb, dev, NULL, idx);
2601+
2602+
cops = NULL;
25602603
}
2561-
rcu_read_unlock();
25622604

25632605
cb->args[0] = idx;
25642606
return skb->len;

0 commit comments

Comments
 (0)