bridge: fdb dumping takes a filter device
authorJamal Hadi Salim <jhs@mojatatu.com>
Thu, 10 Jul 2014 11:01:58 +0000 (07:01 -0400)
committerDavid S. Miller <davem@davemloft.net>
Thu, 10 Jul 2014 19:37:33 +0000 (12:37 -0700)
Dumping a bridge fdb dumps every fdb entry
held. With this change we are going to filter
on selected bridge port.

Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/vxlan.c
include/linux/netdevice.h
include/linux/rtnetlink.h
net/bridge/br_fdb.c
net/bridge/br_private.h
net/core/rtnetlink.c

index e49352d..2899f78 100644 (file)
@@ -7095,13 +7095,14 @@ static int i40e_ndo_fdb_del(struct ndmsg *ndm,
 static int i40e_ndo_fdb_dump(struct sk_buff *skb,
                             struct netlink_callback *cb,
                             struct net_device *dev,
+                            struct net_device *filter_dev,
                             int idx)
 {
        struct i40e_netdev_priv *np = netdev_priv(dev);
        struct i40e_pf *pf = np->vsi->back;
 
        if (pf->flags & I40E_FLAG_SRIOV_ENABLED)
-               idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
+               idx = ndo_dflt_fdb_dump(skb, cb, dev, filter_dev, idx);
 
        return idx;
 }
index f8de2ae..0fdbcc8 100644 (file)
@@ -427,16 +427,17 @@ static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 }
 
 static int qlcnic_fdb_dump(struct sk_buff *skb, struct netlink_callback *ncb,
-                       struct net_device *netdev, int idx)
+                       struct net_device *netdev,
+                       struct net_device *filter_dev, int idx)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
 
        if (!adapter->fdb_mac_learn)
-               return ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
+               return ndo_dflt_fdb_dump(skb, ncb, netdev, filter_dev, idx);
 
        if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
            qlcnic_sriov_check(adapter))
-               idx = ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
+               idx = ndo_dflt_fdb_dump(skb, ncb, netdev, filter_dev, idx);
 
        return idx;
 }
index c2d3601..e6808f7 100644 (file)
@@ -933,7 +933,8 @@ out:
 
 /* Dump forwarding table */
 static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
-                         struct net_device *dev, int idx)
+                         struct net_device *dev,
+                         struct net_device *filter_dev, int idx)
 {
        struct vxlan_dev *vxlan = netdev_priv(dev);
        unsigned int h;
index 8b43a28..3a320db 100644 (file)
@@ -943,7 +943,8 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
  *                   const unsigned char *addr)
  *     Deletes the FDB entry from dev coresponding to addr.
  * int (*ndo_fdb_dump)(struct sk_buff *skb, struct netlink_callback *cb,
- *                    struct net_device *dev, int idx)
+ *                    struct net_device *dev, struct net_device *filter_dev,
+ *                    int idx)
  *     Used to add FDB entries to dump requests. Implementers should add
  *     entries to skb and update idx with the number of entries.
  *
@@ -1114,6 +1115,7 @@ struct net_device_ops {
        int                     (*ndo_fdb_dump)(struct sk_buff *skb,
                                                struct netlink_callback *cb,
                                                struct net_device *dev,
+                                               struct net_device *filter_dev,
                                                int idx);
 
        int                     (*ndo_bridge_setlink)(struct net_device *dev,
index 953937e..167bae7 100644 (file)
@@ -78,6 +78,7 @@ extern void __rtnl_unlock(void);
 extern int ndo_dflt_fdb_dump(struct sk_buff *skb,
                             struct netlink_callback *cb,
                             struct net_device *dev,
+                            struct net_device *filter_dev,
                             int idx);
 extern int ndo_dflt_fdb_add(struct ndmsg *ndm,
                            struct nlattr *tb[],
index 7be3366..6edecd1 100644 (file)
@@ -676,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);
@@ -691,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,
index 23caf5b..62a7fa2 100644 (file)
@@ -399,7 +399,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
 int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], struct net_device *dev,
               const unsigned char *addr, u16 nlh_flags);
 int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
-               struct net_device *dev, int idx);
+               struct net_device *dev, struct net_device *fdev, int idx);
 int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p);
 void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p);
 
index 27acaf7..90a906e 100644 (file)
@@ -2517,6 +2517,7 @@ skip:
 int ndo_dflt_fdb_dump(struct sk_buff *skb,
                      struct netlink_callback *cb,
                      struct net_device *dev,
+                     struct net_device *filter_dev,
                      int idx)
 {
        int err;
@@ -2547,13 +2548,15 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
                        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);
+                               idx = ops->ndo_fdb_dump(skb, cb, dev, NULL,
+                                                       idx);
                }
 
                if (dev->netdev_ops->ndo_fdb_dump)
-                       idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, idx);
+                       idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, NULL,
+                                                           idx);
                else
-                       idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
+                       idx = ndo_dflt_fdb_dump(skb, cb, dev, NULL, idx);
        }
        rcu_read_unlock();