Skip to content

Commit 6a008e9

Browse files
authored
rewrite sock_op program with libbpf 1.0+ (eunomia-bpf#84)
1 parent 15533a6 commit 6a008e9

15 files changed

+253
-290
lines changed

src/29-sockops/.gitignore

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,2 @@
1-
.vscode
2-
package.json
3-
*.o
4-
*.skel.json
5-
*.skel.yaml
6-
package.yaml
7-
ecli
8-
ecc
1+
.output
2+
.vscode

src/29-sockops/Makefile

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2+
OUTPUT := .output
3+
CLANG ?= clang
4+
LIBBPF_SRC := $(abspath ../third_party/libbpf/src)
5+
BPFTOOL_SRC := $(abspath ../third_party/bpftool/src)
6+
LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a)
7+
BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool)
8+
BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool
9+
LIBBLAZESYM_SRC := $(abspath ../third_party/blazesym/)
10+
LIBBLAZESYM_OBJ := $(abspath $(OUTPUT)/libblazesym.a)
11+
LIBBLAZESYM_HEADER := $(abspath $(OUTPUT)/blazesym.h)
12+
ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \
13+
| sed 's/arm.*/arm/' \
14+
| sed 's/aarch64/arm64/' \
15+
| sed 's/ppc64le/powerpc/' \
16+
| sed 's/mips.*/mips/' \
17+
| sed 's/riscv64/riscv/' \
18+
| sed 's/loongarch64/loongarch/')
19+
VMLINUX := ../third_party/vmlinux/$(ARCH)/vmlinux.h
20+
# Use our own libbpf API headers and Linux UAPI headers distributed with
21+
# libbpf to avoid dependency on system-wide headers, which could be missing or
22+
# outdated
23+
INCLUDES := -I$(OUTPUT) -I../third_party/libbpf/include/uapi -I$(dir $(VMLINUX))
24+
CFLAGS := -g -Wall
25+
ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS)
26+
27+
APPS = bpf_contrack bpf_redirect# minimal minimal_legacy uprobe kprobe fentry usdt sockfilter tc ksyscall
28+
29+
CARGO ?= $(shell which cargo)
30+
ifeq ($(strip $(CARGO)),)
31+
BZS_APPS :=
32+
else
33+
BZS_APPS := # profile
34+
APPS += $(BZS_APPS)
35+
# Required by libblazesym
36+
ALL_LDFLAGS += -lrt -ldl -lpthread -lm
37+
endif
38+
39+
# Get Clang's default includes on this system. We'll explicitly add these dirs
40+
# to the includes list when compiling with `-target bpf` because otherwise some
41+
# architecture-specific dirs will be "missing" on some architectures/distros -
42+
# headers such as asm/types.h, asm/byteorder.h, asm/socket.h, asm/sockios.h,
43+
# sys/cdefs.h etc. might be missing.
44+
#
45+
# Use '-idirafter': Don't interfere with include mechanics except where the
46+
# build would have failed anyways.
47+
CLANG_BPF_SYS_INCLUDES ?= $(shell $(CLANG) -v -E - </dev/null 2>&1 \
48+
| sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }')
49+
50+
ifeq ($(V),1)
51+
Q =
52+
msg =
53+
else
54+
Q = @
55+
msg = @printf ' %-8s %s%s\n' \
56+
"$(1)" \
57+
"$(patsubst $(abspath $(OUTPUT))/%,%,$(2))" \
58+
"$(if $(3), $(3))";
59+
MAKEFLAGS += --no-print-directory
60+
endif
61+
62+
define allow-override
63+
$(if $(or $(findstring environment,$(origin $(1))),\
64+
$(findstring command line,$(origin $(1)))),,\
65+
$(eval $(1) = $(2)))
66+
endef
67+
68+
$(call allow-override,CC,$(CROSS_COMPILE)cc)
69+
$(call allow-override,LD,$(CROSS_COMPILE)ld)
70+
71+
.PHONY: all
72+
all: bpf_redirect.bpf.o bpf_contrack.bpf.o
73+
74+
.PHONY: clean
75+
76+
77+
clean:
78+
$(call msg,CLEAN)
79+
$(Q)rm -rf $(OUTPUT) *.bpf.o
80+
81+
$(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT):
82+
$(call msg,MKDIR,$@)
83+
$(Q)mkdir -p $@
84+
85+
# Build libbpf
86+
$(LIBBPF_OBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)/libbpf
87+
$(call msg,LIB,$@)
88+
$(Q)$(MAKE) -C $(LIBBPF_SRC) BUILD_STATIC_ONLY=1 \
89+
OBJDIR=$(dir $@)/libbpf DESTDIR=$(dir $@) \
90+
INCLUDEDIR= LIBDIR= UAPIDIR= \
91+
install
92+
93+
# Build bpftool
94+
$(BPFTOOL): | $(BPFTOOL_OUTPUT)
95+
$(call msg,BPFTOOL,$@)
96+
$(Q)$(MAKE) ARCH= CROSS_COMPILE= OUTPUT=$(BPFTOOL_OUTPUT)/ -C $(BPFTOOL_SRC) bootstrap
97+
98+
99+
# Build BPF code
100+
%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL)
101+
$(call msg,BPF,$@)
102+
$(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) \
103+
$(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) \
104+
-c $(filter %.c,$^) -o $(patsubst %.bpf.o,%.tmp.bpf.o,$@)
105+
$(Q)$(BPFTOOL) gen object $@ $(patsubst %.bpf.o,%.tmp.bpf.o,$@)
106+
107+
108+

src/29-sockops/README.md

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ Merbridge 项目就是这样实现了用 eBPF 代替 iptables 为 Istio 进行
1717
### 编译 eBPF 程序
1818

1919
```shell
20-
# Compile the bpf_sockops program
21-
clang -O2 -g -Wall -target bpf -c bpf_sockops.c -o bpf_sockops.o
22-
clang -O2 -g -Wall -target bpf -c bpf_redir.c -o bpf_redir.o
20+
# Compile the bpf program with libbpf
21+
make
2322
```
2423

2524
### 加载 eBPF 程序
@@ -43,26 +42,45 @@ $ sudo bpftool prog show
4342
### 运行 [iperf3](https://iperf.fr/) 服务器
4443

4544
```shell
46-
iperf3 -s -p 10000
45+
iperf3 -s -p 5001
4746
```
4847

4948
### 运行 [iperf3](https://iperf.fr/) 客户端
5049

5150
```shell
52-
iperf3 -c 127.0.0.1 -t 10 -l 64k -p 10000
51+
iperf3 -c 127.0.0.1 -t 10 -l 64k -p 5001
5352
```
5453

5554
### 收集追踪
5655

56+
查看``sock_ops``追踪本地连接建立
5757
```console
58-
$ ./trace.sh
58+
$ ./trace_bpf_output.sh
5959
iperf3-9516 [001] .... 22500.634108: 0: <<< ipv4 op = 4, port 18583 --> 4135
6060
iperf3-9516 [001] ..s1 22500.634137: 0: <<< ipv4 op = 5, port 4135 --> 18583
6161
iperf3-9516 [001] .... 22500.634523: 0: <<< ipv4 op = 4, port 19095 --> 4135
6262
iperf3-9516 [001] ..s1 22500.634536: 0: <<< ipv4 op = 5, port 4135 --> 19095
6363
```
6464

65-
你应该可以看到 4 个用于套接字建立的事件。如果你没有看到任何事件,那么 eBPF 程序可能没有正确地附加上。
65+
当iperf3 -c建立连接后,你应该可以看到上述用于套接字建立的事件。如果你没有看到任何事件,那么 eBPF 程序可能没有正确地附加上。
66+
67+
此外,当``sk_msg``生效后,可以发现当使用tcpdump捕捉本地lo设备流量时,只能捕获三次握手和四次挥手流量,而iperf数据流量没有被捕获到。如果捕获到iperf数据流量,那么 eBPF 程序可能没有正确地附加上。
68+
69+
70+
```console
71+
$ ./trace_lo_traffic.sh
72+
# 三次握手
73+
13:24:07.181804 IP localhost.46506 > localhost.5001: Flags [S], seq 620239881, win 65495, options [mss 65495,sackOK,TS val 1982813394 ecr 0,nop,wscale 7], length 0
74+
13:24:07.181815 IP localhost.5001 > localhost.46506: Flags [S.], seq 1084484879, ack 620239882, win 65483, options [mss 65495,sackOK,TS val 1982813394 ecr 1982813394,nop,wscale 7], length 0
75+
13:24:07.181832 IP localhost.46506 > localhost.5001: Flags [.], ack 1, win 512, options [nop,nop,TS val 1982813394 ecr 1982813394], length 0
76+
77+
# 四次挥手
78+
13:24:12.475649 IP localhost.46506 > localhost.5001: Flags [F.], seq 1, ack 1, win 512, options [nop,nop,TS val 1982818688 ecr 1982813394], length 0
79+
13:24:12.479621 IP localhost.5001 > localhost.46506: Flags [.], ack 2, win 512, options [nop,nop,TS val 1982818692 ecr 1982818688], length 0
80+
13:24:12.481265 IP localhost.5001 > localhost.46506: Flags [F.], seq 1, ack 2, win 512, options [nop,nop,TS val 1982818694 ecr 1982818688], length 0
81+
13:24:12.481270 IP localhost.46506 > localhost.5001: Flags [.], ack 2, win 512, options [nop,nop,TS val 1982818694 ecr 1982818694], length 0
82+
83+
```
6684

6785
### 卸载 eBPF 程序
6886

src/29-sockops/README_en.md

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ This example program redirects traffic from the sender's socket (outbound) to th
1818

1919
```shell
2020
# Compile the bpf_sockops program
21-
clang -O2 -g -Wall -target bpf -c bpf_sockops.c -o bpf_sockops.o
22-
clang -O2 -g -Wall -target bpf -c bpf_redir.c -o bpf_redir.o
21+
make
2322
```
2423

2524
### Loading the eBPF Program
@@ -43,26 +42,44 @@ $ sudo bpftool prog show
4342
### Running the [iperf3](https://iperf.fr/) Server
4443

4544
```shell
46-
iperf3 -s -p 10000
45+
iperf3 -s -p 5001
4746
```
4847

4948
### Running the [iperf3](https://iperf.fr/) Client
5049

5150
```shell
52-
iperf3 -c 127.0.0.1 -t 10 -l 64k -p 10000
51+
iperf3 -c 127.0.0.1 -t 10 -l 64k -p 5001
5352
```
5453

5554
### Collecting Traces
5655

56+
Show connection setup tracing for localhost connection.
5757
```console
58-
$ ./trace.sh
58+
$ ./trace_bpf_output.sh
5959
iperf3-9516 [001] .... 22500.634108: 0: <<< ipv4 op = 4, port 18583 --> 4135
6060
iperf3-9516 [001] ..s1 22500.634137: 0: <<< ipv4 op = 5, port 4135 --> 18583
6161
iperf3-9516 [001] .... 22500.634523: 0: <<< ipv4 op = 4, port 19095 --> 4135
6262
iperf3-9516 [001] ..s1 22500.634536: 0: <<< ipv4 op = 5, port 4135 --> 19095
6363
```
6464

65-
You should be able to see 4 events for socket establishment. If you don't see any events, the eBPF program may not have been attached correctly.
65+
When ``iperf3 -c`` creates a connection, you should see the above events for socket setup. If you do not see any events, then the eBPF program may not have been properly attached.
66+
67+
In addition, when ``sk_msg`` is enabled, it can be observed that when using tcpdump to capture the traffic on the local lo device, only the three-way handshake and the four-way handshake traffic are captured, but the iperf data traffic is not captured. If the iperf data traffic is captured, then the eBPF program may not have been properly attached.
68+
69+
```console
70+
$ ./trace_lo_traffic.sh
71+
# three-way handshake
72+
13:24:07.181804 IP localhost.46506 > localhost.5001: Flags [S], seq 620239881, win 65495, options [mss 65495,sackOK,TS val 1982813394 ecr 0,nop,wscale 7], length 0
73+
13:24:07.181815 IP localhost.5001 > localhost.46506: Flags [S.], seq 1084484879, ack 620239882, win 65483, options [mss 65495,sackOK,TS val 1982813394 ecr 1982813394,nop,wscale 7], length 0
74+
13:24:07.181832 IP localhost.46506 > localhost.5001: Flags [.], ack 1, win 512, options [nop,nop,TS val 1982813394 ecr 1982813394], length 0
75+
76+
# four-way handshake traffic
77+
13:24:12.475649 IP localhost.46506 > localhost.5001: Flags [F.], seq 1, ack 1, win 512, options [nop,nop,TS val 1982818688 ecr 1982813394], length 0
78+
13:24:12.479621 IP localhost.5001 > localhost.46506: Flags [.], ack 2, win 512, options [nop,nop,TS val 1982818692 ecr 1982818688], length 0
79+
13:24:12.481265 IP localhost.5001 > localhost.46506: Flags [F.], seq 1, ack 2, win 512, options [nop,nop,TS val 1982818694 ecr 1982818688], length 0
80+
13:24:12.481270 IP localhost.46506 > localhost.5001: Flags [.], ack 2, win 512, options [nop,nop,TS val 1982818694 ecr 1982818694], length 0
81+
```
82+
6683

6784
### Unloading the eBPF Program
6885

src/29-sockops/bpf_contrack.bpf.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include "bpf_sockmap.h"
2+
3+
char LICENSE[] SEC("license") = "Dual BSD/GPL";
4+
5+
SEC("sockops")
6+
int bpf_sockops_handler(struct bpf_sock_ops *skops){
7+
u32 family, op;
8+
9+
family = skops->family;
10+
op = skops->op;
11+
if (op != BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB
12+
&& op != BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB) {
13+
return BPF_OK;
14+
}
15+
16+
if(skops->remote_ip4 != LOCALHOST_IPV4 || skops->local_ip4!= LOCALHOST_IPV4) {
17+
return BPF_OK;
18+
}
19+
20+
struct sock_key key = {
21+
.dip = skops->remote_ip4,
22+
.sip = skops->local_ip4,
23+
.sport = bpf_htonl(skops->local_port), /* convert to network byte order */
24+
.dport = skops->remote_port,
25+
.family = skops->family,
26+
};
27+
28+
bpf_printk(">>> new connection: OP:%d, PORT:%d --> %d\n", op, bpf_ntohl(key.sport), bpf_ntohl(key.dport));
29+
30+
bpf_sock_hash_update(skops, &sock_ops_map, &key, BPF_NOEXIST);
31+
return BPF_OK;
32+
}

src/29-sockops/bpf_redir.c

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/29-sockops/bpf_redirect.bpf.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include "bpf_sockmap.h"
2+
3+
char LICENSE[] SEC("license") = "Dual BSD/GPL";
4+
5+
SEC("sk_msg")
6+
int bpf_redir(struct sk_msg_md *msg)
7+
{
8+
if(msg->remote_ip4 != LOCALHOST_IPV4 || msg->local_ip4!= LOCALHOST_IPV4)
9+
return SK_PASS;
10+
11+
struct sock_key key = {
12+
.sip = msg->remote_ip4,
13+
.dip = msg->local_ip4,
14+
.dport = bpf_htonl(msg->local_port), /* convert to network byte order */
15+
.sport = msg->remote_port,
16+
.family = msg->family,
17+
};
18+
return bpf_msg_redirect_hash(msg, &sock_ops_map, &key, BPF_F_INGRESS);
19+
}

src/29-sockops/bpf_sockmap.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include "vmlinux.h"
2+
#include <bpf/bpf_endian.h>
3+
#include <bpf/bpf_helpers.h>
4+
5+
#define LOCALHOST_IPV4 16777343
6+
7+
struct sock_key {
8+
__u32 sip;
9+
__u32 dip;
10+
__u32 sport;
11+
__u32 dport;
12+
__u32 family;
13+
};
14+
15+
struct {
16+
__uint(type, BPF_MAP_TYPE_SOCKHASH);
17+
__uint(max_entries, 65535);
18+
__type(key, struct sock_key);
19+
__type(value, int);
20+
} sock_ops_map SEC(".maps");

src/29-sockops/bpf_sockops.c

Lines changed: 0 additions & 52 deletions
This file was deleted.

0 commit comments

Comments
 (0)