Skip to content

Commit

Permalink
Merge pull request #831 from wynyibo/develop
Browse files Browse the repository at this point in the history
netwatcher:Sql time-consuming threshold and Dns request response number
  • Loading branch information
chenamy2017 authored Jun 14, 2024
2 parents 0b4c365 + 713190a commit eb0278c
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 29 deletions.
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

0 comments on commit eb0278c

Please sign in to comment.