diff --git a/MagicEyes/src/backend/fs/fs_watcher/bpf/open.bpf.c b/MagicEyes/src/backend/fs/fs_watcher/bpf/open.bpf.c index 5824bb774..60e11158a 100644 --- a/MagicEyes/src/backend/fs/fs_watcher/bpf/open.bpf.c +++ b/MagicEyes/src/backend/fs/fs_watcher/bpf/open.bpf.c @@ -1,18 +1,19 @@ -#define BPF_NO_GLOBAL_DATA #include #include #include #include #include "fs_watcher.h" -#define TASK_COMM_LEN 100 -#define path_size 256 +char LICENSE[] SEC("license") = "GPL"; + +#define O_CREAT 0x0200 // 手动定义 O_CREAT 标志的常量值 +#define O_WRONLY 01 /* open for writing only */ struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, 1024); __type(key, pid_t); - __type(value, char[TASK_COMM_LEN]); + __type(value, struct event_open); } data SEC(".maps"); struct { @@ -20,52 +21,84 @@ struct { __uint(max_entries, 256 * 1024); } rb SEC(".maps"); // 环形缓冲区 - SEC("tracepoint/syscalls/sys_enter_openat") int do_syscall_trace(struct trace_event_raw_sys_enter *ctx) { - struct event_open *e; - char comm[TASK_COMM_LEN]; - bpf_get_current_comm(&comm,sizeof(comm)); - e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); - if (!e) - return 0; + struct event_open e = {}; + pid_t pid = bpf_get_current_pid_tgid() >> 32; + e.pid = pid; + e.dfd = ctx->args[0];// 目录文件描述符 + bpf_probe_read_user_str(e.filename, sizeof(e.filename), (const char *)ctx->args[1]); // 文件路径 + e.flags = ctx->args[2]; // 打开标志 + + // 如果包含 O_CREAT 标志,则标记为文件创建 + if (e.flags & O_CREAT || (e.flags & O_WRONLY) ) { + e.is_created = true; + } else { + e.is_created = false; + } + + bpf_map_update_elem(&data,&pid,&e,BPF_ANY); + return 0; +} - char filename[path_size]; - struct task_struct *task = (struct task_struct *)bpf_get_current_task(), - *real_parent; - if (task == NULL) { - bpf_printk("task\n"); - bpf_ringbuf_discard(e, 0); +// 跟踪文件描述符分配过程 +SEC("kprobe/get_unused_fd_flags") +int kprobe_get_unused_fd_flags(struct pt_regs *ctx){ + pid_t pid = bpf_get_current_pid_tgid() >> 32; + struct event_open *e = bpf_map_lookup_elem(&data,&pid); + if(!e){ + bpf_printk("get_unused_fd_flags is failed to found fd\n"); return 0; } - int pid = bpf_get_current_pid_tgid() >> 32, tgid; - - bpf_map_update_elem(&data, &pid, &comm, BPF_ANY); - - int ppid = BPF_CORE_READ(task, real_parent, tgid); - bpf_probe_read_str(e->path_name_, sizeof(e->path_name_), - (void *)(ctx->args[1])); + //获取分配的文件描述符 + e->fd = PT_REGS_RC(ctx); - bpf_printk("path name: %s,pid:%d,ppid:%d\n", e->path_name_, pid, ppid); + bpf_map_update_elem(&data,&pid,e,BPF_ANY); + return 0; +} - struct fdtable *fdt = BPF_CORE_READ(task, files, fdt); - if (fdt == NULL) { - bpf_printk("fdt\n"); - bpf_ringbuf_discard(e, 0); +// 跟踪 openat 系统调用的退出 +SEC("tracepoint/syscalls/sys_exit_openat") +int do_syscall_exit(struct trace_event_raw_sys_exit *ctx) +{ + pid_t pid = bpf_get_current_pid_tgid() >> 32; + struct event_open *e = bpf_map_lookup_elem(&data,&pid); + if(!e){ + bpf_printk("sys_exit_openat is failed to found fd\n"); return 0; } - unsigned int i = 0, count = 0, n = BPF_CORE_READ(fdt, max_fds); - bpf_printk("n:%d\n", n); - - e->n_ = n; - e->pid_ = pid; - - bpf_ringbuf_submit(e, 0); - + e->ret = ctx->ret; + + // 分配 ringbuf 空间 + struct event_open *new_e = bpf_ringbuf_reserve(&rb, sizeof(*new_e), 0); + if (!new_e) { + return 0; // 如果分配失败,提前返回 + } + + //复制数据 + new_e->dfd = e->dfd; + new_e->flags = e->flags; + new_e->fd = e->fd; + new_e->ret =e->ret; + new_e->is_created = e->is_created; + new_e->pid = e->pid; + + // 手动读取文件路径,确保不超过最大长度,并添加 '\0' 结束符 + int filename_len = 0; + while (filename_len < sizeof(new_e->filename) - 1) { + char c = 0; + // 读取路径中的每个字符 + bpf_probe_read(&c, sizeof(c), e->filename + filename_len); + if (c == '\0') break; // 如果遇到 null 字符就停止读取 + new_e->filename[filename_len++] = c; + } + // 确保字符串以 '\0' 结束 + new_e->filename[filename_len] = '\0'; + bpf_printk("Opening file: %s, pid: %d, flags: %d\n", new_e->filename, pid, e->flags); + + bpf_ringbuf_submit(new_e, 0); return 0; } - -char LICENSE[] SEC("license") = "GPL"; \ No newline at end of file diff --git a/MagicEyes/src/backend/fs/fs_watcher/include/fs_watcher.h b/MagicEyes/src/backend/fs/fs_watcher/include/fs_watcher.h index 8c9cc1cdb..ed049ab13 100644 --- a/MagicEyes/src/backend/fs/fs_watcher/include/fs_watcher.h +++ b/MagicEyes/src/backend/fs/fs_watcher/include/fs_watcher.h @@ -6,10 +6,13 @@ #define TASK_COMM_LEN 16 struct event_open { - int pid_; - char path_name_[path_size]; - int n_; - char comm[TASK_COMM_LEN]; + pid_t pid; + int dfd; + char filename[path_size]; + int flags; + int fd; // 文件描述符 + int ret; // 系统调用返回值 + bool is_created; // 标记文件是否创建 }; /*read*/ diff --git a/MagicEyes/src/backend/fs/fs_watcher/src/fs_watcher.c b/MagicEyes/src/backend/fs/fs_watcher/src/fs_watcher.c index beef03c45..9a6ef6c85 100644 --- a/MagicEyes/src/backend/fs/fs_watcher/src/fs_watcher.c +++ b/MagicEyes/src/backend/fs/fs_watcher/src/fs_watcher.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include // 包含文件打开标志宏 #include #include "fs/fs_watcher/open.skel.h" #include "fs/fs_watcher/read.skel.h" @@ -105,7 +107,6 @@ static struct env{ bool disk_io_visit; bool block_rq_issue; bool CacheTrack; - pid_t pid; }env = { .open = false, .read = false, @@ -113,7 +114,6 @@ static struct env{ .disk_io_visit = false, .block_rq_issue = false, .CacheTrack = false, - .pid = -1, }; static const struct argp_option opts[] = { @@ -123,7 +123,6 @@ static const struct argp_option opts[] = { {"disk_io_visit", 'd', 0, 0, "Print disk I/O visit report"}, {"block_rq_issue", 'b', 0, 0, "Print block I/O request submission events. Reports when block I/O requests are submitted to device drivers."}, {"CacheTrack", 't' , 0 ,0 , "WriteBack dirty lagency and other information"}, - {"pid", 'p', "PID", 0, "Specify pid number when report weite. Only support for write report now"}, {0} // 结束标记,用于指示选项列表的结束 }; @@ -142,19 +141,7 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) { env.block_rq_issue = true;break; case 't': env.CacheTrack = true;break; - case 'p': - if (arg) { - env.pid = atoi(arg); - if (env.pid <= 0) { - fprintf(stderr, "Invalid PID value: %s\n", arg); - argp_usage(state); - } - } else { - fprintf(stderr, "-p option requires an argument\n"); - argp_usage(state); - } - break; - default: + default: return ARGP_ERR_UNKNOWN; } return 0; @@ -244,38 +231,65 @@ int main(int argc,char **argv){ } } +const char* flags_to_str(int flags) { + static char str[256]; + str[0] = '\0'; // 清空字符串 + + if (flags & O_RDONLY) strcat(str, "O_RDONLY "); + if (flags & O_WRONLY) strcat(str, "O_WRONLY "); + if (flags & O_RDWR) strcat(str, "O_RDWR "); + if (flags & O_CREAT) strcat(str, "O_CREAT "); + if (flags & O_EXCL) strcat(str, "O_EXCL "); + if (flags & O_TRUNC) strcat(str, "O_TRUNC "); + if (flags & O_APPEND) strcat(str, "O_APPEND "); + if (flags & O_NOFOLLOW) strcat(str, "O_NOFOLLOW "); + if (flags & O_CLOEXEC) strcat(str, "O_CLOEXEC "); + if (flags & O_NONBLOCK) strcat(str, "O_NONBLOCK "); + if (flags & O_SYNC) strcat(str, "O_SYNC "); + if (flags & O_DSYNC) strcat(str, "O_DSYNC "); + if (flags & O_RSYNC) strcat(str, "O_RSYNC "); + if (flags & O_DIRECTORY) strcat(str, "O_DIRECTORY "); + + // 条件编译部分:如果系统定义了 O_NOATIME 和 O_PATH +#ifdef O_NOATIME + if (flags & O_NOATIME) strcat(str, "O_NOATIME "); +#endif + +#ifdef O_PATH + if (flags & O_PATH) strcat(str, "O_PATH "); +#endif + + // 如果没有匹配到标志,返回 "Unknown" + if (str[0] == '\0') { + return "Unknown"; + } + + return str; +} + static int handle_event_open(void *ctx, void *data, size_t data_sz) { - struct event_open *e = (struct event_open *)data; - char *filename = strrchr(e->path_name_, '/'); - ++filename; - - char fd_path[path_size]; - char actual_path[path_size]; - char comm[TASK_COMM_LEN]; - int i = 0; - int map_fd = *(int *)ctx;//传递map得文件描述符 - - - for (; i < e->n_; ++i) { - snprintf(fd_path, sizeof(fd_path), "/proc/%d/fd/%d", e->pid_, - i); - ssize_t len = - readlink(fd_path, actual_path, sizeof(actual_path) - 1); - if (len != -1) { - actual_path[len] = '\0'; - int result = strcmp(e->path_name_, actual_path); - if (result == 0) { - if(bpf_map_lookup_elem(map_fd,&e->pid_,&comm)==0){ - printf("%-60s %-8d %-8d %-8s\n", - e->path_name_, i,e->pid_,comm); - }else{ - fprintf(stderr, "Failed to lookup value for key %d\n", e->pid_); - } - - } - } - } + const struct event_open *e = data; + struct tm *tm; + char ts[32]; + time_t t; + + time(&t); + tm = localtime(&t); + strftime(ts, sizeof(ts), "%H:%M:%S", tm); + const char *ret_str; + // 如果返回值是负数,则是错误码,使用 strerror + if (e->ret < 0) { + ret_str = strerror(-e->ret); // 负数表示错误码 + } else { + // 正数表示文件描述符,直接打印文件描述符 + ret_str = "Success"; // 如果是文件描述符,表示成功 + } + + const char *flags_str = flags_to_str(e->flags); + + printf("%-8s %-8d %-8d %-100s %-8s %-8d %-8s %-8s\n", + ts, e->dfd, e->pid,e->filename, flags_str, e->fd, ret_str, e->is_created ? "true" : "false"); return 0; } @@ -352,7 +366,7 @@ static int process_open(struct open_bpf *skel_open){ LOAD_AND_ATTACH_SKELETON_MAP(skel_open,open); - printf("%-60s %-8s %-8s %-8s\n","filenamename","fd","pid","comm"); + printf("%-8s %-8s %-8s %-100s %-8s %-8s %-8s %-8s\n", "TIME","dfd","PID", "filename", "flags", "fd", "ret", "is_created"); POLL_RING_BUFFER(rb, 1000, err); open_cleanup: @@ -381,22 +395,9 @@ static int process_read(struct read_bpf *skel_read){ static int process_write(struct write_bpf *skel_write){ int err; struct ring_buffer *rb; - int arg_index = 0; - - struct dist_args d_args = {-1}; - LOAD_AND_ATTACH_SKELETON(skel_write,write); - d_args.pid = env.pid; - struct bpf_map *arg_map = bpf_object__find_map_by_name((const struct bpf_object *)*(skel_write->skeleton->obj), "args_map"); - err = bpf_map__update_elem(arg_map, &arg_index, sizeof(arg_index), &d_args, sizeof(d_args), BPF_ANY); - - if (err < 0) { - fprintf(stderr, "ERROR: failed to update args map\n"); - goto write_cleanup; - } - printf("%-8s %-8s %-8s %-8s %-8s\n","ds","inode_number","pid","real_count","count"); POLL_RING_BUFFER(rb, 1000, err); diff --git a/MagicEyes/src/backend/net/net_watcher/src/net_watcher.c b/MagicEyes/src/backend/net/net_watcher/src/net_watcher.c index a6466ebc1..a0fb2d4f7 100644 --- a/MagicEyes/src/backend/net/net_watcher/src/net_watcher.c +++ b/MagicEyes/src/backend/net/net_watcher/src/net_watcher.c @@ -55,6 +55,7 @@ static int all_conn = 0, err_packet = 0, extra_conn_info = 0, layer_time = 0, time_load = 0, dns_info = 0, stack_info = 0, mysql_info = 0, redis_info = 0, count_info = 0, rtt_info = 0, rst_info = 0, protocol_count = 0, redis_stat = 0, overrun_time = 0; // flag +static char *dst_ip = NULL, *src_ip = NULL; static const char argp_program_doc[] = "Watch tcp/ip in network subsystem \n"; static const struct argp_option opts[] = { @@ -66,14 +67,16 @@ 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"}, + {"src-ip", 'S', "SRC_IP", 0, "Filter by source IP address"}, + {"dst-ip", 'D', "DST_IP", 0, "Filter by destination IP address"}, {"udp", 'u', 0, 0, "trace the udp message"}, {"net_filter", 'n', 0, 0, "trace ipv4 packget filter "}, {"drop_reason", 'k', 0, 0, "trace kfree "}, {"addr_to_func", 'F', 0, 0, "translation addr to func and offset"}, {"icmptime", 'I', 0, 0, "set to trace layer time of icmp"}, - {"tcpstate", 'S', 0, 0, "set to trace tcpstate"}, + {"tcpstate", 'P', 0, 0, "set to trace tcpstate"}, {"timeload", 'L', 0, 0, "analysis time load"}, - {"dns", 'D', 0, 0, + {"dns", 'N', 0, 0, "set to trace dns information info include Id 事务ID、Flags 标志字段、Qd " "问题部分计数、An 应答记录计数、Ns 授权记录计数、Ar 附加记录计数、Qr " "域名、rx 收发包 、Qc请求数、Sc响应数"}, @@ -89,8 +92,9 @@ static const struct argp_option opts[] = { {"rst_counters", 'U', 0, 0, "set to trace rst"}, {"protocol_count", 'p', 0, 0, "set to trace protocol count"}, {"overrun_time", 'o', "PERIOD", 0, "set to trace rto overrun"}, - // {"overrun", 'o', 0, 0, "set to trace rto overrun"}, + {NULL, 'h', NULL, OPTION_HIDDEN, "Show the full help"}, {}}; + static u64 sample_period = TIME_THRESHOLD_NS; static error_t parse_arg(int key, char *arg, struct argp_state *state) { @@ -121,6 +125,12 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) case 'd': dport = strtoul(arg, &end, 10); break; + case 'S': + src_ip = arg; + break; + case 'D': + dst_ip = arg; + break; case 'u': udp_info = 1; break; @@ -136,13 +146,13 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) case 'I': icmp_info = 1; break; - case 'S': + case 'P': tcp_info = 1; break; case 'L': time_load = 1; break; - case 'D': + case 'N': dns_info = 1; break; case 'A': @@ -172,11 +182,15 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) case 'o': overrun_time = strtoul(arg, &end, 10); break; + case 'h': + argp_state_help(state, stderr, ARGP_HELP_STD_HELP); + break; default: return ARGP_ERR_UNKNOWN; } return 0; } + static const struct argp argp = { .options = opts, .parser = parse_arg, @@ -505,6 +519,44 @@ int process_delay(float layer_delay, int layer_index) } return 0; } + +static int should_filter(const char *src, const char *dst, const char *filter_src_ip, const char *filter_dst_ip) +{ + // 均未指定 + if (!filter_src_ip && !filter_dst_ip) + { + return 1; + } + + // 指定源IP和目的IP + if (filter_src_ip && filter_dst_ip) + { + if (strcmp(src, filter_src_ip) == 0 && strcmp(dst, filter_dst_ip) == 0) + { + return 1; + } + } + // 只指定源IP + else if (filter_src_ip) + { + + if (strcmp(src, filter_src_ip) == 0) + { + return 1; + } + } + // 只指定目的IP + else if (filter_dst_ip) + { + if (strcmp(dst, filter_dst_ip) == 0) + { + return 1; + } + } + + return 0; +} + static void set_rodata_flags(struct net_watcher_bpf *skel) { skel->rodata->filter_dport = dport; @@ -528,6 +580,7 @@ static void set_rodata_flags(struct net_watcher_bpf *skel) skel->rodata->rtt_info = rtt_info; skel->rodata->rst_info = rst_info; skel->rodata->protocol_count = protocol_count; + skel->rodata->overrun_time = overrun_time; } static void set_disable_load(struct net_watcher_bpf *skel) { @@ -715,8 +768,8 @@ static void print_header(enum MonitorMode mode) "UDP " "INFORMATION====================================================" "====\n"); - printf("%-20s %-20s %-20s %-20s %-20s %-20s %-20s\n", "Saddr", "Daddr", - "Sprot", "Dprot", "udp_time/μs", "RX/direction", "len/byte"); + printf("%-20s %-20s %-20s %-20s %-20s %-20s %-20s\n", "Saddr", "Sport", + "Daddr", "Dprot", "udp_time/μs", "RX/direction", "len/byte"); break; case MODE_NET_FILTER: printf("===============================================================" @@ -724,7 +777,7 @@ static void print_header(enum MonitorMode mode) "INFORMATION====================================================" "=======\n"); printf("%-20s %-20s %-12s %-12s %-8s %-8s %-7s %-8s %-8s %-8s\n", - "Saddr", "Daddr", "Sprot", "Dprot", "PreRT/μs", "L_IN/μs", + "Saddr", "Sport", "Daddr", "Dprot", "PreRT/μs", "L_IN/μs", "FW/μs", "PostRT/μs", "L_OUT/μs", "RX/direction"); break; case MODE_DROP_REASON: @@ -733,7 +786,7 @@ static void print_header(enum MonitorMode mode) "INFORMATION====================================================" "====\n"); printf("%-13s %-17s %-17s %-10s %-10s %-9s %-33s %-30s\n", "Time", - "Saddr", "Daddr", "Sprot", "Dprot", "prot", "addr", "reason"); + "Saddr", "Sport", "Daddr", "Dprot", "prot", "addr", "reason"); break; case MODE_ICMP: printf("=================================================ICMP " @@ -746,8 +799,8 @@ static void print_header(enum MonitorMode mode) "TCP STATE " "INFORMATION====================================================" "====\n"); - printf("%-20s %-20s %-20s %-20s %-20s %-20s %-20s \n", "Saddr", "Daddr", - "Sport", "Dport", "oldstate", "newstate", "time/μs"); + printf("%-20s %-20s %-20s %-20s %-20s %-20s %-20s \n", "Saddr", "Sport", + "Daddr", "Dport", "oldstate", "newstate", "time/μs"); break; case MODE_DNS: printf("===============================================================" @@ -794,28 +847,28 @@ static void print_header(enum MonitorMode mode) "INFORMATION====================================================" "============================\n"); printf("%-10s %-20s %-10s %-10s %-10s %-10s %-20s \n", "Pid", "Comm", - "Saddr", "Daddr", "Sport", "Dport", "Time"); + "Saddr", "Sport", "Daddr", "Dport", "Time"); break; case MODE_EXTRA_CONN: printf("===============================================================" "====================EXTRA CONN " "INFORMATION====================================================" "============================\n"); - printf("%-15s %-15s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-13s %-10s %-10s %-10s %-10s\n", "Saddr", "Daddr", "Sport", "Dport", "backlog", "maxbacklog", "rwnd", "cwnd", "ssthresh", "sndbuf", "wmem_queued", "rx_bytes", "tx_bytes", "srtt", "duration"); + printf("%-15s %-15s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-13s %-10s %-10s %-10s %-10s\n", "Saddr", "Sport", "Daddr", "Dport", "backlog", "maxbacklog", "rwnd", "cwnd", "ssthresh", "sndbuf", "wmem_queued", "rx_bytes", "tx_bytes", "srtt", "duration"); break; case MODE_RETRANS: printf("===============================================================" "====================RETRANS " "INFORMATION====================================================" "============================\n"); - printf("%-15s %-15s %-10s %-10s %-10s %-10s %-10s\n", "Saddr", "Daddr", "Sport", "Dport", "fastRe", "total_retrans", "timeout"); + printf("%-15s %-15s %-10s %-10s %-10s %-10s %-10s\n", "Saddr", "Sport", "Daddr", "Dport", "fastRe", "total_retrans", "timeout"); break; case MODE_CONN: printf("===============================================================" "====================CONN " "INFORMATION====================================================" "============================\n"); - printf("%-15s %-20s %-15s %-15s %-10s %-10s %-10s\n", "Pid", "Sock", "Saddr", "Daddr", "Sport", "Dport", "Is_Server"); + printf("%-15s %-20s %-15s %-15s %-10s %-10s %-10s\n", "Pid", "Sock", "Saddr", "Sport", "Daddr", "Dport", "Is_Server"); break; case MODE_DEFAULT: printf("===============================================================" @@ -837,7 +890,7 @@ static void print_header(enum MonitorMode mode) "=OVERTIME INFORMATION===================================================" "======================\n"); printf("%-20s %-20s %-20s %-20s %-20s %-20s\n", - "Saddr", "Daddr", "Sport", "Dport", "RTO", "Delack_max"); + "Saddr", "Sport", "Daddr", "Dport", "RTO", "Delack_max"); break; case MODE_PROTOCOL_COUNT: printf("===============================================================" @@ -868,6 +921,7 @@ static void bytes_to_str(char *str, unsigned long long num) sprintf(str, "%llu", num); } } + static int print_conns(struct net_watcher_bpf *skel) { @@ -893,9 +947,7 @@ static int print_conns(struct net_watcher_bpf *skel) char s_ip_port_str[INET6_ADDRSTRLEN + 6]; char d_ip_port_str[INET6_ADDRSTRLEN + 6]; - if ((d.saddr & 0x0000FFFF) == 0x0000007F || - (d.daddr & 0x0000FFFF) == 0x0000007F) - return 0; + if (d.family == AF_INET) { inet_ntop(AF_INET, &d.saddr, s_str, sizeof(s_str)); @@ -922,19 +974,19 @@ static int print_conns(struct net_watcher_bpf *skel) if (extra_conn_info) { - printf("%-15s %-15s %-10d %-10d %-10u %-10u %-10u %-10u %-10u %-10u %-13u %-10s %-10s %-10u %-10llu\n", - s_ip_only, d_ip_only, d.sport, d.dport, d.tcp_backlog, + printf("%-15s %-10d %-15s %-10d %-10u %-10u %-10u %-10u %-10u %-10u %-13u %-10s %-10s %-10u %-10llu\n", + s_ip_only, d.sport,d_ip_only, d.dport, d.tcp_backlog, d.max_tcp_backlog, d.rcv_wnd, d.snd_cwnd, d.snd_ssthresh, d.sndbuf, d.sk_wmem_queued, received_bytes, acked_bytes, d.srtt, d.duration); } if (retrans_info) { - printf("%-15s %-15s %-10d %-10d %-10u %-14u %-10u\n", s_ip_only, d_ip_only, d.sport, d.dport, d.fastRe, d.total_retrans, d.timeout); + printf("%-15s %-10d %-15s %-10d %-10u %-14u %-10u\n", s_ip_only, d.sport, d_ip_only, d.dport, d.fastRe, d.total_retrans, d.timeout); } if (all_conn) { - printf("%-15d %-20p %-15s %-15s %-10d %-10d %-10u\n", d.pid, d.sock, s_ip_only, d_ip_only, d.sport, d.dport, d.is_server); + printf("%-15d %-20p %-15s %-10d %-15s %-10d %-10u\n", d.pid, d.sock, s_ip_only, d.sport, d_ip_only, d.dport, d.is_server); } } return 0; @@ -955,9 +1007,12 @@ static int print_packet(void *ctx, void *packet_info, size_t size) char s_str[INET_ADDRSTRLEN]; unsigned int saddr = pack_info->saddr; unsigned int daddr = pack_info->daddr; - if ((daddr & 0x0000FFFF) == 0x0000007F || - (saddr & 0x0000FFFF) == 0x0000007F) + inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)); + inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)); + if (should_filter(s_str, d_str, src_ip, dst_ip)) + { return 0; + } if (dport) if (pack_info->dport != dport) return 0; @@ -986,9 +1041,9 @@ static int print_packet(void *ctx, void *packet_info, size_t size) printf("%-22p %-20s %-8d %-20s %-8d %-14llu %-14llu %-14llu %-14u %-14u %-14d " "%-16s", pack_info->sock, - inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), + s_str, pack_info->sport, - inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), + d_str, pack_info->dport, pack_info->mac_time, pack_info->ip_time, pack_info->tran_time, pack_info->seq, pack_info->ack, pack_info->rx, http_data); } @@ -1015,9 +1070,9 @@ static int print_packet(void *ctx, void *packet_info, size_t size) } printf("%-22p %-20s %-8d %-20s %-8d %-14u %-14u %-14s ", pack_info->sock, - inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), + s_str, pack_info->sport, - inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), + d_str, pack_info->dport, pack_info->seq, pack_info->ack, reason); } } @@ -1025,9 +1080,9 @@ static int print_packet(void *ctx, void *packet_info, size_t size) { printf("%-22p %-20s %-8d %-20s %-8d %-14u %-14u %-14u %-14u %-14u %-14d %-16s\n", pack_info->sock, - inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), + s_str, pack_info->sport, - inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), + d_str, pack_info->dport, 0, 0, 0, pack_info->seq, pack_info->ack, pack_info->rx, http_data); } if (time_load) @@ -1047,20 +1102,24 @@ static int print_udp(void *ctx, void *packet_info, size_t size) { if (!udp_info) 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; - if (pack_info->tran_time > MAXTIME || (daddr & 0x0000FFFF) == 0x0000007F || - (saddr & 0x0000FFFF) == 0x0000007F) + inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)); + inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)); + + if (!should_filter(s_str, d_str, src_ip, dst_ip)) + { return 0; - printf("%-20s %-20s %-20u %-20u %-20llu %-20d %-20d", - 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); + } + + printf("%-20s %-20u %-20s %-20u %-20llu %-20d %-20d\n", + s_str, pack_info->sport,d_str, pack_info->dport, + pack_info->tran_time, pack_info->rx, pack_info->len); if (time_load) { @@ -1071,6 +1130,7 @@ static int print_udp(void *ctx, void *packet_info, size_t size) printf("\n"); return 0; } + static int print_netfilter(void *ctx, void *packet_info, size_t size) { if (!net_filter) @@ -1078,20 +1138,27 @@ static int print_netfilter(void *ctx, void *packet_info, size_t size) char d_str[INET_ADDRSTRLEN]; char s_str[INET_ADDRSTRLEN]; const struct netfilter *pack_info = packet_info; + if (pack_info->local_input_time > MAXTIME || pack_info->forward_time > MAXTIME || pack_info->local_out_time > MAXTIME || pack_info->post_routing_time > MAXTIME || pack_info->pre_routing_time > MAXTIME) return 0; + unsigned int saddr = pack_info->saddr; unsigned int daddr = pack_info->daddr; - // if ((daddr & 0x0000FFFF) == 0x0000007F || - // (saddr & 0x0000FFFF) == 0x0000007F) - // return 0; - printf("%-20s %-20s %-12d %-12d %-8lld %-8lld% -8lld %-8lld %-8lld %-8d", - inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), - inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), pack_info->sport, + + inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)); + inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)); + + if (!should_filter(s_str, d_str, src_ip, dst_ip)) + { + return 0; + } + + printf("%-20s %-12d %-20s %-12d %-8lld %-8lld% -8lld %-8lld %-8lld %-8d", + s_str, pack_info->sport,d_str, pack_info->dport, pack_info->pre_routing_time, pack_info->local_input_time, pack_info->forward_time, pack_info->post_routing_time, pack_info->local_out_time, @@ -1129,9 +1196,15 @@ static int print_tcpstate(void *ctx, void *packet_info, size_t size) const struct tcp_state *pack_info = packet_info; unsigned int saddr = pack_info->saddr; unsigned int daddr = pack_info->daddr; - printf("%-20s %-20s %-20d %-20d %-20s %-20s %-20lld\n", - inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), - inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), pack_info->sport, + inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)); + inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)); + if (!should_filter(s_str, d_str, src_ip, dst_ip)) + { + return 0; + } + + printf("%-20s %-20d %-20s %-20d %-20s %-20s %-20lld\n", + s_str, pack_info->sport,d_str, pack_info->dport, tcp_states[pack_info->oldstate], tcp_states[pack_info->newstate], pack_info->time); @@ -1240,14 +1313,16 @@ static int print_kfree(void *ctx, void *packet_info, size_t size) return 0; char d_str[INET_ADDRSTRLEN]; char s_str[INET_ADDRSTRLEN]; + char prot[6]; const struct reasonissue *pack_info = packet_info; unsigned int saddr = pack_info->saddr; unsigned int daddr = pack_info->daddr; - if (saddr == 0 && daddr == 0) + inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)); + inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)); + if (!should_filter(s_str, d_str, src_ip, dst_ip)) { return 0; } - char prot[6]; if (pack_info->protocol == 2048) { strcpy(prot, "ipv4"); @@ -1263,10 +1338,9 @@ static int print_kfree(void *ctx, void *packet_info, size_t size) } time_t now = time(NULL); struct tm *localTime = localtime(&now); - printf("%02d:%02d:%02d %-17s %-17s %-10u %-10u %-10s", + printf("%02d:%02d:%02d %-17s %-10u %-17s %-10u %-10s", localTime->tm_hour, localTime->tm_min, localTime->tm_sec, - inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), - inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), pack_info->sport, + s_str, pack_info->sport,d_str, pack_info->dport, prot); if (!addr_to_func) printf("%-34lx", pack_info->location); @@ -1293,9 +1367,14 @@ static int print_icmptime(void *ctx, void *packet_info, size_t size) } unsigned int saddr = pack_info->saddr; unsigned int daddr = pack_info->daddr; + inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)); + inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)); + if (!should_filter(s_str, d_str, src_ip, dst_ip)) + { + return 0; + } printf("%-20s %-20s %-20lld %-20d", - inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), - inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), + s_str, d_str, pack_info->icmp_tran_time, pack_info->flag); if (time_load) { @@ -1343,9 +1422,9 @@ static void print_stored_events() { inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)); inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)); - printf("%-10d %-10s %-10s %-10s %-10u %-10u %-20llu", - event->pid, event->comm, s_str, d_str, - event->sport, event->dport, + printf("%-10d %-10s %-10s %-10u %-10s %-10u %-20llu", + event->pid, event->comm, s_str, + event->sport, d_str,event->dport, event->timestamp); } else if (event->family == AF_INET6) @@ -1353,9 +1432,9 @@ static void print_stored_events() inet_ntop(AF_INET6, &event->saddr_v6, saddr_v6, sizeof(saddr_v6)); inet_ntop(AF_INET6, &event->daddr_v6, daddr_v6, sizeof(daddr_v6)); - printf("%-10d %10s %-10s %-10s %-10u %-10u %-20llu\n", + printf("%-10d %10s %-10s %-10u %-10s %-10u %-20llu\n", event->pid, event->comm, saddr_v6, - daddr_v6, event->sport, event->dport, + event->sport,daddr_v6, event->dport, event->timestamp); } printf("\n"); @@ -1399,12 +1478,13 @@ static int print_dns(void *ctx, void *packet_info, size_t size) inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)); inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)); - print_domain_name((const unsigned char *)pack_info->data, domain_name); - if (pack_info->daddr == 0) + + if (!should_filter(s_str, d_str, src_ip, dst_ip)) { return 0; } + printf("%-20s %-20s %-#12x %-#12x %-5x %-5x %-5x %-5x %-47s %-10d %-10d " "%-10d \n", s_str, d_str, pack_info->id, pack_info->flags, pack_info->qdcount, @@ -1549,8 +1629,10 @@ static int print_trace(void *_ctx, void *data, size_t size) return 0; } -static int print_rate(void *ctx, void *data, size_t size) { - if (!overrun_time) { +static int print_rate(void *ctx, void *data, size_t size) +{ + if (!overrun_time) + { return 0; } char d_str[INET_ADDRSTRLEN]; @@ -1558,17 +1640,16 @@ static int print_rate(void *ctx, void *data, size_t size) { const struct tcp_rate *pack_info = (const struct tcp_rate *)data; unsigned int saddr = pack_info->skbap.saddr; unsigned int daddr = pack_info->skbap.daddr; - if ((saddr & 0x0000FFFF) == 0x0000007F || - (daddr & 0x0000FFFF) == 0x0000007F) - return 0; - if ((saddr & 0xFF000000) == 0x01000000 || - (daddr & 0xFF000000) == 0x01000000) - return 0; inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)); inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)); - printf("%-20s %-20s %-20d %-20d %-20lld %-20lld\n", s_str, d_str, - pack_info->skbap.sport, pack_info->skbap.dport, pack_info->tcp_rto, + if (!should_filter(s_str, d_str, src_ip, dst_ip)) + { + return 0; + } + + printf("%-20s %-20d %-20s %-20d %-20lld %-20lld\n", s_str, + pack_info->skbap.sport, d_str,pack_info->skbap.dport, pack_info->tcp_rto, pack_info->tcp_delack_max); return 0; @@ -1584,12 +1665,9 @@ static int print_rtt(void *ctx, void *data, size_t size) char s_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &rtt_tuple->saddr, s_str, sizeof(s_str)); inet_ntop(AF_INET, &rtt_tuple->daddr, d_str, sizeof(d_str)); - if ((rtt_tuple->saddr & 0x0000FFFF) == 0x0000007F || - (rtt_tuple->daddr & 0x0000FFFF) == 0x0000007F || - rtt_tuple->saddr == htonl(0xC0A83C01) || - rtt_tuple->daddr == htonl(0xC0A83C01)) + if (!should_filter(s_str, d_str, src_ip, dst_ip)) { - return 0; // 如果匹配任一过滤条件,放弃处理这些数据包 + return 0; } // 打印源地址和目的地址 printf("Source Address: %s\n", s_str); @@ -1680,10 +1758,9 @@ void print_top_5_keys() // printf("Key: %s, Count: %u\n", pairs[index].key, pairs[index].value); index++; } - // 获取所有键值对 // 排序前 5 个元素 - // 简单选择排序(可替换为其他高效排序算法) + // 简单选择排序 for (int i = 0; i < index - 1; i++) { for (int j = i + 1; j < index; j++) diff --git a/MagicEyes/src/magic_eyes_cli/README.md b/MagicEyes/src/magic_eyes_cli/README.md index 76092efac..164771bae 100644 --- a/MagicEyes/src/magic_eyes_cli/README.md +++ b/MagicEyes/src/magic_eyes_cli/README.md @@ -88,7 +88,7 @@ magic_eyes_cli具有2个固定命令, 即 ### 4. 例程 ```bash -magic_eyes_cli process cpu_watcher -h +./magic_eyes_cli process cpu_watcher -h # <------------------ 自动补全 | 非自动补全 ``` diff --git a/eBPF_Supermarket/Memory_Subsystem/mem_watcher/README.md b/eBPF_Supermarket/Memory_Subsystem/mem_watcher/README.md index 473eaf650..ee00e798f 100644 --- a/eBPF_Supermarket/Memory_Subsystem/mem_watcher/README.md +++ b/eBPF_Supermarket/Memory_Subsystem/mem_watcher/README.md @@ -9,6 +9,10 @@ **eBPF 提供了一种高效的机制来监控和追踪系统级别的事件,包括内存的分配和释放。通过 eBPF,可以跟踪内存分配和释放的请求,并收集每次分配的调用堆栈。然后,分析这些信息,找出执行了内存分配但未执行释放操作的调用堆栈,这有助于程序员找出导致内存泄漏的源头。** --- +## TODO list + +- [x] 监控SLAB分配器的内存使用情况 +- [ ] 跟踪共享内存的用量信息 ## 背景意义 @@ -58,7 +62,7 @@ make ``` make后没有编译生成任何的二进制文件,只打印了logo,效果如下: - ![alt text](/docs/image/15.png) + ![alt text](../docs/image/15.png) 打开makefile,检查makefile逻辑,代码如下: ``` @@ -82,7 +86,7 @@ else BZS_APPS := ``` 再次执行make,发现报错为 "vmlinux.h file not find",如下: - ![alt text](/docs/image/16.png) + ![alt text](../docs/image/16.png) 执行以下命令,生成vmlinux.h文件 ``` @@ -125,7 +129,7 @@ registry = "git://crates.rustcc.cn/crates.io-index" ``` 重新安装还是会报错: - ![alt text](/docs/image/17.png) + ![alt text](../docs/image/17.png) 在 `~/.cargo/config` 文件中添加以下内容,即可解决: ``` @@ -133,7 +137,7 @@ registry = "git://crates.rustcc.cn/crates.io-index" git-fetch-with-cli = true ``` 再次make编译完成,生成二进制文件 mem_watcher,并能正常运行。 - ![alt text](/docs/image/18.png) + ![alt text](../docs/image/18.png) # 工具的使用方法说明 diff --git a/eBPF_Supermarket/kvm_watcher/include/bpf/container.h b/eBPF_Supermarket/kvm_watcher/include/bpf/container.h index 0bb0ae68e..6dda002cb 100644 --- a/eBPF_Supermarket/kvm_watcher/include/bpf/container.h +++ b/eBPF_Supermarket/kvm_watcher/include/bpf/container.h @@ -61,7 +61,8 @@ static int trace_container_sys_entry(struct trace_event_raw_sys_enter *args){ bpf_map_update_elem(&id,&pid,&syscall_id,BPF_ANY); return 0; } -static int trace_container_sys_exit(struct trace_event_raw_sys_exit *args,void *rb,struct common_event *e){ + +static int trace_container_sys_exit(struct trace_event_raw_sys_exit *args){ u64 exit_time = bpf_ktime_get_ns(); pid_t pid = bpf_get_current_pid_tgid(); u64 delay,start_time,syscallid; @@ -89,7 +90,12 @@ static int trace_container_sys_exit(struct trace_event_raw_sys_exit *args,void * if (!syscall_value) { return 0; } - + //检查 syscallid 是否超出范围 + //逻辑检查应该放到获取结构体之后的第一步操作,提前的检查让路径变得显式且安全,否则验证器可能无法通过 + if (syscallid >= MAX_SYSCALL_NUM || syscallid < 0) { + return 0; // 如果超出范围,直接返回 + } + // 读取 container_id int ret = bpf_probe_read_kernel_str(syscall_value->container_id, sizeof(syscall_value->container_id), contain_id); if (ret < 0) { @@ -97,19 +103,12 @@ static int trace_container_sys_exit(struct trace_event_raw_sys_exit *args,void * return 0; } - // 打印读取的 container_id - bpf_printk("container_id: %s\n", syscall_value->container_id); - // 获取进程名并存储 ret = bpf_get_current_comm(syscall_value->proc_name, sizeof(syscall_value->proc_name)); if (ret < 0) { bpf_printk("Failed to read process name, error code: %d\n", ret); return 0; } - //检查 syscallid 是否超出范围 - if (syscallid >= MAX_SYSCALL_NUM || syscallid < 0) { - return 0; // 如果超出范围,直接返回 - } syscall_value->syscall_total_delay[syscallid] += delay; // 加上 delay 的值 syscall_value->syscall_id_counts[syscallid] += 1; // 计数加 1 return 0; @@ -118,4 +117,44 @@ static int trace_container_sys_exit(struct trace_event_raw_sys_exit *args,void * struct data_t { char nodename[MAX_NODENAME_LEN]; }; +static bool is_container_task(const volatile char *hostname){ + struct task_struct *task; + struct nsproxy *ns; + struct uts_namespace *uts; + struct data_t data = {}; + // 获取当前任务的 task_struct + task = (struct task_struct *)bpf_get_current_task(); + + // 获取 nsproxy + bpf_probe_read_kernel(&ns, sizeof(ns), &task->nsproxy); + if (!ns) { + return false; + } + + // 获取 uts_namespace + bpf_probe_read_kernel(&uts, sizeof(uts), &ns->uts_ns); + if (!uts) { + return false; + } + // 读取主机名 + bpf_probe_read_kernel_str(&data.nodename, sizeof(data.nodename), uts->name.nodename); + // 打印主机名 + bool is_equal = true; + for(int i = 0;insproxy); - if (!ns) { - return false; - } - - // 获取 uts_namespace - bpf_probe_read_kernel(&uts, sizeof(uts), &ns->uts_ns); - if (!uts) { - return false; - } - // 读取主机名 - bpf_probe_read_kernel_str(&data.nodename, sizeof(data.nodename), uts->name.nodename); - // 打印主机名 - - for(int i = 0;insproxy); - if (!ns) { - return false; - } - - // 获取 uts_namespace - bpf_probe_read_kernel(&uts, sizeof(uts), &ns->uts_ns); - if (!uts) { - return false; - } - // 读取主机名 - bpf_probe_read_kernel_str(&data.nodename, sizeof(data.nodename), uts->name.nodename); - // 打印主机名 - - for(int i = 0;imaps.proc_syscall_info); @@ -1284,7 +1305,9 @@ int print_container_syscall(struct kvm_watcher_bpf *skel){ int err ; //打印表头 - printf("%-13s %-10s %-10s %-10s %-10s %-10s\n","ContainerID", "Comm","Pid","SYSCALLID","Counts","avage_DELAY(us)"); + //printf("%-13s %-10s %-10s %-10s %-10s %-10s\n","ContainerID", "Comm","Pid","SYSCALLID","Counts","avage_DELAY(us)"); + print_description(); + move_cursor(7, 1); while(!bpf_map_get_next_key(fd,&lookup_key,&next_key)){ err = bpf_map_lookup_elem(fd,&next_key,&values); if (err < 0) { @@ -1294,6 +1317,7 @@ int print_container_syscall(struct kvm_watcher_bpf *skel){ //找出最大的前五个系统调用号 int max[5] = {-1, -1, -1, -1, -1}; // 记录前五个最大值的下标 int top_values[5] = {0,0,0,0,0}; // 记录前五个最大值 + uint64_t result = -1; for (int i = 0; i < 462; i++) { for (int j = 0; j < 5; j++) { if (values.syscall_id_counts[i] > top_values[j]) { @@ -1312,11 +1336,14 @@ int print_container_syscall(struct kvm_watcher_bpf *skel){ if(max[i] == -1){ continue; } - uint64_t result = values.syscall_total_delay[max[i]] / values.syscall_id_counts[max[i]]; + result = values.syscall_total_delay[max[i]] / values.syscall_id_counts[max[i]]; printf("%-13s %-10s %-10d %-10d %-10d %llu\n",values.container_id,values.proc_name,next_key, max[i],values.syscall_id_counts[max[i]],result); } lookup_key = next_key; + if(result != -1){ + printf("==============================================================\n"); + } } memset(&lookup_key, 0, sizeof(pid_t)); memset(&next_key, 0, sizeof(pid_t)); @@ -1328,9 +1355,7 @@ int print_container_syscall(struct kvm_watcher_bpf *skel){ } lookup_key = next_key; } - printf("--------------------------\n"); return 0; - } void print_map_and_check_error(int (*print_func)(struct kvm_watcher_bpf *), struct kvm_watcher_bpf *skel, @@ -1341,7 +1366,10 @@ void print_map_and_check_error(int (*print_func)(struct kvm_watcher_bpf *), printf("Error printing %s map: %d\n", map_name, err); } } - +void clear_screen() { + // ANSI 转义序列清屏 + printf("\033[H\033[J"); +} void print_logo() { char *logo = LOGO_STRING; char command[512]; @@ -1356,7 +1384,6 @@ int attach_probe(struct kvm_watcher_bpf *skel) { return kvm_watcher_bpf__attach(skel); } int main(int argc, char **argv) { - // 定义一个环形缓冲区 struct ring_buffer *rb = NULL; struct kvm_watcher_bpf *skel; @@ -1420,6 +1447,10 @@ int main(int argc, char **argv) { fprintf(stderr, "Please specify an option using %s.\n", OPTIONS_LIST); goto cleanup; } + //实现刷屏操作 + clear_screen(); + fflush(stdout); + print_description(); //打印结果 while (!exiting) { err = ring_buffer__poll(rb, RING_BUFFER_TIMEOUT_MS /* timeout, ms */); @@ -1437,8 +1468,8 @@ int main(int argc, char **argv) { err); } if (env.execute_container_syscall){ - //print_map_and_check_error(print_container_syscall,skel,"container_syscall",err); print_container_syscall(skel); + clear_screen(); } /* Ctrl-C will cause -EINTR */ if (err == -EINTR) {