1/* 2 * Forwarding database 3 * Linux ethernet bridge 4 * 5 * Authors: 6 * Lennert Buytenhek <buytenh@gnu.org> 7 * 8 * $Id: br_fdb.c,v 1.5 2010-06-15 01:09:50 $ 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * as published by the Free Software Foundation; either version 13 * 2 of the License, or (at your option) any later version. 14 */ 15 16#include <linux/kernel.h> 17#include <linux/init.h> 18#include <linux/spinlock.h> 19#include <linux/times.h> 20#include <linux/netdevice.h> 21#include <linux/etherdevice.h> 22#include <linux/jhash.h> 23#include <linux/random.h> 24#include <asm/atomic.h> 25#include <asm/unaligned.h> 26#include "br_private.h" 27/* Foxconn added start pling 07/02/2007 */ 28#define MAX_MAC_CNT 1024 29static int mac_cnt = 0; 30/* Foxconn added end pling 07/02/2007 */ 31#ifdef HNDCTF 32#include <linux/if.h> 33#include <linux/if_vlan.h> 34#include <typedefs.h> 35#include <osl.h> 36#include <ctf/hndctf.h> 37 38static void 39br_brc_init(ctf_brc_t *brc, unsigned char *ea, struct net_device *rxdev) 40{ 41 memset(brc, 0, sizeof(ctf_brc_t)); 42 43 memcpy(brc->dhost.octet, ea, ETH_ALEN); 44 45 if (rxdev->priv_flags & IFF_802_1Q_VLAN) { 46 brc->txifp = (void *)(VLAN_DEV_INFO(rxdev)->real_dev); 47 brc->vid = VLAN_DEV_INFO(rxdev)->vlan_id; 48 brc->action = ((VLAN_DEV_INFO(rxdev)->flags & 1) ? 49 CTF_ACTION_TAG : CTF_ACTION_UNTAG); 50 } else { 51 brc->txifp = (void *)rxdev; 52 brc->action = CTF_ACTION_UNTAG; 53 } 54 55#ifdef DEBUG 56 printk("mac %02x:%02x:%02x:%02x:%02x:%02x\n", 57 brc->dhost.octet[0], brc->dhost.octet[1], 58 brc->dhost.octet[2], brc->dhost.octet[3], 59 brc->dhost.octet[4], brc->dhost.octet[5]); 60 printk("vid: %d action %x\n", brc->vid, brc->action); 61 printk("txif: %s\n", ((struct net_device *)brc->txifp)->name); 62#endif 63 64 return; 65} 66 67/* 68 * Add bridge cache entry. 69 */ 70void 71br_brc_add(unsigned char *ea, struct net_device *rxdev) 72{ 73 ctf_brc_t brc_entry, *brcp; 74 75 /* Add brc entry only if packet is received on ctf 76 * enabled interface 77 */ 78 if (!ctf_isenabled(kcih, ((rxdev->priv_flags & IFF_802_1Q_VLAN) ? 79 VLAN_DEV_INFO(rxdev)->real_dev : rxdev))) 80 return; 81 82 br_brc_init(&brc_entry, ea, rxdev); 83 84#ifdef DEBUG 85 printk("%s: Adding brc entry\n", __FUNCTION__); 86#endif 87 88 /* Add the bridge cache entry */ 89 if ((brcp = ctf_brc_lkup(kcih, ea)) == NULL) 90 ctf_brc_add(kcih, &brc_entry); 91 else { 92 ctf_brc_release(kcih, brcp); 93 ctf_brc_update(kcih, &brc_entry); 94 } 95 96 return; 97} 98 99/* 100 * Update bridge cache entry. 101 */ 102void 103br_brc_update(unsigned char *ea, struct net_device *rxdev) 104{ 105 ctf_brc_t brc_entry; 106 107 /* Update brc entry only if packet is received on ctf 108 * enabled interface 109 */ 110 if (!ctf_isenabled(kcih, ((rxdev->priv_flags & IFF_802_1Q_VLAN) ? 111 VLAN_DEV_INFO(rxdev)->real_dev : rxdev))) 112 return; 113 114 /* Initialize the new device and/or vlan info */ 115 br_brc_init(&brc_entry, ea, rxdev); 116 117#ifdef DEBUG 118 printk("%s: Updating brc entry\n", __FUNCTION__); 119#endif 120 121 /* Update the bridge cache entry */ 122 ctf_brc_update(kcih, &brc_entry); 123 124 return; 125} 126#endif /* HNDCTF */ 127 128static struct kmem_cache *br_fdb_cache __read_mostly; 129static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, 130 const unsigned char *addr); 131 132static u32 fdb_salt __read_mostly; 133 134int __init br_fdb_init(void) 135{ 136 br_fdb_cache = kmem_cache_create("bridge_fdb_cache", 137 sizeof(struct net_bridge_fdb_entry), 138 0, 139 SLAB_HWCACHE_ALIGN, NULL, NULL); 140 if (!br_fdb_cache) 141 return -ENOMEM; 142 143 get_random_bytes(&fdb_salt, sizeof(fdb_salt)); 144 return 0; 145} 146 147void __exit br_fdb_fini(void) 148{ 149 kmem_cache_destroy(br_fdb_cache); 150} 151 152 153/* if topology_changing then use forward_delay (default 15 sec) 154 * otherwise keep longer (default 5 minutes) 155 */ 156static inline unsigned long hold_time(const struct net_bridge *br) 157{ 158 return br->topology_change ? br->forward_delay : br->ageing_time; 159} 160 161static inline int has_expired(const struct net_bridge *br, 162 const struct net_bridge_fdb_entry *fdb) 163{ 164 return !fdb->is_static 165 && time_before_eq(fdb->ageing_timer + hold_time(br), jiffies); 166} 167 168static inline int br_mac_hash(const unsigned char *mac) 169{ 170 /* use 1 byte of OUI cnd 3 bytes of NIC */ 171 u32 key = get_unaligned((u32 *)(mac + 2)); 172 return jhash_1word(key, fdb_salt) & (BR_HASH_SIZE - 1); 173} 174 175static inline void fdb_delete(struct net_bridge_fdb_entry *f) 176{ 177 hlist_del_rcu(&f->hlist); 178 br_fdb_put(f); 179} 180 181void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) 182{ 183 struct net_bridge *br = p->br; 184 int i; 185 186 spin_lock_bh(&br->hash_lock); 187 188 /* Search all chains since old address/hash is unknown */ 189 for (i = 0; i < BR_HASH_SIZE; i++) { 190 struct hlist_node *h; 191 hlist_for_each(h, &br->hash[i]) { 192 struct net_bridge_fdb_entry *f; 193 194 f = hlist_entry(h, struct net_bridge_fdb_entry, hlist); 195 if (f->dst == p && f->is_local) { 196 /* maybe another port has same hw addr? */ 197 struct net_bridge_port *op; 198 list_for_each_entry(op, &br->port_list, list) { 199 if (op != p && 200 !compare_ether_addr(op->dev->dev_addr, 201 f->addr.addr)) { 202 f->dst = op; 203 goto insert; 204 } 205 } 206 207 /* delete old one */ 208 fdb_delete(f); 209 goto insert; 210 } 211 } 212 } 213 insert: 214 /* insert new address, may fail if invalid address or dup. */ 215 fdb_insert(br, p, newaddr); 216 217 spin_unlock_bh(&br->hash_lock); 218} 219 220void br_fdb_cleanup(unsigned long _data) 221{ 222 struct net_bridge *br = (struct net_bridge *)_data; 223 unsigned long delay = hold_time(br); 224 unsigned long next_timer = jiffies + br->forward_delay; 225 int i; 226 227 spin_lock_bh(&br->hash_lock); 228 for (i = 0; i < BR_HASH_SIZE; i++) { 229 struct net_bridge_fdb_entry *f; 230 struct hlist_node *h, *n; 231 232 hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist) { 233 unsigned long this_timer; 234 if (f->is_static) 235 continue; 236 this_timer = f->ageing_timer + delay; 237 if (time_before_eq(this_timer, jiffies)) { 238#ifdef HNDCTF 239 ctf_brc_t *brcp; 240 241 /* Before expiring the fdb entry check the brc 242 * live counter to make sure there are no frames 243 * on this connection for timeout period. 244 */ 245 brcp = ctf_brc_lkup(kcih, f->addr.addr); 246 if (brcp != NULL) { 247 if (brcp->live > 0) { 248 brcp->live = 0; 249 ctf_brc_release(kcih, brcp); 250 f->ageing_timer = jiffies; 251 continue; 252 } 253 ctf_brc_release(kcih, brcp); 254 } 255#endif /* HNDCTF */ 256 fdb_delete(f); 257 } else if (this_timer < next_timer) 258 next_timer = this_timer; 259 } 260 } 261 spin_unlock_bh(&br->hash_lock); 262 263 /* Add HZ/4 to ensure we round the jiffies upwards to be after the next 264 * timer, otherwise we might round down and will have no-op run. */ 265 mod_timer(&br->gc_timer, round_jiffies(next_timer + HZ/4)); 266} 267 268/* Completely flush all dynamic entries in forwarding database.*/ 269void br_fdb_flush(struct net_bridge *br) 270{ 271 int i; 272 273 spin_lock_bh(&br->hash_lock); 274 for (i = 0; i < BR_HASH_SIZE; i++) { 275 struct net_bridge_fdb_entry *f; 276 struct hlist_node *h, *n; 277 hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist) { 278 if (!f->is_static) 279 fdb_delete(f); 280 } 281 } 282 spin_unlock_bh(&br->hash_lock); 283} 284 285/* Flush all entries refering to a specific port. 286 * if do_all is set also flush static entries 287 */ 288void br_fdb_delete_by_port(struct net_bridge *br, 289 const struct net_bridge_port *p, 290 int do_all) 291{ 292 int i; 293 294 spin_lock_bh(&br->hash_lock); 295 for (i = 0; i < BR_HASH_SIZE; i++) { 296 struct hlist_node *h, *g; 297 298 hlist_for_each_safe(h, g, &br->hash[i]) { 299 struct net_bridge_fdb_entry *f 300 = hlist_entry(h, struct net_bridge_fdb_entry, hlist); 301 if (f->dst != p) 302 continue; 303 304 if (f->is_static && !do_all) 305 continue; 306 /* 307 * if multiple ports all have the same device address 308 * then when one port is deleted, assign 309 * the local entry to other port 310 */ 311 if (f->is_local) { 312 struct net_bridge_port *op; 313 list_for_each_entry(op, &br->port_list, list) { 314 if (op != p && 315 !compare_ether_addr(op->dev->dev_addr, 316 f->addr.addr)) { 317 f->dst = op; 318 goto skip_delete; 319 } 320 } 321 } 322 323 fdb_delete(f); 324 skip_delete: ; 325 } 326 } 327 spin_unlock_bh(&br->hash_lock); 328} 329 330/* No locking or refcounting, assumes caller has no preempt (rcu_read_lock) */ 331struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, 332 const unsigned char *addr) 333{ 334 struct hlist_node *h; 335 struct net_bridge_fdb_entry *fdb; 336 337 hlist_for_each_entry_rcu(fdb, h, &br->hash[br_mac_hash(addr)], hlist) { 338 if (!compare_ether_addr(fdb->addr.addr, addr)) { 339 if (unlikely(has_expired(br, fdb))) 340 break; 341 return fdb; 342 } 343 } 344 345 return NULL; 346} 347 348/* Interface used by ATM hook that keeps a ref count */ 349struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, 350 unsigned char *addr) 351{ 352 struct net_bridge_fdb_entry *fdb; 353 354 rcu_read_lock(); 355 fdb = __br_fdb_get(br, addr); 356 if (fdb && !atomic_inc_not_zero(&fdb->use_count)) 357 fdb = NULL; 358 rcu_read_unlock(); 359 return fdb; 360} 361 362static void fdb_rcu_free(struct rcu_head *head) 363{ 364 struct net_bridge_fdb_entry *ent 365 = container_of(head, struct net_bridge_fdb_entry, rcu); 366 kmem_cache_free(br_fdb_cache, ent); 367 mac_cnt--; /* foxconn wklin added , 06/18/2008 */ 368} 369 370/* Set entry up for deletion with RCU */ 371void br_fdb_put(struct net_bridge_fdb_entry *ent) 372{ 373 if (atomic_dec_and_test(&ent->use_count)) { 374#ifdef HNDCTF 375 /* Delete the corresponding brc entry when it expires 376 * or deleted by user. 377 */ 378 ctf_brc_delete(kcih, ent->addr.addr); 379#endif /* HNDCTF */ 380 call_rcu(&ent->rcu, fdb_rcu_free); 381 } 382} 383 384/* 385 * Fill buffer with forwarding table records in 386 * the API format. 387 */ 388int br_fdb_fillbuf(struct net_bridge *br, void *buf, 389 unsigned long maxnum, unsigned long skip) 390{ 391 struct __fdb_entry *fe = buf; 392 int i, num = 0; 393 struct hlist_node *h; 394 struct net_bridge_fdb_entry *f; 395 396 memset(buf, 0, maxnum*sizeof(struct __fdb_entry)); 397 398 rcu_read_lock(); 399 for (i = 0; i < BR_HASH_SIZE; i++) { 400 hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) { 401 if (num >= maxnum) 402 goto out; 403 404 if (has_expired(br, f)) 405 continue; 406 407 if (skip) { 408 --skip; 409 continue; 410 } 411 412 /* convert from internal format to API */ 413 memcpy(fe->mac_addr, f->addr.addr, ETH_ALEN); 414 fe->port_no = f->dst->port_no; 415 fe->is_local = f->is_local; 416 if (!f->is_static) 417 fe->ageing_timer_value = jiffies_to_clock_t(jiffies - f->ageing_timer); 418 ++fe; 419 ++num; 420 } 421 } 422 423 out: 424 rcu_read_unlock(); 425 426 return num; 427} 428 429static inline struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head, 430 const unsigned char *addr) 431{ 432 struct hlist_node *h; 433 struct net_bridge_fdb_entry *fdb; 434 435 hlist_for_each_entry_rcu(fdb, h, head, hlist) { 436 if (!compare_ether_addr(fdb->addr.addr, addr)) 437 return fdb; 438 } 439 return NULL; 440} 441 442static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, 443 struct net_bridge_port *source, 444 const unsigned char *addr, 445 int is_local) 446{ 447 struct net_bridge_fdb_entry *fdb; 448 449 /* foxconn wklin added start, 06/18/2008 */ 450 if (mac_cnt > MAX_MAC_CNT) 451 return 0; 452 /* foxconn wklin added end, 06/18/2008 */ 453 fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC); 454 if (fdb) { 455 mac_cnt++; /* foxconn wklin added , 06/18/2008 */ 456 memcpy(fdb->addr.addr, addr, ETH_ALEN); 457 atomic_set(&fdb->use_count, 1); 458 hlist_add_head_rcu(&fdb->hlist, head); 459 460 fdb->dst = source; 461 fdb->is_local = is_local; 462 fdb->is_static = is_local; 463 fdb->ageing_timer = jiffies; 464 465 /* Add bridge cache entry for non local hosts */ 466#ifdef HNDCTF 467 if (!is_local && (source->state == BR_STATE_FORWARDING)) 468 br_brc_add((unsigned char *)addr, source->dev); 469#endif /* HNDCTF */ 470 } 471 472 return fdb; 473} 474 475static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, 476 const unsigned char *addr) 477{ 478 struct hlist_head *head = &br->hash[br_mac_hash(addr)]; 479 struct net_bridge_fdb_entry *fdb; 480 481 if (!is_valid_ether_addr(addr)) 482 return -EINVAL; 483 484 fdb = fdb_find(head, addr); 485 if (fdb) { 486 /* it is okay to have multiple ports with same 487 * address, just use the first one. 488 */ 489 if (fdb->is_local) 490 return 0; 491 492 printk(KERN_WARNING "%s adding interface with same address " 493 "as a received packet\n", 494 source->dev->name); 495 fdb_delete(fdb); 496 } 497 498 if (!fdb_create(head, source, addr, 1)) 499 return -ENOMEM; 500 501 return 0; 502} 503 504int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, 505 const unsigned char *addr) 506{ 507 int ret; 508 509 spin_lock_bh(&br->hash_lock); 510 ret = fdb_insert(br, source, addr); 511 spin_unlock_bh(&br->hash_lock); 512 return ret; 513} 514 515void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, 516 const unsigned char *addr) 517{ 518 struct hlist_head *head = &br->hash[br_mac_hash(addr)]; 519 struct net_bridge_fdb_entry *fdb; 520 521 /* some users want to always flood. */ 522 if (hold_time(br) == 0) 523 return; 524 525 fdb = fdb_find(head, addr); 526 if (likely(fdb)) { 527 /* attempt to update an entry for a local interface */ 528 if (unlikely(fdb->is_local)) { 529 if (net_ratelimit()) 530 printk(KERN_WARNING "%s: received packet with " 531 " own address as source address\n", 532 source->dev->name); 533 } else { 534 /* fastpath: update of existing entry */ 535#ifdef HNDCTF 536 /* Update the brc entry incase the host moved from 537 * one bridge to another or to a different port under 538 * the same bridge. 539 */ 540 if (source->state == BR_STATE_FORWARDING) 541 br_brc_update((unsigned char *)addr, source->dev); 542#endif /* HNDCTF */ 543 544 fdb->dst = source; 545 fdb->ageing_timer = jiffies; 546 } 547 } else { 548 spin_lock(&br->hash_lock); 549 if (!fdb_find(head, addr)) 550 fdb_create(head, source, addr, 0); 551 /* else we lose race and someone else inserts 552 * it first, don't bother updating 553 */ 554 spin_unlock(&br->hash_lock); 555 } 556} 557