邻居子系统 之 状态定时器回调neigh_timer_handler
概述
在分配邻居子系统之后,会设置定时器来处理那些需要定时器处理的状态,定时器回调函数为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的更多相关文章
- 邻居子系统 之 更新neigh_update
概述 neigh_update函数用来更新指定的邻居项,更新内容是硬件地址和状态,更新之后,会根据新状态设置其输出函数,CONNECTED状态则使用快速输出,否则使用慢速输出:如果是由原来的无效状态变 ...
- 邻居子系统 之 邻居项创建__neigh_create
概述 IP层输出数据包会根据路由的下一跳查询邻居项,如果不存在则会调用__neigh_create创建邻居项,然后调用邻居项的output函数进行输出: __neigh_create完成邻居项的创建, ...
- 邻居子系统输出 之 neigh_output、neigh_hh_output
概述 ip层在构造好ip头,检查完分片之后,会调用邻居子系统的输出函数neigh_output进行输出,输出分为有二层头缓存和没有两种情况,有缓存时调用neigh_hh_output进行快速输出,没有 ...
- jQuery使用():Deferred有状态的回调列表(含源码)
deferred的功能及其使用 deferred的实现原理及模拟源码 一.deferred的功能及其使用 deferred的底层是基于callbacks实现的,建议再熟悉callbacks的内部机制前 ...
- 邻居子系统 之 邻居表的初始化neigh_table_init
概述 邻居子系统支持多种实现,例如ARP,ND等,这些实现需要在其初始化的时候,调用neigh_table_init将邻居表项添加到全局邻居子系统数组中,并对实例中的字段(如hash,定时器等)进行相 ...
- Linux时间子系统之四:定时器的引擎:clock_event_device
早期的内核版本中,进程的调度基于一个称之为tick的时钟滴答,通常使用时钟中断来定时地产生tick信号,每次tick定时中断都会进行进程的统计和调度,并对tick进行计数,记录在一个jiffies变量 ...
- Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()
我们已经在前面几章介绍了低分辨率定时器和高精度定时器的实现原理,内核为了方便其它子系统,在时间子系统中提供了一些用于延时或调度的API,例如msleep,hrtimer_nanosleep等等,这些A ...
- Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()【转】
转自:http://blog.csdn.net/droidphone/article/details/8104433 我们已经在前面几章介绍了低分辨率定时器和高精度定时器的实现原理,内核为了方便其它子 ...
- Linux时间子系统之四:定时器的引擎:clock_event_device【转】
本文转载自:http://blog.csdn.net/droidphone/article/details/8017604 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] ...
随机推荐
- 14.SpringMVC核心技术-类型转换器
类型转换器 在前面的程序中,表单提交的无论是 int 还是 double 类型的请求参数,用于处理该请求 的处理器方法的形参, 均可直接接收到相应类型的相应数据,而非接收到 String 再手工转换. ...
- shell脚本——sed命令
sed 命令 作为行编辑器,对文件进行编辑(以行为单位进行编辑) sed编辑文件,却不改变原文件 sed工作原理: 指定一个文本文件,依次读取文本文件中的每行内容,读取到模式空间中,在模式空间中进行匹 ...
- Delphi 类类型和对象
- jedis五种数据类型的方法解释
常用命令 1)连接操作命令 quit:关闭连接(connection) auth:简单密码认证 help cmd: 查看cmd帮助,例如:help quit 2)持久化 save:将数据同步保存到磁盘 ...
- Gym - 101492I 区间限制费用流
https://cn.vjudge.net/problem/Gym-101492I 如果用单个点代表每个区间 利用拆点来限制区间的流量的话 点是 n^2/2+m个 边是2*n^2条 但是这样会T 解法 ...
- SpringMVC——问题汇总
1.html页面ajax请求/login.后台报: Request method 'GET' not supported 原因: 后台请求使用了method = POST,但是url请求没有formd ...
- jenkins"控制台输出"乱码问题解决
今天在搭建Jenkins环境时,安装完Tomcat.Jenkins.创建项目进行构建后,在查看控制台输出时,结果中文全部显示乱码.然后呢,就是漫长的解决历程,最终呢,解决乱码问题的时间终于超过了环境搭 ...
- [USACO19FEB]Cow Dating——找规律
原题戳这里 题解 显然原题等价于让我们求这个式子\(\prod\limits_{i=l}^{r}(1-p_i)\sum\limits_{i=l}^{r}\frac{p_i}{1-p_i}\)的最大值是 ...
- mysql5.7安装中的问题(服务无法启动。服务没有报告任何错误。排查方法)
1.拒绝访问的问题 权限不够,必须以管理员身份启动命令行 2.MySQL 服务无法启动.服务没有报告任何错误. 进入到你的mysql安装目录,C:\Program Files\MySQL\MySQL ...
- mysql锁定单个表的方法
mysql锁定单个表的方法mysql>lock table userstat read;mysql>unlock tables; 本文来自ChinaUnix博客,如果查看原文请点:http ...