/* Called when a timer expires for a neighbour entry. */
static void neigh_timer_handler(unsigned long arg)
{
unsigned long now, next;
struct neighbour *neigh = (struct neighbour *)arg;
unsigned int state;
int notify = 0;
write_lock(&neigh->lock);
state = neigh->nud_state;
now = jiffies;
next = now + HZ;
if (!(state & NUD_IN_TIMER))
goto out;
//NUD_REACHABLE状态
//1.超时前收到邻居确认报文,包括arp_process中收到arp reply和三层确认报文 ---> NUD_REACHABLE
//2.超时前未收到邻居确认报文,但是主机使用过该表项 ---> NUD_DELAY
//3.超时前未收到邻居确认报文,并且主机未使用过 ---> NUD_STALE
//4.更新下一次检查时间next
if (state & NUD_REACHABLE) {
if (time_before_eq(now,
neigh->confirmed + neigh->parms->reachable_time)) {
neigh_dbg(2, "neigh %p is still alive\n", neigh);
next = neigh->confirmed + neigh->parms->reachable_time;
} else if (time_before_eq(now,
neigh->used +
NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
neigh_dbg(2, "neigh %p is delayed\n", neigh);
neigh->nud_state = NUD_DELAY;
neigh->updated = jiffies;
neigh_suspect(neigh);
next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
} else {
neigh_dbg(2, "neigh %p is suspected\n", neigh);
neigh->nud_state = NUD_STALE;
neigh->updated = jiffies;
neigh_suspect(neigh);
notify = 1;
}
}
//NUD_DELAY状态
//1.超时前接收到邻居确认报文 ---> NUD_REACHABLE
//2.超时前未接收到邻居确认报文 ---> NUD_PROBE
//3.更新下一次检查时间next
else if (state & NUD_DELAY) {
if (time_before_eq(now,
neigh->confirmed +
NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
neigh_dbg(2, "neigh %p is now reachable\n", neigh);
neigh->nud_state = NUD_REACHABLE;
neigh->updated = jiffies;
neigh_connect(neigh);
notify = 1;
next = neigh->confirmed + neigh->parms->reachable_time;
} else {
neigh_dbg(2, "neigh %p is probed\n", neigh);
neigh->nud_state = NUD_PROBE;
neigh->updated = jiffies;
atomic_set(&neigh->probes, 0);
next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
}
}
//NUD_PROBE 和 NUD_INCOMPLETE
//1.更新下一次检查时间next
else {
/* NUD_PROBE|NUD_INCOMPLETE */
next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
}
//NUD_INCOMPLETE 和 NUD_PROBE状态
//1.发送arp请求
//2.arp请求次数超限 ---> NUD_FAILED
if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
#if defined(CONFIG_RTL867X_IPTABLES_FAST_PATH)
if (FastPath_Enabled() && (neigh->nud_state & NUD_VALID)) {
rtl867x_delArp(*(u32*)neigh->primary_key);
}
#endif
neigh->nud_state = NUD_FAILED;
notify = 1;
neigh_invalidate(neigh);
goto out;
}
if (neigh->nud_state & NUD_IN_TIMER) {
if (time_before(next, jiffies + HZ/2))
next = jiffies + HZ/2;
if (!mod_timer(&neigh->timer, next))
neigh_hold(neigh);
}
if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
neigh_probe(neigh);
} else {
out:
write_unlock(&neigh->lock);
}
if (notify)
neigh_update_notify(neigh);
#if defined(CONFIG_RTL867X_IPTABLES_FAST_PATH)
if (FastPath_Enabled()) {
if ((neigh->nud_state & NUD_VALID) && !(state & NUD_VALID)) {
rtl867x_addArp(*(u32*)neigh->primary_key, (ether_t*)neigh->ha, ARP_NONE);
} else if ((state & NUD_VALID) && !(neigh->nud_state & NUD_VALID)) {
rtl867x_delArp(*(u32*)neigh->primary_key);
}
}
#endif
neigh_release(neigh);
}
主要流程:
- NUD_REACHABLE状态
- 超时前收到邻居确认报文,包括arp_process中收到arp reply和三层确认报文 ---> NUD_REACHABLE [reachable_time]
- 超时前未收到邻居确认报文,但是主机使用过该表项 ---> NUD_DELAY [DELAY_PROBE_TIME]
- 超时前未收到邻居确认报文,并且主机未使用过 ---> NUD_STALE
- 更新下一次检查时间next
- NUD_DELAY状态
- 超时前接收到邻居确认报文 ---> NUD_REACHABLE [DELAY_PROBE_TIME]
- 超时前未接收到邻居确认报文 ---> NUD_PROBE [DELAY_PROBE_TIME]
- 更新下一次检查时间next
- NUD_PROBE和NUD_PROBE状态
- 更新下一次检查时间next
- 发送arp请求
- arp请求次数超限 ---> NUD_FAILED [neigh_max_probes]