linux-kernel - 简单的 eBPF 操作不会对 tc 生效

标签 linux-kernel bpf ebpf

我从 samples/bpf/pare_simple.c(来自 Linux 内核树)编译了 BPF 示例,做了非常简单的更改:

SEC("simple")
int handle_ingress(struct __sk_buff *skb)
{
   return TC_ACT_SHOT;
}

所以我希望丢弃任何数据包。我按如下方式安装它:

这发生在 Ubuntu 16.04.3 LTS 上,内核为 4.4.0-98,llvm 和版本 3.8 的 clang 从包中安装,iproute2 是 github 上的最新版本。

$ tc qdisc add dev eth0 clsact
$ tc filter add dev eth0 ingress bpf \
      object-file ./net-next.git/samples/bpf/parse_simple.o \
      section simple verbose

Prog section 'simple' loaded (5)!
 - Type:         3
 - Instructions: 2 (0 over limit)
 - License:      GPL

Verifier analysis:

0: (b7) r0 = 2
1: (95) exit
processed 2 insns, stack depth 0

所以它似乎安装成功,但是这个过滤器/ebpf 不会丢弃数据包,我在 eth0 接口(interface)上生成入口流量,例如ICMP,然后继续。我做错了什么?

最佳答案

TL;DR:您应该将 direct-action 标志添加到 tc filter 命令,如

tc filter add dev eth0 ingress bpf \
    object-file ./net-next.git/samples/bpf/parse_simple.o \
    section simple direct-action verbose
                   ^^^^^^^^^^^^^

tc bpf filter bpf help 的简短帮助提到了这个标志,但目前还没有进入 tc-bpf(8) 手册页,如果我没记错的话。

那么,这个标志是做什么用的?

eBPF 程序可以通过两种方式附加到 tc:作为 Action ,或作为分类器。附有tc filter add 的分类器应该用于过滤数据包,默认情况下不应用任何操作。这意味着它们的返回值具有以下含义(来自 man tc-bpf):

0 , denotes a mismatch

-1 , denotes the default classid configured from the command line

else , everything else will override the default classid to provide a facility for non-linear matching

另一方面,附有 tc action add 的操作可以丢弃、镜像或对数据包执行其他操作,但它们不应该实际过滤它们。

因为 eBPF 比 tc 的传统操作和过滤器更灵活,您实际上可以同时执行这两项操作,过滤数据包(即识别此数据包)并对它执行操作。为了反射(reflect)这种灵 active ,添加了 direct-actionda 标志(对于内核 4.4 或更新版本,具有匹配的 iproute2 包)。它告诉内核将操作(TC_ACT_SHOTTC_ACT_OK 等)的返回值用于分类器。这就是您在此处以内核理解您想要丢弃数据包的方式返回 TC_ACT_SHOT 所需要的。

如果我没记错的话,我们使用这个标志而不是仅仅为操作删除过滤器的原因是你无论如何都需要一个带有 tc 的过滤器来附加你的操作? (待确认)。因此,使用 direct-action 标志,您不必同时附加一个过滤器和一个操作,过滤器可以执行这两种操作。这应该是使用 tc 进行 eBPF 编程的首选方式。

关于linux-kernel - 简单的 eBPF 操作不会对 tc 生效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47591176/

相关文章:

无法编译示例 bpf 程序,缺少 bpf/bpf.h

linux-kernel - 为什么自旋锁在单处理器(单核)系统中不起作用?

linux - 执行 ioctl 时关闭文件描述符

linux - 为 2 个内核分区 Beaglebone 内部 mmc

linux - .function() 和 .function().call 在 systemtap 中的区别

c - 对 seccomp 的隐式引用

linux-kernel - 如何在Ubuntu 20.04上编译BCC?

每种类型的 ebpf 程序的上下文

bpf - XDP 卸载模式标志集不适用于 bcc

linux - 从内核空间访问 BPF 映射