# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/09/24 16:05:14-07:00 davem@nuts.davemloft.net # [NET]: Smooth out periodic neighbour GC. # # Based almost entirely upon work by Tim Gardner # (timg@tpi.com) and Harald Welte (laforge@gnumonks.org) # # Signed-off-by: David S. Miller # # net/core/neighbour.c # 2004/09/24 16:04:44-07:00 davem@nuts.davemloft.net +38 -32 # [NET]: Smooth out periodic neighbour GC. # # Based almost entirely upon work by Tim Gardner # (timg@tpi.com) and Harald Welte (laforge@gnumonks.org) # # Signed-off-by: David S. Miller # # include/net/neighbour.h # 2004/09/24 16:04:44-07:00 davem@nuts.davemloft.net +1 -0 # [NET]: Smooth out periodic neighbour GC. # # Based almost entirely upon work by Tim Gardner # (timg@tpi.com) and Harald Welte (laforge@gnumonks.org) # # Signed-off-by: David S. Miller # diff -Nru a/include/net/neighbour.h b/include/net/neighbour.h --- a/include/net/neighbour.h 2004-09-25 00:30:27 -07:00 +++ b/include/net/neighbour.h 2004-09-25 00:30:27 -07:00 @@ -176,6 +176,7 @@ struct neighbour **hash_buckets; unsigned int hash_mask; __u32 hash_rnd; + unsigned int hash_chain_gc; struct pneigh_entry **phash_buckets; }; diff -Nru a/net/core/neighbour.c b/net/core/neighbour.c --- a/net/core/neighbour.c 2004-09-25 00:30:27 -07:00 +++ b/net/core/neighbour.c 2004-09-25 00:30:27 -07:00 @@ -631,9 +631,8 @@ static void neigh_periodic_timer(unsigned long arg) { struct neigh_table *tbl = (struct neigh_table *)arg; - unsigned long now = jiffies; - int i; - + struct neighbour *n, **np; + unsigned long expire, now = jiffies; write_lock(&tbl->lock); @@ -649,41 +648,49 @@ neigh_rand_reach_time(p->base_reachable_time); } - for (i = 0; i <= tbl->hash_mask; i++) { - struct neighbour *n, **np; + np = &tbl->hash_buckets[tbl->hash_chain_gc]; + tbl->hash_chain_gc = ((tbl->hash_chain_gc + 1) & tbl->hash_mask); - np = &tbl->hash_buckets[i]; - while ((n = *np) != NULL) { - unsigned state; - - write_lock(&n->lock); - - state = n->nud_state; - if (state & (NUD_PERMANENT | NUD_IN_TIMER)) { - write_unlock(&n->lock); - goto next_elt; - } + while ((n = *np) != NULL) { + unsigned int state; - if (time_before(n->used, n->confirmed)) - n->used = n->confirmed; + write_lock(&n->lock); - if (atomic_read(&n->refcnt) == 1 && - (state == NUD_FAILED || - time_after(now, n->used + n->parms->gc_staletime))) { - *np = n->next; - n->dead = 1; - write_unlock(&n->lock); - neigh_release(n); - continue; - } + state = n->nud_state; + if (state & (NUD_PERMANENT | NUD_IN_TIMER)) { write_unlock(&n->lock); + goto next_elt; + } -next_elt: - np = &n->next; + if (time_before(n->used, n->confirmed)) + n->used = n->confirmed; + + if (atomic_read(&n->refcnt) == 1 && + (state == NUD_FAILED || + time_after(now, n->used + n->parms->gc_staletime))) { + *np = n->next; + n->dead = 1; + write_unlock(&n->lock); + neigh_release(n); + continue; } + write_unlock(&n->lock); + +next_elt: + np = &n->next; } - mod_timer(&tbl->gc_timer, now + tbl->gc_interval); + /* Cycle through all hash buckets every base_reachable_time/2 ticks. + * ARP entry timeouts range from 1/2 base_reachable_time to 3/2 + * base_reachable_time. + */ + expire = tbl->parms.base_reachable_time >> 1; + expire /= (tbl->hash_mask + 1); + if (!expire) + expire = 1; + + mod_timer(&tbl->gc_timer, now + expire); + write_unlock(&tbl->lock); } @@ -1324,8 +1331,7 @@ init_timer(&tbl->gc_timer); tbl->gc_timer.data = (unsigned long)tbl; tbl->gc_timer.function = neigh_periodic_timer; - tbl->gc_timer.expires = now + tbl->gc_interval + - tbl->parms.reachable_time; + tbl->gc_timer.expires = now + 1; add_timer(&tbl->gc_timer); init_timer(&tbl->proxy_timer);