在 Linux 增加新的 Qdisc
本文介绍如何在 Linux 中新增 qdisc,这里以 fq_new 为例。
1. 增加 fq_new.ko 内核模块
Linux 支持动态加载 qdisc 内核模块(.ko 文件),我们以 fq 为例创建新的 fq_new.ko。
- 安装相关依赖
sudo apt install make gcc build-essential linux-headers-$(uname -r) - 在工作路径复制 sch_fq.c 得到 sch_fq_new.c,在该路径下创建 include 目录,创建
pkt_sched_fq_new.h,内容参考下一节 - 修改 sch_fq_new.c(修改 Qdisc_ops 和 enqueue / dequeue 逻辑),增加 include
#include "pkt_sched_fq_new.h" static struct Qdisc_ops fq_new_qdisc_ops __read_mostly = { .id = "fq_new", ... } - 创建 Makefile
obj-m := sch_fq_new.o fq_new-y := sch_fq_new.o ccflags-y := -I$(PWD)/include KERNEL_VERSION = $(shell uname -r) all: make -C /lib/modules/$(KERNEL_VERSION)/build M=$(PWD) modules clean: make -C /lib/modules/$(KERNEL_VERSION)/build M=$(PWD) clean - 编译 sch_fq_new.c 得到 sch_fq_new.ko
# 编译 make # 安装模块 sudo insmod sch_fq_new.ko # 删除模块 sudo rmmod sch_fq_new.ko
2. 修改 iproute2 源码
修改 iproute2 源码来支持 fq_new
-
安装源码: iprout2-5.15.0
-
定义 fq_new 参数结构体
include/uapi/linux/pkt_sched.h- 内容参考 fq 的参数结构体即可
- 将新增内容同步到
pkt_sched_fq_new.h
-
创建
q_fq_new.c,根据pkt_sched.h修改参数即可-
需要注意要确保 id 和文件名或 qdisc_util 保持一致
cp tc/q_fq.c tc/q_fq_new.cstruct qdisc_util fq_new_qdisc_util = { .id = "fq_new", .parse_qopt = fq_new_parse_opt, .print_qopt = fq_new_print_opt, .print_xstats = fq_new_print_xstats, }; -
这是因为 tc 会先根据 id 值查找 .so 动态链接库或 qdisc_util,名称不一致会导致走 noexist 分支

-
对于 filter 同理
-
-
修改 tc 目录下的 Makefile,增加
TCMODULES += q_fq_new.o -
如果需要,可以修改 ip.c 和 tc.c 中的 Version 信息
<<< printf("tc utility, iproute2-%s", version); >>> printf("tc utility with fq_new, iproute2-%s", version); -
编译并安装
sudo apt install libdb4o-cil-dev libdb-dev bison flex sudo apt install libmnl-dev sudo apt install pkg-config sudo apt install pkg-config sudo apt install libcap-dev sudo apt install selinux-basics selinux-policy-default sudo apt install libbpf-dev ./configure make -j8 sudo make install
3. 测试
- 检查 iproute2 安装是否成功,如果输出和修改后的 Version 信息一直表明安装成功
tc -V - 给网卡添加队列,将 enp0s8 替换为本机网卡名称,可用 ip addr 查找
sudo tc qdisc add dev enp0s8 root handle 10: fq_new - 检查队列信息
tc qdisc show

被折叠的 条评论
为什么被折叠?



