From 77612fba42c9843f194c362e3d7d6f0598c99302 Mon Sep 17 00:00:00 2001 From: Jiping Yin Date: Tue, 15 Oct 2024 15:42:55 +0800 Subject: [PATCH] feat: agent - eBPF Support RT kernel (#8301) --- agent/src/ebpf/Makefile | 7 +- agent/src/ebpf/kernel/Makefile | 2 + agent/src/ebpf/kernel/include/socket_trace.h | 127 +++++++++++++++---- agent/src/ebpf/user/socket.c | 8 +- agent/src/ebpf/user/socket.h | 1 + agent/src/ebpf/user/tracer.c | 5 + agent/src/ebpf/user/tracer.h | 1 + 7 files changed, 124 insertions(+), 27 deletions(-) diff --git a/agent/src/ebpf/Makefile b/agent/src/ebpf/Makefile index 00fab263a51..8cb2710a2a3 100644 --- a/agent/src/ebpf/Makefile +++ b/agent/src/ebpf/Makefile @@ -143,7 +143,8 @@ SOCKET_TRACE_ELFS := user/socket_trace_bpf_common.c \ user/socket_trace_bpf_3_10_0.c \ user/socket_trace_bpf_5_2_plus.c \ user/socket_trace_bpf_kfunc.c \ - user/socket_trace_bpf_kylin.c + user/socket_trace_bpf_kylin.c \ + user/socket_trace_bpf_rt.c PERF_PROFILER_ELFS := user/perf_profiler_bpf_common.c \ user/perf_profiler_bpf_5_2_plus.c \ @@ -182,6 +183,10 @@ user/socket_trace_bpf_kylin.c: tools/bintobuffer kernel/socket_trace.bpf.c $(call check_clang) $(call compile_socket_trace_elf, kylin, LINUX_VER_KYLIN=1) +user/socket_trace_bpf_rt.c: tools/bintobuffer kernel/socket_trace.bpf.c + $(call check_clang) + $(call compile_socket_trace_elf, rt, LINUX_VER_RT=1) + user/perf_profiler_bpf_common.c: tools/bintobuffer kernel/perf_profiler.bpf.c $(call check_clang) $(call compile_perf_profiler_elf, common) diff --git a/agent/src/ebpf/kernel/Makefile b/agent/src/ebpf/kernel/Makefile index dbb149a7569..64f42583dcb 100644 --- a/agent/src/ebpf/kernel/Makefile +++ b/agent/src/ebpf/kernel/Makefile @@ -40,6 +40,8 @@ else ifeq ($(LINUX_VER_KYLIN),1) EXTRA_EBPF_CLAGS = -DLINUX_VER_KYLIN else ifeq ($(LINUX_VER_KFUNC),1) EXTRA_EBPF_CLAGS = -DLINUX_VER_KFUNC +else ifeq ($(LINUX_VER_RT),1) + EXTRA_EBPF_CLAGS = -DLINUX_VER_RT endif FINAL_TARGET = -emit-llvm -D__TARGET_ARCH_$(ARCH) -o ${@:.elf=.ll} -c $^ && $(LLC) -march=bpf -filetype=obj -mcpu=v2 -o $@ ${@:.elf=.ll} diff --git a/agent/src/ebpf/kernel/include/socket_trace.h b/agent/src/ebpf/kernel/include/socket_trace.h index 14c940279a1..822b4d23790 100644 --- a/agent/src/ebpf/kernel/include/socket_trace.h +++ b/agent/src/ebpf/kernel/include/socket_trace.h @@ -181,14 +181,14 @@ struct conn_info_s { // The protocol of traffic on the connection (HTTP, MySQL, etc.). enum traffic_protocol protocol; // MSG_UNKNOWN, MSG_REQUEST, MSG_RESPONSE - __u32 message_type: 4; + __u32 message_type:4; // Is this segment of data reassembled? - __u32 is_reasm_seg: 1; - __u32 no_trace: 1; /* When set to 1 (or true), tracing will not be performed. */ - __u32 reserved: 26; + __u32 is_reasm_seg:1; + __u32 no_trace:1; /* When set to 1 (or true), tracing will not be performed. */ + __u32 reserved:26; union { - __u8 encoding_type; // Currently used for OpenWire encoding inference + __u8 encoding_type; // Currently used for OpenWire encoding inference __s32 correlation_id; // Currently used for Kafka determination }; __u32 prev_count; // Prestored data length @@ -229,12 +229,12 @@ struct tail_calls_context { * private data. */ char private_data[sizeof(struct infer_data_s)]; - int max_size_limit; // The maximum size of the socket data that can be transferred. + int max_size_limit; // The maximum size of the socket data that can be transferred. __u32 push_reassembly_bytes; // The number of bytes pushed after enabling data reassembly. enum traffic_direction dir; // Data flow direction. - __u8 vecs: 1; // Whether a memory vector is used ? (for specific syscall) - __u8 is_close: 1; // Is it a close() systemcall ? - __u8 reserve: 6; + __u8 vecs:1; // Whether a memory vector is used ? (for specific syscall) + __u8 is_close:1; // Is it a close() systemcall ? + __u8 reserve:6; struct conn_info_s conn_info; struct process_data_extra extra; __u32 bytes_count; @@ -283,8 +283,8 @@ struct data_args_t { }; union { - __u64 socket_id; // Use for socket close - __u64 enter_ts; // Timestamp for enter syscall function. + __u64 socket_id; // Use for socket close + __u64 enter_ts; // Timestamp for enter syscall function. }; __u32 tcp_seq; // Used to record the entry of syscalls @@ -298,6 +298,26 @@ struct data_args_t { } __attribute__ ((packed)); struct syscall_comm_enter_ctx { +#ifdef LINUX_VER_RT + __u64 __pad_0; /* 0 8 */ + unsigned char common_migrate_disable; /* 8 1 */ + unsigned char common_preempt_lazy_count; /* 9 1 */ + int __syscall_nr; /* offset:12 4 */ + union { + struct { + __u64 fd; /* offset:16 8 */ + char *buf; /* offset:24 8 */ + }; + + // For clock_gettime() + struct { + clockid_t which_clock; /* offset:16 4 */ + struct timespec *tp; /* offset:24 8 */ + }; + }; + size_t count; /* 32 8 */ + unsigned int flags; +#else __u64 __pad_0; /* 0 8 */ int __syscall_nr; /* offset:8 4 */ __u32 __pad_1; /* 12 4 */ @@ -309,53 +329,110 @@ struct syscall_comm_enter_ctx { // For clock_gettime() struct { - clockid_t which_clock; /* offset:16 8 */ + clockid_t which_clock; /* offset:16 4 */ struct timespec *tp; /* offset:24 8 */ }; }; size_t count; /* 32 8 */ unsigned int flags; +#endif }; struct sched_comm_exit_ctx { +#ifdef LINUX_VER_RT + __u64 __pad_0; /* 0 8 */ + unsigned char common_migrate_disable; /* 8 1 */ + unsigned char common_preempt_lazy_count; /* 9 1 */ + unsigned short padding; + char comm[16]; /* 12 16 */ + + pid_t pid; /* 28 4 */ + int prio; /* 32 4 */ +#else __u64 __pad_0; /* 0 8 */ char comm[16]; /* offset:8; size:16 */ pid_t pid; /* offset:24; size:4 */ int prio; /* offset:28; size:4 */ +#endif }; struct syscall_sendto_enter_ctx { +#ifdef LINUX_VER_RT + __u64 __pad_0; /* 0 8 */ + unsigned char common_migrate_disable; /* 8 1 */ + unsigned char common_preempt_lazy_count; /* 9 1 */ + + int __syscall_nr; /* 12 4 */ + int fd; /* 16 4 */ + + void *buff; /* 24 8 */ + size_t len; /* 32 8 */ + unsigned int flags; /* 40 4 */ + + struct sockaddr *addr; /* 48 8 */ + int addr_len; /* 56 4 */ +#else __u64 __pad_0; - int __syscall_nr; // offset:8 size:4 - __u32 __pad_1; // offset:12 size:4 - int fd; //offset:16; size:8; signed:0; - void * buff; //offset:24; size:8; signed:0; - size_t len; //offset:32; size:8; signed:0; - unsigned int flags; //offset:40; size:8; signed:0; - struct sockaddr * addr; //offset:48; size:8; signed:0; - int addr_len; //offset:56; size:8; signed:0; + int __syscall_nr; // offset:8 size:4 + __u32 __pad_1; // offset:12 size:4 + int fd; //offset:16; size:8; signed:0; + void *buff; //offset:24; size:8; signed:0; + size_t len; //offset:32; size:8; signed:0; + unsigned int flags; //offset:40; size:8; signed:0; + struct sockaddr *addr; //offset:48; size:8; signed:0; + int addr_len; //offset:56; size:8; signed:0; +#endif }; struct sched_comm_fork_ctx { - __u64 __pad_0; - char parent_comm[16]; - __u32 parent_pid; - char child_comm[16]; - __u32 child_pid; +#ifdef LINUX_VER_RT + __u64 __pad_0; /* 0 8 */ + unsigned char common_migrate_disable; /* 8 1 */ + unsigned char common_preempt_lazy_count; /* 9 1 */ + unsigned short padding; + char parent_comm[16]; /* 12 16 */ + + __u32 parent_pid; /* 28 4 */ + char child_comm[16]; /* 32 16 */ + __u32 child_pid; /* 48 4 */ +#else + __u64 __pad_0; /* 0 8 */ + char parent_comm[16]; /* 8 16 */ + __u32 parent_pid; /* 24 4 */ + char child_comm[16]; /* 28 16 */ + __u32 child_pid; /* 44 4 */ +#endif }; struct sched_comm_exec_ctx { +#ifdef LINUX_VER_RT + __u64 __pad_0; /* 0 8 */ + unsigned char common_migrate_disable; /* 8 1 */ + unsigned char common_preempt_lazy_count; /* 9 1 */ + int __data_loc; /* offset:12 4 */ + __u32 pid; /* offset:16 4 */ + __u32 old_pid; /* offset:20 4 */ +#else __u64 __pad_0; /* 0 8 */ int __data_loc; /* offset:8 4 */ __u32 pid; /* offset:12 4 */ __u32 old_pid; /* offset:16 4 */ +#endif }; struct syscall_comm_exit_ctx { +#ifdef LINUX_VER_RT + __u64 __pad_0; /* 0 8 */ + unsigned char common_migrate_disable; /* 8 1 */ + unsigned char common_preempt_lazy_count; /* 9 1 */ + int __syscall_nr; /* offset:12 4 */ + __u64 ret; /* offset:16 8 */ +#else __u64 __pad_0; /* 0 8 */ int __syscall_nr; /* offset:8 4 */ __u32 __pad_1; /* 12 4 */ __u64 ret; /* offset:16 8 */ +#endif }; static __inline __u64 gen_conn_key_id(__u64 param_1, __u64 param_2) diff --git a/agent/src/ebpf/user/socket.c b/agent/src/ebpf/user/socket.c index e2a6f0477ae..76afa6c1170 100644 --- a/agent/src/ebpf/user/socket.c +++ b/agent/src/ebpf/user/socket.c @@ -45,6 +45,7 @@ #include "socket_trace_bpf_5_2_plus.c" #include "socket_trace_bpf_kylin.c" #include "socket_trace_bpf_kfunc.c" +#include "socket_trace_bpf_rt.c" static enum linux_kernel_type g_k_type; static struct list_head events_list; // Use for extra register events @@ -2055,7 +2056,12 @@ static int select_bpf_binary(char load_name[NAME_LEN], void **bin_buffer, ebpf_warning("Fetch system type faild.\n"); } - if (!skip_kfunc && fentry_can_attach(TEST_KFUNC_NAME) + if (is_rt_kernel()) { + g_k_type = K_TYPE_RT; + snprintf(load_name, NAME_LEN, "socket-trace-bpf-linux-rt"); + bpf_bin_buffer = (void *)socket_trace_rt_ebpf_data; + buffer_sz = sizeof(socket_trace_rt_ebpf_data); + } else if (!skip_kfunc && fentry_can_attach(TEST_KFUNC_NAME) && get_kfunc_params_num(TEST_KFUNC_NAME) == TEST_KFUNC_PARAMS_NUM) { g_k_type = K_TYPE_KFUNC; snprintf(load_name, NAME_LEN, "socket-trace-bpf-linux-kfunc"); diff --git a/agent/src/ebpf/user/socket.h b/agent/src/ebpf/user/socket.h index 8db634656c7..78a739f1da8 100644 --- a/agent/src/ebpf/user/socket.h +++ b/agent/src/ebpf/user/socket.h @@ -48,6 +48,7 @@ enum linux_kernel_type { K_TYPE_VER_5_2_PLUS, K_TYPE_VER_3_10, K_TYPE_KFUNC, + K_TYPE_RT, }; enum probes_act_type { diff --git a/agent/src/ebpf/user/tracer.c b/agent/src/ebpf/user/tracer.c index 27d301a0c1c..f562be92553 100644 --- a/agent/src/ebpf/user/tracer.c +++ b/agent/src/ebpf/user/tracer.c @@ -2138,6 +2138,11 @@ int bpf_tracer_init(const char *log_file, bool is_stdout) return ETR_OK; } +bool is_rt_kernel(void) +{ + return (strstr(linux_release, ".rt") || strstr(linux_release, "-rt")); +} + void bpf_tracer_finish(void) { all_probes_ready = 1; diff --git a/agent/src/ebpf/user/tracer.h b/agent/src/ebpf/user/tracer.h index 80ebfdd22fd..71efbbf9b4c 100644 --- a/agent/src/ebpf/user/tracer.h +++ b/agent/src/ebpf/user/tracer.h @@ -678,6 +678,7 @@ void free_all_readers(struct bpf_tracer *t); int enable_tracer_reader_work(const char *name, int idx, struct bpf_tracer *tracer, void *fn); +bool is_rt_kernel(void); /** * @brief Enable eBPF segmentation reassembly for the specified protocol. *