From e70dc5e68947a77f83c02496b8121ff6109c3fc6 Mon Sep 17 00:00:00 2001 From: zhangxianyu777 <93031728+zhangxianyu777@users.noreply.github.com> Date: Fri, 21 Jun 2024 17:57:55 +0800 Subject: [PATCH] =?UTF-8?q?netwatcher=20:=E6=9B=B4=E6=94=B9uprobe=E9=80=82?= =?UTF-8?q?=E9=85=8D=E5=88=A4=E6=96=AD=E3=80=81=E5=A2=9E=E6=B7=BBredis?= =?UTF-8?q?=E7=9B=91=E6=8E=A7=E4=BF=A1=E6=81=AF=20(incomplete)=20(#835)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add the redis info (incomplete) * Update packet.bpf.h * fix the bug * 11 --------- Co-authored-by: zmx --- .../net_watcher/common.bpf.h | 3 +- .../net_watcher/data/connects.log | 1 - .../net_watcher/netwatcher.bpf.c | 7 +++ .../net_watcher/netwatcher.c | 58 ++++++++++++++---- .../Network_Subsystem/net_watcher/redis.bpf.h | 60 +++++++++++++++++++ .../net_watcher/redis_helper.bpf.h | 55 +++++++++++++++++ 6 files changed, 171 insertions(+), 13 deletions(-) create mode 100644 eBPF_Supermarket/Network_Subsystem/net_watcher/redis.bpf.h create mode 100644 eBPF_Supermarket/Network_Subsystem/net_watcher/redis_helper.bpf.h diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/common.bpf.h b/eBPF_Supermarket/Network_Subsystem/net_watcher/common.bpf.h index 90ad50757..9fa88f752 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/common.bpf.h +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/common.bpf.h @@ -269,7 +269,8 @@ 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, layer_time = 0, http_info = 0, retrans_info = 0, udp_info =0,net_filter = 0, - drop_reason = 0,icmp_info = 0 ,tcp_info = 0 ,dns_info = 0 ,stack_info = 0,mysql_info = 0; + drop_reason = 0,icmp_info = 0 ,tcp_info = 0 ,dns_info = 0 ,stack_info = 0, + mysql_info = 0, redis_info; /* help macro */ diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/data/connects.log b/eBPF_Supermarket/Network_Subsystem/net_watcher/data/connects.log index 733723688..e69de29bb 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/data/connects.log +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/data/connects.log @@ -1 +0,0 @@ -connection{pid="214827",sock="0xffff944e0c3dda00",src="192.168.239.132:35422",dst="20.189.173.1:443",is_server="0",backlog="-",maxbacklog="-",cwnd="-",ssthresh="-",sndbuf="-",wmem_queued="-",rx_bytes="-",tx_bytes="-",srtt="-",duration="-",total_retrans="-",fast_retrans="-",timeout_retrans="-"} diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c index 5c67c4090..3a76a9a39 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.bpf.c @@ -30,6 +30,8 @@ #include "mysql.bpf.h" +#include "redis.bpf.h" + #include "drop.bpf.h" // accecpt an TCP connection @@ -330,4 +332,9 @@ int BPF_KPROBE(query__start) { SEC("uretprobe/_Z16dispatch_commandP3THDPK8COM_DATA19enum_server_command") int BPF_KPROBE(query__end){ return __handle_mysql_end(ctx); +} + +SEC("uprobe/processCommand") +int BPF_KPROBE(query__start_redis) { + return __handle_redis_start(ctx); } \ No newline at end of file diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c index c2ba5490e..cbe4a5765 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c @@ -44,7 +44,7 @@ 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, - count_info = 0; // flag + redis_info = 0 ,count_info = 0;// flag static const char *tcp_states[] = { [1] = "ESTABLISHED", [2] = "SYN_SENT", [3] = "SYN_RECV", @@ -78,8 +78,8 @@ static const struct argp_option opts[] = { {"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 语句、Duration Sql耗时、Request " - "Sql请求数"}, + "进程名、Size sql语句字节大小、Sql 语句"}, + {"redis", 'R', 0, 0}, {"count", 'C', "NUMBER", 0, "specify the time to count the number of requests"}, {}}; @@ -141,6 +141,9 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) { case 'M': mysql_info = 1; break; + case 'R': + redis_info = 1; + break; case 'C': count_info = strtoul(arg, &end, 10); break; @@ -169,6 +172,7 @@ enum MonitorMode { MODE_TCP, MODE_DNS, MODE_MYSQL, + MODE_REDIS, MODE_DEFAULT }; @@ -187,7 +191,10 @@ enum MonitorMode get_monitor_mode() { return MODE_DNS; } else if (mysql_info) { return MODE_MYSQL; - } else { + } else if (redis_info) { + return MODE_REDIS; + } + else { return MODE_DEFAULT; } } @@ -227,7 +234,7 @@ void print_logo() { pclose(lolcat_pipe); } -static const char binary_path[] = "/usr/sbin/mysqld"; +static char binary_path[64]=""; #define __ATTACH_UPROBE(skel, sym_name, prog_name, is_retprobe) \ do { \ LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts, .func_name = #sym_name, \ @@ -419,6 +426,7 @@ static void set_rodata_flags(struct netwatcher_bpf *skel) { skel->rodata->dns_info = dns_info; skel->rodata->stack_info = stack_info; skel->rodata->mysql_info = mysql_info; + skel->rodata->redis_info = redis_info; } static void set_disable_load(struct netwatcher_bpf *skel) { @@ -556,6 +564,8 @@ static void set_disable_load(struct netwatcher_bpf *skel) { mysql_info ? true : false); bpf_program__set_autoload(skel->progs.query__end, mysql_info ? true : false); + bpf_program__set_autoload(skel->progs.query__start_redis, + redis_info ? true : false); } static void print_header(enum MonitorMode mode) { @@ -617,6 +627,14 @@ static void print_header(enum MonitorMode mode) { printf("%-20s %-20s %-20s %-20s %-40s %-20s %-20s \n", "Pid", "Tid", "Comm", "Size", "Sql", "Duration/μs", "Request"); break; + case MODE_REDIS: + printf("===============================================================" + "====================MYSQL " + "INFORMATION====================================================" + "============================\n"); + printf("%-20s %-20s %-20s %-40s %-20s \n", "Pid", "Comm", "Size", "Sql", + "duration/μs"); + break; case MODE_DEFAULT: printf("===============================================================" "=INFORMATION===================================================" @@ -765,7 +783,7 @@ static int print_conns(struct netwatcher_bpf *skel) { static int print_packet(void *ctx, void *packet_info, size_t size) { if (udp_info || net_filter || drop_reason || icmp_info || tcp_info || - dns_info || mysql_info) + dns_info || mysql_info||redis_info) return 0; const struct pack_t *pack_info = packet_info; if (pack_info->mac_time > MAXTIME || pack_info->ip_time > MAXTIME || @@ -1155,7 +1173,8 @@ static int print_trace(void *_ctx, void *data, size_t size) { return 0; } -int attach_uprobe(struct netwatcher_bpf *skel) { +int attach_uprobe_mysql(struct netwatcher_bpf *skel) { + ATTACH_UPROBE_CHECKED( skel, _Z16dispatch_commandP3THDPK8COM_DATA19enum_server_command, query__start); @@ -1164,7 +1183,12 @@ int attach_uprobe(struct netwatcher_bpf *skel) { query__end); return 0; } - +int attach_uprobe_redis(struct netwatcher_bpf *skel) { + ATTACH_UPROBE_CHECKED( + skel, processCommand, + query__start_redis); + return 0; +} int main(int argc, char **argv) { char *last_slash = strrchr(argv[0], '/'); if (last_slash) { @@ -1222,13 +1246,25 @@ int main(int argc, char **argv) { /* Attach tracepoint handler */ if (mysql_info) { - err = attach_uprobe(skel); + strcpy(binary_path, "/usr/sbin/mysqld"); + err = attach_uprobe_mysql(skel); if (err) { fprintf(stderr, "failed to attach uprobes\n"); goto cleanup; } - } else { + } + else if(redis_info) + { + strcpy(binary_path, "/usr/bin/redis-server"); + err = attach_uprobe_redis(skel); + if (err) { + fprintf(stderr, "failed to attach uprobes\n"); + + goto cleanup; + } + } + else { err = netwatcher_bpf__attach(skel); if (err) { fprintf(stderr, "Failed to attach BPF skeleton\n"); @@ -1237,7 +1273,7 @@ int main(int argc, char **argv) { } enum MonitorMode mode = get_monitor_mode(); - print_logo(); + //print_logo(); print_header(mode); diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/redis.bpf.h b/eBPF_Supermarket/Network_Subsystem/net_watcher/redis.bpf.h new file mode 100644 index 000000000..66ef4364b --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/redis.bpf.h @@ -0,0 +1,60 @@ +// Copyright 2023 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: blown.away@qq.com +// mysql + +#include "common.bpf.h" +#include "redis_helper.bpf.h" +#define MAXEPOLL 10 +static __always_inline int __handle_redis_start(struct pt_regs *ctx) { + struct client *cli = (struct client *)PT_REGS_PARM1(ctx); + int argc; + void *ptr; + char name[100]=""; + int argv_len; + bpf_probe_read(&argc, sizeof(argc), &cli->argc); + bpf_printk("%d",argc); + robj **arg0; + robj *arg1; + //unsigned type; + unsigned encoding; + unsigned lru; + int refcount; + bpf_probe_read(&arg0, sizeof(arg0), &cli->argv); + + // 读取 argv[0],即第一个命令参数 + bpf_probe_read(&arg1, sizeof(arg1), &arg0[0]); + + for(int i=0;iptr 中的字符串 + bpf_probe_read(&ptr, sizeof(ptr),&arg1->ptr); + bpf_probe_read_str(name, sizeof(name),ptr); + bpf_printk("%s",name); + } + // 读取 argv[0]->ptr 中的字符串 + bpf_probe_read(&ptr, sizeof(ptr),&arg1->ptr); + bpf_probe_read_str(name, sizeof(name),ptr); + + + bpf_probe_read(&argv_len, sizeof(argv_len), &cli->argv_len_sum); + + bpf_printk("%d",argv_len); + + pid_t pid = bpf_get_current_pid_tgid() >> 32; + return 0; +} + diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/redis_helper.bpf.h b/eBPF_Supermarket/Network_Subsystem/net_watcher/redis_helper.bpf.h new file mode 100644 index 000000000..21f2031f7 --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/redis_helper.bpf.h @@ -0,0 +1,55 @@ +// Copyright 2023 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: blown.away@qq.com +// +// netwatcher libbpf 内核<->用户 传递信息相关结构体 + +#ifndef __REDIS_HELPER_BPF_H +#define __REDIS_HELPER_BPF_H + +#include "netwatcher.h" +#include "vmlinux.h" +#include +#include +#include +#include +#include +#include + +#define LRU_BITS 24 +typedef struct redisObject { + unsigned type:4; + unsigned encoding:4; + unsigned lru:24; + int refcount; + void *ptr; +} robj; + +struct client { + u64 id; /* Client incremental unique ID. */ + u64 conn; + int resp; /* RESP protocol version. Can be 2 or 3. */ + u64 db; /* Pointer to currently SELECTed DB. */ + robj *name; /* As set by CLIENT SETNAME. */ + char* querybuf; /* Buffer we use to accumulate client queries. */ + unsigned long qb_pos; /* The position we have read in querybuf. */ + char* pending_querybuf; + unsigned long querybuf_peak; /* Recent (100ms or more) peak of querybuf size. */ + int argc; /* Num of arguments of current command. */ + robj **argv; /* Arguments of current command. */ + unsigned long argv_len_sum; /* Size of argv array (may be more than argc) */ +}; + +#endif