邻居项的垃圾回收
为了避免浪费不必要的存储空间,邻居子系统维护着一套垃圾回收机制,它将失效的或者是长时间末使用的邻居项删除。
回忆一下,在邻居表(neigh_table)中有一个定时器struct timer_list gc_timer结构,我们看它是怎么初始化的。
在neigh_table_init()中
{
…
….
init_timer(&tbl->gc_timer);
tbl->gc_timer.data= (unsigned long)tbl;
tbl->gc_timer.function = neigh_periodic_timer;
tbl->gc_timer.expires= now + 1;
add_timer(&tbl->gc_timer;
…
}
在一滴答之后,计时器超时,运行计时器处理函数neigh_periodic_timer()
static void neigh_periodic_timer(unsigned long arg)
{
struct neigh_table *tbl = (struct neigh_table *)arg;
struct neighbour *n, **np;
unsigned long expire, now = jiffies;
NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
write_lock(&tbl->lock);
/*
*periodically recompute ReachableTime from random function
*/
//每300HZ随机初始化REACHABLE状态超时时间
if (time_after(now, tbl->last_rand + 300 * HZ)) {
struct neigh_parms *p;
tbl->last_rand = now;
for (p = &tbl->parms; p; p = p->next)
p->reachable_time =
neigh_rand_reach_time(p->base_reachable_time);
}
//hash_chain_gc在初始化函数中并末处理
//所以,此处为零
np = &tbl->hash_buckets[tbl->hash_chain_gc];
//使hash_chain_gc指向下一项,如过超过最大值hash_mash
//则又返回到初始值
tbl->hash_chain_gc = ((tbl->hash_chain_gc + 1) & tbl->hash_mask);
while ((n = *np) != NULL) {
unsigned int state;
write_lock(&n->lock);
state = n->nud_state;
//如果对应的是静态项,或者正在被计时器初始状态
if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
write_unlock(&n->lock);
goto next_elt;
}
//如果使用时间超过了被证实时间
//则调整使用时间
if (time_before(n->used, n->confirmed))
n->used = n->confirmed;
//如果引用计数为1,且状态为FAILED,则状其删除,并
//释放其所占的空间
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;
}
/* 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);
}