IP重组笔记

本文详细记录了IP协议分片重组的过程,包括IP重组的数据结构、时机以及关键函数的解析,帮助理解IP分片如何在到达目的地址时重组为完整封包。
摘要由CSDN通过智能技术生成

看过ip协议源码后,将分片与重组注意事项记录下来,以免忘记。

1。ip重组结构体组织形式

理解任何代码,首先需要理解其数据结构,以及凌驾于数据结构之上的操作。

整体而言,所有分片都存储在全局变量ip4_frags中:

#define INETFRAGS_HASHSZ        64

static struct inet_frags ip4_frags->hash

struct hlist_head hash[INETFRAGS_HASHSZ]

该全局变量还包含了一组函数指针,用于处理封包的分片,其中一个重要的函数指针是match,用于查找分片封包的队列时进行比较。

ip层收到的每一个ip分片都存储在由skb_buff的成员next链接起来的链表中,该链表嵌入在一个表示独立封包的队列结构体inet_frag_queue中,每一个这样的队列结构体表示唯一一个封包,多个封包通过该结构体成员struct hlist_node   list链接成链表形式,inet_frag_queue又嵌入在struct ipq结构体中,该结构体又包含了ip分片相关的重要字段。

现在看struct ipq 、struct inet_frag_queue、与全局变量的成员hash数组之间的关系ip4_frags->hash:

hash是一个数组,大小默认是64,即包含64个元素,每个元素都是一个链表,每个链表的结点类型为inet_frag_queue,所以查找分片封包的队列时,计算hash值,得到队列链表头指针,即可挨着比较每个封包的队列,找到封包的队列后,再比较队列的关键字是否与分片的关键字相同。

需要注意inet_frag_queue是嵌入在ipq中,所以存储封包的结构体实际类型是ipq,程序里根据inet_frag_queue类型的q得到q所属ipq的地址即指针,ipq里存储了一个封包的队列(队列里是所有相关的分片),与查找时使用的ip头相关信息(源目的地址、协议等)。

手工白板画图

2。ip重组的时机

ip重组是指,当封包到达最终目的地址,则进行重组,即在3层ip层收到ip封包时,如果该封包的最后一个封包到达时,将该封包的所有分片按照分片的偏移量组成一个封包,将该封包传递到4层。

ip重组函数是ip_defrag,该函数的前后调用关系链如下:

ip_rcv-》NF_HOOK(netfilter pre-routing)-》ip_rcv_finish-》ip_route_input_noref(ip路由查找)-》dst_input-》分支如下:

分支1:

设置Router Alert选项走此路径:dst_input-》ip_forward-》ip_call_ra_chain-》ip_defrag(ip重组)-》raw_rcv

 直接转发的封包走此路径        :dst_input-》ip_forward-》NF_HOOK(netfilter ip-forwarding)-》ip_forward_finish-》dst_output-》ip_output

 

分支2:dst_input-》ip_local_deliver-》{ ip_defrag,NF_HOOK } -》ip_local_deliver_finish-》{tcp_v4_rcv,udp_rcv,icmp_rcv,igmp_rcv}(4层协议处理函数)

到达本地主机的封包走此路径,如果是分片则执行ip_defrag,如果ip_defrag返回非0则表示封包的分片尚未完全到达,直接返回;如果不是分片或者封包所有分片均已到达并且重组成功,则继续执行 -》NF_HOOK(netfilter local-in)

经过以上了解了重组的位置,下边看看ip_defrag函数的重组过程:
 

3。ip重组函数解释

参数:skb ip封包片段,user 说明重组原因,因为什么要重组

/* Process an incoming IP datagram fragment. */
int ip_defrag(struct sk_buff *skb, u32 user)
{
    struct ipq *qp;
    struct net *net;

    net = skb->dev ? dev_net(skb->dev) : dev_net(skb_dst(skb)->dev);
    IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS);

    /* Start by cleaning up the memory. */
    if (atomic_read(&net->ipv4.frags.mem) > net->ipv4.frags.high_thresh)
        ip_evictor(net);

    /* Lookup (or create) queue header */
    // 根据ip头信息查找ip片段所属封包的ipq,ipq的inet_frag_queue存储了封包的所有分片
    // 分片以链表形式链接在inet_frag_queue的sk_buff类型的链表fragments上
    if ((qp = ip_find(net, ip_hdr(skb), user)) != NULL) {
        int ret;

        spin_lock(&qp->q.lock);

        // 将ip片段放入hash队列,如果是做好一个片段,内部会重组,返回0
        ret = ip_frag_queue(qp, skb);

        spin_unlock(&qp->q.lock);
        ipq_put(qp);
        return ret;
    }   

    IP_INC_ST
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

种菜的

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值