Merge branch 'bridge-fdb-dump-filter'
Jamal Hadi Salim says: ==================== bridge: fdb dumping takes a filter device v7: Vxlan driver was not updated with new API. Found by DaveM v6: Missed checkpatch > 80 chars lines found by Varka Bhadram v5: Embarassing qlnic compile failure found by DaveM v4: Request from DaveM to use proper comment tagging and remove if-stmnt braces V3: Suggestion from Eric D. to use for_each_netdev Suggestion from Stephen H. to reduce level of indentation V2: Suggestions from Vlad Get rid of rcu read lock since rtnl_lock is being held simplify for readability ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
51b5bd199a
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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[],
|
||||
|
|
|
@ -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,19 @@ int br_fdb_dump(struct sk_buff *skb,
|
|||
if (idx < cb->args[0])
|
||||
goto skip;
|
||||
|
||||
if (filter_dev &&
|
||||
(!f->dst || f->dst->dev != filter_dev)) {
|
||||
if (filter_dev != dev)
|
||||
goto skip;
|
||||
/* !f->dst is a speacial case for bridge
|
||||
* It means the MAC belongs to the bridge
|
||||
* Therefore need a little more filtering
|
||||
* we only want to dump the !f->dst case
|
||||
*/
|
||||
if (f->dst)
|
||||
goto skip;
|
||||
}
|
||||
|
||||
if (fdb_fill_info(skb, br, f,
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -2534,28 +2535,72 @@ EXPORT_SYMBOL(ndo_dflt_fdb_dump);
|
|||
|
||||
static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
int idx = 0;
|
||||
struct net *net = sock_net(skb->sk);
|
||||
struct net_device *dev;
|
||||
struct nlattr *tb[IFLA_MAX+1];
|
||||
struct net_device *bdev = NULL;
|
||||
struct net_device *br_dev = NULL;
|
||||
const struct net_device_ops *ops = NULL;
|
||||
const struct net_device_ops *cops = NULL;
|
||||
struct ifinfomsg *ifm = nlmsg_data(cb->nlh);
|
||||
struct net *net = sock_net(skb->sk);
|
||||
int brport_idx = 0;
|
||||
int br_idx = 0;
|
||||
int idx = 0;
|
||||
|
||||
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;
|
||||
if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
|
||||
ifla_policy) == 0) {
|
||||
if (tb[IFLA_MASTER])
|
||||
br_idx = nla_get_u32(tb[IFLA_MASTER]);
|
||||
}
|
||||
|
||||
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);
|
||||
brport_idx = ifm->ifi_index;
|
||||
|
||||
if (br_idx) {
|
||||
br_dev = __dev_get_by_index(net, br_idx);
|
||||
if (!br_dev)
|
||||
return -ENODEV;
|
||||
|
||||
ops = br_dev->netdev_ops;
|
||||
bdev = br_dev;
|
||||
}
|
||||
|
||||
for_each_netdev(net, dev) {
|
||||
if (brport_idx && (dev->ifindex != brport_idx))
|
||||
continue;
|
||||
|
||||
if (!br_idx) { /* user did not specify a specific bridge */
|
||||
if (dev->priv_flags & IFF_BRIDGE_PORT) {
|
||||
br_dev = netdev_master_upper_dev_get(dev);
|
||||
cops = br_dev->netdev_ops;
|
||||
}
|
||||
|
||||
bdev = dev;
|
||||
} else {
|
||||
if (dev != br_dev &&
|
||||
!(dev->priv_flags & IFF_BRIDGE_PORT))
|
||||
continue;
|
||||
|
||||
if (br_dev != netdev_master_upper_dev_get(dev) &&
|
||||
!(dev->priv_flags & IFF_EBRIDGE))
|
||||
continue;
|
||||
|
||||
bdev = br_dev;
|
||||
cops = ops;
|
||||
}
|
||||
|
||||
if (dev->priv_flags & IFF_BRIDGE_PORT) {
|
||||
if (cops && cops->ndo_fdb_dump)
|
||||
idx = cops->ndo_fdb_dump(skb, cb, br_dev, dev,
|
||||
idx);
|
||||
}
|
||||
|
||||
idx = ndo_dflt_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);
|
||||
else
|
||||
idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
|
||||
idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, bdev, dev,
|
||||
idx);
|
||||
|
||||
cops = NULL;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
cb->args[0] = idx;
|
||||
return skb->len;
|
||||
|
|
Loading…
Reference in New Issue