tc ebpf 实践

1. 用 tc 加载 BPF 程序

给定一个为 tc 编译的 BPF 对象文件 prog.o, 可以通过 tc 命令将其加载到一个网 络设备(netdevice)。但与 XDP 不同,设备是否支持 attach BPF 程序并不依赖驱动 (即任何网络设备都支持 tc BPF)。下面的命令可以将程序 attach 到 em1 的ingress 网络:

$ tc qdisc add dev em1 clsact

$ tc filter add dev em1 ingress bpf da obj prog.o

第一步创建了一个 clsact qdisc (Linux 排队规则,Linux queueing discipline)。

clsact 是一个 dummy qdisc,和 ingress qdisc 类似,可以持有(hold)分类器和 动作(classifier and actions),但不执行真正的排队(queueing)。后面 attach bpf 分类器需要用到它。clsact qdisc 提供了两个特殊的 hook:ingress and egress,分类器可以 attach 到这两个 hook 点。这两个 hook 都位于 datapath 的 关键收发路径上,设备 em1 的每个包都会经过这两个点。这两个 hook 分别会被下面的内 核函数调用:

  • ingress hook:__netif_receive_skb_core() -> sch_handle_ingress()
  • egress hook:__dev_queue_xmit() -> sch_handle_egress()

 类似地,将程序 attach 到 egress hook:

$ tc filter add dev em1 egress bpf da obj prog.o

 

第二条命令,tc filter 选择了在 da(direct-action)模式中使用 bpfda 是 推荐的模式,并且应该永远指定这个参数。粗略地说,da 模式表示 bpf 分类器不需 要调用外部的 tc action 模块。事实上 bpf 分类器也完全不需要调用外部模块,因 为所有的 packet mangling、转发或其他类型的 action 都可以在这单个 BPF 程序内完成 ,因此执行会明显更快。

配置了这两条命令之后,程序就 attach 完成了,接下来只要有包经过这个设备,就会触发 这个程序执行。和 XDP 类似,如果没有使用默认 section 名字,那可以在加载时指定,例 如指定 section 为 foobar

$ tc filter add dev em1 egress bpf da obj prog.o sec foobar

查看已经 attach 的程序:

 

$ tc filter show dev em1 ingress

filter protocol all pref 49152 bpf

filter protocol all pref 49152 bpf handle 0x1 prog.o:[ingress] direct-action id 1 tag c5f7825e5dac396f

$ tc filter show dev em1 egress

filter protocol all pref 49152 bpf

filter protocol all pref 49152 bpf handle 0x1 prog.o:[egress] direct-action id 2 tag b2fd5adc0f262714

输出中的 prog.o:[ingress] 表示 section ingress 中的程序是从 文件 prog.o 加 载的,而且 bpf 工作在 direct-action 模式。上面还打印了程序的 id 和 tag, 其中 tag 是指令流(instruction stream)的哈希,可以关联到对应的对象文件或用perf 查看调用栈信息。id 是一个操作系统层唯一的 BPF 程序标识符,可以用 bpftool 进一步查看或 dump 相关的程序信息。

程序优先级(pref)和句柄(handle

在上面的 show 命令中,tc 还打印出了 pref 49152 和 handle 0x1。如果之前没有 通过命令行显式指定,这两个数据就会自动生成。pref 表示优先级,如果指定了多个分 类器,它们会按照优先级从高到低依次执行;handle 是一个标识符,在加载了同一分类器的多 个实例并且它们的优先级(pref)都一样的情况下会用到这个标识符。因为 在 BPF 的场景下,单个程序就足够了,因此 pref 和 handle 通常情况下都可以忽略。

除非打算后面原子地替换 attached BPF 程序,否则不建议在加载时显式指定 pref 和 handle。显式指定这两个参数的好处是,后面执行 replace 操作时,就不需要再去动 态地查询这两个值。显式指定 pref 和 handle 时的加载命令:

$ tc filter add dev em1 ingress pref 1 handle 1 bpf da obj prog.o sec foobar
 
$ tc filter show dev em1 ingress
filter protocol all pref 1 bpf
filter protocol all pref 1 bpf handle 0x1 prog.o:[foobar] direct-action id 1 tag c5f7825e5dac396f

 对应的原子 replace 命令:将 ingress hook 处的已有程序替换为 prog.o 文件中 foobar section 中的新 BPF 程序

$ tc filter replace dev em1 ingress pref 1 handle 1 bpf da obj prog.o sec foobar

2. 用 tc 删除 BPF 程序

要分别从 ingress 和 egress 删除所有 attach 的程序

$ tc filter del dev em1 ingress
$ tc filter del dev em1 egress

要从 netdevice 删除整个 clsact qdisc(会隐式地删除 attach 到 ingress 和 egress hook 上面的所有程序),执行


$ tc qdisc del dev em1 clsact

3. offload 到网卡

如果网卡驱动支持 tc BPF 程序,那也可以将它们 offload 到网卡 。Netronome 的 nfp 网卡对 XDP 和 tc BPF 程序都支持 offload。

$ tc qdisc add dev em1 clsact
$ tc filter replace dev em1 ingress pref 1 handle 1 bpf skip_sw da obj prog.o
Error: TC offload is disabled on net device.
We have an error talking to the kernel

如果显式以上错误,那需要先启用网卡的 hw-tc-offload 功能:

$ ethtool -K em1 hw-tc-offload on
 
$ tc qdisc add dev em1 clsact
$ tc filter replace dev em1 ingress pref 1 handle 1 bpf skip_sw da obj prog.o
$ tc filter show dev em1 ingress
filter protocol all pref 1 bpf
filter protocol all pref 1 bpf handle 0x1 prog.o:[classifier] direct-action skip_sw in_hw id 19 tag 57cd311f2e27366b

其中的 in_hw 标志表示这个程序已经被 offload 到网卡了。

注意,tc 和 XDP offload 无法同时加载,因此必须要指明是 tc 还是 XDP offload 选项 。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
eBPF(extended Berkeley Packet Filter)是一种在Linux内核中执行程序的技术,它可以用于网络分析、性能监控、安全审计等多种用途。下面是一个eBPF入门实践教程的大致步骤: 1. 确保你的系统支持eBPF:你需要一个运行Linux内核4.1或更高版本的机器,并且要启用eBPF功能。你可以通过运行`uname -r`命令来检查你的内核版本。 2. 安装所需的工具:你需要安装clang编译器、LLVM和libbpf库。这些工具可以帮助你编写和编译eBPF程序。你可以使用包管理器(如apt、yum等)来安装这些工具。 3. 学习eBPF原理:了解eBPF的基本概念和工作原理是很重要的。eBPF程序是一种在内核中执行的小型虚拟机程序,它可以通过钩子函数与内核交互并处理数据。 4. 编写eBPF程序:使用C语言编写eBPF程序,并使用clang编译器将其编译为eBPF字节码。eBPF程序可以通过BPF syscall加载到内核中。 5. 调试和测试:在运行eBPF程序之前,你可以使用bpftool和bpfsyscall等工具进行调试和测试。这些工具可以帮助你检查eBPF程序的正确性和性能。 6. 部署eBPF程序:一旦你的eBPF程序通过测试,你可以使用ip、tc等工具将其部署到实际的网络环境中。这些工具允许你在网络数据包到达内核之前或之后执行eBPF程序。 以上是一个简单的eBPF入门实践教程的大致步骤。在实际使用中,你可能会遇到更多的挑战和复杂性。但通过不断学习和实践,你将能够掌握eBPF技术并应用于各种场景中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值