在 XDP 网关项目中,为了提高网络包吞吐性能,需要充分利用 CPU 核;这就需要调整网卡 queue 数量,并将 queue 对应的 IRQ 绑定到指定的 CPU 核上。
因此,在绑核之后,需要对 IRQ 绑核进行跟踪,以便观测绑核配置是否被更改了。
IRQ 绑核的内核函数
IRQ 绑核的方式如下:
echo 1 > /proc/irq/${IRQ_ID}/smp_affinity
。echo 1 > /proc/irq/${IRQ_ID}/smp_affinity_list
。
所以,直接看这 2 个操作对应的内核源代码 kernel/irq/proc.c
吧。
找到如下 2 个函数:
// https://github.com/torvalds/linux/blob/master/kernel/irq/proc.c
static ssize_t write_irq_affinity(int type, struct file *file,
const char __user *buffer, size_t count, loff_t *pos)
{
unsigned int irq = (int)(long)pde_data(file_inode(file));
// ...
}
static ssize_t irq_affinity_proc_write(struct file *file,
const char __user *buffer, size_t count, loff_t *pos)
{
return write_irq_affinity(0, file, buffer, count, pos);
}
static ssize_t irq_affinity_list_proc_write(struct file *file,
const char __user *buffer, size_t count, loff_t *pos)
{
return write_irq_affinity(1, file, buffer, count, pos);
}
使用 bpftrace
确认一下:
# bpftrace -l 'k:*irq_affinity*'
kprobe:irq_affinity_list_proc_write
kprobe:irq_affinity_proc_write
# bpftrace -e 'k:irq_affinity_list_proc_write, k:irq_affinity_proc_write { printf("irq_affinity: %s\n", comm); }'
Attaching 2 probes...
irq_affinity: zsh
跟踪 IRQ 绑核函数
因为不是要跟踪所有的 IRQ,而是只跟踪网卡 queue 对应的 IRQ;所以在 kprobe
这 2 个函数的时候,需要参考 (int)(long)pde_data(file_inode(file))
拿到 IRQ ID,并进行过滤。
而后,使用 bpf_get_current_pid_tgid()
拿到当前进程的 PID。
接着,产生一条 perf 事件,将 IRQ ID 和 PID 传递给用户态程序。
用户态程序接收到事件后,需要根据 PID 去查询进程信息,包括父进程信息,一遍确认是哪个进程在更改绑核配置。
总结
跟踪 IRQ 绑核的函数,kprobe
irq_affinity_list_proc_write
和 irq_affinity_proc_write
即可,并将 IRQ ID 和 PID 传递给用户态程序。