我对Linux内核的经验非常少。我最近刚刚开始玩它。
为了我的研究目的,我一直在努力追踪数据包到达的最早时间。我可以通过修改设备驱动程序并在设备驱动程序的中断处理程序函数中记录时间戳来在设备驱动程序级别执行此操作。对不起,这篇文章可能会长一点。
例如,我修改了这个函数(https://elixir.bootlin.com/linux/v4.7/source/drivers/net/ethernet/intel/i40e/i40e_main.c#L3232)来跟踪调用这个函数的时间戳。
进一步深入并跟随此调用的堆栈跟踪,我们将找到如下的堆栈跟踪:
我试图在函数do_IRQ()函数中跟踪数据包到达的时间戳(上面的堆栈跟踪中的粗体字)。作为参考,do_IRQ函数如下所示:
__visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
struct irq_desc * desc;
/* high bit used in ret_from_ code */
unsigned vector = ~regs->orig_ax;
**int int_number;**
entering_irq();
/* entering_irq() tells RCU that we're not quiescent. Check it. */
RCU_LOCKDEP_WARN(!rcu_is_watching(), "IRQ failed to wake up RCU");
desc = __this_cpu_read(vector_irq[vector]);
**int_number = desc->irq_data.irq;**
**printk(KERN_INFO "IRQ Number=%d; Vector=%d \n", int_number, vector);**
if (!handle_irq(desc, regs)) {
ack_APIC_irq();
if (desc != VECTOR_RETRIGGERED) {
pr_emerg_ratelimited("%s: %d.%d No irq handler for vector\n",
__func__, smp_processor_id(),
vector);
} else {
__this_cpu_write(vector_irq[vector], VECTOR_UNUSED);
}
}
exiting_irq();
set_irq_regs(old_regs);
return 1;
}
为了让我的意图更加清晰,我已经表明我对这个函数的更改包含在" **"。
例如,在我的测试机器上,我的NIC绑定到IRQ编号19. int_number 变量表示该编号。因此,这让我可以跟踪特定IRQ号码的IRQ。
它可能与单个队列NIC适配器无关,但它适用于多队列适配器,因为我可以使用流控制器将数据包定向到固定队列,并且每个队列都绑定到特定的IRQ编号。因此,这将帮助我轻松跟踪我的数据包。
我的方法:
只是为了澄清我的最后一项任务:我正在尝试捕获我的数据包最早到达的时间戳,如:
t1
t2
t3
t4
我很感激对此有任何意见。
谢谢!