Message ID | 1401023042-6902-1-git-send-email-jhs@emojatatu.com |
---|---|
State | Superseded, archived |
Delegated to: | David Miller |
Headers | show |
Grrr... Just noticed a debug statement in there - will resend. cheers, jamal On 05/25/14 09:04, Jamal Hadi Salim wrote: > From: Jamal Hadi Salim <jhs@mojatatu.com> > > This patch allows something equivalent to > "brctl showmacs <bridge device>" with iproute2 > syntax "bridge fdb show br <bridge device>" > Filtering by bridge is done in the kernel. > The current setup doesnt scale when you have many bridges each > with large fdbs (preliminary fix with the kernel patch). > > Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com> > --- > net/core/rtnetlink.c | 50 +++++++++++++++++++++++++++++++++++--------------- > 1 file changed, 35 insertions(+), 15 deletions(-) > > diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c > index f31268d..a605742 100644 > --- a/net/core/rtnetlink.c > +++ b/net/core/rtnetlink.c > @@ -2509,26 +2509,46 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) > { > int idx = 0; > struct net *net = sock_net(skb->sk); > + const struct net_device_ops *ops; > struct net_device *dev; > + struct ndmsg *ndm; > > - rcu_read_lock(); > - for_each_netdev_rcu(net, dev) { > - if (dev->priv_flags & IFF_BRIDGE_PORT) { > - struct net_device *br_dev; > - const struct net_device_ops *ops; > - > - br_dev = netdev_master_upper_dev_get(dev); > - ops = br_dev->netdev_ops; > - if (ops->ndo_fdb_dump) > - idx = ops->ndo_fdb_dump(skb, cb, dev, idx); > + ndm = nlmsg_data(cb->nlh); > + if (ndm->ndm_ifindex) { > + dev = __dev_get_by_index(net, ndm->ndm_ifindex); > + if (dev == NULL) { > + pr_info("PF_BRIDGE: RTM_GETNEIGH with unknown ifindex\n"); > + return -ENODEV; > } > > - if (dev->netdev_ops->ndo_fdb_dump) > - idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, idx); > - else > - idx = ndo_dflt_fdb_dump(skb, cb, dev, idx); > + printk("Requested for bridge <%s>\n", dev->name); > + ops = dev->netdev_ops; > + if (ops->ndo_fdb_dump) { > + idx = ops->ndo_fdb_dump(skb, cb, dev, idx); > + } else { > + pr_info("PF_BRIDGE: RTM_GETNEIGH %s no dumper\n", > + dev->name); > + return -EINVAL; > + } > + } else { > + rcu_read_lock(); > + for_each_netdev_rcu(net, dev) { > + if (dev->priv_flags & IFF_BRIDGE_PORT) { > + struct net_device *br_dev; > + br_dev = netdev_master_upper_dev_get(dev); > + ops = br_dev->netdev_ops; > + if (ops->ndo_fdb_dump) > + idx = ops->ndo_fdb_dump(skb, cb, dev, idx); > + } > + > + if (dev->netdev_ops->ndo_fdb_dump) > + idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, > + idx); > + else > + idx = ndo_dflt_fdb_dump(skb, cb, dev, idx); > + } > + rcu_read_unlock(); > } > - rcu_read_unlock(); > > cb->args[0] = idx; > return skb->len; > -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index f31268d..a605742 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -2509,26 +2509,46 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) { int idx = 0; struct net *net = sock_net(skb->sk); + const struct net_device_ops *ops; struct net_device *dev; + struct ndmsg *ndm; - rcu_read_lock(); - for_each_netdev_rcu(net, dev) { - if (dev->priv_flags & IFF_BRIDGE_PORT) { - struct net_device *br_dev; - const struct net_device_ops *ops; - - br_dev = netdev_master_upper_dev_get(dev); - ops = br_dev->netdev_ops; - if (ops->ndo_fdb_dump) - idx = ops->ndo_fdb_dump(skb, cb, dev, idx); + ndm = nlmsg_data(cb->nlh); + if (ndm->ndm_ifindex) { + dev = __dev_get_by_index(net, ndm->ndm_ifindex); + if (dev == NULL) { + pr_info("PF_BRIDGE: RTM_GETNEIGH with unknown ifindex\n"); + return -ENODEV; } - if (dev->netdev_ops->ndo_fdb_dump) - idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, idx); - else - idx = ndo_dflt_fdb_dump(skb, cb, dev, idx); + printk("Requested for bridge <%s>\n", dev->name); + ops = dev->netdev_ops; + if (ops->ndo_fdb_dump) { + idx = ops->ndo_fdb_dump(skb, cb, dev, idx); + } else { + pr_info("PF_BRIDGE: RTM_GETNEIGH %s no dumper\n", + dev->name); + return -EINVAL; + } + } else { + rcu_read_lock(); + for_each_netdev_rcu(net, dev) { + if (dev->priv_flags & IFF_BRIDGE_PORT) { + struct net_device *br_dev; + br_dev = netdev_master_upper_dev_get(dev); + ops = br_dev->netdev_ops; + if (ops->ndo_fdb_dump) + idx = ops->ndo_fdb_dump(skb, cb, dev, idx); + } + + if (dev->netdev_ops->ndo_fdb_dump) + idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, + idx); + else + idx = ndo_dflt_fdb_dump(skb, cb, dev, idx); + } + rcu_read_unlock(); } - rcu_read_unlock(); cb->args[0] = idx; return skb->len;