diff --git a/agent/plugin/common.bpf.h b/agent/plugin/common.bpf.h index 7e31cb2a4a092229aa64b60804d748eff030baf4..27427aeb8d3635aea898b71eaa5d3f2ec19ea7f5 100644 --- a/agent/plugin/common.bpf.h +++ b/agent/plugin/common.bpf.h @@ -42,6 +42,11 @@ struct __uint(max_entries, 1024); } perf_map SEC(".maps"); +struct +{ + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 256 * 1024); +} flags_rb SEC(".maps"); /*map helper*/ struct @@ -93,6 +98,34 @@ struct __type(value, struct tid_map_value); } inner_tid_map SEC(".maps"); +// 用于存储 SYN 包计数 +struct +{ + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 65536); + __type(key, struct addr_pair); + __type(value, u64); +} syn_count_map SEC(".maps"); + +// 用于存储 SYN-ACK 包计数 +struct +{ + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 65536); + __type(key, struct addr_pair); + __type(value, u64); +} synack_count_map SEC(".maps"); + +// 用于存储 FIN 包计数 +struct +{ + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 65536); + __type(key, struct addr_pair); + __type(value, u64); +} fin_count_map SEC(".maps"); + +static int kprobe_select = 1, fentry_select = 1, udp_info = 1,packet_count = 1,protocol_info = 1,tcp_output_info=1; /*funcation hepler*/ static __always_inline int get_current_tgid() { @@ -127,14 +160,26 @@ static __always_inline void get_udp_pkt_tuple(struct event *pkt_tuple, pkt_tuple->tran_flag = UDP; } -static void get_tcp_pkt_tuple(struct event *pkt_tuple, struct iphdr *ip, struct tcphdr *tcp) +static void get_tcp_pkt_tuple(void *pkt_tuple, struct iphdr *ip, struct tcphdr *tcp, int type) { - pkt_tuple->client_ip = _R(ip, saddr); - pkt_tuple->server_ip = _R(ip, daddr); - pkt_tuple->client_port = __bpf_ntohs(_R(tcp, source)); - pkt_tuple->server_port = __bpf_ntohs(_R(tcp, dest)); - pkt_tuple->seq = __bpf_ntohl(_R(tcp, seq)); - pkt_tuple->ack = __bpf_ntohl(_R(tcp, ack_seq)); + if (type == 1) + { // struct tuple_key + struct tuple_key *key = (struct tuple_key *)pkt_tuple; + key->saddr = _R(ip, saddr); + key->daddr = _R(ip, daddr); + key->sport = __bpf_ntohs(_R(tcp, source)); + key->dport = __bpf_ntohs(_R(tcp, dest)); + } + else if (type == 2) + { // struct event + struct event *event = (struct event *)pkt_tuple; + event->client_ip = _R(ip, saddr); + event->server_ip = _R(ip, daddr); + event->client_port = __bpf_ntohs(_R(tcp, source)); + event->server_port = __bpf_ntohs(_R(tcp, dest)); + event->seq = __bpf_ntohl(_R(tcp, seq)); + event->ack = __bpf_ntohl(_R(tcp, ack_seq)); + } } static __always_inline void *bmloti(void *map, const void *key, const void *init) @@ -174,7 +219,7 @@ static __always_inline char is_period_txrx(struct sock *sk) return 0; } -static __always_inline void report_tx_rx(void *ctx, struct tcp_metrics_s *metrics, struct sock *sk) +static __always_inline void report_tx_rx(struct tcp_metrics_s *metrics, struct sock *sk) { if (!is_period_txrx(sk)) @@ -330,4 +375,11 @@ static __always_inline int fill_sk_skb(struct drop_event *event, struct sock *sk } return 0; } +static __always_inline void fill_tcp_packet_type(struct tuple_key *devent, struct sock *sk) +{ + devent->saddr = _R(sk, __sk_common.skc_rcv_saddr); + devent->daddr = _R(sk, __sk_common.skc_daddr); + devent->sport = _R(sk, __sk_common.skc_num); + devent->dport = __bpf_ntohs(_R(sk, __sk_common.skc_dport)); +} #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 f5d6b720cefce889bf01de8f933b03aad5be4f2c..320cac18ec1d71902061cad1c4d389ed1ce12913 100644 --- a/agent/plugin/probe.bpf.c +++ b/agent/plugin/probe.bpf.c @@ -1,81 +1,239 @@ #include "common.bpf.h" #include "traffic.bpf.h" -// udp recieve -SEC("kprobe/udp_rcv") -int BPF_KPROBE(udp_rcv, struct sk_buff *skb) +/*helper*/ +static inline int udp_rcv_common(struct sk_buff *skb, bool is_fentry) { + if ((is_fentry ? !fentry_select : !kprobe_select) || !udp_info) + { + return 0; + } return __udp_rcv(skb); } - -SEC("kprobe/__udp_enqueue_schedule_skb") -int BPF_KPROBE(__udp_enqueue_schedule_skb, struct sock *sk, - struct sk_buff *skb) +static inline int udp_enqueue_common(struct sock *sk, struct sk_buff *skb, bool is_fentry) { + if ((is_fentry ? !fentry_select : !kprobe_select) || !udp_info) + { + return 0; + } return udp_enqueue_schedule_skb(sk, skb); } - -//send -SEC("kprobe/udp_send_skb") -int BPF_KPROBE(udp_send_skb, struct sk_buff *skb) +static inline int udp_send_common(struct sk_buff *skb, bool is_fentry) { + if ((is_fentry ? !fentry_select : !kprobe_select) || !udp_info) + { + return 0; + } return __udp_send_skb(skb); } +static inline int dev_hard_start_xmit_common(struct sk_buff *skb, bool is_fentry) +{ + if ((is_fentry ? !fentry_select : !kprobe_select) || !protocol_info) + { + return 0; + } +} +static inline int tcp_cleanup_common(struct sock *sk, int copied, bool is_fentry) +{ + if ((is_fentry ? !fentry_select : !kprobe_select) || !tcp_output_info) + { + return 0; + } + return __tcp_cleanup_rbuf(sk, copied); +} +static inline int tcp_send_common(struct sock *sk, struct msghdr *msg, size_t size, bool is_fentry) +{ + if ((is_fentry ? !fentry_select : !kprobe_select) || !tcp_output_info) + { + return 0; + } + return __tcp_sendmsg(sk, msg, size); +} +static inline int eth_type_trans_common(struct sk_buff *skb, bool is_fentry) +{ + if ((is_fentry ? !fentry_select : !kprobe_select) || !protocol_info) + { + return 0; + } + return __eth_type_trans(skb); +} +static inline int tcp_connect_common(struct sock *sk, bool is_fentry) +{ + if ((is_fentry ? !fentry_select : !kprobe_select) || !packet_count) + { + return 0; + } + return __tcp_connect(sk); +} +static inline int tcp_rcv_state_process_common(struct sock *sk, struct sk_buff *skb, bool is_fentry) +{ + if ((is_fentry ? !fentry_select : !kprobe_select) || !packet_count) + { + return 0; + } + return __tcp_rcv_state_process(sk, skb); +} +static inline int tcp_send_fin_common(struct sock *sk, bool is_fentry) +{ + if ((is_fentry ? !fentry_select : !kprobe_select) || !packet_count) + { + return 0; + } + return __tcp_send_fin(sk); +} +// udp recieve +SEC("kprobe/udp_rcv") +int BPF_KPROBE(kp_udp_rcv, struct sk_buff *skb) +{ + return udp_rcv_common(skb, false); +} +SEC("fentry/udp_rcv") +int BPF_PROG(ft_udp_rcv, struct sk_buff *skb) +{ + return udp_rcv_common(skb, true); +} +SEC("kprobe/__udp_enqueue_schedule_skb") +int BPF_KPROBE(kp__udp_enqueue_schedule_skb, struct sock *sk, struct sk_buff *skb) +{ + return udp_enqueue_common(sk, skb, false); +} +SEC("fentry/__udp_enqueue_schedule_skb") +int BPF_PROG(ft__udp_enqueue_schedule_skb, struct sock *sk, struct sk_buff *skb) +{ + return udp_enqueue_common(sk, skb, true); +} +SEC("kprobe/udp_send_skb") +int BPF_KPROBE(kp_udp_send_skb, struct sk_buff *skb) +{ + return udp_send_common(skb, false); +} +SEC("fentry/udp_send_skb") +int BPF_PROG(ft_udp_send_skb, struct sk_buff *skb) +{ + return udp_send_common(skb, true); +} SEC("kprobe/ip_send_skb") -int BPF_KPROBE(ip_send_skb, struct net *net, struct sk_buff *skb) +int BPF_KPROBE(kp_ip_send_skb, struct net *net, struct sk_buff *skb) { + if (!kprobe_select || !udp_info) + { + return 0; + } return __ip_send_skb(skb); } -//tcp status +// // tcp status SEC("tracepoint/sock/inet_sock_set_state") -int handle_tcp_state(struct trace_event_raw_inet_sock_set_state *ctx) { +int handle_tcp_state(struct trace_event_raw_inet_sock_set_state *ctx) +{ return __handle_tcp_state(ctx); } // protocol recieve SEC("kprobe/tcp_sendmsg") -int __handle_tcp_sendmsg(struct pt_regs *ctx) +int BPF_KPROBE(kp_tcp_sendmsg, struct sock *sk, struct msghdr *msg, size_t size) { - return __tcp_sendmsg(ctx); + return tcp_send_common(sk, msg, size, false); } +SEC("fentry/tcp_sendmsg") +int BPF_PROG(ft_tcp_sendmsg, struct sock *sk, struct msghdr *msg, size_t size) +{ + return tcp_send_common(sk, msg, size, true); +} SEC("kprobe/tcp_cleanup_rbuf") -int __handle_tcp_cleanup_rbuf(struct pt_regs *ctx) +int BPF_KPROBE(kp_tcp_cleanup_rbuf, struct sock *sk, int copied) { - return __tcp_cleanup_rbuf(ctx); + return tcp_cleanup_common(sk, copied, false); +} + +SEC("fentry/tcp_cleanup_rbuf") +int BPF_PROG(ft_tcp_cleanup_rbuf, struct sock *sk, int copied) +{ + return tcp_cleanup_common(sk, copied, true); } // count the usage of protocol ports // receive SEC("kprobe/eth_type_trans") -int BPF_KPROBE(eth_type_trans, struct sk_buff *skb) +int BPF_KPROBE(kp_eth_type_trans, struct sk_buff *skb) { - return __eth_type_trans(skb); + return eth_type_trans_common(skb, false); +} +SEC("fentry/eth_type_trans") +int BPF_PROG(ft_eth_type_trans, struct sk_buff *skb) +{ + return eth_type_trans_common(skb, true); } -// send SEC("kprobe/dev_hard_start_xmit") -int BPF_KPROBE(dev_hard_start_xmit, struct sk_buff *skb) +int BPF_KPROBE(kp_dev_hard_start_xmit, struct sk_buff *skb) +{ + return dev_hard_start_xmit_common(skb, false); +} +SEC("fentry/dev_hard_start_xmit") +int BPF_PROG(ft_dev_hard_start_xmit, struct sk_buff *skb) { - return __dev_hard_start_xmit(skb); + return dev_hard_start_xmit_common(skb, true); } -// iptables drop +// // iptables drop SEC("kprobe/ipt_do_table") -int BPF_KPROBE(ipt_do_table, struct sk_buff *skb, u32 hook, struct nf_hook_state *state) +int kp_ipt_do_table(struct pt_regs *ctx) { - struct xt_table *table = (struct xt_table *)PT_REGS_PARM4(ctx); return __ipt_do_table_start(ctx); } + SEC("kretprobe/ipt_do_table") -int BPF_KRETPROBE(ipt_do_table_ret) +int BPF_KRETPROBE(kp_ipt_do_table_ret) { int ret = PT_REGS_RC(ctx); - return __ipt_do_table_ret(ctx, ret); + __ipt_do_table_ret(ctx, ret); + return 0; } + SEC("tracepoint/skb/kfree_skb") int handle_kfree_skb(struct trace_event_raw_kfree_skb *ctx) { return __kfree_skb(ctx); } +SEC("kprobe/tcp_connect") +int BPF_KPROBE(kp_tcp_connect, struct sock *sk) +{ + return tcp_connect_common(sk, false); +} + +SEC("fentry/tcp_connect") +int BPF_PROG(ft_tcp_connect, struct sock *sk) +{ + return tcp_connect_common(sk, true); +} +SEC("kprobe/tcp_rcv_state_process") +int BPF_KPROBE(kp_tcp_rcv_state_process, struct sock *sk, struct sk_buff *skb) +{ + return tcp_rcv_state_process_common(sk, skb, false); +} +SEC("fentry/tcp_rcv_state_process") +int BPF_PROG(ft_tcp_rcv_state_process, struct sock *sk, struct sk_buff *skb) +{ + return tcp_rcv_state_process_common(sk, skb, true); +} +SEC("kprobe/tcp_send_fin") +int BPF_KPROBE(kp_tcp_send_fin, struct sock *sk) +{ + return tcp_send_fin_common(sk, false); +} +SEC("fentry/tcp_send_fin") +int BPF_PROG(ft_tcp_send_fin, struct sock *sk) +{ + return tcp_send_fin_common(sk, true); +} +// SEC("kprobe/tcp_send_reset") +// int handle_send_reset(struct pt_regs *ctx) +// { +// if (!kprobe_select || !packet_count) +// { +// return 0; +// } +// return __tcp_send_reset(ctx); +// } diff --git a/agent/plugin/probe.c b/agent/plugin/probe.c index d5d3ff4482239027e8bd9088809b4b6c78391c9f..6bf09f1ef9a47f61055b23e0f4fbaa924c9339e7 100755 --- a/agent/plugin/probe.c +++ b/agent/plugin/probe.c @@ -16,16 +16,20 @@ #include "probe.h" static volatile bool exiting = false; -static int udp_info = 0, tcp_status_info = 0, tcp_output_info = 0, protocol_info = 0, port_distribution = 0, drop_info = 0, drop_skb = 0, num_symbols = 0, cache_size = 0; +static int udp_info = 0, tcp_status_info = 0, tcp_output_info = 0, protocol_info = 0, port_distribution = 0, drop_info = 0, drop_skb = 0, num_symbols = 0, cache_size = 0, kprobe_select = 0, fentry_select = 0; +static int packet_count = 0; struct protocol_stats proto_stats[MAX] = {0}; -static int interval = 5, entry_count = 0; +static int interval = 20, entry_count = 0; struct packet_info entries[MAX_ENTRIES]; struct SymbolEntry symbols[MAXSYMBOLS]; struct SymbolEntry cache[CACHEMAXSIZE]; +static struct packet_stats hash_map[HASH_MAP_SIZE] = {0}; const char argp_program_doc[] = "Trace time delay in network subsystem \n"; static const struct argp_option opts[] = { + {"kprobe", 'K', 0, 0, "Specify the mount type"}, + {"fentry", 'F', 0, 0, "Specify the mount type"}, {"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"}, @@ -33,6 +37,7 @@ static const struct argp_option opts[] = { {"port_distribution_info", 'P', 0, 0, "statistical use of top10 destination ports"}, {"drop_info", 'i', 0, 0, "trace the iptables drop"}, {"drop_skb", 'd', 0, 0, "trace the all skb drop"}, + {"packet_count", 'c', 0, 0, "trace the packet include SYN、SYN-ACK、FIN"}, {}, }; @@ -40,6 +45,13 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) { switch (key) { + case 'K': + kprobe_select = 1; // 设置 kprobe 标志 + break; + case 'F': + fentry_select = 1; // 设置 fentry 标志 + break; + case 'u': udp_info = 1; break; @@ -61,8 +73,13 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) case 'd': drop_skb = 1; break; + case 'c': + packet_count = 1; + break; default: + fprintf(stderr, "错误: 未知选项 '%c'\n", key); return ARGP_ERR_UNKNOWN; + break; } return 0; } @@ -90,7 +107,7 @@ static void format_ip_address(__be32 ip, char *buffer, size_t buffer_size) static int print_udp_event_info(void *ctx, void *packet_info, size_t data_sz) { - if (!udp_info) + if (!udp_info || (!fentry_select && !kprobe_select)) { return 0; } @@ -120,7 +137,7 @@ static int print_udp_event_info(void *ctx, void *packet_info, size_t data_sz) static int print_tcp_state_info(void *ctx, void *packet_info, size_t data_sz) { - if (!tcp_status_info) + if (!tcp_status_info || (!fentry_select && !kprobe_select)) { return 0; } @@ -148,7 +165,7 @@ static int print_tcp_state_info(void *ctx, void *packet_info, size_t data_sz) static int print_tcp_flow_info(void *ctx, void *packet_info, size_t data_sz) { - if (!tcp_output_info) + if (!tcp_output_info || (!fentry_select && !kprobe_select)) { return 0; } @@ -263,7 +280,7 @@ static int find_port_entry(int dst_port, int proto) static int print_drop(void *ctx, void *packet_info, size_t data_sz) { - if (!drop_info) + if (!drop_info || (!fentry_select && !kprobe_select)) { return 0; } @@ -272,11 +289,6 @@ static int print_drop(void *ctx, void *packet_info, size_t data_sz) char s_str[INET_ADDRSTRLEN]; char d_str[INET_ADDRSTRLEN]; - if (!drop_info) - { - return 0; - } - format_ip_address(event->skbap.saddr, s_str, sizeof(s_str)); format_ip_address(event->skbap.daddr, d_str, sizeof(d_str)); const char *type_str = event->type >= 0 && event->type < 4 ? drop_type_str[event->type] : "UNKNOWN"; @@ -387,7 +399,7 @@ struct SymbolEntry findfunc(unsigned long int addr) static int print_drop_skb(void *ctx, void *packet_info, size_t data_sz) { - if (!drop_skb) + if (!drop_skb || (!fentry_select && !kprobe_select)) { return 0; } @@ -467,6 +479,70 @@ static int print_top_5_keys() entry_count = 0; return 0; } + +static int tuple_key_hash(const struct tuple_key *key, u8 packet_type) +{ + return (key->saddr ^ key->daddr ^ key->sport ^ key->dport ^ packet_type) % HASH_MAP_SIZE; +} + +static void output_statistics() +{ + for (int i = 0; i < HASH_MAP_SIZE; i++) + { + struct packet_stats *stats = &hash_map[i]; + if (stats->syn_count != 0 || stats->synack_count != 0 || stats->fin_count != 0) + { + char s_str[INET_ADDRSTRLEN]; + char d_str[INET_ADDRSTRLEN]; + format_ip_address(stats->key.saddr, s_str, sizeof(s_str)); + format_ip_address(stats->key.daddr, d_str, sizeof(d_str)); + printf("Tuple (Source: %s:%d, Destination: %s:%d): SYN Count: %lld, SYN-ACK Count: %lld, FIN Count: %lld\n", + s_str, stats->key.sport, d_str, stats->key.dport, + stats->syn_count, stats->synack_count, stats->fin_count); + stats->syn_count = 0; + stats->synack_count = 0; + stats->fin_count = 0; + } + } +} +static int print_packet_count(void *ctx, void *packet_info, size_t data_sz) +{ + if (!packet_info || (!fentry_select && !kprobe_select)) + { + return 0; + } + const struct tcp_event *event = (struct tcp_event *)packet_info; + + // 创建 4-tuple 作为 key + struct tuple_key key = { + .saddr = event->saddr, + .daddr = event->daddr, + .sport = event->sport, + .dport = event->dport}; + + // 包含 packet_type 以生成唯一的哈希索引 + int hash_index = tuple_key_hash(&key, event->sum.key.packet_type); + struct packet_stats *stats = &hash_map[hash_index]; + + // 存储 4-tuple 信息 + stats->key = key; + + // 根据包类型更新对应计数 + if (event->sum.key.packet_type == 1) + { // SYN + stats->syn_count = event->sum.syn_count; + } + else if (event->sum.key.packet_type == 2) + { // SYN-ACK + stats->synack_count = event->sum.synack_count; + } + else if (event->sum.key.packet_type == 3) + { // FIN + stats->fin_count = event->sum.fin_count; + } + return 0; +} + int main(int argc, char **argv) { @@ -478,6 +554,8 @@ int main(int argc, char **argv) struct ring_buffer *port_events_rb = NULL; struct ring_buffer *perf_map = NULL; struct ring_buffer *trace_all_drop = NULL; + struct ring_buffer *flags_rb = NULL; + /* Parse command line arguments */ err = argp_parse(&argp, argc, argv, 0, NULL, NULL); if (err) @@ -485,7 +563,7 @@ 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); + // libbpf_set_print(libbpf_print_fn); /* Cleaner handling of Ctrl-C */ signal(SIGINT, sig_handler); @@ -560,33 +638,40 @@ int main(int argc, char **argv) fprintf(stderr, "Failed to create ring buffer\n"); goto cleanup; } + flags_rb = ring_buffer__new(bpf_map__fd(skel->maps.flags_rb), print_packet_count, NULL, NULL); + if (!flags_rb) + { + err = -1; + fprintf(stderr, "Failed to create ring buffer\n"); + goto cleanup; + } /* Process events */ - if (udp_info) + if (udp_info && (fentry_select || kprobe_select)) { printf("%-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s\n", "Pid", "Client_ip", "Server_ip", "Client_port", "Server_port", "Comm", "Tran_time/μs", "Direction", "len/byte"); } - if (tcp_status_info) + if (tcp_status_info && (fentry_select || kprobe_select)) { printf("%-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s \n", "Pid", "Client_ip", "Server_ip", "Client_port", "Server_port", "oldstate", "newstate", "time/μs"); } - if (tcp_output_info) + if (tcp_output_info && (fentry_select || kprobe_select)) { printf("%-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s\n", "Pid", "Client_ip", "Server_ip", "Client_port", "Server_port", "Send/bytes", "receive/bytes", "segs_in", "segs_out", "Direction"); } - if (drop_info) + if (drop_info && (fentry_select || kprobe_select)) { printf("%-20s %-20s %-20s %-20s %-20s %-20s %-20s \n", "Pid", "Client_ip", "Server_ip", "Client_port", "Server_port", "Protocol", "Drop_type"); } - if (drop_skb) + if (drop_skb && (fentry_select || kprobe_select)) { printf("%-20s %-20s %-20s %-20s %-20s %-20s %-20s \n", "Pid", "Client_ip", "Server_ip", "Client_port", "Server_port", "Protocol", "DROP_addr"); } - if (protocol_info) + if (protocol_info && (fentry_select || kprobe_select)) { printf("==========Proportion of each agreement==========\n"); } - if (port_distribution) + if (port_distribution && (fentry_select || kprobe_select)) { printf("==========port_distribution==========\n"); } @@ -600,6 +685,7 @@ int main(int argc, char **argv) err = ring_buffer__poll(port_events_rb, 100 /* timeout, ms */); err = ring_buffer__poll(perf_map, 100 /* timeout, ms */); err = ring_buffer__poll(trace_all_drop, 100 /* timeout, ms */); + err = ring_buffer__poll(flags_rb, 100 /* timeout, ms */); /* Ctrl-C will cause -EINTR */ // Regularly calculate and print the proportion of agreements if (err == -EINTR) @@ -612,13 +698,16 @@ 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) >= interval) { if (port_distribution) print_top_5_keys(); - if (protocol_info) + else if (protocol_info) calculate_protocol_usage(proto_stats, 256, interval); + else if (packet_count) + output_statistics(); gettimeofday(&start, NULL); } } @@ -631,6 +720,7 @@ cleanup: ring_buffer__free(port_events_rb); ring_buffer__free(perf_map); ring_buffer__free(trace_all_drop); + ring_buffer__free(flags_rb); probe_bpf__destroy(skel); return err < 0 ? -err : 0; diff --git a/agent/plugin/probe.h b/agent/plugin/probe.h index c95ec246027b74fe3fb17e823147cb4f6a657e72..48c75566482c1b054287697dce3c5482ff4bb203 100644 --- a/agent/plugin/probe.h +++ b/agent/plugin/probe.h @@ -6,6 +6,7 @@ typedef unsigned short u16; typedef unsigned int u32; typedef unsigned long long u64; +#define ETH_HLEN 14 // 以太网头部的长度 #define MAXSYMBOLS 300000 #define CACHEMAXSIZE 5 #define SK(sk) ((const struct sock *)(sk)) @@ -33,6 +34,8 @@ typedef unsigned long long u64; #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)) #define TCP_PROBE_TXRX (u32)(1 << 3) +#define RCV_SHUTDOWN 2 +#define HASH_MAP_SIZE 1024 /* bpf.h struct helper */ struct ktime_info @@ -136,13 +139,13 @@ struct protocol_stats uint64_t tx_count; }; -struct addr_pair -{ - u32 saddr; - u32 daddr; - u16 sport; - u16 dport; +struct addr_pair { + u32 saddr; + u32 daddr; + u16 sport; + u16 dport; }; + static const char *tcp_states[] = { [1] = "ESTABLISHED", [2] = "SYN_SENT", @@ -158,6 +161,7 @@ static const char *tcp_states[] = { [12] = "NEW_SYN_RECV", [13] = "UNKNOWN", }; + static const char *protocol[] = { [0] = "TCP", [1] = "UDP", @@ -218,5 +222,31 @@ struct SymbolEntry unsigned long addr; char name[30]; }; +// 4-tuple 结构体定义 +struct tuple_key { + uint32_t saddr; + uint32_t daddr; + uint16_t sport; + uint16_t dport; + u8 packet_type; +}; + +struct packet_stats { + u64 syn_count; + u64 synack_count; + u64 fin_count; + struct tuple_key key; +}; + +struct tcp_event { + u32 saddr; + u32 daddr; + u16 sport; + u16 dport; + struct packet_stats sum; +}; + + + #endif diff --git a/agent/plugin/traffic.bpf.h b/agent/plugin/traffic.bpf.h index 4582e9809fc41d65dfef29e3ee51dbc22c5d8cf6..bac098d231bee5a45c6b7cc1dce1194911318fa4 100644 --- a/agent/plugin/traffic.bpf.h +++ b/agent/plugin/traffic.bpf.h @@ -157,7 +157,7 @@ static __always_inline int __handle_tcp_state(struct trace_event_raw_inet_sock_s return 0; } // tcp -static __always_inline void handle_tcp_metrics(struct pt_regs *ctx, struct sock *sk, size_t size, bool is_tx, int pid) +static __always_inline void handle_tcp_metrics( struct sock *sk, size_t size, bool is_tx, int pid) { struct tcp_metrics_s *metrics = get_tcp_metrics(sk); if (!metrics) @@ -188,36 +188,31 @@ static __always_inline void handle_tcp_metrics(struct pt_regs *ctx, struct sock TCP_RX_DATA(metrics->tx_rx_stats, size); } - report_tx_rx(ctx, metrics, sk); + report_tx_rx(metrics, sk); } // send -static __always_inline int __tcp_sendmsg(struct pt_regs *ctx) +static __always_inline int __tcp_sendmsg(struct sock *sk,struct msghdr *msg, size_t size) { - struct sock *sk = (struct sock *)PT_REGS_PARM1(ctx); int pid = get_current_tgid(); struct tcp_metrics_s tuple = {}; - get_tcp_tuple(sk, &tuple); - size_t send_size = (size_t)PT_REGS_PARM3(ctx); - // bpf_printk("Sending size: %zu\n", send_size); - handle_tcp_metrics(ctx, sk, send_size, true, pid); + handle_tcp_metrics(sk, size, true, pid); return 0; } // recieve -static __always_inline int __tcp_cleanup_rbuf(struct pt_regs *ctx) +static __always_inline int __tcp_cleanup_rbuf(struct sock *sk, int copied) { - struct sock *sk = (struct sock *)PT_REGS_PARM1(ctx); int pid = get_current_tgid(); struct tcp_metrics_s tuple = {}; get_tcp_tuple(sk, &tuple); - int recieve_size = (int)PT_REGS_PARM2(ctx); + int recieve_size = copied; if (recieve_size <= 0) { return 0; } // bpf_printk("recieve_size: %zu\n", recieve_size); - handle_tcp_metrics(ctx, sk, (size_t)recieve_size, false, pid); + handle_tcp_metrics( sk, (size_t)recieve_size, false, pid); return 0; } @@ -310,13 +305,13 @@ static __always_inline int __ipt_do_table_start(struct pt_regs *ctx) struct tid_map_value value = {}; struct sk_buff *skb = (struct sk_buff *)PT_REGS_PARM1(ctx); - struct nf_hook_state *state = (struct nf_hook_state *)PT_REGS_PARM3(ctx); - struct xt_table *table = (struct xt_table *)PT_REGS_PARM4(ctx); - u32 hook = (u32)PT_REGS_PARM2(ctx); + struct nf_hook_state *state = (struct nf_hook_state *)PT_REGS_PARM2(ctx); + struct xt_table *table = (struct xt_table *)PT_REGS_PARM3(ctx); + // u32 hook = (u32)PT_REGS_PARM2(ctx); value.skb = skb; value.state = state; - value.hook = hook; + // value.hook = hook; value.table = table; bpf_map_update_elem(&inner_tid_map, &tid, &value, BPF_ANY); @@ -355,7 +350,7 @@ static __always_inline int submit_event(struct pt_regs *ctx, struct tid_map_valu bpf_probe_read(event->name, sizeof(event->name), (void *)addr); } - event->hook = value->hook; + // event->hook = value->hook; } bpf_ringbuf_submit(event, 0); return 1; @@ -370,18 +365,15 @@ static __always_inline int handle_drop_event(struct pt_regs *ctx, int ret, struc return submit_event(ctx, value, drop_type); } -static __always_inline int __ipt_do_table_ret(struct pt_regs *ctx, int ret) -{ +static __always_inline int __ipt_do_table_ret(struct pt_regs *ctx, int ret) { u32 tid = bpf_get_current_pid_tgid(); struct tid_map_value *value = bpf_map_lookup_elem(&inner_tid_map, &tid); - if (handle_drop_event(ctx, ret, value, DROP_IPTABLES_DROP)) - { + if (handle_drop_event(ctx, ret, value, DROP_IPTABLES_DROP)) { bpf_map_delete_elem(&inner_tid_map, &tid); } return 0; } - static __always_inline int __kfree_skb(struct trace_event_raw_kfree_skb *ctx) { struct sk_buff *skb = ctx->skbaddr; @@ -390,7 +382,7 @@ static __always_inline int __kfree_skb(struct trace_event_raw_kfree_skb *ctx) struct iphdr *ip = extract_iphdr(skb); struct tcphdr *tcp = extract_tcphdr(skb); struct event devent = {0}; - get_tcp_pkt_tuple(&devent, ip, tcp); + get_tcp_pkt_tuple(&devent, ip, tcp,2); struct reasonissue *event; event = bpf_ringbuf_reserve(&trace_all_drop, sizeof(*event), 0); if (!event) @@ -410,3 +402,89 @@ static __always_inline int __kfree_skb(struct trace_event_raw_kfree_skb *ctx) bpf_ringbuf_submit(event, 0); return 0; } + +static __always_inline void update_packet_count(void *map, struct tuple_key *devent, u8 packet_type) +{ + u64 *count = bpf_map_lookup_elem(map, devent); + u64 new_count = 1; + + if (!count) + { + bpf_map_update_elem(map, devent, &new_count, BPF_ANY); + count = &new_count; + } + else + { + __atomic_add_fetch(count, 1, __ATOMIC_RELAXED); + } + + struct tcp_event *event = bpf_ringbuf_reserve(&flags_rb, sizeof(*event), 0); + if (!event) + { + return; + } + __builtin_memset(event, 0, sizeof(*event)); + event->saddr = devent->saddr; + event->daddr = devent->daddr; + event->sport = devent->sport; + event->dport = devent->dport; + event->sum.key.packet_type = packet_type; + switch (event->sum.key.packet_type) + { + case 1: // syn + event->sum.syn_count = *count; + break; + case 2: // syn-ack + event->sum.synack_count = *count; + break; + case 3: // fin + event->sum.fin_count = *count; + break; + default: + break; + } + bpf_ringbuf_submit(event, 0); +} + +static __always_inline int __tcp_connect(struct sock *sk) +{ + if (!sk ) + return 0; + struct tuple_key devent = {0}; + fill_tcp_packet_type(&devent, sk); // SYN packet type + // update SYN + update_packet_count(&syn_count_map, &devent, 1); + return 0; +} + +static __always_inline int __tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) +{ + if (!sk || !skb) + return 0; + struct iphdr *ip = extract_iphdr(skb); + struct tcphdr *tcp = extract_tcphdr(skb); + struct tuple_key devent = {0}; + get_tcp_pkt_tuple(&devent, ip, tcp,1); + + // update SYN-ACK + update_packet_count(&synack_count_map, &devent, 2); + return 0; +} + +static __always_inline int __tcp_send_fin(struct sock *sk) +{ + if (!sk) + return 0; + struct tuple_key devent = {0}; + fill_tcp_packet_type(&devent, sk); // FIN packet type + // update FIN + update_packet_count(&fin_count_map, &devent, 3); + return 0; +} + +// 捕获 RST 包 +// static __always_inline int __tcp_send_reset(struct pt_regs *ctx) { +// // 增加 RST 包计数 +// increment_packet_count(RST); +// return 0; +// } \ No newline at end of file