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 ---