Skip to content

Commit 51b5bd1

Browse files
committed
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>
2 parents 69b4b7a + 5e6d243 commit 51b5bd1

File tree

8 files changed

+87
-22
lines changed

8 files changed

+87
-22
lines changed

drivers/net/ethernet/intel/i40e/i40e_main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7095,13 +7095,14 @@ static int i40e_ndo_fdb_del(struct ndmsg *ndm,
70957095
static int i40e_ndo_fdb_dump(struct sk_buff *skb,
70967096
struct netlink_callback *cb,
70977097
struct net_device *dev,
7098+
struct net_device *filter_dev,
70987099
int idx)
70997100
{
71007101
struct i40e_netdev_priv *np = netdev_priv(dev);
71017102
struct i40e_pf *pf = np->vsi->back;
71027103

71037104
if (pf->flags & I40E_FLAG_SRIOV_ENABLED)
7104-
idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
7105+
idx = ndo_dflt_fdb_dump(skb, cb, dev, filter_dev, idx);
71057106

71067107
return idx;
71077108
}

drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -427,16 +427,17 @@ static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
427427
}
428428

429429
static int qlcnic_fdb_dump(struct sk_buff *skb, struct netlink_callback *ncb,
430-
struct net_device *netdev, int idx)
430+
struct net_device *netdev,
431+
struct net_device *filter_dev, int idx)
431432
{
432433
struct qlcnic_adapter *adapter = netdev_priv(netdev);
433434

434435
if (!adapter->fdb_mac_learn)
435-
return ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
436+
return ndo_dflt_fdb_dump(skb, ncb, netdev, filter_dev, idx);
436437

437438
if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
438439
qlcnic_sriov_check(adapter))
439-
idx = ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
440+
idx = ndo_dflt_fdb_dump(skb, ncb, netdev, filter_dev, idx);
440441

441442
return idx;
442443
}

drivers/net/vxlan.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,8 @@ static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
933933

934934
/* Dump forwarding table */
935935
static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
936-
struct net_device *dev, int idx)
936+
struct net_device *dev,
937+
struct net_device *filter_dev, int idx)
937938
{
938939
struct vxlan_dev *vxlan = netdev_priv(dev);
939940
unsigned int h;

include/linux/netdevice.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,8 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
943943
* const unsigned char *addr)
944944
* Deletes the FDB entry from dev coresponding to addr.
945945
* int (*ndo_fdb_dump)(struct sk_buff *skb, struct netlink_callback *cb,
946-
* struct net_device *dev, int idx)
946+
* struct net_device *dev, struct net_device *filter_dev,
947+
* int idx)
947948
* Used to add FDB entries to dump requests. Implementers should add
948949
* entries to skb and update idx with the number of entries.
949950
*
@@ -1114,6 +1115,7 @@ struct net_device_ops {
11141115
int (*ndo_fdb_dump)(struct sk_buff *skb,
11151116
struct netlink_callback *cb,
11161117
struct net_device *dev,
1118+
struct net_device *filter_dev,
11171119
int idx);
11181120

11191121
int (*ndo_bridge_setlink)(struct net_device *dev,

include/linux/rtnetlink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ extern void __rtnl_unlock(void);
7878
extern int ndo_dflt_fdb_dump(struct sk_buff *skb,
7979
struct netlink_callback *cb,
8080
struct net_device *dev,
81+
struct net_device *filter_dev,
8182
int idx);
8283
extern int ndo_dflt_fdb_add(struct ndmsg *ndm,
8384
struct nlattr *tb[],

net/bridge/br_fdb.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,7 @@ static void fdb_notify(struct net_bridge *br,
676676
int br_fdb_dump(struct sk_buff *skb,
677677
struct netlink_callback *cb,
678678
struct net_device *dev,
679+
struct net_device *filter_dev,
679680
int idx)
680681
{
681682
struct net_bridge *br = netdev_priv(dev);
@@ -691,6 +692,19 @@ int br_fdb_dump(struct sk_buff *skb,
691692
if (idx < cb->args[0])
692693
goto skip;
693694

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+
}
707+
694708
if (fdb_fill_info(skb, br, f,
695709
NETLINK_CB(cb->skb).portid,
696710
cb->nlh->nlmsg_seq,

net/bridge/br_private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
399399
int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], struct net_device *dev,
400400
const unsigned char *addr, u16 nlh_flags);
401401
int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
402-
struct net_device *dev, int idx);
402+
struct net_device *dev, struct net_device *fdev, int idx);
403403
int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p);
404404
void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p);
405405

net/core/rtnetlink.c

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2517,6 +2517,7 @@ static int nlmsg_populate_fdb(struct sk_buff *skb,
25172517
int ndo_dflt_fdb_dump(struct sk_buff *skb,
25182518
struct netlink_callback *cb,
25192519
struct net_device *dev,
2520+
struct net_device *filter_dev,
25202521
int idx)
25212522
{
25222523
int err;
@@ -2534,28 +2535,72 @@ EXPORT_SYMBOL(ndo_dflt_fdb_dump);
25342535

25352536
static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
25362537
{
2537-
int idx = 0;
2538-
struct net *net = sock_net(skb->sk);
25392538
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;
25402549

2541-
rcu_read_lock();
2542-
for_each_netdev_rcu(net, dev) {
2543-
if (dev->priv_flags & IFF_BRIDGE_PORT) {
2544-
struct net_device *br_dev;
2545-
const struct net_device_ops *ops;
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+
}
25462576

2547-
br_dev = netdev_master_upper_dev_get(dev);
2548-
ops = br_dev->netdev_ops;
2549-
if (ops->ndo_fdb_dump)
2550-
idx = ops->ndo_fdb_dump(skb, cb, dev, idx);
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+
}
2590+
2591+
if (dev->priv_flags & IFF_BRIDGE_PORT) {
2592+
if (cops && cops->ndo_fdb_dump)
2593+
idx = cops->ndo_fdb_dump(skb, cb, br_dev, dev,
2594+
idx);
25512595
}
25522596

2597+
idx = ndo_dflt_fdb_dump(skb, cb, dev, NULL, idx);
25532598
if (dev->netdev_ops->ndo_fdb_dump)
2554-
idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, idx);
2555-
else
2556-
idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
2599+
idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, bdev, dev,
2600+
idx);
2601+
2602+
cops = NULL;
25572603
}
2558-
rcu_read_unlock();
25592604

25602605
cb->args[0] = idx;
25612606
return skb->len;

0 commit comments

Comments
 (0)