网络子系统55_ip协议分片重组_加入ipq
//ip分片加入到正确的ipq结构
//调用路径:ip_defrag->ip_frag_queue// 处理过程:
// 1.正在被释放的ipq,不处理新加入的分片(ipq正在被释放由last_in设置COMPLETE指出)
// 2.处理分片的合法性
// 2.1当该封包为最后一个分片时
// 2.1.1如果之前没有接收到最后一个分片,则该分片在总有效载荷中的结尾位置需要大于等于以推测出的最大长度
// 2.1.2如果之前已经接收到最后一个分片,则该分片在总有效载荷中的结尾位置需要等于之前接收到的最后一个分片给出的结尾位置
// 2.2结尾位置对齐到8字节边界,截去多余的字节,希望后续到达的分片补齐
// 3.更新该分片的skb->data移动到ip有效载荷,skb->tail到8字节
// 4.处理重叠
// 5.将分片插入到ipq的分片列表中
// 6.更新ipq的时间戳,移动ipq到rcu链表尾部// 重叠的处理:
// 1.一个分片最多只会与一个前边的分片发生重叠,此时,截去该分片发生重叠的部分
// 2.一个分片可能会与多个后边的分片发生重叠,此时
// 2.1 如果后边的一个分片完全被重叠,则释放后边的这个分片
// 2.2 如果后边的这个分片只有部分被重叠,则从后边的这个分片中截去重叠的部分
// 3.使被截去缓存区的skb的校验和失效1.1 static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
{struct sk_buff *prev, *next;int flags, offset;int ihl, end;//ipq正在被释放if (qp->last_in & COMPLETE)goto err;//此ip分片(ip有效载荷)在所有有效载荷中的偏移量offset = ntohs(skb->nh.iph->frag_off);flags = offset & ~IP_OFFSET;//DF MF标志offset &= IP_OFFSET;偏移量为13bit的字段,去掉高3bit的flagoffset <<= 3; //偏移量以8字节为单位ihl = skb->nh.iph->ihl * 4;end = offset + skb->len - ihl;//该ip分片的有效载荷在总有效载荷的最后一个字节的位置//接收到最后一个分片if ((flags & IP_MF) == 0) {//1.该分片指示的总有效载荷大小不足从已接收到的报文推断出的长度if (end < qp->len ||((qp->last_in & LAST_IN) && end != qp->len))//2.已经接收到最后一个分片,又接收到一个最后一个分片,但是长度不等goto err;qp->last_in |= LAST_IN;//LAST_IN表示已经接收到最后一个分片qp->len = end;//总有效载荷的长度} else {//非最后一个分片if (end&7) {//结尾位置没有对齐到8字节end &= ~7;//去掉结尾的字节,希望后来的数据补齐if (skb->ip_summed != CHECKSUM_UNNECESSARY)skb->ip_summed = CHECKSUM_NONE;//由于截去了末尾的字节,因此表示校验和失效}if (end > qp->len) {//非最后一个分片,但是长度超过了总有效载荷长度if (qp->last_in & LAST_IN)goto err;//有错误qp->len = end;//由于新接收到的分片其结尾字节位置大于最大的结尾位置,更新最大的结尾位置}}if (end == offset)//长度为0分片的goto err;//pskb_pull 与 skb_pull的区别:// 1.skb_pull只简单移动 skb->data的指针// 2.pskb_pull考虑当skb->data到skb->tail之间的数据量如果不足够移动时,从frags或者frag_list中向前拷贝if (pskb_pull(skb, ihl) == NULL)//更新skb->data,使其指向ip有效载荷goto err;if (pskb_trim(skb, end-offset))//更新skb->tail指针,使skb->data与skb->tail之间的数据量为end-offsetgoto err;//在ipq->fragments中寻找该分片前边的分片//一个分片前边分片的满足条件:// 1.它的偏移量小于该分片的偏移量// 2.它后边分片的偏移量大于等于该分片的偏移量prev = NULL;for(next = qp->fragments; next != NULL; next = next->next) {if (FRAG_CB(next)->offset >= offset)break; prev = next;}//已经接收到该分片前边的分片//该分片最多只会与前边的一个分片重叠if (prev) {int i = (FRAG_CB(prev)->offset + prev->len) - offset;//该分片与前边的分片存在重叠的部分if (i > 0) {offset += i;//更新该分片的offsetif (end <= offset)goto err;if (!pskb_pull(skb, i))//从该分片中删除重叠的部分goto err;if (skb->ip_summed != CHECKSUM_UNNECESSARY)skb->ip_summed = CHECKSUM_NONE;//由于该分片长度被截取,因此校验和失效}}//接着之前的搜索,寻找该分片的后边的分片//该分片会与多个后边的分片重叠while (next && FRAG_CB(next)->offset < end) {int i = end - FRAG_CB(next)->offset;//与后边第一个分片重叠的字节数//重叠的字节数小于后边分片的长度,说明只与后边一个分片发生了重叠if (i < next->len) {//更新后边分片的data指针,截取重叠的部分if (!pskb_pull(next, i))goto err;//更新后边分片的偏移量FRAG_CB(next)->offset += i;//由于从后边分片截取了重叠的部分,从已接收到的数据量减去这部分字节qp->meat -= i;if (next->ip_summed != CHECKSUM_UNNECESSARY)next->ip_summed = CHECKSUM_NONE;//由于截取了后边的这个分片,使其校验和失效break;} else {//否则完全包含了后边的这个分片, 则直接释放掉被重叠的这个分片struct sk_buff *free_it = next;next = next->next;if (prev)prev->next = next;elseqp->fragments = next;qp->meat -= free_it->len;frag_kfree_skb(free_it, NULL);}}//强制转换skb->cb为分片控制块//经过与前边,后边的分片比较,最终确定该分片的偏移量//设置该分片的偏移量FRAG_CB(skb)->offset = offset;//将分片添加到ipq的fragments链表中skb->next = next;if (prev)prev->next = skb;elseqp->fragments = skb;//此分片为第一个分片if (skb->dev)qp->iif = skb->dev->ifindex;skb->dev = NULL;qp->stamp = skb->stamp;//更新ipq的时间戳为最新收到的这个skb的时间戳qp->meat += skb->len;//skb->truesize为skb中所有缓存区占用的总大小atomic_add(skb->truesize, &ip_frag_mem);//增加分片子系统使用的内存量if (offset == 0)qp->last_in |= FIRST_IN;write_lock(&ipfrag_lock);list_move_tail(&qp->lru_list, &ipq_lru_list);write_unlock(&ipfrag_lock);return;err:kfree_skb(skb);
}
转载于:https://www.cnblogs.com/pangblog/p/3367657.html
网络子系统55_ip协议分片重组_加入ipq相关推荐
- 网络编程_HTTP协议_Web服务器_(TCP3次握手4次挥手,长短连接,伪静态、静态和动态)
Python高级语法--网络编程--进阶学习笔记 文中案例参考: https://github.com/FangbaiZhang/Python_advanced_learning/tree/maste ...
- 网络子系统45_ip协议tos处理
//ip报头tos字段,一个字节 // 二进制位:[0 1 2] [3] [4] [5] [6] [7] // 1.[0 1 2] 表示优先级: // 000 路由 // 001 优先级 // 010 ...
- 蓝牙协议分析(3)_蓝牙低功耗(BLE)协议栈介绍
原文链接:蓝牙协议分析(3)_蓝牙低功耗(BLE)协议栈介绍 系列索引:蓝牙协议分析(1)_基本概念 蓝牙协议分析(2)_协议架构 目录 1. 前言 2. Why 3. How和What 4. Phy ...
- 网络 网络层 | IP协议、网段划分、公网与私网、路由选择
网络层是用信子网的边界,是通信设备的协议最高层.其功能是负责地址管理与路由选择(为每一条网络中的数据根据想去的地方选择合适的路径),典型的协议是IP协议,典型的设备是路由器 IP协议 IP协议的工作类 ...
- 系统架构设计笔记(15)—— 网络架构与协议
网络架构是指计算机网络的各层及其协议的集合.计算机之间要交换数据,就必须遵守一些事先约定好的规则,用于规定信息的格式及如何发送和接收信息的一套规则就称为网络协议.为了减少网络协议设计的复杂性,网络设计 ...
- 转载:IBM SNA:IBM 系统网络架构及其协议
和 OSI 模型相对,系统网络架构(SNA)由 IBM 提出,也是最为流行的网络架构模型之一.虽然 SNA 模型现在已经过时,但它仍然得到了广泛的应用.SNA 的设计基于 IBM 大型机使用的主机 - ...
- 计算机网络---网络架构与协议
从古代的驿站.八百里快马,到近代的电报.电话,人类对于通信的追求从未间断,信息的处理与通信技术的革新一直伴随社会的发展.而作为 20 世纪人类最伟大.最卓越的发明--个人计算机的出现与发展,使得人们获 ...
- 无线传感器网络标准化与协议分析
无线传感器网络作为一门面向应用的研究领域,在近几年获得了飞速发展.在关键技术的研发方面,学术界从网络协议.数据融合.测试测量.操作系统.服务质量.节点定位.时间同步等方面开展了大量研究,取得丰硕的成果 ...
- Lwip IP包分片重组
1. 开发环境 操作系统:SylixOS 编程环境:RealEvo-IDE3.1 硬件平台:AT9x25开发板 2. 技术实现 SylixOS系统使用的网络协议栈是Lwip协议栈.Lwip ...
- (转)C#网络编程(订立协议和发送文件) - Part.4
源码下载:http://www.tracefact.net/SourceCode/Network-Part4.rar C#网络编程(订立协议和发送文件) - Part.4 文件传输 前面两篇文章所使用 ...
最新文章
- (C++)A+B 输入输出练习VII 输入包含若干行,每行输入两个整数a和b,由空格分隔。 对于每组输入,输出a和b的和,每行输出后接一个空行。
- 版本迭代规划的几大关键步骤
- consul-template + nginx部署高可用负载均衡
- 如何从RxJava升级到RxJava2
- python是c语言写的吗-python和C语言的差别
- c语言如何快速看懂别人的程序,探究如何快速看懂单片机程序方法
- java transient关键字
- sonarqube没有html插件,SonarQube Github插件没有写拉问题的问题
- Oracle导入程序Imp的使用详解
- 揭开 Python 内存分配时的小秘密!
- 【转】浅谈命令查询职责分离(CQRS)模式
- linux基础(二)——linux各文件夹含义和作用
- 手机麦克风权限在哪里开启_手机麦克风权限怎么设置
- Domino版本、维护版本和补丁程序概念
- 都是做游戏,为嘛国内外出来的产品相差这么大?
- 【常见的优化算法介绍】
- 大数据中的物联网运用
- RPC好,还是RESTful好?
- 深度探索C++对象模型第2章 构造函数语义学
- Spy vs. Spy