IPv4之分片重组(三)

本文深入探讨IPv4分片重组的细节,涉及IP分片队列在重组完成和超时后的回收机制,以及哈希表的重新散列过程,确保系统资源的有效管理。
摘要由CSDN通过智能技术生成

这篇笔记来看看分片重组功能额外的一些实现细节,包括:

  1. IP分片队列的回收;
  2. 哈希表的重新散列;

IP分片队列的回收

首先,最正常的情况就是收到了所有的IP分片,然后将其组装成一个完整的IP报文,然后递交给上层。情况最差的,就是在规定的时间内没有收到全部的分片,这时需要有老化机制,使得之前缓存的片段能够被释放,否则对系统是一种负担。

重组完成后的IP分片队列回收

在ip_frag_reasm()中,并没有看到有对IP分片队列的明确回收操作,相关的两个动作如下:

/* Build a new IP datagram from all its fragments. */
static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, struct net_device *dev)
{
   
...
	// 实现见下文
	ipq_kill(qp);
	// 分片队列后面的skb全部移除
	qp->q.fragments = NULL;
...
}

ipq_kill()

void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f)
{
   
	// 停止定时器,如果停止成功则递减引用计数,因为在安装定时器时增加了引用计数
	// 这里需要对应操作
	if (del_timer(&fq->timer))
		atomic_dec(&fq->refcnt);
	// 对于没有设置COMPLETE标记的IP分片队列,将其从哈希表和LRU表中移除,并且递减其引用计数,然后设置CPMPLETE,
	// 如果不设置该标记,后续无法进行释放。重组场景调用ipq_kill()时还并没有设置COMPLETE标记
	if (!(fq->last_in & COMPLETE)) {
   
		fq_unlink(fq, f);
		atomic_dec(&fq->refcnt);
		fq->last_in |= COMPLETE;
	}
}
EXPORT_SYMBOL(inet_frag_kill);

/* Kill ipq entry. It is not destroyed immediately,
 * because caller (and someone more) holds reference count.
 */
static void ipq_kill(struct ipq *ipq)
{
   
	inet_frag_kill(&ipq->q, &ip4_frags);
}

如上代码所示,对于正常重组后的IP分片队列,这里仅仅是递减了其引用计数,并没有执行直接的释放动作,所以需要回忆其从创建到重组过程中引用计数的变化:

创建时

static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf, struct inet_frags *f, void *arg)
{
   
	struct inet_frag_queue *q;
...
	// 初始化引用计数为1
	atomic_set(&q->refcnt, 1);
...
}

启动定时器/插入哈希表时
创建IP分片队列后,会立即启动其组装超时定时器,此时也会增加引用计数,因为定时器超时函数也会引用该IP分片队列。

在将IP分片队列放入全局的哈希表和LRU表后,也会增加引用计数。

static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
		struct inet_frag_queue *qp_in, struct inet_frags *f
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值