bridge: fdb dumping takes a filter device
[cascardo/linux.git] / net / bridge / br_fdb.c
index b524c36..6edecd1 100644 (file)
@@ -93,7 +93,7 @@ static void fdb_rcu_free(struct rcu_head *head)
 static void fdb_add_hw(struct net_bridge *br, const unsigned char *addr)
 {
        int err;
-       struct net_bridge_port *p, *tmp;
+       struct net_bridge_port *p;
 
        ASSERT_RTNL();
 
@@ -107,11 +107,9 @@ static void fdb_add_hw(struct net_bridge *br, const unsigned char *addr)
 
        return;
 undo:
-       list_for_each_entry(tmp, &br->port_list, list) {
-               if (tmp == p)
-                       break;
-               if (!br_promisc_port(tmp))
-                       dev_uc_del(tmp->dev, addr);
+       list_for_each_entry_continue_reverse(p, &br->port_list, list) {
+               if (!br_promisc_port(p))
+                       dev_uc_del(p->dev, addr);
        }
 }
 
@@ -678,6 +676,7 @@ errout:
 int br_fdb_dump(struct sk_buff *skb,
                struct netlink_callback *cb,
                struct net_device *dev,
+               struct net_device *filter_dev,
                int idx)
 {
        struct net_bridge *br = netdev_priv(dev);
@@ -693,6 +692,10 @@ int br_fdb_dump(struct sk_buff *skb,
                        if (idx < cb->args[0])
                                goto skip;
 
+                       if (filter_dev && (!f->dst || !f->dst->dev ||
+                                          f->dst->dev != filter_dev))
+                               goto skip;
+
                        if (fdb_fill_info(skb, br, f,
                                          NETLINK_CB(cb->skb).portid,
                                          cb->nlh->nlmsg_seq,