Linux内核网络部分---IP数据报文分片重组

本文介绍Linux系统中IP报文的分片原理及重组方法。重点讲解如何判断IP报文是否已分片,以及如何利用哈希表进行分片重组。同时,介绍了Wireshark在网络分析中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当Linux系统接收到一个IP报文时,判断IP报文是否是有分片,如果未分片的话,则直接返回该报文。否则,进行IP报文重组的处理。

问题1:如何判断IP数据报文是否有分片;

IP数据报分片的原因:物理网络层一般要限制每次发送数据帧的最大长度(MTU46-1500字节),把一份IP数据报分片以后,只有到达目的地才进行重新组装(这里的重新组装与其他网络协议不同,它们要求在下一站就进行进行重新组装,而不是在最终的目的地),已经分片过的数据报有可能会再次进行分片(可能不止一次)。 

当IP数据报被分片后,每一片都成为一个分组,具有自己的IP首部,并在选择路由时与其他分组独立。这样,当数据报的这些片到达目的端时有可能会失序,但是在IP首部中有足够的信息让接收端能正确组装这些数据报片。

尽管IP分片过程看起来是透明的,但有一点让人不想使用它:即使只丢失一片数据也要重传整个数据报。因为IP层本身没有超时重传的机制——由更高层来负责超时和重传(TCP有超时和重传机制,但UDP没有。一些UDP应用程序本身也执行超时和重传)。当来自TCP报文段的某一片丢失后,TCP在超时后会重发整个TCP报文段,该报文段对应于一份IP数据报。没有办法只重传数据报中的一个数据报片。事实上,如果对数据报分片的是中间路由器,而不是起始端系统,那么起始端系统就无法知道数据报是如何被分片的。就这个原因,经常需要避免分片。如果60120秒后(IP_FRAG_TIME常量指定。(30HZ))重组队列内包未到齐则重组过程失败重组队列被释放,同时向发送方以ICMP协议通知失败信息重组队列的内存消耗不得大于256k(sysctl_ipfrag_high_thresh), 否则将会调用(ip_evictor)释放每支散列尾端的重组队列.




判断IP数据报文是否还有分片:

1、对于每份IP数据报来说,其标识字段都包含一个唯一值。该值在数据报分片时被复制到每个片中。

2、标志字段用其中一个比特来表示“更多的片”,除了最后一片外,其他每个组成数据报的片都要把该比特MF置 1。

3、片偏移字段指的是该片偏移原始数据报开始处的位置。另外,当数据报被分片后,每个片的总长度值要改为该片的长度值。(IdentificationR DF MF Fragment Offset

对应于写1473字节的IP数据报长度为1501,就必须进行分片(第 3行和第4行)。第一片数据长度1500 = 20字节IP部首 + 8字节UDP部首 +1472字节数据。第二片数据长度 = 20字节IP部首 + 1字节数据。

    wireshark是非常流行的网络封包分析软件,功能十分强大。可以截取各种网络封包,显示网络封包的详细信息。使用wireshark的人必须了解网络协议,否则就看不懂wireshark了。为了安全考虑,wireshark只能查看封包,而不能修改封包的内容,或者发送封包。

wireshark是捕获机器上的某一块网卡的网络包,当你的机器上有多块网卡的时候,你需要选择一个网卡。

WireShark 主要分为这几个界面

1. Display Filter(显示过滤器),  用于过滤

2. Packet List Pane(封包列表), 显示捕获到的封包, 有源地址和目标地址,端口号。 颜色不同,代表

3. Packet Details Pane(封包详细信息), 显示封包中的字段

4. Dissector Pane(16进制数据)

5. Miscellanous(地址栏,杂项)

使用过滤是非常重要的, 初学者使用wireshark时,将会得到大量的冗余信息,在几千甚至几万条记录中,以至于很难找到自己需要的部分。搞得晕头转向。过滤器会帮助我们在大量的数据中迅速找到我们需要的信息。

封包列表(Packet List Pane)封包列表的面板中显示,编号,时间戳,源地址,目标地址,协议,长度,以及封包信息。 你可以看到不同的协议用了不同的颜色显示。

封包详细信息 (Packet Details Pane)

这个面板是我们最重要的,用来查看协议中的每一个字段。

各行信息分别为

Frame:   物理层的数据帧概况

Ethernet II: 数据链路层以太网帧头部信息

Internet Protocol Version 4: 互联网层IP包头部信息

 Transmission Control Protocol:  传输层T的数据段头部信息,此处是TCP

 Hypertext Transfer Protocol:  应用层的信息,此处是HTTP协议

wireshark与对应的OSI七层模型、


TCP包的具体内容

 从下图可以看到wireshark捕获到的TCP包中的每个字段、





问题2:如何对IP数据报文进行分片重组;

哈希表的结构与实现

1.基本概念:

1、散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。数组的特点是:寻址容易,插入和删除困难;而链表的特点是:寻址困难,插入和删除容易。哈希表综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构

2、哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法——Linux内核实现方法:拉链法常见有冲突处理方法还有开放定址法、再散列法建立一个公共溢出区),我们可以理解为“链表的数组”。链地址使用链表存储关键字,可以随时插入新数据,数据量大小不受限制。缺点是要用到指针,给新单元分配地址需要时间,会一定程度上减慢算法速度,但影响不大可以忽略。

3、左边很明显是个数组,数组的每个成员包括一个指针,指向一个链表的头,当然这个链表可能为空,也可能元素很多。我们根据元素的一些特征把元素分配到不同的链表中去,也是根据这些特征,找到正确的链表,再从链表中找出这个元素。元素特征转变为数组下标的方法就是散列法(哈希函数)hash 最重要的是选择适当的hash函数,从而平均的分配关键字在桶中的位置,从而优化查找 插入和删除所用的时间。

4、它是一种单向密码体制,即它是一个从明文到密文的不可逆的映射,只有加密过程,没有解密过程。同时,哈希函数可以将任意长度的输入经过变化以后得到固定长度的输出。hash算法一般用于快速查找和加密。哈希函数当然不止一种,下面列出三种比较常用的:1,除法散列法 :最直观的一种,上图使用的就是这种散列法,公式: index = value % 16;2,平方散列法 ;3,斐波那契(Fibonacci)散列法;

基于BKDRhash实现Hash算法http://www.codeceo.com/article/hash-based-on-bkdrhash.html

报文队列数据结构:


IP分片数据结构:

本文使用的散列函数:

(1)初始化哈希(散列)表,每个单元分配的内存大小为sizeof(ipq_t),前一个节点和下一个节点赋NULL

(2) 先申请一个sk_buff_t缓冲区,再给sk_buff_t的IP分片部首申请sizeof(iphdr_t)大小的空间,存储数据的data数据区则申请一个RESERVE_SIZE + len空间,用于接收IP分片报文

(3)1、从接收到的IP分片报文中,提取偏移地址frag_off和标志位mf,如果都为0,则表示这是一个完整的IP数据包,直接返回。

         2、否则提取IP部首中的IP源地址、目标地址、标识和协议作为哈希函数的输入,根据运算结果求出分片在Hash表的位置。

         3、由于本文构造的哈希表采用的是拉链法,所以需要继续在哈希索引单元的ipq_t链表中查找该分片所属的报文。

         4、找到所属报文后,将分片加入分片链表中,并判断报文是否完整(判断方法是,当检测到标志位mf=0时,累计接收到的                 数据长度len,是否等于mf = 0的分片的偏移地址+该分片的长度),若完整则将所有分片链表的数据都拷出来,并删除其               ipq结点及分片链表。

        5、若是没有找到所属报文,则添加一个新的ipq_t节点。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值