bridge: Add functionality to sync static fdb entries to hw

Add code that allows static fdb entires to be synced to the
hw list for a specified port.  This will be used later to
program ports that can function in non-promiscuous mode.

Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Vlad Yasevich 2014-05-16 09:59:17 -04:00 committed by David S. Miller
parent e028e4b8dc
commit 8db24af71b
2 changed files with 58 additions and 0 deletions

View file

@ -874,3 +874,59 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
out:
return err;
}
int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p)
{
struct net_bridge_fdb_entry *fdb, *tmp;
int i;
int err;
ASSERT_RTNL();
for (i = 0; i < BR_HASH_SIZE; i++) {
hlist_for_each_entry(fdb, &br->hash[i], hlist) {
/* We only care for static entries */
if (!fdb->is_static)
continue;
err = dev_uc_add(p->dev, fdb->addr.addr);
if (err)
goto rollback;
}
}
return 0;
rollback:
for (i = 0; i < BR_HASH_SIZE; i++) {
hlist_for_each_entry(tmp, &br->hash[i], hlist) {
/* If we reached the fdb that failed, we can stop */
if (tmp == fdb)
break;
/* We only care for static entries */
if (!tmp->is_static)
continue;
dev_uc_del(p->dev, tmp->addr.addr);
}
}
return err;
}
void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p)
{
struct net_bridge_fdb_entry *fdb;
int i;
ASSERT_RTNL();
for (i = 0; i < BR_HASH_SIZE; i++) {
hlist_for_each_entry_rcu(fdb, &br->hash[i], hlist) {
/* We only care for static entries */
if (!fdb->is_static)
continue;
dev_uc_del(p->dev, fdb->addr.addr);
}
}
}

View file

@ -399,6 +399,8 @@ 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);
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);
/* br_forward.c */
void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb);