[文/告别年代   Email:byeyear@hotmail.com]

重大修订记录

-----------------------------------------

2016.11.03

感谢@ wayne88 指出(见文后讨论帖),对本文所述的NETIF_FLAG_UP标记和有效IP地址之间的关系,lwip代码作者其实是存有疑虑的。见以下链接:

http://savannah.nongnu.org/bugs/?func=detailitem&item_id=37068

所幸该链接不会影响本文内容。对1.4.1版代码,代码作者仍然采用了如本文所述的、他认为可能是“unclear”的做法。

注意

-----------------------------------------

本文基于lwip-1.4.1,若文章与代码对不上,请确认代码版本。

基本流程

-----------------------------------------

A. link up -> link down:

关闭MAC和DMA;

调用netif_set_link_down

B. link down -> link up:

打开MAC和DMA;

调用netif_set_link_up

C. 注意:当使用RAW API时,所有使用RAW API的代码(包括处理链路状态的代码)必须运行于同一线程环境。

-----------------------------------------

代码分析

-----------------------------------------

有四个函数和两个标志位和链路状态改变有关:

A. netif_set_up

该函数设置NETIF_FLAG_UP标记,并在链路已up(NETIF_FLAG_LINK_UP有效)的情况下发送arp探测。

/* 删除了部分预编译条件和无关代码 */
void netif_set_up(struct netif *netif)
{
if (!(netif->flags & NETIF_FLAG_UP)) {
netif->flags |= NETIF_FLAG_UP;
/* 链路有效情况下发送ARP探测 */
if (netif->flags & NETIF_FLAG_LINK_UP) {
if (netif->flags & (NETIF_FLAG_ETHARP)) {
etharp_gratuitous(netif);
}
}
}
}

如果你的网络使用静态IP,那么在lwip初始化时调用该函数;

如果你的网络使用DHCP,那么DHCP成功后lwip会帮你调用netif_set_up。

B. netif_set_down

除非你需要关闭网络,否则一般不需要主动调用该函数。

C. netif_set_link_up

该函数设置NETIF_FLAG_LINK_UP标记,启动DHCP和AutoIP,并在NETIF_FLAG_UP标记有效的情况下发送arp探测。

void netif_set_link_up(struct netif *netif )
{
if (!(netif->flags & NETIF_FLAG_LINK_UP)) {
netif->flags |= NETIF_FLAG_LINK_UP;
if (netif->dhcp) {
dhcp_network_changed(netif);
}
/* ...其它代码(autoip相关)... */
if (netif->flags & NETIF_FLAG_UP) {
if (netif->flags & NETIF_FLAG_ETHARP) {
etharp_gratuitous(netif);
}
}
NETIF_LINK_CALLBACK(netif);
}
}

当驱动程序检测到链路从down变化为up时,重新初始化MAC和DMA,然后调用该函数。

注意:初始化时如果链路有效,low_level_init直接设置NETIF_FLAG_LINK_UP,而不调用netif_set_link_up函数,避免在lwip没有完全初始化好时启动DHCP。

D. netif_set_link_down

当驱动程序检测到链路从up变为down时调用该函数,并关闭MAC和DMA。

E. NETIF_FLAG_UP和NETIF_FLAG_LINK_UP

前者表示lwip协议栈已经就绪(已得到合法IP地址,且协议栈已准备好收发数据包);后者表示链路层有效。

或者说,一个是软件(协议栈)就绪标志,一个是硬件(链路层)就绪标志。

F. 参考lwip代码中的netif.h文件对这两个标记的详细说明。

网上很多port代码不管是否使用DHCP都在lwip初始化时设置NETIF_FLAG_UP,这是*不*正确的。

NETIF_FLAG_UP必须在获得有效IP地址后才能置位,以保证顺利发送ARP探测。

所以,如果使用了DHCP,那么初始化时就不能设置NETIF_FLAG_UP。

LwIP会在链路有效情况下发送DHCP请求,并在拿到有效IP地址后为你设置NETIF_FLAG_UP。

情景分析

--------------------------------------------------------------

A. 静态IP,初始化时链路有效

这是最简情况。驱动层会看到Link有效,并直接设置NETIF_FLAG_LINK_UP。

随后lwip初始化过程中调用netif_set_up,该函数设置NETIF_FLAG_UP,并发送arp探测。

B. 静态IP,初始化时链路无效

驱动层不会设置NETIF_FLAG_LINK_UP。

lwip初始化过程会调用netif_set_up,该函数看到没有link,除了设置NETIF_FLAG_UP标记外不会做任何事。

当链路变为有效后,驱动层调用netif_set_link_up,发送arp探测。

C. 动态IP,初始化时链路有效

驱动层直接设置NETIF_FLAG_LINK_UP。

lwip初始化过程中调用dhcp_start,启动DHCP过程。

但lwip初始化过程不会调用netif_set_up,因为还没有获得有效IP地址。

获得有效IP后,lwip会帮我们调用netif_set_up,发送arp探测。

D. 动态IP,初始化时链路无效

驱动层不会设置NETIF_FLAG_LINK_UP。

lwip初始化过程中仍然会调用dhcp_start。对dhcp_start的调用是必须的,因为dhcp过程需要的资源将在该函数中分配。

等到链路有效后驱动层调用netif_set_link_up,该函数会启动DHCP过程。

获得有效IP后,lwip会帮我们调用netif_set_up,发送arp探测。

E. 静态IP,链路断开后重建

链路断开时netif_set_link_down,重建后netif_set_link_up发送arp探测。

NETIF_FLAG_UP在设置后就一直有效。

F. 动态IP,链路断开后重建

链路重建后netif_set_link_up重新启动DHCP过程,该过程会清除NETIF_FLAG_UP标记。

DHCP完成后lwip自动调用netif_set_up重新置位该标记并发起arp探测。

总结

-------------------------------------------------------------------------------------

1. 使用静态IP

low_level_init根据当前链路状态设置或不设置NETIF_FLAG_LINK_UP;

lwip初始化时调用netif_set_up;

链路状态改变时调用netif_set_link_up/netif_set_link_down。

2. 使用动态IP

low_level_init根据当前链路状态设置或不设置NETIF_FLAG_LINK_UP;

lwip初始化时调用dhcp_start;

链路状态改变时调用netif_set_link_up/netif_set_link_down;

不要在使用动态IP时直接调用netif_set_up,而是由lwip协议栈代码在成功获得IP后为你调用这个函数。

[文/告别年代   Email:byeyear@hotmail.com]

LwIP:处理链路状态改变的更多相关文章

  1. 【ISIS(中间系统到中间系统)路由链路状态信息协议初识】

    ISIS单区域的基本配置 一:根据项目需求,考虑到组网的规模和条件,部署ISIS单区域的拓扑图如下: 二:配置 1:首先对RTA进行配置,在系统视图创建ISIS进程:进入ISIS配置视图,指定IS的级 ...

  2. iOS:使用代理模式监听开关状态改变事件

    记一次解决跨控制器监听开关状态改变的尝试. 为了统一设置UITableViewCell里的内容,自定义了UITableViewCell类的一个基类,命名为SettingCell.SettingCell ...

  3. stat file 查看文件的 最新的被访问时间 最近的修改时间 最近的状态改变时间

    [root@NB ~]# stat /media/6FE5-D831/git-data/IT-DOC/web收藏.txt File: `/media/6FE5-D831/git-data/IT-DOC ...

  4. OSPF(Open Shortest Path First开放式最短路径优先 -链路状态路由协议

    OSPF分为OSPFv2和OSPFv3两个版本,其中OSPFv2用在IPv4网络,OSPFv3用在IPv6网络 思科OSPF的协议管理距离(AD)是110,华为OSPF的协议管理距离是10 通告网络接 ...

  5. Spark系列(六)Master注册机制和状态改变机制

    各组件的注册流程如下图: 注册机制源码说明: 入口:org.apache.spark.deploy.master文件下的receiveWithLogging方法中的case RegisterAppli ...

  6. javascript 中状态改变触发事件

    转 有限状态机:是一个非常有用的模型,可以模拟世界上大部分事物. 它有三个特征: * 状态总数(state)是有限的. * 任一时刻,只处在一种状态之中. * 某种条件下,会从一种状态转变(trans ...

  7. s5-14 链路状态路由选择

    为什么DV逐渐让位于LS? DV  站的不高,看得不远  完全相信邻居 LS  想办法站得高,看更远  多高.多远?  怎么做? 链路状态路由(Link State) 主要思想 发现 它的邻 ...

  8. dfs带状态改变的做法

    所谓带状态改变是指:在搜索到某个位置的时候,状态发生改变,继续计算步数. 给一个例题: 蒜头君要回家,但是他家的钥匙在他的朋友花椰妹手里,他要先从花椰妹手里取得钥匙才能回到家.花椰妹告诉他:“你家的钥 ...

  9. 微信小程序开发——列表分页上拉加载封装实现(订单列表为例,订单状态改变后刷新列表滚动位置不变)

    业务需求: 业务需求是给订单列表添加分页功能,也就是上拉加载这种每次只请求加载固定数量的数据. 需求分析: 对业务来说就是简单的分页上拉加载,但是对于技术实现来说,除了要处理分页数据的累加加载,还要处 ...

随机推荐

  1. node.js express 4.x 安装指南 (找了很久呀,痛苦之路)

    问题出现这,版本的问题,还有express4.0以上的版本启动node app.js指令的变更,蛋疼.参考这个

  2. typedef struct用法详解与小结

    1.基本解释 typedef为C语言的关键字,作用是为一种数据类型定义一个新名字,这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等). 在编程中使用typedef ...

  3. Oracle11g 查询长时间运行的SQL

    一.大量的查询 某些时候,因为SQL的问题,导致数据库的session大量积压,服务器的磁盘读增大,CPU使用率剧增.一般这种SQL,都是一些全表扫描.多表关联.报表或者排序类的SQL.这中情况很有可 ...

  4. 2018-2019-2 网络对抗技术 20165202 Exp4 恶意代码分析

    博客目录 一.实践目标 二.实践内容 1.系统运行监控 2.恶意软件分析 三.实验步骤 四.基础问题回答 五.遇到的问题及解决 六.实验总结 一.实践目标 监控你自己系统的运行状态,看有没有可疑的程序 ...

  5. (转)2017年12月宋华教授携IBM中国研究院、猪八戒网、中航信托、33复杂美共同论道智慧供应链金融

    今年10月,国务院发布的<关于积极推进供应链创新与应用的指导意见>,不仅强调了发展服务型制造的重要性,同时也指出要积极稳妥发展供应链金融,推动供应链金融服务实体经济,鼓励商业银行.供应链核 ...

  6. jeecms系统使用介绍——通过二次开发实现对word、pdf、txt等上传附件的全文检索

    转载请注明出处:http://blog.csdn.net/dongdong9223/article/details/76912307 本文出自[我是干勾鱼的博客] 之前在文章<基于Java的门户 ...

  7. Spring Cloud Sleuth进阶实战

    转载请标明出处: http://blog.csdn.net/forezp/article/details/76795269 本文出自方志朋的博客 为什么需要Spring Cloud Sleuth 微服 ...

  8. specified属性

  9. React中如何优雅的捕捉事件错误

    React中如何优雅的捕捉事件错误 前话 人无完人,所以代码总会出错,出错并不可怕,关键是怎么处理. 我就想问问大家react的错误怎么捕捉呢? 这个时候: 小白:怎么处理? 小白+: ErrorBo ...

  10. 【LGR-054】洛谷10月月赛II

    [LGR-054]洛谷10月月赛II luogu 成功咕掉Codeforces Round #517的后果就是,我\(\mbox{T4}\)依旧没有写出来.\(\mbox{GG}\) . 浏览器 \( ...