eBPF 深度剖析 第11节 eBPF 与 tc——流量控制的艺术 |
就像交响乐团的指挥用指挥棒精确控制每个乐手的出场时机,Linux 的流量控制(tc)用 eBPF 程序精确控制每个数据包的去向——谁先走、谁后走、谁要改道、谁直接劝退。 |
一、为什么需要 tc?(XDP 解决不了的问题)
XDP 很强大,但它有个致命弱点:只能在网卡驱动层拦截数据包,而且只能处理入站流量(ingress)。
1.2 tc 出场
tc(traffic control) 是 Linux 内核的流量控制系统,它能做 XDP 做不到的事:
| 出站流量控制 | |
| 入站流量处理 | |
| 流量整形 | |
| 队列管理 | |
| 与 eBPF 配合 |
一句话总结:XDP 是"门卫"(只管进门),tc 是"交通指挥官"(管进出双向)。 |
二、tc 架构——qdisc、class、filter
tc 的核心概念有三个,理解它们就理解了流量控制:
2.1 qdisc(排队规则)
qdisc = queueing discipline(排队规则)。每个网卡都有一个 qdisc,决定数据包如何排队、如何发送。
2.2 class(类别)
class 是 qdisc 的子节点,可以对流量分层限速。比如:
htb qdisc ├── class 1:1(总带宽 100Mbps) ├── class 1:10(SSH,保证 10Mbps) ├── class 1:20(HTTP,保证 30Mbps) └── class 1:30(其他,剩余带宽) |
2.3 filter(过滤器)
filter 决定"这个数据包属于哪个 class"。而 eBPF 程序,就是最高级的 filter。
数据包到达 → filter 判断 → 放到对应 class 的队列 → 按规则发送 |
三、clsact qdisc——eBPF 的最佳拍档
3.1 为什么用 clsact?
传统的 tc qdisc(如 htb)是有队列的,会引入延迟。而 clsact(classifier and action) 是专为 eBPF 设计的无队列 qdisc:
3.2 挂载 clsact
|
四、eBPF 在 tc 上的挂载方式
4.1 ingress 和 egress
tc 支持两个挂载点:
4.2 用 tc 命令挂载 eBPF 程序
|
4.3 查看已挂载的 tc eBPF 程序
|
五、XDP vs tc——该用哪个?
这是 eBPF 开发者最常问的问题。答案:看场景。
5.1 性能对比
5.2 决策树
|
六、实战:用 tc + eBPF 做流量分类
6.1 目标
功能:用 tc 挂载 eBPF 程序,实现:
1. 统计入站/出站包数量 2. 丢弃所有 SSH(端口 22)流量 3. 标记 HTTP(端口 80)流量(修改 DSCP 字段) |
6.2 内核态代码(tc_classifier.c)
|
6.3 编译
|
6.4 挂载到 ingress 和 egress
|
6.5 测试
|
6.6 卸载
|
七、tc 与 XDP 的协同使用
7.1 分层防御
在实际生产中,XDP 和 tc 通常配合使用:
数据包到达网卡 ↓ [XDP] 超高速丢包(DDOS 防护、黑名单过滤) ↓(放过) [协议栈处理] ↓ [tc ingress] 精细过滤(修改包、复杂逻辑) ↓(放过) [上层应用] ↓(发出) [tc egress] 流量整形、QoS、出站过滤 ↓ 发出网卡 |
7.2 Cilium 的做法
Cilium(Kubernetes 网络插件)就是 XDP + tc 协同的典范:
八、常用 tc + eBPF 场景
8.1 场景1:容器网络限速
|
8.2 场景2:Kubernetes Service 负载均衡(Cilium)
Cilium 用 eBPF 在 tc 层做 Service 负载均衡:
Pod A 访问 Service IP:Port ↓ [tc egress] eBPF 程序修改目标 IP:Port 为后端 Pod IP:Port ↓ 直接发送到后端 Pod(绕过 iptables) |
8.3 场景3:流量镜像(Mirror)
用 eBPF 在 tc 层复制数据包,发送到监控端口:
|
九、总结
9.1 下一步
- 第 12 节:eBPF 与 perf_event——如何高效将内核数据传到用户态 - 第 13 节:eBPF 与 tracing(kprobe/uprobe)——用 eBPF 追踪内核和用户态函数 |
我是 [你的名字],正在连载「eBPF 深度解析」系列(共 100 节)。 下节见 🚀 |
◆ ◆ ◆