概述

在分配邻居子系统之后,会设置定时器来处理那些需要定时器处理的状态,定时器回调函数为neigh_timer_handler;函数会根据状态机变换规则对状态进行切换,切换状态后,如果需要更新输出函数则更新,并更新定时器下一次超时时间;其中NUD_INCOMPLETE | NUD_PROBE状态需要发送邻居请求,如果超过最大次数,则释放缓存中的数据包;

源码分析
 /* 邻居项各个状态的定时器处理回调 */
static void neigh_timer_handler(unsigned long arg)
{
unsigned long now, next;
struct neighbour *neigh = (struct neighbour *)arg;
unsigned int state;
int notify = ; write_lock(&neigh->lock); state = neigh->nud_state;
now = jiffies;
next = now + HZ; /* 无定时器状态 */
if (!(state & NUD_IN_TIMER))
goto out; /* REACHABLE状态 */
if (state & NUD_REACHABLE) {
/* 确认时间未超时,设置下次超时时间 */
if (time_before_eq(now,
neigh->confirmed + neigh->parms->reachable_time)) {
neigh_dbg(, "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(, "neigh %p is delayed\n", neigh);
/* 进入DELAY状态 */
neigh->nud_state = NUD_DELAY;
neigh->updated = jiffies; /* 更新output函数 */
neigh_suspect(neigh);
next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
}
/* 确认时间和闲置时间都超时了 */
else {
neigh_dbg(, "neigh %p is suspected\n", neigh);
/* 进入STALE状态 */
neigh->nud_state = NUD_STALE;
neigh->updated = jiffies;
/* 更新输出函数 */
neigh_suspect(neigh);
notify = ;
}
}
/* DELAY状态 */
else if (state & NUD_DELAY) {
/* 最后一次确认时间没达到超时时间 */
if (time_before_eq(now,
neigh->confirmed +
NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
neigh_dbg(, "neigh %p is now reachable\n", neigh); /* 进入REACHABLE状态,更新输出函数 */
neigh->nud_state = NUD_REACHABLE;
neigh->updated = jiffies;
neigh_connect(neigh);
notify = ;
next = neigh->confirmed + neigh->parms->reachable_time;
}
/* 最后确认时间已经达到了超时时间,进入PROBE状态 */
else {
neigh_dbg(, "neigh %p is probed\n", neigh);
neigh->nud_state = NUD_PROBE;
neigh->updated = jiffies;
atomic_set(&neigh->probes, );
notify = ;
next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
}
}
/* NUD_PROBE|NUD_INCOMPLETE */
else {
/* NUD_PROBE|NUD_INCOMPLETE */
next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
} /* NUD_PROBE|NUD_INCOMPLETE状态,达到了最大尝试次数 */
if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
/* 进入FAILED状态,清空缓存包队列 */
neigh->nud_state = NUD_FAILED;
notify = ;
neigh_invalidate(neigh);
goto out;
} /* 定时器处理状态,则更新定时器 */
if (neigh->nud_state & NUD_IN_TIMER) {
if (time_before(next, jiffies + HZ/))
next = jiffies + HZ/;
if (!mod_timer(&neigh->timer, next))
neigh_hold(neigh);
} /* NUD_PROBE|NUD_INCOMPLETE状态,发送请求包 */
if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
neigh_probe(neigh);
} else {
out:
write_unlock(&neigh->lock);
} /* 通知关心的模块 */
if (notify)
neigh_update_notify(neigh, ); neigh_release(neigh);
}

邻居子系统 之 状态定时器回调neigh_timer_handler的更多相关文章

  1. 邻居子系统 之 更新neigh_update

    概述 neigh_update函数用来更新指定的邻居项,更新内容是硬件地址和状态,更新之后,会根据新状态设置其输出函数,CONNECTED状态则使用快速输出,否则使用慢速输出:如果是由原来的无效状态变 ...

  2. 邻居子系统 之 邻居项创建__neigh_create

    概述 IP层输出数据包会根据路由的下一跳查询邻居项,如果不存在则会调用__neigh_create创建邻居项,然后调用邻居项的output函数进行输出: __neigh_create完成邻居项的创建, ...

  3. 邻居子系统输出 之 neigh_output、neigh_hh_output

    概述 ip层在构造好ip头,检查完分片之后,会调用邻居子系统的输出函数neigh_output进行输出,输出分为有二层头缓存和没有两种情况,有缓存时调用neigh_hh_output进行快速输出,没有 ...

  4. jQuery使用():Deferred有状态的回调列表(含源码)

    deferred的功能及其使用 deferred的实现原理及模拟源码 一.deferred的功能及其使用 deferred的底层是基于callbacks实现的,建议再熟悉callbacks的内部机制前 ...

  5. 邻居子系统 之 邻居表的初始化neigh_table_init

    概述 邻居子系统支持多种实现,例如ARP,ND等,这些实现需要在其初始化的时候,调用neigh_table_init将邻居表项添加到全局邻居子系统数组中,并对实例中的字段(如hash,定时器等)进行相 ...

  6. Linux时间子系统之四:定时器的引擎:clock_event_device

    早期的内核版本中,进程的调度基于一个称之为tick的时钟滴答,通常使用时钟中断来定时地产生tick信号,每次tick定时中断都会进行进程的统计和调度,并对tick进行计数,记录在一个jiffies变量 ...

  7. Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()

    我们已经在前面几章介绍了低分辨率定时器和高精度定时器的实现原理,内核为了方便其它子系统,在时间子系统中提供了一些用于延时或调度的API,例如msleep,hrtimer_nanosleep等等,这些A ...

  8. Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()【转】

    转自:http://blog.csdn.net/droidphone/article/details/8104433 我们已经在前面几章介绍了低分辨率定时器和高精度定时器的实现原理,内核为了方便其它子 ...

  9. Linux时间子系统之四:定时器的引擎:clock_event_device【转】

    本文转载自:http://blog.csdn.net/droidphone/article/details/8017604 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+] ...

随机推荐

  1. [转载]clip gradient抑制梯度爆炸

    [转载]clip gradient抑制梯度爆炸 来源:https://blog.csdn.net/u010814042/article/details/76154391 1.梯度爆炸的影响 在一个只有 ...

  2. Vector , list 和 deque的区别

     vector   表示一段连续的内存区域,每个元素被顺序存储在这段内存中,对vector   的随机访问效率很高,但对非末尾元素的插入和删除则效率非常低.  deque    也表示一段连续的内存区 ...

  3. js对象中属性调用.和[] 两种方式的区别

    JS 调用属性一般有两种方法——点和中括号的方法. 标准格式是对象.属性(不带双引号),注意一点的是:js对象的属性,key标准是不用加引号的,加也可以,特别的情况必须加,如果key数字啊,表达式啊等 ...

  4. CHD-5.3.6集群安装

    我是基于Apache-hadoop2.7.3版本安装成功后,已有的环境进行安装chd-5..6 已用的环境: JDK版本: java version "1.8.0_191" Jav ...

  5. 【SpringBoot】Web开发

    一.简介 1.1 引入SpringBoot模块 1.2 SpringBoot对静态资源的映射规则 二.模版引擎 2.1 简介 2.2 引入thymeleaf 2.3 Thymeleaf使用 一.简介 ...

  6. 【异常】‘for’ loop initial declarations are only allowed in C99 mode

    1 Python版本导致的异常 /root/Python-3.5.7/Modules/_pickle.c: In function ‘PyMemoTable_Copy’: /root/Python-3 ...

  7. DNSMASQ 部分选项 设置

    --local-service 仅接受地址位于本地子网上的主机(即服务器上存在接口的子网)的DNS查询.仅当没有--interface,-- except-interface,--listen-add ...

  8. jQuery表单验证正则表达式-简单

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...

  9. delphi xe5 fastreport4.14 中文很多时换行不正确

    用一般的frxMEMOview 中文换行是瞎换,缺少数据,换成frxrichview 即可, frxrichview 使用注意点 1).Delphi中文很多时换行不正确 2).要在窗体上拖一个frxr ...

  10. D. Happy Tree Party CodeForces 593D【树链剖分,树边权转点权】

    Codeforces Round #329 (Div. 2) D. Happy Tree Party time limit per test 3 seconds memory limit per te ...