void br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, unsigned char *addr, int is_local) { struct net_bridge_fdb_entry *fdb; int hash; hash = br_mac_hash(addr); write_lock_bh(&br->hash_lock); fdb = br->hash[hash]; while (fdb != NULL) { if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) { /* attempt to update an entry for a local interface */ if (fdb->is_local) { if (is_local) printk(KERN_INFO "%s: attempt to add" " interface with same source address.\n", source->dev->name); else if (net_ratelimit()) printk(KERN_WARNING "%s: received packet with " " own address as source address\n", source->dev->name); goto out; } __fdb_possibly_replace(fdb, source, is_local); goto out; } fdb = fdb->next_hash; } fdb = kmalloc(sizeof(*fdb), GFP_ATOMIC); if (fdb == NULL) goto out; memcpy(fdb->addr.addr, addr, ETH_ALEN); atomic_set(&fdb->use_count, 1); fdb->dst = source; fdb->is_local = is_local; fdb->is_static = is_local; fdb->ageing_timer = jiffies; __hash_link(br, fdb, hash); out: write_unlock_bh(&br->hash_lock); }
void br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, unsigned char *addr, int is_local) { struct net_bridge_fdb_entry *fdb; int hash; hash = br_mac_hash(addr); write_lock_bh(&br->hash_lock); fdb = br->hash[hash]; while (fdb != NULL) { if (!fdb->is_local && !memcmp(fdb->addr.addr, addr, ETH_ALEN)) { __fdb_possibly_replace(fdb, source, is_local); write_unlock_bh(&br->hash_lock); return; } fdb = fdb->next_hash; } fdb = kmalloc(sizeof(*fdb), GFP_ATOMIC); if (fdb == NULL) { write_unlock_bh(&br->hash_lock); return; } memcpy(fdb->addr.addr, addr, ETH_ALEN); atomic_set(&fdb->use_count, 1); fdb->dst = source; fdb->is_local = is_local; fdb->is_static = is_local; fdb->ageing_timer = jiffies; __hash_link(br, fdb, hash); write_unlock_bh(&br->hash_lock); }
void br_fdb_changeaddr(struct net_bridge_port *p, unsigned char *newaddr) { struct net_bridge *br; int i; br = p->br; write_lock_bh(&br->hash_lock); for (i=0;i<BR_HASH_SIZE;i++) { struct net_bridge_fdb_entry *f; f = br->hash[i]; while (f != NULL) { if (f->dst == p && f->is_local) { __hash_unlink(f); memcpy(f->addr.addr, newaddr, ETH_ALEN); __hash_link(br, f, br_mac_hash(newaddr)); write_unlock_bh(&br->hash_lock); return; } f = f->next_hash; } } write_unlock_bh(&br->hash_lock); }