Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

netwatcher:Sql time-consuming threshold and Dns request response number #831

Merged
merged 6 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions eBPF_Supermarket/Network_Subsystem/net_watcher/common.bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ struct dns_query {
char data[64];// 可变长度数据(域名+类型+类)
};

struct dns{
u32 saddr;
u32 daddr;
};

// 操作BPF映射的一个辅助函数
static __always_inline void * //__always_inline强制内联
bpf_map_lookup_or_try_init(void *map, const void *key, const void *init) {
Expand Down Expand Up @@ -229,13 +234,37 @@ struct {
__type(value, __u64);
} tcp_state SEC(".maps");

//sql 耗时
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 256*1024);
__type(key, __u32);
__type(value, __u64);
} mysql_time SEC(".maps");

//sql请求数
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1024);
__type(key,__u32);
__type(value,__u64);
} sql_count SEC(".maps");

//dns计数根据每个saddr、daddr
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1024);
__type(key,struct dns);
__type(value,__u64);
} dns_request_count SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1024);
__type(key,struct dns);
__type(value,__u64);
} dns_response_count 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,
Expand Down
19 changes: 15 additions & 4 deletions eBPF_Supermarket/Network_Subsystem/net_watcher/mysql.bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ static __always_inline int __handle_mysql_start(struct pt_regs *ctx) {
union COM_DATA *com_data = (union COM_DATA *)PT_REGS_PARM2(ctx);

pid_t pid = bpf_get_current_pid_tgid() >> 32;
pid_t tid = bpf_get_current_pid_tgid();
void *thd = (void *)PT_REGS_PARM1(ctx);
char *sql;
u32 size = 0;
Expand All @@ -32,7 +33,7 @@ static __always_inline int __handle_mysql_start(struct pt_regs *ctx) {
return 0;
}

u64 start_time = bpf_ktime_get_ns()/1000;
u64 start_time = bpf_ktime_get_ns() / 1000;
bpf_map_update_elem(&mysql_time, &pid, &start_time, BPF_ANY);

struct mysql_query *message =
Expand All @@ -45,20 +46,22 @@ static __always_inline int __handle_mysql_start(struct pt_regs *ctx) {
&com_data->com_query.length);
bpf_probe_read_str(&sql, sizeof(sql), &com_data->com_query.query);
bpf_probe_read_str(&message->msql, sizeof(message->msql), sql);
bpf_printk("%s",sql);

message->pid = pid;
message->tid = tid;
bpf_get_current_comm(&message->comm, sizeof(comm));

bpf_ringbuf_submit(message, 0);

return 0;
}

static __always_inline int __handle_mysql_end(struct pt_regs *ctx) {

pid_t pid = bpf_get_current_pid_tgid() >> 32;
pid_t tid = bpf_get_current_pid_tgid();
u64 *start_time_ptr, duration;
u64 end_time = bpf_ktime_get_ns()/1000;
u64 end_time = bpf_ktime_get_ns() / 1000;
start_time_ptr = bpf_map_lookup_elem(&mysql_time, &pid);
if (!start_time_ptr) {
return 0;
Expand All @@ -70,10 +73,18 @@ static __always_inline int __handle_mysql_end(struct pt_regs *ctx) {
if (!message) {
return 0;
}
u64 *count_ptr, count = 1;
count_ptr = bpf_map_lookup_elem(&sql_count, &tid);
if (count_ptr) {
count = *count_ptr + 1;
}
message->count = count;
bpf_map_update_elem(&sql_count, &tid, &count, BPF_ANY);

message->duratime = duration;

bpf_ringbuf_submit(message, 0);
bpf_map_delete_elem(&mysql_time, &pid);

return 0;
}
70 changes: 47 additions & 23 deletions eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ 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, stack_info = 0, mysql_info = 0; // flag
time_load = 0, dns_info = 0, stack_info = 0, mysql_info = 0,
count_info = 0; // flag

static const char *tcp_states[] = {
[1] = "ESTABLISHED", [2] = "SYN_SENT", [3] = "SYN_RECV",
Expand All @@ -54,7 +55,6 @@ static const char *tcp_states[] = {
};

static const char argp_program_doc[] = "Watch tcp/ip in network subsystem \n";

static const struct argp_option opts[] = {
{"all", 'a', 0, 0, "set to trace CLOSED connection"},
{"err", 'e', 0, 0, "set to trace TCP error packets"},
Expand All @@ -74,11 +74,14 @@ static const struct argp_option opts[] = {
{"dns", 'D', 0, 0,
"set to trace dns information info include Id 事务ID、Flags 标志字段、Qd "
"问题部分计数、An 应答记录计数、Ns 授权记录计数、Ar 附加记录计数、Qr "
"域名、rx 收发包 "},
"域名、rx 收发包 、Qc请求数、Sc响应数"},
{"stack", 'A', 0, 0, "set to trace of stack "},
{"mysql", 'M', 0, 0,
"set to trace mysql information info include Pid 进程id、Comm "
"进程名、Size sql语句字节大小、Sql 语句"},
"进程名、Size sql语句字节大小、Sql 语句、Duration Sql耗时、Request "
"Sql请求数"},
{"count", 'C', "NUMBER", 0,
"specify the time to count the number of requests"},
{}};

static error_t parse_arg(int key, char *arg, struct argp_state *state) {
Expand Down Expand Up @@ -138,6 +141,9 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) {
case 'M':
mysql_info = 1;
break;
case 'C':
count_info = strtoul(arg, &end, 10);
break;
default:
return ARGP_ERR_UNKNOWN;
}
Expand Down Expand Up @@ -253,7 +259,6 @@ static const char binary_path[] = "/usr/sbin/mysqld";
__ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, false)
#define ATTACH_URETPROBE_CHECKED(skel, sym_name, prog_name) \
__ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, true)

struct SymbolEntry symbols[300000];
int num_symbols = 0;
// 定义快表
Expand Down Expand Up @@ -357,6 +362,9 @@ struct LayerDelayInfo {
#define GRANULARITY 3
#define ALPHA 0.2 // 衰减因子
#define MAXTIME 10000
#define SLOW_QUERY_THRESHOLD 10000 //
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_RESET "\x1b[0m"

// 全局变量用于存储每层的移动平均值
float ewma_values[NUM_LAYERS] = {0};
Expand Down Expand Up @@ -596,17 +604,18 @@ static void print_header(enum MonitorMode mode) {
"====================DNS "
"INFORMATION===================================================="
"============================\n");
printf("%-20s %-20s %-12s %-12s %-5s %-5s %-5s %-5s %-47s %5s \n",
printf("%-20s %-20s %-12s %-12s %-5s %-5s %-5s %-5s %-47s %-10s %-10s "
"%-10s \n",
"Saddr", "Daddr", "Id", "Flags", "Qd", "An", "Ns", "Ar", "Qr",
"RX/direction");
"Qc", "Sc", "RX/direction");
break;
case MODE_MYSQL:
printf("==============================================================="
"====================MYSQL "
"INFORMATION===================================================="
"============================\n");
printf("%-20s %-20s %-20s %-40s %-20s \n", "Pid", "Comm", "Size", "Sql",
"duration/μs");
printf("%-20s %-20s %-20s %-20s %-40s %-20s %-20s \n", "Pid", "Tid",
"Comm", "Size", "Sql", "Duration/μs", "Request");
break;
case MODE_DEFAULT:
printf("==============================================================="
Expand Down Expand Up @@ -921,6 +930,9 @@ static int print_netfilter(void *ctx, void *packet_info, size_t size) {
return 0;
unsigned int saddr = pack_info->saddr;
unsigned int daddr = pack_info->daddr;
// if ((daddr & 0x0000FFFF) == 0x0000007F ||
// (saddr & 0x0000FFFF) == 0x0000007F)
// return 0;
printf("%-20s %-20s %-12d %-12d %-8lld %-8lld% -8lld %-8lld %-8lld %-8d",
inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)),
inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), pack_info->sport,
Expand Down Expand Up @@ -1031,6 +1043,7 @@ static int print_icmptime(void *ctx, void *packet_info, size_t size) {
printf("\n");
return 0;
}

// 从DNS数据包中提取并打印域名
static void print_domain_name(const unsigned char *data, char *output) {
const unsigned char *next = data;
Expand Down Expand Up @@ -1066,30 +1079,41 @@ static int print_dns(void *ctx, void *packet_info, size_t size) {
inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str));

print_domain_name((const unsigned char *)pack_info->data, domain_name);

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,
if (pack_info->daddr == 0) {
return 0;
}
printf("%-20s %-20s %-#12x %-#12x %-5x %-5x %-5x %-5x %-47s %-10d %-10d "
"%-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);

domain_name, pack_info->request_count, pack_info->response_count,
pack_info->rx);
return 0;
}

static mysql_query last_query;

static int print_mysql(void *ctx, void *packet_info, size_t size) {
if (!mysql_info) {
return 0;
}

const mysql_query *pack_info = packet_info;
// 假设duratime总是0
if (pack_info->duratime == 0) {
// 存储开始事件数据

memcpy(&last_query, pack_info, sizeof(mysql_query));
} else {
// 结束事件 合并
printf("%-20d %-20s %-20u %-40s %-20llu\n", last_query.pid,
last_query.comm, last_query.size, last_query.msql,
pack_info->duratime);
// 重置
memset(&last_query, 0, sizeof(last_query));

printf("%-20d %-20d %-20s %-20u %-40s", last_query.pid, last_query.tid,
last_query.comm, last_query.size, last_query.msql);
// 当 duratime 大于 count_info 时,才打印 duratime
if (pack_info->duratime > count_info) {
printf("%-21llu", pack_info->duratime);
} else {
printf("%-21s", "");
}

printf("%-20d\n", pack_info->count);
memset(&last_query, 0, sizeof(mysql_query));
}
return 0;
}
Expand Down
4 changes: 4 additions & 0 deletions eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ struct dns_information {
u16 arcount;
char data[64];
int rx;
int response_count;
int request_count;
};
#define MAX_STACK_DEPTH 128
typedef u64 stack_trace_t[MAX_STACK_DEPTH];
Expand All @@ -170,10 +172,12 @@ struct stacktrace_event {

typedef struct mysql_query {
int pid;
int tid;
char comm[20];
u32 size;
char msql[256];
u64 duratime;
int count;
} mysql_query;

#endif /* __NETWATCHER_H */
41 changes: 39 additions & 2 deletions eBPF_Supermarket/Network_Subsystem/net_watcher/udp.bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,17 @@ static __always_inline int __ip_send_skb(struct sk_buff *skb) {
static __always_inline int process_dns_packet(struct sk_buff *skb, int rx) {
if (skb == NULL)
return 0;

u16 QR_flags;
u64 *count_ptr, response_count = 0, request_count = 0;
struct sock *sk = BPF_CORE_READ(skb, sk);
struct packet_tuple pkt_tuple = {
.saddr = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr),
.daddr = BPF_CORE_READ(sk, __sk_common.skc_daddr),
.sport = BPF_CORE_READ(sk, __sk_common.skc_num),
.dport = __bpf_ntohs(BPF_CORE_READ(sk, __sk_common.skc_dport)),
.tran_flag = UDP};
// 使用saddr、daddr作为key
struct dns key = {.saddr = pkt_tuple.saddr, .daddr = pkt_tuple.daddr};

if ((pkt_tuple.sport != 53) && (pkt_tuple.dport != 53))
return 0;
Expand All @@ -151,7 +154,39 @@ static __always_inline int process_dns_packet(struct sk_buff *skb, int rx) {
bpf_probe_read_kernel(message->data, sizeof(message->data),
BPF_CORE_READ(skb, head) + dns_offset +
sizeof(struct dns_header));

QR_flags = __bpf_ntohs(query.header.flags);
/*
1000 0000 0000 0000
&运算提取最高位QR, QR=1 Response QR=0 Request
*/
if (QR_flags & 0x8000) { // 响应
count_ptr = bpf_map_lookup_elem(&dns_response_count, &key);
if (count_ptr) {
response_count = *count_ptr + 1;
} else {
response_count = 1;
}
bpf_map_update_elem(&dns_response_count, &key, &response_count,
BPF_ANY);
// 保留映射中的请求计数值
count_ptr = bpf_map_lookup_elem(&dns_request_count, &key);
if (count_ptr) {
request_count = *count_ptr;
}
} else { // 请求
count_ptr = bpf_map_lookup_elem(&dns_request_count, &key);
if (count_ptr) {
request_count = *count_ptr + 1;
} else {
request_count = 1;
}
bpf_map_update_elem(&dns_request_count, &key, &request_count, BPF_ANY);
// 保留映射中的响应计数值
count_ptr = bpf_map_lookup_elem(&dns_response_count, &key);
if (count_ptr) {
response_count = *count_ptr;
}
}
message->saddr = rx ? pkt_tuple.saddr : pkt_tuple.daddr;
message->daddr = rx ? pkt_tuple.daddr : pkt_tuple.saddr;
message->id = __bpf_ntohs(query.header.id);
Expand All @@ -160,6 +195,8 @@ static __always_inline int process_dns_packet(struct sk_buff *skb, int rx) {
message->ancount = __bpf_ntohs(query.header.ancount);
message->nscount = __bpf_ntohs(query.header.nscount);
message->arcount = __bpf_ntohs(query.header.arcount);
message->request_count = request_count;
message->response_count = response_count;
message->rx = rx;

bpf_ringbuf_submit(message, 0);
Expand Down
Loading