diff --git a/agent/plugin/common.bpf.h b/agent/plugin/common.bpf.h index 51ae29d9457460eea8b81cf40557231ffc0073a6..81894a01fa608dd11999cd1d007128e4d83df6ff 100644 --- a/agent/plugin/common.bpf.h +++ b/agent/plugin/common.bpf.h @@ -24,6 +24,7 @@ struct } tcp_rb SEC(".maps"); /*map helper*/ + struct { __uint(type, BPF_MAP_TYPE_LRU_HASH); @@ -40,7 +41,6 @@ struct __type(value, u64); } tcp_status SEC(".maps"); - /*funcation hepler*/ static __always_inline int get_current_tgid() { diff --git a/agent/plugin/probe.bpf.c b/agent/plugin/probe.bpf.c index 4b5c716bf7f293a4bc04caaa0a19082acfbe0b2e..e341418a122da649f109827bf70f90ac086387e7 100644 --- a/agent/plugin/probe.bpf.c +++ b/agent/plugin/probe.bpf.c @@ -28,3 +28,8 @@ int BPF_KPROBE(ip_send_skb, struct net *net, struct sk_buff *skb) return __ip_send_skb(skb); } +//tcp status +SEC("tracepoint/sock/inet_sock_set_state") +int handle_tcp_state(struct trace_event_raw_inet_sock_set_state *ctx) { + return __handle_tcp_state(ctx); +} diff --git a/agent/plugin/probe.c b/agent/plugin/probe.c index 703a42495bc7cf0b57369a8d5aa89a9d7e217ff5..eed6ac073a4c21bbeb3d53778439397d764c08a5 100755 --- a/agent/plugin/probe.c +++ b/agent/plugin/probe.c @@ -15,12 +15,13 @@ #include "probe.h" static volatile bool exiting = false; -int udp_info = 0; +int udp_info = 0, tcp_status_info = 0; const char argp_program_doc[] = "Trace time delay in network subsystem \n"; static const struct argp_option opts[] = { {"udp", 'u', 0, 0, "trace the udp message"}, + {"tcp_status_info", 't', 0, 0, "trace the tcp states"}, {}, }; @@ -31,6 +32,9 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) case 'u': udp_info = 1; break; + case 't': + tcp_status_info = 1; + break; default: return ARGP_ERR_UNKNOWN; } @@ -43,6 +47,22 @@ static const struct argp argp = { .doc = argp_program_doc, }; +static const char *tcp_states[] = { + [1] = "ESTABLISHED", + [2] = "SYN_SENT", + [3] = "SYN_RECV", + [4] = "FIN_WAIT1", + [5] = "FIN_WAIT2", + [6] = "TIME_WAIT", + [7] = "CLOSE", + [8] = "CLOSE_WAIT", + [9] = "LAST_ACK", + [10] = "LISTEN", + [11] = "CLOSING", + [12] = "NEW_SYN_RECV", + [13] = "UNKNOWN", +}; + static void sig_handler(int sig) { exiting = true; @@ -53,28 +73,69 @@ static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va return vfprintf(stderr, format, args); } -static int handle_event(void *ctx, void *packet_info, size_t data_sz) +static void format_ip_address(__be32 ip, char *buffer, size_t buffer_size) +{ + inet_ntop(AF_INET, &ip, buffer, buffer_size); +} + +static void print_udp_event_info(const struct event *pack_info) { - if (!udp_info) - { - return 0; - } - char d_str[INET_ADDRSTRLEN]; char s_str[INET_ADDRSTRLEN]; - const struct event *pack_info = packet_info; - unsigned int saddr = pack_info->client_ip; - unsigned int daddr = pack_info->server_ip; + char d_str[INET_ADDRSTRLEN]; if (pack_info->client_port == 0 || pack_info->server_port == 0 || pack_info->pid == 0) { - return 0; + return; } + format_ip_address(pack_info->client_ip, s_str, sizeof(s_str)); + format_ip_address(pack_info->server_ip, d_str, sizeof(d_str)); + printf("%-20d %-20s %-20s %-20u %-20d %-20s %-20d %-20d %-20d\n", pack_info->pid, - inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), - inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), pack_info->client_port, - pack_info->server_port, pack_info->comm, pack_info->tran_time, pack_info->udp_direction, pack_info->len); + s_str, + d_str, + pack_info->client_port, + pack_info->server_port, + pack_info->comm, + pack_info->tran_time, + pack_info->udp_direction, + pack_info->len); +} + +static void print_tcp_state_info(const struct event *pack_info) +{ + char s_str[INET_ADDRSTRLEN]; + char d_str[INET_ADDRSTRLEN]; + + format_ip_address(pack_info->client_ip, s_str, sizeof(s_str)); + format_ip_address(pack_info->server_ip, d_str, sizeof(d_str)); + + printf("%-20d %-20s %-20s %-20d %-20d %-20s %-20s %-20d\n", + pack_info->pid, + s_str, + d_str, + pack_info->client_port, + pack_info->server_port, + tcp_states[pack_info->oldstate], + tcp_states[pack_info->newstate], + pack_info->tran_time); +} + +static int handle_event(void *ctx, void *packet_info, size_t data_sz) +{ + const struct event *pack_info = (const struct event *)packet_info; + + if (udp_info) + { + print_udp_event_info(pack_info); + } + + if (tcp_status_info) + { + print_tcp_state_info(pack_info); + } + return 0; } @@ -84,7 +145,7 @@ int main(int argc, char **argv) int err = 0; struct ring_buffer *udp_rb = NULL; struct ring_buffer *tcp_rb = NULL; - + /* Parse command line arguments */ err = argp_parse(&argp, argc, argv, 0, NULL, NULL); if (err) @@ -130,16 +191,27 @@ int main(int argc, char **argv) fprintf(stderr, "Failed to create ring buffer\n"); goto cleanup; } - + tcp_rb = ring_buffer__new(bpf_map__fd(skel->maps.tcp_rb), handle_event, NULL, NULL); + if (!tcp_rb) + { + err = -1; + fprintf(stderr, "Failed to create ring buffer\n"); + goto cleanup; + } /* Process events */ if (udp_info) { 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) + { + printf("%-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s \n", "Pid","Client_ip", "Server_ip", "Client_port", "Server_port", "oldstate", "newstate", "time/μs"); + } while (!exiting) { err = ring_buffer__poll(udp_rb, 100 /* timeout, ms */); + err = ring_buffer__poll(tcp_rb, 100 /* timeout, ms */); /* Ctrl-C will cause -EINTR */ if (err == -EINTR) { @@ -156,6 +228,7 @@ int main(int argc, char **argv) cleanup: /* Clean up */ ring_buffer__free(udp_rb); + ring_buffer__free(tcp_rb); probe_bpf__destroy(skel); return err < 0 ? -err : 0; diff --git a/agent/plugin/probe.h b/agent/plugin/probe.h index 9f97b069027df8cce9ec1dce774aa4e62e49f2da..cab968bc131bb92422917ccd57668d9f8e67a854 100644 --- a/agent/plugin/probe.h +++ b/agent/plugin/probe.h @@ -49,7 +49,11 @@ struct event int udp_direction; u16 protocol; int tran_time; + u16 family; char comm[TASK_COMM_LEN]; + int oldstate; + int newstate; + u8 type; }; #endif diff --git a/agent/plugin/traffic.bpf.h b/agent/plugin/traffic.bpf.h index 25e4e1fdead31384812ea702a1e200d18e01b449..4a47f92c529d20cbb340976c561a9b35e5a1d629 100644 --- a/agent/plugin/traffic.bpf.h +++ b/agent/plugin/traffic.bpf.h @@ -108,3 +108,51 @@ static __always_inline int __ip_send_skb(struct sk_buff *skb) submit_message(&pkt_tuple, tran_time, 0, __bpf_ntohs(_R(udp, len))); return 0; } + +// tcp status +static __always_inline int __handle_tcp_state(struct trace_event_raw_inet_sock_set_state *ctx) +{ + u64 time, newtime; + if (ctx->protocol != IPPROTO_TCP) + return 0; + + struct sock *sk = (struct sock *)ctx->skaddr; + u64 *before_time = bpf_map_lookup_elem(&tcp_status, &sk); + newtime = NS_TIME(); + if (!before_time) + time = 0; + else + time = newtime - *before_time; + struct event tcpstate = {}; + tcpstate.oldstate = ctx->oldstate; + tcpstate.newstate = ctx->newstate; + tcpstate.family = ctx->family; + tcpstate.client_port = ctx->sport; + tcpstate.server_port = ctx->dport; + bpf_probe_read_kernel(&tcpstate.client_ip, sizeof(tcpstate.client_ip), + &sk->__sk_common.skc_rcv_saddr); + bpf_probe_read_kernel(&tcpstate.server_ip, sizeof(tcpstate.server_ip), + &sk->__sk_common.skc_daddr); + tcpstate.tran_time = time; + if (ctx->newstate == TCP_CLOSE) + bpf_map_delete_elem(&tcp_status, &sk); + else + bpf_map_update_elem(&tcp_status, &sk, &newtime, BPF_ANY); + + struct event *message; + message = bpf_ringbuf_reserve(&tcp_rb, sizeof(*message), 0); + if (!message) + { + return 0; + } + message->pid = get_current_tgid(); + message->client_ip = tcpstate.client_ip; + message->server_ip = tcpstate.server_ip; + message->client_port = tcpstate.client_port; + message->server_port = tcpstate.server_port; + message->oldstate = tcpstate.oldstate; + message->newstate = tcpstate.newstate; + message->tran_time = tcpstate.tran_time; + bpf_ringbuf_submit(message, 0); + return 0; +}