Lwip IP包分片重组

1. 开发环境

 操作系统:SylixOS
 编程环境:RealEvo-IDE3.1
 硬件平台:AT9x25开发板


2. 技术实现

SylixOS系统使用的网络协议栈是Lwip协议栈。Lwip是Light Weight (轻型)IP协议,有无操作系统的支持都可以运行。Lwip实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用,它只需十几KB的RAM和40K左右的ROM就可以运行,这使Lwip协议栈适合在低端的嵌入式系统中使用。

Lwip协议栈主要关注的是怎么样减少内存的使用和代码的大小,这样就可以让Lwip适用于资源有限的小型平台例如嵌入式系统。为了简化处理过程和内存要求,Lwip对API进行了裁减,可以不需要复制一些数据。

网络协议栈是以层的结构来实现的。链路层具有最大传输单元MTU这个特性,它限制了数据帧的最大长度,不同的网络类型都有一个上限值。以太网的MTU是1500。如果IP层有数据包要传,而且数据包的长度超过了MTU,那么IP层就要对数据包进行分片(fragmentation)操作,使每一片的长度都小于或等于MTU。我们假设要传输一个UDP数据包,以太网的MTU为1500字节,一般IP首部为20字节,UDP首部为8字节,数据的净荷(payload)部分预留是1500-20-8=1472字节。如果数据部分大于1472字节,就会出现分片现象。

本篇文章主要介绍Lwip里对收到的IP分片报文重组的实现。

2.1 IP报文重组宏观分析

这里写图片描述
图 2 1 IP包重组框图
IP包的重组的简单流程如图2-1所示。

首先,Lwip协议里会有一个单向链表,每个结点是一个ip_reassdata的结构体,reassdatagrams指向这个链表。

ip_reassdata结点用来进行分片包的重组,每个结点对应着一个完整的IP包。这个结构体里有一个指向pbuf的成员。当一个IP报文通过ip4_input向上层传输时,会检测是否属于分片包,如果是,则需要进行分片重组。

重组时,会从reassdatagrams链表里查找是否已经有ip_reassdata这个结构体了,如果有,就会改变每个分片包的报头,这里是通过一个ip_reass_helper结构体改变的。改变完之后,会把这个分片包根据偏移插入到ip_reassdata这个结构体后面对应的位置。如果在reassdatagrams链表里查找不到对应的ip_reassdata这个结构体,那么说明这个分片包是收到帧的第一个报文,因此会创建一个新的ip_reassdata结构体,然后再进行后续操作。插入完成后,协议栈会检测报文是否全部接收并重组完成。如果完成,就会从reassdatagrams链表中把ip_reassdata结构体删除并把重组好的报文返回给ip4_input。

2.2 代码分析

IP包的分片重组是通过ip4_reass 这个函数来完成的。判断需要重组时都会调用这个函数,这个函数的主要内容如下:
1. 对收到的IP报文的首部长度检测,Lwip目前是不支持IP报文头带填充位的。
2. 通过IP报文头,获得偏移和数据报文的长度。
3. lwip的一个特性:它对reassdatagrams链表上的pbuf的总数是有限制的,因此协议栈会判断加上收到的这些pbuf的个数后,会不会超过这个限制。
4. 如果超过了,会删除链表中存在时间最长的那个。
5. 从链表中寻找对当前的pbuf对应的ip_reassdata结构体。如果没有,则会新创建一个结构体。
6. 现在应该已经找到一个合适的 ip_reassdata结构体了,此时会做一个判断:如果当前的这个IP报文的偏移为0并且此时的 ip_reassdata结构体的偏移也不等于0,那么需要把当前的这个IP分片报文的头部拷贝到 ip_reassdata结构体中。
7. 检测当前收到的IP分片报文是不是最后一个,如果是最后一个,那么,就更新一下当前IP分片报文对应的 ip_reassdata结构体。
8. 上述两个检测完成之后,会调用ip_reass_chain_frag_into_datagram_and_validate,找到一个合适的地方,把IP分片包插进去。
9. 检测当前的报文是否组装完成,如果完成,返回一个非0的值。否则,返回0。
10. 上述检测结果如果是没有完成,则ip4_reass 直接返回。如果完成了,则会对 ip_reassdata结构体的iphdr字段做修改,包括报文总长度、校验和,并且把iphdr字段全部拷贝到第一个分片包的头部,这样,整个IP包的信息就出现在第一个分片包的信息里。
11. 接下来,把其他的IP分片包的的信息头删除,这样一个完整的IP包就重组完成了。
12. 最后,调用 ip_reass_dequeue_datagram 将ip_reassdata结构体从整个链表中删除。 代码执行到这里,整个重组基本完成。

3. 参考资料

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值