summaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorstephen hemminger <shemminger@vyatta.com>2011-09-30 14:37:27 +0000
committerDavid S. Miller <davem@davemloft.net>2011-10-03 12:17:33 -0400
commit64af1bac9b979ae1f2f052742fda06d65f497643 (patch)
treebcd4b0063382a5b9da64fb2e19af4ec0bfd98516 /net/bridge
parent77f9859837cbe262ef2aa12fc38d18458814c2ca (diff)
bridge: allow updating existing fdb entries
Need to allow application to update existing fdb entries that already exist. This makes bridge netlink neighbor API have same flags and semantics as ip neighbor table. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_fdb.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 68def3b7fb4..c8e7861b88b 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -558,19 +558,28 @@ skip:
/* Create new static fdb entry */
static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr,
- __u16 state)
+ __u16 state, __u16 flags)
{
struct net_bridge *br = source->br;
struct hlist_head *head = &br->hash[br_mac_hash(addr)];
struct net_bridge_fdb_entry *fdb;
fdb = fdb_find(head, addr);
- if (fdb)
- return -EEXIST;
+ if (fdb == NULL) {
+ if (!(flags & NLM_F_CREATE))
+ return -ENOENT;
- fdb = fdb_create(head, source, addr);
- if (!fdb)
- return -ENOMEM;
+ fdb = fdb_create(head, source, addr);
+ if (!fdb)
+ return -ENOMEM;
+ } else {
+ if (flags & NLM_F_EXCL)
+ return -EEXIST;
+
+ if (flags & NLM_F_REPLACE)
+ fdb->updated = fdb->used = jiffies;
+ fdb->is_local = fdb->is_static = 0;
+ }
if (state & NUD_PERMANENT)
fdb->is_local = fdb->is_static = 1;
@@ -626,7 +635,7 @@ int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
}
spin_lock_bh(&p->br->hash_lock);
- err = fdb_add_entry(p, addr, ndm->ndm_state);
+ err = fdb_add_entry(p, addr, ndm->ndm_state, nlh->nlmsg_flags);
spin_unlock_bh(&p->br->hash_lock);
return err;