From 6a008e9efe8fba2b7709b8464d55446cd4dbddd9 Mon Sep 17 00:00:00 2001 From: Hao Liu <33043980+SirHao@users.noreply.github.com> Date: Wed, 6 Dec 2023 18:04:58 +0800 Subject: [PATCH] rewrite sock_op program with libbpf 1.0+ (#84) --- src/29-sockops/.gitignore | 10 +- src/29-sockops/Makefile | 108 +++++++++++++++++++ src/29-sockops/README.md | 32 ++++-- src/29-sockops/README_en.md | 29 +++-- src/29-sockops/bpf_contrack.bpf.c | 32 ++++++ src/29-sockops/bpf_redir.c | 27 ----- src/29-sockops/bpf_redirect.bpf.c | 19 ++++ src/29-sockops/bpf_sockmap.h | 20 ++++ src/29-sockops/bpf_sockops.c | 52 --------- src/29-sockops/bpf_sockops.h | 168 ----------------------------- src/29-sockops/load.sh | 26 ++--- src/29-sockops/trace.sh | 2 - src/29-sockops/trace_bpf_output.sh | 2 + src/29-sockops/trace_lo_traffic.sh | 4 + src/29-sockops/unload.sh | 14 ++- 15 files changed, 254 insertions(+), 291 deletions(-) create mode 100644 src/29-sockops/Makefile create mode 100644 src/29-sockops/bpf_contrack.bpf.c delete mode 100644 src/29-sockops/bpf_redir.c create mode 100644 src/29-sockops/bpf_redirect.bpf.c create mode 100644 src/29-sockops/bpf_sockmap.h delete mode 100644 src/29-sockops/bpf_sockops.c delete mode 100644 src/29-sockops/bpf_sockops.h delete mode 100755 src/29-sockops/trace.sh create mode 100755 src/29-sockops/trace_bpf_output.sh create mode 100755 src/29-sockops/trace_lo_traffic.sh diff --git a/src/29-sockops/.gitignore b/src/29-sockops/.gitignore index 024ee36..2f694fe 100644 --- a/src/29-sockops/.gitignore +++ b/src/29-sockops/.gitignore @@ -1,8 +1,2 @@ -.vscode -package.json -*.o -*.skel.json -*.skel.yaml -package.yaml -ecli -ecc +.output +.vscode \ No newline at end of file diff --git a/src/29-sockops/Makefile b/src/29-sockops/Makefile new file mode 100644 index 0000000..adb3250 --- /dev/null +++ b/src/29-sockops/Makefile @@ -0,0 +1,108 @@ +# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) +OUTPUT := .output +CLANG ?= clang +LIBBPF_SRC := $(abspath ../third_party/libbpf/src) +BPFTOOL_SRC := $(abspath ../third_party/bpftool/src) +LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a) +BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool) +BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool +LIBBLAZESYM_SRC := $(abspath ../third_party/blazesym/) +LIBBLAZESYM_OBJ := $(abspath $(OUTPUT)/libblazesym.a) +LIBBLAZESYM_HEADER := $(abspath $(OUTPUT)/blazesym.h) +ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \ + | sed 's/arm.*/arm/' \ + | sed 's/aarch64/arm64/' \ + | sed 's/ppc64le/powerpc/' \ + | sed 's/mips.*/mips/' \ + | sed 's/riscv64/riscv/' \ + | sed 's/loongarch64/loongarch/') +VMLINUX := ../third_party/vmlinux/$(ARCH)/vmlinux.h +# Use our own libbpf API headers and Linux UAPI headers distributed with +# libbpf to avoid dependency on system-wide headers, which could be missing or +# outdated +INCLUDES := -I$(OUTPUT) -I../third_party/libbpf/include/uapi -I$(dir $(VMLINUX)) +CFLAGS := -g -Wall +ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) + +APPS = bpf_contrack bpf_redirect# minimal minimal_legacy uprobe kprobe fentry usdt sockfilter tc ksyscall + +CARGO ?= $(shell which cargo) +ifeq ($(strip $(CARGO)),) +BZS_APPS := +else +BZS_APPS := # profile +APPS += $(BZS_APPS) +# Required by libblazesym +ALL_LDFLAGS += -lrt -ldl -lpthread -lm +endif + +# Get Clang's default includes on this system. We'll explicitly add these dirs +# to the includes list when compiling with `-target bpf` because otherwise some +# architecture-specific dirs will be "missing" on some architectures/distros - +# headers such as asm/types.h, asm/byteorder.h, asm/socket.h, asm/sockios.h, +# sys/cdefs.h etc. might be missing. +# +# Use '-idirafter': Don't interfere with include mechanics except where the +# build would have failed anyways. +CLANG_BPF_SYS_INCLUDES ?= $(shell $(CLANG) -v -E - &1 \ + | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') + +ifeq ($(V),1) + Q = + msg = +else + Q = @ + msg = @printf ' %-8s %s%s\n' \ + "$(1)" \ + "$(patsubst $(abspath $(OUTPUT))/%,%,$(2))" \ + "$(if $(3), $(3))"; + MAKEFLAGS += --no-print-directory +endif + +define allow-override + $(if $(or $(findstring environment,$(origin $(1))),\ + $(findstring command line,$(origin $(1)))),,\ + $(eval $(1) = $(2))) +endef + +$(call allow-override,CC,$(CROSS_COMPILE)cc) +$(call allow-override,LD,$(CROSS_COMPILE)ld) + +.PHONY: all +all: bpf_redirect.bpf.o bpf_contrack.bpf.o + +.PHONY: clean + + +clean: + $(call msg,CLEAN) + $(Q)rm -rf $(OUTPUT) *.bpf.o + +$(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT): + $(call msg,MKDIR,$@) + $(Q)mkdir -p $@ + +# Build libbpf +$(LIBBPF_OBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)/libbpf + $(call msg,LIB,$@) + $(Q)$(MAKE) -C $(LIBBPF_SRC) BUILD_STATIC_ONLY=1 \ + OBJDIR=$(dir $@)/libbpf DESTDIR=$(dir $@) \ + INCLUDEDIR= LIBDIR= UAPIDIR= \ + install + +# Build bpftool +$(BPFTOOL): | $(BPFTOOL_OUTPUT) + $(call msg,BPFTOOL,$@) + $(Q)$(MAKE) ARCH= CROSS_COMPILE= OUTPUT=$(BPFTOOL_OUTPUT)/ -C $(BPFTOOL_SRC) bootstrap + + +# Build BPF code +%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL) + $(call msg,BPF,$@) + $(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) \ + $(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) \ + -c $(filter %.c,$^) -o $(patsubst %.bpf.o,%.tmp.bpf.o,$@) + $(Q)$(BPFTOOL) gen object $@ $(patsubst %.bpf.o,%.tmp.bpf.o,$@) + + + diff --git a/src/29-sockops/README.md b/src/29-sockops/README.md index 604725b..6825bba 100644 --- a/src/29-sockops/README.md +++ b/src/29-sockops/README.md @@ -17,9 +17,8 @@ Merbridge 项目就是这样实现了用 eBPF 代替 iptables 为 Istio 进行 ### 编译 eBPF 程序 ```shell -# Compile the bpf_sockops program -clang -O2 -g -Wall -target bpf -c bpf_sockops.c -o bpf_sockops.o -clang -O2 -g -Wall -target bpf -c bpf_redir.c -o bpf_redir.o +# Compile the bpf program with libbpf +make ``` ### 加载 eBPF 程序 @@ -43,26 +42,45 @@ $ sudo bpftool prog show ### 运行 [iperf3](https://iperf.fr/) 服务器 ```shell -iperf3 -s -p 10000 +iperf3 -s -p 5001 ``` ### 运行 [iperf3](https://iperf.fr/) 客户端 ```shell -iperf3 -c 127.0.0.1 -t 10 -l 64k -p 10000 +iperf3 -c 127.0.0.1 -t 10 -l 64k -p 5001 ``` ### 收集追踪 +查看``sock_ops``追踪本地连接建立 ```console -$ ./trace.sh +$ ./trace_bpf_output.sh iperf3-9516 [001] .... 22500.634108: 0: <<< ipv4 op = 4, port 18583 --> 4135 iperf3-9516 [001] ..s1 22500.634137: 0: <<< ipv4 op = 5, port 4135 --> 18583 iperf3-9516 [001] .... 22500.634523: 0: <<< ipv4 op = 4, port 19095 --> 4135 iperf3-9516 [001] ..s1 22500.634536: 0: <<< ipv4 op = 5, port 4135 --> 19095 ``` -你应该可以看到 4 个用于套接字建立的事件。如果你没有看到任何事件,那么 eBPF 程序可能没有正确地附加上。 +当iperf3 -c建立连接后,你应该可以看到上述用于套接字建立的事件。如果你没有看到任何事件,那么 eBPF 程序可能没有正确地附加上。 + +此外,当``sk_msg``生效后,可以发现当使用tcpdump捕捉本地lo设备流量时,只能捕获三次握手和四次挥手流量,而iperf数据流量没有被捕获到。如果捕获到iperf数据流量,那么 eBPF 程序可能没有正确地附加上。 + + +```console +$ ./trace_lo_traffic.sh +# 三次握手 +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 +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 +13:24:07.181832 IP localhost.46506 > localhost.5001: Flags [.], ack 1, win 512, options [nop,nop,TS val 1982813394 ecr 1982813394], length 0 + +# 四次挥手 +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 +13:24:12.479621 IP localhost.5001 > localhost.46506: Flags [.], ack 2, win 512, options [nop,nop,TS val 1982818692 ecr 1982818688], length 0 +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 +13:24:12.481270 IP localhost.46506 > localhost.5001: Flags [.], ack 2, win 512, options [nop,nop,TS val 1982818694 ecr 1982818694], length 0 + +``` ### 卸载 eBPF 程序 diff --git a/src/29-sockops/README_en.md b/src/29-sockops/README_en.md index c8dd42a..f9af4ac 100644 --- a/src/29-sockops/README_en.md +++ b/src/29-sockops/README_en.md @@ -18,8 +18,7 @@ This example program redirects traffic from the sender's socket (outbound) to th ```shell # Compile the bpf_sockops program -clang -O2 -g -Wall -target bpf -c bpf_sockops.c -o bpf_sockops.o -clang -O2 -g -Wall -target bpf -c bpf_redir.c -o bpf_redir.o +make ``` ### Loading the eBPF Program @@ -43,26 +42,44 @@ $ sudo bpftool prog show ### Running the [iperf3](https://iperf.fr/) Server ```shell -iperf3 -s -p 10000 +iperf3 -s -p 5001 ``` ### Running the [iperf3](https://iperf.fr/) Client ```shell -iperf3 -c 127.0.0.1 -t 10 -l 64k -p 10000 +iperf3 -c 127.0.0.1 -t 10 -l 64k -p 5001 ``` ### Collecting Traces +Show connection setup tracing for localhost connection. ```console -$ ./trace.sh +$ ./trace_bpf_output.sh iperf3-9516 [001] .... 22500.634108: 0: <<< ipv4 op = 4, port 18583 --> 4135 iperf3-9516 [001] ..s1 22500.634137: 0: <<< ipv4 op = 5, port 4135 --> 18583 iperf3-9516 [001] .... 22500.634523: 0: <<< ipv4 op = 4, port 19095 --> 4135 iperf3-9516 [001] ..s1 22500.634536: 0: <<< ipv4 op = 5, port 4135 --> 19095 ``` -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. +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. + +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. + +```console +$ ./trace_lo_traffic.sh +# three-way handshake +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 +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 +13:24:07.181832 IP localhost.46506 > localhost.5001: Flags [.], ack 1, win 512, options [nop,nop,TS val 1982813394 ecr 1982813394], length 0 + +# four-way handshake traffic +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 +13:24:12.479621 IP localhost.5001 > localhost.46506: Flags [.], ack 2, win 512, options [nop,nop,TS val 1982818692 ecr 1982818688], length 0 +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 +13:24:12.481270 IP localhost.46506 > localhost.5001: Flags [.], ack 2, win 512, options [nop,nop,TS val 1982818694 ecr 1982818694], length 0 +``` + ### Unloading the eBPF Program diff --git a/src/29-sockops/bpf_contrack.bpf.c b/src/29-sockops/bpf_contrack.bpf.c new file mode 100644 index 0000000..765e914 --- /dev/null +++ b/src/29-sockops/bpf_contrack.bpf.c @@ -0,0 +1,32 @@ +#include "bpf_sockmap.h" + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; + +SEC("sockops") +int bpf_sockops_handler(struct bpf_sock_ops *skops){ + u32 family, op; + + family = skops->family; + op = skops->op; + if (op != BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB + && op != BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB) { + return BPF_OK; + } + + if(skops->remote_ip4 != LOCALHOST_IPV4 || skops->local_ip4!= LOCALHOST_IPV4) { + return BPF_OK; + } + + struct sock_key key = { + .dip = skops->remote_ip4, + .sip = skops->local_ip4, + .sport = bpf_htonl(skops->local_port), /* convert to network byte order */ + .dport = skops->remote_port, + .family = skops->family, + }; + + bpf_printk(">>> new connection: OP:%d, PORT:%d --> %d\n", op, bpf_ntohl(key.sport), bpf_ntohl(key.dport)); + + bpf_sock_hash_update(skops, &sock_ops_map, &key, BPF_NOEXIST); + return BPF_OK; +} \ No newline at end of file diff --git a/src/29-sockops/bpf_redir.c b/src/29-sockops/bpf_redir.c deleted file mode 100644 index 654587b..0000000 --- a/src/29-sockops/bpf_redir.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include - -#include "bpf_sockops.h" - -__section("sk_msg") -int bpf_redir(struct sk_msg_md *msg) -{ - __u64 flags = BPF_F_INGRESS; - struct sock_key key = {}; - - sk_msg_extract4_key(msg, &key); - // See whether the source or destination IP is local host - if (key.sip4 == 16777343 || key.dip4 == 16777343) { - // See whether the source or destination port is 10000 - if (key.sport == 4135 || key.dport == 4135) { - int len1 = (__u64)msg->data_end - (__u64)msg->data; - printk("<<< redir_proxy port %d --> %d (%d)\n", key.sport, key.dport, len1); - msg_redirect_hash(msg, &sock_ops_map, &key, flags); - } - } - - return SK_PASS; -} - -BPF_LICENSE("GPL"); -int _version __section("version") = 1; diff --git a/src/29-sockops/bpf_redirect.bpf.c b/src/29-sockops/bpf_redirect.bpf.c new file mode 100644 index 0000000..84938bd --- /dev/null +++ b/src/29-sockops/bpf_redirect.bpf.c @@ -0,0 +1,19 @@ +#include "bpf_sockmap.h" + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; + +SEC("sk_msg") +int bpf_redir(struct sk_msg_md *msg) +{ + if(msg->remote_ip4 != LOCALHOST_IPV4 || msg->local_ip4!= LOCALHOST_IPV4) + return SK_PASS; + + struct sock_key key = { + .sip = msg->remote_ip4, + .dip = msg->local_ip4, + .dport = bpf_htonl(msg->local_port), /* convert to network byte order */ + .sport = msg->remote_port, + .family = msg->family, + }; + return bpf_msg_redirect_hash(msg, &sock_ops_map, &key, BPF_F_INGRESS); +} \ No newline at end of file diff --git a/src/29-sockops/bpf_sockmap.h b/src/29-sockops/bpf_sockmap.h new file mode 100644 index 0000000..82fb9e8 --- /dev/null +++ b/src/29-sockops/bpf_sockmap.h @@ -0,0 +1,20 @@ +#include "vmlinux.h" +#include +#include + +#define LOCALHOST_IPV4 16777343 + +struct sock_key { + __u32 sip; + __u32 dip; + __u32 sport; + __u32 dport; + __u32 family; +}; + +struct { + __uint(type, BPF_MAP_TYPE_SOCKHASH); + __uint(max_entries, 65535); + __type(key, struct sock_key); + __type(value, int); +} sock_ops_map SEC(".maps"); \ No newline at end of file diff --git a/src/29-sockops/bpf_sockops.c b/src/29-sockops/bpf_sockops.c deleted file mode 100644 index b19929b..0000000 --- a/src/29-sockops/bpf_sockops.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include - -#include "bpf_sockops.h" - -static inline void bpf_sock_ops_ipv4(struct bpf_sock_ops *skops) -{ - struct sock_key key = {}; - sk_extract4_key(skops, &key); - if (key.dip4 == 16777343 || key.sip4 == 16777343 ) { - if (key.dport == 4135 || key.sport == 4135) { - int ret = sock_hash_update(skops, &sock_ops_map, &key, BPF_NOEXIST); - printk("<<< ipv4 op = %d, port %d --> %d\n", skops->op, key.sport, key.dport); - if (ret != 0) - printk("*** FAILED %d ***\n", ret); - } - } -} - -static inline void bpf_sock_ops_ipv6(struct bpf_sock_ops *skops) -{ - if (skops->remote_ip4) - bpf_sock_ops_ipv4(skops); -} - - -__section("sockops") -int bpf_sockmap(struct bpf_sock_ops *skops) -{ - __u32 family, op; - - family = skops->family; - op = skops->op; - - printk("<<< op %d, port = %d --> %d\n", op, skops->local_port, skops->remote_port); - switch (op) { - case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: - case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: - if (family == AF_INET6) - bpf_sock_ops_ipv6(skops); - else if (family == AF_INET) - bpf_sock_ops_ipv4(skops); - break; - default: - break; - } - return 0; -} - -BPF_LICENSE("GPL"); -int _version __section("version") = 1; diff --git a/src/29-sockops/bpf_sockops.h b/src/29-sockops/bpf_sockops.h deleted file mode 100644 index c625da2..0000000 --- a/src/29-sockops/bpf_sockops.h +++ /dev/null @@ -1,168 +0,0 @@ -#include -#include - -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define __bpf_ntohs(x) __builtin_bswap16(x) -# define __bpf_htons(x) __builtin_bswap16(x) -# define __bpf_constant_ntohs(x) ___constant_swab16(x) -# define __bpf_constant_htons(x) ___constant_swab16(x) -# define __bpf_ntohl(x) __builtin_bswap32(x) -# define __bpf_htonl(x) __builtin_bswap32(x) -# define __bpf_constant_ntohl(x) ___constant_swab32(x) -# define __bpf_constant_htonl(x) ___constant_swab32(x) -#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -# define __bpf_ntohs(x) (x) -# define __bpf_htons(x) (x) -# define __bpf_constant_ntohs(x) (x) -# define __bpf_constant_htons(x) (x) -# define __bpf_ntohl(x) (x) -# define __bpf_htonl(x) (x) -# define __bpf_constant_ntohl(x) (x) -# define __bpf_constant_htonl(x) (x) -#else -# error "Fix your compiler's __BYTE_ORDER__?!" -#endif - -#define bpf_htons(x) \ - (__builtin_constant_p(x) ? \ - __bpf_constant_htons(x) : __bpf_htons(x)) -#define bpf_ntohs(x) \ - (__builtin_constant_p(x) ? \ - __bpf_constant_ntohs(x) : __bpf_ntohs(x)) -#define bpf_htonl(x) \ - (__builtin_constant_p(x) ? \ - __bpf_constant_htonl(x) : __bpf_htonl(x)) -#define bpf_ntohl(x) \ - (__builtin_constant_p(x) ? \ - __bpf_constant_ntohl(x) : __bpf_ntohl(x)) - -/** Section helper macros. */ - -#ifndef __section -# define __section(NAME) \ - __attribute__((section(NAME), used)) -#endif - -#ifndef __section_tail -# define __section_tail(ID, KEY) \ - __section(__stringify(ID) "/" __stringify(KEY)) -#endif - -#ifndef __section_cls_entry -# define __section_cls_entry \ - __section("classifier") -#endif - -#ifndef __section_act_entry -# define __section_act_entry \ - __section("action") -#endif - -#ifndef __section_license -# define __section_license \ - __section("license") -#endif - -#ifndef __section_maps -# define __section_maps \ - __section("maps") -#endif - -/** Declaration helper macros. */ - -#ifndef BPF_LICENSE -# define BPF_LICENSE(NAME) \ - char ____license[] __section_license = NAME -#endif - -#ifndef BPF_FUNC -# define BPF_FUNC(NAME, ...) \ - (*NAME)(__VA_ARGS__) = (void *)BPF_FUNC_##NAME -#endif - -static int BPF_FUNC(sock_hash_update, struct bpf_sock_ops *skops, void *map, void *key, uint64_t flags); -static int BPF_FUNC(msg_redirect_hash, struct sk_msg_md *md, void *map, void *key, uint64_t flags); -static void BPF_FUNC(trace_printk, const char *fmt, int fmt_size, ...); - -#ifndef printk -# define printk(fmt, ...) \ - ({ \ - char ____fmt[] = fmt; \ - trace_printk(____fmt, sizeof(____fmt), ##__VA_ARGS__); \ - }) -#endif - - -struct bpf_map_def { - __u32 type; - __u32 key_size; - __u32 value_size; - __u32 max_entries; - __u32 map_flags; -}; - -union v6addr { - struct { - __u32 p1; - __u32 p2; - __u32 p3; - __u32 p4; - }; - __u8 addr[16]; -}; - -struct sock_key { - union { - struct { - __u32 sip4; - __u32 pad1; - __u32 pad2; - __u32 pad3; - }; - union v6addr sip6; - }; - union { - struct { - __u32 dip4; - __u32 pad4; - __u32 pad5; - __u32 pad6; - }; - union v6addr dip6; - }; - __u8 family; - __u8 pad7; - __u16 pad8; - __u32 sport; - __u32 dport; -} __attribute__((packed)); - -struct bpf_map_def __section_maps sock_ops_map = { - .type = BPF_MAP_TYPE_SOCKHASH, - .key_size = sizeof(struct sock_key), - .value_size = sizeof(int), - .max_entries = 65535, - .map_flags = 0, -}; - -static inline void sk_extract4_key(struct bpf_sock_ops *ops, - struct sock_key *key) -{ - key->dip4 = ops->remote_ip4; - key->sip4 = ops->local_ip4; - key->family = 1; - - key->sport = (bpf_htonl(ops->local_port) >> 16); - key->dport = ops->remote_port >> 16; -} - -static inline void sk_msg_extract4_key(struct sk_msg_md *msg, - struct sock_key *key) -{ - key->sip4 = msg->remote_ip4; - key->dip4 = msg->local_ip4; - key->family = 1; - - key->dport = (bpf_htonl(msg->local_port) >> 16); - key->sport = msg->remote_port >> 16; -} diff --git a/src/29-sockops/load.sh b/src/29-sockops/load.sh index df2073b..faba8f5 100755 --- a/src/29-sockops/load.sh +++ b/src/29-sockops/load.sh @@ -2,19 +2,19 @@ set -x set -e -# Mount bpf filesystem sudo mount -t bpf bpf /sys/fs/bpf/ -# Load the bpf_sockops program -sudo bpftool prog load bpf_sockops.o "/sys/fs/bpf/bpf_sockop" -sudo bpftool cgroup attach "/sys/fs/cgroup/unified/" sock_ops pinned "/sys/fs/bpf/bpf_sockop" - -MAP_ID=$(sudo bpftool prog show pinned "/sys/fs/bpf/bpf_sockop" | grep -o -E 'map_ids [0-9]+' | awk '{print $2}') -sudo bpftool map pin id $MAP_ID "/sys/fs/bpf/sock_ops_map" - -# Load the bpf_redir program -if [ -z $1 ] -then - sudo bpftool prog load bpf_redir.o "/sys/fs/bpf/bpf_redir" map name sock_ops_map pinned "/sys/fs/bpf/sock_ops_map" - sudo bpftool prog attach pinned "/sys/fs/bpf/bpf_redir" msg_verdict pinned "/sys/fs/bpf/sock_ops_map" +# check if old program already loaded +if [ -e "/sys/fs/bpf/bpf_sockops" ]; then + echo ">>> bpf_sockops already loaded, uninstalling..." + ./unload.sh + echo ">>> old program already deleted..." fi + +# load and attach sock_ops program +sudo bpftool prog load bpf_contrack.bpf.o /sys/fs/bpf/bpf_sockops type sockops pinmaps /sys/fs/bpf/ +sudo bpftool cgroup attach "/sys/fs/cgroup/" sock_ops pinned "/sys/fs/bpf/bpf_sockops" + +# load and attach sk_msg program +sudo bpftool prog load bpf_redirect.bpf.o "/sys/fs/bpf/bpf_redir" map name sock_ops_map pinned "/sys/fs/bpf/sock_ops_map" +sudo bpftool prog attach pinned /sys/fs/bpf/bpf_redir msg_verdict pinned /sys/fs/bpf/sock_ops_map diff --git a/src/29-sockops/trace.sh b/src/29-sockops/trace.sh deleted file mode 100755 index 4589b36..0000000 --- a/src/29-sockops/trace.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -sudo cat /sys/kernel/debug/tracing/trace_pipe diff --git a/src/29-sockops/trace_bpf_output.sh b/src/29-sockops/trace_bpf_output.sh new file mode 100755 index 0000000..a70f627 --- /dev/null +++ b/src/29-sockops/trace_bpf_output.sh @@ -0,0 +1,2 @@ +#!/bin/bash +sudo cat /sys/kernel/debug/tracing/trace_pipe \ No newline at end of file diff --git a/src/29-sockops/trace_lo_traffic.sh b/src/29-sockops/trace_lo_traffic.sh new file mode 100755 index 0000000..6ddeeae --- /dev/null +++ b/src/29-sockops/trace_lo_traffic.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +# 5001 is the default port for iperf server +tcpdump -i lo port 5001 \ No newline at end of file diff --git a/src/29-sockops/unload.sh b/src/29-sockops/unload.sh index 32d8659..f4c7a5a 100755 --- a/src/29-sockops/unload.sh +++ b/src/29-sockops/unload.sh @@ -1,13 +1,11 @@ #!/bin/bash set -x -# UnLoad the bpf_redir program -sudo bpftool prog detach pinned "/sys/fs/bpf/bpf_redir" msg_verdict pinned "/sys/fs/bpf/sock_ops_map" -sudo rm "/sys/fs/bpf/bpf_redir" -# UnLoad the bpf_sockops program -sudo bpftool cgroup detach "/sys/fs/cgroup/unified/" sock_ops pinned "/sys/fs/bpf/bpf_sockop" -sudo rm "/sys/fs/bpf/bpf_sockop" +# detach and clear the bpf programs +sudo bpftool cgroup detach "/sys/fs/cgroup/" sock_ops pinned "/sys/fs/bpf/bpf_sockops" && \ +bpftool prog detach pinned /sys/fs/bpf/bpf_redir msg_verdict pinned /sys/fs/bpf/sock_ops_map && \ +sudo unlink /sys/fs/bpf/bpf_sockops && \ +sudo unlink /sys/fs/bpf/sock_ops_map && \ +sudo unlink /sys/fs/bpf/bpf_redir -# Delete the map -sudo rm "/sys/fs/bpf/sock_ops_map"