Skip to content

教程:Tracing04 - tcpdump

在本课中,我们将展示如何将数据包样本从 XDP 程序一直转储到 pcap 转储文件。

转储数据包样本

在此示例中,我们将展示如何通过 perf 事件将数据和数据包样本发送到用户空间。

首先你需要定义事件映射,它将允许你通过 perf 事件环形缓冲区将事件 发送到用户空间:

sh
struct {
	__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
	__type(key, int);
	__type(value, struct S);
	__uint(max_entries, MAX_CPUS);
} my_map SEC(".maps");

value 确定我们将通过 perf 事件环形缓冲区发布到用户空间的事件数据类型。 在我们的例子中是 struct S

sh
struct S {
        __u16 cookie;
        __u16 pkt_len;
} __packed;

我们设置事件的值(metadata 变量)并将它们传递给 bpf_perf_event_output 调用:

sh
int xdp_sample_prog(struct xdp_md *ctx)
{
        void *data_end = (void *)(long)ctx->data_end;
        void *data = (void *)(long)ctx->data;

	...

        __u64 flags = BPF_F_CURRENT_CPU;
        __u16 sample_size = (__u16)(data_end - data);
        struct S metadata;

        metadata.cookie = 0xdead;
        metadata.pkt_len = min(sample_size, SAMPLE_SIZE);

	ret = bpf_perf_event_output(ctx, &my_map, flags,
				    &metadata, sizeof(metadata));
	...

要将实际的数据包转储添加到事件,我们可以用请求的样本大小设置 flags 的高 32 位,bpf_perf_event_output 将把指定数量的数据包字节附加到 perf 事件:

sh
__u64 flags = BPF_F_CURRENT_CPU;

flags |= (__u64)sample_size << 32;

ret = bpf_perf_event_output(ctx, &my_map, flags,
                            &metadata, sizeof(metadata));

请在 xdp_sample_pkts_kern.c 文件中查看完整的 eBPF 代码。

作业

作业 1:设置测试环境

在本课中,我们将使用前一课的设置: Basic02 - 按名称加载程序 https://github.com/xdp-project/xdp-tutorial/tree/master/basic02-prog-by-name#assignment-2-add-xdp_abort-program

sh
$ sudo ../testenv/testenv.sh setup --name veth-basic02

并生成一些数据包:

sh
$ sudo ../testenv/testenv.sh enter --name veth-basic02
# ping  fc00:dead:cafe:1::1
PING fc00:dead:cafe:1::1(fc00:dead:cafe:1::1) 56 data bytes

作业 2:PCAP 转储文件

构建 xdp_sample_pkts_user 转储程序;为此你可能需要安装 libpcap-dev 和 32 位 libc dev 包。加载 eBPF 内核数据包转储程序并将数据包存储到 转储文件:

sh
$ sudo ./xdp_sample_pkts_user -d veth-basic02 -F
pkt len: 118   bytes. hdr: 76 58 28 55 df 4e fa e2 b6 27 8e 79 86 dd 60 0d 48 1b 00 40 3a 40 fc 00 de ad ca fe 00 ...
pkt len: 118   bytes. hdr: 76 58 28 55 df 4e fa e2 b6 27 8e 79 86 dd 60 0d 48 1b 00 40 3a 40 fc 00 de ad ca fe 00 ...
^C
2 packet samples stored in samples.pcap

使用 tcpdump 应用程序检查 pcap 转储:

sh
$ tcpdump -r ./samples.pcap
reading from file ./samples.pcap, link-type EN10MB (Ethernet)
12:12:04.553039 IP6 fc00:dead:cafe:1::2 > krava: ICMP6, echo request, seq 2177, length 64
12:12:05.576864 IP6 fc00:dead:cafe:1::2 > krava: ICMP6, echo request, seq 2178, length 64