bridge: allow updating existing fdb entries
authorstephen hemminger <shemminger@vyatta.com>
Fri, 30 Sep 2011 14:37:27 +0000 (14:37 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 3 Oct 2011 16:17:33 +0000 (12:17 -0400)
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>
net/bridge/br_fdb.c

index 68def3b7fb49552657a0f42141b84613da85e43a..c8e7861b88b02983e0d5ff202de4e6165bb022b8 100644 (file)
@@ -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;