From 748c473c5e8d4fea2470ebf04f5b83a849e8a3af Mon Sep 17 00:00:00 2001 From: wynyibo Date: Fri, 19 Jan 2024 12:35:56 +0800 Subject: [PATCH 1/9] add udp_tracing --- .../Network_Subsystem/udp_tracing/Makefile | 114 ++++++++++++ .../udp_tracing/udp_tracing.bpf.c | 148 +++++++++++++++ .../udp_tracing/udp_tracing.c | 173 ++++++++++++++++++ .../udp_tracing/udp_tracing.h | 18 ++ 4 files changed, 453 insertions(+) create mode 100644 eBPF_Supermarket/Network_Subsystem/udp_tracing/Makefile create mode 100644 eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.bpf.c create mode 100644 eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.c create mode 100644 eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.h diff --git a/eBPF_Supermarket/Network_Subsystem/udp_tracing/Makefile b/eBPF_Supermarket/Network_Subsystem/udp_tracing/Makefile new file mode 100644 index 000000000..723d66589 --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/udp_tracing/Makefile @@ -0,0 +1,114 @@ +# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) +OUTPUT := .output +CLANG ?= clang +LIBBPF_SRC := $(abspath ../libbpf-bootstrap/libbpf/src) +BPFTOOL_SRC := $(abspath ../libbpf-bootstrap/bpftool/src) +LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a) +BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool) +BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool + +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 := ../libbpf-bootstrap/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../../libbpf/include/uapi -I$(dir $(VMLINUX)) +CFLAGS := -g -Wall +ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) + +APPS = udp_tracing + +# 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: $(APPS) + +.PHONY: clean +clean: + $(call msg,CLEAN) + $(Q)rm -rf $(OUTPUT) $(APPS) + +$(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 +$(OUTPUT)/%.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,$@) + +# Generate BPF skeletons +$(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL) + $(call msg,GEN-SKEL,$@) + $(Q)$(BPFTOOL) gen skeleton $< > $@ + +# Build user-space code +$(patsubst %,$(OUTPUT)/%.o,$(APPS)): %.o: %.skel.h + +$(OUTPUT)/%.o: %.c $(wildcard %.h) | $(OUTPUT) + $(call msg,CC,$@) + $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@ + +# Build application binary +$(APPS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT) + $(call msg,BINARY,$@) + $(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lelf -lz -o $@ + +# delete failed targets +.DELETE_ON_ERROR: + +# keep intermediate (.skel.h, .bpf.o, etc) targets +.SECONDARY: + diff --git a/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.bpf.c b/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.bpf.c new file mode 100644 index 000000000..387f53f22 --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.bpf.c @@ -0,0 +1,148 @@ +#include "vmlinux.h" +#include +#include +#include +#include +#include "udp_tracing.h" +#define AF_INET 2 +char LICENSE[] SEC("license") = "Dual BSD/GPL"; + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 256 * 1024); +} rb SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __uint(max_entries, 10800); + __type(key, int); + __type(value, struct udp_tracing); +} udp_flow_map SEC(".maps"); + + + +/* +//存储进程id与端口号关系 +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 10800); + __type(key,int); + __type(value, struct udp_tracing); +} port_map SEC(".maps"); +//存储进程id与流量关系 +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 10800); + __type(key,int); + __type(value, int); +} port_flow_map SEC(".maps"); +*/ +struct udp_tracing{ + unsigned int dport; + unsigned int sport; + unsigned int saddr; + unsigned int daddr; + unsigned long long send; + unsigned long long recv; +}; + +const volatile int filter_sport = 0; + +#define FILTER_SPORT if(filter_sport){if (sp.port != filter_sport) { return 0; }} +//kprobe 挂载 udp_sendmsg 函数 +SEC("kprobe/udp_sendmsg") +int trace_sys_send(struct pt_regs *ctx) +{ + + unsigned int pid=bpf_get_current_pid_tgid();;//获取当前进程pid + u64 tmp =PT_REGS_PARM3_CORE(ctx);// + //struct sock *sock = (struct sock *)PT_REGS_PARM1_CORE(ctx); + struct udp_tracing *st=bpf_map_lookup_elem(&udp_flow_map,&pid);//使用bpf_map_lookup_elem函数查找udp_flow_map中以pid为键的元素 + if(st&&tmp>0)//如果找到对应的元素 + { + st->send+=tmp;//累加 + } + else{ + struct udp_tracing val = {.send = tmp, .recv = 0}; + //bpf_map_update_elem函数将以key为键、recv为值的元素插入到udp_flow_map中,进行更新 + bpf_map_update_elem(&udp_flow_map,&pid,&val,BPF_ANY); + } + return 0; + + +} + +SEC("kprobe/udp_recvmsg") +int trace_sys_recv(struct pt_regs *ctx) +{ + unsigned int pid=bpf_get_current_pid_tgid(); + + //查找pid关联的值 + struct udp_tracing *st=bpf_map_lookup_elem(&udp_flow_map,&pid); + if(!st) + { + return 0; + } + + + + struct sock *sock = (struct sock *)PT_REGS_PARM1_CORE(ctx); + st->daddr = BPF_CORE_READ(sock, __sk_common.skc_daddr); + st->saddr = BPF_CORE_READ(sock, __sk_common.skc_rcv_saddr); + st->sport = BPF_CORE_READ(sock, __sk_common.skc_num); + st->dport = BPF_CORE_READ(sock, __sk_common.skc_dport); + bpf_map_update_elem(&udp_flow_map,&pid,st,BPF_ANY); + bpf_printk("%d",st->daddr); + return 0; +} +SEC("kretprobe/udp_recvmsg") +int trace_sys_recv_ret(struct pt_regs *ctx) +{ + unsigned int total; + unsigned int pid=bpf_get_current_pid_tgid(); + + //查找pid关联的值 + struct udp_tracing *st=bpf_map_lookup_elem(&udp_flow_map,&pid); + if(!st) + { + return 0; + } + u64 tmp=PT_REGS_RC(ctx); + if(tmp>0) + { + + // if(st)//存在 + // { + st->recv+=tmp; + // } + //else{ + // struct udp_tracing val = {.send = tmp, .recv = 0}; + // //bpf_map_update_elem函数将以key为键、recv为值的元素插入到udp_flow_map中,进行更新 + // bpf_map_update_elem(&udp_flow_map,&pid,&val,BPF_ANY); + // } + // return 0; + + } + else{ + + struct udp_tracing val = {.send = tmp, .recv = 0}; + //bpf_map_update_elem函数将以key为键、recv为值的元素插入到udp_flow_map中,进行更新 + bpf_map_update_elem(&udp_flow_map,&pid,&val,BPF_ANY); + } + + struct sock *sock = (struct sock *)PT_REGS_PARM1_CORE(ctx); + struct cwnd_data *data; + data = bpf_ringbuf_reserve(&rb, sizeof(*data), 0); + if (!data) + return 0; + data->pid = pid; + bpf_get_current_comm(&(data->comm),sizeof(data->comm)); + data->saddr=st->saddr; + data->daddr=st->daddr; + data->sport=st->sport; + data->dport= st->dport; + data->send=st->send; + data->recv=st->recv; + data->total=st->send+st->recv; + bpf_ringbuf_submit(data, 0); + return 0; +} \ No newline at end of file diff --git a/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.c b/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.c new file mode 100644 index 000000000..c610d7c78 --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.c @@ -0,0 +1,173 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "udp_tracing.h" +#include "udp_tracing.skel.h" + +static volatile bool exiting = false; + +int count = 0; +int count_i = 0; +bool verbose = false; + +int sport,dport,sampling,local; + +const char argp_program_doc[] = "Trace time delay in network subsystem \n"; + +static const struct argp_option opts[] = { + { "verbose", 'v', NULL, 0, "Verbose debug output" }, + { "sport", 's', "SPORT", 0, "trace this source port only" }, + { "dport", 'd', "DPORT", 0, "trace this destination port only" }, + { "count", 'c', "COUNT", 0, "count of outputs"}, + { "local", 'l', "LOCAL", 0, "show local connections"}, + + {}, +}; + +static error_t parse_arg(int key, char *arg, struct argp_state *state) +{ + char *end; + switch(key){ + case 'v': + verbose = true; + break; + case 'd': + dport = strtoul(arg,&end,10); + break; + case 's': + sport = strtoul(arg,&end,10); + break; + case 'c': + count = strtoul(arg,&end,10); + break; + case 'l': + local = strtoul(arg,&end,10); + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static const struct argp argp = { + .options = opts, + .parser = parse_arg, + .doc = argp_program_doc, +}; + +static void sig_handler(int sig) +{ + exiting = true; +} + + +static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) +{ + if (level == LIBBPF_DEBUG && !verbose) + return 0; + return vfprintf(stderr, format, args); +} + +static int handle_event(void *ctx, void *data, size_t data_sz) +{ + const struct cwnd_data *d = data; + char d_str[INET_ADDRSTRLEN]; + char s_str[INET_ADDRSTRLEN]; + int pid=d->pid; + int send=d->send; + int recv=d->recv; + unsigned int saddr=d->saddr; + unsigned int daddr=d->daddr; + unsigned int sport=d->sport; + unsigned int dport=d->dport; + unsigned int total=d->total; + if("") + printf("%-10d %-15s %-10d %-10d %-22s %-22s %-10d %-10d %-22d\n",pid,d->comm,send,recv,inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)),inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)),sport,dport,total); + return 0; +} + +int main(int argc, char **argv) +{ + struct ring_buffer *rb = NULL; + struct udp_tracing_bpf *skel; + int err = 0; + + /* Parse command line arguments */ + err = argp_parse(&argp, argc, argv, 0, NULL, NULL); + if (err) + return err; + + libbpf_set_strict_mode(LIBBPF_STRICT_ALL); + /* Set up libbpf errors and debug info callback */ + libbpf_set_print(libbpf_print_fn); + + /* Cleaner handling of Ctrl-C */ + signal(SIGINT, sig_handler); + signal(SIGTERM, sig_handler); + + /* Load and verify BPF application */ + skel = udp_tracing_bpf__open(); + if (!skel) { + fprintf(stderr, "Failed to open and load BPF skeleton\n"); + return 1; + } + + if(sport){ + printf("filter open,sport:%d \n",sport); + skel->rodata->filter_sport = sport; + } + + + /* Load & verify BPF programs */ + err = udp_tracing_bpf__load(skel); + if (err) { + fprintf(stderr, "Failed to load and verify BPF skeleton\n"); + goto cleanup; + } + /* Attach tracepoints */ + err =udp_tracing_bpf__attach(skel); + if (err) { + fprintf(stderr, "Failed to attach BPF skeleton\n"); + goto cleanup; + } + /* Set up ring buffer polling */ + rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, NULL, NULL); + if (!rb) { + err = -1; + fprintf(stderr, "Failed to create ring buffer\n"); + goto cleanup; + } + + /* Process events */ + printf("%-10s %-15s %-10s %-10s %-22s %-22s %-10s %-10s %-22s\n" , + "pid","comm","send","recv","saddr","daddr" ,"sport","sport","total"); + //printf("%-22s %-22s\n","pid" ,"sum" ); + while (!exiting) { + err = ring_buffer__poll(rb, 100 /* timeout, ms */); + /* Ctrl-C will cause -EINTR */ + if (err == -EINTR) { + err = 0; + break; + } + if (err < 0) { + printf("Error polling perf buffer: %d\n", err); + break; + } + if(count != 0 && count_i>=count) + break; + } + +cleanup: + /* Clean up */ + ring_buffer__free(rb); + udp_tracing_bpf__destroy(skel); + + return err < 0 ? -err : 0; +} \ No newline at end of file diff --git a/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.h b/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.h new file mode 100644 index 000000000..f4e339abf --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.h @@ -0,0 +1,18 @@ +#ifndef __UDP_TRACING_H +#define __UDP_TRACING_H + +struct cwnd_data{ + int pid; + unsigned long long send; + unsigned long long recv; + unsigned int saddr; + unsigned int daddr; + unsigned int sport; + unsigned int dport; + unsigned int total; + char comm[20]; + +}; + +#define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0])) +#endif \ No newline at end of file From f3a90ed678e58f10c418c2c8be712dd9c2bf2d42 Mon Sep 17 00:00:00 2001 From: wynyibo <147615158+wynyibo@users.noreply.github.com> Date: Fri, 19 Jan 2024 13:05:25 +0800 Subject: [PATCH 2/9] udp_tracing.bpf.c --- .../udp_tracing/udp_tracing.bpf.c | 51 +++---------------- 1 file changed, 6 insertions(+), 45 deletions(-) diff --git a/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.bpf.c b/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.bpf.c index 387f53f22..5f15efd2c 100644 --- a/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.bpf.c +++ b/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.bpf.c @@ -18,24 +18,6 @@ struct { __type(value, struct udp_tracing); } udp_flow_map SEC(".maps"); - - -/* -//存储进程id与端口号关系 -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 10800); - __type(key,int); - __type(value, struct udp_tracing); -} port_map SEC(".maps"); -//存储进程id与流量关系 -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 10800); - __type(key,int); - __type(value, int); -} port_flow_map SEC(".maps"); -*/ struct udp_tracing{ unsigned int dport; unsigned int sport; @@ -52,7 +34,6 @@ const volatile int filter_sport = 0; SEC("kprobe/udp_sendmsg") int trace_sys_send(struct pt_regs *ctx) { - unsigned int pid=bpf_get_current_pid_tgid();;//获取当前进程pid u64 tmp =PT_REGS_PARM3_CORE(ctx);// //struct sock *sock = (struct sock *)PT_REGS_PARM1_CORE(ctx); @@ -67,24 +48,18 @@ int trace_sys_send(struct pt_regs *ctx) bpf_map_update_elem(&udp_flow_map,&pid,&val,BPF_ANY); } return 0; - - } SEC("kprobe/udp_recvmsg") int trace_sys_recv(struct pt_regs *ctx) { unsigned int pid=bpf_get_current_pid_tgid(); - //查找pid关联的值 struct udp_tracing *st=bpf_map_lookup_elem(&udp_flow_map,&pid); if(!st) { return 0; - } - - - + } struct sock *sock = (struct sock *)PT_REGS_PARM1_CORE(ctx); st->daddr = BPF_CORE_READ(sock, __sk_common.skc_daddr); st->saddr = BPF_CORE_READ(sock, __sk_common.skc_rcv_saddr); @@ -98,8 +73,7 @@ SEC("kretprobe/udp_recvmsg") int trace_sys_recv_ret(struct pt_regs *ctx) { unsigned int total; - unsigned int pid=bpf_get_current_pid_tgid(); - + unsigned int pid=bpf_get_current_pid_tgid(); //查找pid关联的值 struct udp_tracing *st=bpf_map_lookup_elem(&udp_flow_map,&pid); if(!st) @@ -108,27 +82,14 @@ int trace_sys_recv_ret(struct pt_regs *ctx) } u64 tmp=PT_REGS_RC(ctx); if(tmp>0) - { - - // if(st)//存在 - // { - st->recv+=tmp; - // } - //else{ - // struct udp_tracing val = {.send = tmp, .recv = 0}; - // //bpf_map_update_elem函数将以key为键、recv为值的元素插入到udp_flow_map中,进行更新 - // bpf_map_update_elem(&udp_flow_map,&pid,&val,BPF_ANY); - // } - // return 0; - + { + st->recv+=tmp; } - else{ - + else{ struct udp_tracing val = {.send = tmp, .recv = 0}; //bpf_map_update_elem函数将以key为键、recv为值的元素插入到udp_flow_map中,进行更新 bpf_map_update_elem(&udp_flow_map,&pid,&val,BPF_ANY); } - struct sock *sock = (struct sock *)PT_REGS_PARM1_CORE(ctx); struct cwnd_data *data; data = bpf_ringbuf_reserve(&rb, sizeof(*data), 0); @@ -145,4 +106,4 @@ int trace_sys_recv_ret(struct pt_regs *ctx) data->total=st->send+st->recv; bpf_ringbuf_submit(data, 0); return 0; -} \ No newline at end of file +} From 8befee4eb1893e463da1a2696e899fb67951f543 Mon Sep 17 00:00:00 2001 From: wynyibo <147615158+wynyibo@users.noreply.github.com> Date: Fri, 19 Jan 2024 13:07:44 +0800 Subject: [PATCH 3/9] udp_tracing.c --- .../udp_tracing/udp_tracing.c | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.c b/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.c index c610d7c78..884ab40f2 100644 --- a/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.c +++ b/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.c @@ -24,7 +24,7 @@ const char argp_program_doc[] = "Trace time delay in network subsystem \n"; static const struct argp_option opts[] = { { "verbose", 'v', NULL, 0, "Verbose debug output" }, { "sport", 's', "SPORT", 0, "trace this source port only" }, - { "dport", 'd', "DPORT", 0, "trace this destination port only" }, + { "dport", 'd', "DPORT", 0, "trace this destination port only" }, { "count", 'c', "COUNT", 0, "count of outputs"}, { "local", 'l', "LOCAL", 0, "show local connections"}, @@ -44,14 +44,14 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) case 's': sport = strtoul(arg,&end,10); break; - case 'c': - count = strtoul(arg,&end,10); - break; - case 'l': - local = strtoul(arg,&end,10); - break; + case 'c': + count = strtoul(arg,&end,10); + break; + case 'l': + local = strtoul(arg,&end,10); + break; default: - return ARGP_ERR_UNKNOWN; + return ARGP_ERR_UNKNOWN; } return 0; } @@ -78,17 +78,16 @@ static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va static int handle_event(void *ctx, void *data, size_t data_sz) { const struct cwnd_data *d = data; - char d_str[INET_ADDRSTRLEN]; - char s_str[INET_ADDRSTRLEN]; + char d_str[INET_ADDRSTRLEN]; + char s_str[INET_ADDRSTRLEN]; int pid=d->pid; - int send=d->send; - int recv=d->recv; + int send=d->send; + int recv=d->recv; unsigned int saddr=d->saddr; unsigned int daddr=d->daddr; unsigned int sport=d->sport; - unsigned int dport=d->dport; - unsigned int total=d->total; - if("") + unsigned int dport=d->dport; + unsigned int total=d->total; printf("%-10d %-15s %-10d %-10d %-22s %-22s %-10d %-10d %-22d\n",pid,d->comm,send,recv,inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)),inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)),sport,dport,total); return 0; } @@ -170,4 +169,4 @@ int main(int argc, char **argv) udp_tracing_bpf__destroy(skel); return err < 0 ? -err : 0; -} \ No newline at end of file +} From 74088cb6d7c13f1c9a0c63158660afeeab515117 Mon Sep 17 00:00:00 2001 From: wynyibo Date: Thu, 25 Jan 2024 18:41:17 +0800 Subject: [PATCH 4/9] add udp_traffic argument --- .../net_watcher/netwatcher.bpf.c | 671 +++++++++++------- .../net_watcher/netwatcher.c | 144 ++-- .../net_watcher/netwatcher.h | 24 +- 3 files changed, 513 insertions(+), 326 deletions(-) diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c index 204cf8a3e..b6b30f1f3 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c @@ -25,52 +25,60 @@ #include #include -struct ktime_info { // us time stamp info发送数据包 - unsigned long long qdisc_time; // tx包离开mac层时间戳 - unsigned long long mac_time; // tx、rx包到达mac层时间戳 - unsigned long long ip_time; // tx、rx包到达ip层时间戳 - //unsigned long long tcp_time; // tx、rx包到达tcp层时间戳 - unsigned long long tran_time; // tx、rx包到达传输层时间戳 +struct ktime_info { // us time stamp info发送数据包 + unsigned long long qdisc_time; // tx包离开mac层时间戳 + unsigned long long mac_time; // tx、rx包到达mac层时间戳 + unsigned long long ip_time; // tx、rx包到达ip层时间戳 + // unsigned long long tcp_time; // tx、rx包到达tcp层时间戳 + unsigned long long tran_time; // tx、rx包到达传输层时间戳 unsigned long long app_time; // rx包离开tcp层时间戳 void *sk; // 此包所属 socket套接字 unsigned char data[MAX_HTTP_HEADER]; // 用户层数据 }; struct packet_tuple { - unsigned __int128 saddr_v6; //ipv6 源地址 - unsigned __int128 daddr_v6; //ipv6 目的地址 - unsigned int saddr; //源地址 - unsigned int daddr; //目的地址 - unsigned short sport; //源端口号 - unsigned short dport; //目的端口号 - unsigned int seq; //seq报文序号 - unsigned int ack; //ack确认号 - unsigned int tran_flag; //1:tcp 2:udp - + unsigned __int128 saddr_v6; // ipv6 源地址 + unsigned __int128 daddr_v6; // ipv6 目的地址 + unsigned int saddr; // 源地址 + unsigned int daddr; // 目的地址 + unsigned short sport; // 源端口号 + unsigned short dport; // 目的端口号 + unsigned int seq; // seq报文序号 + unsigned int ack; // ack确认号 + unsigned int tran_flag; // 1:tcp 2:udp +}; +struct udp_tracing { + unsigned int dport; + unsigned int sport; + unsigned int saddr; + unsigned int daddr; + unsigned long long send; + unsigned long long recv; }; -//操作BPF映射的一个辅助函数 -static __always_inline void *//__always_inline强制内联 +// 操作BPF映射的一个辅助函数 +static __always_inline void * //__always_inline强制内联 bpf_map_lookup_or_try_init(void *map, const void *key, const void *init) { void *val; long err; - val = bpf_map_lookup_elem(map, key);//在BPF映射中查找具有给定键的条目 + val = bpf_map_lookup_elem(map, key); // 在BPF映射中查找具有给定键的条目 if (val) return val; - //此时没有对应key的value - err = bpf_map_update_elem(map, key, init, BPF_NOEXIST);//向BPF映射中插入或更新一个条目 - if (err && err != -EEXIST)//插入失败 + // 此时没有对应key的value + err = bpf_map_update_elem(map, key, init, + BPF_NOEXIST); // 向BPF映射中插入或更新一个条目 + if (err && err != -EEXIST) // 插入失败 return 0; - return bpf_map_lookup_elem(map, key);//返回对应value值 + return bpf_map_lookup_elem(map, key); // 返回对应value值 } char LICENSE[] SEC("license") = "Dual BSD/GPL"; #define MAX_CONN 1000 -//存储每个packet_tuple包所对应的ktime_info时间戳 +// 存储每个packet_tuple包所对应的ktime_info时间戳 struct { __uint(type, BPF_MAP_TYPE_LRU_HASH); __uint(max_entries, MAX_CONN *MAX_PACKET); @@ -78,13 +86,17 @@ struct { __type(value, struct ktime_info); } timestamps SEC(".maps"); -//包相关信息通过此buffer提供给userspace +// 包相关信息通过此buffer提供给userspace struct { __uint(type, BPF_MAP_TYPE_RINGBUF); __uint(max_entries, 256 * 1024); } rb SEC(".maps"); -//存储每个tcp连接所对应的conn_t +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 256 * 1024); +} udp_rb SEC(".maps"); +// 存储每个tcp连接所对应的conn_t struct { __uint(type, BPF_MAP_TYPE_LRU_HASH); __uint(max_entries, MAX_CONN); @@ -92,29 +104,37 @@ struct { __type(value, struct conn_t); } conns_info SEC(".maps"); -//根据ptid存储sock指针,从而在上下文无sock的内核探测点获得sock +// 根据ptid存储sock指针,从而在上下文无sock的内核探测点获得sock struct { __uint(type, BPF_MAP_TYPE_LRU_HASH); __uint(max_entries, MAX_CONN); __type(key, u64); __type(value, struct sock *); } sock_stores SEC(".maps"); +// udp流量 +struct { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __uint(max_entries, 10800); + __type(key, int); + __type(value, struct udp_tracing); +} udp_flow_map SEC(".maps"); const volatile int filter_dport = 0; const volatile int filter_sport = 0; const volatile int all_conn = 0, err_packet = 0, extra_conn_info = 0, - layer_time = 0, http_info = 0, retrans_info = 0; + layer_time = 0, http_info = 0, retrans_info = 0, + udp_info = 0, udp_traffic = 0; /* help macro */ -//连接的目标端口是否匹配于filter_dport的值 +// 连接的目标端口是否匹配于filter_dport的值 #define FILTER_DPORT \ if (filter_dport) { \ if (conn.dport != filter_dport) { \ return 0; \ } \ } -//连接的源端口是否匹配于filter_sport的值 +// 连接的源端口是否匹配于filter_sport的值 #define FILTER_SPORT \ if (filter_sport) { \ if (conn.sport != filter_sport) { \ @@ -122,24 +142,23 @@ const volatile int all_conn = 0, err_packet = 0, extra_conn_info = 0, } \ } -//初始化conn_t结构 +// 初始化conn_t结构 /* #define CONN_INIT - struct conn_t conn = {0}; //声明一各conn_t结构,并初始化为0 - conn.pid = ptid >> 32; //将ptid的高32位赋给pid - conn.ptid = ptid; //初始化ptid - u16 protocol = BPF_CORE_READ(sk, sk_protocol); //读取协议字段 - if (protocol != IPPROTO_TCP) //检查其协议字段是否为IPPROTO_TCP - return 0; - bpf_get_current_comm(&conn.comm, sizeof(conn.comm)); //获取当前进程名字 - conn.sock = sk; //套接字指针sk - u16 family = BPF_CORE_READ(sk, __sk_common.skc_family); //地址族字段 - __be16 dport = BPF_CORE_READ(sk, __sk_common.skc_dport); //目标端口字段 - u16 sport = BPF_CORE_READ(sk, __sk_common.skc_num); //源端口字段 - conn.family = family; - conn.sport = sport; - conn.dport = __bpf_ntohs(dport); //字节序转换 - conn.init_timestamp = bpf_ktime_get_ns() / 1000; //将当前时间戳(s) + struct conn_t conn = {0}; //声明一各conn_t结构,并初始化为0 conn.pid = ptid +>> 32; //将ptid的高32位赋给pid conn.ptid = ptid; +//初始化ptid u16 protocol = BPF_CORE_READ(sk, sk_protocol); //读取协议字段 if +(protocol != IPPROTO_TCP) //检查其协议字段是否为IPPROTO_TCP + return 0; + bpf_get_current_comm(&conn.comm, sizeof(conn.comm)); //获取当前进程名字 + conn.sock = sk; //套接字指针sk + u16 family = BPF_CORE_READ(sk, __sk_common.skc_family); //地址族字段 + __be16 dport = BPF_CORE_READ(sk, __sk_common.skc_dport); //目标端口字段 + u16 sport = BPF_CORE_READ(sk, __sk_common.skc_num); //源端口字段 + conn.family = family; + conn.sport = sport; + conn.dport = __bpf_ntohs(dport); //字节序转换 + conn.init_timestamp = bpf_ktime_get_ns() / 1000; //将当前时间戳(s) */ #define CONN_INIT \ struct conn_t conn = {0}; \ @@ -157,22 +176,19 @@ const volatile int all_conn = 0, err_packet = 0, extra_conn_info = 0, conn.sport = sport; \ conn.dport = __bpf_ntohs(dport); \ conn.init_timestamp = bpf_ktime_get_ns() / 1000; - /* 初始化conn_t地址相关信息 -#define CONN_ADD_ADDRESS - if (family == AF_INET) { //Internet IP Protocol - conn.saddr = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr);//获取源地址 - conn.daddr = BPF_CORE_READ(sk, __sk_common.skc_daddr); //获取目的地址 - } else if (family == AF_INET6) { //IP version 6 - bpf_probe_read_kernel( //从sk中读取IPv6连接的源地址 - &conn.saddr_v6, //存放位置 - sizeof(sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32), //读取大小 - &sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32); //读取位置 - bpf_probe_read_kernel( //从sk中读取IPv6连接的目的地址 - &conn.daddr_v6, - sizeof(sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32), - &sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32); +#define CONN_ADD_ADDRESS + if (family == AF_INET) { //Internet IP +Protocol conn.saddr = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr);//获取源地址 + conn.daddr = BPF_CORE_READ(sk, __sk_common.skc_daddr); //获取目的地址 + } else if (family == AF_INET6) { //IP version 6 + bpf_probe_read_kernel( //从sk中读取IPv6连接的源地址 &conn.saddr_v6, +//存放位置 sizeof(sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32), //读取大小 + &sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32); //读取位置 + bpf_probe_read_kernel( //从sk中读取IPv6连接的目的地址 &conn.daddr_v6, + sizeof(sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32), + &sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32); } */ #define CONN_ADD_ADDRESS \ @@ -191,21 +207,23 @@ const volatile int all_conn = 0, err_packet = 0, extra_conn_info = 0, } /* 初始化conn其余额外信息 -#define CONN_ADD_EXTRA_INFO //添加额外信息 - if (extra_conn_info) { - struct tcp_sock *tp = (struct tcp_sock *)sk; //新建tcp_sock结构体 - conn->srtt = BPF_CORE_READ(tp, srtt_us); //平滑往返时间 - conn->duration = bpf_ktime_get_ns() / 1000 - conn->init_timestamp; // 已连接建立时长 - conn->bytes_acked = BPF_CORE_READ(tp, bytes_acked); //已确认的字节数 - conn->bytes_received = BPF_CORE_READ(tp, bytes_received);//已接收的字节数 - conn->snd_cwnd = BPF_CORE_READ(tp, snd_cwnd); //拥塞窗口大小 - conn->rcv_wnd = BPF_CORE_READ(tp, rcv_wnd); //接收窗口大小 - conn->snd_ssthresh = BPF_CORE_READ(tp, snd_ssthresh); //慢启动阈值 - conn->total_retrans = BPF_CORE_READ(tp, total_retrans); //重传包数 - conn->sndbuf = BPF_CORE_READ(sk, sk_sndbuf); //发送缓冲区大小(byte) - conn->sk_wmem_queued = BPF_CORE_READ(sk, sk_wmem_queued);//已使用的发送缓冲区 - conn->tcp_backlog = BPF_CORE_READ(sk, sk_ack_backlog); //backlog传入连接请求的当前最大排队队列大小 - conn->max_tcp_backlog = BPF_CORE_READ(sk, sk_max_ack_backlog); //max_backlog传入连接请求的最大挂起队列大小 +#define CONN_ADD_EXTRA_INFO //添加额外信息 + if (extra_conn_info) { + struct tcp_sock *tp = (struct tcp_sock *)sk; //新建tcp_sock结构体 + conn->srtt = BPF_CORE_READ(tp, srtt_us); //平滑往返时间 + conn->duration = bpf_ktime_get_ns() / 1000 - conn->init_timestamp; // +已连接建立时长 conn->bytes_acked = BPF_CORE_READ(tp, bytes_acked); +//已确认的字节数 conn->bytes_received = BPF_CORE_READ(tp, +bytes_received);//已接收的字节数 conn->snd_cwnd = BPF_CORE_READ(tp, snd_cwnd); +//拥塞窗口大小 conn->rcv_wnd = BPF_CORE_READ(tp, rcv_wnd); //接收窗口大小 + conn->snd_ssthresh = BPF_CORE_READ(tp, snd_ssthresh); //慢启动阈值 + conn->total_retrans = BPF_CORE_READ(tp, total_retrans); //重传包数 + conn->sndbuf = BPF_CORE_READ(sk, sk_sndbuf); //发送缓冲区大小(byte) + conn->sk_wmem_queued = BPF_CORE_READ(sk, +sk_wmem_queued);//已使用的发送缓冲区 conn->tcp_backlog = BPF_CORE_READ(sk, +sk_ack_backlog); //backlog传入连接请求的当前最大排队队列大小 + conn->max_tcp_backlog = BPF_CORE_READ(sk, sk_max_ack_backlog); +//max_backlog传入连接请求的最大挂起队列大小 } */ @@ -226,19 +244,18 @@ const volatile int all_conn = 0, err_packet = 0, extra_conn_info = 0, conn->max_tcp_backlog = BPF_CORE_READ(sk, sk_max_ack_backlog); \ } -#define CONN_INFO_TRANSFER tinfo->sk = conn->sock; //将conn->sock赋给tinfo->sk +#define CONN_INFO_TRANSFER tinfo->sk = conn->sock; // 将conn->sock赋给tinfo->sk /* 初始化pack_t结构 -#define PACKET_INIT_WITH_COMMON_INFO - struct pack_t *packet; //创建pack_t指针 - packet = bpf_ringbuf_reserve(&rb, sizeof(*packet), 0); //为pack_t结构体分配内存空间 - if (!packet) { //分配失败 - return 0; - } - packet->err = 0; //err - packet->sock = sk; //socket 指针 - packet->ack = pkt_tuple.ack; //确认号 +#define PACKET_INIT_WITH_COMMON_INFO + struct pack_t *packet; //创建pack_t指针 + packet = bpf_ringbuf_reserve(&rb, sizeof(*packet), 0); +//为pack_t结构体分配内存空间 if (!packet) { //分配失败 return 0; + } + packet->err = 0; //err + packet->sock = sk; //socket 指针 + packet->ack = pkt_tuple.ack; //确认号 packet->seq = pkt_tuple.seq; //序号 */ #define PACKET_INIT_WITH_COMMON_INFO \ @@ -255,32 +272,34 @@ const volatile int all_conn = 0, err_packet = 0, extra_conn_info = 0, /* help macro end */ /* help functions */ -//将struct sock类型的指针转化为struct tcp_sock类型的指针 +// 将struct sock类型的指针转化为struct tcp_sock类型的指针 static struct tcp_sock *tcp_sk(const struct sock *sk) { return (struct tcp_sock *)sk; } -//将struct sk_buff类型的指针转化为struct udphdr类型的指针 +// 将struct sk_buff类型的指针转化为struct udphdr类型的指针 static struct udphdr *skb_to_udphdr(const struct sk_buff *skb) { - return (struct udphdr *)((BPF_CORE_READ(skb, head) + //报文头部偏移 - BPF_CORE_READ(skb, transport_header))); //传输层部分偏移 + return (struct udphdr *)(( + BPF_CORE_READ(skb, head) + // 报文头部偏移 + BPF_CORE_READ(skb, transport_header))); // 传输层部分偏移 } -//将struct sk_buff类型的指针转化为struct tcphdr类型的指针 +// 将struct sk_buff类型的指针转化为struct tcphdr类型的指针 static struct tcphdr *skb_to_tcphdr(const struct sk_buff *skb) { - return (struct tcphdr *)((BPF_CORE_READ(skb, head) + //报文头部偏移 - BPF_CORE_READ(skb, transport_header))); //传输层部分偏移 + return (struct tcphdr *)(( + BPF_CORE_READ(skb, head) + // 报文头部偏移 + BPF_CORE_READ(skb, transport_header))); // 传输层部分偏移 } -//将struct sk_buff类型的指针转化为struct iphdr类型的指针 +// 将struct sk_buff类型的指针转化为struct iphdr类型的指针 static inline struct iphdr *skb_to_iphdr(const struct sk_buff *skb) { return (struct iphdr *)(BPF_CORE_READ(skb, head) + BPF_CORE_READ(skb, network_header)); } -//将struct sk_buff类型的指针转化为struct ipv6hdr类型的指针 +// 将struct sk_buff类型的指针转化为struct ipv6hdr类型的指针 static inline struct ipv6hdr *skb_to_ipv6hdr(const struct sk_buff *skb) { return (struct ipv6hdr *)(BPF_CORE_READ(skb, head) + BPF_CORE_READ(skb, network_header)); } -//初始化packet_tuple结构指针pkt_tuple +// 初始化packet_tuple结构指针pkt_tuple static void get_pkt_tuple(struct packet_tuple *pkt_tuple, struct iphdr *ip, struct tcphdr *tcp) { pkt_tuple->saddr = BPF_CORE_READ(ip, saddr); @@ -295,12 +314,12 @@ static void get_pkt_tuple(struct packet_tuple *pkt_tuple, struct iphdr *ip, pkt_tuple->seq = __bpf_ntohl(seq); //__bpf_ntohls根据字节序来转化为真实值(32位) pkt_tuple->ack = __bpf_ntohl(ack); - - pkt_tuple->tran_flag=TCP; //tcp包 + + pkt_tuple->tran_flag = TCP; // tcp包 } -//初始化packet_tuple结构指针pkt_tuple +// 初始化packet_tuple结构指针pkt_tuple static void get_udp_pkt_tuple(struct packet_tuple *pkt_tuple, struct iphdr *ip, - struct udphdr *udp) { + struct udphdr *udp) { pkt_tuple->saddr = BPF_CORE_READ(ip, saddr); pkt_tuple->daddr = BPF_CORE_READ(ip, daddr); u16 sport = BPF_CORE_READ(udp, source); @@ -310,9 +329,9 @@ static void get_udp_pkt_tuple(struct packet_tuple *pkt_tuple, struct iphdr *ip, pkt_tuple->dport = __bpf_ntohs(dport); pkt_tuple->seq = 0; pkt_tuple->ack = 0; - pkt_tuple->tran_flag = UDP; //udp包 + pkt_tuple->tran_flag = UDP; // udp包 } -//初始化packet_tuple结构指针pkt_tuple + static void get_pkt_tuple_v6(struct packet_tuple *pkt_tuple, struct ipv6hdr *ip6h, struct tcphdr *tcp) { bpf_probe_read_kernel(&pkt_tuple->saddr_v6, sizeof(pkt_tuple->saddr_v6), @@ -328,8 +347,7 @@ static void get_pkt_tuple_v6(struct packet_tuple *pkt_tuple, pkt_tuple->seq = __bpf_ntohl(seq); pkt_tuple->ack = __bpf_ntohl(ack); - pkt_tuple->tran_flag=TCP; //tcp包 - + pkt_tuple->tran_flag = 1; // tcp包 } /* help functions end */ @@ -337,26 +355,27 @@ static void get_pkt_tuple_v6(struct packet_tuple *pkt_tuple, accecpt an TCP connection */ SEC("kretprobe/inet_csk_accept") -int BPF_KRETPROBE(inet_csk_accept_exit,//接受tcp连接 - struct sock *sk) { // this func return a newsk +int BPF_KRETPROBE(inet_csk_accept_exit, // 接受tcp连接 + struct sock *sk) { // this func return a newsk // bpf_printk("inet_accept_ret\n"); - if (sk == NULL) { //newsk is null + if (sk == NULL) { // newsk is null // bpf_printk("inet_accept_ret err: newsk is null\n"); return 0; } - u64 ptid = bpf_get_current_pid_tgid();//获取当前进程pid + u64 ptid = bpf_get_current_pid_tgid(); // 获取当前进程pid - CONN_INIT //初始化conn_t结构中基本信息 - conn.is_server = 1; + CONN_INIT // 初始化conn_t结构中基本信息 + conn.is_server = 1; - FILTER_DPORT//过滤目标端口 - FILTER_SPORT//过滤源端口 + FILTER_DPORT // 过滤目标端口 - CONN_ADD_ADDRESS//conn_t结构中增加地址信息 + FILTER_SPORT // 过滤源端口 - //更新/插入conns_info中的键值对 - int err = bpf_map_update_elem(&conns_info, &sk, &conn, BPF_ANY); - if (err) {//更新错误 + CONN_ADD_ADDRESS // conn_t结构中增加地址信息 + + // 更新/插入conns_info中的键值对 + int err = bpf_map_update_elem(&conns_info, &sk, &conn, BPF_ANY); + if (err) { // 更新错误 // bpf_printk("inet_accept update err.\n"); return 0; } @@ -370,12 +389,12 @@ int BPF_KRETPROBE(inet_csk_accept_exit,//接受tcp连接 /** connect an TCP connection */ -SEC("kprobe/tcp_v4_connect")//进入tcp_v4_connect +SEC("kprobe/tcp_v4_connect") // 进入tcp_v4_connect int BPF_KPROBE(tcp_v4_connect, const struct sock *sk) { // bpf_printk("tcp_v4_connect\n"); - u64 ptid = bpf_get_current_pid_tgid(); //获取当前pid + u64 ptid = bpf_get_current_pid_tgid(); // 获取当前pid int err = bpf_map_update_elem(&sock_stores, &ptid, &sk, BPF_ANY); - //更新/插入sock_stores中的键值对 + // 更新/插入sock_stores中的键值对 if (err) { // bpf_printk("tcp_v4_connect update sock_stores err.\n"); return 0; @@ -383,80 +402,75 @@ int BPF_KPROBE(tcp_v4_connect, const struct sock *sk) { return 0; } -SEC("kretprobe/tcp_v4_connect")//退出tcp_v4_connect +SEC("kretprobe/tcp_v4_connect") // 退出tcp_v4_connect int BPF_KRETPROBE(tcp_v4_connect_exit, int ret) { - u64 ptid = bpf_get_current_pid_tgid();//获取当前pid + u64 ptid = bpf_get_current_pid_tgid(); // 获取当前pid struct sock **skp = bpf_map_lookup_elem(&sock_stores, &ptid); - //获得sock_stores中ptid对应的*sk 用skp指向 + // 获得sock_stores中ptid对应的*sk 用skp指向 if (skp == NULL) { return 0; } // bpf_printk("tcp_v4_connect_exit\n"); - if (ret != 0) {//连接失败 + if (ret != 0) { // 连接失败 // bpf_printk("tcp_v4_connect_exit but ret %d\n", ret); - bpf_map_delete_elem(&sock_stores, &ptid);//删除对应键值对 + bpf_map_delete_elem(&sock_stores, &ptid); // 删除对应键值对 return 0; } struct sock *sk = *skp; - CONN_INIT //初始化conn_t结构中基本信息 - conn.is_server = 0; //主动连接 + CONN_INIT // 初始化conn_t结构中基本信息 + conn.is_server = 0; // 主动连接 + + FILTER_DPORT // 过滤目标端口 - FILTER_DPORT //过滤目标端口 - FILTER_SPORT //过滤源端口 + FILTER_SPORT // 过滤源端口 - CONN_ADD_ADDRESS //conn_t结构中增加地址信息 + CONN_ADD_ADDRESS // conn_t结构中增加地址信息 - long err = bpf_map_update_elem(&conns_info, &sk, &conn, BPF_ANY); - //更新conns_info中sk对应的conn + long err = bpf_map_update_elem(&conns_info, &sk, &conn, BPF_ANY); + // 更新conns_info中sk对应的conn if (err) { - // bpf_printk("tcp_v4_connect_exit update err.\n"); return 0; } - // bpf_printk("tcp_v4_connect_exit update sk: %p\n", sk); return 0; } -SEC("kprobe/tcp_v6_connect")//进入tcp_v6_connect函数 +SEC("kprobe/tcp_v6_connect") // 进入tcp_v6_connect函数 int BPF_KPROBE(tcp_v6_connect, const struct sock *sk) { - // bpf_printk("tcp_v6_connect\n"); - u64 pid = bpf_get_current_pid_tgid();//获取pid + u64 pid = bpf_get_current_pid_tgid(); // 获取pid int err = bpf_map_update_elem(&sock_stores, &pid, &sk, BPF_ANY); - //更新sock_stores中对应pid对应的sk + // 更新sock_stores中对应pid对应的sk if (err) { - // bpf_printk("tcp_v6_connect update sock_stores err.\n"); return 0; } return 0; } -SEC("kretprobe/tcp_v6_connect")//退出tcp_v6_connect函数 +SEC("kretprobe/tcp_v6_connect") // 退出tcp_v6_connect函数 int BPF_KRETPROBE(tcp_v6_connect_exit, int ret) { - u64 ptid = bpf_get_current_pid_tgid();//获取pid + u64 ptid = bpf_get_current_pid_tgid(); // 获取pid struct sock **skp = bpf_map_lookup_elem(&sock_stores, &ptid); - //获得sock_stores中ptid对应的*sk 用skp指向 + // 获得sock_stores中ptid对应的*sk 用skp指向 if (skp == NULL) { return 0; } - // bpf_printk("tcp_v6_connect_exit\n"); - if (ret != 0) {//错误 - // bpf_printk("tcp_v6_connect_exit but return %d\n", ret); - bpf_map_delete_elem(&sock_stores, &ptid);//删除对应键值对 + if (ret != 0) { // 错误 + bpf_map_delete_elem(&sock_stores, &ptid); // 删除对应键值对 return 0; } struct sock *sk = *skp; - CONN_INIT //初始化conn_t结构中基本信息 - conn.is_server = 0; //主动连接 + CONN_INIT // 初始化conn_t结构中基本信息 + conn.is_server = 0; // 主动连接 - FILTER_DPORT //过滤目标端口 - FILTER_SPORT //过滤源端口 + FILTER_DPORT // 过滤目标端口 - CONN_ADD_ADDRESS //conn_t结构中增加地址信息 + FILTER_SPORT // 过滤源端口 - long err = bpf_map_update_elem(&conns_info, &sk, &conn, BPF_ANY); - //更新conns_info中sk对应的conn + CONN_ADD_ADDRESS // conn_t结构中增加地址信息 + + long err = bpf_map_update_elem(&conns_info, &sk, &conn, BPF_ANY); + // 更新conns_info中sk对应的conn if (err) { - // bpf_printk("tcp_v6_connect_exit update err.\n"); return 0; } // bpf_printk("tcp_v4_connect_exit update sk: %p.\n", sk); @@ -474,11 +488,11 @@ int BPF_KPROBE(tcp_set_state, struct sock *sk, int state) { return 0; } struct conn_t *value = bpf_map_lookup_elem(&conns_info, &sk); - //查找sk对应的conn_t - if (state == TCP_CLOSE && value != NULL) {//TCP_CLOSE置1 说明关闭连接 + // 查找sk对应的conn_t + if (state == TCP_CLOSE && value != NULL) { // TCP_CLOSE置1 说明关闭连接 // delete - bpf_map_delete_elem(&sock_stores, &value->ptid);//删除sock_stores - bpf_map_delete_elem(&conns_info, &sk);//删除conns_info + bpf_map_delete_elem(&sock_stores, &value->ptid); // 删除sock_stores + bpf_map_delete_elem(&conns_info, &sk); // 删除conns_info } return 0; } @@ -515,28 +529,32 @@ int BPF_KPROBE(tcp_set_state, struct sock *sk, int state) { /************************************************ receive path * ****************************************/ /** in ipv4 && ipv6 */ -SEC("kprobe/eth_type_trans")//进入eth_type_trans +SEC("kprobe/eth_type_trans") // 进入eth_type_trans int BPF_KPROBE(eth_type_trans, struct sk_buff *skb) { - const struct ethhdr *eth = (struct ethhdr *)BPF_CORE_READ(skb, data);//读取里面的报文数据 - u16 protocol = BPF_CORE_READ(eth, h_proto); //读取包ID + const struct ethhdr *eth = + (struct ethhdr *)BPF_CORE_READ(skb, data); // 读取里面的报文数据 + u16 protocol = BPF_CORE_READ(eth, h_proto); // 读取包ID // bpf_printk("protocol: %d\n", __bpf_ntohs(protocol)); if (protocol == __bpf_htons(ETH_P_IP)) { // Protocol is IP 0x0800 - //14 --> sizeof(struct ethhdr) / define - struct iphdr *ip = (struct iphdr *)(BPF_CORE_READ(skb, data) + 14);//链路层头部长度为14 源端口6字节 目的端口6字节 类型2字节 + // 14 --> sizeof(struct ethhdr) / define + struct iphdr *ip = + (struct iphdr *)(BPF_CORE_READ(skb, data) + + 14); // 链路层头部长度为14 源端口6字节 + // 目的端口6字节 类型2字节 struct tcphdr *tcp = (struct tcphdr *)(BPF_CORE_READ(skb, data) + sizeof(struct iphdr) + 14); - struct packet_tuple pkt_tuple = {0}; //声明packet_tuple结构pkt_tuple - get_pkt_tuple(&pkt_tuple, ip, tcp); //初始化pkt_tuple + struct packet_tuple pkt_tuple = {0}; // 声明packet_tuple结构pkt_tuple + get_pkt_tuple(&pkt_tuple, ip, tcp); // 初始化pkt_tuple - struct ktime_info *tinfo, zero = {0}; //定义ktime_info结构zero以及tinfo + struct ktime_info *tinfo, zero = {0}; // 定义ktime_info结构zero以及tinfo tinfo = (struct ktime_info *)bpf_map_lookup_or_try_init( ×tamps, &pkt_tuple, &zero); - if (tinfo == NULL) {//初始化失败 + if (tinfo == NULL) { // 初始化失败 // bpf_printk("v4 rx tinfo init fail.\n"); return 0; } - //成功则获取当前内核时间并转换成毫秒 + // 成功则获取当前内核时间并转换成毫秒 tinfo->mac_time = bpf_ktime_get_ns() / 1000; // bpf_printk("v4 rx init.\n"); } else if (protocol == __bpf_htons(ETH_P_IPV6)) { // Protocol is IPV6 @@ -562,19 +580,21 @@ int BPF_KPROBE(eth_type_trans, struct sk_buff *skb) { } /** in only ipv4 */ -SEC("kprobe/ip_rcv_core")//跟踪记录ipv4数据包在内核中的处理时间 +SEC("kprobe/ip_rcv_core") // 跟踪记录ipv4数据包在内核中的处理时间 int BPF_KPROBE(ip_rcv_core, struct sk_buff *skb) { if (!layer_time) { return 0; } if (skb == NULL) return 0; - struct iphdr *ip = skb_to_iphdr(skb);//通过skb获取ipv4包头信息 - struct tcphdr *tcp = skb_to_tcphdr(skb);//获取tcp包头信息 - struct packet_tuple pkt_tuple = {0};//定义一个packet_tuple结构体变量pkt_tuple并初始化 + struct iphdr *ip = skb_to_iphdr(skb); // 通过skb获取ipv4包头信息 + struct tcphdr *tcp = skb_to_tcphdr(skb); // 获取tcp包头信息 + struct packet_tuple pkt_tuple = { + 0}; // 定义一个packet_tuple结构体变量pkt_tuple并初始化 get_pkt_tuple(&pkt_tuple, ip, tcp); struct ktime_info *tinfo; - tinfo = bpf_map_lookup_elem(×tamps, &pkt_tuple);//在timestamps映射中查找元素pkt_tuple + tinfo = bpf_map_lookup_elem( + ×tamps, &pkt_tuple); // 在timestamps映射中查找元素pkt_tuple if (tinfo == NULL) { return 0; } @@ -600,14 +620,14 @@ int BPF_KPROBE(ip6_rcv_core, struct sk_buff *skb) { if (tinfo == NULL) { return 0; } - + tinfo->ip_time = bpf_ktime_get_ns() / 1000; // bpf_printk("rx enter ipv6 layer.\n"); return 0; } -/**in only ipv4 *///接收数据包 -SEC("kprobe/tcp_v4_rcv")//记录数据包在tcpv4层时间戳 +/**in only ipv4 */ // 接收数据包 +SEC("kprobe/tcp_v4_rcv") // 记录数据包在tcpv4层时间戳 int BPF_KPROBE(tcp_v4_rcv, struct sk_buff *skb) { if (!layer_time) { return 0; @@ -629,7 +649,7 @@ int BPF_KPROBE(tcp_v4_rcv, struct sk_buff *skb) { } /** in only ipv6 */ -SEC("kprobe/tcp_v6_rcv")//接收tcpv6数据包 +SEC("kprobe/tcp_v6_rcv") // 接收tcpv6数据包 int BPF_KPROBE(tcp_v6_rcv, struct sk_buff *skb) { if (!layer_time) { return 0; @@ -659,8 +679,8 @@ int BPF_KPROBE(tcp_v4_do_rcv, struct sock *sk, struct sk_buff *skb) { return 0; struct conn_t *conn = bpf_map_lookup_elem(&conns_info, &sk); if (conn == NULL) { - // bpf_printk("get a v4 rx pack but conn not record, its sock is: %p", - // sk); + // bpf_printk("get a v4 rx pack but conn not record, its sock is: + // %p",sk); return 0; } struct iphdr *ip = skb_to_iphdr(skb); @@ -682,7 +702,7 @@ int BPF_KPROBE(tcp_v4_do_rcv, struct sock *sk, struct sk_buff *skb) { return 0; } -SEC("kprobe/tcp_v6_do_rcv")//tcp层包时间 +SEC("kprobe/tcp_v6_do_rcv") // tcp层包时间 int BPF_KPROBE(tcp_v6_do_rcv, struct sock *sk, struct sk_buff *skb) { if (sk == NULL || skb == NULL) return 0; @@ -697,7 +717,7 @@ int BPF_KPROBE(tcp_v6_do_rcv, struct sock *sk, struct sk_buff *skb) { struct ipv6hdr *ip6h = skb_to_ipv6hdr(skb); struct tcphdr *tcp = skb_to_tcphdr(skb); struct packet_tuple pkt_tuple = {0}; - get_pkt_tuple_v6(&pkt_tuple, ip6h, tcp);//使用ip和tcp信息填充pkt_tuple + get_pkt_tuple_v6(&pkt_tuple, ip6h, tcp); // 使用ip和tcp信息填充pkt_tuple struct ktime_info *tinfo; tinfo = bpf_map_lookup_elem(×tamps, &pkt_tuple); @@ -715,11 +735,11 @@ int BPF_KPROBE(tcp_v6_do_rcv, struct sock *sk, struct sk_buff *skb) { } /** in ipv4 && ipv6 */ -SEC("kprobe/skb_copy_datagram_iter")//处理网络数据包,记录分析包在不同网络层之间的时间差,分ipv4以及ipv6 +SEC("kprobe/skb_copy_datagram_iter") // 处理网络数据包,记录分析包在不同网络层之间的时间差,分ipv4以及ipv6 int BPF_KPROBE(skb_copy_datagram_iter, struct sk_buff *skb) { if (skb == NULL) return 0; - __be16 protocol = BPF_CORE_READ(skb, protocol);//读取skb协议字段 + __be16 protocol = BPF_CORE_READ(skb, protocol); // 读取skb协议字段 struct tcphdr *tcp = skb_to_tcphdr(skb); struct packet_tuple pkt_tuple = {0}; struct ktime_info *tinfo; @@ -727,7 +747,6 @@ int BPF_KPROBE(skb_copy_datagram_iter, struct sk_buff *skb) { struct iphdr *ip = skb_to_iphdr(skb); get_pkt_tuple(&pkt_tuple, ip, tcp); - tinfo = bpf_map_lookup_elem(×tamps, &pkt_tuple); if (tinfo == NULL) { return 0; @@ -738,7 +757,7 @@ int BPF_KPROBE(skb_copy_datagram_iter, struct sk_buff *skb) { /** ipv6 */ struct ipv6hdr *ip6h = skb_to_ipv6hdr(skb); get_pkt_tuple_v6(&pkt_tuple, ip6h, tcp); - + if ((tinfo = bpf_map_lookup_elem(×tamps, &pkt_tuple)) == NULL) { return 0; } @@ -761,26 +780,29 @@ int BPF_KPROBE(skb_copy_datagram_iter, struct sk_buff *skb) { if (layer_time) { packet->mac_time = tinfo->ip_time - tinfo->mac_time; - //计算MAC层和ip层之间的时间差 + // 计算MAC层和ip层之间的时间差 packet->ip_time = tinfo->tran_time - tinfo->ip_time; - //计算ip层和tcp层之间的时间差 + // 计算ip层和tcp层之间的时间差 packet->tran_time = tinfo->app_time - tinfo->tran_time; - //计算tcp层和应用层之间的时间差 + // 计算tcp层和应用层之间的时间差 } - packet->rx = 1;//数据包已经被接收 + packet->rx = 1; // 数据包已经被接收 // RX HTTP INFO if (http_info) { int doff = BPF_CORE_READ_BITFIELD_PROBED(tcp, doff); // 得用bitfield_probed - //读取tcp头部中的数据偏移字段 + // 读取tcp头部中的数据偏移字段 unsigned char *user_data = (unsigned char *)((unsigned char *)tcp + (doff * 4)); - //计算tcp的负载开始位置就是tcp头部之后的数据,将tcp指针指向tcp头部位置将其转换成unsigned char类型 - //doff * 4数据偏移值(tcp的头部长度20个字节)乘以4计算tcp头部实际字节长度,32位为单位就是4字节 - bpf_probe_read_str(packet->data, sizeof(packet->data), user_data); //将tcp负载数据读取到packet->data - } - bpf_ringbuf_submit(packet, 0);//将packet提交到缓冲区 + // 计算tcp的负载开始位置就是tcp头部之后的数据,将tcp指针指向tcp头部位置将其转换成unsigned + // char类型 + // doff * + // 4数据偏移值(tcp的头部长度20个字节)乘以4计算tcp头部实际字节长度,32位为单位就是4字节 + bpf_probe_read_str(packet->data, sizeof(packet->data), + user_data); // 将tcp负载数据读取到packet->data + } + bpf_ringbuf_submit(packet, 0); // 将packet提交到缓冲区 return 0; } @@ -788,36 +810,41 @@ int BPF_KPROBE(skb_copy_datagram_iter, struct sk_buff *skb) { /**** receive error packet ****/ /* TCP invalid seq error */ -//根据传入的数据包提取关键信息(如IP和TCP头部信息),并将这些信息与其他元数据(如套接字信息和错误标识)一同存储到BPF ring buffer中 -SEC("kprobe/tcp_validate_incoming")//验证传入数据包的序列号 +// 根据传入的数据包提取关键信息(如IP和TCP头部信息),并将这些信息与其他元数据(如套接字信息和错误标识)一同存储到BPF +// ring buffer中 +SEC("kprobe/tcp_validate_incoming") // 验证传入数据包的序列号 int BPF_KPROBE(tcp_validate_incoming, struct sock *sk, struct sk_buff *skb) { if (!err_packet) { return 0; } if (sk == NULL || skb == NULL) return 0; - struct conn_t *conn = bpf_map_lookup_elem(&conns_info, &sk);//BPFmap查找与套接字sk关联的信息 + struct conn_t *conn = + bpf_map_lookup_elem(&conns_info, &sk); // BPFmap查找与套接字sk关联的信息 if (conn == NULL) { return 0; } - struct tcp_skb_cb *tcb = TCP_SKB_CB(skb);//数据包信息 - u32 start_seq = BPF_CORE_READ(tcb, seq);//开始序列号 - u32 end_seq = BPF_CORE_READ(tcb, end_seq);//结束序列号 - struct tcp_sock *tp = tcp_sk(sk);//套接字信息 - u32 rcv_wup = BPF_CORE_READ(tp, rcv_wup);//接收方已经确认并准备接收的数据最后一个字节的序列号 - u32 rcv_nxt = BPF_CORE_READ(tp, rcv_nxt);//期望发送发下次发送的数据字节序列号 - u32 rcv_wnd = BPF_CORE_READ(tp, rcv_wnd);//tcp接收窗口大小 - u32 receive_window = rcv_wup + rcv_nxt - rcv_wnd;//当前可用的接收窗口 - receive_window = 0; + struct tcp_skb_cb *tcb = TCP_SKB_CB(skb); // 数据包信息 + u32 start_seq = BPF_CORE_READ(tcb, seq); // 开始序列号 + u32 end_seq = BPF_CORE_READ(tcb, end_seq); // 结束序列号 + struct tcp_sock *tp = tcp_sk(sk); // 套接字信息 + u32 rcv_wup = BPF_CORE_READ( + tp, rcv_wup); // 接收方已经确认并准备接收的数据最后一个字节的序列号 + u32 rcv_nxt = + BPF_CORE_READ(tp, rcv_nxt); // 期望发送发下次发送的数据字节序列号 + u32 rcv_wnd = BPF_CORE_READ(tp, rcv_wnd); // tcp接收窗口大小 + u32 receive_window = rcv_wup + rcv_nxt - rcv_wnd; // 当前可用的接收窗口 + receive_window = 0; if (end_seq >= rcv_wup && rcv_nxt + receive_window >= start_seq) { // bpf_printk("error_identify: tcp seq validated. \n"); return 0; - //检查数据包序列号是否在接收窗口内 + // 检查数据包序列号是否在接收窗口内 } // bpf_printk("error_identify: tcp seq err. \n"); // invalid seq - u16 family = BPF_CORE_READ(sk, __sk_common.skc_family);//获取套接字的地址族就是获得当前ip协议 + u16 family = BPF_CORE_READ( + sk, __sk_common.skc_family); // 获取套接字的地址族就是获得当前ip协议 struct packet_tuple pkt_tuple = {0}; if (family == AF_INET) { struct iphdr *ip = skb_to_iphdr(skb); @@ -835,14 +862,14 @@ int BPF_KPROBE(tcp_validate_incoming, struct sock *sk, struct sk_buff *skb) { if (!packet) { return 0; } - packet->err = 1;//错误标记此数据包有问题 + packet->err = 1; // 错误标记此数据包有问题 packet->sock = sk; packet->ack = pkt_tuple.ack; packet->seq = pkt_tuple.seq; bpf_ringbuf_submit(packet, 0); return 0; } -//跟踪网络数据包检测tcp检验和错误 +// 跟踪网络数据包检测tcp检验和错误 /* TCP invalid checksum error*/ SEC("kretprobe/__skb_checksum_complete") int BPF_KRETPROBE(__skb_checksum_complete_exit, int ret) { @@ -869,8 +896,8 @@ int BPF_KRETPROBE(__skb_checksum_complete_exit, int ret) { if (!packet) { return 0; } - packet->err = 2;//校验和错误 - packet->sock = sk;//存储socket信息到sock字段中 + packet->err = 2; // 校验和错误 + packet->sock = sk; // 存储socket信息到sock字段中 bpf_ringbuf_submit(packet, 0); return 0; @@ -883,57 +910,61 @@ int BPF_KRETPROBE(__skb_checksum_complete_exit, int ret) { * \brief: 获取数据包进入TCP层时刻的时间戳, 发送tcp层起始点 * out ipv4 && ipv6 */ -SEC("kprobe/tcp_sendmsg")//跟踪tcp发送包信息 +SEC("kprobe/tcp_sendmsg") // 跟踪tcp发送包信息 int BPF_KPROBE(tcp_sendmsg, struct sock *sk, struct msghdr *msg, size_t size) { - struct conn_t *conn = bpf_map_lookup_elem(&conns_info, &sk); if (conn == NULL) { return 0; } - u16 family = BPF_CORE_READ(sk, __sk_common.skc_family); - struct ktime_info *tinfo, zero = {0};//存储时间 - struct packet_tuple pkt_tuple = {0};//存储数据包信息 + struct ktime_info *tinfo, zero = {0}; // 存储时间 + struct packet_tuple pkt_tuple = {0}; // 存储数据包信息 /** ipv4 */ if (family == AF_INET) { u16 dport = BPF_CORE_READ(sk, __sk_common.skc_dport); - pkt_tuple.saddr = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr);//源ip - pkt_tuple.daddr = BPF_CORE_READ(sk, __sk_common.skc_daddr);//目的ip - pkt_tuple.sport = BPF_CORE_READ(sk, __sk_common.skc_num);//源端口 - pkt_tuple.dport = __bpf_ntohs(dport);//目的端口并进行字节序转换 - - u32 snd_nxt = BPF_CORE_READ(tcp_sk(sk), snd_nxt);//tcp要发送的下一个字节序列号 - u32 rcv_nxt = BPF_CORE_READ(tcp_sk(sk), rcv_nxt);//tcp接收的下一个字节的期望序列号 + pkt_tuple.saddr = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr); // 源ip + pkt_tuple.daddr = BPF_CORE_READ(sk, __sk_common.skc_daddr); // 目的ip + pkt_tuple.sport = BPF_CORE_READ(sk, __sk_common.skc_num); // 源端口 + pkt_tuple.dport = __bpf_ntohs(dport); // 目的端口并进行字节序转换 + + u32 snd_nxt = + BPF_CORE_READ(tcp_sk(sk), snd_nxt); // tcp要发送的下一个字节序列号 + u32 rcv_nxt = BPF_CORE_READ(tcp_sk(sk), + rcv_nxt); // tcp接收的下一个字节的期望序列号 pkt_tuple.seq = snd_nxt; pkt_tuple.ack = rcv_nxt; - + pkt_tuple.tran_flag = TCP; tinfo = (struct ktime_info *)bpf_map_lookup_or_try_init( - ×tamps, &pkt_tuple, &zero);//timestamps的BPF map保存数据包与时间戳的映射 + ×tamps, &pkt_tuple, + &zero); // timestamps的BPF map保存数据包与时间戳的映射 if (tinfo == NULL) { return 0; } tinfo->tran_time = bpf_ktime_get_ns() / 1000; } else if (family == AF_INET6) { - //读取ipv6源地址 + // 读取ipv6源地址 bpf_probe_read_kernel( &pkt_tuple.saddr_v6, sizeof(sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32), &sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32); -//获取ipv6目的地址 + // 获取ipv6目的地址 bpf_probe_read_kernel( &pkt_tuple.daddr_v6, sizeof(sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32), &sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32); -//sk套接字中获取源端口号 + // sk套接字中获取源端口号 pkt_tuple.sport = BPF_CORE_READ(sk, __sk_common.skc_num); - //获取目的端口 + // 获取目的端口 u16 dport = BPF_CORE_READ(sk, __sk_common.skc_dport); pkt_tuple.dport = __bpf_ntohs(dport); - u32 snd_nxt = BPF_CORE_READ(tcp_sk(sk), snd_nxt);//发送的下一个字节序列号 - u32 rcv_nxt = BPF_CORE_READ(tcp_sk(sk), rcv_nxt);//期望接收的下一个字节序列号 + u32 snd_nxt = + BPF_CORE_READ(tcp_sk(sk), snd_nxt); // 发送的下一个字节序列号 + u32 rcv_nxt = + BPF_CORE_READ(tcp_sk(sk), rcv_nxt); // 期望接收的下一个字节序列号 pkt_tuple.seq = snd_nxt; pkt_tuple.ack = rcv_nxt; + pkt_tuple.tran_flag = TCP; tinfo = (struct ktime_info *)bpf_map_lookup_or_try_init( ×tamps, &pkt_tuple, &zero); @@ -948,6 +979,9 @@ int BPF_KPROBE(tcp_sendmsg, struct sock *sk, struct msghdr *msg, size_t size) { CONN_ADD_EXTRA_INFO // TX HTTP info + if (!udp_info) { + return 0; + } if (http_info) { unsigned char *user_data = BPF_CORE_READ(msg, msg_iter.iov, iov_base); tinfo = (struct ktime_info *)bpf_map_lookup_or_try_init( @@ -986,7 +1020,7 @@ int BPF_KPROBE(ip_queue_xmit, struct sock *sk, struct sk_buff *skb) { ack = BPF_CORE_READ(tcp, ack_seq); pkt_tuple.seq = __bpf_ntohl(seq); pkt_tuple.ack = __bpf_ntohl(ack); - + pkt_tuple.tran_flag = TCP; if ((tinfo = bpf_map_lookup_elem(×tamps, &pkt_tuple)) == NULL) { return 0; } @@ -1002,7 +1036,7 @@ tcp)获取ip段的数据 out only ipv6 */ SEC("kprobe/inet6_csk_xmit") int BPF_KPROBE(inet6_csk_xmit, struct sock *sk, struct sk_buff *skb) { - if (!layer_time) { + if (!udp_info) { return 0; } u16 family = BPF_CORE_READ(sk, __sk_common.skc_family); @@ -1030,7 +1064,7 @@ int BPF_KPROBE(inet6_csk_xmit, struct sock *sk, struct sk_buff *skb) { ack = BPF_CORE_READ(tcp, ack_seq); pkt_tuple.seq = __bpf_ntohl(seq); pkt_tuple.ack = __bpf_ntohl(ack); - + pkt_tuple.tran_flag = TCP; if ((tinfo = bpf_map_lookup_elem(×tamps, &pkt_tuple)) == NULL) { return 0; } @@ -1045,12 +1079,14 @@ int BPF_KPROBE(inet6_csk_xmit, struct sock *sk, struct sk_buff *skb) { */ SEC("kprobe/__dev_queue_xmit") int BPF_KPROBE(__dev_queue_xmit, struct sk_buff *skb) { - if (!layer_time) { - return 0; - } - //从skb中读取以太网头部 + /* if (!layer_time) { + return 0; + }*/ + // 从skb中读取以太网头部 const struct ethhdr *eth = (struct ethhdr *)BPF_CORE_READ(skb, data); - u16 protocol = BPF_CORE_READ(eth, h_proto);//以太网头部协议字段该字段存储的是以太网帧所封装的上层协议类型 + u16 protocol = BPF_CORE_READ( + eth, + h_proto); // 以太网头部协议字段该字段存储的是以太网帧所封装的上层协议类型 struct tcphdr *tcp = skb_to_tcphdr(skb); struct packet_tuple pkt_tuple = {0}; struct ktime_info *tinfo; @@ -1098,7 +1134,7 @@ int BPF_KPROBE(dev_hard_start_xmit, struct sk_buff *skb) { if ((tinfo = bpf_map_lookup_elem(×tamps, &pkt_tuple)) == NULL) { return 0; } - //数据包在队列中等待的时间 + // 数据包在队列中等待的时间 tinfo->qdisc_time = bpf_ktime_get_ns() / 1000; } else if (protocol == __bpf_ntohs(ETH_P_IPV6)) { /** ipv6 */ @@ -1112,27 +1148,32 @@ int BPF_KPROBE(dev_hard_start_xmit, struct sk_buff *skb) { } else { return 0; } + /*----- record packet time info ------*/ if (tinfo == NULL) { return 0; } struct sock *sk = tinfo->sk; - if (sk == NULL) { + if (!sk) { return 0; } - PACKET_INIT_WITH_COMMON_INFO - //记录各层的时间差值 + // 记录各层的时间差值 if (layer_time) { packet->tran_time = tinfo->ip_time - tinfo->tran_time; packet->ip_time = tinfo->mac_time - tinfo->ip_time; - packet->mac_time = tinfo->qdisc_time - tinfo->mac_time;//队列纪律层,处于网络协议栈最底层,负责实际数据传输与接收 + packet->mac_time = + tinfo->qdisc_time - + tinfo + ->mac_time; // 队列纪律层,处于网络协议栈最底层,负责实际数据传输与接收 } - packet->rx = 0;//发送一个数据包 + + packet->rx = 0; // 发送一个数据包 // TX HTTP Info if (http_info) { bpf_probe_read_str(packet->data, sizeof(packet->data), tinfo->data); + bpf_printk("%s", packet->data); } bpf_ringbuf_submit(packet, 0); @@ -1146,7 +1187,7 @@ int BPF_KPROBE(dev_hard_start_xmit, struct sk_buff *skb) { * 还是RACK触发的快速恢复,都将使用函数tcp_enter_recovery进入 * TCP_CA_Recovery拥塞阶段。 */ -SEC("kprobe/tcp_enter_recovery")//tcp连接进入恢复状态调用 +SEC("kprobe/tcp_enter_recovery") // tcp连接进入恢复状态调用 int BPF_KPROBE(tcp_enter_recovery, struct sock *sk) { if (!retrans_info) { return 0; @@ -1157,7 +1198,7 @@ int BPF_KPROBE(tcp_enter_recovery, struct sock *sk) { // sk); return 0; } - conn->fastRe += 1;//统计进入tcp恢复状态的次数 + conn->fastRe += 1; // 统计进入tcp恢复状态的次数 return 0; } @@ -1174,8 +1215,6 @@ int BPF_KPROBE(tcp_enter_loss, struct sock *sk) { } struct conn_t *conn = bpf_map_lookup_elem(&conns_info, &sk); if (conn == NULL) { - // bpf_printk("get a v4 rx pack but conn not record, its sock is: %p", - // sk); return 0; } conn->timeout += 1; @@ -1184,15 +1223,14 @@ int BPF_KPROBE(tcp_enter_loss, struct sock *sk) { /**** retrans end ****/ - /* new */ SEC("kprobe/udp_rcv") -int BPF_KPROBE(udp_rcv,struct sk_buff *skb) -{ - if (skb == NULL)//判断是否为空 +int BPF_KPROBE(udp_rcv, struct sk_buff *skb) { + if (!udp_info) + return 0; + if (skb == NULL) // 判断是否为空 return 0; - bpf_printk("udp_rcv %u",bpf_get_current_pid_tgid()); struct iphdr *ip = skb_to_iphdr(skb); struct udphdr *udp = skb_to_udphdr(skb); struct packet_tuple pkt_tuple = {0}; @@ -1200,24 +1238,18 @@ int BPF_KPROBE(udp_rcv,struct sk_buff *skb) get_udp_pkt_tuple(&pkt_tuple, ip, udp); struct ktime_info *tinfo, zero = {0}; - tinfo = (struct ktime_info *)bpf_map_lookup_or_try_init( - ×tamps, &pkt_tuple, &zero); + tinfo = (struct ktime_info *)bpf_map_lookup_or_try_init(×tamps, + &pkt_tuple, &zero); if (tinfo == NULL) { return 0; } tinfo->tran_time = bpf_ktime_get_ns() / 1000; - //bpf_printk("1---saddr : %u daddr : %u sport : %u dport : %u tran_flag : %u seq:%u ack:%u\n", - //pkt_tuple.saddr,pkt_tuple.daddr,pkt_tuple.sport,pkt_tuple.dport,pkt_tuple.tran_flag,pkt_tuple.seq,pkt_tuple.ack); return 0; - } - - SEC("kprobe/__udp_enqueue_schedule_skb") -int BPF_KPROBE(__udp_enqueue_schedule_skb,struct sock *sk, struct sk_buff *skb) -{ - bpf_printk("__udp_enqueue_schedule_skb %u",bpf_get_current_pid_tgid()); - if (skb == NULL)//判断是否为空 +int BPF_KPROBE(__udp_enqueue_schedule_skb, struct sock *sk, + struct sk_buff *skb) { + if (skb == NULL) // 判断是否为空 return 0; struct iphdr *ip = skb_to_iphdr(skb); struct udphdr *udp = skb_to_udphdr(skb); @@ -1227,16 +1259,115 @@ int BPF_KPROBE(__udp_enqueue_schedule_skb,struct sock *sk, struct sk_buff *skb) pkt_tuple.saddr = BPF_CORE_READ(sk, __sk_common.skc_daddr); pkt_tuple.dport = BPF_CORE_READ(sk, __sk_common.skc_num); pkt_tuple.sport = __bpf_ntohs(dport); - pkt_tuple.tran_flag=2; - //bpf_printk("2---saddr : %u daddr : %u sport : %u dport : %u tran_flag : %u seq:%u ack:%u\n", - //pkt_tuple.saddr,pkt_tuple.daddr,pkt_tuple.sport,pkt_tuple.dport,pkt_tuple.tran_flag,pkt_tuple.seq,pkt_tuple.ack); - + pkt_tuple.tran_flag = 2; + struct ktime_info *tinfo, zero = {0}; tinfo = bpf_map_lookup_elem(×tamps, &pkt_tuple); if (tinfo == NULL) { return 0; } - bpf_printk("udp_time : %lld\n",bpf_ktime_get_ns() / 1000 - tinfo->tran_time); + struct udp_message *message; + struct udp_message *udp_message = + bpf_map_lookup_elem(×tamps, &pkt_tuple); + ; + message = bpf_ringbuf_reserve(&udp_rb, sizeof(*message), 0); + if (!message) { + return 0; + } + message->tran_time = bpf_ktime_get_ns() / 1000 - tinfo->tran_time; + message->saddr = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr); + message->daddr = BPF_CORE_READ(sk, __sk_common.skc_daddr); + message->sport = BPF_CORE_READ(sk, __sk_common.skc_num); + message->dport = BPF_CORE_READ(sk, __sk_common.skc_dport); + + bpf_ringbuf_submit(message, 0); return 0; +} +// kprobe 挂载 udp_sendmsg 函数 +SEC("kprobe/udp_sendmsg") +int trace_sys_send(struct pt_regs *ctx) { + int time; + unsigned int pid = bpf_get_current_pid_tgid(); + ; // 获取当前进程pid + u64 tmp = PT_REGS_PARM3_CORE(ctx); // 获取发送数据的大小 + // struct sock *sock = (struct sock *)PT_REGS_PARM1_CORE(ctx); + struct udp_tracing *st = bpf_map_lookup_elem( + &udp_flow_map, + &pid); // 使用bpf_map_lookup_elem函数查找udp_flow_map中以pid为键的元素 + if (st && tmp > 0) // 如果找到对应的元素 + { + st->send += tmp; // 累加 + } else { + struct udp_tracing val = {.send = tmp, .recv = 0}; + // bpf_map_update_elem函数将以key为键、recv为值的元素插入到udp_flow_map中,进行更新 + bpf_map_update_elem(&udp_flow_map, &pid, &val, BPF_ANY); + } + struct packet_tuple pkt_tuple = {0}; + struct ktime_info *tinfo; + struct udp_message *message; + struct udp_message *udp_message = + bpf_map_lookup_elem(×tamps, &pkt_tuple); + ; + message = bpf_ringbuf_reserve(&udp_rb, sizeof(*message), 0); + if (!message) { + return 0; + } + message->tran_time = bpf_ktime_get_ns() / 1000 - tinfo->tran_time; + + bpf_ringbuf_submit(message, 0); + return 0; +} + +SEC("kprobe/udp_recvmsg") +int trace_sys_recv(struct pt_regs *ctx) { + unsigned int pid = bpf_get_current_pid_tgid(); + struct udp_tracing *st = bpf_map_lookup_elem(&udp_flow_map, &pid); + if (!st) { + return 0; + } + struct sock *sock = (struct sock *)PT_REGS_PARM1_CORE(ctx); + st->daddr = BPF_CORE_READ(sock, __sk_common.skc_daddr); + st->saddr = BPF_CORE_READ(sock, __sk_common.skc_rcv_saddr); + st->sport = BPF_CORE_READ(sock, __sk_common.skc_num); + st->dport = BPF_CORE_READ(sock, __sk_common.skc_dport); + bpf_map_update_elem(&udp_flow_map, &pid, st, BPF_ANY); + bpf_printk("%d", st->daddr); + return 0; +} + +SEC("kretprobe/udp_recvmsg") +int trace_sys_recv_ret(struct pt_regs *ctx) { + struct packet_tuple pkt_tuple = {0}; + pkt_tuple.tran_flag = 2; + unsigned int total; + unsigned int pid = bpf_get_current_pid_tgid(); + // 查找pid关联的值 + struct udp_tracing *st = bpf_map_lookup_elem(&udp_flow_map, &pid); + if (!st) { + return 0; + } + u64 tmp = PT_REGS_RC(ctx); + if (tmp > 0) { + st->recv += tmp; + } else { + struct udp_tracing val = {.send = tmp, .recv = 0}; + // bpf_map_update_elem函数将以key为键、recv为值的元素插入到udp_flow_map中,进行更新 + bpf_map_update_elem(&udp_flow_map, &pid, &val, BPF_ANY); + } + struct sock *sock = (struct sock *)PT_REGS_PARM1_CORE(ctx); + struct udp_message *data; + data = bpf_ringbuf_reserve(&udp_rb, sizeof(*data), 0); + if (!data) + return 0; + bpf_get_current_comm(&(data->comm), sizeof(data->comm)); + data->saddr = st->saddr; + data->daddr = st->daddr; + data->sport = st->sport; + data->dport = st->dport; + data->send = st->send; + data->recv = st->recv; + data->total = st->send + st->recv; + bpf_ringbuf_submit(data, 0); + return 0; } \ No newline at end of file diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c index 878b089e0..4de0a04b6 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c @@ -38,7 +38,8 @@ static char packets_file_path[1024]; static int sport = 0, dport = 0; // for filter static int all_conn = 0, err_packet = 0, extra_conn_info = 0, layer_time = 0, - http_info = 0, retrans_info = 0; // flag + http_info = 0, retrans_info = 0, udp_info = 0, + udp_traffic = 0; // flag static const char argp_program_doc[] = "Watch tcp/ip in network subsystem \n"; @@ -51,6 +52,8 @@ static const struct argp_option opts[] = { {"http", 'i', 0, 0, "set to trace http info"}, {"sport", 's', "SPORT", 0, "trace this source port only"}, {"dport", 'd', "DPORT", 0, "trace this destination port only"}, + {"udp", 'u', 0, 0, "trace the udp message"}, + {"udp_traffic", 'c', 0, 0, "trace the udp traffic"}, {}}; static error_t parse_arg(int key, char *arg, struct argp_state *state) { @@ -80,6 +83,12 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) { case 'd': dport = strtoul(arg, &end, 10); break; + case 'u': + udp_info = 1; + break; + case 'c': + udp_traffic = 1; + break; default: return ARGP_ERR_UNKNOWN; } @@ -134,10 +143,6 @@ static int print_conns(struct netwatcher_bpf *skel) { char s_ip_port_str[INET6_ADDRSTRLEN + 6]; char d_ip_port_str[INET6_ADDRSTRLEN + 6]; - - if(http_info){ - printf("%u,%u,%llu\n",d.rcv_wnd, d.snd_cwnd,d.duration); - } if (d.family == AF_INET) { sprintf(s_ip_port_str, "%s:%d", @@ -199,7 +204,8 @@ static int print_conns(struct netwatcher_bpf *skel) { } static int print_packet(void *ctx, void *packet_info, size_t size) { - + if (udp_info || udp_traffic) + return 0; const struct pack_t *pack_info = packet_info; if (pack_info->err) { FILE *file = fopen(err_file_path, "a"); @@ -217,13 +223,15 @@ static int print_packet(void *ctx, void *packet_info, size_t size) { } fprintf(file, "error{sock=\"%p\",seq=\"%u\",ack=\"%u\"," - "reason=\"%s\"} 0\n", + "reason=\"%s\"} \n", pack_info->sock, pack_info->seq, pack_info->ack, reason); fclose(file); } else { FILE *file = fopen(packets_file_path, "a"); char http_data[256]; + if (strstr((char *)pack_info->data, "HTTP/1")) { + for (int i = 0; i < sizeof(pack_info->data); ++i) { if (pack_info->data[i] == '\r') { http_data[i] = '\0'; @@ -232,43 +240,66 @@ static int print_packet(void *ctx, void *packet_info, size_t size) { http_data[i] = pack_info->data[i]; } } else { + sprintf(http_data, "-"); } - if(http_info == 0){ - if (layer_time) { - printf("%-22p %-10u %-10u %-10llu %-10llu %-10llu %-5d %s\n", - pack_info->sock, pack_info->seq, pack_info->ack, - pack_info->mac_time, pack_info->ip_time, pack_info->tran_time, - pack_info->rx, http_data); - fprintf(file, - "packet{sock=\"%p\",seq=\"%u\",ack=\"%u\"," - "mac_time=\"%llu\",ip_time=\"%llu\",tran_time=\"%llu\",http_" - "info=\"%s\",rx=\"%d\"} \n", - pack_info->sock, pack_info->seq, pack_info->ack, - pack_info->mac_time, pack_info->ip_time, - pack_info->tran_time, http_data, pack_info->rx); - } - if(http_info|| retrans_info||extra_conn_info){ - printf("%-22p %-10u %-10u %-5d %s\n", + if (layer_time) { + printf("%-22p %-10u %-10u %-10llu %-10llu %-10llu %-5d %s\n", pack_info->sock, pack_info->seq, pack_info->ack, + pack_info->mac_time, pack_info->ip_time, + pack_info->tran_time, pack_info->rx, http_data); + fprintf( + file, + "packet{sock=\"%p\",seq=\"%u\",ack=\"%u\"," + "mac_time=\"%llu\",ip_time=\"%llu\",tran_time=\"%llu\",http_" + "info=\"%s\",rx=\"%d\"} \n", + pack_info->sock, pack_info->seq, pack_info->ack, + pack_info->mac_time, pack_info->ip_time, pack_info->tran_time, + http_data, pack_info->rx); + } else { + printf("%-22p %-10u %-10u %-10d %-10d %-10d %-5d %s\n", + pack_info->sock, pack_info->seq, pack_info->ack, 0, 0, 0, pack_info->rx, http_data); - fprintf(file, + fprintf(file, "packet{sock=\"%p\",seq=\"%u\",ack=\"%u\"," + "mac_time=\"%d\",ip_time=\"%d\",tran_time=\"%d\",http_" "info=\"%s\",rx=\"%d\"} \n", - pack_info->sock, pack_info->seq, pack_info->ack, http_data, - pack_info->rx); - } - + pack_info->sock, pack_info->seq, pack_info->ack, 0, 0, 0, + http_data, pack_info->rx); } fclose(file); } return 0; } - +static int print_udp(void *ctx, void *packet_info, size_t size) { + char d_str[INET_ADDRSTRLEN]; + char s_str[INET_ADDRSTRLEN]; + const struct udp_message *pack_info = packet_info; + unsigned int saddr = pack_info->saddr; + unsigned int daddr = pack_info->daddr; + int send = pack_info->send; + int recv = pack_info->recv; + unsigned int total = pack_info->total; + if (daddr) { + if (udp_info && pack_info->tran_time) { + printf("%-15s %-15s %-10u %-10u %-10llu \n", + inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), + inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), + pack_info->sport, pack_info->dport, pack_info->tran_time); + + } else if (udp_traffic) { + printf("%-15s %-15s %-10u %-10u %-10d %-10d %-10d\n", + inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), + inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), + pack_info->sport, pack_info->dport, send, recv, total); + } + } + return 0; +} int main(int argc, char **argv) { char *last_slash = strrchr(argv[0], '/'); if (last_slash) { - *(last_slash+1) = '\0'; + *(last_slash + 1) = '\0'; } strcpy(connects_file_path, argv[0]); strcpy(err_file_path, argv[0]); @@ -277,6 +308,7 @@ int main(int argc, char **argv) { strcat(err_file_path, "data/err.log"); strcat(packets_file_path, "data/packets.log"); struct ring_buffer *rb = NULL; + struct ring_buffer *udp_rb = NULL; struct netwatcher_bpf *skel; int err; /* Parse command line arguments */ @@ -306,6 +338,8 @@ int main(int argc, char **argv) { skel->rodata->layer_time = layer_time; skel->rodata->http_info = http_info; skel->rodata->retrans_info = retrans_info; + skel->rodata->udp_info = udp_info; + skel->rodata->udp_traffic = udp_traffic; err = netwatcher_bpf__load(skel); if (err) { @@ -319,28 +353,42 @@ int main(int argc, char **argv) { fprintf(stderr, "Failed to attach BPF skeleton\n"); goto cleanup; } - - if(layer_time) { + /*if (!udp_info) { printf("%-22s %-10s %-10s %-10s %-10s %-10s %-5s %s\n", "SOCK", "SEQ", - "ACK", "MAC_TIME", "IP_TIME", "tran_time", "RX", "HTTP"); + "ACK", "MAC_TIME", "IP_TIME", "TRAN_TIME", "RX", "HTTP"); + }*/ + if (udp_info) { + printf(" %-15s %-15s %-10s %-10s %-10s \n", "saddr", "daddr", "sprot", + "dprot", "udp_time"); + } else if (udp_traffic) { + printf(" %-15s %-15s %-10s %-10s %-10s %-10s %-10s\n", "saddr", "daddr", + "sprot", "dprot", "send", "recv", "total"); } - - if(http_info|| retrans_info||extra_conn_info) { + /* else if(http_info) + { + print_conns(skel); + sleep(1); - printf("%-22s %-10s %-10s %-5s \n", "SOCK", "SEQ", - "ACK", "RX"); + }*/ + else { + printf("%-22s %-10s %-10s %-10s %-10s %-10s %-5s %s\n", "SOCK", "SEQ", + "ACK", "MAC_TIME", "IP_TIME", "TRAN_TIME", "RX", "HTTP"); + } + udp_rb = + ring_buffer__new(bpf_map__fd(skel->maps.udp_rb), print_udp, NULL, NULL); + if (!udp_rb) { + err = -1; + fprintf(stderr, "Failed to create ring buffer\n"); + goto cleanup; } - /* Set up ring buffer polling */ rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), print_packet, NULL, NULL); if (!rb) { err = -1; fprintf(stderr, "Failed to create ring buffer\n"); goto cleanup; - } - - + } FILE *err_file = fopen(err_file_path, "w+"); if (err_file == NULL) { fprintf(stderr, "Failed to open err.log: (%s)\n", strerror(errno)); @@ -353,17 +401,13 @@ int main(int argc, char **argv) { return 0; } fclose(packet_file); - + /* Process events */ while (!exiting) { - err = ring_buffer__poll(rb, 100 /* timeout, ms */); - - if(http_info) { - print_conns(skel); - sleep(1); - } - + err = ring_buffer__poll(udp_rb, 100 /* timeout, ms */); + print_conns(skel); + sleep(1); /* Ctrl-C will cause -EINTR */ if (err == -EINTR) { err = 0; @@ -378,4 +422,4 @@ int main(int argc, char **argv) { cleanup: netwatcher_bpf__destroy(skel); return err < 0 ? -err : 0; -} +} \ No newline at end of file diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h index 80955641a..9287f1ee0 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h @@ -72,18 +72,30 @@ struct conn_t { #define MAX_PACKET 1000 #define MAX_HTTP_HEADER 256 - struct pack_t { int err; // no err(0) invalid seq(1) invalid checksum(2) unsigned long long mac_time; // mac layer 处理时间(us) unsigned long long ip_time; // ip layer 处理时间(us) - //unsigned long long tcp_time; // tcp layer 处理时间(us) - unsigned long long tran_time; // tcp layer 处理时间(us) - unsigned int seq; // the seq num of packet - unsigned int ack; // the ack num of packet + // unsigned long long tcp_time; // tcp layer 处理时间(us) + unsigned long long tran_time; // tcp layer 处理时间(us) + unsigned int seq; // the seq num of packet + unsigned int ack; // the ack num of packet unsigned char data[MAX_HTTP_HEADER]; // 用户层数据 const void *sock; // 此包tcp连接的 socket 指针 int rx; // rx packet(1) or tx packet(0) }; -#endif /* __NETWATCHER_H */ \ No newline at end of file +struct udp_message { + int pid; + unsigned int saddr; + unsigned int daddr; + unsigned short sport; + unsigned short dport; + unsigned long long tran_time; + unsigned long long send; + unsigned long long recv; + unsigned int total; + char comm[20]; + +}; +#endif /* __NETWATCHER_H */ From 21e2c7eedffe53c3e02f0d376e158f7c70113c2f Mon Sep 17 00:00:00 2001 From: wynyibo Date: Thu, 25 Jan 2024 19:00:53 +0800 Subject: [PATCH 5/9] update netwatcher.c --- .../Network_Subsystem/net_watcher/netwatcher.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c index 4de0a04b6..ca19c8857 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c @@ -353,10 +353,6 @@ int main(int argc, char **argv) { fprintf(stderr, "Failed to attach BPF skeleton\n"); goto cleanup; } - /*if (!udp_info) { - printf("%-22s %-10s %-10s %-10s %-10s %-10s %-5s %s\n", "SOCK", "SEQ", - "ACK", "MAC_TIME", "IP_TIME", "TRAN_TIME", "RX", "HTTP"); - }*/ if (udp_info) { printf(" %-15s %-15s %-10s %-10s %-10s \n", "saddr", "daddr", "sprot", "dprot", "udp_time"); @@ -365,12 +361,6 @@ int main(int argc, char **argv) { "sprot", "dprot", "send", "recv", "total"); } - /* else if(http_info) - { - print_conns(skel); - sleep(1); - - }*/ else { printf("%-22s %-10s %-10s %-10s %-10s %-10s %-5s %s\n", "SOCK", "SEQ", "ACK", "MAC_TIME", "IP_TIME", "TRAN_TIME", "RX", "HTTP"); From 4520f06d796dc8c292aab68a82c83f157b206ac6 Mon Sep 17 00:00:00 2001 From: wynyibo Date: Thu, 25 Jan 2024 20:23:50 +0800 Subject: [PATCH 6/9] update --- .../net_watcher/netwatcher.bpf.c | 45 ------------------- .../net_watcher/netwatcher.h | 8 ---- 2 files changed, 53 deletions(-) diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c index bead694d7..0be68e979 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c @@ -46,7 +46,6 @@ struct packet_tuple { unsigned int seq; // seq报文序号 unsigned int ack; // ack确认号 unsigned int tran_flag; // 1:tcp 2:udp -<<<<<<< HEAD }; struct udp_tracing { unsigned int dport; @@ -55,8 +54,6 @@ struct udp_tracing { unsigned int daddr; unsigned long long send; unsigned long long recv; -======= ->>>>>>> 00908ad12044b548bb192576ce0bbdaeaebfd28e }; // 操作BPF映射的一个辅助函数 @@ -125,12 +122,8 @@ struct { const volatile int filter_dport = 0; const volatile int filter_sport = 0; const volatile int all_conn = 0, err_packet = 0, extra_conn_info = 0, -<<<<<<< HEAD layer_time = 0, http_info = 0, retrans_info = 0, udp_info = 0, udp_traffic = 0; -======= - layer_time = 0, http_info = 0, retrans_info = 0, udp_info; ->>>>>>> 00908ad12044b548bb192576ce0bbdaeaebfd28e /* help macro */ @@ -374,21 +367,12 @@ int BPF_KRETPROBE(inet_csk_accept_exit, // 接受tcp连接 CONN_INIT // 初始化conn_t结构中基本信息 conn.is_server = 1; -<<<<<<< HEAD FILTER_DPORT // 过滤目标端口 FILTER_SPORT // 过滤源端口 CONN_ADD_ADDRESS // conn_t结构中增加地址信息 -======= - FILTER_DPORT // 过滤目标端口 - - FILTER_SPORT // 过滤源端口 - - CONN_ADD_ADDRESS // conn_t结构中增加地址信息 - ->>>>>>> 00908ad12044b548bb192576ce0bbdaeaebfd28e // 更新/插入conns_info中的键值对 int err = bpf_map_update_elem(&conns_info, &sk, &conn, BPF_ANY); if (err) { // 更新错误 @@ -436,19 +420,11 @@ int BPF_KRETPROBE(tcp_v4_connect_exit, int ret) { CONN_INIT // 初始化conn_t结构中基本信息 conn.is_server = 0; // 主动连接 -<<<<<<< HEAD FILTER_DPORT // 过滤目标端口 FILTER_SPORT // 过滤源端口 CONN_ADD_ADDRESS // conn_t结构中增加地址信息 -======= - FILTER_DPORT // 过滤目标端口 - - FILTER_SPORT // 过滤源端口 - - CONN_ADD_ADDRESS // conn_t结构中增加地址信息 ->>>>>>> 00908ad12044b548bb192576ce0bbdaeaebfd28e long err = bpf_map_update_elem(&conns_info, &sk, &conn, BPF_ANY); // 更新conns_info中sk对应的conn @@ -486,19 +462,11 @@ int BPF_KRETPROBE(tcp_v6_connect_exit, int ret) { CONN_INIT // 初始化conn_t结构中基本信息 conn.is_server = 0; // 主动连接 -<<<<<<< HEAD FILTER_DPORT // 过滤目标端口 FILTER_SPORT // 过滤源端口 CONN_ADD_ADDRESS // conn_t结构中增加地址信息 -======= - FILTER_DPORT // 过滤目标端口 - - FILTER_SPORT // 过滤源端口 - - CONN_ADD_ADDRESS // conn_t结构中增加地址信息 ->>>>>>> 00908ad12044b548bb192576ce0bbdaeaebfd28e long err = bpf_map_update_elem(&conns_info, &sk, &conn, BPF_ANY); // 更新conns_info中sk对应的conn @@ -1111,15 +1079,9 @@ int BPF_KPROBE(inet6_csk_xmit, struct sock *sk, struct sk_buff *skb) { */ SEC("kprobe/__dev_queue_xmit") int BPF_KPROBE(__dev_queue_xmit, struct sk_buff *skb) { -<<<<<<< HEAD /* if (!layer_time) { return 0; }*/ -======= - if (!layer_time) { - return 0; - } ->>>>>>> 00908ad12044b548bb192576ce0bbdaeaebfd28e // 从skb中读取以太网头部 const struct ethhdr *eth = (struct ethhdr *)BPF_CORE_READ(skb, data); u16 protocol = BPF_CORE_READ( @@ -1284,10 +1246,6 @@ int BPF_KPROBE(udp_rcv, struct sk_buff *skb) { tinfo->tran_time = bpf_ktime_get_ns() / 1000; return 0; } -<<<<<<< HEAD -======= - ->>>>>>> 00908ad12044b548bb192576ce0bbdaeaebfd28e SEC("kprobe/__udp_enqueue_schedule_skb") int BPF_KPROBE(__udp_enqueue_schedule_skb, struct sock *sk, struct sk_buff *skb) { @@ -1325,7 +1283,6 @@ int BPF_KPROBE(__udp_enqueue_schedule_skb, struct sock *sk, bpf_ringbuf_submit(message, 0); return 0; } -<<<<<<< HEAD // kprobe 挂载 udp_sendmsg 函数 SEC("kprobe/udp_sendmsg") @@ -1414,5 +1371,3 @@ int trace_sys_recv_ret(struct pt_regs *ctx) { bpf_ringbuf_submit(data, 0); return 0; } -======= ->>>>>>> 00908ad12044b548bb192576ce0bbdaeaebfd28e diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h index bf1771e18..9287f1ee0 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h @@ -86,16 +86,12 @@ struct pack_t { }; struct udp_message { -<<<<<<< HEAD int pid; -======= ->>>>>>> 00908ad12044b548bb192576ce0bbdaeaebfd28e unsigned int saddr; unsigned int daddr; unsigned short sport; unsigned short dport; unsigned long long tran_time; -<<<<<<< HEAD unsigned long long send; unsigned long long recv; unsigned int total; @@ -103,7 +99,3 @@ struct udp_message { }; #endif /* __NETWATCHER_H */ -======= -}; -#endif /* __NETWATCHER_H */ ->>>>>>> 00908ad12044b548bb192576ce0bbdaeaebfd28e From b9cfbe7c0726da2bbd93ae9152bdbbe230b385a7 Mon Sep 17 00:00:00 2001 From: wynyibo Date: Thu, 25 Jan 2024 20:45:49 +0800 Subject: [PATCH 7/9] del udp_tracing --- .../Network_Subsystem/udp_tracing/Makefile | 114 ------------ .../udp_tracing/udp_tracing.bpf.c | 109 ----------- .../udp_tracing/udp_tracing.c | 172 ------------------ .../udp_tracing/udp_tracing.h | 18 -- 4 files changed, 413 deletions(-) delete mode 100644 eBPF_Supermarket/Network_Subsystem/udp_tracing/Makefile delete mode 100644 eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.bpf.c delete mode 100644 eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.c delete mode 100644 eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.h diff --git a/eBPF_Supermarket/Network_Subsystem/udp_tracing/Makefile b/eBPF_Supermarket/Network_Subsystem/udp_tracing/Makefile deleted file mode 100644 index 723d66589..000000000 --- a/eBPF_Supermarket/Network_Subsystem/udp_tracing/Makefile +++ /dev/null @@ -1,114 +0,0 @@ -# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) -OUTPUT := .output -CLANG ?= clang -LIBBPF_SRC := $(abspath ../libbpf-bootstrap/libbpf/src) -BPFTOOL_SRC := $(abspath ../libbpf-bootstrap/bpftool/src) -LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a) -BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool) -BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool - -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 := ../libbpf-bootstrap/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../../libbpf/include/uapi -I$(dir $(VMLINUX)) -CFLAGS := -g -Wall -ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) - -APPS = udp_tracing - -# 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: $(APPS) - -.PHONY: clean -clean: - $(call msg,CLEAN) - $(Q)rm -rf $(OUTPUT) $(APPS) - -$(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 -$(OUTPUT)/%.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,$@) - -# Generate BPF skeletons -$(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL) - $(call msg,GEN-SKEL,$@) - $(Q)$(BPFTOOL) gen skeleton $< > $@ - -# Build user-space code -$(patsubst %,$(OUTPUT)/%.o,$(APPS)): %.o: %.skel.h - -$(OUTPUT)/%.o: %.c $(wildcard %.h) | $(OUTPUT) - $(call msg,CC,$@) - $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@ - -# Build application binary -$(APPS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT) - $(call msg,BINARY,$@) - $(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lelf -lz -o $@ - -# delete failed targets -.DELETE_ON_ERROR: - -# keep intermediate (.skel.h, .bpf.o, etc) targets -.SECONDARY: - diff --git a/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.bpf.c b/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.bpf.c deleted file mode 100644 index 5f15efd2c..000000000 --- a/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.bpf.c +++ /dev/null @@ -1,109 +0,0 @@ -#include "vmlinux.h" -#include -#include -#include -#include -#include "udp_tracing.h" -#define AF_INET 2 -char LICENSE[] SEC("license") = "Dual BSD/GPL"; - -struct { - __uint(type, BPF_MAP_TYPE_RINGBUF); - __uint(max_entries, 256 * 1024); -} rb SEC(".maps"); -struct { - __uint(type, BPF_MAP_TYPE_LRU_HASH); - __uint(max_entries, 10800); - __type(key, int); - __type(value, struct udp_tracing); -} udp_flow_map SEC(".maps"); - -struct udp_tracing{ - unsigned int dport; - unsigned int sport; - unsigned int saddr; - unsigned int daddr; - unsigned long long send; - unsigned long long recv; -}; - -const volatile int filter_sport = 0; - -#define FILTER_SPORT if(filter_sport){if (sp.port != filter_sport) { return 0; }} -//kprobe 挂载 udp_sendmsg 函数 -SEC("kprobe/udp_sendmsg") -int trace_sys_send(struct pt_regs *ctx) -{ - unsigned int pid=bpf_get_current_pid_tgid();;//获取当前进程pid - u64 tmp =PT_REGS_PARM3_CORE(ctx);// - //struct sock *sock = (struct sock *)PT_REGS_PARM1_CORE(ctx); - struct udp_tracing *st=bpf_map_lookup_elem(&udp_flow_map,&pid);//使用bpf_map_lookup_elem函数查找udp_flow_map中以pid为键的元素 - if(st&&tmp>0)//如果找到对应的元素 - { - st->send+=tmp;//累加 - } - else{ - struct udp_tracing val = {.send = tmp, .recv = 0}; - //bpf_map_update_elem函数将以key为键、recv为值的元素插入到udp_flow_map中,进行更新 - bpf_map_update_elem(&udp_flow_map,&pid,&val,BPF_ANY); - } - return 0; -} - -SEC("kprobe/udp_recvmsg") -int trace_sys_recv(struct pt_regs *ctx) -{ - unsigned int pid=bpf_get_current_pid_tgid(); - //查找pid关联的值 - struct udp_tracing *st=bpf_map_lookup_elem(&udp_flow_map,&pid); - if(!st) - { - return 0; - } - struct sock *sock = (struct sock *)PT_REGS_PARM1_CORE(ctx); - st->daddr = BPF_CORE_READ(sock, __sk_common.skc_daddr); - st->saddr = BPF_CORE_READ(sock, __sk_common.skc_rcv_saddr); - st->sport = BPF_CORE_READ(sock, __sk_common.skc_num); - st->dport = BPF_CORE_READ(sock, __sk_common.skc_dport); - bpf_map_update_elem(&udp_flow_map,&pid,st,BPF_ANY); - bpf_printk("%d",st->daddr); - return 0; -} -SEC("kretprobe/udp_recvmsg") -int trace_sys_recv_ret(struct pt_regs *ctx) -{ - unsigned int total; - unsigned int pid=bpf_get_current_pid_tgid(); - //查找pid关联的值 - struct udp_tracing *st=bpf_map_lookup_elem(&udp_flow_map,&pid); - if(!st) - { - return 0; - } - u64 tmp=PT_REGS_RC(ctx); - if(tmp>0) - { - st->recv+=tmp; - } - else{ - struct udp_tracing val = {.send = tmp, .recv = 0}; - //bpf_map_update_elem函数将以key为键、recv为值的元素插入到udp_flow_map中,进行更新 - bpf_map_update_elem(&udp_flow_map,&pid,&val,BPF_ANY); - } - struct sock *sock = (struct sock *)PT_REGS_PARM1_CORE(ctx); - struct cwnd_data *data; - data = bpf_ringbuf_reserve(&rb, sizeof(*data), 0); - if (!data) - return 0; - data->pid = pid; - bpf_get_current_comm(&(data->comm),sizeof(data->comm)); - data->saddr=st->saddr; - data->daddr=st->daddr; - data->sport=st->sport; - data->dport= st->dport; - data->send=st->send; - data->recv=st->recv; - data->total=st->send+st->recv; - bpf_ringbuf_submit(data, 0); - return 0; -} diff --git a/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.c b/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.c deleted file mode 100644 index 884ab40f2..000000000 --- a/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.c +++ /dev/null @@ -1,172 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "udp_tracing.h" -#include "udp_tracing.skel.h" - -static volatile bool exiting = false; - -int count = 0; -int count_i = 0; -bool verbose = false; - -int sport,dport,sampling,local; - -const char argp_program_doc[] = "Trace time delay in network subsystem \n"; - -static const struct argp_option opts[] = { - { "verbose", 'v', NULL, 0, "Verbose debug output" }, - { "sport", 's', "SPORT", 0, "trace this source port only" }, - { "dport", 'd', "DPORT", 0, "trace this destination port only" }, - { "count", 'c', "COUNT", 0, "count of outputs"}, - { "local", 'l', "LOCAL", 0, "show local connections"}, - - {}, -}; - -static error_t parse_arg(int key, char *arg, struct argp_state *state) -{ - char *end; - switch(key){ - case 'v': - verbose = true; - break; - case 'd': - dport = strtoul(arg,&end,10); - break; - case 's': - sport = strtoul(arg,&end,10); - break; - case 'c': - count = strtoul(arg,&end,10); - break; - case 'l': - local = strtoul(arg,&end,10); - break; - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -static const struct argp argp = { - .options = opts, - .parser = parse_arg, - .doc = argp_program_doc, -}; - -static void sig_handler(int sig) -{ - exiting = true; -} - - -static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) -{ - if (level == LIBBPF_DEBUG && !verbose) - return 0; - return vfprintf(stderr, format, args); -} - -static int handle_event(void *ctx, void *data, size_t data_sz) -{ - const struct cwnd_data *d = data; - char d_str[INET_ADDRSTRLEN]; - char s_str[INET_ADDRSTRLEN]; - int pid=d->pid; - int send=d->send; - int recv=d->recv; - unsigned int saddr=d->saddr; - unsigned int daddr=d->daddr; - unsigned int sport=d->sport; - unsigned int dport=d->dport; - unsigned int total=d->total; - printf("%-10d %-15s %-10d %-10d %-22s %-22s %-10d %-10d %-22d\n",pid,d->comm,send,recv,inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)),inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)),sport,dport,total); - return 0; -} - -int main(int argc, char **argv) -{ - struct ring_buffer *rb = NULL; - struct udp_tracing_bpf *skel; - int err = 0; - - /* Parse command line arguments */ - err = argp_parse(&argp, argc, argv, 0, NULL, NULL); - if (err) - return err; - - libbpf_set_strict_mode(LIBBPF_STRICT_ALL); - /* Set up libbpf errors and debug info callback */ - libbpf_set_print(libbpf_print_fn); - - /* Cleaner handling of Ctrl-C */ - signal(SIGINT, sig_handler); - signal(SIGTERM, sig_handler); - - /* Load and verify BPF application */ - skel = udp_tracing_bpf__open(); - if (!skel) { - fprintf(stderr, "Failed to open and load BPF skeleton\n"); - return 1; - } - - if(sport){ - printf("filter open,sport:%d \n",sport); - skel->rodata->filter_sport = sport; - } - - - /* Load & verify BPF programs */ - err = udp_tracing_bpf__load(skel); - if (err) { - fprintf(stderr, "Failed to load and verify BPF skeleton\n"); - goto cleanup; - } - /* Attach tracepoints */ - err =udp_tracing_bpf__attach(skel); - if (err) { - fprintf(stderr, "Failed to attach BPF skeleton\n"); - goto cleanup; - } - /* Set up ring buffer polling */ - rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, NULL, NULL); - if (!rb) { - err = -1; - fprintf(stderr, "Failed to create ring buffer\n"); - goto cleanup; - } - - /* Process events */ - printf("%-10s %-15s %-10s %-10s %-22s %-22s %-10s %-10s %-22s\n" , - "pid","comm","send","recv","saddr","daddr" ,"sport","sport","total"); - //printf("%-22s %-22s\n","pid" ,"sum" ); - while (!exiting) { - err = ring_buffer__poll(rb, 100 /* timeout, ms */); - /* Ctrl-C will cause -EINTR */ - if (err == -EINTR) { - err = 0; - break; - } - if (err < 0) { - printf("Error polling perf buffer: %d\n", err); - break; - } - if(count != 0 && count_i>=count) - break; - } - -cleanup: - /* Clean up */ - ring_buffer__free(rb); - udp_tracing_bpf__destroy(skel); - - return err < 0 ? -err : 0; -} diff --git a/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.h b/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.h deleted file mode 100644 index f4e339abf..000000000 --- a/eBPF_Supermarket/Network_Subsystem/udp_tracing/udp_tracing.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __UDP_TRACING_H -#define __UDP_TRACING_H - -struct cwnd_data{ - int pid; - unsigned long long send; - unsigned long long recv; - unsigned int saddr; - unsigned int daddr; - unsigned int sport; - unsigned int dport; - unsigned int total; - char comm[20]; - -}; - -#define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0])) -#endif \ No newline at end of file From cb6ccbf56a2abbab09c1951eb78dc4eddaa9c44f Mon Sep 17 00:00:00 2001 From: wynyibo Date: Fri, 26 Jan 2024 11:53:46 +0800 Subject: [PATCH 8/9] udp received packet traffic --- .../net_watcher/netwatcher.bpf.c | 160 ++++-------------- .../net_watcher/netwatcher.c | 77 +++++---- .../net_watcher/netwatcher.h | 10 +- 3 files changed, 77 insertions(+), 170 deletions(-) diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c index 0be68e979..88facf8c2 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c @@ -46,14 +46,7 @@ struct packet_tuple { unsigned int seq; // seq报文序号 unsigned int ack; // ack确认号 unsigned int tran_flag; // 1:tcp 2:udp -}; -struct udp_tracing { - unsigned int dport; - unsigned int sport; - unsigned int saddr; - unsigned int daddr; - unsigned long long send; - unsigned long long recv; + unsigned int len; }; // 操作BPF映射的一个辅助函数 @@ -111,19 +104,11 @@ struct { __type(key, u64); __type(value, struct sock *); } sock_stores SEC(".maps"); -// udp流量 -struct { - __uint(type, BPF_MAP_TYPE_LRU_HASH); - __uint(max_entries, 10800); - __type(key, int); - __type(value, struct udp_tracing); -} udp_flow_map SEC(".maps"); const volatile int filter_dport = 0; const volatile int filter_sport = 0; const volatile int all_conn = 0, err_packet = 0, extra_conn_info = 0, - layer_time = 0, http_info = 0, retrans_info = 0, - udp_info = 0, udp_traffic = 0; + layer_time = 0, http_info = 0, retrans_info = 0, udp_info; /* help macro */ @@ -367,11 +352,11 @@ int BPF_KRETPROBE(inet_csk_accept_exit, // 接受tcp连接 CONN_INIT // 初始化conn_t结构中基本信息 conn.is_server = 1; - FILTER_DPORT // 过滤目标端口 - - FILTER_SPORT // 过滤源端口 + FILTER_DPORT // 过滤目标端口 - CONN_ADD_ADDRESS // conn_t结构中增加地址信息 + FILTER_SPORT // 过滤源端口 + + CONN_ADD_ADDRESS // conn_t结构中增加地址信息 // 更新/插入conns_info中的键值对 int err = bpf_map_update_elem(&conns_info, &sk, &conn, BPF_ANY); @@ -420,11 +405,11 @@ int BPF_KRETPROBE(tcp_v4_connect_exit, int ret) { CONN_INIT // 初始化conn_t结构中基本信息 conn.is_server = 0; // 主动连接 - FILTER_DPORT // 过滤目标端口 + FILTER_DPORT // 过滤目标端口 - FILTER_SPORT // 过滤源端口 + FILTER_SPORT // 过滤源端口 - CONN_ADD_ADDRESS // conn_t结构中增加地址信息 + CONN_ADD_ADDRESS // conn_t结构中增加地址信息 long err = bpf_map_update_elem(&conns_info, &sk, &conn, BPF_ANY); // 更新conns_info中sk对应的conn @@ -462,11 +447,11 @@ int BPF_KRETPROBE(tcp_v6_connect_exit, int ret) { CONN_INIT // 初始化conn_t结构中基本信息 conn.is_server = 0; // 主动连接 - FILTER_DPORT // 过滤目标端口 + FILTER_DPORT // 过滤目标端口 - FILTER_SPORT // 过滤源端口 + FILTER_SPORT // 过滤源端口 - CONN_ADD_ADDRESS // conn_t结构中增加地址信息 + CONN_ADD_ADDRESS // conn_t结构中增加地址信息 long err = bpf_map_update_elem(&conns_info, &sk, &conn, BPF_ANY); // 更新conns_info中sk对应的conn @@ -912,10 +897,12 @@ int BPF_KRETPROBE(__skb_checksum_complete_exit, int ret) { */ SEC("kprobe/tcp_sendmsg") // 跟踪tcp发送包信息 int BPF_KPROBE(tcp_sendmsg, struct sock *sk, struct msghdr *msg, size_t size) { + struct conn_t *conn = bpf_map_lookup_elem(&conns_info, &sk); if (conn == NULL) { return 0; } + u16 family = BPF_CORE_READ(sk, __sk_common.skc_family); struct ktime_info *tinfo, zero = {0}; // 存储时间 struct packet_tuple pkt_tuple = {0}; // 存储数据包信息 @@ -979,10 +966,7 @@ int BPF_KPROBE(tcp_sendmsg, struct sock *sk, struct msghdr *msg, size_t size) { CONN_ADD_EXTRA_INFO // TX HTTP info - if (!udp_info) { - return 0; - } - if (http_info) { + if (http_info&&udp_info) { unsigned char *user_data = BPF_CORE_READ(msg, msg_iter.iov, iov_base); tinfo = (struct ktime_info *)bpf_map_lookup_or_try_init( ×tamps, &pkt_tuple, &zero); @@ -1036,7 +1020,7 @@ tcp)获取ip段的数据 out only ipv6 */ SEC("kprobe/inet6_csk_xmit") int BPF_KPROBE(inet6_csk_xmit, struct sock *sk, struct sk_buff *skb) { - if (!udp_info) { + if (!layer_time) { return 0; } u16 family = BPF_CORE_READ(sk, __sk_common.skc_family); @@ -1079,9 +1063,9 @@ int BPF_KPROBE(inet6_csk_xmit, struct sock *sk, struct sk_buff *skb) { */ SEC("kprobe/__dev_queue_xmit") int BPF_KPROBE(__dev_queue_xmit, struct sk_buff *skb) { - /* if (!layer_time) { - return 0; - }*/ + if (!layer_time) { + return 0; + } // 从skb中读取以太网头部 const struct ethhdr *eth = (struct ethhdr *)BPF_CORE_READ(skb, data); u16 protocol = BPF_CORE_READ( @@ -1236,7 +1220,7 @@ int BPF_KPROBE(udp_rcv, struct sk_buff *skb) { struct packet_tuple pkt_tuple = {0}; get_udp_pkt_tuple(&pkt_tuple, ip, udp); - + struct ktime_info *tinfo, zero = {0}; tinfo = (struct ktime_info *)bpf_map_lookup_or_try_init(×tamps, &pkt_tuple, &zero); @@ -1246,9 +1230,12 @@ int BPF_KPROBE(udp_rcv, struct sk_buff *skb) { tinfo->tran_time = bpf_ktime_get_ns() / 1000; return 0; } + SEC("kprobe/__udp_enqueue_schedule_skb") int BPF_KPROBE(__udp_enqueue_schedule_skb, struct sock *sk, struct sk_buff *skb) { + if (!udp_info) + return 0; if (skb == NULL) // 判断是否为空 return 0; struct iphdr *ip = skb_to_iphdr(skb); @@ -1260,7 +1247,13 @@ int BPF_KPROBE(__udp_enqueue_schedule_skb, struct sock *sk, pkt_tuple.dport = BPF_CORE_READ(sk, __sk_common.skc_num); pkt_tuple.sport = __bpf_ntohs(dport); pkt_tuple.tran_flag = 2; - + int total=0; + int len=__bpf_ntohs(BPF_CORE_READ(udp,len));//网络字节序转换成主机字节序 + if(total) + { + total+=len; + } + pkt_tuple.len=total; struct ktime_info *tinfo, zero = {0}; tinfo = bpf_map_lookup_elem(×tamps, &pkt_tuple); if (tinfo == NULL) { @@ -1279,95 +1272,8 @@ int BPF_KPROBE(__udp_enqueue_schedule_skb, struct sock *sk, message->daddr = BPF_CORE_READ(sk, __sk_common.skc_daddr); message->sport = BPF_CORE_READ(sk, __sk_common.skc_num); message->dport = BPF_CORE_READ(sk, __sk_common.skc_dport); - - bpf_ringbuf_submit(message, 0); - return 0; -} - -// kprobe 挂载 udp_sendmsg 函数 -SEC("kprobe/udp_sendmsg") -int trace_sys_send(struct pt_regs *ctx) { - int time; - unsigned int pid = bpf_get_current_pid_tgid(); - ; // 获取当前进程pid - u64 tmp = PT_REGS_PARM3_CORE(ctx); // 获取发送数据的大小 - // struct sock *sock = (struct sock *)PT_REGS_PARM1_CORE(ctx); - struct udp_tracing *st = bpf_map_lookup_elem( - &udp_flow_map, - &pid); // 使用bpf_map_lookup_elem函数查找udp_flow_map中以pid为键的元素 - if (st && tmp > 0) // 如果找到对应的元素 - { - st->send += tmp; // 累加 - } else { - struct udp_tracing val = {.send = tmp, .recv = 0}; - // bpf_map_update_elem函数将以key为键、recv为值的元素插入到udp_flow_map中,进行更新 - bpf_map_update_elem(&udp_flow_map, &pid, &val, BPF_ANY); - } - struct packet_tuple pkt_tuple = {0}; - struct ktime_info *tinfo; - struct udp_message *message; - struct udp_message *udp_message = - bpf_map_lookup_elem(×tamps, &pkt_tuple); - ; - message = bpf_ringbuf_reserve(&udp_rb, sizeof(*message), 0); - if (!message) { - return 0; - } - message->tran_time = bpf_ktime_get_ns() / 1000 - tinfo->tran_time; - + message->rx=0;//收包 + message->len=__bpf_ntohs(BPF_CORE_READ(udp,len)); bpf_ringbuf_submit(message, 0); return 0; -} - -SEC("kprobe/udp_recvmsg") -int trace_sys_recv(struct pt_regs *ctx) { - unsigned int pid = bpf_get_current_pid_tgid(); - struct udp_tracing *st = bpf_map_lookup_elem(&udp_flow_map, &pid); - if (!st) { - return 0; - } - struct sock *sock = (struct sock *)PT_REGS_PARM1_CORE(ctx); - st->daddr = BPF_CORE_READ(sock, __sk_common.skc_daddr); - st->saddr = BPF_CORE_READ(sock, __sk_common.skc_rcv_saddr); - st->sport = BPF_CORE_READ(sock, __sk_common.skc_num); - st->dport = BPF_CORE_READ(sock, __sk_common.skc_dport); - bpf_map_update_elem(&udp_flow_map, &pid, st, BPF_ANY); - bpf_printk("%d", st->daddr); - return 0; -} - -SEC("kretprobe/udp_recvmsg") -int trace_sys_recv_ret(struct pt_regs *ctx) { - struct packet_tuple pkt_tuple = {0}; - pkt_tuple.tran_flag = 2; - unsigned int total; - unsigned int pid = bpf_get_current_pid_tgid(); - // 查找pid关联的值 - struct udp_tracing *st = bpf_map_lookup_elem(&udp_flow_map, &pid); - if (!st) { - return 0; - } - u64 tmp = PT_REGS_RC(ctx); - if (tmp > 0) { - st->recv += tmp; - } else { - struct udp_tracing val = {.send = tmp, .recv = 0}; - // bpf_map_update_elem函数将以key为键、recv为值的元素插入到udp_flow_map中,进行更新 - bpf_map_update_elem(&udp_flow_map, &pid, &val, BPF_ANY); - } - struct sock *sock = (struct sock *)PT_REGS_PARM1_CORE(ctx); - struct udp_message *data; - data = bpf_ringbuf_reserve(&udp_rb, sizeof(*data), 0); - if (!data) - return 0; - bpf_get_current_comm(&(data->comm), sizeof(data->comm)); - data->saddr = st->saddr; - data->daddr = st->daddr; - data->sport = st->sport; - data->dport = st->dport; - data->send = st->send; - data->recv = st->recv; - data->total = st->send + st->recv; - bpf_ringbuf_submit(data, 0); - return 0; -} +} \ No newline at end of file diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c index ca19c8857..e19881110 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c @@ -35,11 +35,11 @@ static volatile bool exiting = false; static char connects_file_path[1024]; static char err_file_path[1024]; static char packets_file_path[1024]; +static char udp_file_path[1024]; static int sport = 0, dport = 0; // for filter static int all_conn = 0, err_packet = 0, extra_conn_info = 0, layer_time = 0, - http_info = 0, retrans_info = 0, udp_info = 0, - udp_traffic = 0; // flag + http_info = 0, retrans_info = 0, udp_info; // flag static const char argp_program_doc[] = "Watch tcp/ip in network subsystem \n"; @@ -53,7 +53,6 @@ static const struct argp_option opts[] = { {"sport", 's', "SPORT", 0, "trace this source port only"}, {"dport", 'd', "DPORT", 0, "trace this destination port only"}, {"udp", 'u', 0, 0, "trace the udp message"}, - {"udp_traffic", 'c', 0, 0, "trace the udp traffic"}, {}}; static error_t parse_arg(int key, char *arg, struct argp_state *state) { @@ -86,9 +85,6 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) { case 'u': udp_info = 1; break; - case 'c': - udp_traffic = 1; - break; default: return ARGP_ERR_UNKNOWN; } @@ -204,7 +200,7 @@ static int print_conns(struct netwatcher_bpf *skel) { } static int print_packet(void *ctx, void *packet_info, size_t size) { - if (udp_info || udp_traffic) + if (udp_info) return 0; const struct pack_t *pack_info = packet_info; if (pack_info->err) { @@ -272,28 +268,35 @@ static int print_packet(void *ctx, void *packet_info, size_t size) { return 0; } static int print_udp(void *ctx, void *packet_info, size_t size) { + if (!udp_info) + return 0; + FILE *file = fopen(udp_file_path, "a+");//追加 + if (file == NULL) { + fprintf(stderr, "Failed to open udp.log: (%s)\n", strerror(errno)); + return 0; + } char d_str[INET_ADDRSTRLEN]; char s_str[INET_ADDRSTRLEN]; const struct udp_message *pack_info = packet_info; unsigned int saddr = pack_info->saddr; unsigned int daddr = pack_info->daddr; - int send = pack_info->send; - int recv = pack_info->recv; - unsigned int total = pack_info->total; - if (daddr) { - if (udp_info && pack_info->tran_time) { - printf("%-15s %-15s %-10u %-10u %-10llu \n", - inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), - inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), - pack_info->sport, pack_info->dport, pack_info->tran_time); - - } else if (udp_traffic) { - printf("%-15s %-15s %-10u %-10u %-10d %-10d %-10d\n", - inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), - inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), - pack_info->sport, pack_info->dport, send, recv, total); - } + if(udp_info) + { + printf("%-20s %-20s %-20u %-20u %-20llu %-20d %-20d\n", + inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), + inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), pack_info->sport, + pack_info->dport, pack_info->tran_time,pack_info->rx,pack_info->len); + fprintf( + file, + "packet{saddr=\"%s\",daddr=\"%s\",sport=\"%u\"," + "dport=\"%u\",udp_time=\"%llu\",rx=\"%d\",len=\"%d\"} \n", + inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), + inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), pack_info->sport, + pack_info->dport, pack_info->tran_time,pack_info->rx,pack_info->len); + //fseek(file, 0, SEEK_END); //指针移动到文件头部 } + + fclose(file); return 0; } int main(int argc, char **argv) { @@ -304,9 +307,11 @@ int main(int argc, char **argv) { strcpy(connects_file_path, argv[0]); strcpy(err_file_path, argv[0]); strcpy(packets_file_path, argv[0]); + strcpy(udp_file_path, argv[0]); strcat(connects_file_path, "data/connects.log"); strcat(err_file_path, "data/err.log"); strcat(packets_file_path, "data/packets.log"); + strcat(udp_file_path,"data/udp.log"); struct ring_buffer *rb = NULL; struct ring_buffer *udp_rb = NULL; struct netwatcher_bpf *skel; @@ -339,7 +344,6 @@ int main(int argc, char **argv) { skel->rodata->http_info = http_info; skel->rodata->retrans_info = retrans_info; skel->rodata->udp_info = udp_info; - skel->rodata->udp_traffic = udp_traffic; err = netwatcher_bpf__load(skel); if (err) { @@ -353,20 +357,15 @@ int main(int argc, char **argv) { fprintf(stderr, "Failed to attach BPF skeleton\n"); goto cleanup; } - if (udp_info) { - printf(" %-15s %-15s %-10s %-10s %-10s \n", "saddr", "daddr", "sprot", - "dprot", "udp_time"); - } else if (udp_traffic) { - printf(" %-15s %-15s %-10s %-10s %-10s %-10s %-10s\n", "saddr", "daddr", - "sprot", "dprot", "send", "recv", "total"); - - } - else { + if (!udp_info) { printf("%-22s %-10s %-10s %-10s %-10s %-10s %-5s %s\n", "SOCK", "SEQ", "ACK", "MAC_TIME", "IP_TIME", "TRAN_TIME", "RX", "HTTP"); } - udp_rb = - ring_buffer__new(bpf_map__fd(skel->maps.udp_rb), print_udp, NULL, NULL); + if (udp_info) { + printf("%-20s %-20s %-20s %-20s %-20s %-20s %-20s\n", "saddr", "daddr", "sprot", + "dprot", "udp_time","rx","len"); + } + udp_rb =ring_buffer__new(bpf_map__fd(skel->maps.udp_rb), print_udp, NULL, NULL); if (!udp_rb) { err = -1; fprintf(stderr, "Failed to create ring buffer\n"); @@ -391,6 +390,12 @@ int main(int argc, char **argv) { return 0; } fclose(packet_file); + FILE *udp_file = fopen(udp_file_path, "w+"); + if (udp_file == NULL) { + fprintf(stderr, "Failed to open udp.log: (%s)\n", strerror(errno)); + return 0; + } + fclose(udp_file); /* Process events */ while (!exiting) { @@ -412,4 +417,4 @@ int main(int argc, char **argv) { cleanup: netwatcher_bpf__destroy(skel); return err < 0 ? -err : 0; -} \ No newline at end of file +} diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h index 9287f1ee0..a0902679f 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h @@ -86,16 +86,12 @@ struct pack_t { }; struct udp_message { - int pid; unsigned int saddr; unsigned int daddr; unsigned short sport; unsigned short dport; unsigned long long tran_time; - unsigned long long send; - unsigned long long recv; - unsigned int total; - char comm[20]; - + int rx; + int len; }; -#endif /* __NETWATCHER_H */ +#endif /* __NETWATCHER_H */ \ No newline at end of file From 6b0241e39c35374fb1434cbd9cd4248269df83e6 Mon Sep 17 00:00:00 2001 From: wynyibo <147615158+wynyibo@users.noreply.github.com> Date: Fri, 26 Jan 2024 13:53:44 +0800 Subject: [PATCH 9/9] netwatcher.bpf.c --- .../Network_Subsystem/net_watcher/netwatcher.bpf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c index 88facf8c2..b88721bfc 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c @@ -1247,13 +1247,13 @@ int BPF_KPROBE(__udp_enqueue_schedule_skb, struct sock *sk, pkt_tuple.dport = BPF_CORE_READ(sk, __sk_common.skc_num); pkt_tuple.sport = __bpf_ntohs(dport); pkt_tuple.tran_flag = 2; - int total=0; + /* int total=0; int len=__bpf_ntohs(BPF_CORE_READ(udp,len));//网络字节序转换成主机字节序 if(total) { total+=len; } - pkt_tuple.len=total; + pkt_tuple.len=total;*/ struct ktime_info *tinfo, zero = {0}; tinfo = bpf_map_lookup_elem(×tamps, &pkt_tuple); if (tinfo == NULL) { @@ -1276,4 +1276,4 @@ int BPF_KPROBE(__udp_enqueue_schedule_skb, struct sock *sk, message->len=__bpf_ntohs(BPF_CORE_READ(udp,len)); bpf_ringbuf_submit(message, 0); return 0; -} \ No newline at end of file +}