+
+void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
+ const unsigned char *addr)
+{
+ struct hlist_head *head = &br->hash[br_mac_hash(addr)];
+ struct net_bridge_fdb_entry *fdb;
+
+ /* some users want to always flood. */
+ if (hold_time(br) == 0)
+ return;
+
+ fdb = fdb_find(head, addr);
+ if (likely(fdb)) {
+ /* attempt to update an entry for a local interface */
+ if (unlikely(fdb->is_local)) {
+ if (net_ratelimit())
+ printk(KERN_WARNING "%s: received packet with "
+ " own address as source address\n",
+ source->dev->name);
+ } else {
+ /* fastpath: update of existing entry */
+ fdb->dst = source;
+ fdb->ageing_timer = jiffies;
+ }
+ } else {
+ spin_lock(&br->hash_lock);
+ if (!fdb_find(head, addr))
+ fdb_create(head, source, addr, 0);
+ /* else we lose race and someone else inserts
+ * it first, don't bother updating
+ */
+ spin_unlock(&br->hash_lock);
+ }
+}