br_fdb.c (858a0d7eb5300b5f620d98ab3c4b96c9d5f19131) | br_fdb.c (f7cdee8a79a1cb03fa9ca71b825e72f880b344e1) |
---|---|
1/* 2 * Forwarding database 3 * Linux ethernet bridge 4 * 5 * Authors: 6 * Lennert Buytenhek <buytenh@gnu.org> 7 * 8 * This program is free software; you can redistribute it and/or --- 140 unchanged lines hidden (view full) --- 149static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f) 150{ 151 if (f->is_static) 152 fdb_del_hw_addr(br, f->addr.addr); 153 154 if (f->added_by_external_learn) 155 fdb_del_external_learn(f); 156 | 1/* 2 * Forwarding database 3 * Linux ethernet bridge 4 * 5 * Authors: 6 * Lennert Buytenhek <buytenh@gnu.org> 7 * 8 * This program is free software; you can redistribute it and/or --- 140 unchanged lines hidden (view full) --- 149static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f) 150{ 151 if (f->is_static) 152 fdb_del_hw_addr(br, f->addr.addr); 153 154 if (f->added_by_external_learn) 155 fdb_del_external_learn(f); 156 |
157 hlist_del_rcu(&f->hlist); | 157 hlist_del_init_rcu(&f->hlist); |
158 fdb_notify(br, f, RTM_DELNEIGH); 159 call_rcu(&f->rcu, fdb_rcu_free); 160} 161 162/* Delete a local entry if no other port had the same address. */ 163static void fdb_delete_local(struct net_bridge *br, 164 const struct net_bridge_port *p, 165 struct net_bridge_fdb_entry *f) --- 119 unchanged lines hidden (view full) --- 285 if (f && f->is_local && !f->dst && !f->added_by_user) 286 fdb_delete_local(br, NULL, f); 287 fdb_insert(br, NULL, newaddr, v->vid); 288 } 289out: 290 spin_unlock_bh(&br->hash_lock); 291} 292 | 158 fdb_notify(br, f, RTM_DELNEIGH); 159 call_rcu(&f->rcu, fdb_rcu_free); 160} 161 162/* Delete a local entry if no other port had the same address. */ 163static void fdb_delete_local(struct net_bridge *br, 164 const struct net_bridge_port *p, 165 struct net_bridge_fdb_entry *f) --- 119 unchanged lines hidden (view full) --- 285 if (f && f->is_local && !f->dst && !f->added_by_user) 286 fdb_delete_local(br, NULL, f); 287 fdb_insert(br, NULL, newaddr, v->vid); 288 } 289out: 290 spin_unlock_bh(&br->hash_lock); 291} 292 |
293void br_fdb_cleanup(unsigned long _data) | 293void br_fdb_cleanup(struct work_struct *work) |
294{ | 294{ |
295 struct net_bridge *br = (struct net_bridge *)_data; | 295 struct net_bridge *br = container_of(work, struct net_bridge, 296 gc_work.work); |
296 unsigned long delay = hold_time(br); | 297 unsigned long delay = hold_time(br); |
297 unsigned long next_timer = jiffies + br->ageing_time; | 298 unsigned long work_delay = delay; 299 unsigned long now = jiffies; |
298 int i; 299 | 300 int i; 301 |
300 spin_lock(&br->hash_lock); | |
301 for (i = 0; i < BR_HASH_SIZE; i++) { 302 struct net_bridge_fdb_entry *f; 303 struct hlist_node *n; 304 | 302 for (i = 0; i < BR_HASH_SIZE; i++) { 303 struct net_bridge_fdb_entry *f; 304 struct hlist_node *n; 305 |
306 if (!br->hash[i].first) 307 continue; 308 309 spin_lock_bh(&br->hash_lock); |
|
305 hlist_for_each_entry_safe(f, n, &br->hash[i], hlist) { 306 unsigned long this_timer; | 310 hlist_for_each_entry_safe(f, n, &br->hash[i], hlist) { 311 unsigned long this_timer; |
312 |
|
307 if (f->is_static) 308 continue; 309 if (f->added_by_external_learn) 310 continue; 311 this_timer = f->updated + delay; | 313 if (f->is_static) 314 continue; 315 if (f->added_by_external_learn) 316 continue; 317 this_timer = f->updated + delay; |
312 if (time_before_eq(this_timer, jiffies)) | 318 if (time_after(this_timer, now)) 319 work_delay = min(work_delay, this_timer - now); 320 else |
313 fdb_delete(br, f); | 321 fdb_delete(br, f); |
314 else if (time_before(this_timer, next_timer)) 315 next_timer = this_timer; | |
316 } | 322 } |
323 spin_unlock_bh(&br->hash_lock); 324 cond_resched(); |
|
317 } | 325 } |
318 spin_unlock(&br->hash_lock); | |
319 | 326 |
320 mod_timer(&br->gc_timer, round_jiffies_up(next_timer)); | 327 /* Cleanup minimum 10 milliseconds apart */ 328 work_delay = max_t(unsigned long, work_delay, msecs_to_jiffies(10)); 329 mod_delayed_work(system_long_wq, &br->gc_work, work_delay); |
321} 322 323/* Completely flush all dynamic entries in forwarding database.*/ 324void br_fdb_flush(struct net_bridge *br) 325{ 326 int i; 327 328 spin_lock_bh(&br->hash_lock); --- 48 unchanged lines hidden (view full) --- 377 __u16 vid) 378{ 379 struct net_bridge_fdb_entry *fdb; 380 381 hlist_for_each_entry_rcu(fdb, 382 &br->hash[br_mac_hash(addr, vid)], hlist) { 383 if (ether_addr_equal(fdb->addr.addr, addr) && 384 fdb->vlan_id == vid) { | 330} 331 332/* Completely flush all dynamic entries in forwarding database.*/ 333void br_fdb_flush(struct net_bridge *br) 334{ 335 int i; 336 337 spin_lock_bh(&br->hash_lock); --- 48 unchanged lines hidden (view full) --- 386 __u16 vid) 387{ 388 struct net_bridge_fdb_entry *fdb; 389 390 hlist_for_each_entry_rcu(fdb, 391 &br->hash[br_mac_hash(addr, vid)], hlist) { 392 if (ether_addr_equal(fdb->addr.addr, addr) && 393 fdb->vlan_id == vid) { |
385 if (unlikely(has_expired(br, fdb))) 386 break; | |
387 return fdb; 388 } 389 } 390 391 return NULL; 392} 393 394#if IS_ENABLED(CONFIG_ATM_LANE) --- 761 unchanged lines hidden --- | 394 return fdb; 395 } 396 } 397 398 return NULL; 399} 400 401#if IS_ENABLED(CONFIG_ATM_LANE) --- 761 unchanged lines hidden --- |