linux网络协议栈neigh_timer_handler


/* 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);
}

主要流程:

  1. NUD_REACHABLE状态 
    1. 超时前收到邻居确认报文,包括arp_process中收到arp reply和三层确认报文   ---> NUD_REACHABLE     [reachable_time]
    2. 超时前未收到邻居确认报文,但是主机使用过该表项                                            ---> NUD_DELAY                 [DELAY_PROBE_TIME]
    3. 超时前未收到邻居确认报文,并且主机未使用过                                                    ---> NUD_STALE
    4. 更新下一次检查时间next
  2. NUD_DELAY状态
    1. 超时前接收到邻居确认报文                                                                                        ---> NUD_REACHABLE     [DELAY_PROBE_TIME]
    2. 超时前未接收到邻居确认报文                                                                                    ---> NUD_PROBE                [DELAY_PROBE_TIME]
    3. 更新下一次检查时间next
  3. NUD_PROBE和NUD_PROBE状态
    1. 更新下一次检查时间next
    2. 发送arp请求
    3. arp请求次数超限                                                                                                          ---> NUD_FAILED                  [neigh_max_probes]                                                       

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值