rdma rxe ack超时处理原理

在rxe_req.c文件:

在int rxe_requester(void *arg)发包函数的最后会调用update_state函数,触发retrans_timer定时器

static void update_state(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
			 struct rxe_pkt_info *pkt, int payload)
{
	qp->req.opcode = pkt->opcode;

	if (pkt->mask & RXE_END_MASK)
		qp->req.wqe_index = queue_next_index(qp->sq.queue,
						     qp->req.wqe_index);

	qp->need_req_skb = 0;

	if (qp->qp_timeout_jiffies && !timer_pending(&qp->retrans_timer))
		mod_timer(&qp->retrans_timer,
			  jiffies + qp->qp_timeout_jiffies);
}

所以,retransmit_timer函数会被执行

void retransmit_timer(struct timer_list *t)
{
	struct rxe_qp *qp = from_timer(qp, t, retrans_timer);

	if (qp->valid) {
		qp->comp.timeout = 1;
		rxe_run_task(&qp->comp.task, 1);
	}
}

从而,在定时器到期以后会调度到rxe_completer函数,
然后从skb队列里取出skb包,如果超时取出的skb为NULL,说明定时器到期以后,还没有ack过来,
那么state的变化为COMPST_GET_WQE->COMPST_EXIT->COMPST_ERROR_RETRY->COMPST_ERROR_RETRY,
然后设置qp->req.need_retry = 1;并启动rxe_run_task(&qp->req.task, 0);
到了req的调度以后,
该条件成立,最后通过req_retry函数重发数据包。

	if (unlikely(qp->req.need_retry)) {
		req_retry(qp);
		qp->req.need_retry = 0;
	}

对于timer_pending做了一个测试,注意看打印。

struct timer_list mytimer;
int i = 0;
//定时器超时处理函数
static void mytimer_handle(struct timer_list *t)
{
        printk("The timer has happened %d times!\n", i);
		if(timer_pending(&mytimer))
			printk("timer_pending true!\n");
        //这里需要说明的是,定时器在超时后会自动在系统中删除,也就是说如果定义了一个1s后执行的定时器
        //1s后定时器到期后将会在系统中删除,无法完成周期性的定时任务;
        //如果想要周期性执行,需要在超时处理函数中再次修改下定时器到期时间;
//      mod_timer(&mytimer, jiffies + HZ);
        i++;
        mod_timer(&mytimer, jiffies+HZ);
		
		if(timer_pending(&mytimer))
			printk("timer_pending true! 11\n");
}

static int __init hello_init(void)
{
        printk("mytimer init!!\n");
        timer_setup(&mytimer, mytimer_handle, 0);//(1)初始化定时器mytimer,并设置超时处理函数
		if(timer_pending(&mytimer))
			printk("timer_pending false!\n");
        //mytimer.expires = jiffies + HZ;//(2)设置超时时间,1s
        //add_timer(&mytimer);//(3)将定时器mytimer添加到系统中
        mod_timer(&mytimer, jiffies+HZ);
				if(timer_pending(&mytimer))
			printk("timer_pending false 11!\n");
        return 0;
}

static void hello_exit(void)
{
        printk("mytimer exit!!\n");
        del_timer(&mytimer);//(4)退出时删除定时器
}

MODULE_AUTHOR("Tan xujia");
MODULE_LICENSE("Dual BSD/GPL");

module_init(hello_init);
module_exit(hello_exit);
# SPDX-License-Identifier: GPL-2.0
obj-m += vmax.o

vmax-objs := \
	vma.o 
	
all:
	make -C /usr/src/linux-headers-$(shell uname -r) M=$(shell pwd) modules
clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值