From 2cb3d77d0feb667d672300609704369e91a16e20 Mon Sep 17 00:00:00 2001 From: Vchanger Date: Mon, 4 Aug 2025 21:16:56 +0800 Subject: [PATCH 1/4] [Feat] snooper: support global observation and filter with blacklist --- src/common/ipc.c | 22 ++++----- src/common/ipc.h | 12 +++-- src/lib/probe/probe_mng.c | 95 ++++++++++++++++++++++++++------------- src/lib/probe/probe_mng.h | 1 + src/lib/probe/snooper.c | 80 +++++++++++++++++++++++---------- src/lib/probe/snooper.h | 2 + 6 files changed, 146 insertions(+), 66 deletions(-) diff --git a/src/common/ipc.c b/src/common/ipc.c index 9ca2efc0..59905322 100644 --- a/src/common/ipc.c +++ b/src/common/ipc.c @@ -52,7 +52,8 @@ struct ipc_tlv_s { struct ipc_msg_s { long msg_type; // Equivalent to enum probe_type_e - u32 msg_flag; + u16 msg_flag; + u16 snooper_state; u32 msg_len; char msg[0]; }; @@ -63,6 +64,8 @@ IPC msg format: ---|----------------|----------------|----------------|----------------| / | msg_type(enum probe_type_e) | | |----------------|----------------|----------------|----------------| + | | msg_flag | snooper_state | + | |----------------|----------------|----------------|----------------| | | msg_len | ----|---|----------------|----------------|----------------|----------------| / | | type(100) | len(FIX 4 Bytes) | @@ -76,10 +79,6 @@ IPC msg format: | | ~ value(struct probe_params) ~ | | | | msg_len | | | - | | |----------------|----------------|----------------|----------------| - | | | type(102) | len(FIX 4 Bytes) | - | | |----------------|----------------|----------------|----------------| - | | | value(probe_flags) | | | |----------------|----------------|----------------|----------------| | | | type(103) | len(FIX 4 Bytes) | | | |----------------|----------------|----------------|----------------| @@ -523,6 +522,7 @@ static struct ipc_msg_s* __create_ipc_msg(struct ipc_body_s* ipc_body, struct cu } ipc_msg->msg_flag = ipc_body->probe_flags; + ipc_msg->snooper_state = ipc_body->snooper_state; buf = (char *)(ipc_msg->msg); ret = __build_ipc_msg(buf, ipc_msg->msg_len, ipc_body, custom_ipc_msg); @@ -769,7 +769,7 @@ int send_ipc_msg(int msqid, long msg_type, struct ipc_body_s* ipc_body) return -1; } - if (msgsnd(msqid, ipc_msg, ipc_msg->msg_len + sizeof(ipc_msg->msg_len) + sizeof(ipc_msg->msg_flag), 0) < 0) { + if (msgsnd(msqid, ipc_msg, ipc_msg->msg_len + sizeof(struct ipc_msg_s) - sizeof(ipc_msg->msg_type), 0) < 0) { ERROR("[IPC] send ipc message(msg_type = %ld) failed(%d). Try increasing sysctl param kernel.msgmax.\n", msg_type, errno); err = -1; } @@ -798,7 +798,7 @@ int send_custom_ipc_msg(int msqid, long msg_type, struct ipc_body_s* ipc_body, s return -1; } - if (msgsnd(msqid, ipc_msg, ipc_msg->msg_len + sizeof(ipc_msg->msg_len) + sizeof(ipc_msg->msg_flag), 0) < 0) { + if (msgsnd(msqid, ipc_msg, ipc_msg->msg_len + sizeof(struct ipc_msg_s) - sizeof(ipc_msg->msg_type), 0) < 0) { ERROR("[IPC] send ipc message(msg_type = %ld) failed(%d).\n", msg_type, errno); err = -1; } @@ -824,7 +824,7 @@ int recv_ipc_msg(int msqid, long msg_type, struct ipc_body_s *ipc_body) } ipc_msg = __get_raw_ipc_msg(msg_type); - msg_len = ipc_msg->msg_len + sizeof(ipc_msg->msg_len) + sizeof(ipc_msg->msg_flag); + msg_len = ipc_msg->msg_len + sizeof(struct ipc_msg_s) - sizeof(ipc_msg->msg_type); /* Only deal with the last message within every check */ while (msgrcv(msqid, ipc_msg, msg_len, msg_type, IPC_NOWAIT) != -1) { msg_rcvd = 1; @@ -843,6 +843,7 @@ int recv_ipc_msg(int msqid, long msg_type, struct ipc_body_s *ipc_body) goto end; } ipc_body->probe_flags = msg_flags; + ipc_body->snooper_state = ipc_msg->snooper_state; err = 0; } @@ -867,7 +868,7 @@ int recv_custom_ipc_msg(int msqid, long msg_type, struct ipc_body_s *ipc_body, s } ipc_msg = __get_raw_ipc_msg(msg_type); - msg_len = ipc_msg->msg_len + sizeof(ipc_msg->msg_len) + sizeof(ipc_msg->msg_flag); + msg_len = ipc_msg->msg_len + sizeof(struct ipc_msg_s) - sizeof(ipc_msg->msg_type); /* Only deal with the last message within every check */ while (msgrcv(msqid, ipc_msg, msg_len, msg_type, IPC_NOWAIT) != -1) { msg_rcvd = 1; @@ -887,6 +888,7 @@ int recv_custom_ipc_msg(int msqid, long msg_type, struct ipc_body_s *ipc_body, s goto end; } ipc_body->probe_flags = msg_flags; + ipc_body->snooper_state = ipc_msg->snooper_state; err = 0; } @@ -909,7 +911,7 @@ void clear_ipc_msg(long msg_type) } ipc_msg = __get_raw_ipc_msg(msg_type); - msg_len = ipc_msg->msg_len + sizeof(u32); + msg_len = ipc_msg->msg_len + sizeof(struct ipc_msg_s) - sizeof(ipc_msg->msg_type); while (1) { if (msgrcv(msqid, ipc_msg, msg_len, msg_type, IPC_NOWAIT) == -1) { break; diff --git a/src/common/ipc.h b/src/common/ipc.h index 9ebc02c8..8d021f1c 100644 --- a/src/common/ipc.h +++ b/src/common/ipc.h @@ -240,6 +240,11 @@ struct snooper_obj_s { } obj; }; +enum snooper_state_e { + SNOOPER_STATE_WHITELIST = 0, + SNOOPER_STATE_BLACKLIST, +}; + struct custom_params { char label[MAX_CUSTOM_PARAMS_LEN]; char value[MAX_CUSTOM_PARAMS_LEN]; @@ -252,12 +257,13 @@ struct custom_ipc { unsigned int params_num; }; -#define IPC_FLAGS_SNOOPER_CHG 0x00000001 -#define IPC_FLAGS_PARAMS_CHG 0x00000002 +#define IPC_FLAGS_SNOOPER_CHG 0x01 +#define IPC_FLAGS_PARAMS_CHG 0x02 struct ipc_body_s { u32 probe_range_flags; // Refer to flags defined [PROBE_RANGE_XX_XX] u32 snooper_obj_num; - u32 probe_flags; + u16 probe_flags; + u16 snooper_state; struct probe_params probe_param; struct snooper_obj_s snooper_objs[SNOOPER_MAX]; }; diff --git a/src/lib/probe/probe_mng.c b/src/lib/probe/probe_mng.c index faf7e8ae..5b8cf7db 100644 --- a/src/lib/probe/probe_mng.c +++ b/src/lib/probe/probe_mng.c @@ -235,16 +235,6 @@ int check_custom_range(const char *key, const char *comp) return 0; } -static int check_probe_snooper_conf_num(struct probe_s *probe) -{ - if (probe->snooper_conf_num == 0 && (!strcmp(probe->name, "tcp") || - !strcmp(probe->name, "socket") || !strcmp(probe->name, "container"))) { - PARSE_ERR("the snooper for %s cannot be empty", probe->name); - return -1; - } - return 0; -} - static struct probe_mng_s *g_probe_mng; static struct custom_ini *g_custom_ini; @@ -424,6 +414,7 @@ static struct probe_s* new_probe(const char* name, enum probe_type_e probe_type) probe->fifo->probe = probe; probe->probe_type = probe_type; probe->snooper_type = probe_define[probe_type - 1].snooper_type; + probe->snooper_state = SNOOPER_STATE_WHITELIST; ret = init_probe_bin(probe, probe_type); if (ret) { goto err; @@ -1037,7 +1028,7 @@ static int probe_parser_state(struct probe_s *probe, const void *item) } if (!strcasecmp(PROBE_STATE_RUNNING, (const char *)Json_GetValueString(item))) { - if (check_probe_range(probe) || check_probe_snooper_conf_num(probe)) { + if (check_probe_range(probe)) { return -1; } return start_probe(probe); @@ -1136,15 +1127,24 @@ struct probe_parser_s { // !!!NOTICE:The function sequence and macros cannot be changed. #define PARSER_FLAG_CMD 0x01 #define PARSER_FLAG_SNOOPERS 0x02 -#define PARSER_FLAG_PARAMS 0x04 -#define PARSER_FLAG_STATE 0x08 +#define PARSER_FLAG_BLACKLIST 0x04 +#define PARSER_FLAG_PARAMS 0x08 +#define PARSER_FLAG_STATE 0x10 + struct probe_parser_s probe_parsers[] = { - {"cmd", probe_parser_cmd, probe_printer_cmd, probe_backup_cmd, probe_rollback_cmd}, - {"snoopers", parse_snooper, print_snooper, backup_snooper, rollback_snooper}, - {"params", probe_parser_params, print_params, probe_backup_params, probe_rollback_params}, - {"state", probe_parser_state, print_state, NULL, NULL} + {"cmd", probe_parser_cmd, probe_printer_cmd, probe_backup_cmd, probe_rollback_cmd}, + {"snoopers", parse_snooper, print_snooper, backup_snooper, rollback_snooper}, + {"blacklist", parse_blacklist, print_blacklist, backup_snooper, rollback_snooper}, + {"params", probe_parser_params, print_params, probe_backup_params, probe_rollback_params}, + {"state", probe_parser_state, print_state, NULL, NULL} }; +static inline int snooper_blacklist_dup(u32 tmp_flag, u32 parse_flag) +{ + return (tmp_flag == PARSER_FLAG_BLACKLIST) && + (parse_flag & PARSER_FLAG_SNOOPERS); +} + static void rollback_probe(struct probe_s *probe, struct probe_s *probe_backup, u32 flag) { struct probe_parser_s *parser; @@ -1155,11 +1155,14 @@ static void rollback_probe(struct probe_s *probe, struct probe_s *probe_backup, size_t size = sizeof(probe_parsers) / sizeof(struct probe_parser_s); for (size_t i = 0; i < size; i++) { - if ((flag >> i) & 0x1) { + u32 tmp_flag = 0x1 << i; + if (flag & tmp_flag) { parser = &(probe_parsers[i]); if (parser->rollbacker) { - parser->rollbacker(probe, probe_backup); + if (!snooper_blacklist_dup(tmp_flag, flag)) { + parser->rollbacker(probe, probe_backup); + } } } } @@ -1273,11 +1276,12 @@ static void set_probe_modify(struct probe_s *probe, struct probe_s *backup_probe probe->is_params_chg = 1; } - if (!(parse_flag & PARSER_FLAG_SNOOPERS)) { + if (!((parse_flag & PARSER_FLAG_SNOOPERS) || (parse_flag & PARSER_FLAG_BLACKLIST))) { return; } - if (probe->snooper_conf_num != backup_probe->snooper_conf_num) { + if (probe->snooper_conf_num != backup_probe->snooper_conf_num || + probe->snooper_state != backup_probe->snooper_state) { probe->is_snooper_chg = 1; return; } @@ -1309,10 +1313,23 @@ static void probe_info_print(struct probe_s *probe) } } +static inline int snooper_invalid(const struct probe_s *probe) +{ + if (probe->snooper_type == SNOOPER_TYPE_NONE) { + return 0; + } + + if (probe->snooper_state == SNOOPER_STATE_WHITELIST && probe->snooper_conf_num == 0) { + PARSE_ERR("the snooper for %s cannot be empty", probe->name); + return -1; + } + return 0; +} + int parse_probe_json(const char *probe_name, const char *probe_content) { int ret = -1; - u32 parse_flag = 0; + u32 parse_flag = 0, tmp_flag; struct probe_parser_s *parser; struct probe_s *probe_backup = NULL; @@ -1340,18 +1357,27 @@ int parse_probe_json(const char *probe_name, const char *probe_content) size_t size = sizeof(probe_parsers) / sizeof(struct probe_parser_s); for (size_t i = 0; i < size; i++) { + tmp_flag = 0x1 << i; parser = &(probe_parsers[i]); - itemObj = Json_GetObjectItem(jsonObj, parser->item); + if (tmp_flag == PARSER_FLAG_PARAMS && snooper_invalid(probe)) { + rollback_probe(probe, probe_backup, parse_flag); + ret = -1; + break; + } + itemObj = Json_GetObjectItem(jsonObj, parser->item); if (itemObj == NULL) { continue; } - parse_flag |= 0x1 << i; + parse_flag |= tmp_flag; if (parser->backuper) { - parser->backuper(probe, probe_backup); + if (!snooper_blacklist_dup(tmp_flag, parse_flag)) { + parser->backuper(probe, probe_backup); + } } + ret = parser->parser(probe, itemObj); if (ret) { rollback_probe(probe, probe_backup, parse_flag); @@ -1424,12 +1450,21 @@ char *get_probe_json(const char *probe_name) if (parser->printer) { if (strcmp(parser->item, "state") == 0) { parser->printer(probe, res); - } else { - item = Json_CreateObject(); - parser->printer(probe, item); - Json_AddItemToObject(res, parser->item, item); - Json_Delete(item); + continue; + } + + if (strcmp(parser->item, "snoopers") == 0 && probe->snooper_state != SNOOPER_STATE_WHITELIST) { + continue; + } + + if (strcmp(parser->item, "blacklist") == 0 && probe->snooper_state != SNOOPER_STATE_BLACKLIST) { + continue; } + + item = Json_CreateObject(); + parser->printer(probe, item); + Json_AddItemToObject(res, parser->item, item); + Json_Delete(item); } } diff --git a/src/lib/probe/probe_mng.h b/src/lib/probe/probe_mng.h index 96b7fc80..b096db31 100644 --- a/src/lib/probe/probe_mng.h +++ b/src/lib/probe/probe_mng.h @@ -82,6 +82,7 @@ struct probe_s { char is_snooper_chg; // Probe snoopers changed char resnd_snooper_for_restart; // Need to resend snooper obj after probe is restarted u8 snooper_type; // Specify the type of snoopers that one probe really concern */ + enum snooper_state_e snooper_state; enum probe_type_e probe_type; struct custom custom; // User-defined probe u32 probe_range_flags; // Refer to flags defined [PROBE_RANGE_XX_XX] diff --git a/src/lib/probe/snooper.c b/src/lib/probe/snooper.c index b4efcf39..75c633f8 100644 --- a/src/lib/probe/snooper.c +++ b/src/lib/probe/snooper.c @@ -643,9 +643,11 @@ static int parse_snooper_pod_container(struct probe_s *probe, const void *json, void print_snooper(struct probe_s *probe, void *json) { - print_snooper_procid(probe, json); - print_snooper_procname(probe, json); - print_snooper_pod_container(probe, json); + if (probe->snooper_conf_num) { + print_snooper_procid(probe, json); + print_snooper_procname(probe, json); + print_snooper_pod_container(probe, json); + } } static void __build_ipc_body(struct probe_s *probe, struct ipc_body_s* ipc_body) @@ -686,6 +688,7 @@ static void __build_ipc_body(struct probe_s *probe, struct ipc_body_s* ipc_body) ipc_body->probe_flags = (IPC_FLAGS_PARAMS_CHG | IPC_FLAGS_SNOOPER_CHG); } memcpy(&(ipc_body->probe_param), &probe->probe_param, sizeof(struct probe_params)); + ipc_body->snooper_state = (u16)probe->snooper_state; return; } @@ -721,21 +724,8 @@ int send_snooper_obj(struct probe_s *probe) return send_ipc_msg(__probe_mng_snooper->msq_id, (long)probe->probe_type, &ipc_body); } -int parse_snooper(struct probe_s *probe, const void *json) +static inline int __parse_snooper(struct probe_s *probe, const void *json) { - int i; - - if (probe->snooper_type == SNOOPER_TYPE_NONE) { - return 0; - } - - /* free current snooper config */ - for (i = 0 ; i < probe->snooper_conf_num ; i++) { - free_snooper_conf(probe->snooper_confs[i]); - probe->snooper_confs[i] = NULL; - } - probe->snooper_conf_num = 0; - if (parse_snooper_procid(probe, json)) { PARSE_ERR("Error occurs when parsing snooper %s", SNOOPER_OBJNAME_PROCID); return -1; @@ -760,9 +750,15 @@ int parse_snooper(struct probe_s *probe, const void *json) PARSE_ERR("Error occurs when parsing snooper %s", SNOOPER_OBJNAME_CONTAINERNAME); return -1; } +} - if (probe->snooper_conf_num == 0) { - PARSE_ERR("the snooper for %s cannot be empty", probe->name); +int parse_snooper(struct probe_s *probe, const void *json) +{ + if (probe->snooper_type == SNOOPER_TYPE_NONE) { + return 0; + } + + if (__parse_snooper(probe, json)) { return -1; } @@ -776,10 +772,47 @@ int parse_snooper(struct probe_s *probe, const void *json) return -1; } - refresh_snooper_obj(probe); + probe->snooper_state = SNOOPER_STATE_WHITELIST; + if (probe->snooper_conf_num) { + refresh_snooper_obj(probe); + } + return 0; +} + + +int parse_blacklist(struct probe_s *probe, const void *json) +{ + if (probe->snooper_type == SNOOPER_TYPE_NONE) { + return 0; + } + + if (probe->snooper_conf_num) { + PARSE_ERR("snoopers and blacklist are mutually exclusive"); + return -1; + } + + if (__parse_snooper(probe, json)) { + return -1; + } + + probe->snooper_state = SNOOPER_STATE_BLACKLIST; + if (probe->snooper_conf_num) { + refresh_snooper_obj(probe); + } + return 0; } + +void print_blacklist(struct probe_s *probe, void *json) +{ + if (probe->snooper_conf_num) { + print_snooper_procid(probe, json); + print_snooper_procname(probe, json); + print_snooper_pod_container(probe, json); + } +} + void free_snooper_obj(struct snooper_obj_s* snooper_obj) { if (snooper_obj == NULL) { @@ -815,10 +848,10 @@ static struct snooper_obj_s* new_snooper_obj(void) void backup_snooper(struct probe_s *probe, struct probe_s *probe_backup) { - u32 snooper_conf_num = probe->snooper_conf_num; - - probe_backup->snooper_conf_num = snooper_conf_num; + probe_backup->snooper_state = probe->snooper_state; + probe_backup->snooper_conf_num = probe->snooper_conf_num; + probe->snooper_conf_num = 0; (void)memcpy(&probe_backup->snooper_confs, &probe->snooper_confs, SNOOPER_CONF_MAX * (sizeof(struct snooper_conf_s *))); (void)memset(&probe->snooper_confs, 0, SNOOPER_CONF_MAX * (sizeof(struct snooper_conf_s *))); @@ -845,6 +878,7 @@ void rollback_snooper(struct probe_s *probe, struct probe_s *probe_backup) } probe->snooper_conf_num = probe_backup->snooper_conf_num; + probe->snooper_state = probe_backup->snooper_state; probe_backup->snooper_conf_num = 0; } diff --git a/src/lib/probe/snooper.h b/src/lib/probe/snooper.h index 59b7551a..9aa046e1 100644 --- a/src/lib/probe/snooper.h +++ b/src/lib/probe/snooper.h @@ -54,6 +54,8 @@ struct snooper_conf_s { void print_snooper(struct probe_s *probe, void *json); int parse_snooper(struct probe_s *probe, const void *json); +int parse_blacklist(struct probe_s *probe, const void *json); +void print_blacklist(struct probe_s *probe, void *json); void free_snooper_conf(struct snooper_conf_s* snooper_conf); void free_snooper_obj(struct snooper_obj_s* snooper_obj); int load_snooper_bpf(struct probe_mng_s *probe_mng); -- Gitee From f7696f2fce83e46a8ee4b81395edbee7ddac1cc2 Mon Sep 17 00:00:00 2001 From: Vchanger Date: Mon, 4 Aug 2025 21:25:15 +0800 Subject: [PATCH 2/4] [Feat] endpoint: adapt global and blacklist snooper --- gala-gopher.spec | 2 +- src/common/common.h | 2 +- src/common/container.c | 3 +- src/common/util.c | 28 +--- src/lib/probe/probe_mng.c | 2 +- .../ebpf.probe/src/endpointprobe/endpoint.c | 150 +++++++++++------- .../ebpf.probe/src/endpointprobe/endpoint.h | 5 +- .../src/endpointprobe/endpoint.meta | 5 + .../ebpf.probe/src/endpointprobe/tcp.bpf.c | 23 ++- .../ebpf.probe/src/endpointprobe/udp.bpf.c | 3 + .../extends/ebpf.probe/src/include/__libbpf.h | 32 ++++ 11 files changed, 169 insertions(+), 86 deletions(-) diff --git a/gala-gopher.spec b/gala-gopher.spec index 0a5d0255..1be87f89 100644 --- a/gala-gopher.spec +++ b/gala-gopher.spec @@ -57,7 +57,7 @@ BuildRequires: jsoncpp-devel java-1.8.0-openjdk-devel %endif Requires: bash gawk procps-ng glibc elfutils libbpf >= 2:0.8 -Requires: libconfig libevent iproute jsoncpp libstdc++ +Requires: libconfig libevent iproute jsoncpp libstdc++ util-linux %if !0%{?disable_kafka_channel} Requires: librdkafka diff --git a/src/common/common.h b/src/common/common.h index 841cc812..0658d8d7 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -233,7 +233,7 @@ int get_proc_cmdline(u32 pid, char *buf, u32 buf_len); int get_proc_str_cmdline(const char *pid_str, char *buf, u32 buf_len); int get_proc_exe(u32 pid, char *buf, u32 buf_len); int get_so_path(int pid, char *elf_path, int size, const char *so_keyword); -int get_kern_version(u32 *kern_version); +u32 get_kernel_version(); int is_valid_proc(int pid); void convert_to_host_path(char *host_path, const char *path, int path_len); int regex_pattern_matched(const char *conf_pattern, const char *target); diff --git a/src/common/container.c b/src/common/container.c index 9be1b55e..86d314f4 100644 --- a/src/common/container.c +++ b/src/common/container.c @@ -1391,9 +1391,8 @@ static int __set_netns_by_pid(pid_t pid) { int ret; int fd = -1; - u32 kern_version = 0; + u32 kern_version = get_kernel_version(); - (void)get_kern_version(&kern_version); if (kern_version < KERNEL_VERSION(5, 3, 0)) { fd = __get_netns_fd(pid); } else { diff --git a/src/common/util.c b/src/common/util.c index 3a958726..adf79a7e 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "common.h" #define CHROOT_CMD "/usr/sbin/chroot %s %s" @@ -542,29 +543,16 @@ int get_so_path(int pid, char *elf_path, int size, const char *so_keyword) return -1; } -int get_kern_version(u32 *kern_version) +u32 get_kernel_version() { - char major, minor, patch = 0; + struct utsname uts; + u32 major, minor, patch = 0; - char version[INT_LEN]; - const char *major_cmd = "uname -r | awk -F '.' '{print $1}' 2>/dev/null"; - const char *minor_cmd = "uname -r | awk -F '.' '{print $2}' 2>/dev/null"; - - version[0] = 0; - if (exec_cmd(major_cmd, version, INT_LEN)) { - return -1; - } - major = (char)strtol(version, NULL, 10); - - version[0] = 0; - if (exec_cmd(minor_cmd, version, INT_LEN)) { - return -1; + uname(&uts); + if (sscanf(uts.release, "%u.%u.%u", &major, &minor, &patch) != 3) { + return 0; } - - minor = (char)strtol(version, NULL, 10); - - *kern_version = (u32)KERNEL_VERSION(major, minor, patch); - return 0; + return (u32)KERNEL_VERSION(major, minor, patch); } int is_valid_proc(int pid) diff --git a/src/lib/probe/probe_mng.c b/src/lib/probe/probe_mng.c index 5b8cf7db..00a6a0d2 100644 --- a/src/lib/probe/probe_mng.c +++ b/src/lib/probe/probe_mng.c @@ -45,7 +45,7 @@ struct probe_define_s probe_define[] = { {"flamegraph", "/opt/gala-gopher/extend_probes/stackprobe", PROBE_FG, SNOOPER_TYPE_PROC, ENABLE_FLAMEGRAPH}, {"l7", "/opt/gala-gopher/extend_probes/l7probe", PROBE_L7, SNOOPER_TYPE_ALL, ENABLE_L7}, {"tcp", "/opt/gala-gopher/extend_probes/tcpprobe", PROBE_TCP, SNOOPER_TYPE_PROC, ENABLE_TCP}, - {"socket", "/opt/gala-gopher/extend_probes/endpoint", PROBE_SOCKET, SNOOPER_TYPE_ALL, ENABLE_SOCKET}, + {"socket", "/opt/gala-gopher/extend_probes/endpoint", PROBE_SOCKET, SNOOPER_TYPE_PROC, ENABLE_SOCKET}, {"io", "/opt/gala-gopher/extend_probes/ioprobe", PROBE_IO, SNOOPER_TYPE_NONE, ENABLE_IO}, {"proc", "/opt/gala-gopher/extend_probes/taskprobe", PROBE_PROC, SNOOPER_TYPE_ALL, ENABLE_PROC}, {"jvm", "/opt/gala-gopher/extend_probes/jvmprobe", PROBE_JVM, SNOOPER_TYPE_PROC, ENABLE_JVM}, diff --git a/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.c b/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.c index 04c341d2..b1502bac 100644 --- a/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.c +++ b/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.c @@ -55,6 +55,8 @@ #define OO_TCP_SOCK "endpoint_tcp" #define OO_UDP_SOCK "endpoint_udp" +#define PROG_TCP_INDEX 0 +#define PROG_UDP_INDEX 1 #define OPEN_TCP_PROBE(probe_name, end, load, buffer) \ INIT_OPEN_OPTS(probe_name); \ @@ -105,6 +107,7 @@ struct tcp_socket_id_s { int tgid; // process id int is_multi; // 1: multi procs listen to one sock enum socket_role_e role; + char comm[TASK_COMM_LEN]; struct conn_addr_s client_ipaddr; struct conn_addr_s server_ipaddr; struct conn_addr_s toa_client_ipaddr; @@ -165,19 +168,21 @@ struct endpoint_probe_s { static volatile sig_atomic_t g_stop; static struct endpoint_probe_s g_ep_probe; static char new_reqsk_drop_func_exist; +static char listen_port_loaded; static char is_snooper(struct endpoint_probe_s *probe, int tgid) { struct snooper_obj_s *snooper; + char is_whitelist = probe->ipc_body.snooper_state == SNOOPER_STATE_WHITELIST ? 1 : 0; for (int i = 0; i < probe->ipc_body.snooper_obj_num; i++) { if (probe->ipc_body.snooper_objs[i].type == SNOOPER_OBJ_PROC) { snooper = &(probe->ipc_body.snooper_objs[i]); if (snooper->obj.proc.proc_id == (unsigned int )tgid) { - return 1; + return is_whitelist; } } } - return 0; + return !is_whitelist; } static void free_tcp_sock(struct tcp_socket_s *tcp_sock) @@ -375,11 +380,12 @@ static void output_tcp_socket(struct tcp_socket_s* tcp_sock) } (void)fprintf(stdout, - "|%s|%d|%s|%s|%s|%s|%u|%u|%d" + "|%s|%d|%s|%s|%s|%s|%s|%u|%u|%d" "|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu" "|%s|\n", OO_TCP_SOCK, tcp_sock->id.tgid, + tcp_sock->id.comm, (tcp_sock->id.role == TCP_SERVER) ? "server" : "client", tcp_sock->client_ip, tcp_sock->toa_client_ip ? : "", @@ -540,6 +546,7 @@ void __init_tcp_socket_id(struct tcp_socket_id_s *id, const struct tcp_socket_ev { memcpy(&(id->client_ipaddr), &(evt->client_ipaddr), sizeof(id->client_ipaddr)); memcpy(&(id->server_ipaddr), &(evt->server_ipaddr), sizeof(id->server_ipaddr)); + memcpy(id->comm, evt->comm, sizeof(evt->comm)); id->is_multi = evt->is_multi; id->tgid = (id->is_multi == 1) ? getpgid(evt->tgid) : (evt->tgid); id->role = evt->role; @@ -794,6 +801,7 @@ static int add_tcp_listen(struct endpoint_probe_s *probe, struct tcp_listen_port memset(listen, 0, sizeof(struct tcp_listen_s)); memcpy(&(listen->key), &key, sizeof(key)); listen->val.proc_id = tlp->pid; + memcpy(listen->val.comm, tlp->comm, sizeof(tlp->comm)); H_ADD_KEYPTR(probe->listens, &listen->key, sizeof(struct tcp_listen_key_s), listen); return 0; } @@ -811,7 +819,7 @@ static void load_tcp_listens(struct endpoint_probe_s *probe) for (int i = 0; i < tlps->tlp_num; i++) { tlp = tlps->tlp[i]; - if (tlp && is_snooper(probe, tlp->pid)) { + if (tlp) { unsigned long ino; ret = get_listen_sock_inode(tlp, &ino); if (ret < 0) { @@ -838,13 +846,36 @@ err: return; } +static void reload_listen_map(struct endpoint_probe_s *probe) +{ + struct tcp_listen_val_s value; + struct tcp_listen_key_s k = {0}; + struct tcp_listen_key_s nk = {0}; + struct tcp_listen_s *listen, *tmp; + + while (bpf_map_get_next_key(probe->listen_port_fd, &k, &nk) == 0) { + (void)bpf_map_lookup_elem(probe->listen_port_fd, &nk, &value); + (void)bpf_map_delete_elem(probe->listen_port_fd, &nk); + } + + H_ITER(probe->listens, listen, tmp) { + (void)bpf_map_update_elem(probe->listen_port_fd, &(listen->key), &(listen->val), BPF_ANY); + } + return; +} + + +#define LS_ALL_NETNS "lsns -t net -n" static void reload_listen_port(struct endpoint_probe_s *probe) { int ret, netns_fd; - struct snooper_con_info_s *container; - struct ipc_body_s *ipc_body = &probe->ipc_body; + u32 ns_pid; + FILE *f = NULL; + char line[LINE_BUF_LEN]; - destroy_tcp_listens(probe); + if (listen_port_loaded) { + return; + } netns_fd = get_netns_fd(getpid()); if (netns_fd <= 0) { @@ -852,44 +883,36 @@ static void reload_listen_port(struct endpoint_probe_s *probe) return; } - load_tcp_listens(probe); + f = popen(LS_ALL_NETNS, "r"); + if (f == NULL) { + ERROR("[EPPROBE]: Get netns fd failed.\n"); + (void)close(netns_fd); + return; + } + + destroy_tcp_listens(probe); + while (!feof(f)) { + if (fgets(line, LINE_BUF_LEN, f) == NULL) { + break; + } - for (int i = 0; i < ipc_body->snooper_obj_num && i < SNOOPER_MAX; i++) { - if (ipc_body->snooper_objs[i].type != SNOOPER_OBJ_CON) { + if (sscanf(line, "%*d %*s %*d %u", &ns_pid) != 1) { + ERROR("[EPPROBE]: Failed to read pid of net namespace.\n"); continue; } - container = &(ipc_body->snooper_objs[i].obj.con_info); - ret = enter_container_netns((const char *)container->con_id); + ret = enter_proc_netns(ns_pid); if (ret) { - ERROR("[EPPROBE]: Enter container netns failed.(container_id = %s)\n", container->con_id); + ERROR("[EPPROBE]: Enter proc netns failed.(proc_id = %s)\n", ns_pid); continue; } - load_tcp_listens(probe); - (void)exit_container_netns(netns_fd); } + listen_port_loaded = 1; (void)close(netns_fd); - return; -} - -static void reload_listen_map(struct endpoint_probe_s *probe) -{ - struct tcp_listen_val_s value; - struct tcp_listen_key_s k = {0}; - struct tcp_listen_key_s nk = {0}; - struct tcp_listen_s *listen, *tmp; - - while (bpf_map_get_next_key(probe->listen_port_fd, &k, &nk) == 0) { - (void)bpf_map_lookup_elem(probe->listen_port_fd, &nk, &value); - (void)bpf_map_delete_elem(probe->listen_port_fd, &nk); - } - - H_ITER(probe->listens, listen, tmp) { - (void)bpf_map_update_elem(probe->listen_port_fd, &(listen->key), &(listen->val), BPF_ANY); - } + reload_listen_map(probe); return; } @@ -1021,7 +1044,7 @@ static int endpoint_load_probe_tcp(struct endpoint_probe_s *probe, struct bpf_pr OPEN_TCP_PROBE(tcp, err, is_load, buffer); if (is_load) { - + listen_port_loaded = 0; int kernel_version = probe_kernel_version(); PROG_ENABLE_ONLY_IF(tcp, bpf_raw_trace_tcp_retransmit_synack, kernel_version > KERNEL_VERSION(4, 18, 0)); PROG_ENABLE_ONLY_IF(tcp, bpf_trace_tcp_retransmit_synack_func, kernel_version <= KERNEL_VERSION(4, 18, 0)); @@ -1030,16 +1053,16 @@ static int endpoint_load_probe_tcp(struct endpoint_probe_s *probe, struct bpf_pr MAP_SET_MAX_ENTRIES(tcp, tcp_evt_map, buffer, ringbuf_map_size); LOAD_ATTACH(endpoint, tcp, err, is_load); - prog->skels[prog->num].skel = tcp_skel; - prog->skels[prog->num].fn = (skel_destroy_fn)tcp_bpf__destroy; - prog->custom_btf_paths[prog->num] = tcp_open_opts.btf_custom_path; + prog->skels[PROG_TCP_INDEX].skel = tcp_skel; + prog->skels[PROG_TCP_INDEX].fn = (skel_destroy_fn)tcp_bpf__destroy; + prog->custom_btf_paths[PROG_TCP_INDEX] = tcp_open_opts.btf_custom_path; int ret = bpf_buffer__open(buffer, proc_tcp_sock_evt, NULL, probe); if (ret) { ERROR("[ENDPOINT] Open 'tcp_evt_map' bpf_buffer failed.\n"); goto err; } - prog->buffers[prog->num] = buffer; + prog->buffers[PROG_TCP_INDEX] = buffer; prog->num++; probe->listen_port_fd = GET_MAP_FD(tcp, tcp_listen_port); } @@ -1062,16 +1085,16 @@ static int endpoint_load_probe_udp(struct endpoint_probe_s *probe, struct bpf_pr MAP_SET_MAX_ENTRIES(udp, udp_evt_map, buffer, ringbuf_map_size); LOAD_ATTACH(endpoint, udp, err, is_load); - prog->skels[prog->num].skel = udp_skel; - prog->skels[prog->num].fn = (skel_destroy_fn)udp_bpf__destroy; - prog->custom_btf_paths[prog->num] = udp_open_opts.btf_custom_path; + prog->skels[PROG_UDP_INDEX].skel = udp_skel; + prog->skels[PROG_UDP_INDEX].fn = (skel_destroy_fn)udp_bpf__destroy; + prog->custom_btf_paths[PROG_UDP_INDEX] = udp_open_opts.btf_custom_path; int ret = bpf_buffer__open(buffer, proc_udp_sock_evt, NULL, probe); if (ret) { ERROR("[ENDPOINT] Open 'udp_evt_map' bpf_buffer failed.\n"); goto err; } - prog->buffers[prog->num] = buffer; + prog->buffers[PROG_UDP_INDEX] = buffer; prog->num++; } @@ -1083,36 +1106,47 @@ err: return -1; } -static int endpoint_load_probe(struct endpoint_probe_s *probe, struct ipc_body_s *ipc_body) +static int endpoint_reload_probe(struct endpoint_probe_s *probe, struct ipc_body_s *ipc_body) { - char is_load_tcp, is_load_udp; - struct bpf_prog_s *new_prog = NULL; - - is_load_tcp = ipc_body->probe_range_flags & PROBE_RANGE_SOCKET_TCP; - is_load_udp = ipc_body->probe_range_flags & PROBE_RANGE_SOCKET_UDP; - if (!(is_load_tcp | is_load_udp)) { + char to_load_tcp, to_load_udp; + char is_tcp_loaded, is_udp_loaded; + struct bpf_prog_s *prog = probe->prog; + + to_load_tcp = ipc_body->probe_range_flags & PROBE_RANGE_SOCKET_TCP; + to_load_udp = ipc_body->probe_range_flags & PROBE_RANGE_SOCKET_UDP; + is_tcp_loaded = probe->ipc_body.probe_range_flags & PROBE_RANGE_SOCKET_TCP; + is_udp_loaded = probe->ipc_body.probe_range_flags & PROBE_RANGE_SOCKET_UDP; + if (!(to_load_tcp | to_load_udp)) { + unload_bpf_prog(&probe->prog); return 0; } - new_prog = alloc_bpf_prog(); - if (new_prog == NULL) { - return -1; + if (prog == NULL) { + prog = alloc_bpf_prog(); + if (prog == NULL) { + return -1; + } } - if (endpoint_load_probe_tcp(probe, new_prog, ipc_body->probe_param.ringbuf_map_size, is_load_tcp)) { + unload_bpf_subprog(prog, PROG_TCP_INDEX, is_tcp_loaded && !to_load_tcp); + if (endpoint_load_probe_tcp(probe, prog, ipc_body->probe_param.ringbuf_map_size, + !is_tcp_loaded && to_load_tcp)) { goto err; } - if (endpoint_load_probe_udp(probe, new_prog, ipc_body->probe_param.ringbuf_map_size, is_load_udp)) { + + unload_bpf_subprog(prog, PROG_UDP_INDEX, is_udp_loaded && !to_load_udp); + if (endpoint_load_probe_udp(probe, prog, ipc_body->probe_param.ringbuf_map_size, + !is_udp_loaded && to_load_udp)) { goto err; } probe->last_report = time(NULL); - probe->prog = new_prog; + probe->prog = prog; return 0; err: - unload_bpf_prog(&new_prog); + unload_bpf_prog(&probe->prog); return -1; } @@ -1305,8 +1339,7 @@ int main(int argc, char **argv) ret = recv_ipc_msg(msq_id, (long)PROBE_SOCKET, &ipc_body); if (ret == 0) { if (ipc_body.probe_range_flags != g_ep_probe.ipc_body.probe_range_flags) { - unload_bpf_prog(&(g_ep_probe.prog)); - if (endpoint_load_probe(&g_ep_probe, &ipc_body)) { + if (endpoint_reload_probe(&g_ep_probe, &ipc_body)) { break; } } @@ -1319,7 +1352,6 @@ int main(int argc, char **argv) destroy_ipc_body(&(g_ep_probe.ipc_body)); (void)memcpy(&(g_ep_probe.ipc_body), &ipc_body, sizeof(g_ep_probe.ipc_body)); reload_listen_port(&g_ep_probe); - reload_listen_map(&g_ep_probe); } if (poll_endpoint_pb(&g_ep_probe)) { diff --git a/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.h b/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.h index 0ac4291e..e7a66e3f 100644 --- a/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.h +++ b/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.h @@ -57,7 +57,8 @@ struct conn_addr_s { struct tcp_socket_event_s { int tgid; // process id - int is_multi; // is_multi: 1: multi procs listen to one sock + char is_multi; // is_multi: 1: multi procs listen to one sock + char comm[TASK_COMM_LEN]; u64 estab_latency; // unit: ns struct conn_addr_s client_ipaddr; struct conn_addr_s server_ipaddr; @@ -70,6 +71,7 @@ struct tcp_socket_event_s { struct udp_socket_event_s { int tgid; // process id + char comm[TASK_COMM_LEN]; struct conn_addr_s local_ipaddr; struct conn_addr_s remote_ipaddr; enum socket_evt_e evt; @@ -84,6 +86,7 @@ struct tcp_listen_key_s { struct tcp_listen_val_s { unsigned int proc_id; + char comm[TASK_COMM_LEN]; int is_multi; // 1: proc_id is pgid of multi procs, used for multi procs listen to one sock }; diff --git a/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.meta b/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.meta index f316db55..7cccb1bd 100644 --- a/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.meta +++ b/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.meta @@ -12,6 +12,11 @@ measurements: type: "key", name: "tgid", }, + { + description: "command of process", + type: "key", + name: "comm", + }, { description: "role", type: "key", diff --git a/src/probes/extends/ebpf.probe/src/endpointprobe/tcp.bpf.c b/src/probes/extends/ebpf.probe/src/endpointprobe/tcp.bpf.c index 6cec8c35..bd6f81fb 100644 --- a/src/probes/extends/ebpf.probe/src/endpointprobe/tcp.bpf.c +++ b/src/probes/extends/ebpf.probe/src/endpointprobe/tcp.bpf.c @@ -108,6 +108,7 @@ struct { struct sock_info_s { enum socket_role_e role; int tgid; + char comm[TASK_COMM_LEN]; int is_multi; // 1: multi procs listen to one sock u64 syn_start_ts; // client: ts of SYN_SENT ; server: ts of sending synack }; @@ -155,6 +156,7 @@ static __always_inline void add_sock(const struct sock *sk, enum socket_role_e r new_info.tgid = tgid; new_info.is_multi = 0; // default is 0 new_info.role = role; + bpf_get_current_comm(&new_info.comm, sizeof(new_info.comm)); if (role == TCP_CLIENT) { new_info.syn_start_ts = bpf_ktime_get_ns(); @@ -171,6 +173,7 @@ static __always_inline void add_sock_and_tgid(const struct sock *sk, enum socket info.tgid = v->proc_id; info.is_multi = v->is_multi; info.role = role; + __builtin_memcpy(info.comm, v->comm, sizeof(v->comm)); bpf_map_update_elem(&tcp_socks, &sk, &info, BPF_ANY); return; } @@ -180,6 +183,7 @@ static __always_inline void add_sock_by_listen_sk(const struct sock *sk, struct struct sock_info_s new_info = {0}; new_info.tgid = info->tgid; + __builtin_memcpy(new_info.comm, info->comm, sizeof(info->comm)); new_info.role = TCP_SERVER; new_info.syn_start_ts = info->syn_start_ts; bpf_map_update_elem(&tcp_socks, &sk, &new_info, BPF_ANY); @@ -354,6 +358,7 @@ static __always_inline void report_synack_sent_evt(void *ctx, const struct sock* get_request_sockaddr(&evt, req); evt.evt = retran ? EP_STATS_RETRANS_SYNACK : EP_STATS_SYNACK_SENT; evt.tgid = info->tgid; + __builtin_memcpy(evt.comm, info->comm, sizeof(info->comm)); evt.is_multi = info->is_multi; // report; @@ -398,6 +403,7 @@ KRETPROBE(tcp_connect, pt_regs) get_connect_sockaddr(&evt, (const struct sock *)sk); evt.evt = args->neigh_failed ? EP_STATS_SYN_DROP : EP_STATS_SYN_SENT; evt.tgid = (int)(id >> INT_LEN); + bpf_get_current_comm(&evt.comm, sizeof(evt.comm)); evt.is_multi = 0; // report; @@ -498,6 +504,7 @@ KPROBE(tcp_set_state, pt_regs) } evt.tgid = info->tgid; + __builtin_memcpy(evt.comm, info->comm, sizeof(info->comm)); evt.is_multi = info->is_multi; curr_ts = bpf_ktime_get_ns(); if (info->syn_start_ts != 0 && (curr_ts > info->syn_start_ts)) { @@ -511,6 +518,7 @@ KPROBE(tcp_set_state, pt_regs) get_connect_sockaddr(&evt, (const struct sock *)sk); evt.evt = EP_STATS_ACTIVE_FAILS; evt.tgid = info->tgid; + __builtin_memcpy(evt.comm, info->comm, sizeof(info->comm)); evt.is_multi = info->is_multi; // report; @@ -522,6 +530,7 @@ KPROBE(tcp_set_state, pt_regs) get_accept_sockaddr(&evt, (const struct sock *)sk); evt.evt = EP_STATS_PASSIVE_FAILS; evt.tgid = info->tgid; + __builtin_memcpy(evt.comm, info->comm, sizeof(info->comm)); evt.is_multi = info->is_multi; // report; @@ -540,6 +549,7 @@ KPROBE(tcp_set_state, pt_regs) evt.evt = EP_STATS_CONN_CLOSE; evt.tgid = info->tgid; + __builtin_memcpy(evt.comm, info->comm, sizeof(info->comm)); evt.is_multi = info->is_multi; evt.role = info->role; (void)bpfbuf_output(ctx, &tcp_evt_map, &evt, sizeof(struct tcp_socket_event_s)); @@ -783,11 +793,12 @@ KPROBE(tcp_conn_request, pt_regs) } struct sock_info_s* info = lkup_sock((const struct sock *)sk); + struct tcp_listen_val_s *val = NULL; if (info && info->role == TCP_LISTEN_SK) { tgid = info->tgid; is_multi = info->is_multi; } else { - struct tcp_listen_val_s *val = get_proc_info_by_listen_sk((const struct sock *)sk); + val = get_proc_info_by_listen_sk((const struct sock *)sk); if (val == NULL) { goto end; } @@ -851,6 +862,12 @@ KPROBE(tcp_conn_request, pt_regs) } evt.tgid = tgid; + if (info) + __builtin_memcpy(evt.comm, info->comm, sizeof(info->comm)); + + if (val) + __builtin_memcpy(evt.comm, val->comm, sizeof(val->comm)); + evt.is_multi = is_multi; // report; evt.role = TCP_SERVER; @@ -890,6 +907,7 @@ KPROBE(tcp_req_err, pt_regs) get_accept_sockaddr(&evt, (const struct sock *)sk); evt.evt = EP_STATS_LISTEN_DROPS; evt.tgid = info->tgid; + __builtin_memcpy(evt.comm, info->comm, sizeof(info->comm)); evt.is_multi = info->is_multi; // report; @@ -940,6 +958,7 @@ KPROBE(inet_csk_reqsk_queue_drop_and_put, pt_regs) get_request_sockaddr(&evt, req); evt.evt = EP_STATS_REQ_DROP; evt.tgid = info->tgid; + __builtin_memcpy(evt.comm, info->comm, sizeof(info->comm)); evt.is_multi = info->is_multi; // report; @@ -963,6 +982,7 @@ KPROBE(__inet_csk_reqsk_queue_drop, pt_regs) get_request_sockaddr(&evt, req); evt.evt = EP_STATS_REQ_DROP; evt.tgid = info->tgid; + __builtin_memcpy(evt.comm, info->comm, sizeof(info->comm)); evt.is_multi = info->is_multi; // report; @@ -1003,6 +1023,7 @@ KPROBE(tcp_retransmit_skb, pt_regs) get_connect_sockaddr(&evt, (const struct sock *)sk); evt.evt = EP_STATS_RETRANS_SYN; evt.tgid = info->tgid; + __builtin_memcpy(evt.comm, info->comm, sizeof(info->comm)); evt.is_multi = info->is_multi; // report; diff --git a/src/probes/extends/ebpf.probe/src/endpointprobe/udp.bpf.c b/src/probes/extends/ebpf.probe/src/endpointprobe/udp.bpf.c index 5c7c19bc..6269e526 100644 --- a/src/probes/extends/ebpf.probe/src/endpointprobe/udp.bpf.c +++ b/src/probes/extends/ebpf.probe/src/endpointprobe/udp.bpf.c @@ -140,6 +140,7 @@ KPROBE(udp_sendmsg, pt_regs) get_local_sockaddr(&evt, (const struct sock *)sk); evt.val = (u64)len; evt.tgid = (int)(bpf_get_current_pid_tgid() >> INT_LEN); + bpf_get_current_comm(&evt.comm, sizeof(evt.comm)); evt.evt = EP_STATS_UDP_SENDS; // report; @@ -186,6 +187,7 @@ KRETPROBE(__skb_recv_udp, pt_regs) unsigned int len = _(skb->len); evt.val = (u64)len; evt.tgid = (int)(bpf_get_current_pid_tgid() >> INT_LEN); + bpf_get_current_comm(&evt.comm, sizeof(evt.comm)); evt.evt = EP_STATS_UDP_RCVS; // report; @@ -273,6 +275,7 @@ KRETPROBE(__udp_enqueue_schedule_skb, pt_regs) evt.val = (u64)len; evt.evt = EP_STATS_QUE_RCV_FAILED; evt.tgid = (int)(id >> INT_LEN); + bpf_get_current_comm(&evt.comm, sizeof(evt.comm)); // report; (void)bpfbuf_output(ctx, &udp_evt_map, &evt, sizeof(struct udp_socket_event_s)); diff --git a/src/probes/extends/ebpf.probe/src/include/__libbpf.h b/src/probes/extends/ebpf.probe/src/include/__libbpf.h index 34d0be5b..78a3c3c4 100644 --- a/src/probes/extends/ebpf.probe/src/include/__libbpf.h +++ b/src/probes/extends/ebpf.probe/src/include/__libbpf.h @@ -656,6 +656,38 @@ static __always_inline __maybe_unused void unload_bpf_prog(struct bpf_prog_s **u return; } +static __always_inline __maybe_unused void unload_bpf_subprog(struct bpf_prog_s *prog, u32 index, char subprog_loaded) +{ + if (prog == NULL || index >= prog->num || !subprog_loaded) { + return; + } + + if (prog->skels[index].skel) { + prog->skels[index].fn(prog->skels[index].skel); + + for (int i = 0; i < prog->skels[i]._link_num; i++) { + if (prog->skels[index]._link[i]) { + (void)bpf_link__destroy(prog->skels[index]._link[i]); + } + } + + prog->skels[index].skel = NULL; + } + + perf_buffer__free(prog->pbs[index]); + prog->pbs[index] = NULL; + + ring_buffer__free(prog->rbs[index]); + prog->rbs[index] = NULL; + + bpf_buffer__free(prog->buffers[index]); + prog->buffers[index] = NULL; + + free((char *)prog->custom_btf_paths[index]); + prog->custom_btf_paths[index] = NULL; + + prog->num--; +} #endif #endif -- Gitee From c307cf260e73b62390fae797e786882182de4a35 Mon Sep 17 00:00:00 2001 From: Vchanger Date: Mon, 4 Aug 2025 21:33:03 +0800 Subject: [PATCH 3/4] [Feat] tcpprobe: adapt global and blacklist snooper --- .../extends/ebpf.probe/src/include/__libbpf.h | 4 +- .../ebpf.probe/src/include/__obj_map.h | 23 +++++++- .../ebpf.probe/src/tcpprobe/tcp_link.meta | 5 ++ .../ebpf.probe/src/tcpprobe/tcp_probe.c | 53 +++++++++++++++++-- .../ebpf.probe/src/tcpprobe/tcpprobe.c | 28 +++++++--- 5 files changed, 100 insertions(+), 13 deletions(-) diff --git a/src/probes/extends/ebpf.probe/src/include/__libbpf.h b/src/probes/extends/ebpf.probe/src/include/__libbpf.h index 78a3c3c4..15c6a409 100644 --- a/src/probes/extends/ebpf.probe/src/include/__libbpf.h +++ b/src/probes/extends/ebpf.probe/src/include/__libbpf.h @@ -104,9 +104,11 @@ static __always_inline int set_memlock_rlimit(unsigned long limit) __MAP_SET_PIN_PATH(probe_name, cgrp_obj_map, "/sys/fs/bpf/gala-gopher/__"#app_name"_cgroup_map"); \ __MAP_SET_PIN_PATH(probe_name, nm_obj_map, "/sys/fs/bpf/gala-gopher/__"#app_name"_nm_map"); \ __MAP_SET_PIN_PATH(probe_name, proc_obj_map, "/sys/fs/bpf/gala-gopher/__"#app_name"_proc_map"); \ + __MAP_SET_PIN_PATH(probe_name, snooper_state_map, "/sys/fs/bpf/gala-gopher/__"#app_name"_snooper_state_map"); \ } while (0) -#define GET_PROC_MAP_PIN_PATH(app_name) ("/sys/fs/bpf/gala-gopher/__"#app_name"_proc_map") +#define GET_PROC_MAP_PIN_PATH(app_name) ("/sys/fs/bpf/gala-gopher/__"#app_name"_proc_map") +#define GET_SNOOPER_STATE_MAP_PIN_PATH(app_name) ("/sys/fs/bpf/gala-gopher/__"#app_name"_snooper_state_map") #define INIT_BPF_APP(app_name, limit) \ static char __init = 0; \ diff --git a/src/probes/extends/ebpf.probe/src/include/__obj_map.h b/src/probes/extends/ebpf.probe/src/include/__obj_map.h index c59fff23..b800a29d 100644 --- a/src/probes/extends/ebpf.probe/src/include/__obj_map.h +++ b/src/probes/extends/ebpf.probe/src/include/__obj_map.h @@ -38,6 +38,12 @@ * and read and write operations in user mode. * MUST NOT BE perform write operations in kernel mode. */ +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(key_size, sizeof(u32)); // const value 0 + __uint(value_size, sizeof(u32)); + __uint(max_entries, 1); +} snooper_state_map SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_HASH); @@ -60,6 +66,18 @@ struct { __uint(max_entries, PROC_MAP_MAX_ENTRIES); } proc_obj_map SEC(".maps"); +static __always_inline __maybe_unused char is_snooper_blacklist() +{ + u32 key = 0; + u32 *snooper_state = bpf_map_lookup_elem(&snooper_state_map, &key); + + if (snooper_state) { + return (*snooper_state) ? 1 : 0; + } + + return 0; +} + static __always_inline __maybe_unused char is_cgrp_exist(struct cgroup_s *obj) { if (bpf_map_lookup_elem(&cgrp_obj_map, obj) == (void *)0) { @@ -78,10 +96,11 @@ static __always_inline __maybe_unused char is_nm_exist(struct nm_s *obj) static __always_inline __maybe_unused char is_proc_exist(struct proc_s *obj) { + char blacklist = is_snooper_blacklist(); if (bpf_map_lookup_elem(&proc_obj_map, obj) == (void *)0) { - return 0; + return blacklist; } - return 1; + return !blacklist; } static __always_inline __maybe_unused int proc_add(struct proc_s *obj) diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.meta b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.meta index 4f8a18a9..d4ff1edd 100644 --- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.meta +++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.meta @@ -11,6 +11,11 @@ measurements: type: "key", name: "tgid", }, + { + description: "command of process", + type: "key", + name: "comm", + }, { description: "role", type: "key", diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c index bfe6e17c..6af7084a 100644 --- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c +++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c @@ -412,10 +412,11 @@ static int output_tcp_metrics(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *t if (outputted) { (void)fprintf(stdout, - "|%s|%u|%s|%s|%s|%s|%u|%u|%u" + "|%s|%u|%s|%s|%s|%s|%s|%u|%u|%u" "%s%s%s%s%s%s%s|\n", TCP_TBL_METRIC, tracker->id.tgid, + tracker->id.comm, (tracker->id.role == 0) ? "server" : "client", tracker->src_ip, tracker->toa_src_ip ? : "", @@ -918,6 +919,10 @@ static int tcp_load_probe_link(struct tcp_mng_s *tcp_mng, unsigned char ringbuf_ int err; struct bpf_buffer *buffer = NULL; + if (prog->num) { + return 0; + } + __OPEN_PROBE_WITH_OUTPUT(tcp_link, err, 1, buffer, ringbuf_map_size); __SELECT_DESTROY_SOCK_HOOKPOINT(tcp_link); __LOAD_PROBE(tcp_link, err, 1); @@ -943,6 +948,45 @@ err: return -1; } +void tcp_unload_probe(struct tcp_mng_s *tcp_mng) +{ + struct bpf_prog_s *prog = tcp_mng->tcp_progs; + if (prog == NULL || prog->num == 0) { + return; + } + + // start from 1 to skip unload tcp_link + for (int i = 1; i < prog->num; i++) { + if (prog->skels[i].skel) { + prog->skels[i].fn(prog->skels[i].skel); + + for (int j = 0; j < prog->skels[i]._link_num; j++) { + if (prog->skels[i]._link[j]) { + (void)bpf_link__destroy(prog->skels[i]._link[j]); + } + } + prog->skels[i].skel = NULL; + } + + if (prog->pbs[i]) { + perf_buffer__free(prog->pbs[i]); + } + + if (prog->rbs[i]) { + ring_buffer__free(prog->rbs[i]); + } + + if (prog->buffers[i]) { + bpf_buffer__free(prog->buffers[i]); + } + + free((char *)prog->custom_btf_paths[i]); + prog->num--; + } + return; +} + + int tcp_load_probe(struct tcp_mng_s *tcp_mng, struct ipc_body_s *ipc_body, struct bpf_prog_s **new_prog) { char is_load = 0, is_load_stats = 0; @@ -965,9 +1009,12 @@ int tcp_load_probe(struct tcp_mng_s *tcp_mng, struct ipc_body_s *ipc_body, struc return 0; } - prog = alloc_bpf_prog(); + prog = *new_prog; if (prog == NULL) { - return -1; + prog = alloc_bpf_prog(); + if (prog == NULL) { + return -1; + } } if (tcp_load_probe_link(tcp_mng, ipc_body->probe_param.ringbuf_map_size, prog)) { diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c index c14cd7af..93690125 100644 --- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c +++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c @@ -50,6 +50,7 @@ static struct tcp_mng_s g_tcp_mng; #define RM_COMMON_MAP_PATH "/usr/bin/rm -rf /sys/fs/bpf/gala-gopher/__tcpprobe_*" int load_established_tcps(int proc_obj_map_fd, int map_fd); +void tcp_unload_probe(struct tcp_mng_s *tcp_mng); int tcp_load_probe(struct tcp_mng_s *tcp_mng, struct ipc_body_s *ipc_body, struct bpf_prog_s **new_prog); void scan_tcp_trackers(struct tcp_mng_s *tcp_mng); void scan_tcp_flow_trackers(struct tcp_mng_s *tcp_mng); @@ -285,7 +286,9 @@ static void tcp_load_args(int args_fd, struct ipc_body_s *ipc_body) int main(int argc, char **argv) { int err = -1, ret; - int tcp_fd_map_fd = -1, proc_obj_map_fd = -1, args_map_fd = -1; + int tcp_fd_map_fd = -1, proc_obj_map_fd = -1; + int snooper_state_map_fd = -1, args_map_fd = -1; + u32 snooper_state_key = 0, is_snooper_blacklist = 0; struct tcp_mng_s *tcp_mng = &g_tcp_mng; struct ipc_body_s ipc_body; @@ -331,8 +334,10 @@ int main(int argc, char **argv) tcp_fd_map_fd = bpf_obj_get(TCP_LINK_FD_PATH); proc_obj_map_fd = bpf_obj_get(GET_PROC_MAP_PIN_PATH(tcpprobe)); + snooper_state_map_fd = bpf_obj_get(GET_SNOOPER_STATE_MAP_PIN_PATH(tcpprobe)); args_map_fd = bpf_obj_get(TCP_LINK_ARGS_PATH); - if (tcp_fd_map_fd <= 0 || proc_obj_map_fd <= 0 || args_map_fd <= 0) { + if (tcp_fd_map_fd <= 0 || proc_obj_map_fd <= 0 || + snooper_state_map_fd <= 0 || args_map_fd <= 0) { ERROR("[TCPPROBE]: Failed to get bpf map fd\n"); goto err; } @@ -347,7 +352,7 @@ int main(int argc, char **argv) if (tcp_mng->ipc_body.probe_range_flags != ipc_body.probe_range_flags || ipc_body.probe_flags == 0) { INFO("[TCPPROBE]: Starting to unload ebpf prog.\n"); reload_tc_bpf(&ipc_body); - unload_bpf_prog(&(tcp_mng->tcp_progs)); + tcp_unload_probe(tcp_mng); if (tcp_load_probe(tcp_mng, &ipc_body, &(tcp_mng->tcp_progs))) { destroy_ipc_body(&ipc_body); break; @@ -359,7 +364,14 @@ int main(int argc, char **argv) } if (ipc_body.probe_flags & IPC_FLAGS_SNOOPER_CHG || ipc_body.probe_flags == 0) { - lkup_established_tcp(proc_obj_map_fd, &ipc_body); + if (ipc_body.snooper_state != tcp_mng->ipc_body.snooper_state) { + is_snooper_blacklist = (ipc_body.snooper_state == SNOOPER_STATE_WHITELIST) ? 0 : 1; + (void)bpf_map_update_elem(snooper_state_map_fd, &snooper_state_key, + &is_snooper_blacklist, BPF_ANY); + } + if (!is_snooper_blacklist) { + lkup_established_tcp(proc_obj_map_fd, &ipc_body); + } reload_tcp_snoopers(proc_obj_map_fd, &(tcp_mng->ipc_body), &ipc_body); } destroy_ipc_body(&(tcp_mng->ipc_body)); @@ -371,9 +383,11 @@ int main(int argc, char **argv) goto err; } - ret = load_established_tcps_mngt(proc_obj_map_fd, tcp_fd_map_fd); - if (ret) { - goto err; + if (!is_snooper_blacklist) { + ret = load_established_tcps_mngt(proc_obj_map_fd, tcp_fd_map_fd); + if (ret) { + goto err; + } } // poll from last buffer to adapt for pinned perf event map -- Gitee From 365c0c92e0208c73b231e225f64bcb7455c713c5 Mon Sep 17 00:00:00 2001 From: Vchanger Date: Mon, 4 Aug 2025 21:40:24 +0800 Subject: [PATCH 4/4] skip appending comm label for tcpprobe and endpoint --- src/lib/imdb/imdb.c | 13 +++++++++---- src/lib/imdb/imdb.h | 3 ++- src/resource/resource.c | 4 ++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/lib/imdb/imdb.c b/src/lib/imdb/imdb.c index 37051954..12263a1c 100644 --- a/src/lib/imdb/imdb.c +++ b/src/lib/imdb/imdb.c @@ -894,15 +894,20 @@ static int append_proc_level_labels(const char *tgid_str, char **buffer_ptr, int tgidRecord = IMDB_TgidCreateRecord(mgr, tgid_str); } if (tgidRecord == NULL) { + if (table->metric_has_comm) { + return ret; + } DEBUG("[IMDB] Failed to create tgid cache(tgid=%s)\n", tgid_str); return IMDB_BUILD_ERR; } IMDB_TgidRecordUpdateLabel(tgidRecord, table->probe); - ret = __snprintf(buffer_ptr, *size_ptr, size_ptr, cmd_fmt, - META_COMMON_LABEL_PROC_COMM, tgidRecord->comm); - if (ret < 0) { - return IMDB_BUFFER_FULL; + if (!table->metric_has_comm) { + ret = __snprintf(buffer_ptr, *size_ptr, size_ptr, cmd_fmt, + META_COMMON_LABEL_PROC_COMM, tgidRecord->comm); + if (ret < 0) { + return IMDB_BUFFER_FULL; + } } if (is_entity_proc(table->entity_name)) { diff --git a/src/lib/imdb/imdb.h b/src/lib/imdb/imdb.h index fbe645cc..72ab0308 100644 --- a/src/lib/imdb/imdb.h +++ b/src/lib/imdb/imdb.h @@ -95,7 +95,8 @@ typedef struct IMDB_Table_s { IMDB_Meta *meta; struct probe_s *probe; char weighting; // 0: Highest Level(Entitlement to priority); >0: Low priority - char pad[3]; // rsvd + char metric_has_comm; + char pad[2]; // rsvd uint32_t recordsCapability; // Capability for records count in one table uint32_t recordNum; IMDB_Record *records; diff --git a/src/resource/resource.c b/src/resource/resource.c index e68d48d5..341b132e 100644 --- a/src/resource/resource.c +++ b/src/resource/resource.c @@ -335,6 +335,10 @@ static int IMDBMgrTableLoad(IMDB_Table *table, Measurement *mm) if (strcmp(mm->fields[i].type, METRIC_TYPE_KEY) == 0) { keyNum++; } + + if (strcmp(mm->fields[i].name, META_COMMON_LABEL_PROC_COMM) == 0) { + table->metric_has_comm = 1; + } } if (keyNum == 0) { -- Gitee