Skip to content

Commit baa0494

Browse files
committed
Adding tracing04-xdp-tcpdump example
In this lesson we will show how to dump the packet samples from XDP program all the way to the pcap dump file. Adding support for example specific libraries to be specified with USER_LIBS variable. Using it for -lpcap in here. Signed-off-by: Jiri Olsa <jolsa@kernel.org>
1 parent 7b22e4e commit baa0494

6 files changed

Lines changed: 574 additions & 2 deletions

File tree

common/common.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ CFLAGS ?= -I$(LIBBPF_DIR)/root/usr/include/ -g
4242
CFLAGS += -I../headers/
4343
LDFLAGS ?= -L$(LIBBPF_DIR)
4444

45-
LIBS = -l:libbpf.a -lelf
45+
LIBS = -l:libbpf.a -lelf $(USER_LIBS)
4646

4747
all: llvm-check $(USER_TARGETS) $(XDP_OBJ) $(COPY_LOADER) $(COPY_STATS)
4848

tracing03-xdp-debug-print/README.org

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ $ sudo ../testenv/testenv.sh setup --name veth-basic02
8787
#+end_example
8888

8989
Load XDP program from xdp_prog_kern.o that will print
90-
ethertnet header on every incomming packet:
90+
ethertnet header on every incoming packet:
9191

9292
#+begin_example sh
9393
$ sudo ../basic02-prog-by-name/xdp_loader --dev veth-basic02 --force --progsec xdp

tracing04-xdp-tcpdump/Makefile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2+
3+
XDP_TARGETS := xdp_sample_pkts_kern
4+
USER_TARGETS := xdp_sample_pkts_user
5+
USER_LIBS=-lpcap
6+
7+
LLC ?= llc
8+
CLANG ?= clang
9+
CC := gcc
10+
11+
LIBBPF_DIR = ../libbpf/src/
12+
COMMON_DIR = ../common/
13+
14+
include $(COMMON_DIR)/common.mk
15+
COMMON_OBJS := $(COMMON_DIR)/common_params.o

tracing04-xdp-tcpdump/README.org

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# -*- fill-column: 76; -*-
2+
#+TITLE: Tutorial: Tracing04 - tcpdump
3+
#+OPTIONS: ^:nil
4+
5+
In this lesson we will show how to dump the packet samples
6+
from XDP program all the way to the pcap dump file.
7+
8+
9+
* Table of Contents :TOC:
10+
- [[#dump-the-packet-sample][Dump the packet sample]]
11+
- [[#assignments][Assignments]]
12+
- [[#assignment-1-setup][Assignment 1: Setting up your test lab]]
13+
- [[#assignment-2-pcap-dump][Assignment 2: The PCAP dump file]]
14+
15+
* Dump the packet sample
16+
17+
In this example we will show how to send data and packet sample
18+
into user space via perf event.
19+
20+
First you need to define the event map, which will allow you
21+
to send events to the user space via perf event ring buffer:
22+
23+
#+begin_example sh
24+
struct bpf_map_def SEC("maps") my_map = {
25+
.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
26+
.key_size = sizeof(int),
27+
.value_size = sizeof(__u32),
28+
.max_entries = MAX_CPUS,
29+
};
30+
#+end_example
31+
32+
The value_size determines the size of the event data we will
33+
be posting to the user space through perf event ring buffer.
34+
In our case it's sizeof(u32) which is size of following structure:
35+
36+
#+begin_example sh
37+
struct S {
38+
__u16 cookie;
39+
__u16 pkt_len;
40+
} __packed;
41+
#+end_example
42+
43+
We set the values of the event (metadata variable) and pass them
44+
into the bpf_perf_event_output call:
45+
46+
#+begin_example sh
47+
int xdp_sample_prog(struct xdp_md *ctx)
48+
{
49+
void *data_end = (void *)(long)ctx->data_end;
50+
void *data = (void *)(long)ctx->data;
51+
52+
...
53+
54+
__u64 flags = BPF_F_CURRENT_CPU;
55+
struct S metadata;
56+
57+
metadata.cookie = 0xdead;
58+
metadata.pkt_len = (__u16)(data_end - data);
59+
60+
ret = bpf_perf_event_output(ctx, &my_map, flags,
61+
&metadata, sizeof(metadata));
62+
...
63+
#+end_example
64+
65+
To add the actual packet dump to the event, we can
66+
set flags upper 32 bits with the size of the requested sample
67+
and the bpf_perf_event_output will attach the specified
68+
amount of bytes from packet to the perf event:
69+
70+
71+
#+begin_example sh
72+
__u64 flags = BPF_F_CURRENT_CPU;
73+
74+
flags |= (__u64)sample_size << 32;
75+
76+
ret = bpf_perf_event_output(ctx, &my_map, flags,
77+
&metadata, sizeof(metadata));
78+
#+end_example
79+
80+
Please check the whole eBPF code in xdp_sample_pkts_kern.c file.
81+
82+
* Assignments
83+
84+
** Assignment 1: Setting up your test lab
85+
86+
In this lesson we will use the setup of the previous lesson:
87+
Basic02 - loading a program by name [[https://github.com/xdp-project/xdp-tutorial/tree/master/basic02-prog-by-name#assignment-2-add-xdp_abort-program]]
88+
89+
#+begin_example sh
90+
$ sudo ../testenv/testenv.sh setup --name veth-basic02
91+
#+end_example
92+
93+
and make some packets:
94+
95+
#+begin_example sh
96+
$ sudo ../testenv/testenv.sh enter --name veth-basic02
97+
# ping fc00:dead:cafe:1::1
98+
PING fc00:dead:cafe:1::1(fc00:dead:cafe:1::1) 56 data bytes
99+
#+end_example
100+
101+
** Assignment 2: The PCAP dump file
102+
103+
Load the eBPF kernel packets dump program and store the packets to the dump file:
104+
105+
#+begin_example sh
106+
$ sudo ./xdp_sample_pkts_user -d veth-basic02 -F
107+
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 ...
108+
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 ...
109+
^C
110+
2 packet samples stored in samples.pcap
111+
#+end_example
112+
113+
Check the pcap dump with the tcpdump application:
114+
#+begin_example sh
115+
$ tcpdump -r ./samples.pcap
116+
reading from file ./samples.pcap, link-type EN10MB (Ethernet)
117+
12:12:04.553039 IP6 fc00:dead:cafe:1::2 > krava: ICMP6, echo request, seq 2177, length 64
118+
12:12:05.576864 IP6 fc00:dead:cafe:1::2 > krava: ICMP6, echo request, seq 2178, length 64
119+
#+end_example
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <linux/bpf.h>
3+
#include <string.h>
4+
#include "bpf_helpers.h"
5+
6+
#define SAMPLE_SIZE 1024ul
7+
#define MAX_CPUS 128
8+
9+
#ifndef __packed
10+
#define __packed __attribute__((packed))
11+
#endif
12+
13+
#define min(x, y) ((x) < (y) ? (x) : (y))
14+
15+
#define bpf_printk(fmt, ...) \
16+
({ \
17+
char ____fmt[] = fmt; \
18+
bpf_trace_printk(____fmt, sizeof(____fmt), \
19+
##__VA_ARGS__); \
20+
})
21+
22+
/* Metadata will be in the perf event before the packet data. */
23+
struct S {
24+
__u16 cookie;
25+
__u16 pkt_len;
26+
} __packed;
27+
28+
struct bpf_map_def SEC("maps") my_map = {
29+
.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
30+
.key_size = sizeof(int),
31+
.value_size = sizeof(__u32),
32+
.max_entries = MAX_CPUS,
33+
};
34+
35+
SEC("xdp_sample")
36+
int xdp_sample_prog(struct xdp_md *ctx)
37+
{
38+
void *data_end = (void *)(long)ctx->data_end;
39+
void *data = (void *)(long)ctx->data;
40+
41+
if (data < data_end) {
42+
/* The XDP perf_event_output handler will use the upper 32 bits
43+
* of the flags argument as a number of bytes to include of the
44+
* packet payload in the event data. If the size is too big, the
45+
* call to bpf_perf_event_output will fail and return -EFAULT.
46+
*
47+
* See bpf_xdp_event_output in net/core/filter.c.
48+
*
49+
* The BPF_F_CURRENT_CPU flag means that the event output fd
50+
* will be indexed by the CPU number in the event map.
51+
*/
52+
__u64 flags = BPF_F_CURRENT_CPU;
53+
__u16 sample_size;
54+
int ret;
55+
struct S metadata;
56+
57+
metadata.cookie = 0xdead;
58+
metadata.pkt_len = (__u16)(data_end - data);
59+
sample_size = min(metadata.pkt_len, SAMPLE_SIZE);
60+
61+
flags |= (__u64)sample_size << 32;
62+
63+
ret = bpf_perf_event_output(ctx, &my_map, flags,
64+
&metadata, sizeof(metadata));
65+
if (ret)
66+
bpf_printk("perf_event_output failed: %d\n", ret);
67+
}
68+
69+
return XDP_PASS;
70+
}
71+
72+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)