首页 > 系统相关 >linux 4.19 ip重组

linux 4.19 ip重组

时间:2024-07-02 10:00:09浏览次数:19  
标签:frag ... struct 4.19 ip linux 队列 分片 inet

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.pngimage

图1 4.19分片包接收流程

根据分析,内核中待重组的分片包占用内存量由高水位(net.ipv4.ipfrag_high_thresh)阈值和分片保留时间(net.ipv4.ipfrag_time)来控制,如果待重组分片包内存占用高于高水位(high_thresh),那么新收到的数据包分片将会直接丢弃, 如果分片包超过最大保留时间(ipfrag_time),那么已经收到的数据包也会被丢弃。

附3.10 ip重组

image

标签:frag,...,struct,4.19,ip,linux,队列,分片,inet
From: https://www.cnblogs.com/forwards/p/18279336

相关文章

  • Linux 下 zookeeper 集群部署
    目录1.zookeeper下载2.环境准备3.zookeeper部署3.1 修改系统配置文件3.2开放端口3.3安装zookeeper3.4 验证4.设置服务开机自启动本文将以三台服务器为例,介绍在linux系统下zookeeper的部署方式。1.zookeeper下载  下载地址:Indexof/dist/zookeeper(a......
  • Shell Lab: Writing Your Own Linux Shell
    18-213/18-613,Summer2024ShellLab:WritingYourOwnLinuxShellAssigned:Mon,July8,2024Due:Thurs,Mon,July22,2024at11:59PMLastPossibleHandin:Thu,July25th,2024at11:59PM1IntroductionThepurposeofthisassignmentistohelpyoubecom......
  • Linux的磁盘分区、挂载,解释挂载的经典案例——如何增加一块硬盘
    (1)分区、挂载释义:①无论有几个分区(硬盘),分给哪一目录使用(Linux文件系统),它归根结底就只有一个根目录。一个独立且唯一的文件结构。每个分区都是用来组成整个文件系统的一部分。②“挂载”(Mount)是指将设备(如硬盘、光盘、USB驱动器等)中的一个分区与一个已存在的目录(挂载点)关联起......
  • 嵌入式GDB调试Linux C程序或交叉编译(开发板)
    目录简介开始使用电脑端准备安装gdb1.编译带调试信息的可执行文件2.进入gdb3.启动程序常用命令设置断点:进入函数打印数值结束常用命令l回车键bCSnpq参考文档1、安装gdb。2、gdb的简单使用。(1)在可执行文件中加入源码信息(2)进入gdb(3)gdb调试常用命令[1]start[2]单步执行(n......
  • Linux 文件系统扩展
    今天发现/usr目录空间不够。需要扩展。之前没有处理过。今天试了一下调整。并且记录下来整个过程。1使用fdisk-l查看磁盘信息2、使用fdisk/dev/sda对磁盘进行分区操作完后,多了一个/dev/sda34使用pvcreate/dev/sda3创建物理卷5、使用vgextendol/dev/sda3扩展磁......
  • 如何做好一个企业家IP:塑造独特的个人品牌
    在当今数字化时代,个人品牌的力量愈发凸显,对于企业家而言,一个强大的IP(IntellectualProperty,即知识产权或个人品牌)不仅有助于提升个人影响力,还能为企业的发展注入强大动力。那么,如何做好一个企业家IP呢?本文将从几个关键方面进行探讨。一、明确品牌定位与核心价值观企业家IP的......
  • 塑造卓越企业家IP:多维度视角下的策略解析
    在构建和塑造企业家IP的过程中,我们需要从多个维度进行考量,以确保个人品牌能够全面、立体地展现企业家的独特魅力和价值。以下是从不同角度探讨如何做好一个企业家IP的策略。一、从个人特质出发深入了解自我:企业家需要清晰地认识到自己的优势、劣势、价值观和愿景,确保IP能够......
  • 国产操作系统上通过主机名查ip地址 _ 统信 _ 麒麟 _ 中科方德
    原文链接:国产操作系统上通过主机名查ip地址|统信|麒麟|中科方德Hello,大家好啊!今天给大家带来一篇在国产操作系统上通过主机名查找IP地址的文章。通过主机名查找IP地址是网络管理和故障排除中常见的操作之一。本文将详细介绍如何在国产操作系统(如统信UOS、麒麟KOS、中......
  • Linux内存不够了?看看如何开启虚拟内存增加内存使用量
    1、为什么要使用虚拟内存当我们没有多余的钱去购买大内存的云服务器时,但是当前服务器里面的软件和程序运行的比较多导致内存不够用了。这个时候可以通过增加虚拟内存来扩大内存容量。但是在启用虚拟内存时,需要仔细考虑系统的实际需求和硬件配置,以及权衡虚拟内存的优缺点,考虑好利......
  • es启动报错exception during geoip databases update
    解决:在es配置文件中添加如下重启ingest.geoip.downloader.enabled:false  报错信息{"type":"server","timestamp":"2024-07-01T15:11:05,965Z","level":"ERROR","component":"o.e.i.g.GeoIpDownlo......