diff --git a/MagicEyes/src/backend/fs/fs_watcher/bpf/CacheTrack.bpf.c b/MagicEyes/src/backend/fs/fs_watcher/bpf/CacheTrack.bpf.c index 608c59967..b96f3ac7b 100644 --- a/MagicEyes/src/backend/fs/fs_watcher/bpf/CacheTrack.bpf.c +++ b/MagicEyes/src/backend/fs/fs_watcher/bpf/CacheTrack.bpf.c @@ -6,34 +6,34 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL"; -// struct { -// __uint(type, BPF_MAP_TYPE_HASH); -// __uint(max_entries, 1024); -// __type(key, char[30] ); -// __type(value,struct event_CacheTrack); -// } data SEC(".maps"); - -// struct { -// __uint(type, BPF_MAP_TYPE_HASH); -// __uint(max_entries, 1024); -// __type(key, u64 ); -// __type(value,struct event_CacheTrack); -// } unique_map SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1024); + __type(key, u64); // 使用inode作为key + __type(value, struct event_CacheTrack); //存储事件结构体 +} data_map SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_RINGBUF); __uint(max_entries, 256 * 1024); } rb SEC(".maps"); - +//事件会在脏 inode 开始进行写回时触发 SEC("tracepoint/writeback/writeback_dirty_inode_start") int trace_writeback_start(struct trace_event_raw_writeback_dirty_inode_template *ctx){ pid_t pid = bpf_get_current_pid_tgid() >> 32; u64 timestamp = bpf_ktime_get_ns(); + ino_t inode; + char comm[16]; struct event_CacheTrack event_info ={}; char name[32]; + // 获取当前进程的命令名称 + bpf_get_current_comm(&comm, sizeof(comm)); - event_info.ino = ctx->ino; + // 将 comm 字符串复制到 event_info.comm + __builtin_memcpy(event_info.comm, comm, sizeof(comm)); + + event_info.ino = inode = ctx->ino; event_info.state = ctx->state; @@ -41,80 +41,39 @@ int trace_writeback_start(struct trace_event_raw_writeback_dirty_inode_template event_info.time = timestamp; - // bpf_probe_read(name, sizeof(name), ctx->name); // 从 ctx 复制设备名称 - - // 检查 name 是否为空字符串 - // if (name[0] == '\0') { - // return 0; - // } - // if(name == NULL) - // return 0; - - // __builtin_memcpy(event_info.name, name, sizeof(name)); - // bpf_printk("comm_123:%s\n",event_info.name); + bpf_map_update_elem(&data_map,&inode,&event_info,BPF_ANY); + return 0; +} +// 事件会在每个 inode 进行单独写回时触发 +SEC("tracepoint/writeback/writeback_single_inode") +int trace_writeback_single_inode(struct trace_event_raw_writeback_single_inode_template *ctx){ + ino_t inode = ctx->ino; + u64 timestamp_conmplete = bpf_ktime_get_ns(); + struct event_CacheTrack *event_info; + + //从map中获取该inode对应的事件信息 + event_info = bpf_map_lookup_elem(&data_map,&inode); + if(!event_info){ + bpf_printk("failed to found event_info\n"); + return 0; + } + //更新inode写回完成的信息 + event_info->wrote = ctx->wrote; //已写回的字节数 + event_info->nr_to_write = ctx->nr_to_write; //待写回的字节数 + event_info->writeback_index = ctx->writeback_index; //表示写回操作的索引或序号 + event_info->time_complete = timestamp_conmplete; + + // 将事件信息提交到 ring buffer struct event_CacheTrack *ring_event = bpf_ringbuf_reserve(&rb, sizeof(struct event_CacheTrack), 0); - if (!ring_event) + if (!ring_event) { + bpf_printk("Failed to reserve space in ring buffer for inode %llu\n", inode); return 0; + } - __builtin_memcpy(ring_event, &event_info, sizeof(event_info)); - - bpf_printk("event_info_ino:%d\n",event_info.ino); - + // 将事件信息从 map 拷贝到 ring buffer + __builtin_memcpy(ring_event, event_info, sizeof(struct event_CacheTrack)); bpf_ringbuf_submit(ring_event, 0); - - // bpf_map_update_elem(&data,name,&event_info,BPF_ANY); - // bpf_map_update_elem(&unique_map,&event_info.queue_id,&event_info,BPF_ANY); return 0; -} - -// SEC("tracepoint/writeback/writeback_written") -// int trace_writeback_end(struct trace_event_raw_writeback_work_class *ctx) { -// bpf_printk("2222222\n"); -// u64 timestamp = bpf_ktime_get_ns(); -// char name[30]; -// bpf_probe_read_str(name, sizeof(name), ctx->name); // 从 ctx 复制设备名称 - -// if(name == NULL) -// return 0; - -// bpf_printk("comm:%s\n",name); - -// struct event_CacheTrack *e = bpf_map_lookup_elem(&data,name); -// if(!e){ -// bpf_printk("e failed\n"); -// return 0; -// } - - -// struct event_CacheTrack *q = bpf_map_lookup_elem(&unique_map,&e->queue_id); -// if(!q){ -// bpf_printk("q failed\n"); -// return 0; -// } - -// struct event_CacheTrack *q_event = bpf_ringbuf_reserve(&rb, sizeof(struct event_CacheTrack), 0); -// if (!q_event){ -// bpf_printk("Ring buffer is full!\n"); -// return 0; -// } - -// q_event->nr_pages = ctx->nr_pages; -// q_event->sb_dev = ctx->sb_dev; -// q_event->sync_mode = ctx->sync_mode; -// q_event->for_kupdate = ctx->for_kupdate; -// q_event->range_cyclic = ctx->range_cyclic; -// q_event->for_background = ctx->for_background; -// q_event->reason = ctx->reason; -// q_event->cgroup_ino = ctx->cgroup_ino; -// q_event->time = timestamp - q->start_timestamp; - -// bpf_printk("time:%llu\n",q_event->time); -// bpf_printk("123\n"); - -// bpf_ringbuf_submit(q_event, 0); - -// return 0; - -// } \ No newline at end of file +} \ 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 83f527e2a..8c9cc1cdb 100644 --- a/MagicEyes/src/backend/fs/fs_watcher/include/fs_watcher.h +++ b/MagicEyes/src/backend/fs/fs_watcher/include/fs_watcher.h @@ -50,16 +50,20 @@ struct event_block_rq_issue { /*CacheTrack*/ struct event_CacheTrack{ - pid_t pid; + char comm[16]; long long time; //耗时 - // char name[32]; // 设备名称 ino_t ino; // inode 号 unsigned long state; // inode 状态 unsigned long flags; // inode 标志 + long int nr_to_write; // 待写回字节数 + long unsigned int writeback_index; //写回操作的索引或序号 + long unsigned int wrote; //已写回的字节数 + long long time_complete; // 写回开始时间 }; /*send pid to ebpf*/ struct dist_args { pid_t pid; }; -#endif /* __MEM_WATCHER_H */ \ No newline at end of file +#endif /* __MEM_WATCHER_H */ + 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 47dd14bc0..beef03c45 100644 --- a/MagicEyes/src/backend/fs/fs_watcher/src/fs_watcher.c +++ b/MagicEyes/src/backend/fs/fs_watcher/src/fs_watcher.c @@ -171,7 +171,8 @@ static const struct argp argp = { static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) { - return vfprintf(stderr, format, args); + // return vfprintf(stderr, format, args); + return 0; } static volatile bool exiting = false; @@ -198,7 +199,7 @@ static int process_CacheTrack(struct CacheTrack_bpf *skel_CacheTrack); int main(int argc,char **argv){ - + int err; struct open_bpf *skel_open; struct read_bpf *skel_read; @@ -209,19 +210,19 @@ int main(int argc,char **argv){ 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); signal(SIGALRM, sig_handler); - + err = argp_parse(&argp, argc, argv, 0, NULL, NULL); - printf("success!\n"); + // printf("success!\n"); if (err) return err; @@ -254,7 +255,7 @@ static int handle_event_open(void *ctx, void *data, size_t data_sz) 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_, @@ -266,12 +267,12 @@ static int handle_event_open(void *ctx, void *data, size_t data_sz) int result = strcmp(e->path_name_, actual_path); if (result == 0) { if(bpf_map_lookup_elem(map_fd,&e->pid_,&comm)==0){ - printf("get , filename:%s , fd:%d , pid:%d ,comm:%s\n", + 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_); } - + } } } @@ -290,7 +291,7 @@ static int handle_event_read(void *ctx, void *data, size_t data_sz) tm = localtime(&t); strftime(ts, sizeof(ts), "%H:%M:%S", tm); - printf("%-8s %-7d %-7llu\n", ts, e->pid,e->duration_ns); + printf("%-10s %-8d %-8llu\n",ts,e->pid,e->duration_ns); return 0; } @@ -303,14 +304,14 @@ static int handle_event_write(void *ctx, void *data, size_t data_sz) time(&t); tm = localtime(&t); strftime(ts, sizeof(ts), "%H:%M:%S", tm); - printf("ts:%-8s pid:%-7ld inode_number:%-3ld cout:%-3ld real_count:%-3ld\n", ts, e->pid,e->inode_number,e->count,e->real_count); + printf("%-8s %-8ld %-8ld %-8ld %-8ld\n", ts, e->pid,e->inode_number,e->count,e->real_count); return 0; } static int handle_event_disk_io_visit(void *ctx, void *data,unsigned long data_sz) { const struct event_disk_io_visit *e = data; - printf("%-10llu %-9d %-7d %-4d %-7d %-16s\n", + printf("%-18llu %-7d %-7d %-4d %-7d %-16s\n", e->timestamp, e->blk_dev, e->sectors, e->rwbs, e->count, e->comm); return 0; @@ -318,26 +319,40 @@ static int handle_event_disk_io_visit(void *ctx, void *data,unsigned long data_s static int handle_event_block_rq_issue(void *ctx, void *data,unsigned long data_sz) { const struct event_block_rq_issue *e = data; - printf("%-10llu %-9d %-7d %-4d %-16s Total I/O: %" PRIu64 "\n", + printf("%-18llu %-15d %-15d %-10d %-16s Total I/O: %" PRIu64 "\n", e->timestamp, e->dev, e->sector, e->nr_sectors, e->comm, e->total_io); return 0; } -static int handle_event_CacheTrack(void *ctx, void *data,unsigned long data_sz) { +static int handle_event_CacheTrack(void *ctx, void *data, unsigned long data_sz) { const struct event_CacheTrack *event = data; - printf("%-20lld %-19lu %-20lu %-5lu\n", event->time, event->ino, event->state, event->flags); + + // 计算写回操作的耗时 + long long writeback_duration = event->time_complete - event->time; + + // 打印所有相关的信息 + printf("%-19llu %-15s %-20lu %-5lu %-20ld %-20lu %-20llu %-20lld\n", + event->ino, // inode 号 + event->comm, //进程comm + event->state, // inode 状态 + event->flags, // inode 标志 + event->nr_to_write, // 待写回字节数 + event->writeback_index, // 写回操作的索引或序号 + event->wrote, // 已写回的字节数 + writeback_duration); // 写回耗时 return 0; } + static int process_open(struct open_bpf *skel_open){ int err; struct ring_buffer *rb; - + LOAD_AND_ATTACH_SKELETON_MAP(skel_open,open); - printf("%-8s %-8s %-8s %-8s\n","filenamename","fd","pid","comm"); + printf("%-60s %-8s %-8s %-8s\n","filenamename","fd","pid","comm"); POLL_RING_BUFFER(rb, 1000, err); open_cleanup: @@ -350,10 +365,10 @@ static int process_open(struct open_bpf *skel_open){ static int process_read(struct read_bpf *skel_read){ int err; struct ring_buffer *rb; - + LOAD_AND_ATTACH_SKELETON(skel_read,read); - printf("%-8s %-8s %-8s %-8s\n","filename","fd","pid","ds"); + printf("%-10s %-8s %-8s\n","TIME","PID","DS"); POLL_RING_BUFFER(rb, 1000, err); read_cleanup: @@ -370,6 +385,7 @@ static int process_write(struct write_bpf *skel_write){ struct dist_args d_args = {-1}; + LOAD_AND_ATTACH_SKELETON(skel_write,write); d_args.pid = env.pid; @@ -394,7 +410,7 @@ static int process_write(struct write_bpf *skel_write){ static int process_disk_io_visit(struct disk_io_visit_bpf *skel_disk_io_visit){ int err; struct ring_buffer *rb; - + LOAD_AND_ATTACH_SKELETON(skel_disk_io_visit,disk_io_visit); printf("%-18s %-7s %-7s %-4s %-7s %-16s\n","TIME", "DEV", "SECTOR", "RWBS", "COUNT", "COMM"); POLL_RING_BUFFER(rb, 1000, err); @@ -410,9 +426,9 @@ static int process_disk_io_visit(struct disk_io_visit_bpf *skel_disk_io_visit){ static int process_block_rq_issue(struct block_rq_issue_bpf *skel_block_rq_issue){ int err; struct ring_buffer *rb; - + LOAD_AND_ATTACH_SKELETON(skel_block_rq_issue,block_rq_issue); - printf("%-18s %-7s %-7s %-4s %-16s %-5sn","TIME", "DEV", "SECTOR", "SECTORS","COMM","Total_Size"); + printf("%-18s %-15s %-15s %-10s %-16s %-5s\n","TIME", "DEV", "SECTOR", "SECTORS","COMM","Total_Size"); POLL_RING_BUFFER(rb, 1000, err); block_rq_issue_cleanup: @@ -426,9 +442,19 @@ static int process_block_rq_issue(struct block_rq_issue_bpf *skel_block_rq_issue static int process_CacheTrack(struct CacheTrack_bpf *skel_CacheTrack){ int err; struct ring_buffer *rb; - + LOAD_AND_ATTACH_SKELETON(skel_CacheTrack,CacheTrack); - printf("%-20s %-19s %-20s %-5s\n","TIME", "INO","STATE","FLAGS"); + // 打印列标题说明(解释各列的含义) + printf("%-19s %-15s %-20s %-5s %-20s %-20s %-20s %-20s\n", + "INODE", // inode号 + "COMM", //comm进程名 + "STATE", // inode 状态 + "FLAGS", // inode 标志 + "NR_TO_WRITE", // 待写回字节数 + "WRITEBACK_INDEX", // 写回操作的索引或序号 + "WROTE", // 已写回字节数 + "WRITEBACK_DURATION"); // 写回操作的耗时 + POLL_RING_BUFFER(rb, 1000, err); CacheTrack_cleanup: diff --git a/MagicEyes/src/backend/net/net_watcher/bpf/common.bpf.h b/MagicEyes/src/backend/net/net_watcher/bpf/common.bpf.h index 87a70d5fd..a6b124b90 100644 --- a/MagicEyes/src/backend/net/net_watcher/bpf/common.bpf.h +++ b/MagicEyes/src/backend/net/net_watcher/bpf/common.bpf.h @@ -252,6 +252,12 @@ struct __uint(max_entries, 256 * 1024); } icmp_rb SEC(".maps"); +struct +{ + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 256 * 1024); +} rate_rb SEC(".maps"); + struct { __uint(type, BPF_MAP_TYPE_RINGBUF); @@ -431,6 +437,22 @@ struct __uint(max_entries, 1024); // 最大条目数 } key_count SEC(".maps"); +struct +{ + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, MAX_COMM *MAX_PACKET); + __type(key, struct sock *); + __type(value, u64); +} tcp_rate_map SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, u32); + __type(value, struct tcp_args_s); + __uint(max_entries, 1); +} args_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, @@ -438,7 +460,7 @@ const volatile int all_conn = 0, err_packet = 0, extra_conn_info = 0, udp_info = 0, net_filter = 0, drop_reason = 0, icmp_info = 0, tcp_info = 0, dns_info = 0, stack_info = 0, mysql_info = 0, redis_info = 0, rtt_info = 0, rst_info = 0, - protocol_count = 0, redis_stat = 0; + protocol_count = 0, redis_stat = 0,overrun_time = 0; ; /* help macro */ @@ -736,6 +758,11 @@ static __always_inline u64 log2l(u64 v) return log2(v); } +static __always_inline int get_current_tgid() +{ + return (int)(bpf_get_current_pid_tgid() >> PID); +} + /* help functions end */ #endif diff --git a/MagicEyes/src/backend/net/net_watcher/bpf/net_watcher.bpf.c b/MagicEyes/src/backend/net/net_watcher/bpf/net_watcher.bpf.c index d1a095425..bb37e56f6 100644 --- a/MagicEyes/src/backend/net/net_watcher/bpf/net_watcher.bpf.c +++ b/MagicEyes/src/backend/net/net_watcher/bpf/net_watcher.bpf.c @@ -341,7 +341,7 @@ int BPF_UPROBE(redis_addReply) { // rtt SEC("kprobe/tcp_rcv_established") int BPF_KPROBE(tcp_rcv_established, struct sock *sk, struct sk_buff *skb) { - return __tcp_rcv_established(sk, skb); + return __tcp_rcv_established(sk, skb); } // tcpstate @@ -349,7 +349,7 @@ SEC("tracepoint/sock/inet_sock_set_state") int handle_set_state(struct trace_event_raw_inet_sock_set_state *ctx) { return __handle_set_state(ctx); } -// RST + SEC("tracepoint/tcp/tcp_send_reset") int handle_send_reset(struct trace_event_raw_tcp_send_reset *ctx) { return __handle_send_reset(ctx); @@ -358,4 +358,9 @@ int handle_send_reset(struct trace_event_raw_tcp_send_reset *ctx) { SEC("tracepoint/tcp/tcp_receive_reset") int handle_receive_reset(struct trace_event_raw_tcp_receive_reset *ctx) { return __handle_receive_reset(ctx); -} \ No newline at end of file +} + +SEC("raw_tracepoint/tcp_rcv_space_adjust") +int handle_tcp_rcv_space_adjust(struct bpf_raw_tracepoint_args *ctx) { + return __handle_tcp_rcv_space_adjust(ctx); +} diff --git a/MagicEyes/src/backend/net/net_watcher/bpf/tcp.bpf.h b/MagicEyes/src/backend/net/net_watcher/bpf/tcp.bpf.h index e81932871..c4229403e 100644 --- a/MagicEyes/src/backend/net/net_watcher/bpf/tcp.bpf.h +++ b/MagicEyes/src/backend/net/net_watcher/bpf/tcp.bpf.h @@ -17,10 +17,8 @@ #include "common.bpf.h" -static __always_inline int __inet_csk_accept(struct sock *sk) -{ - if (sk == NULL) - { // newsk is null +static __always_inline int __inet_csk_accept(struct sock *sk) { + if (sk == NULL) { // newsk is null // bpf_printk("inet_accept_ret err: newsk is null\n"); return 0; } @@ -37,8 +35,7 @@ static __always_inline int __inet_csk_accept(struct sock *sk) // 更新/插入conns_info中的键值对 int err = bpf_map_update_elem(&conns_info, &sk, &conn, BPF_ANY); - if (err) - { // 更新错误 + if (err) { // 更新错误 // bpf_printk("inet_accept update err.\n"); return 0; } @@ -46,31 +43,26 @@ static __always_inline int __inet_csk_accept(struct sock *sk) return 0; } -static __always_inline int __tcp_v4_connect(const struct sock *sk) -{ +static __always_inline int __tcp_v4_connect(const struct sock *sk) { u64 ptid = bpf_get_current_pid_tgid(); int err = bpf_map_update_elem(&sock_stores, &ptid, &sk, BPF_ANY); // 更新/插入sock_stores中的键值对 - if (err) - { + if (err) { // bpf_printk("tcp_v4_connect update sock_stores err.\n"); return 0; } return 0; } -static __always_inline int __tcp_v4_connect_exit(int ret) -{ +static __always_inline int __tcp_v4_connect_exit(int ret) { u64 ptid = bpf_get_current_pid_tgid(); struct sock **skp = bpf_map_lookup_elem(&sock_stores, &ptid); - if (skp == NULL) - { + 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); // 删除对应键值对 return 0; @@ -87,36 +79,30 @@ static __always_inline int __tcp_v4_connect_exit(int ret) long err = bpf_map_update_elem(&conns_info, &sk, &conn, BPF_ANY); // 更新conns_info中sk对应的conn - if (err) - { + if (err) { return 0; } return 0; } -static __always_inline int __tcp_v6_connect(const struct sock *sk) -{ +static __always_inline int __tcp_v6_connect(const struct sock *sk) { u64 pid = bpf_get_current_pid_tgid(); // 获取pid int err = bpf_map_update_elem(&sock_stores, &pid, &sk, BPF_ANY); // 更新sock_stores中对应pid对应的sk - if (err) - { + if (err) { return 0; } return 0; } -static __always_inline int __tcp_v6_connect_exit(int ret) -{ +static __always_inline int __tcp_v6_connect_exit(int ret) { u64 ptid = bpf_get_current_pid_tgid(); // 获取pid struct sock **skp = bpf_map_lookup_elem(&sock_stores, &ptid); // 获得sock_stores中ptid对应的*sk 用skp指向 - if (skp == NULL) - { + if (skp == NULL) { return 0; } - if (ret != 0) - { + if (ret != 0) { bpf_map_delete_elem(&sock_stores, &ptid); return 0; } @@ -133,23 +119,19 @@ static __always_inline int __tcp_v6_connect_exit(int ret) long err = bpf_map_update_elem(&conns_info, &sk, &conn, BPF_ANY); // 更新conns_info中sk对应的conn - if (err) - { + if (err) { return 0; } // bpf_printk("tcp_v4_connect_exit update sk: %p.\n", sk); return 0; } -static __always_inline int __tcp_set_state(struct sock *sk, int state) -{ - if (all_conn) - { +static __always_inline int __tcp_set_state(struct sock *sk, int state) { + if (all_conn) { 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 说明关闭连接 + 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 @@ -159,18 +141,15 @@ static __always_inline int __tcp_set_state(struct sock *sk, int state) // receive error packet static __always_inline int __tcp_validate_incoming(struct sock *sk, - struct sk_buff *skb) -{ - if (!err_packet) - { + 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关联的信息 - if (conn == NULL) - { + if (conn == NULL) { return 0; } struct tcp_skb_cb *tcb = TCP_SKB_CB(skb); // 数据包信息 @@ -180,13 +159,12 @@ static __always_inline int __tcp_validate_incoming(struct sock *sk, u32 rcv_wup = BPF_CORE_READ( tp, rcv_wup); // 接收方已经确认并准备接收的数据最后一个字节的序列号 u32 rcv_nxt = - BPF_CORE_READ(tp, 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) - { + if (end_seq >= rcv_wup && rcv_nxt + receive_window >= start_seq) { // bpf_printk("error_identify: tcp seq validated. \n"); return 0; // 检查数据包序列号是否在接收窗口内 @@ -196,26 +174,20 @@ static __always_inline int __tcp_validate_incoming(struct sock *sk, u16 family = BPF_CORE_READ( sk, __sk_common.skc_family); // 获取套接字的地址族就是获得当前ip协议 struct packet_tuple pkt_tuple = {0}; - if (family == AF_INET) - { + if (family == AF_INET) { struct iphdr *ip = skb_to_iphdr(skb); struct tcphdr *tcp = skb_to_tcphdr(skb); get_pkt_tuple(&pkt_tuple, ip, tcp); - } - else if (family == AF_INET6) - { + } else if (family == AF_INET6) { struct ipv6hdr *ip6h = skb_to_ipv6hdr(skb); struct tcphdr *tcp = skb_to_tcphdr(skb); get_pkt_tuple_v6(&pkt_tuple, ip6h, tcp); - } - else - { + } else { return 0; } struct pack_t *packet; packet = bpf_ringbuf_reserve(&rb, sizeof(*packet), 0); - if (!packet) - { + if (!packet) { return 0; } packet->err = 1; // 错误标记此数据包有问题 @@ -225,34 +197,28 @@ static __always_inline int __tcp_validate_incoming(struct sock *sk, bpf_ringbuf_submit(packet, 0); return 0; } -static __always_inline int skb_checksum_complete(int ret) -{ - if (!err_packet) - { +static __always_inline int skb_checksum_complete(int ret) { + if (!err_packet) { return 0; } u64 pid = bpf_get_current_pid_tgid(); struct sock **skp = bpf_map_lookup_elem(&sock_stores, &pid); - if (skp == NULL) - { + if (skp == NULL) { return 0; } - if (ret == 0) - { + if (ret == 0) { // bpf_printk("error_identify: tcp checksum validated. \n"); return 0; } // bpf_printk("error_identify: tcp checksum error. \n"); struct sock *sk = *skp; struct conn_t *conn = bpf_map_lookup_elem(&conns_info, &sk); - if (conn == NULL) - { + if (conn == NULL) { return 0; } struct pack_t *packet; packet = bpf_ringbuf_reserve(&rb, sizeof(*packet), 0); - if (!packet) - { + if (!packet) { return 0; } packet->err = 2; // 校验和错误 @@ -262,15 +228,12 @@ static __always_inline int skb_checksum_complete(int ret) return 0; } // retrans packet -static __always_inline int __tcp_enter_recovery(struct sock *sk) -{ - if (!retrans_info) - { +static __always_inline int __tcp_enter_recovery(struct sock *sk) { + if (!retrans_info) { return 0; } struct conn_t *conn = bpf_map_lookup_elem(&conns_info, &sk); - if (conn == NULL) - { + if (conn == NULL) { // bpf_printk("get a v4 rx pack but conn not record, its sock is: %p", // sk); return 0; @@ -279,23 +242,19 @@ static __always_inline int __tcp_enter_recovery(struct sock *sk) return 0; } -static __always_inline int __tcp_enter_loss(struct sock *sk) -{ - if (!retrans_info) - { +static __always_inline int __tcp_enter_loss(struct sock *sk) { + if (!retrans_info) { return 0; } struct conn_t *conn = bpf_map_lookup_elem(&conns_info, &sk); - if (conn == NULL) - { + if (conn == NULL) { return 0; } conn->timeout += 1; return 0; } static __always_inline int -__handle_set_state(struct trace_event_raw_inet_sock_set_state *ctx) -{ +__handle_set_state(struct trace_event_raw_inet_sock_set_state *ctx) { if (ctx->protocol != IPPROTO_TCP) return 0; @@ -327,8 +286,7 @@ __handle_set_state(struct trace_event_raw_inet_sock_set_state *ctx) struct tcp_state *message; message = bpf_ringbuf_reserve(&tcp_rb, sizeof(*message), 0); - if (!message) - { + if (!message) { return 0; } @@ -345,8 +303,7 @@ __handle_set_state(struct trace_event_raw_inet_sock_set_state *ctx) } static __always_inline int __tcp_rcv_established(struct sock *sk, - struct sk_buff *skb) -{ + struct sk_buff *skb) { const struct inet_sock *inet = (struct inet_sock *)(sk); struct tcp_sock *ts; struct hist *histp; @@ -360,8 +317,7 @@ static __always_inline int __tcp_rcv_established(struct sock *sk, struct ip_packet key = {.saddr = pkt_tuple.saddr, .daddr = pkt_tuple.daddr}; histp = bpf_map_lookup_elem(&hists, &key); - if (!histp) - { + if (!histp) { struct hist zero = {}; bpf_map_update_elem(&hists, &key, &zero, BPF_ANY); @@ -385,8 +341,7 @@ static __always_inline int __tcp_rcv_established(struct sock *sk, struct RTT *message; message = bpf_ringbuf_reserve(&rtt_rb, sizeof(*message), 0); - if (!message) - { + if (!message) { return 0; } message->saddr = pkt_tuple.saddr; @@ -401,9 +356,7 @@ static __always_inline int __tcp_rcv_established(struct sock *sk, return 0; } -static __always_inline int ret(void *ctx, u8 direction, u16 sport, - u16 dport) -{ +static __always_inline int ret(void *ctx, u8 direction, u16 sport, u16 dport) { struct reset_event_t *message = bpf_ringbuf_reserve(&events, sizeof(*message), 0); if (!message) @@ -416,34 +369,25 @@ static __always_inline int ret(void *ctx, u8 direction, u16 sport, message->family = BPF_CORE_READ(sk, __sk_common.skc_family); message->timestamp = bpf_ktime_get_ns() / 1000; - if (message->family == AF_INET) - { - if (direction == 0) - { // Send + if (message->family == AF_INET) { + if (direction == 0) { // Send message->saddr = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr); message->daddr = BPF_CORE_READ(sk, __sk_common.skc_daddr); - } - else - { // Receive + } else { // Receive message->saddr = BPF_CORE_READ(sk, __sk_common.skc_daddr); message->daddr = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr); } message->saddr_v6 = 0; message->daddr_v6 = 0; - } - else if (message->family == AF_INET6) - { - if (direction == 0) - { // Send + } else if (message->family == AF_INET6) { + if (direction == 0) { // Send bpf_probe_read_kernel( &message->saddr_v6, sizeof(message->saddr_v6), &sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32); bpf_probe_read_kernel( &message->daddr_v6, sizeof(message->daddr_v6), &sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32); - } - else - { // Receive + } else { // Receive bpf_probe_read_kernel( &message->saddr_v6, sizeof(message->saddr_v6), &sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32); @@ -456,13 +400,10 @@ static __always_inline int ret(void *ctx, u8 direction, u16 sport, message->daddr = 0; } - if (direction == 0) - { // Send + if (direction == 0) { // Send message->sport = bpf_ntohs(sport); message->dport = bpf_ntohs(dport); - } - else - { // Receive + } else { // Receive message->sport = bpf_ntohs(dport); message->dport = bpf_ntohs(sport); } @@ -471,12 +412,9 @@ static __always_inline int ret(void *ctx, u8 direction, u16 sport, // 增加 RST 计数 u32 pid = message->pid; u64 *count = bpf_map_lookup_elem(&counters, &pid); - if (count) - { + if (count) { *count += 1; - } - else - { + } else { u64 initial_count = 1; bpf_map_update_elem(&counters, &pid, &initial_count, BPF_ANY); count = &initial_count; @@ -488,8 +426,7 @@ static __always_inline int ret(void *ctx, u8 direction, u16 sport, return 0; } static __always_inline int -__handle_send_reset(struct trace_event_raw_tcp_send_reset *ctx) -{ +__handle_send_reset(struct trace_event_raw_tcp_send_reset *ctx) { struct sock *sk = (struct sock *)ctx->skaddr; if (!sk) return 0; @@ -498,12 +435,69 @@ __handle_send_reset(struct trace_event_raw_tcp_send_reset *ctx) } static __always_inline int -__handle_receive_reset(struct trace_event_raw_tcp_receive_reset *ctx) -{ +__handle_receive_reset(struct trace_event_raw_tcp_receive_reset *ctx) { struct sock *sk = (struct sock *)ctx->skaddr; if (!sk) return 0; // bpf_printk("Receive reset: sport=%u, dport=%u\n", ctx->sport, // ctx->dport); return ret((void *)ctx->skaddr, 1, ctx->sport, ctx->dport); -} \ No newline at end of file +} + +// 获取当前采样周期 +static __always_inline u64 get_period(void) { + u32 key = 0; + u64 period = TIME_THRESHOLD_NS; // 默认值 + struct tcp_args_s *args; + + // 查找用户设置的采样周期 + args = (struct tcp_args_s *)bpf_map_lookup_elem(&args_map, &key); + if (args) { + period = args->sample_period; + } + + return period; +} + +static __always_inline int +__handle_tcp_rcv_space_adjust(struct bpf_raw_tracepoint_args *ctx) { + struct sock *sk = (struct sock *)ctx->args[0]; + if (!sk) + return 0; + + u64 current_time = bpf_ktime_get_ns(); + + // 从 tcp_rate_map 中查找上次采样时间 + u64 *last_time = bpf_map_lookup_elem(&tcp_rate_map, &sk); + + // 如果没有找到上次采样时间,首次采样时设置为当前时间 + if (last_time) { + if ((current_time - *last_time) < get_period()) { + return 0; + } + } + + bpf_map_update_elem(&tcp_rate_map, &sk, ¤t_time, BPF_ANY); + + struct inet_connection_sock *icsk = (struct inet_connection_sock *)sk; + if (!icsk) + return 0; + + struct tcp_rate *message = + bpf_ringbuf_reserve(&rate_rb, sizeof(*message), 0); + if (!message) + return 0; + + message->skbap.saddr = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr); + message->skbap.daddr = BPF_CORE_READ(sk, __sk_common.skc_daddr); + message->skbap.sport = __bpf_ntohs(BPF_CORE_READ(sk, __sk_common.skc_num)); + message->skbap.dport = + __bpf_ntohs(BPF_CORE_READ(sk, __sk_common.skc_dport)); + message->tcp_rto = BPF_CORE_READ(icsk, icsk_rto); + // BPF_CORE_READ(icsk, icsk_ack.ato); + message->pid = get_current_tgid(); + message->tcp_delack_max = BPF_CORE_READ(icsk, icsk_delack_max); + bpf_ringbuf_submit(message, 0); + + return 0; +} diff --git a/MagicEyes/src/backend/net/net_watcher/include/net_watcher.h b/MagicEyes/src/backend/net/net_watcher/include/net_watcher.h index c3253b607..97fd33cb6 100644 --- a/MagicEyes/src/backend/net/net_watcher/include/net_watcher.h +++ b/MagicEyes/src/backend/net/net_watcher/include/net_watcher.h @@ -55,6 +55,10 @@ typedef unsigned long long u64; #define MAX_STACK_DEPTH 128 #define MAX_EVENTS 1024 #define CACHEMAXSIZE 5 +#define PID 32 +#define NS(x) ((x) * 1000000000) // 1 秒等于 10^9 纳秒 +#define TIME_THRESHOLD_NS NS(10) + typedef u64 stack_trace_t[MAX_STACK_DEPTH]; struct conn_t @@ -270,6 +274,7 @@ static const char *protocol[] = { [2] = "ICMP", [3] = "UNKNOWN", }; + static const char *tcp_states[] = { [1] = "ESTABLISHED", [2] = "SYN_SENT", @@ -285,9 +290,32 @@ static const char *tcp_states[] = { [12] = "NEW_SYN_RECV", [13] = "UNKNOWN", }; + struct LayerDelayInfo { float delay; // 时延数据 int layer_index; // 层索引 }; + +struct addr_pair +{ + u32 saddr; + u32 daddr; + u16 sport; + u16 dport; +}; +struct tcp_rate +{ + struct addr_pair skbap; + u64 tcp_ato; + u64 tcp_rto; + u64 tcp_delack_max; + u32 pid; +}; + +struct tcp_args_s { + u64 sample_period; +}; + + #endif /* __NET_WATCHER_H */ \ No newline at end of file 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 701c82a96..a6466ebc1 100644 --- a/MagicEyes/src/backend/net/net_watcher/src/net_watcher.c +++ b/MagicEyes/src/backend/net/net_watcher/src/net_watcher.c @@ -54,7 +54,7 @@ static int all_conn = 0, err_packet = 0, extra_conn_info = 0, layer_time = 0, drop_reason = 0, addr_to_func = 0, icmp_info = 0, tcp_info = 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; // flag + protocol_count = 0, redis_stat = 0, overrun_time = 0; // flag static const char argp_program_doc[] = "Watch tcp/ip in network subsystem \n"; static const struct argp_option opts[] = { @@ -88,8 +88,10 @@ static const struct argp_option opts[] = { {"rtt", 'T', 0, 0, "set to trace rtt"}, {"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"}, {}}; - +static u64 sample_period = TIME_THRESHOLD_NS; static error_t parse_arg(int key, char *arg, struct argp_state *state) { char *end; @@ -167,6 +169,9 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) case 'C': count_info = strtoul(arg, &end, 10); break; + case 'o': + overrun_time = strtoul(arg, &end, 10); + break; default: return ARGP_ERR_UNKNOWN; } @@ -195,6 +200,7 @@ enum MonitorMode MODE_RETRANS, MODE_CONN, MODE_ERROR, + MODE_OVERTIME, MODE_DEFAULT }; enum MonitorMode get_monitor_mode() @@ -263,6 +269,10 @@ enum MonitorMode get_monitor_mode() { return MODE_ERROR; } + else if (overrun_time) + { + return MODE_OVERTIME; + } else { return MODE_DEFAULT; @@ -693,6 +703,8 @@ static void set_disable_load(struct net_watcher_bpf *skel) rst_info ? true : false); bpf_program__set_autoload(skel->progs.handle_receive_reset, rst_info ? true : false); + bpf_program__set_autoload(skel->progs.handle_tcp_rcv_space_adjust, + overrun_time ? true : false); } static void print_header(enum MonitorMode mode) { @@ -820,6 +832,13 @@ static void print_header(enum MonitorMode mode) printf("%-22s %-20s %-8s %-20s %-8s %-14s %-14s %-15s \n", "SOCK", "Saddr", "Sport", "Daddr", "Dport", "Seq", "Ack", "Reason"); break; + case MODE_OVERTIME: + printf("===============================================================" + "=OVERTIME INFORMATION===================================================" + "======================\n"); + printf("%-20s %-20s %-20s %-20s %-20s %-20s\n", + "Saddr", "Daddr", "Sport", "Dport", "RTO", "Delack_max"); + break; case MODE_PROTOCOL_COUNT: printf("===============================================================" "=MODE_PROTOCOL_COUNT===========================================" @@ -923,7 +942,7 @@ static int print_conns(struct net_watcher_bpf *skel) static int print_packet(void *ctx, void *packet_info, size_t size) { if (udp_info || net_filter || drop_reason || icmp_info || tcp_info || all_conn || - dns_info || mysql_info || redis_info || rtt_info || protocol_count || redis_stat || extra_conn_info || retrans_info) + dns_info || mysql_info || redis_info || rtt_info || protocol_count || redis_stat || extra_conn_info || retrans_info || overrun_time) return 0; char http_data[256]; const struct pack_t *pack_info = packet_info; @@ -1313,7 +1332,7 @@ static void print_stored_events() char d_str[INET_ADDRSTRLEN]; char saddr_v6[INET6_ADDRSTRLEN]; char daddr_v6[INET6_ADDRSTRLEN]; - + for (int i = 0; i < event_count; i++) { struct reset_event_t *event = &event_store[i]; @@ -1364,7 +1383,7 @@ static void print_domain_name(const unsigned char *data, char *output) output[pos++] = *next++; } } - output[pos] = '\0'; + output[pos] = '\0'; } static int print_dns(void *ctx, void *packet_info, size_t size) { @@ -1529,6 +1548,31 @@ static int print_trace(void *_ctx, void *data, size_t size) printf("\n"); return 0; } + +static int print_rate(void *ctx, void *data, size_t size) { + if (!overrun_time) { + return 0; + } + char d_str[INET_ADDRSTRLEN]; + char s_str[INET_ADDRSTRLEN]; + 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, + pack_info->tcp_delack_max); + + return 0; +} static int print_rtt(void *ctx, void *data, size_t size) { if (!rtt_info) @@ -1653,7 +1697,7 @@ void print_top_5_keys() } } printf("----------------------------\n"); - + printf("Top 5 Keys:\n"); for (int i = 0; i < 5 && i < index; i++) { @@ -1679,6 +1723,7 @@ int main(int argc, char **argv) struct ring_buffer *rtt_rb = NULL; struct ring_buffer *events = NULL; struct ring_buffer *port_rb = NULL; + struct ring_buffer *rate_rb = NULL; struct net_watcher_bpf *skel; int err; /* Parse command line arguments */ @@ -1688,8 +1733,8 @@ int main(int argc, char **argv) if (err) return err; } - - // libbpf_set_print(libbpf_print_fn); + + // libbpf_set_print(libbpf_print_fn); /* Cleaner handling of Ctrl-C */ signal(SIGINT, sig_handler); @@ -1856,6 +1901,15 @@ int main(int argc, char **argv) fprintf(stderr, "Failed to create ring buffer(trace)\n"); goto cleanup; } + + rate_rb = ring_buffer__new(bpf_map__fd(skel->maps.rate_rb), + print_rate, NULL, NULL); + if (!rate_rb) + { + err = -1; + fprintf(stderr, "Failed to create ring buffer(trace)\n"); + goto cleanup; + } /* Set up ring buffer polling */ rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), print_packet, NULL, NULL); if (!rb) @@ -1885,6 +1939,7 @@ int main(int argc, char **argv) err = ring_buffer__poll(events, 100 /* timeout, ms */); err = ring_buffer__poll(port_rb, 100 /* timeout, ms */); err = ring_buffer__poll(redis_stat_rb, 100 /* timeout, ms */); + err = ring_buffer__poll(rate_rb, 100 /* timeout, ms */); print_conns(skel); sleep(1); /* Ctrl-C will cause -EINTR */ @@ -1898,8 +1953,22 @@ int main(int argc, char **argv) printf("Error polling perf buffer: %d\n", err); break; } - gettimeofday(&end, NULL); + if (overrun_time) + { + u32 key = 0; + struct tcp_args_s new_args; + new_args.sample_period = overrun_time; + + // 更新 args_map,传递采样周期给 BPF 程序 + err = bpf_map_update_elem(bpf_map__fd(skel->maps.args_map), &key, &new_args, BPF_ANY); + if (err) + { + fprintf(stderr, "Failed to update sample period\n"); + return 1; + } + } + if ((end.tv_sec - start.tv_sec) >= 5) { if (rst_info) @@ -1941,6 +2010,7 @@ int main(int argc, char **argv) ring_buffer__free(events); ring_buffer__free(port_rb); ring_buffer__free(redis_stat_rb); + ring_buffer__free(rate_rb); net_watcher_bpf__destroy(skel); return err < 0 ? -err : 0; } diff --git a/MagicEyes/src/visualization/panels/fs_watcher.json b/MagicEyes/src/visualization/panels/fs_watcher.json new file mode 100644 index 000000000..fdfae74f8 --- /dev/null +++ b/MagicEyes/src/visualization/panels/fs_watcher.json @@ -0,0 +1,131 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 6, + "links": [], + "liveNow": false, + "panels": [ + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "kg80JrQSk" + }, + "exemplar": true, + "expr": "{bpf_out_data=\"DS\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Panel Title", + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 34, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "read", + "uid": "au0ws6VHz", + "version": 2, + "weekStart": "" +} + diff --git a/MagicEyes/src/visualization/vscode_ext/tool_config_sample/lmp_tool_ext_config.json b/MagicEyes/src/visualization/vscode_ext/tool_config_sample/lmp_tool_ext_config.json index 0102d7e69..8d9cb1c07 100644 --- a/MagicEyes/src/visualization/vscode_ext/tool_config_sample/lmp_tool_ext_config.json +++ b/MagicEyes/src/visualization/vscode_ext/tool_config_sample/lmp_tool_ext_config.json @@ -35,6 +35,10 @@ { "description" : "Linux 文件子系统观测工具集", "tools" : [ + { + "name":"fs_watcher", + "description":"文件系统观测" + }, { "name": "fast_fuse", "description" : "FUSE 性能优化" diff --git a/eBPF_Supermarket/Filesystem_Subsystem/fast_fuse/difuse/src/difuse b/eBPF_Supermarket/Filesystem_Subsystem/fast_fuse/difuse/src/difuse deleted file mode 100755 index dccdfc251..000000000 Binary files a/eBPF_Supermarket/Filesystem_Subsystem/fast_fuse/difuse/src/difuse and /dev/null differ diff --git a/eBPF_Supermarket/Filesystem_Subsystem/fast_fuse/difuse/test/pro.sh b/eBPF_Supermarket/Filesystem_Subsystem/fast_fuse/difuse/test/pro.sh new file mode 100755 index 000000000..7f1bb09ce --- /dev/null +++ b/eBPF_Supermarket/Filesystem_Subsystem/fast_fuse/difuse/test/pro.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# 挂载点目录 +MOUNT_POINT="../src/mountpoints" +SRC_DIR="../src" + +# FUSE 可执行文件 +FUSE_EXEC="../src/difuse" + +echo "Compiling FUSE filesystem..." +make -C "$SRC_DIR" clean +make -C "$SRC_DIR" all + +# 检查编译是否成功 +if [ ! -f "$FUSE_EXEC" ]; then + echo "Compilation failed. Exiting." + exit 1 +fi + +# 创建挂载点目录(如果不存在) +if [ ! -d "$MOUNT_POINT" ]; then + mkdir -p "$MOUNT_POINT" +fi + +# 挂载 FUSE 文件系统(前台运行并显示调试信息) +echo "Mounting FUSE filesystem..." +$FUSE_EXEC -f -d "$MOUNT_POINT" & +FUSE_PID=$! +sleep 2 # 等待文件系统完全挂载 + +# 确保脚本退出时卸载文件系统 +trap "fusermount -u $MOUNT_POINT" EXIT + +# 基准测试:写入 +echo "开始写入基准测试..." +echo "# Write operation: Creating testfile_100MB_1" >> ../test/dd_output.log +dd if=/dev/zero of=$MOUNT_POINT/testfile_100MB_1 bs=1M count=100 status=progress 2>> ../test/dd_output.log +echo "Created testfile_100MB_1" + +# 读取 +echo "# Read operation: Reading testfile_100MB_1" >> ../test/dd_output.log +dd if=$MOUNT_POINT/testfile_100MB_1 of=/dev/null bs=1M status=progress 2>> ../test/dd_output.log +echo "Read testfile_100MB_1" diff --git a/eBPF_Supermarket/kvm_watcher/include/bpf/container.h b/eBPF_Supermarket/kvm_watcher/include/bpf/container.h index 5271054ef..0bb0ae68e 100644 --- a/eBPF_Supermarket/kvm_watcher/include/bpf/container.h +++ b/eBPF_Supermarket/kvm_watcher/include/bpf/container.h @@ -24,7 +24,7 @@ #include #include #include -#define MAX_NODENAME_LEN 64 +#define MAX_NODENAME_LEN 13 struct { __uint(type,BPF_MAP_TYPE_HASH); __uint(max_entries, 8192); @@ -46,6 +46,12 @@ struct { __type(value,struct container_id); }container_id_map SEC(".maps"); +struct { + __uint(type,BPF_MAP_TYPE_HASH); + __uint(max_entries, 80); + __type(key, pid_t); + __type(value,struct syscall_value); //记录容器ID、进程名、系统调用号、每个调用号的次数、单位时间内的总延迟 +}proc_syscall_info SEC(".maps"); static int trace_container_sys_entry(struct trace_event_raw_sys_enter *args){ u64 st = bpf_ktime_get_ns(); @@ -62,8 +68,8 @@ static int trace_container_sys_exit(struct trace_event_raw_sys_exit *args,void * u64 *st = bpf_map_lookup_elem(&time_info,&pid); if( st !=0){ start_time = *st; - delay = (exit_time - start_time)/1000; - bpf_map_delete_elem(&time_info, &pid); + delay = (exit_time - start_time)/1000; + bpf_map_delete_elem(&time_info, &pid); }else{ return 0; } @@ -72,65 +78,44 @@ static int trace_container_sys_exit(struct trace_event_raw_sys_exit *args,void * syscallid = *sc_id; bpf_map_delete_elem(&id, &pid); }else{ - return 0; + return 0; } const void *contain_id = bpf_map_lookup_elem(&container_id_map,&pid); - if(contain_id != NULL){ - bpf_printk("hostname=%s\n",contain_id); - }else{ + if(contain_id == NULL){ + return 0; + } + //用指针去获取用户定义好的结构体,不然结构体过大会导致栈溢出 + struct syscall_value *syscall_value = bpf_map_lookup_elem(&proc_syscall_info, &pid); + if (!syscall_value) { return 0; } - RESERVE_RINGBUF_ENTRY(rb, e); - e->syscall_data.delay = delay; - bpf_get_current_comm(&e->syscall_data.comm, sizeof(e->syscall_data.comm)); - e->syscall_data.pid = pid; - bpf_probe_read_kernel_str(&(e->syscall_data.container_id),sizeof(e->syscall_data.container_id),contain_id); - e->syscall_data.syscall_id = syscallid; - bpf_ringbuf_submit(e, 0); + + // 读取 container_id + int ret = bpf_probe_read_kernel_str(syscall_value->container_id, sizeof(syscall_value->container_id), contain_id); + if (ret < 0) { + bpf_printk("Failed to read container_id from kernel space, error code: %d\n", ret); + 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; } struct data_t { char nodename[MAX_NODENAME_LEN]; }; -static bool is_container_task(const volatile char hostname[MAX_NODENAME_LEN]){ - 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;ishow){ - printf("%-9s %10s\n", "DELAY(us)","SYSCALLID"); + //printf("%-13s %-10s %-10s %-10s %-10s %-10s\n","ContainerID", "Comm","Pid","SYSCALLID","Counts","avage_DELAY(us)"); }else{ - printf("%-8s %-22s %-9s %10s %-16s\n", "PID", "CONTAINER_ID", - "DELAY(us)", "SYSCALLID", "COMM"); + //printf("%-13s %-10s %-10s %-10s %-10s %-10s\n","ContainerID", "Comm","Pid","SYSCALLID","Counts","avage_DELAY(us)"); } break; case EXIT: @@ -1027,6 +1026,7 @@ int print_hc_map(struct kvm_watcher_bpf *skel) { struct hc_key next_key = {}; struct hc_value hc_value = {}; int first_run = 1; + // Iterate over the map while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) { if (first_run) { @@ -1238,6 +1238,100 @@ int print_exit_map(struct kvm_watcher_bpf *skel) { __print_exit_map(userspace_exit_fd, EXIT_USERSPACE_NR); return 0; } +int memset_big_struct(struct kvm_watcher_bpf *skel){ + //对占用大内存的结构体的map进行初始化 + int fd_memset = bpf_map__fd(skel->maps.proc_syscall_info); + int fd_proc = bpf_map__fd(skel->maps.container_id_map); + pid_t pid ,next_pid; + while (!bpf_map_get_next_key(fd_proc, &pid, &next_pid)) { + struct syscall_value new_value = {}; + int err = bpf_map_lookup_elem(fd_memset,&next_pid,&new_value); + //填充 new_value + strncpy(new_value.container_id, "", sizeof(new_value.container_id)); + strncpy(new_value.proc_name, "", sizeof(new_value.proc_name)); + // 初始化 syscalls 的 counts 和延迟为0 + memset(new_value.syscall_id_counts, 0, sizeof(new_value.syscall_id_counts)); + memset(new_value.syscall_total_delay, 0, sizeof(new_value.syscall_total_delay)); + // 在 BPF map 中插入初始化的值 + int ret = bpf_map_update_elem(fd_memset, &next_pid, &new_value, BPF_ANY); + if (ret < 0) { + perror("Error updating BPF map"); + return -1; + } + pid = next_pid; + } + //清除记录容器pid的map,不然无法重新给系统调用信息的map赋值 + memset(&pid, 0, sizeof(pid_t)); + memset(&next_pid, 0, sizeof(pid_t)); + while (!bpf_map_get_next_key(fd_proc, pid, next_pid)) { + int err = bpf_map_delete_elem(fd_proc, next_pid); + if (err < 0) { + fprintf(stderr, "failed to cleanup map: %d\n", err); + return -1; + } + pid = next_pid; + } + return 0; +} +int print_container_syscall(struct kvm_watcher_bpf *skel){ + OUTPUT_INTERVAL(2); + memset_big_struct(skel); + OUTPUT_INTERVAL(5); + int fd = bpf_map__fd(skel->maps.proc_syscall_info); + int fd1 = bpf_map__fd(skel->maps.container_id_map); + struct syscall_value values; + pid_t lookup_key,next_key; + + int err ; + //打印表头 + printf("%-13s %-10s %-10s %-10s %-10s %-10s\n","ContainerID", "Comm","Pid","SYSCALLID","Counts","avage_DELAY(us)"); + while(!bpf_map_get_next_key(fd,&lookup_key,&next_key)){ + err = bpf_map_lookup_elem(fd,&next_key,&values); + if (err < 0) { + fprintf(stderr, "failed to lookup values: %d\n", err); + return -1; + } + //找出最大的前五个系统调用号 + int max[5] = {-1, -1, -1, -1, -1}; // 记录前五个最大值的下标 + int top_values[5] = {0,0,0,0,0}; // 记录前五个最大值 + for (int i = 0; i < 462; i++) { + for (int j = 0; j < 5; j++) { + if (values.syscall_id_counts[i] > top_values[j]) { + // 将当前值插入到正确的位置,后面的值依次后移 + for (int k = 5 - 1; k > j; k--) { + top_values[k] = top_values[k - 1]; + max[k] = max[k - 1]; + } + top_values[j] = values.syscall_id_counts[i]; + max[j] = i; + break; + } + } + } + for(int i = 0;i<5;i++){ + if(max[i] == -1){ + continue; + } + uint64_t 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; + } + memset(&lookup_key, 0, sizeof(pid_t)); + memset(&next_key, 0, sizeof(pid_t)); + while (!bpf_map_get_next_key(fd, lookup_key, next_key)) { + err = bpf_map_delete_elem(fd, next_key); + if (err < 0) { + fprintf(stderr, "failed to cleanup map: %d\n", err); + return -1; + } + 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, const char *map_name, int err) { @@ -1262,6 +1356,7 @@ 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; @@ -1325,6 +1420,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Please specify an option using %s.\n", OPTIONS_LIST); goto cleanup; } + //打印结果 while (!exiting) { err = ring_buffer__poll(rb, RING_BUFFER_TIMEOUT_MS /* timeout, ms */); if (env.execute_hypercall) { @@ -1340,6 +1436,10 @@ int main(int argc, char **argv) { print_map_and_check_error(print_vcpu_load_map, skel, "vcpu_load", err); } + if (env.execute_container_syscall){ + //print_map_and_check_error(print_container_syscall,skel,"container_syscall",err); + print_container_syscall(skel); + } /* Ctrl-C will cause -EINTR */ if (err == -EINTR) { err = 0;