邻居子系统 之 状态定时器回调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 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] ...
随机推荐
- 深入浅出GNU X86-64 汇编
深入浅出GNU X86-64 汇编 来源 https://blog.csdn.net/pro_technician/article/details/78173777 原文 https://www3.n ...
- # 机器学习算法总结-第六天(Adaboost算法)
SKlearn中的Adaboost使用 主要调的参数:第一部分是对我们的Adaboost的框架进行调参, 第二部分是对我们选择的弱分类器进行调参. 使用 Adaboost 进行手写数字识别 导入库,载 ...
- Category与Extension详解
自己做笔录 用来后来回顾.. (一) Category 1.什么是category category是objective-C 2.0之后添加的语言特性,别人口中的分类.类别其实都是指category. ...
- celery最佳体验
目录 目录 不使用数据库作为 Broker 不要过分关注任务结果 实现优先级任务 应用 Worker 并发池的动态扩展 应用任务预取数 保持任务的幂等性 应用任务超时限制 善用任务工作流 合理应用 a ...
- Django—logging配置
我写Django项目常用的logging配置. # Django的日志配置项 BASE_LOG_DIR = os.path.join(BASE_DIR, "log") LOGGIN ...
- PAT Advanced 1020 Tree Traversals (25 分)
1020 Tree Traversals (25 分) Suppose that all the keys in a binary tree are distinct positive integ ...
- Codeforces 1149 B - Three Religions
B - Three Religions 思路:dp dp[i][j][k]:a的前i个和b的前j个和c的前k个能构成的最前面的位置 删字符时状态不用改变,加字符时只会改变1*250*250个状态 代码 ...
- PAT乙级1037
题目链接 https://pintia.cn/problem-sets/994805260223102976/problems/994805284923359232 题解 还算简单,就是模拟我们在生活 ...
- hivesql中的concat函数,concat_ws函数,concat_group函数之间的区别
一.CONCAT()函数CONCAT()函数用于将多个字符串连接成一个字符串.使用数据表Info作为示例,其中SELECT id,name FROM info LIMIT 1;的返回结果为 +---- ...
- web自动化之前端知识
下面这种写法只作用于这1个标签: 下面这种也是比较老的写法: 下面是常用的方式:把一个css样式放入到一个文件中,然后引用: 第三方引用的css一般是压缩过的,这样静态资源加载速度会比较快. 如 ...