diff --git a/.github/workflows/ebpf_stack_analyser.yml b/.github/workflows/ebpf_stack_analyser.yml index ef5a99d5b..d5a37e6a8 100644 --- a/.github/workflows/ebpf_stack_analyser.yml +++ b/.github/workflows/ebpf_stack_analyser.yml @@ -23,7 +23,7 @@ jobs: - name: Install native lib dependencies run: | - git submodule update --init --recursive eBPF_Supermarket/Stack_Analyser/ MagicEyes/ + git submodule update --init --recursive eBPF_Supermarket/lib/ MagicEyes/ sudo apt install clang libelf1 libelf-dev zlib1g-dev - name: Compile test examples diff --git a/.gitmodules b/.gitmodules index 122b510a0..a2d3cd09c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -46,9 +46,6 @@ [submodule "eBPF_Supermarket/CPU_Subsystem/libbpf"] path = eBPF_Supermarket/CPU_Subsystem/libbpf url = https://github.com/libbpf/libbpf.git -[submodule "eBPF_Supermarket/Stack_Analyser/libbpf-bootstrap"] - path = eBPF_Supermarket/Stack_Analyser/libbpf-bootstrap - url = https://github.com/libbpf/libbpf-bootstrap.git [submodule "eBPF_Supermarket/Network_Subsystem/net_manager/lib/libbpf"] path = eBPF_Supermarket/Network_Subsystem/net_manager/lib/libbpf url = https://github.com/libbpf/libbpf.git diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/common.bpf.h b/eBPF_Supermarket/Network_Subsystem/net_watcher/common.bpf.h index 8ee64f3c5..1ad6d1771 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/common.bpf.h +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/common.bpf.h @@ -227,10 +227,18 @@ struct { const volatile int filter_dport = 0; const volatile int filter_sport = 0; const volatile int all_conn = 0, err_packet = 0, extra_conn_info = 0, - layer_time = 0, http_info = 0, retrans_info = 0, udp_info =0,net_filter = 0,drop_reason = 0,icmp_info = 0 ,tcp_info = 0 ,dns_info = 0; + layer_time = 0, http_info = 0, retrans_info = 0, udp_info =0,net_filter = 0, + drop_reason = 0,icmp_info = 0 ,tcp_info = 0 ,dns_info = 0 ,stack_info = 0; /* help macro */ +#define FILTER \ + if(filter_dport&&filter_dport!= pkt_tuple.dport) \ + return 0; \ + if(filter_sport&&filter_sport!= pkt_tuple.sport) \ + return 0; \ + + // 连接的目标端口是否匹配于filter_dport的值 #define FILTER_DPORT \ if (filter_dport) { \ diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/drop.bpf.h b/eBPF_Supermarket/Network_Subsystem/net_watcher/drop.bpf.h index 87dd7b707..8c7883c17 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/drop.bpf.h +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/drop.bpf.h @@ -42,6 +42,7 @@ int __tp_kfree(struct trace_event_raw_kfree_skb *ctx) message->location = (long)ctx->location; message->drop_reason = ctx->reason; bpf_ringbuf_submit(message,0); - getstack(ctx); + if(stack_info) + getstack(ctx); return 0; } \ No newline at end of file diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netfilter.bpf.h b/eBPF_Supermarket/Network_Subsystem/net_watcher/netfilter.bpf.h index f07db7d10..5e92a025c 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netfilter.bpf.h +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netfilter.bpf.h @@ -22,7 +22,7 @@ int submit_nf_time(struct packet_tuple pkt_tuple, struct filtertime *tinfo, int { int time =0; struct netfilter *message; - + FILTER message = bpf_ringbuf_reserve(&netfilter_rb, sizeof(*message), 0); if(!message){ return 0; @@ -116,7 +116,6 @@ int store_nf_time(struct sk_buff *skb, int hook) return 0; } } - tinfo->time[hook] = bpf_ktime_get_ns() / 1000; if(hook == e_ip_local_deliver_finish){ submit_nf_time(tinfo->init, tinfo, 1); diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c index a4a173d1e..e2b5c3d09 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c @@ -43,7 +43,7 @@ static int sport = 0, dport = 0; // for filter static int all_conn = 0, err_packet = 0, extra_conn_info = 0, layer_time = 0, http_info = 0, retrans_info = 0, udp_info = 0, net_filter = 0, drop_reason = 0, addr_to_func = 0, icmp_info = 0, tcp_info = 0, - time_load = 0, dns_info = 0; // flag + time_load = 0, dns_info = 0, stack_info=0; // flag static const char *tcp_states[] = { [1] = "ESTABLISHED", [2] = "SYN_SENT", [3] = "SYN_RECV", @@ -75,6 +75,7 @@ static const struct argp_option opts[] = { "set to trace dns information info include Id 事务ID、Flags 标志字段、Qd " "问题部分计数、An 应答记录计数、Ns 授权记录计数、Ar 附加记录计数、Qr " "域名、rx 收发包 "}, + {"stack", 'A', 0, 0, "set to trace of stack "}, {}}; static error_t parse_arg(int key, char *arg, struct argp_state *state) { @@ -128,6 +129,9 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) { case 'D': dns_info = 1; break; + case 'A': + stack_info = 1; + break; default: return ARGP_ERR_UNKNOWN; } @@ -364,6 +368,7 @@ static void set_rodata_flags(struct netwatcher_bpf *skel) { skel->rodata->tcp_info = tcp_info; skel->rodata->icmp_info = icmp_info; skel->rodata->dns_info = dns_info; + skel->rodata->stack_info = stack_info; } static void set_disable_load(struct netwatcher_bpf *skel) { @@ -506,48 +511,48 @@ 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", "Daddr", + "Sprot", "Dprot", "udp_time/μs", "RX/direction", "len/byte"); break; case MODE_NET_FILTER: printf("===============================================================" - "===NET FILTER " + "===NETFILTER " "INFORMATION====================================================" "=======\n"); printf("%-20s %-20s %-12s %-12s %-8s %-8s %-7s %-8s %-8s %-8s\n", - "saddr", "daddr", "dprot", "sprot", "PreRT/μs", "L_IN/μs", - "FW/μs", "PostRT/μs", "L_OUT/μs", "rx/direction"); + "Saddr", "Daddr", "Sprot", "Dprot", "PreRT/μs", "L_IN/μs", + "FW/μs", "PostRT/μs", "L_OUT/μs", "RX/direction"); break; case MODE_DROP_REASON: printf("===============================================================" "DROP " "INFORMATION====================================================" "====\n"); - printf("%-13s %-17s %-17s %-10s %-10s %-9s %-33s %-30s\n", "time", - "saddr", "daddr", "sprot", "dprot", "prot", "addr", "reason"); + printf("%-13s %-17s %-17s %-10s %-10s %-9s %-33s %-30s\n", "Time", + "Saddr", "Daddr", "Sprot", "Dprot", "prot", "addr", "reason"); break; case MODE_ICMP: printf("=================================================ICMP " "INFORMATION==============================================\n"); - printf("%-20s %-20s %-20s %-20s\n", "saddr", "daddr", "icmp_time/μs", - "tx//direction"); + printf("%-20s %-20s %-20s %-20s\n", "Saddr", "Daddr", "icmp_time/μs", + "RX/direction"); break; case MODE_TCP: printf("===============================================================" "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", "Daddr", + "Sport", "Dport", "oldstate", "newstate", "time/μs"); break; case MODE_DNS: printf("===============================================================" "====================DNS " "INFORMATION====================================================" "============================\n"); - printf("%-20s %-20s %-12s %-12s %-12s %-12s %-12s %-11s %-47s %5s \n", - "saddr", "daddr", "Id", "Flags", "Qd", "An", "Ns", "Ar", "Qr", - "rx/direction"); + printf("%-20s %-20s %-12s %-12s %-5s %-5s %-5s %-5s %-47s %5s \n", + "Saddr", "Daddr", "Id", "Flags", "Qd", "An", "Ns", "Ar", "Qr", + "RX/direction"); break; case MODE_DEFAULT: printf("===============================================================" @@ -555,12 +560,19 @@ static void print_header(enum MonitorMode mode) { "======================\n"); printf("%-22s %-20s %-8s %-20s %-8s %-15s %-15s %-15s %-15s %-15s \n", "SOCK", "Saddr", "Sport", "Daddr", "Dport", "MAC_TIME/μs", - "IP_TIME/μs", "TRAN_TIME/μs", "RX//direction", "HTTP"); + "IP_TIME/μs", "TRAN_TIME/μs", "RX/direction", "HTTP"); break; } } static void open_log_files() { + FILE *connect_file = fopen(connects_file_path, "w+"); + if (connect_file == NULL) { + fprintf(stderr, "Failed to open connect.log: (%s)\n", strerror(errno)); + exit(EXIT_FAILURE); + } + fclose(connect_file); + FILE *err_file = fopen(err_file_path, "w+"); if (err_file == NULL) { fprintf(stderr, "Failed to open err.log: (%s)\n", strerror(errno)); @@ -1000,7 +1012,7 @@ static int print_dns(void *ctx, void *packet_info, size_t size) { print_domain_name((const unsigned char *)pack_info->data, domain_name); - printf("%-20s %-20s %-#12x %-#12x %-12x %-12x %-12x %-11x %-47s %-10d\n", + printf("%-20s %-20s %-#12x %-#12x %-5x %-5x %-5x %-5x %-47s %-10d\n", s_str, d_str, pack_info->id, pack_info->flags, pack_info->qdcount, pack_info->ancount, pack_info->nscount, pack_info->arcount, domain_name, pack_info->rx); diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/udp.bpf.h b/eBPF_Supermarket/Network_Subsystem/net_watcher/udp.bpf.h index 2feb3a9a8..af739e859 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/udp.bpf.h +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/udp.bpf.h @@ -23,6 +23,7 @@ static __always_inline int __udp_rcv(struct sk_buff *skb) { struct udphdr *udp = skb_to_udphdr(skb); struct packet_tuple pkt_tuple = {0}; get_udp_pkt_tuple(&pkt_tuple, ip, udp); + FILTER struct ktime_info *tinfo, zero = {0}; tinfo = (struct ktime_info *)bpf_map_lookup_or_try_init(×tamps, &pkt_tuple, &zero); @@ -40,6 +41,7 @@ static __always_inline int udp_enqueue_schedule_skb(struct sock *sk, struct udphdr *udp = skb_to_udphdr(skb); struct packet_tuple pkt_tuple = {0}; get_udp_pkt_tuple(&pkt_tuple, ip, udp); + FILTER struct ktime_info *tinfo, zero = {0}; tinfo = bpf_map_lookup_elem(×tamps, &pkt_tuple); if (tinfo == NULL) { @@ -75,6 +77,7 @@ static __always_inline int __udp_send_skb(struct sk_buff *skb) { pkt_tuple.sport = sport; // 源端口 pkt_tuple.dport = __bpf_ntohs(dport); // 目的端口并进行字节序转换 pkt_tuple.tran_flag = UDP; + FILTER struct ktime_info *tinfo, zero = {0}; bpf_printk("udp_send_skb%d %d %d %d", pkt_tuple.saddr, pkt_tuple.daddr, pkt_tuple.sport, pkt_tuple.dport); @@ -93,8 +96,7 @@ static __always_inline int __ip_send_skb(struct sk_buff *skb) { struct udphdr *udp = skb_to_udphdr(skb); struct packet_tuple pkt_tuple = {0}; get_udp_pkt_tuple(&pkt_tuple, ip, udp); - bpf_printk("ip_send_skb%d %d %d %d", pkt_tuple.saddr, pkt_tuple.daddr, - pkt_tuple.sport, pkt_tuple.dport); + FILTER struct ktime_info *tinfo, zero = {0}; tinfo = bpf_map_lookup_elem(×tamps, &pkt_tuple); if (tinfo == NULL) { diff --git a/eBPF_Supermarket/Stack_Analyser/Makefile b/eBPF_Supermarket/Stack_Analyser/Makefile index 37cbf813e..0b17426e8 100644 --- a/eBPF_Supermarket/Stack_Analyser/Makefile +++ b/eBPF_Supermarket/Stack_Analyser/Makefile @@ -19,8 +19,11 @@ OUTPUT := .output BPF_SKEL := bpf_skel CLANG ?= clang -LIBBPF_SRC := $(abspath libbpf-bootstrap/libbpf/src) -BPFTOOL_SRC := $(abspath libbpf-bootstrap/bpftool/src) +CXX := clang +LIB := ../lib +LIBBPF_ROOT := $(abspath $(LIB)/libbpf) +LIBBPF_SRC := $(LIBBPF_ROOT)/src +BPFTOOL_SRC := $(abspath $(LIB)/bpftool/src) LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a) BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool) BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool @@ -31,11 +34,12 @@ ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \ | sed 's/mips.*/mips/' \ | sed 's/riscv64/riscv/' \ | sed 's/loongarch64/loongarch/') -VMLINUX := libbpf-bootstrap/vmlinux/$(ARCH)/vmlinux.h + +VMLINUX := $(LIB)/vmlinux.h # Use our own libbpf API headers and Linux UAPI headers distributed with # libbpf to avoid dependency on system-wide headers, which could be missing or # outdated -INCLUDES := -I./include -I./$(OUTPUT) -I./$(BPF_SKEL) -I./libbpf-bootstrap/libbpf/include/uapi -I$(dir $(VMLINUX)) +INCLUDES := -I./include -I./$(OUTPUT) -I./$(BPF_SKEL) -I$(LIBBPF_ROOT)/include/uapi -I$(dir $(VMLINUX)) CFLAGS := -Og -Wall ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) @@ -85,6 +89,16 @@ clean: $(call msg,CLEAN) $(Q)rm -rf $(OUTPUT) $(TARGETS) $(BPF_SKEL) +init: + $(call msg,INIT,$(LIB)) + $(Q)git submodule update --init --recursive ../lib/ + +$(LIBBPF_SRC) $(BPFTOOL_SRC): init + +$(VMLINUX): + $(call msg,BTFDUMP,$@) + $(Q)bpftool btf dump file /sys/kernel/btf/vmlinux format c > $@ + $(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT) $(BPF_SKEL): $(call msg,MKDIR,$@) $(Q)mkdir -p $@ diff --git a/eBPF_Supermarket/Stack_Analyser/README.md b/eBPF_Supermarket/Stack_Analyser/README.md index efcea400e..2df17eb1b 100644 --- a/eBPF_Supermarket/Stack_Analyser/README.md +++ b/eBPF_Supermarket/Stack_Analyser/README.md @@ -61,21 +61,34 @@ Stack_Analyzer是一个基于eBPF的按照指定时间间隔(默认为5s)来 ## 编译要求 -Ubuntu下需要安装一下依赖,其他发行版类似 +初始化并更新libbpf和bpftool的代码仓库: ```shell -$ git submodule update --init --recursive -$ apt install clang libelf1 libelf-dev zlib1g-dev +git submodule update --init --recursive ../lib/* ``` +需要安装一下依赖: -g++-10以上,clang-12以上 +Ubuntu下 + +```shell +sudo apt update +sudo apt install -y clang libelf1 libelf-dev zlib1g-dev bpftool +``` + +CentOS下 + +```shell +sudo dnf install clang elfutils-libelf elfutils-libelf-devel zlib-devel bpftool +``` + +clang-12以上 # 使用方法 ## 工具编译 ```shell -$ make +$ make -j$(nproc) ``` ## 命令使用方法 diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c index 292066b21..24f2a14e7 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c @@ -484,7 +484,7 @@ int memleak__mm_page_free(struct trace_event_raw_mm_page_free *ctx) SEC("tracepoint/percpu/percpu_alloc_percpu") int memleak__percpu_alloc_percpu(struct trace_event_raw_percpu_alloc_percpu *ctx) { - gen_alloc_enter(ctx->bytes_alloc); + gen_alloc_enter(ctx->size); return gen_alloc_exit2(ctx, (u64)(ctx->ptr)); } diff --git a/eBPF_Supermarket/Stack_Analyser/libbpf-bootstrap b/eBPF_Supermarket/Stack_Analyser/libbpf-bootstrap deleted file mode 160000 index b0c8234df..000000000 --- a/eBPF_Supermarket/Stack_Analyser/libbpf-bootstrap +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b0c8234dfb8f31eb12c99b26bb2bec96eb76aff3 diff --git a/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.c b/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.c index ccfa4d95e..daf3c22d7 100644 --- a/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.c +++ b/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.c @@ -328,6 +328,7 @@ static struct env { bool execute_ioctl; bool execute_timer; bool verbose; + bool show; int monitoring_time; pid_t vm_pid; enum EventType event_type; @@ -347,6 +348,7 @@ static struct env { .verbose = false, .monitoring_time = 0, .vm_pid = -1, + .show = false, .event_type = NONE_TYPE, }; @@ -376,6 +378,7 @@ static const struct argp_option opts[] = { "Monitoring the data of mmio page fault.(The -f option must be " "specified.)"}, {"vm_pid", 'p', "PID", 0, "Specify the virtual machine pid to monitor."}, + {"show", 's', NULL, 0, "Visual display"}, {"monitoring_time", 't', "SEC", 0, "Time for monitoring."}, {"kvm_ioctl", 'l', NULL, 0, "Monitoring the KVM IOCTL."}, {"kvm_timer", 'T', NULL, 0, "Monitoring the KVM hv or software timer."}, @@ -386,6 +389,9 @@ static const struct argp_option opts[] = { // 解析命令行参数 static error_t parse_arg(int key, char *arg, struct argp_state *state) { switch (key) { + case 's': + env.show = true; + break; case 'H': argp_state_help(state, stderr, ARGP_HELP_STD_HELP); break; @@ -735,11 +741,12 @@ static int print_event_head(struct env *env) { "VAILD?"); break; case EXIT: - printf("Waiting vm_exit ... \n"); + //可视化调整输出格式 + // printf("Waiting vm_exit ... \n"); break; case VCPU_LOAD: //可视化调整输出格式 - //printf("Waiting vm_vcpu_load ... \n"); + // printf("Waiting vm_vcpu_load ... \n"); break; case HALT_POLL: printf("%-18s %-15s %-15s %-10s %-7s %-11s %-10s\n", "TIME(ms)", @@ -1023,38 +1030,60 @@ int print_vcpu_load_map(struct kvm_watcher_bpf *skel) { int fd = bpf_map__fd(skel->maps.load_map); int err; struct load_key lookup_key = {}; - struct load_key next_key = {}; + struct load_key next_key = {}; struct load_value load_value = {}; - //可视化调整输出格式 - //int first = 1; - while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) { + int first = 1; + if (env.show) { if (is_first) { + printf("%-12s %-12s %-12s %-12s %-12s %-12s %-12s %-12s\n", "pid", + "tid", "total_time", "max_time", "min_time", "counts", + "vcpuid", "pcpuid"); is_first = 0; - //可视化调整输出格式 - //printf("\nTIME:%s\n", getCurrentTimeFormatted()); + } + while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) { + err = bpf_map_lookup_elem(fd, &next_key, &load_value); + if (err < 0) { + fprintf(stderr, "failed to lookup vcpu_load_value: %d\n", err); + return -1; + } + printf("%-12d %-12d %-12.4f %-12.4f %-12.4f %-12u %-12d %-12d\n", + next_key.pid, next_key.tid, + NS_TO_MS_WITH_DECIMAL(load_value.total_time), + NS_TO_MS_WITH_DECIMAL(load_value.max_time), + NS_TO_MS_WITH_DECIMAL(load_value.min_time), load_value.count, + load_value.vcpu_id, load_value.pcpu_id); + + lookup_key = next_key; + } + + } else { + if (first) { + first = 0; + printf("\nTIME:%s\n", getCurrentTimeFormatted()); printf("%-12s %-12s %-12s %-12s %-12s %-12s %-12s %-12s\n", "pid", "tid", "total_time", "max_time", "min_time", "counts", "vcpuid", "pcpuid"); - //可视化调整输出格式 - // printf( - // "------------ ------------ ------------ ------------ " - // "------------ " - // "------------ " - // "------------ " - // "------------\n"); + printf( + "------------ ------------ ------------ ------------ " + "------------ " + "------------ " + "------------ " + "------------\n"); } - err = bpf_map_lookup_elem(fd, &next_key, &load_value); - if (err < 0) { - fprintf(stderr, "failed to lookup vcpu_load_value: %d\n", err); - return -1; + while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) { + err = bpf_map_lookup_elem(fd, &next_key, &load_value); + if (err < 0) { + fprintf(stderr, "failed to lookup vcpu_load_value: %d\n", err); + return -1; + } + printf("%-12d %-12d %-12.4f %-12.4f %-12.4f %-12u %-12d %-12d\n", + next_key.pid, next_key.tid, + NS_TO_MS_WITH_DECIMAL(load_value.total_time), + NS_TO_MS_WITH_DECIMAL(load_value.max_time), + NS_TO_MS_WITH_DECIMAL(load_value.min_time), load_value.count, + load_value.vcpu_id, load_value.pcpu_id); + lookup_key = next_key; } - printf("%-12d %-12d %-12.4f %-12.4f %-12.4f %-12u %-12d %-12d\n", - next_key.pid, next_key.tid, - NS_TO_MS_WITH_DECIMAL(load_value.total_time), - NS_TO_MS_WITH_DECIMAL(load_value.max_time), - NS_TO_MS_WITH_DECIMAL(load_value.min_time), load_value.count, - load_value.vcpu_id, load_value.pcpu_id); - lookup_key = next_key; } clear_map(&lookup_key, &next_key, VCPU_LOAD, fd); return 0; @@ -1070,50 +1099,68 @@ void __print_exit_map(int fd, enum NameType name_type) { // Iterate over the array __u32 pid = 0; __u32 tid = 0; - for (int i = 0; i < count; i++) { - if (first_run) { - first_run = 0; - if (name_type == EXIT_NR) { - printf( - "============================================KVM_EXIT======" - "========" - "==============================\n"); - } else if (name_type == EXIT_USERSPACE_NR) { + if (env.show) { + if (is_first) { + printf("%-12s %-12s %-12s %-12s %-12s %-12s\n", "PID", "TID", + "TOTAL_TIME", "MAX_TIME", "MIN_TIME", "COUNT"); + is_first = 0; + } + for (int i = 0; i < count; i++) { + printf("%-12d %-12d %-12.4f %-12.4f %-12.4f %-12u\n", keys[i].pid, + keys[i].tid, NS_TO_MS_WITH_DECIMAL(values[i].total_time), + NS_TO_MS_WITH_DECIMAL(values[i].max_time), + NS_TO_MS_WITH_DECIMAL(values[i].min_time), values[i].count); + } + + } else { + for (int i = 0; i < count; i++) { + if (first_run) { + first_run = 0; + if (name_type == EXIT_NR) { + printf( + "============================================KVM_EXIT==" + "====" + "========" + "==============================\n"); + } else if (name_type == EXIT_USERSPACE_NR) { + printf( + "\n=======================================KVM_" + "USERSPACE_" + "EXIT=======" + "================================\n"); + } else { + return; + } + printf("%-12s %-12s %-12s %-12s %-12s %-12s %-12s\n", "PID", + "TID", "TOTAL_TIME", "MAX_TIME", "MIN_TIME", "COUNT", + "REASON"); printf( - "\n=======================================KVM_USERSPACE_" - "EXIT=======" - "================================\n"); - } else { - return; + "------------ ------------ ------------ ------------ " + "------------ " + "------------ " + "------------\n"); } - printf("%-12s %-12s %-12s %-12s %-12s %-12s %-12s\n", "PID", "TID", - "TOTAL_TIME", "MAX_TIME", "MIN_TIME", "COUNT", "REASON"); - printf( - "------------ ------------ ------------ ------------ " - "------------ " - "------------ " - "------------\n"); - } - // Print the current entry - if (tid == 0 || tid != keys[i].tid) { - tid = keys[i].tid; - if (pid == 0 || pid != keys[i].pid) { - pid = keys[i].pid; - printf("%-13d", pid); - } else { - printf("%-13s", ""); + // Print the current entry + if (tid == 0 || tid != keys[i].tid) { + tid = keys[i].tid; + if (pid == 0 || pid != keys[i].pid) { + pid = keys[i].pid; + printf("%-13d", pid); + } else { + printf("%-13s", ""); + } + printf("%-12d %-12.4f %-12.4f %-12.4f %-12u %-12s\n", + keys[i].tid, NS_TO_MS_WITH_DECIMAL(values[i].total_time), + NS_TO_MS_WITH_DECIMAL(values[i].max_time), + NS_TO_MS_WITH_DECIMAL(values[i].min_time), + values[i].count, getName(keys[i].reason, name_type)); + } else if (tid == keys[i].tid) { + printf("%25s %-12.4f %-12.4f %-12.4f %-12u %-12s\n", "", + NS_TO_MS_WITH_DECIMAL(values[i].total_time), + NS_TO_MS_WITH_DECIMAL(values[i].max_time), + NS_TO_MS_WITH_DECIMAL(values[i].min_time), + values[i].count, getName(keys[i].reason, name_type)); } - printf("%-12d %-12.4f %-12.4f %-12.4f %-12u %-12s\n", keys[i].tid, - NS_TO_MS_WITH_DECIMAL(values[i].total_time), - NS_TO_MS_WITH_DECIMAL(values[i].max_time), - NS_TO_MS_WITH_DECIMAL(values[i].min_time), values[i].count, - getName(keys[i].reason, name_type)); - } else if (tid == keys[i].tid) { - printf("%25s %-12.4f %-12.4f %-12.4f %-12u %-12s\n", "", - NS_TO_MS_WITH_DECIMAL(values[i].total_time), - NS_TO_MS_WITH_DECIMAL(values[i].max_time), - NS_TO_MS_WITH_DECIMAL(values[i].min_time), values[i].count, - getName(keys[i].reason, name_type)); } } clear_map(&lookup_key, &next_key, EXIT, fd); @@ -1121,7 +1168,7 @@ void __print_exit_map(int fd, enum NameType name_type) { int print_exit_map(struct kvm_watcher_bpf *skel) { int exit_fd = bpf_map__fd(skel->maps.exit_map); int userspace_exit_fd = bpf_map__fd(skel->maps.userspace_exit_map); - //printf("\nTIME:%s\n", getCurrentTimeFormatted()); + // printf("\nTIME:%s\n", getCurrentTimeFormatted()); __print_exit_map(exit_fd, EXIT_NR); __print_exit_map(userspace_exit_fd, EXIT_USERSPACE_NR); return 0; @@ -1156,7 +1203,7 @@ int main(int argc, char **argv) { struct kvm_watcher_bpf *skel; int err; //可视化调整输出格式 - //print_logo(); + // print_logo(); /*解析命令行参数*/ err = argp_parse(&argp, argc, argv, 0, NULL, NULL);