linux 4.19 ip重组
IP重组
ip重组这部分 4.19内核与3.10内核有些差别,4.9.134以后内核中不使用低水位和工作队列了,同时使用了rhashtable 替代了 hash bucket的概念,在3.10内核中使用1024个hash bucket, 每个bucket中最多存放128个分片队列,在4.19内核中所有的分片队列都保存在可动态调整的rhashtable 中,同时不再使用低水位和工作队列对ip 分片进行回收
4.19内核中,在内存中会分配一个reassembly buffer用于IP分片的重组。同时,也定义了一系列的参数用于控制IP分片处理过程:
net.ipv4.ipfrag_high_thresh: 用于IP分片重组的最大内存用量(默认为4194304 ,即4Mb)。
net.ipv4.ipfrag_time: IP分片在内存中的保留时间(默认30,单位:秒)。
对应上述网络协议栈的内核参数,内核层定义了结构体netns_frags,包含分片重组功能需要的全局控制信息,其定义如下:
struct netns_frags {
struct percpu_counter mem ____cacheline_aligned_in_smp;
/* sysctls */
int timeout;
int high_thresh;
int low_thresh;
int max_dist;
struct inet_frags *f;
struct rhashtable rhashtable ____cacheline_aligned_in_smp;
atomic_long_t mem ____cacheline_aligned_in_smp;
};
其中rhashtable为分片队列(inet_frag_queue)所在的hash表,IP分片包在内核中根据IP报头的4个字段计算得到一个hash值(key值),每个hash值对应一个分片队列,在实现分片包重组功能时,IP层需要先缓存收到的所有分片包,等待同一个IP报文的所有分片包都到达后,把它们重组成一个大包再提交给L4(TCP/UDP... ...)协议。
当收到新的ip分片包时,将查找是否存在同一数据包的分片队列。首先检查当前内存中所有待重组分片包占用的内存(frag_mem_limit)是否高于高水位(net.ipv4.ipfrag_high_thresh),如果高于则丢弃分片包;否则接着对接收到的分片包与rhashtable表中缓存的分片队列进行匹配(即从rhashtable表查找分片队列)将属于同一数据包的分片包放在同一个分片队列中,如果一个数据包的所有分片包都接收完成,那么将进入数据包的重构流程;如果匹配失败,说明该分片属于一个新的数据包,那么进入分片队列新建流程。分片队列的接收查找函数inet_frag_find定义如下:
struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, void *key)
{
struct inet_frag_queue *fq = NULL, *prev;
//①高水位判断
if (!nf->high_thresh || frag_mem_limit(nf) > nf->high_thresh)
return NULL;
rcu_read_lock();
prev = rhashtable_lookup(&nf->rhashtable, key, nf->f->rhash_params); //② 查找rhashtable中的分片队列
if (!prev)
fq = inet_frag_create(nf, key, &prev); //③ 创建新分片队列
if (prev && !IS_ERR(prev)) {
fq = prev;
if (!refcount_inc_not_zero(&fq->refcnt))
fq = NULL;
}
rcu_read_unlock();
return fq;
}
在分片队列的新建流程中,将从slab中分配一段空间,相应增加分片包占用的内存,同时设置定时器(超时时常为30秒)用来检查重组结果,如果定时器超时未重组成功,该分片包也将丢弃。分片包的新建函数inet_frag_alloc定义如下:
static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf,
struct inet_frags *f,
void *arg)
{
struct inet_frag_queue *q;
q = kmem_cache_zalloc(f->frags_cachep, GFP_ATOMIC);
if (!q)
return NULL;
... ...
add_frag_mem_limit(nf, f->qsize); //①增加分片报文占用内存
setup_timer(&q->timer, //②设置超时定时器
f->frag_expire, (unsigned long)q);
... ...
return q;
}
int ip_defrag(struct net *net, struct sk_buff *skb, u32 user)
{
... ...
qp = ip_find(net, ip_hdr(skb), user, vif); //①查找分片队列
if (qp) {
... ...
ret = ip_frag_queue(qp, skb); //②分片队列入队操作
... ...
return ret;
}
kfree_skb(skb);
return -ENOMEM;
}
如果一个数据包的所有分片包都已接收,则需将所有分片包整合获得原始数据包,并将整合后的数据包提交给高层协议。同时,处理与分片包相关的数据结构,譬如更新当前分片包占用的内存(frag_mem_limit),停止与分片包相关的定时器等。数据包的重构函数ip_frag_reasm定义如下:
static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
struct sk_buff *prev_tail, struct net_device *dev)
{
... ...
ipq_kill(qp); //①减少分片包引用计数
... ...
sub_frag_mem_limit(qp->q.net, //②减少分片包占用内存
head->truesize);
... ...
}
所以,一个分片包的接收通常经历了查找分片、缓存、重组、释放等阶段,下图是分片包的接收流程。
file:///home/zxq/%E4%B8%8B%E8%BD%BD/ip%E9%87%8D%E7%BB%84.png
图1 4.19分片包接收流程
根据分析,内核中待重组的分片包占用内存量由高水位(net.ipv4.ipfrag_high_thresh)阈值和分片保留时间(net.ipv4.ipfrag_time)来控制,如果待重组分片包内存占用高于高水位(high_thresh),那么新收到的数据包分片将会直接丢弃, 如果分片包超过最大保留时间(ipfrag_time),那么已经收到的数据包也会被丢弃。
附3.10 ip重组

linux 4.19 ip重组的更多相关文章
- linux下取IP(正则)
linux下取IP(正则) 常见方法: ifconfig eth0|grep "inet addr"|awk -F ":" '{print $2}'|awk ' ...
- Linux 能PING IP 但不能PING 主机域名的解决方法 vim /etc/nsswitch.conf hosts: files dns wins
Linux 能PING IP 但不能PING 主机域名的解决方法 转载 2013年12月25日 10:24:27 13749 . vi /etc/nsswitch.conf hosts: files ...
- linux配置网卡IP地址命令详细介绍及一些常用网络配置命令
linux配置网卡IP地址命令详细介绍及一些常用网络配置命令2010-- 个评论 收藏 我要投稿 Linux命令行下配置IP地址不像图形界面下那么方 便,完全需要我们手动配置,下面就给大家介绍几种配置 ...
- linux下TCP/IP及内核参数优化调优(转)
Linux下TCP/IP及内核参数优化有多种方式,参数配置得当可以大大提高系统的性能,也可以根据特定场景进行专门的优化,如TIME_WAIT过高,DDOS攻击等等. 如下配置是写在sysctl.con ...
- Linux内核 TCP/IP、Socket参数调优
Linux内核 TCP/IP.Socket参数调优 2014-06-06 Harrison.... 阅 9611 转 165 转藏到我的图书馆 微信分享: Doc1: /proc/sy ...
- Linux下检测IP地址冲突及解决方法
问题说明:在公司办公网内的一台物理机A上安装了linux系统(ip:192.168.9.120),在上面部署了jenkins,redmine,svn程序.由于是在办公网内,这台机器和同事电脑都是在同一 ...
- linux c/c++ IP字符串转换成可比较大小的数字
由www.169it.com搜集整理 IP字符串转换成可比较大小的数字,具体代码如下所示: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include "stdio. ...
- linux下设置ip地址 gw网关,dns的方法
本文介绍下,在linux中设置IP地址.网关.dns的方法,有需要的朋友作个参考吧. 设置linux网络的方法有两种:第一种:使用命令修改(直接即时生效) 复制代码代码示例: ip and net ...
- Ubuntu Linux下设置IP的配置命令
Ubuntu Linux下设置IP的配置命令 今天装了Ubuntu,但是发现不能上网,开始排查问题: 1.首先确定网络连接是否正确,所用的网线是否可以正常工作 2.查看网卡是否能正常工作,检测的方法如 ...
- Linux tomcat设置ip地址直接访问,tomcat设置ip地址直接访问,tomcat绑定ip地址
Linux tomcat设置ip地址直接访问,tomcat设置ip地址直接访问,tomcat绑定ip地址 >>>>>>>>>>>> ...
随机推荐
- 小程序中使用 lottie 动画 | 踩坑经验分享
最近被拉去支援紧急需求(赶在五一节假日前上线的,双休需要加班),参与到项目中才知道,开发的项目是微信小程序技术栈的.由于是临时支援,笔者也很久没开发过微信小程序了,所以挑选了相对独立,业务属性相对轻薄 ...
- ansible系列(1)--ansible基础
目录 1. ansible概述 1.1 ansible的功能 1.2 ansible的特性 1.3 ansible的架构 1.4 ansible注意事项 1. ansible概述 Ansible 是一 ...
- 对于Docker和Podman的一点使用经验
前言:本文会以多个实际的线上例子,分享自己对于Docker和Podman的一点使用经验及踩过的坑,希望对读者有一点帮助. 本文bash脚本初步加工后可直接使用(兼容mac和linux系统),对于关键点 ...
- AI回答总不满意?你的提问方式可能完全错误!
AI回答总不满意?你的提问方式可能完全错误! 大家好,我是卷福同学,一个专注AI大模型整活的前阿里程序员,腾讯云社区2023新秀突破作者 向AI提问想写一篇论文,结果AI就生成2000字左右的文章后就 ...
- 【OpenVINO™】在 C# 中使用OpenVINO™ 部署PP-YOLOE实现物体检测
前言 OpenVINO C# API 是一个 OpenVINO 的 .Net wrapper,应用最新的 OpenVINO 库开发,通过 OpenVINO C API 实现 .Net 对 OpenV ...
- JDK源码阅读-------自学笔记(十五)(java.lang.Math数学类)
Math类简介 用于常见的数学方法 如果需要更加强大的数学运算能力,计算高等数学中的相关内容,可以使用apache commons下面的Math类库 常用方法及实战 abs 绝对值 实例: 1 //绝 ...
- 有隙可乘 - Android 序列化漏洞分析实战
作者:vivo 互联网大前端团队 - Ma Lian 本文主要描述了FileProvider,startAnyWhere实现,Parcel不对称漏洞以及这三者结合产生的漏洞利用实战,另外阐述了漏洞利用 ...
- pageoffice6 版本实现在线打开word 文件禁止保存、禁止另存、禁止打印的需求
在实际项目需求中,有时需要限制用户的保存.另存.打印文件操作,实现此效果只需在OnPageOfficeCtrlInit或AfterDocumentOpened事件中调用js设置PageOffice控件 ...
- 【超强SQL】WordPress批量修改指定分类下所有文章状态
前阵子主题君的某一个手游下载站的某一个分类,被百度K了,导致整个分类的文章收录都没了,这时候如果想要回复权重,就需要把这个分类的文章都删除了. 下面主题君给大家分享一段巨牛逼的SQL, WordPre ...
- WPF ListBox 控件绑定 Binding
当我们需要用到循环的列表内容,并且模板化程度高的时候,建议使用 ListBox 来做绑定.XAML: <Window.DataContext> <local:VMTempTest/& ...