neigh_add_timer(neigh, next); 
if (!mod_timer(&neigh->timer, next)) neigh_hold(neigh); 
static void neigh_timer_handler(unsigned long arg){	unsigned long now, next;	struct neighbour *neigh = (struct neighbour *)arg;	unsigned state;	int notify = 0;	write_lock(&neigh->lock);	state = neigh->nud_state;	now = jiffies;	next = now + HZ;	if (!(state & NUD_IN_TIMER)) {#ifndef CONFIG_SMP		printk(KERN_WARNING "neigh: timer & !nud_in_timer\n");#endif		goto out;	}	if (state & NUD_REACHABLE) {		if (time_before_eq(now, 				   neigh->confirmed + neigh->parms->reachable_time)) {			NEIGH_PRINTK2("neigh %p is still alive.\n", neigh);			next = neigh->confirmed + neigh->parms->reachable_time;		} else if (time_before_eq(now,					  neigh->used + neigh->parms->delay_probe_time)) {			NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);			neigh->nud_state = NUD_DELAY;			neigh_suspect(neigh);			next = now + neigh->parms->delay_probe_time;		} else {			NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);			neigh->nud_state = NUD_STALE;			neigh_suspect(neigh);		}	} else if (state & NUD_DELAY) {		if (time_before_eq(now, 				   neigh->confirmed + neigh->parms->delay_probe_time)) {			NEIGH_PRINTK2("neigh %p is now reachable.\n", neigh);			neigh->nud_state = NUD_REACHABLE;			neigh_connect(neigh);			next = neigh->confirmed + neigh->parms->reachable_time;		} else {			NEIGH_PRINTK2("neigh %p is probed.\n", neigh);			neigh->nud_state = NUD_PROBE;			atomic_set(&neigh->probes, 0);			next = now + neigh->parms->retrans_time;		}	} else {		/* NUD_PROBE|NUD_INCOMPLETE */		next = now + neigh->parms->retrans_time;	}	if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&	    atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {		struct sk_buff *skb;		neigh->nud_state = NUD_FAILED;		notify = 1;		NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);		NEIGH_PRINTK2("neigh %p is failed.\n", neigh);		/* It is very thin place. report_unreachable is very complicated		   routine. Particularly, it can hit the same neighbour entry!		   So that, we try to be accurate and avoid dead loop. --ANK		 */		while (neigh->nud_state == NUD_FAILED &&		       (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {			write_unlock(&neigh->lock);			neigh->ops->error_report(neigh, skb);			write_lock(&neigh->lock);		}		skb_queue_purge(&neigh->arp_queue);	}	if (neigh->nud_state & NUD_IN_TIMER) {		neigh_hold(neigh);		if (time_before(next, jiffies + HZ/2))			next = jiffies + HZ/2;		neigh_add_timer(neigh, next);	}	if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {		struct sk_buff *skb = skb_peek(&neigh->arp_queue);		/* keep skb alive even if arp_queue overflows */		if (skb)			skb_get(skb);		write_unlock(&neigh->lock);		neigh->ops->solicit(neigh, skb);		atomic_inc(&neigh->probes);		if (skb)			kfree_skb(skb);	} else {out:		write_unlock(&neigh->lock);	}#ifdef CONFIG_ARPD	if (notify && neigh->parms->app_probes)		neigh_app_notify(neigh);#endif	neigh_release(neigh);}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/6fb9974f49f7a6032118c5b6caa6e08e7097913e/neighbour.c/clean/net/core/neighbour.c