소스 검색

Fixed #TASK_QT-9810 Network 调试

roger.wang 1 년 전
부모
커밋
bc74581a7b
2개의 변경된 파일236개의 추가작업 그리고 7개의 파일을 삭제
  1. 223 0
      ebpftracer/ebpf/tcp/state.c
  2. 13 7
      ebpftracer/tracer.go

+ 223 - 0
ebpftracer/ebpf/tcp/state.c

@@ -73,6 +73,25 @@ struct connection {
     __u64 bytes_received;
 };
 
+// char* get_tcp_state_name(int state_number) {  
+//     switch (state_number) {  
+//         case 1: return "BPF_TCP_ESTABLISHED";  
+//         case 2: return "BPF_TCP_SYN_SENT";  
+//         case 3: return "BPF_TCP_SYN_RECV";  
+//         case 4: return "BPF_TCP_FIN_WAIT1";  
+//         case 5: return "BPF_TCP_FIN_WAIT2";  
+//         case 6: return "BPF_TCP_TIME_WAIT";  
+//         case 7: return "BPF_TCP_CLOSE";  
+//         case 8: return "BPF_TCP_CLOSE_WAIT";  
+//         case 9: return "BPF_TCP_LAST_ACK";  
+//         case 10: return "BPF_TCP_LISTEN";  
+//         case 11: return "BPF_TCP_CLOSING";  
+//         case 12: return "BPF_TCP_NEW_SYN_RECV";  
+//         case 13: return "BPF_TCP_MAX_STATES";  
+//         default: return "Unknown State";  
+//     }  
+// }
+
 struct {
     __uint(type, BPF_MAP_TYPE_LRU_HASH);
     __uint(key_size, sizeof(struct connection_id));
@@ -93,6 +112,8 @@ int inet_sock_set_state(void *ctx)
     }
     __u64 id = bpf_get_current_pid_tgid();
     __u32 pid = id >> 32;
+    cw_bpf_debug("socket inet_sock_set_state oldstate=%d --> newstate=%d\n", args.oldstate, args.newstate);
+    // cw_bpf_debug("socket inet_sock_set_state oldstate=%s --> newstate=%s\n", get_tcp_state_name(args.oldstate), get_tcp_state_name(args.newstate));
 
     if (args.oldstate == BPF_TCP_CLOSE && args.newstate == BPF_TCP_SYN_SENT) {
         __u64 *fdp = bpf_map_lookup_elem(&fd_by_pid_tgid, &id);
@@ -152,6 +173,40 @@ int inet_sock_set_state(void *ctx)
         type = EVENT_TYPE_LISTEN_CLOSE;
         map = &tcp_listen_events;
     }
+    if (args.oldstate == BPF_TCP_SYN_RECV && args.newstate == BPF_TCP_ESTABLISHED) {
+        // __u64 *fdp = bpf_map_lookup_elem(&fd_by_pid_tgid, &id);
+        __u64 id2 = bpf_get_current_pid_tgid();
+        cw_bpf_debug("socket inet_sock_set_state entry tgid %d\n", id2);
+        // if (!fdp) {
+        //     cw_bpf_debug("socket inet_sock_set_state no fd %d\n", id);
+        //     return 0;
+        // }
+        // cw_bpf_debug("socket inet_sock_set_state Connection accepted: fd=%d\n", *fdp);
+        // bpf_map_delete_elem(&fd_by_pid_tgid, &id);
+        struct SOCK_TUPLE {
+            char     laddr[16];
+            char     raddr[16];
+            uint16_t sport;
+            uint16_t dport;
+            uint8_t  proto;
+        };
+        // struct sock *sock = (struct sock *)BPF_CORE_READ(args, skaddr);
+        struct sock *sock = (struct sock *)args.skaddr;
+        __u64 hash;
+        bpf_probe_read(&hash, sizeof(hash), &sock->__sk_common.skc_hash);
+        struct SOCK_TUPLE stuple = {};  
+        // bpf_probe_read_kernel(stuple->laddr, sizeof(args->saddr), BPF_CORE_READ(args, saddr));
+        // bpf_probe_read_kernel(stuple->raddr, sizeof(args->daddr), BPF_CORE_READ(args, daddr));
+        __builtin_memcpy(&stuple.laddr, &args.saddr, sizeof(stuple.laddr));
+        __builtin_memcpy(&stuple.raddr, &args.daddr, sizeof(stuple.raddr));
+        // stuple->lport = BPF_CORE_READ(args, sport);
+        // stuple->rport = BPF_CORE_READ(args, dport);
+        stuple.sport = args.sport;
+        stuple.dport = args.dport;
+        cw_bpf_debug("socket inet_sock_set_state Connection accepted: sk=%x, %lld\n", sock, hash);
+        cw_bpf_debug("socket inet_sock_set_state Connection accepted: dport=%d, lport=%d\n", stuple.sport, stuple.dport);
+        cw_bpf_debug("socket inet_sock_set_state Connection accepted: saddr=%s, daddr=%s\n", stuple.laddr, stuple.raddr);
+    }
 
     if (type == 0) {
         return 0;
@@ -232,3 +287,171 @@ int sys_enter_close(void *ctx) {
     }
     return 0;
 }
+
+void u32_to_ip(__u32 ip) {  
+    // 将32位整数拆分为四个8位整数  
+    unsigned char bytes[4];  
+    bytes[0] = (ip >> 24) & 0xFF;  
+    bytes[1] = (ip >> 16) & 0xFF;  
+    bytes[2] = (ip >> 8) & 0xFF;  
+    bytes[3] = ip & 0xFF;  
+
+    // 使用sprintf将这些整数格式化为字符串  
+    cw_bpf_debug("[Go] [socket/IP: %u.%u", bytes[0], bytes[1]);  
+    cw_bpf_debug("[Go] [socket/IP: %u.%u", bytes[2], bytes[3]);  
+}  
+
+
+// 用于存储文件描述符和套接字指针的 map  
+struct {  
+    __uint(type, BPF_MAP_TYPE_HASH);  
+    __type(key, __u64);  // 使用进程 ID 作为键  
+    __type(value, struct sock *);  
+    __uint(max_entries, 1024);  
+} socket_map SEC(".maps");  
+
+
+struct ipv4_tuple_t {  
+    __u32 saddr;  
+    __u32 daddr;  
+    __u16 sport;  
+    __u16 dport;  
+    __u8  protocol;  
+};
+
+#define ___bpf_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, _b, _c, N, ...) N
+#define ___bpf_concat(a, b) a ## b
+#define ___bpf_apply(fn, n) ___bpf_concat(fn, n)
+#define ___bpf_narg(...) \
+	___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
+#define ___bpf_kretprobe_args0()       ctx
+#define ___bpf_kretprobe_args1(x)      ___bpf_kretprobe_args0(), (void *)PT_REGS_RC(ctx)
+#define ___bpf_kretprobe_args(args...) ___bpf_apply(___bpf_kretprobe_args, ___bpf_narg(args))(args)
+
+#define BPF_KRETPROBE(name, args...)					    \
+name(struct pt_regs *ctx);						    \
+static __attribute__((always_inline)) typeof(name(0))			    \
+____##name(struct pt_regs *ctx, ##args);				    \
+typeof(name(0)) name(struct pt_regs *ctx)				    \
+{									    \
+	_Pragma("GCC diagnostic push")					    \
+	_Pragma("GCC diagnostic ignored \"-Wint-conversion\"")		    \
+	return ____##name(___bpf_kretprobe_args(args));			    \
+	_Pragma("GCC diagnostic pop")					    \
+}									    \
+static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args)
+
+#define bpf_core_read(dst, sz, src)					    \
+	bpf_probe_read(dst, sz, (const void *)__builtin_preserve_access_index(src))
+
+SEC("kprobe/inet_csk_accept")
+// int BPF_KRETPROBE(inet_csk_accept, struct sock *sk) {
+int kprobe__inet_csk_accept(struct pt_regs *ctx) {  
+    cw_bpf_debug("socket inet_csk_accept Connection inet_csk_accept entry\n");
+    return 0; 
+}
+
+// 在 socket 接受时挂钩获取五元组信息  
+SEC("kretprobe/inet_csk_accept")
+// int BPF_KRETPROBE(inet_csk_accept, struct sock *sk) {
+int kretprobe__inet_csk_accept(struct pt_regs *ctx) {  
+    struct sock *sk = (struct sock *)PT_REGS_RC(ctx);
+    __u16 family = 0;
+    bpf_core_read(&family, sizeof(family), &sk->__sk_common.skc_family);
+    cw_bpf_debug("socket inet_csk_accept Connection family: family=%d\n", family);
+    if (family == AF_INET)
+	{
+        cw_bpf_debug("socket inet_csk_accept Connection family22: family=%d\n", family);
+    }
+    struct ipv4_tuple_t tuple = {};  
+
+    // 从 __sk_common 获取信息  
+    bpf_probe_read(&tuple.saddr, sizeof(tuple.saddr), &sk->__sk_common.skc_rcv_saddr);  
+    bpf_probe_read(&tuple.daddr, sizeof(tuple.daddr), &sk->__sk_common.skc_daddr);  
+    bpf_probe_read(&tuple.sport, sizeof(tuple.sport), &sk->__sk_common.skc_num);  
+    bpf_probe_read(&tuple.dport, sizeof(tuple.dport), &sk->__sk_common.skc_dport);  
+
+    tuple.sport = bpf_ntohs(tuple.sport);  
+    tuple.dport = bpf_ntohs(tuple.dport);
+
+    __u64 hash;
+    bpf_probe_read(&hash, sizeof(hash), &sk->__sk_common.skc_hash);
+
+    cw_bpf_debug("socket inet_csk_accept Connection accepted: sk=%x, hash: %lld\n", sk, hash);
+    cw_bpf_debug("socket inet_csk_accept Connection accepted: dport=%d, lport=%d\n", tuple.dport, tuple.sport);
+    cw_bpf_debug("socket inet_csk_accept Connection accepted: saddr=%lld, daddr=%lld\n", tuple.saddr, tuple.daddr);
+    cw_bpf_debug("[Go] inet_csk_accept [socket/tracepoint__sys_exit_accept4]getget: rdi_ptr::pid -- \n");
+    u32_to_ip(tuple.saddr);
+    u32_to_ip(tuple.daddr);
+    __u64 pid_tgid = bpf_get_current_pid_tgid();  
+    cw_bpf_debug("[Go] inet_csk_accept [socket/kprobe__inet_csk_accept]getget: rdi_ptr::pid: %d\n", pid_tgid);
+    // 将进程 ID 关联到 `struct sock` 指针  
+    // bpf_map_update_elem(&socket_map, &pid_tgid, &sk, BPF_ANY);  
+
+    return 0;  
+}  
+
+struct sys_exit_accept4_ctx {
+	__u64 __unused_syscall_header;
+	__u32 __unused_syscall_nr;
+	__u64 ret;
+};
+struct sys_enter_accept4_ctx {
+	__u64 __unused_syscall_header;
+	__u32 __unused_syscall_nr;
+
+	__u64 fd;
+	__u64 *sockaddr;
+	__u64 addrlen;
+};
+// 在系统调用accept返回时挂钩获取文件描述符  
+SEC("tracepoint/syscalls/sys_enter_accept4")  
+int tracepoint__sys_enter_accept4(struct sys_enter_accept4_ctx *ctx) {  
+    __u64 fd = ctx->fd;  
+    __u64 *sockaddr = ctx->sockaddr;  
+    __u64 pid_tgid = bpf_get_current_pid_tgid();  
+    cw_bpf_debug("[Go] [socket/tracepoint__sys_entry_accept4]getget: rdi_ptr::pid: %d,-- %d\n", pid_tgid, fd);
+    struct ipv4_tuple_t tuple = {};  
+    // cw_bpf_debug("[Go] [socket/tracepoint__sys_entry_accept4]getget: rdi_ptr::pid: %d\n", *sockaddr);
+    return 0;  
+}  
+
+// 在系统调用accept返回时挂钩获取文件描述符  
+SEC("tracepoint/syscalls/sys_exit_accept4")  
+int tracepoint__sys_exit_accept4(struct sys_exit_accept4_ctx *ctx) {  
+    __u64 fd = ctx->ret;  
+    __u64 pid_tgid = bpf_get_current_pid_tgid();  
+    cw_bpf_debug("[Go] [socket/tracepoint__sys_exit_accept4]getget: rdi_ptr::pid: %d,-- %d\n", pid_tgid, fd);
+    // bpf_map_update_elem(&fd_by_pid_tgid, &pid_tgid, &fd, BPF_ANY);
+    // struct sock **skp;  
+    
+
+    // // 从 map 中获取 `struct sock` 指针  
+    // skp = bpf_map_lookup_elem(&socket_map, &pid_tgid);  
+    // if (skp && fd >= 0) {  
+        
+    //     struct sock *sk = *skp;
+    //     __u16 lport = 0, dport = 0;
+    //     bpf_probe_read(&lport, sizeof(lport), &sk->__sk_common.skc_num);
+    //     bpf_probe_read(&dport, sizeof(dport), &sk->__sk_common.skc_dport);
+    //     __u32 saddr, daddr;
+    //     bpf_probe_read(&saddr, sizeof(__u32), &sk->__sk_common.skc_rcv_saddr);
+	// 	bpf_probe_read(&daddr, sizeof(__u32), &sk->__sk_common.skc_daddr);
+	// 	// sport = lport;
+	// 	// dport = ntohs(dport);
+    //     cw_bpf_debug("socket Connection accepted: fd=%d, dport=%d, lport=%d\n", fd, dport, lport);
+    //     cw_bpf_debug("socket Connection accepted: saddr=%lld, daddr=%lld\n", saddr, daddr);
+    //     cw_bpf_debug("[Go] [socket/tracepoint__sys_exit_accept4]getget: rdi_ptr::pid -- \n");
+    //     u32_to_ip(saddr);
+    //     u32_to_ip(daddr);
+    //     // 在此可以访问 `sk` 结构,提取五元组信息进行处理  
+
+    //     // 打印文件描述符和相关信息给用户空间  
+    //     bpf_printk("fd: %d", fd);  
+    // }  
+
+    // // 从地图中移除项目,避免泄漏  
+    // bpf_map_delete_elem(&socket_map, &pid_tgid);  
+
+    return 0;  
+}  

+ 13 - 7
ebpftracer/tracer.go

@@ -106,7 +106,7 @@ type TrafficStats struct {
 }
 
 type Event struct {
-	StackEvent 	*StackEvent
+	StackEvent   *StackEvent
 	Type         EventType
 	Reason       EventReason
 	Pid          uint32
@@ -122,12 +122,12 @@ type Event struct {
 type perfMapType uint8
 
 const (
-	perfMapTypeProcEvents   perfMapType = 1
-	perfMapTypeTCPEvents    perfMapType = 2
-	perfMapTypeFileEvents   perfMapType = 3
-	perfMapTypeL7Events     perfMapType = 4
-	perfMapTypeSocketEvents perfMapType = 5
-	perfMapTypeEventQueue   perfMapType = 6
+	perfMapTypeProcEvents         perfMapType = 1
+	perfMapTypeTCPEvents          perfMapType = 2
+	perfMapTypeFileEvents         perfMapType = 3
+	perfMapTypeL7Events           perfMapType = 4
+	perfMapTypeSocketEvents       perfMapType = 5
+	perfMapTypeEventQueue         perfMapType = 6
 	perfMapTypePythonThreadEvents perfMapType = 7
 )
 
@@ -360,6 +360,12 @@ func (t *Tracer) ebpf(ch chan<- Event) error {
 				t.uprobes[programSpec.Name] = program
 				continue
 			}
+			if strings.HasPrefix(programSpec.SectionName, "kretprobe/") {
+				klog.Infof("[end] Look eBPF specProgramskretprobekretprobe------", programSpec.SectionName)
+				klog.Infof("[end] Look eBPF specProgramskretprobekretprobe------", programSpec.AttachTo)
+				l, err = link.Kretprobe(programSpec.AttachTo, program, nil)
+				continue
+			}
 			l, err = link.Kprobe(programSpec.AttachTo, program, nil)
 		}
 		if err != nil {