linux 4.19 ip重组

linux,ip · 浏览次数 : 0

小编点评

在Linux内核中,IP分片重组是一个重要的机制,用于处理在网络传输过程中发生的分片问题。在4.19内核中,相比于3.10内核,有一些重要的变化和改进。 首先,4.19内核不再使用低水位和工作队列来进行IP分片的回收,而是使用了rhashtable来替代hash bucket的概念。这意味着在4.19内核中,所有的分片队列都保存在可动态调整的rhashtable中,而不是3.10内核中的1024个hash bucket。 其次,4.19内核在内存中会分配一个reassembly buffer用于IP分片的重组。同时,内核定义了一系列参数用于控制IP分片处理过程,例如net.ipv4.ipfrag_high_thresh(用于控制IP分片重组的最大内存用量)和net.ipv4.ipfrag_time(IP分片在内存中的保留时间)。 此外,4.19内核中还定义了一个名为netns_frags的结构体,它包含了分片重组功能所需的全局控制信息。这个结构体包括一个percpu_counter(用于统计内存使用情况)、一个timeout(用于控制分片包在内存中的保留时间)、一个high_thresh(用于设置高水位阈值)和一个low_thresh(用于设置低水位阈值)等成员。 在分片包的接收流程中,首先会查找分片队列,然后缓存收到的所有分片包。当收到新的ip分片包时,会查找是否存在同一数据包的分片队列。如果存在,则将属于同一数据包的分片包放在同一个分片队列中;如果不存在,则创建一个新的分片队列。在分片队列的新建流程中,会从slab中分配一段空间,增加分片包占用的内存,并设置定时器用于检查重组结果。 最后,在数据包的重构流程中,会减少分片包的引用计数,并减少分片包占用的内存。这些过程共同构成了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.pngimage

图1 4.19分片包接收流程

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

附3.10 ip重组

image

与linux 4.19 ip重组相似的内容:

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内核中所

Linux定时任务概述

Linux定时任务概述 基于centos7.6.1810 参考鸟哥私房菜 /etc/crontab [root@VM-4-10-centos ~]# cat /etc/crontab SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=

[转帖]Linux 磁盘I/O 调度算法 说明

2022-08-23 13:031361转载Linux 1 Linux 4.0 IO协议栈框架图 I/O 调度算法在各个进程竞争磁盘I/O的时候担当了裁判的角色。他要求请求的次序和时机做最优化的处理,以求得尽可能最好的整体I/O性能。 Linux 4.0 IO协议栈框架图 I/O调度程序的总结 当向

[转帖]MinIO Client(mc)完全指南

https://www.cnblogs.com/lvzhenjiang/p/14944821.html 目录 一、获取MinIO Client(mc) 1.1 docker版 1.2 Homebrew (macOS) 1.3 下载二进制文件(GNU/Linux) 1.4 下载二进制文件(Micros

[转帖]MinIO Client(mc)完全指南

https://www.cnblogs.com/lvzhenjiang/p/14944821.html 目录 一、获取MinIO Client(mc) 1.1 docker版 1.2 Homebrew (macOS) 1.3 下载二进制文件(GNU/Linux) 1.4 下载二进制文件(Micros

[转帖]Linux下的I/O复用与epoll详解

https://blog.csdn.net/weixin_39094034/article/details/110393127 前言 I/O多路复用有很多种实现。在linux上,2.4内核前主要是select和poll,自Linux 2.6内核正式引入epoll以来,epoll已经成为了目前实现高性

[转帖]LVS入门篇(五)之LVS+Keepalived实战

LVS入门篇(五)之LVS+Keepalived实战 https://www.cnblogs.com/linuxk/p/9365189.html 一、实验架构和环境说明 (1)本次基于VMware Workstation搭建一个四台Linux(CentOS 7.4)系统所构成的一个服务器集群,其中两

Linux 特权 SUID/SGID 的详解

导航 0 前言 1 权限匹配流程 2 五种身份变化 3 有效用户/组 4 特权对 Shell 脚本无效 5 Sudo 与 SUID/SGID 的优先级 6 SUID、SGID、Sticky 各自的功能 0、前言 Linux最优秀的地方之一,就在于他的多人多工环境。而为了让各个使用者具有较保密的档案资

[转帖]Linux服务器跨三网的网卡配置方法(4网卡3网段)

服务器有4个网卡,其中1、2号网卡进行绑定,配置10地址;3号网卡配置互联网地址;4号网卡配置192私网地址。IP信息如下 IP202.*.*.*10.14.167.229192.168.188.202掩码255.255.255.240255.255.255.240255.255.255.192网关

【Azure App Service for Linux】NodeJS镜像应用启动失败,遇见 RangeError: Incorrect locale information provided

问题描述 在App Service For Linux 中,部署NodeJS应用,应用启动失败。 报错信息为: 2023-08-29T11:21:36.329731566Z RangeError: Incorrect locale information provided2023-08-29T11: