From d5cf7bcb8ed31e13233fa634d7dc9b002c574e2c Mon Sep 17 00:00:00 2001 From: wynyibo <2548712106@qq.com> Date: Sat, 10 Aug 2024 17:57:21 +0800 Subject: [PATCH] count the top 5 ports and pps within 5 seconds --- agent/plugin/Makefile | 1 + agent/plugin/common.bpf.h | 9 +++- agent/plugin/probe.bpf.c | 2 - agent/plugin/probe.c | 108 +++++++++++++++++++++++++++++++++---- agent/plugin/probe.h | 23 ++++---- agent/plugin/traffic.bpf.h | 6 +-- 6 files changed, 120 insertions(+), 29 deletions(-) diff --git a/agent/plugin/Makefile b/agent/plugin/Makefile index 6d79d5c..6d1c45c 100644 --- a/agent/plugin/Makefile +++ b/agent/plugin/Makefile @@ -83,6 +83,7 @@ $(LIBBPF_OBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPU $(BPFTOOL): | $(BPFTOOL_OUTPUT) $(call msg,BPFTOOL,$@) $(Q)$(MAKE) ARCH= CROSS_COMPILE= OUTPUT=$(BPFTOOL_OUTPUT)/ -C $(BPFTOOL_SRC) bootstrap + bpftool btf dump file /sys/kernel/btf/vmlinux format c > $(VMLINUX) # Build BPF code $(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL) diff --git a/agent/plugin/common.bpf.h b/agent/plugin/common.bpf.h index 21075ac..92e6712 100644 --- a/agent/plugin/common.bpf.h +++ b/agent/plugin/common.bpf.h @@ -68,7 +68,12 @@ struct __type(value, struct packet_count); } proto_stats SEC(".maps"); -int udp_info = 0, tcp_status_info = 0, tcp_output_info = 0; +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 65536); + __type(key, u16); + __type(value, struct packet_info); +} port_count SEC(".maps"); /*funcation hepler*/ static __always_inline int get_current_tgid() @@ -202,6 +207,7 @@ static __always_inline void get_tcp_tuple(struct sock *sk, struct tcp_metrics_s tuple->server_port = __bpf_ntohs(_R(sk, __sk_common.skc_dport)); } + static __always_inline struct packet_count *count_packet(__u32 proto, bool is_tx) { struct packet_count *count; @@ -234,4 +240,5 @@ static __always_inline struct packet_count *count_packet(__u32 proto, bool is_tx return count; } + #endif // __COMMON_BPF_H \ No newline at end of file diff --git a/agent/plugin/probe.bpf.c b/agent/plugin/probe.bpf.c index 6320607..4156fbf 100644 --- a/agent/plugin/probe.bpf.c +++ b/agent/plugin/probe.bpf.c @@ -54,13 +54,11 @@ int __handle_tcp_cleanup_rbuf(struct pt_regs *ctx) SEC("kprobe/eth_type_trans") int BPF_KPROBE(eth_type_trans,struct sk_buff *skb) { - bpf_printk("eth_type_trans"); return __eth_type_trans(skb); } //send SEC("kprobe/dev_hard_start_xmit") int BPF_KPROBE(dev_hard_start_xmit,struct sk_buff *skb) { - bpf_printk("dev_hard_start_xmit"); return __dev_hard_start_xmit(skb); } \ No newline at end of file diff --git a/agent/plugin/probe.c b/agent/plugin/probe.c index 7f40e4e..e5823fd 100755 --- a/agent/plugin/probe.c +++ b/agent/plugin/probe.c @@ -9,16 +9,17 @@ #include #include #include +#include #include #include "probe.h" #include "probe.skel.h" #include "probe.h" - static volatile bool exiting = false; -int udp_info = 0, tcp_status_info = 0, tcp_output_info = 0, protocol_info = 0; +static int udp_info = 0, tcp_status_info = 0, tcp_output_info = 0, protocol_info = 0, port_distribution = 0; struct protocol_stats proto_stats[256] = {0}; -time_t start_time; -int interval = 5; // 每5 秒计算一次 +static int interval = 5, entry_count = 0; // 每5 秒计算一次 +struct packet_info entries[MAX_ENTRIES]; +time_t start_time = 0; const char argp_program_doc[] = "Trace time delay in network subsystem \n"; @@ -26,7 +27,8 @@ static const struct argp_option opts[] = { {"udp", 'u', 0, 0, "trace the udp message"}, {"tcp_status_info", 't', 0, 0, "trace the tcp states"}, {"tcp_output_info", 'o', 0, 0, "trace the tcp flow"}, - {"protocol_info", 'p', 0, 0, "trace the tcp flow"}, + {"protocol_info", 'p', 0, 0, "statistics on the use of different protocols"}, + {"port_distribution_info", 'P', 0, 0, "statistical use of top10 destination ports"}, {}, }; @@ -46,6 +48,9 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) case 'p': protocol_info = 1; break; + case 'P': + port_distribution = 1; + break; default: return ARGP_ERR_UNKNOWN; } @@ -171,16 +176,22 @@ void calculate_protocol_usage(struct protocol_stats proto_stats[], int num_proto for (int i = 0; i < num_protocols; i++) { - if (proto_stats[i].rx_count >= last_rx[i]) { + if (proto_stats[i].rx_count >= last_rx[i]) + { delta_rx[i] = proto_stats[i].rx_count - last_rx[i]; - } else { - delta_rx[i] = proto_stats[i].rx_count; + } + else + { + delta_rx[i] = proto_stats[i].rx_count; } - if (proto_stats[i].tx_count >= last_tx[i]) { + if (proto_stats[i].tx_count >= last_tx[i]) + { delta_tx[i] = proto_stats[i].tx_count - last_tx[i]; - } else { - delta_tx[i] = proto_stats[i].tx_count; + } + else + { + delta_tx[i] = proto_stats[i].tx_count; } current_rx += delta_rx[i]; @@ -223,17 +234,79 @@ void calculate_protocol_usage(struct protocol_stats proto_stats[], int num_proto memset(proto_stats, 0, num_protocols * sizeof(struct protocol_stats)); } +int compare_by_pps(const void *a, const void *b) +{ + return ((struct packet_info *)b)->packet_count - ((struct packet_info *)a)->packet_count; +} + +void init_start_time() +{ + start_time = time(NULL); +} + +// 查找数组中是否已经记录了指定端口号和协议号 +int find_port_entry(int dst_port, int proto) +{ + for (int i = 0; i < entry_count; i++) + { + if (entries[i].dst_port == dst_port && entries[i].proto == proto) + { + return i; + } + } + return -1; +} + static int print_count_protocol_use(void *ctx, void *packet_info, size_t data_sz) { const struct packet_info *pack_protocol_info = (const struct packet_info *)packet_info; + if (protocol_info) { proto_stats[pack_protocol_info->proto].rx_count += pack_protocol_info->count.rx_count; proto_stats[pack_protocol_info->proto].tx_count += pack_protocol_info->count.tx_count; } + if (port_distribution) + { + // 查找当前端口号和协议号是否已经存在于 entries 数组中 + int index = find_port_entry(pack_protocol_info->dst_port, pack_protocol_info->proto); + if (index != -1) + { + entries[index].packet_count++; + } + else + { + if (entry_count >= MAX_ENTRIES) + { + printf("entry_count big"); + return 0; + } + entries[entry_count].dst_port = pack_protocol_info->dst_port; + entries[entry_count].proto = pack_protocol_info->proto; + entries[entry_count].packet_count = 1; + entry_count++; + } + } return 0; } +static int print_top_5_keys() +{ + printf("Entry count: %d\n", entry_count); + + // 使用 qsort 对 PPS 进行排序 + qsort(entries, entry_count, sizeof(struct packet_info), compare_by_pps); + // 输出前10个最频繁使用的端口号及其 PPS 值和协议号 + printf("==========Top %d Ports by PPS:\n", TOP_N); + for (int i = 0; i < TOP_N && i < entry_count; i++) + { + const char *proto_str = (entries[i].proto >= 0 && entries[i].proto <= 3) ? protocol[entries[i].proto] : "UNKNOWN"; + printf("Port: %d, PPS: %d, Protocol: %s\n", entries[i].dst_port, entries[i].packet_count, proto_str); + } + memset(entries, 0, entry_count * sizeof(struct packet_info)); + entry_count = 0; + return 0; +} int main(int argc, char **argv) { struct probe_bpf *skel; @@ -325,7 +398,13 @@ int main(int argc, char **argv) { printf("==========Proportion of each agreement==========\n"); } + if (port_distribution) + { + printf("==========port_distribution==========\n"); + } start_time = time(NULL); + struct timeval start, end; + gettimeofday(&start, NULL); while (!exiting) { err = ring_buffer__poll(udp_rb, 100 /* timeout, ms */); @@ -354,6 +433,13 @@ int main(int argc, char **argv) printf("Error polling perf buffer: %d\n", err); break; } + gettimeofday(&end, NULL); + if ((end.tv_sec - start.tv_sec) >= 5) + { + if (port_distribution) + print_top_5_keys(); + gettimeofday(&start, NULL); + } } cleanup: diff --git a/agent/plugin/probe.h b/agent/plugin/probe.h index b469714..de49007 100644 --- a/agent/plugin/probe.h +++ b/agent/plugin/probe.h @@ -19,11 +19,11 @@ typedef unsigned long long u64; #define MAX_SUM 1024 #define TASK_COMM_LEN 16 #define ETH_P_IP 0X0800 -#define IPPROTO_TCP 6 -#define IPPROTO_UDP 17 #define TCP 1 #define UDP 2 #define TIMEOUT_NS 5000ULL +#define TOP_N 5 +#define MAX_ENTRIES 1000 #define TCP_TX_DATA(data, delta) __sync_fetch_and_add(&((data).tx), (__u64)(delta)) #define TCP_RX_DATA(data, delta) __sync_fetch_and_add(&((data).rx), (__u64)(delta)) @@ -100,18 +100,19 @@ enum struct packet_count { - u64 rx_count; - u64 tx_count; + u64 rx_count; + u64 tx_count; }; struct packet_info { - __u32 src_ip; - __u32 dst_ip; - __u16 src_port; - __u16 dst_port; - __u32 proto; - struct packet_count count; + u32 src_ip; + u32 dst_ip; + u16 src_port; + u16 dst_port; + u32 proto; + int packet_count; + struct packet_count count; }; struct protocol_stats @@ -142,4 +143,6 @@ static const char *protocol[] = { [2] = "ICMP", [3] = "UNKNOWN", }; + + #endif diff --git a/agent/plugin/traffic.bpf.h b/agent/plugin/traffic.bpf.h index d8907ab..f18a867 100644 --- a/agent/plugin/traffic.bpf.h +++ b/agent/plugin/traffic.bpf.h @@ -275,7 +275,7 @@ static __always_inline int process_packet(struct sk_buff *skb, bool is_tx) pkt->proto = PROTO_UNKNOWN; // bpf_printk("proto=%u\n", pkt->proto); } - // bpf_printk("proto=%u\n", pkt->proto); + struct packet_count *count = count_packet(pkt->proto, is_tx); if (count) { @@ -288,10 +288,6 @@ static __always_inline int process_packet(struct sk_buff *skb, bool is_tx) pkt->count.rx_count = 0; } - // bpf_printk("pkt: src_ip=%u, dst_ip=%u, proto=%u\n", pkt->src_ip, pkt->dst_ip, pkt->proto); - // bpf_printk("src_port=%d, dst_port=%d\n", pkt->src_port, pkt->dst_port); - // bpf_printk("count_tx=%llu, count_rx=%llu\n", pkt->count.tx_count, pkt->count.rx_count); - bpf_ringbuf_submit(pkt, 0); return 0; -- Gitee