TCP/IP协议如何实现ip分片
发表于:2025-01-24 作者:千家信息网编辑
千家信息网最后更新 2025年01月24日,小编给大家分享一下TCP/IP协议如何实现ip分片,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!分析一下ip分片。首先我们
千家信息网最后更新 2025年01月24日TCP/IP协议如何实现ip分片
小编给大家分享一下TCP/IP协议如何实现ip分片,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
分析一下ip分片。首先我们要先了解为什么需要分片。比如在以太网中,使用CSMA/CD协议(由网卡实现),他规定了一个链路层数据包(不包括mac头,但是这一版内核实现的时候是包括了mac头的大小)的最大值(MTU)和最小值。所以如果上层的包大于这个阈值就需要被分片。而分片和组包的实现是在ip层。我们看一下具体的逻辑。ip分片的逻辑在ip_fragment函数里实现。
void ip_fragment(
struct sock *sk,
struct sk_buff *skb,
struct device *dev,
int is_frag
)
定义的一些变量。
struct iphdr *iph;
unsigned char *raw;
unsigned char *ptr;
struct sk_buff *skb2;
int left, mtu, hlen, len;
int offset;
unsigned long flags;
// mac首地址
raw = skb->data;
// ip头首地址,hard_header_len为mac头大小
iph = (struct iphdr *) (raw + dev->hard_header_len);
skb->ip_hdr = iph;
// ip头的大小,不包括数据部分
hlen = (iph->ihl * sizeof(unsigned long));
// ip包总大小减去ip层等于ip报文的数据长度,即需要分片的部分的大小
left = ntohs(iph->tot_len) - hlen;
// ip头+mac头
hlen += dev->hard_header_len;
// 每个分片的数据部分长度等于mac层的mtu减去mac头和ip头,即mac层的mtu包括了mac头、ip头、ip数据部分的总和。
mtu = (dev->mtu - hlen);
// 数据部分首地址
ptr = (raw + hlen);
判断是否可以分片。
// 设置了不能分片则发送icmp报文,可以对照ip报文格式看
if (ntohs(iph->frag_off) & IP_DF)
{
icmp_send(skb,ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, dev->mtu, dev);
return;
}
判断即将被分片的ip包是否本身也是一个分片。即经过了多次ip分片。
/*
该ip报文本身就是一个分片,现在需要进行再次分片,
偏移的首地址是该报文的首地址乘以8,因为再次被分片的报文,他的偏移是
基于原来未被分片的数据的偏移。而不是针对当前这个分片的偏移
*/
if (is_frag & 2)
offset = (ntohs(iph->frag_off) & 0x1fff) << 3;
else
offset = 0
开始处理分片。
// 还有则继续处理
while(left > 0)
{
// ip包默认承载的字节数,但是如果大于mtu的话则取小的值,即mtu
len = left;
// 大于mtu则还要分片,即只能承载mtu大小的字节,否则就是最后一个分片
if (len > mtu)
len = mtu;
/*
剩下的字节比mtu大的时候下面的判断会成立,
即剩下的字节还不能在这次发送完,还要继续分片
除8乘8即取8的倍数大小,不一定等于mtu
*/
if (len < left)
{
len/=8;
len*=8;
}
// len 为这一分片承载的数据大小
// 申请新的skb,大小为mac头+ip头+数据部分长度
if ((skb2 = alloc_skb(len + hlen,GFP_ATOMIC)) == NULL)
{
return;
}
skb2->arp = skb->arp;
skb2->free = 1;
// 总大小是mac头+ip头+数据部分长度
skb2->len = len + hlen;
// 指向刚分配的内存首地址,开始复制数据
skb2->h.raw=(char *) skb2->data;
save_flags(flags);
restore_flags(flags);
// ip地址
skb2->raddr = skb->raddr;
// raw指向mac头首地址,这里把mac报头和ip报头+选项都复制到skb中,ip选项应该只复制到第一个分片,这里会复制到每一个分片中
memcpy(skb2->h.raw, raw, hlen);
// 复制数据部分,长度为len,ptr指向原ip报文中数据部分的首地址,
memcpy(skb2->h.raw + hlen, ptr, len);
// 剩下需要分片的字节数
left -= len;
// 指向ip头首地址
skb2->h.raw+=dev->hard_header_len;
iph = (struct iphdr *)(skb2->h.raw);
// 设置该分片的偏移,除以8,见ip协议的规定
iph->frag_off = htons((offset >> 3));
/*
1. 还有数据,则置MF,还要更多分片
2. is_frag =1;说明该分片后面还有更多分片。
表示被分片的数据本身就是一个ip分片,即再分片。
所以该报文下的所有分片MF都是1。
*/
if (left > 0 || (is_frag & 1))
iph->frag_off |= htons(IP_MF);
// 更新数据指针和偏移
ptr += len;
offset += len;
// 发送分片
ip_queue_xmit(sk, dev, skb2, 2);
}
分片主要的逻辑是1 申请一个新的内存,把待分片报文中的mac头、ip头,复制到新内存,然后数据部分切一块继续复制到内存后面。如此,直到分片完毕
2 修改ip报文中的一些字段的值 ,比如MF。
3 调底层接口逐个发送分片
分片的逻辑不算复杂,不讲解的太详细了。
以上是"TCP/IP协议如何实现ip分片"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!
数据
地址
大小
报文
部分
偏移
字节
长度
内存
指向
逻辑
就是
更多
篇文章
内容
再次
报头
时候
处理
复杂
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
无锡抖音小程序软件开发
数据库io到瓶颈了怎么优化
华梦网络技术有限公司
查询数据库归档位置
河南康创科技互联网有限公司
济南信创云服务器
隆盛宏康软件开发小程序
寻找服务器失败 csgo
装数据库有何用
幼儿园网络安全国旗下讲话稿
网络安全法第59条规定理解
青岛云豆互联网科技有限公司
基岩版1.18新生存服务器
2021国家网络安全周
中国创伤数据库表
数据库xs表在哪里
苹果手机通话记录数据库
去印尼做软件开发
如何避免网络安全问题的发生
人渣被该服务器移除
青蛙数据库软件是什么
如何访问内网服务器
广州设备维修管理软件开发
电脑qq服务器响应错误
ESB数据库连接失败
打开sql数据库文件
数据库营销方法
数据库延迟方案
计算机三级网络技术是a
数据库环境搭建 所需知识