From ba065ebd20e887ddd5d8cc4e49f375b01e239b4a Mon Sep 17 00:00:00 2001 From: xuchunxiao119 <9571203+xuchunxiao119@user.noreply.gitee.com> Date: Tue, 7 Jan 2025 10:10:48 +0800 Subject: [PATCH] add custom probe management --- build/install.sh | 6 + config/gala-gopher-custom.json | 0 gala-gopher.spec | 1 + script/init_probes.sh | 15 + src/common/args.h | 2 +- src/common/ipc.c | 149 +++- src/common/ipc.h | 17 +- src/common/json_tool.cpp | 20 + src/common/json_tool.h | 3 + src/lib/base.h | 13 + src/lib/meta/meta.c | 101 ++- src/lib/meta/meta.h | 1 + src/lib/probe/extend_probe.c | 2 +- src/lib/probe/probe_mng.c | 759 +++++++++++++++++- src/lib/probe/probe_mng.h | 25 + src/lib/probe/probe_params_parser.c | 135 +++- src/lib/probe/snooper.c | 9 +- src/probes/extends/python.probe/common/ipc.py | 25 + src/resource/resource.c | 1 + 19 files changed, 1229 insertions(+), 55 deletions(-) create mode 100644 config/gala-gopher-custom.json diff --git a/build/install.sh b/build/install.sh index 9f2c14a3..6d73dd33 100755 --- a/build/install.sh +++ b/build/install.sh @@ -69,6 +69,7 @@ function install_conf() { GOPHER_CONF_FILE=${PROJECT_FOLDER}/config/gala-gopher.conf GOPHER_PROBES_INIT_FILE=${PROJECT_FOLDER}/config/probes.init GOPHER_CONF_TARGET_DIR=/etc/gala-gopher + GOPHER_CUSTOM_FILE=${PROJECT_FOLDER}/config/gala-gopher-custom.json if [ $# -eq 1 ]; then GOPHER_CONF_TARGET_DIR=$1 @@ -82,6 +83,9 @@ function install_conf() { if [ ! -f ${GOPHER_PROBES_INIT_FILE} ]; then echo "${GOPHER_PROBES_INIT_FILE} not exist. please check ./config dir." fi + if [ ! -f ${GOPHER_CUSTOM_FILE} ]; then + echo "${GOPHER_CUSTOM_FILE} not exist. please check ./config dir." + fi # install gala-gopher.conf if [ ! -d ${GOPHER_CONF_TARGET_DIR} ]; then @@ -89,6 +93,8 @@ function install_conf() { fi cp -f ${GOPHER_CONF_FILE} ${GOPHER_CONF_TARGET_DIR} echo "install ${GOPHER_CONF_FILE} success." + cp -f ${GOPHER_CUSTOM_FILE} ${GOPHER_CONF_TARGET_DIR} + echo "install ${GOPHER_CUSTOM_FILE} success." cp -f ${GOPHER_PROBES_INIT_FILE} ${GOPHER_CONF_TARGET_DIR} echo "install ${GOPHER_PROBES_INIT_FILE} success." } diff --git a/config/gala-gopher-custom.json b/config/gala-gopher-custom.json new file mode 100644 index 00000000..e69de29b diff --git a/gala-gopher.spec b/gala-gopher.spec index ca1da4c2..0a5d0255 100644 --- a/gala-gopher.spec +++ b/gala-gopher.spec @@ -191,6 +191,7 @@ fi %attr(0640,root,root) %config(noreplace) /etc/gala-gopher/probes.init %attr(0640,root,root) %config(noreplace) /etc/gala-gopher/*.conf %attr(0640,root,root) %config(noreplace) /etc/gala-gopher/extend_probes/*.conf +%attr(0640,root,root) %config(noreplace) /etc/gala-gopher/gala-gopher-custom.json %attr(0600,root,root) /usr/lib/systemd/system/gala-gopher.service %attr(0550,root,root) /usr/libexec/gala-gopher/init_probes.sh %attr(0550,root,root) /usr/libexec/gala-gopher/start_pre.sh diff --git a/script/init_probes.sh b/script/init_probes.sh index 5a86ea05..f61bbbb0 100755 --- a/script/init_probes.sh +++ b/script/init_probes.sh @@ -17,6 +17,7 @@ GOPHER_INITIAL_CONF="/etc/gala-gopher/probes.init" GOPHER_CMD_SOCK_PATH="/var/run/gala_gopher/gala_gopher_cmd.sock" GOPHER_PIDFILE="/var/run/gala_gopher/gala-gopher.pid" MAX_INIT_NUM=25 +GOPHER_CUSTOM_JSON="/etc/gala-gopher/gala-gopher-custom.json" MAX_ATTEMPTS=20 PROBES=( @@ -43,6 +44,19 @@ PROBES=( "flowtracer" ) +function check_custom() +{ + if [ -e "$GOPHER_CUSTOM_JSON" ] && [ -s "$GOPHER_CUSTOM_JSON" ]; then + custome_keys=$(cat "$GOPHER_CUSTOM_JSON" | tr -d '\n' | tr -s ' ' | sed 's/"[[:space:]]*{/{/g; s/:[[:space:]]*{/:{/g; s/{/{\n/g; s/}/}\n/g' | grep -o '"[^"]*"[[:space:]]*:{' | cut -d '"' -f 2) + for key in $custome_keys; do + if [ -n "$key" ]; then + PROBES+=("$key") + fi + done + fi + echo "PROBES=(${PROBES[*]})" +} + function check_gopher_running() { local attempt=0 @@ -107,6 +121,7 @@ function save_probes_json() exit 1 fi + check_custom for url in "${PROBES[@]}"; do response=$(gopher-ctl probe get "$url") if [ -z "${response}" ] || echo "${response}" | grep -qi "failed" || [ "${response}" = "{}" ]; then diff --git a/src/common/args.h b/src/common/args.h index 8c5ef5c6..ab20a8b2 100644 --- a/src/common/args.h +++ b/src/common/args.h @@ -14,7 +14,7 @@ ******************************************************************************/ #ifndef __GOPHER_ARGS_H__ #define __GOPHER_ARGS_H__ - +#include "../lib/base.h" #pragma once #define DEFAULT_PERIOD 60 diff --git a/src/common/ipc.c b/src/common/ipc.c index 9241a076..9ca2efc0 100644 --- a/src/common/ipc.c +++ b/src/common/ipc.c @@ -28,7 +28,8 @@ enum ipct_type_e { IPCT_PROBE_RANGE = 100, IPCT_PROBE_PARAMS = 101, - IPCT_SNOOPER_NUM = 102 + IPCT_SNOOPER_NUM = 102, + IPCT_CUSTOM_MSG = 103 }; enum ipct_subtype_e { @@ -352,13 +353,17 @@ static struct ipc_operator_s ipc_operators[SNOOPER_OBJ_MAX] = { {SNOOPER_OBJ_CON, get_tlv_len_container, build_tlv_container, deserialize_tlv_container} }; -static u32 __calc_ipc_msg_len(struct ipc_body_s* ipc_body) +static u32 __calc_ipc_msg_len(struct ipc_body_s* ipc_body, struct custom_ipc *custom_ipc_body) { u32 msg_len = IPC_TLV_LEN_DEFAULT; for (int i = 0; i < ipc_body->snooper_obj_num && i < SNOOPER_MAX; i++) { msg_len += ipc_operators[ipc_body->snooper_objs[i].type].get_tlv_len(&(ipc_body->snooper_objs[i])); } + + if (custom_ipc_body != NULL) { + msg_len += sizeof(struct custom_ipc) + sizeof(struct ipc_tlv_s); + } return msg_len; } @@ -421,7 +426,19 @@ static int __build_snooper_tlv(char *buf, size_t size, struct ipc_body_s* ipc_bo return fill_len; } -static int __build_ipc_msg(char *buf, size_t size, struct ipc_body_s* ipc_body) +static int __build_custom_tlv(char *buf, size_t size, struct custom_ipc *custom_ipc_msg) +{ + struct custom_ipc *value; + struct ipc_tlv_s *tlv = (struct ipc_tlv_s *)buf; + + tlv->type = IPCT_CUSTOM_MSG; + tlv->len = sizeof(struct custom_ipc); + value = (struct custom_ipc *)(buf + sizeof(struct ipc_tlv_s)); + (void)memcpy(value, custom_ipc_msg, sizeof(struct custom_ipc)); + return (sizeof(struct ipc_tlv_s) + sizeof(struct custom_ipc)); +} + +static int __build_ipc_msg(char *buf, size_t size, struct ipc_body_s* ipc_body, struct custom_ipc *custom_ipc_msg) { int fill_len = 0, build_len = 0; int max_len = (int)size; @@ -451,6 +468,16 @@ static int __build_ipc_msg(char *buf, size_t size, struct ipc_body_s* ipc_body) cur += build_len; fill_len += build_len; + if (custom_ipc_msg != NULL) { + build_len = __build_custom_tlv(cur, (size_t)max_len, custom_ipc_msg); + max_len = max_len - build_len; + if (max_len < 0) { + return -1; + } + cur += build_len; + fill_len += build_len; + } + build_len = __build_snooper_tlv(cur, (size_t)max_len, ipc_body); if (build_len < 0) { return -1; @@ -467,12 +494,12 @@ static void __free_ipc_msg(struct ipc_msg_s* ipc_msg) (void)free(ipc_msg); } -static struct ipc_msg_s* __malloc_ipc_msg(struct ipc_body_s* ipc_body, long msg_type) +static struct ipc_msg_s* __malloc_ipc_msg(struct ipc_body_s* ipc_body, struct custom_ipc *custom_ipc_msg, long msg_type) { size_t size; struct ipc_msg_s* ipc_msg; - u32 msg_len = __calc_ipc_msg_len(ipc_body); + u32 msg_len = __calc_ipc_msg_len(ipc_body, custom_ipc_msg); size = sizeof(struct ipc_msg_s) + msg_len; ipc_msg = (struct ipc_msg_s *)malloc(size); @@ -486,11 +513,11 @@ static struct ipc_msg_s* __malloc_ipc_msg(struct ipc_body_s* ipc_body, long msg_ return ipc_msg; } -static struct ipc_msg_s* __create_ipc_msg(struct ipc_body_s* ipc_body, long msg_type) +static struct ipc_msg_s* __create_ipc_msg(struct ipc_body_s* ipc_body, struct custom_ipc *custom_ipc_msg, long msg_type) { int ret; char *buf; - struct ipc_msg_s* ipc_msg = __malloc_ipc_msg(ipc_body, msg_type); + struct ipc_msg_s* ipc_msg = __malloc_ipc_msg(ipc_body, custom_ipc_msg, msg_type); if (ipc_msg == NULL) { return NULL; } @@ -498,7 +525,7 @@ static struct ipc_msg_s* __create_ipc_msg(struct ipc_body_s* ipc_body, long msg_ ipc_msg->msg_flag = ipc_body->probe_flags; buf = (char *)(ipc_msg->msg); - ret = __build_ipc_msg(buf, ipc_msg->msg_len, ipc_body); + ret = __build_ipc_msg(buf, ipc_msg->msg_len, ipc_body, custom_ipc_msg); if (ret) { __free_ipc_msg(ipc_msg); return NULL; @@ -562,6 +589,18 @@ static int __deserialize_snooper_num_tlv(char *buf, size_t size, struct ipc_body return (tlv->len + sizeof(struct ipc_tlv_s)); } +static int __deserialize_custom_tlv(char *buf, size_t size, struct custom_ipc *custom_ipc_msg) +{ + struct ipc_tlv_s *tlv = (struct ipc_tlv_s *)buf; + + if ((tlv->type != IPCT_CUSTOM_MSG) || (tlv->len != sizeof(struct custom_ipc))) { + return -1; + } + + (void)memcpy(custom_ipc_msg, tlv->value, sizeof(struct custom_ipc)); + return (tlv->len + sizeof(struct ipc_tlv_s)); +} + static int __deserialize_snooper_tlv(char *buf, size_t size, struct ipc_body_s* ipc_body) { int max_len = (int)size, offset_len = 0, deserialize_len = 0; @@ -598,7 +637,7 @@ static int __deserialize_snooper_tlv(char *buf, size_t size, struct ipc_body_s* return (size_t)offset_len; } -static int __deserialize_ipc_msg(struct ipc_msg_s* ipc_msg, struct ipc_body_s* ipc_body) +static int __deserialize_ipc_msg(struct ipc_msg_s* ipc_msg, struct ipc_body_s* ipc_body, struct custom_ipc *custom_ipc_msg) { char *cur, *start; int max_len = ipc_msg->msg_len, offset = 0, deserialize_len = 0; @@ -638,6 +677,19 @@ static int __deserialize_ipc_msg(struct ipc_msg_s* ipc_msg, struct ipc_body_s* i return -1; } + if (custom_ipc_msg != NULL) { + cur = start + offset; + deserialize_len = __deserialize_custom_tlv(cur, (size_t)max_len, custom_ipc_msg); + if (deserialize_len < 0) { + return -1; + } + offset += deserialize_len; + max_len -= deserialize_len; + if (max_len < 0) { + return -1; + } + } + if (max_len == 0) { return offset; } @@ -708,11 +760,11 @@ int send_ipc_msg(int msqid, long msg_type, struct ipc_body_s* ipc_body) return -1; } - if (msg_type < PROBE_BASEINFO || msg_type >= PROBE_TYPE_MAX) { + if (msg_type < PROBE_BASEINFO || msg_type == PROBE_TYPE_MAX || msg_type > (MAX_CUSTOM_NUM + PROBE_CUSTOM_IPC)) { return -1; } - ipc_msg = __create_ipc_msg(ipc_body, msg_type); + ipc_msg = __create_ipc_msg(ipc_body, NULL, msg_type); if (ipc_msg == NULL) { return -1; } @@ -728,6 +780,35 @@ int send_ipc_msg(int msqid, long msg_type, struct ipc_body_s* ipc_body) return err; } +int send_custom_ipc_msg(int msqid, long msg_type, struct ipc_body_s* ipc_body, struct custom_ipc *custom_ipc_msg) +{ + int err = 0; + struct ipc_msg_s* ipc_msg; + + if (msqid < 0) { + return -1; + } + + if (msg_type > (MAX_CUSTOM_NUM + PROBE_CUSTOM_IPC)) { + return -1; + } + + ipc_msg = __create_ipc_msg(ipc_body, custom_ipc_msg, msg_type); + if (ipc_msg == NULL) { + return -1; + } + + if (msgsnd(msqid, ipc_msg, ipc_msg->msg_len + sizeof(ipc_msg->msg_len) + sizeof(ipc_msg->msg_flag), 0) < 0) { + ERROR("[IPC] send ipc message(msg_type = %ld) failed(%d).\n", msg_type, errno); + err = -1; + } + + __free_ipc_msg(ipc_msg); + ipc_msg = NULL; + + return err; +} + /* return 0 when ipc msg recvd and build a valid ipc_body */ int recv_ipc_msg(int msqid, long msg_type, struct ipc_body_s *ipc_body) { @@ -756,7 +837,7 @@ int recv_ipc_msg(int msqid, long msg_type, struct ipc_body_s *ipc_body) goto end; } (void)memset(ipc_body, 0, sizeof(struct ipc_body_s)); - deserialize_len = __deserialize_ipc_msg(ipc_msg, ipc_body); + deserialize_len = __deserialize_ipc_msg(ipc_msg, ipc_body, NULL); if (deserialize_len < 0) { ERROR("[IPC] recv ipc message(msg_type = %d) deserialize failed.\n", msg_type); goto end; @@ -772,6 +853,50 @@ end: return err; } +int recv_custom_ipc_msg(int msqid, long msg_type, struct ipc_body_s *ipc_body, struct custom_ipc *custom_ipc_msg) +{ + int err = -1; + int deserialize_len; + struct ipc_msg_s* ipc_msg; + int msg_rcvd = 0; + u32 msg_len; + u32 msg_flags = 0; + + if (msqid < 0) { + return -1; + } + + ipc_msg = __get_raw_ipc_msg(msg_type); + msg_len = ipc_msg->msg_len + sizeof(ipc_msg->msg_len) + sizeof(ipc_msg->msg_flag); + /* Only deal with the last message within every check */ + while (msgrcv(msqid, ipc_msg, msg_len, msg_type, IPC_NOWAIT) != -1) { + msg_rcvd = 1; + msg_flags |= ipc_msg->msg_flag; + } + + if (msg_rcvd) { + if (ipc_msg->msg_len > __GOPHER_IPC_MSG_LEN) { + ERROR("[IPC] recv ipc message(msg_type = %d) invalid len.\n", msg_type); + goto end; + } + (void)memset(ipc_body, 0, sizeof(struct ipc_body_s)); + (void)memset(custom_ipc_msg, 0, sizeof(struct custom_ipc)); + deserialize_len = __deserialize_ipc_msg(ipc_msg, ipc_body, custom_ipc_msg); + if (deserialize_len < 0) { + ERROR("[CUSTOM IPC] recv ipc message(msg_type = %d) deserialize failed.\n", msg_type); + goto end; + } + ipc_body->probe_flags = msg_flags; + err = 0; + } + +end: + if ((err != 0) && (msg_rcvd != 0)) { + destroy_ipc_body(ipc_body); + } + return err; +} + void clear_ipc_msg(long msg_type) { int msqid; diff --git a/src/common/ipc.h b/src/common/ipc.h index e945faf4..a93fbd44 100644 --- a/src/common/ipc.h +++ b/src/common/ipc.h @@ -211,10 +211,11 @@ enum probe_type_e { PROBE_FLOWTRACER, // If you want to add a probe, add the probe type. - + PROBE_CUSTOM, PROBE_TYPE_MAX }; +#define PROBE_CUSTOM_IPC 100 enum snooper_obj_e { SNOOPER_OBJ_PROC = 0, SNOOPER_OBJ_CON, @@ -238,6 +239,18 @@ struct snooper_obj_s { } obj; }; +struct custom_params { + char label[MAX_CUSTOM_PARAMS_LEN]; + char value[MAX_CUSTOM_PARAMS_LEN]; +}; + +struct custom_ipc { + char subprobe[MAX_SUBPEOBE_NUM][MAX_CUSTOM_NAME_LEN]; + unsigned int subprobe_num; + struct custom_params custom_param[MAX_CUSTOM_NUM]; + unsigned int params_num; +}; + #define IPC_FLAGS_SNOOPER_CHG 0x00000001 #define IPC_FLAGS_PARAMS_CHG 0x00000002 struct ipc_body_s { @@ -251,8 +264,10 @@ struct ipc_body_s { int create_ipc_msg_queue(unsigned int ipc_flag); void destroy_ipc_msg_queue(int msqid); int send_ipc_msg(int msqid, long msg_type, struct ipc_body_s *ipc_body); +int send_custom_ipc_msg(int msqid, long msg_type, struct ipc_body_s* ipc_body, struct custom_ipc *custom_ipc_msg); int recv_ipc_msg(int msqid, long msg_type, struct ipc_body_s *ipc_body); void clear_ipc_msg(long msg_type); void destroy_ipc_body(struct ipc_body_s *ipc_body); char is_load_probe_ipc(struct ipc_body_s *ipc_body, u32 probe_range_flag); +int recv_custom_ipc_msg(int msqid, long msg_type, struct ipc_body_s *ipc_body, struct custom_ipc *custom_ipc_msg); #endif diff --git a/src/common/json_tool.cpp b/src/common/json_tool.cpp index d5cf52fe..92640e34 100644 --- a/src/common/json_tool.cpp +++ b/src/common/json_tool.cpp @@ -53,6 +53,16 @@ unsigned char Json_IsString(const void *jsonObj) return ret; } +unsigned char Json_IsBool(const void *jsonObj) +{ + if (!jsonObj) { + return 0; + } + auto *jsObj = static_cast(jsonObj); + bool ret = jsObj->isBool(); + return ret; +} + unsigned char Json_IsNumeric(const void *jsonObj) { if (!jsonObj) { @@ -128,6 +138,12 @@ const char *Json_GetValueString(const void *jsonObj) } } +bool Json_GetValueBool(const void *jsonObj) +{ + auto *jsObj = static_cast(jsonObj); + return jsObj->asBool(); +} + struct key_value_pairs* Json_GetKeyValuePairs(const void *jsonObj) { if (!jsonObj) { @@ -148,6 +164,10 @@ struct key_value_pairs* Json_GetKeyValuePairs(const void *jsonObj) for (Json::ValueConstIterator it = jsObj.begin(); it != jsObj.end(); ++it) { auto& kv = kv_pairs->kv_pairs[kv_pairs->len]; kv.key = strdup(it.name().c_str()); + if (!kv.key) { + Json_DeleteKeyValuePairs(kv_pairs); + return nullptr; + } kv.valuePtr = (void *)(&(*it)); ++kv_pairs->len; } diff --git a/src/common/json_tool.h b/src/common/json_tool.h index 73f10a9f..4c6e1178 100644 --- a/src/common/json_tool.h +++ b/src/common/json_tool.h @@ -22,6 +22,7 @@ extern "C" { #endif +#include #include "limits.h" #define INVALID_INT_NUM (-INT_MAX) @@ -69,6 +70,7 @@ unsigned char Json_IsString(const void *jsonObj); unsigned char Json_IsNumeric(const void *jsonObj); unsigned char Json_IsObject(const void *jsonObj); unsigned char Json_IsArray(const void *jsonObj); +unsigned char Json_IsBool(const void *jsonObj); /*** * brief return Number, Array, String, Other. @@ -77,6 +79,7 @@ int Json_GetType(const void *jsonObj); /* get value */ int Json_GetValueInt(const void *jsonObj); +bool Json_GetValueBool(const void *jsonObj); /*** * write json data relative diff --git a/src/lib/base.h b/src/lib/base.h index fcf56e63..ca107f53 100644 --- a/src/lib/base.h +++ b/src/lib/base.h @@ -60,6 +60,17 @@ // probe config #define MAX_PROBE_NAME_LEN 32 +// custom config +#define MAX_CUSTOM_NAME_LEN 64 +#define MAX_BIN_LEN 100 +#define MAX_SUBPEOBE_NUM 8 +#define MAX_CUSTOM_NUM (8 + 1) //The subscript of custom starts from 1. +#define MAX_CUSTOM_PARAMS_LEN 64 +#define MAX_CUSTOM_PARAMS_NUM 8 +#define MAX_PRIVILEGE_LEN 8 +#define MAX_CUSTOM_CONFIG (2048 * 2048 * 10) +#define MAX_RESTART_TIMES 10 + // extend probe config #define MAX_EXTEND_PROBE_COMMAND_LEN 128 #define MAX_PARAM_LEN 128 @@ -99,6 +110,8 @@ typedef enum { #define GALA_GOPHER_RUN_DIR "/var/run/gala_gopher/" #define GALA_GOPHER_CMD_SOCK_PATH "/var/run/gala_gopher/gala_gopher_cmd.sock" #define GALA_GOPHER_RUN_DIR_MODE 0750 +/* custom probe json path */ +#define GALA_GOPHER_CUSTOM_PATH "/etc/gala-gopher/gala-gopher-custom.json" #endif diff --git a/src/lib/meta/meta.c b/src/lib/meta/meta.c index 30de877f..c332843a 100644 --- a/src/lib/meta/meta.c +++ b/src/lib/meta/meta.c @@ -21,6 +21,8 @@ #include #include "logs.h" #include "meta.h" +#include "json_tool.h" +#include "probe_mng.h" #if GALA_GOPHER_INFO("inner func") static Measurement *MeasurementCreate(void); @@ -248,13 +250,25 @@ int MeasurementMgrLoadSingleMeta(MeasurementMgr *mgr, const char *metaPath) return 0; } -int MeasurementMgrLoad(const MeasurementMgr *mgr, const char *metaDir) +static int get_custom_meta_from_bin(char *meta, size_t meta_path_len, char *bin) +{ + char *ptr = strrchr(bin, '.'); + + if (ptr != NULL) { + *ptr = '\0'; + (void)snprintf(meta, meta_path_len, "%s%s", bin, ".meta"); + return 0; + } + return -1; +} + +static int get_meta_from_dir(const MeasurementMgr *mgr, const char *metaDir) { int ret = 0; DIR *d = NULL; + d = opendir(metaDir); char metaPath[MAX_META_PATH_LEN] = {0}; - d = opendir(metaDir); if (d == NULL) { ERROR("open meta directory failed.\n"); return -1; @@ -267,6 +281,10 @@ int MeasurementMgrLoad(const MeasurementMgr *mgr, const char *metaDir) file = readdir(d); continue; } + if (strstr(file->d_name, ".meta") == NULL) { + file = readdir(d); + continue; + } memset(metaPath, 0, sizeof(metaPath)); (void)snprintf(metaPath, MAX_META_PATH_LEN - 1, "%s/%s", metaDir, file->d_name); @@ -284,6 +302,85 @@ int MeasurementMgrLoad(const MeasurementMgr *mgr, const char *metaDir) return 0; } +static int get_custom_meta(const MeasurementMgr *mgr) +{ + char *json_data; + int ret; + void *json_obj = NULL; + struct key_value_pairs *kv_pairs = NULL; + struct key_value *kv; + char meta_path[MAX_META_PATH_LEN] = {0}; + char probe_path[MAX_META_PATH_LEN] = {0}; + + json_data = calloc(1, MAX_CUSTOM_CONFIG + 1); + if (json_data == NULL) { + ERROR("[CUSTOM META]Custom memory allocation error\r\n"); + return -1; + } + + ret = file_handle(GALA_GOPHER_CUSTOM_PATH, json_data, MAX_CUSTOM_CONFIG + 1); + if (ret) { + ERROR("[CUSTOM META]The file cannot be opened.\n"); + free(json_data); + return -1; + } + + json_obj = Json_Parse(json_data); + if (json_obj == NULL) { + free(json_data); + ERROR("[CUSTOM META]invalid json format.\r\n"); + return -1; + } + + kv_pairs = Json_GetKeyValuePairs(json_obj); + if (!kv_pairs) { + free(json_data); + Json_Delete(json_obj); + ERROR("[CUSTOM META]invalid json param pairs.\r\n"); + return -1; + } + + Json_ArrayForEach(kv, kv_pairs) { + snprintf(probe_path, sizeof(probe_path), "%s", probe_extern_cmd_param("bin", kv->valuePtr)); + if (get_custom_meta_from_bin(meta_path, sizeof(meta_path) - 1, probe_path)) { + (void)snprintf(meta_path, sizeof(meta_path) - 1, "%s%s", probe_path, ".meta"); + } + INFO("custom meta path is %s.\n", meta_path); + ret = MeasurementMgrLoadSingleMeta((MeasurementMgr *)mgr, meta_path); + if (ret != 0) { + ERROR("[META] load single meta file failed. meta file: %s.Check whether the file exists.\n", meta_path); + Json_DeleteKeyValuePairs(kv_pairs); + Json_Delete(json_obj); + free(json_data); + return -1; + } + } + + Json_DeleteKeyValuePairs(kv_pairs); + Json_Delete(json_obj); + free(json_data); + return 0; +} + +int MeasurementMgrLoad(const MeasurementMgr *mgr, const char *metaDir) +{ + int ret = 0; + /* Internal probe */ + ret = get_meta_from_dir(mgr, metaDir); + if (ret) { + return -1; + } + if (is_file_exit(GALA_GOPHER_CUSTOM_PATH)) { + return 0; + } + /* Custom probe */ + ret = get_custom_meta(mgr); + if (ret) { + return -1; + } + return 0; +} + #if GALA_GOPHER_INFO("report_meta_to_kafka func") static int metadata_build_timestamp(char *json_str, int max_len) { diff --git a/src/lib/meta/meta.h b/src/lib/meta/meta.h index ac7e300f..aa24e42b 100644 --- a/src/lib/meta/meta.h +++ b/src/lib/meta/meta.h @@ -21,6 +21,7 @@ #include "base.h" #ifdef KAFKA_CHANNEL #include "kafka.h" +#include "probe_mng.h" #endif #define META_FIELD_TYPE_KEY "key" diff --git a/src/lib/probe/extend_probe.c b/src/lib/probe/extend_probe.c index a51832b6..a67d03fc 100644 --- a/src/lib/probe/extend_probe.c +++ b/src/lib/probe/extend_probe.c @@ -162,7 +162,7 @@ retry: parseExtendProbeOutput(probe, f); out: - clear_ipc_msg((long)probe->probe_type); + clear_ipc_msg((long)(probe->probe_type == PROBE_CUSTOM) ? (PROBE_CUSTOM_IPC + probe->custom.index) : probe->probe_type); if (f) { pclose(f); } diff --git a/src/lib/probe/probe_mng.c b/src/lib/probe/probe_mng.c index 24027ce9..de6e2e83 100644 --- a/src/lib/probe/probe_mng.c +++ b/src/lib/probe/probe_mng.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include "ipc.h" #include "pod_mng.h" @@ -35,7 +37,7 @@ #include "json_tool.h" #include "probe_mng.h" -static void init_probe_bin(struct probe_s *probe, enum probe_type_e probe_type); +static int init_probe_bin(struct probe_s *probe, enum probe_type_e probe_type); struct probe_define_s probe_define[] = { {"baseinfo", "system_infos", PROBE_BASEINFO, SNOOPER_TYPE_ALL, ENABLE_BASEINFO}, @@ -62,6 +64,13 @@ struct probe_define_s probe_define[] = { // If you want to add a probe, add the probe define. }; +struct probe_threshold_verify verify[] = { + {"name", MAX_CUSTOM_NAME_LEN}, + {"bin", MAX_BIN_LEN}, + {"probe_num", MAX_SUBPEOBE_NUM}, + {"param", MAX_CUSTOM_PARAMS_LEN} +}; + struct probe_range_define_s { enum probe_type_e probe_type; char *desc; @@ -195,6 +204,36 @@ static int check_probe_range(struct probe_s *probe) return 0; } +static int check_duplicate(const char str[][MAX_CUSTOM_NAME_LEN], const unsigned int n) { + for (size_t i = 0; i < n; i++) { + for (size_t j = i + 1; j < n; j++) { + if (strcmp(str[i], str[j]) == 0) { + return -1; + } + } + } + return 0; +} + + +int check_custom_range(const char *key, const char *comp) +{ + if (key == NULL || comp == NULL) { + return -1; + } + + int size = sizeof(verify) / sizeof(struct probe_threshold_verify); + for (int i = 0; i < size; i++) { + if (strcmp(verify[i].name, comp) != 0) { + continue; + } + if (strlen(key) == 0 || strlen(key) > verify[i].max) { + return -1; + } + } + return 0; +} + static int check_probe_snooper_conf_num(struct probe_s *probe) { if (probe->snooper_conf_num == 0 && (!strcmp(probe->name, "tcp") || @@ -206,6 +245,7 @@ static int check_probe_snooper_conf_num(struct probe_s *probe) } static struct probe_mng_s *g_probe_mng; +static struct custom_ini *g_custom_ini; char g_parse_json_err[PARSE_JSON_ERR_STR_LEN]; @@ -292,6 +332,10 @@ static int attach_probe_fd(struct probe_mng_s *probe_mng, struct probe_s *probe) static void detach_probe_fd(struct probe_mng_s *probe_mng, struct probe_s *probe) { struct epoll_event event; + if (probe_mng == NULL || probe == NULL) { + return; + } + if (probe_mng->ingress_epoll_fd < 0 || probe->fifo == NULL) { return; } @@ -359,6 +403,9 @@ static struct probe_s* new_probe(const char* name, enum probe_type_e probe_type) memset(probe, 0, sizeof(struct probe_s)); probe->name = strdup(name); + if (probe->name == NULL) { + goto err; + } ret = pthread_rwlock_init(&probe->rwlock, NULL); if (ret) { @@ -376,7 +423,10 @@ 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; - init_probe_bin(probe, probe_type); + ret = init_probe_bin(probe, probe_type); + if (ret) { + goto err; + } set_default_params(probe); ret = attach_probe_fd(g_probe_mng, probe); @@ -439,13 +489,20 @@ end: return ret; } -static void init_probe_bin(struct probe_s *probe, enum probe_type_e probe_type) +static int init_probe_bin(struct probe_s *probe, enum probe_type_e probe_type) { if (probe_type >= PROBE_TYPE_MAX) { - return; + return -1; } - probe->bin = strdup(probe_define[probe_type - 1].bin); + if (probe_type != PROBE_CUSTOM) { + probe->bin = strdup(probe_define[probe_type - 1].bin); + } else { + probe->bin = strdup("/extern"); + } + if (probe->bin == NULL) { + return -1; + } if (is_extend_probe(probe)) { probe->is_extend_probe = 1; @@ -453,13 +510,12 @@ static void init_probe_bin(struct probe_s *probe, enum probe_type_e probe_type) } else { int ret = set_probe_entry(probe); if (ret) { - return; + return -1; } probe->is_extend_probe = 0; probe->cb = native_probe_thread_cb; } - - return; + return 0; } static int get_probe_pid(struct probe_s *probe) @@ -509,10 +565,12 @@ static int try_start_probe(struct probe_s *probe) int ret; if (IS_RUNNING_PROBE(probe)) { + probe->resnd_snooper_for_restart = 0; return 0; } if (!IS_STARTED_PROBE(probe)) { + probe->resnd_snooper_for_restart = 0; return 0; } @@ -539,7 +597,7 @@ static int try_start_probe(struct probe_s *probe) probe->probe_status.status_flags |= PROBE_FLAGS_RUNNING; probe->probe_status.status_flags &= ~(PROBE_FLAGS_STOPPED); (void)pthread_rwlock_unlock(&probe->rwlock); - probe->resnd_snooper_for_restart = 1; // must be reset when start ends + probe->resnd_snooper_for_restart += 1; // must be reset when start ends return 0; } @@ -594,7 +652,7 @@ static int stop_probe(struct probe_s *probe) if (IS_NATIVE_PROBE(probe)) { set_probe_status_stopped(probe); - clear_ipc_msg((long)probe->probe_type); + clear_ipc_msg((long)(probe->probe_type == PROBE_CUSTOM) ? (PROBE_CUSTOM_IPC + probe->custom.index) : probe->probe_type); } else { if (kill_extend_probe(probe)) { return -1; @@ -624,17 +682,85 @@ static enum probe_type_e get_probe_type_by_name(const char *probe_name) return probe_define[i].type; } } - PARSE_ERR("invalid probe name"); + + if (g_custom_ini) { + for (size_t i = 1; i <= g_custom_ini->custom_num; i++) { + if (!strcmp(g_custom_ini->custom[i]->name, probe_name)) { + return PROBE_CUSTOM; + } + } + } + + PARSE_ERR("invalid probe name %s", probe_name); return PROBE_TYPE_MAX; } +/* Pass the parameters of the init custom probe record to the currently probe. */ +static int information_transfer(struct probe_s *custom, struct probe_s *probe) +{ + char *bin; + unsigned int size; + + /* Transfer the bin, privilege, subprobe, params information in the JSON file. */ + bin = probe->bin; + probe->bin = strdup(custom->bin); + if (bin != NULL) { + free(bin); + bin = NULL; + } + + probe->custom.privilege = custom->custom.privilege; + + size = custom->custom.custom_ipc_msg.params_num; + for (int i = 0; i < size; i++) { + snprintf(probe->custom.custom_ipc_msg.custom_param[i].label, MAX_CUSTOM_PARAMS_LEN, + "%s", custom->custom.custom_ipc_msg.custom_param[i].label); + } + probe->custom.custom_ipc_msg.params_num = size; + probe->custom.index = custom->custom.index; + + return 0; +} + +static int find_custom_ini(struct probe_s *probe) { + u32 num = g_custom_ini->custom_num; + int ret; + + for (int i = 0; i <= num; i++) { + if ((g_custom_ini->custom[i] != NULL) && (strcmp(g_custom_ini->custom[i]->name, probe->name)) == 0) { + ret = information_transfer(g_custom_ini->custom[i], probe); + return ret; + } + } + return -1; +} + static struct probe_s *get_probe_by_name(const char *probe_name) { enum probe_type_e probe_type = get_probe_type_by_name(probe_name); + u32 custom_index = g_probe_mng->custom_index; + if (probe_type >= PROBE_TYPE_MAX) { return NULL; } + if (probe_type == PROBE_CUSTOM) { + for (size_t i = 1; i <= custom_index; i++) { + if (strcmp(probe_name, g_probe_mng->custom[i]->name) == 0) { + return g_probe_mng->custom[i]; + } + } + custom_index++; + if (custom_index >= MAX_CUSTOM_NUM) { + PARSE_ERR("The number of external probes has over the threshold."); + return NULL; + } + g_probe_mng->custom[custom_index] = new_probe(probe_name, PROBE_CUSTOM); + if (g_probe_mng->custom[custom_index] != NULL && !find_custom_ini(g_probe_mng->custom[custom_index])) { + g_probe_mng->custom_index = custom_index; + } + return g_probe_mng->custom[custom_index]; + } if (g_probe_mng->probes[probe_type]) { return g_probe_mng->probes[probe_type]; } @@ -647,14 +773,25 @@ static void probe_printer_cmd(struct probe_s *probe, void *json) { void *range; Json_AddStringToObject(json, "bin", probe->bin ? :""); - - size_t size = sizeof(probe_range_define) / sizeof(struct probe_range_define_s); + size_t size = 0; range = Json_CreateArray(); - for (size_t i = 0; i < size; i++) { - if (probe->probe_type == probe_range_define[i].probe_type) { - if (probe->probe_range_flags & probe_range_define[i].flags) { - Json_AddStringItemToArray(range, probe_range_define[i].desc); + if (probe->probe_type == PROBE_CUSTOM) { + size = probe->custom.custom_ipc_msg.subprobe_num; + + for (size_t i = 0; i < size; i++) { + if (probe->custom.custom_ipc_msg.subprobe[i] != NULL) { + Json_AddStringItemToArray(range, probe->custom.custom_ipc_msg.subprobe[i]); + } + } + } else { + size = sizeof(probe_range_define) / sizeof(struct probe_range_define_s); + + for (size_t i = 0; i < size; i++) { + if (probe->probe_type == probe_range_define[i].probe_type) { + if (probe->probe_range_flags & probe_range_define[i].flags) { + Json_AddStringItemToArray(range, probe_range_define[i].desc); + } } } } @@ -662,45 +799,239 @@ static void probe_printer_cmd(struct probe_s *probe, void *json) Json_Delete(range); } +static int custom_subprobe_parser(struct probe_s *probe, const char *subprobe) +{ + unsigned int subsize; + size_t index; + + if (subprobe == NULL) { + return -1; + } + + subsize = g_custom_ini->custom[probe->custom.index]->custom.custom_ipc_msg.subprobe_num; + for (index = 0; index < subsize; index++) { + if (strcmp(subprobe, g_custom_ini->custom[probe->custom.index]->custom.custom_ipc_msg.subprobe[index]) == 0) { + break; + } + } + if (index == subsize) { + ERROR("[Custom]invalid external probe range: subprobe name error,name is %s.\n", subprobe); + return -1; + } + snprintf(probe->custom.custom_ipc_msg.subprobe[probe->custom.custom_ipc_msg.subprobe_num], + MAX_CUSTOM_NAME_LEN, "%s", subprobe); + (probe->custom.custom_ipc_msg.subprobe_num)++; + return 0; +} /* {"probe":["XX","YY"]} , XX must be string and must be in supported probe range*/ static int probe_parser_range(struct probe_s *probe, void *probe_item) { - int range; + int range = 0; void *object; + unsigned int subnum_bak = 0; + char subprobe_bak[MAX_SUBPEOBE_NUM][MAX_CUSTOM_NAME_LEN] = {0}; + int ret = 0; + if (probe->probe_type == PROBE_CUSTOM) { + for (int j = 0; j < probe->custom.custom_ipc_msg.subprobe_num; j++) { + snprintf(subprobe_bak[j], MAX_CUSTOM_NAME_LEN, "%s", probe->custom.custom_ipc_msg.subprobe[j]); + } + subnum_bak = probe->custom.custom_ipc_msg.subprobe_num; + memset(probe->custom.custom_ipc_msg.subprobe, 0, sizeof(char) * MAX_SUBPEOBE_NUM * MAX_CUSTOM_NAME_LEN); + probe->custom.custom_ipc_msg.subprobe_num = 0; + } probe->probe_range_flags = 0; size_t size = Json_GetArraySize(probe_item); for (size_t i = 0; i < size; i++) { object = Json_GetArrayItem(probe_item, i); if (!Json_IsString(object)) { - PARSE_ERR("invalid probe range: must be string"); + ERROR("Invalid probe range: must be string.\n"); return -1; } - - range = get_probe_range(probe->probe_type, (const char*)Json_GetValueString(object)); - if (!range) { - PARSE_ERR("unsupported probe range: %s", (const char*)Json_GetValueString(object)); + if (check_custom_range((char *)Json_GetValueString(object), "name")) { + ERROR("The lengh of probe name must range from 0 to %d.\n", MAX_CUSTOM_NAME_LEN); return -1; } + + if (probe->probe_type == PROBE_CUSTOM) { + ret = custom_subprobe_parser(probe, (const char*)Json_GetValueString(object)); + if (ret) { + for (int j = 0; j < subnum_bak; j++) { + memset(probe->custom.custom_ipc_msg.subprobe[j], 0, sizeof(char) * MAX_CUSTOM_NAME_LEN); + snprintf(probe->custom.custom_ipc_msg.subprobe[j], MAX_CUSTOM_NAME_LEN, "%s", subprobe_bak[j]); + } + probe->custom.custom_ipc_msg.subprobe_num = subnum_bak; + return -1; + } + } else { + range = get_probe_range(probe->probe_type, (const char*)Json_GetValueString(object)); + if (!range) { + ERROR("unsupported probe range: %s.\n", (const char*)Json_GetValueString(object)); + return -1; + } + } probe->probe_range_flags |= (u32)range; } return check_probe_range(probe); } +char *probe_extern_cmd_param(const char *key, const void *item) +{ + void *probe_object; + + probe_object = Json_GetObjectItem(item, key); + if (probe_object == NULL && !Json_IsString(probe_object)) { + PARSE_ERR("invalid probe range: must be string and not null.\n"); + return NULL; + } + return (char *)Json_GetValueString(probe_object); +} + +static int custom_params_ini(struct probe_s *probe, char *param) { + char *ptr = NULL; + int count = 0; + + if (param == NULL) { + return -1; + } + ptr = strtok(param, ","); + while (ptr != NULL) { + if (count == MAX_CUSTOM_PARAMS_NUM) { + ERROR("[CUSTOM INI]The number of custom params must less than MAX_CUSTOM_PARAMS_NUM.\n"); + return -1; + } + if (check_custom_range(ptr, "param")) { + ERROR("[CUSTOM INI]The length of custom params must range from 0 to %d.\n", MAX_CUSTOM_PARAMS_LEN); + return -1; + } + if (strlen(ptr) == 0) { + ERROR("[CUSTOM INI]The string must contain non-space characters."); + return -1; + } + for (size_t i = 0; i < count; ++i) { + if (strcmp(ptr, probe->custom.custom_ipc_msg.custom_param[i].label) == 0) { + ERROR("[CUSTOM INI] Duplicate parameter names are not allowed."); + return -1; + } + } + snprintf(probe->custom.custom_ipc_msg.custom_param[count].label, MAX_CUSTOM_PARAMS_LEN, "%s", ptr); + INFO("The NO.%d param is %s.\n", count, ptr); + count++; + ptr = strtok(NULL, ","); + } + probe->custom.custom_ipc_msg.params_num = count; + return 0; +} + static int probe_parser_cmd(struct probe_s *probe, const void *item) { int ret = 0; void *probe_object; + char *bin; probe_object = Json_GetObjectItem(item, "probe"); - if (probe_object != NULL) { - ret = probe_parser_range(probe, probe_object); + if (probe_object == NULL) { + ERROR("[Custom ini]:Faild get probe params from json.\n"); + return -1; + } + ret = probe_parser_range(probe, probe_object); + if (ret) { + PARSE_ERR("invalid range type."); + return ret; + } + + /* Custom probe dedicated, there are tow scenarios.*/ + if (probe->probe_type == PROBE_CUSTOM) { + bin = probe_extern_cmd_param("bin", item); + if (bin == NULL || strcmp(probe->bin, bin)) { + PARSE_ERR("invalid custom probe bin path"); + return -1; + } } return ret; } +static int custom_parser(struct probe_s *probe, const void *item) +{ + int ret = 0; + size_t size; + void *probe_object; + void *object; + char *type; + + probe_object = Json_GetObjectItem(item, "probe"); + if (probe_object == NULL) { + ERROR("[Custom ini]Invalid json format: please check probe value.\n"); + return -1; + } + + size = Json_GetArraySize(probe_object); + if (size > MAX_SUBPEOBE_NUM) { + ERROR("[Custom ini]The number of subprobe must less than MAX_SUBPEOBE_NUM.\n"); + return -1; + } + + for (size_t i = 0; i < size; i++) { + object = Json_GetArrayItem(probe_object, i); + if (!Json_IsString(object)) { + ERROR("[Custom ini]Invalid probe range: must be string.\n"); + return -1; + } + if (check_custom_range((char *)Json_GetValueString(object), "name")) { + ERROR("[Custom ini]The lengh of probe name must range from 0 to %d.\n", MAX_CUSTOM_NAME_LEN); + return -1; + } + + snprintf(probe->custom.custom_ipc_msg.subprobe[i], MAX_CUSTOM_NAME_LEN, "%s", (char *)Json_GetValueString(object)); + (probe->custom.custom_ipc_msg.subprobe_num)++; + } + + ret = check_duplicate(probe->custom.custom_ipc_msg.subprobe, probe->custom.custom_ipc_msg.subprobe_num); + if (ret) { + ERROR("[Custom ini] Duplicate subprobe names are not allowed.\n"); + return -1; + } + + type = probe_extern_cmd_param("bin", item); + if (type == NULL) { + ERROR("[Custom ini] Invalid json format: please check bin value.\n"); + return -1; + } + + if (check_path_for_security(type)) { + ERROR("[Custom ini] Custom probe bin contains insecure characters.\n"); + return -1; + } + + probe->bin = strdup(type); + if (probe->bin == NULL) { + ERROR("[Custom ini] Failed to strdup custom probe bin\n"); + return -1; + } + + if (check_custom_range(probe->bin, "bin")) { + ERROR("[Custom ini]:The length of bin must range from 0 to %d.\n", MAX_BIN_LEN); + return -1; + } + + probe->custom.privilege = false; + + type = probe_extern_cmd_param("custom_param", item); + if (type == NULL) { + ERROR("[Custom ini]Invalid json format: please check custom_param value.\n"); + return -1; + } + ret = custom_params_ini(probe, type); + if (ret) { + ERROR("[Custom ini]invalid json type, check custom params.\n"); + return -1; + } + + return 0; +} + static void probe_backup_cmd(struct probe_s *probe, struct probe_s *probe_backup) { probe_backup->bin = probe->bin ? strdup(probe->bin) : NULL; @@ -773,14 +1104,50 @@ static void print_params(struct probe_s *probe, void *json) probe_params_to_json(probe, json); } +static void custom_param_backup(struct custom *custom, struct custom *custom_backup) +{ + custom_backup->index = custom->index; + custom_backup->privilege = custom->privilege; + custom_backup->custom_ipc_msg.params_num = custom->custom_ipc_msg.params_num; + custom_backup->custom_ipc_msg.subprobe_num = custom->custom_ipc_msg.subprobe_num; + for (int i = 0; i < custom->custom_ipc_msg.subprobe_num; i++) { + snprintf(custom_backup->custom_ipc_msg.subprobe[i], MAX_CUSTOM_NAME_LEN, "%s", custom->custom_ipc_msg.subprobe[i]); + } + for (int i = 0; i < custom->custom_ipc_msg.params_num; i++) { + snprintf(custom_backup->custom_ipc_msg.custom_param[i].label, MAX_CUSTOM_PARAMS_LEN, "%s", custom->custom_ipc_msg.custom_param[i].label); + snprintf(custom_backup->custom_ipc_msg.custom_param[i].value, MAX_CUSTOM_PARAMS_LEN, "%s", custom->custom_ipc_msg.custom_param[i].value); + } +} + +static void custom_param_rollback(struct custom *custom, struct custom *custom_backup) +{ + custom->index = custom_backup->index; + custom->privilege = custom_backup->privilege; + custom->custom_ipc_msg.params_num = custom_backup->custom_ipc_msg.params_num; + custom->custom_ipc_msg.subprobe_num = custom_backup->custom_ipc_msg.subprobe_num; + for (int i = 0; i < custom->custom_ipc_msg.subprobe_num; i++) { + snprintf(custom->custom_ipc_msg.subprobe[i], MAX_CUSTOM_NAME_LEN, "%s", custom_backup->custom_ipc_msg.subprobe[i]); + } + for (int i = 0; i < custom->custom_ipc_msg.params_num; i++) { + snprintf(custom->custom_ipc_msg.custom_param[i].label, MAX_CUSTOM_PARAMS_LEN, "%s", custom_backup->custom_ipc_msg.custom_param[i].label); + snprintf(custom->custom_ipc_msg.custom_param[i].value, MAX_CUSTOM_PARAMS_LEN, "%s", custom_backup->custom_ipc_msg.custom_param[i].value); + } +} + static void probe_backup_params(struct probe_s *probe, struct probe_s *probe_backup) { memcpy(&probe_backup->probe_param, &probe->probe_param, sizeof(struct probe_params)); + if (probe->probe_type == PROBE_CUSTOM) { + custom_param_backup(&probe->custom, &probe_backup->custom); + } } static void probe_rollback_params(struct probe_s *probe, struct probe_s *probe_backup) { memcpy(&probe->probe_param, &probe_backup->probe_param, sizeof(struct probe_params)); + if (probe->probe_type == PROBE_CUSTOM) { + custom_param_rollback(&probe->custom, &probe_backup->custom); + } } typedef int (*probe_json_parser)(struct probe_s *, const void *); @@ -966,6 +1333,16 @@ static void set_probe_modify(struct probe_s *probe, struct probe_s *backup_probe return; } +static void probe_info_print(struct probe_s *probe) +{ + INFO("probe name = %s\n", probe->name); + INFO("probe bin = %s\n", probe->bin); + INFO("probe privilege = %s\n", (probe->custom.privilege == true ? "true" : "false")); + for (int i = 0; i < probe->custom.custom_ipc_msg.subprobe_num; i++) { + INFO("probe subprobe %d is %s\n", i, probe->custom.custom_ipc_msg.subprobe[i]); + } +} + int parse_probe_json(const char *probe_name, const char *probe_content) { int ret = -1; @@ -990,11 +1367,10 @@ int parse_probe_json(const char *probe_name, const char *probe_content) goto end; } - probe_backup = (struct probe_s *)malloc(sizeof(struct probe_s)); + probe_backup = (struct probe_s *)calloc(1, sizeof(struct probe_s)); if (probe_backup == NULL) { goto end; } - (void)memset(probe_backup, 0, sizeof(struct probe_s)); size_t size = sizeof(probe_parsers) / sizeof(struct probe_parser_s); for (size_t i = 0; i < size; i++) { @@ -1021,6 +1397,10 @@ int parse_probe_json(const char *probe_name, const char *probe_content) set_probe_modify(probe, probe_backup, parse_flag); } + if (ret == 0) { + probe_info_print(probe); + } + /* Send snooper obj after parsing successfully */ if (ret == 0 && (IS_STARTED_PROBE(probe) || IS_RUNNING_PROBE(probe)) && (probe->is_params_chg || probe->is_snooper_chg || probe->resnd_snooper_for_restart)) { @@ -1044,7 +1424,7 @@ char *get_probe_json(const char *probe_name) { void *res = NULL, *item; char *buf = NULL; - struct probe_s *probe; + struct probe_s *probe = NULL; struct probe_parser_s *parser; get_probemng_lock(); @@ -1055,7 +1435,19 @@ char *get_probe_json(const char *probe_name) } res = Json_CreateObject(); - probe = g_probe_mng->probes[probe_type]; + if (probe_type == PROBE_CUSTOM) { + for (int i = 1; i <= g_probe_mng->custom_index; i++) { + if (strcmp(g_probe_mng->custom[i]->name, probe_name) == 0) { + probe = g_probe_mng->custom[i]; + break; + } + if (i == (g_probe_mng->custom_index) - 1) { + goto end; + } + } + } else { + probe = g_probe_mng->probes[probe_type]; + } if (probe == NULL) { goto end; } @@ -1094,7 +1486,7 @@ void destroy_probe_threads(void) struct probe_s *probe = g_probe_mng->probes[i]; if (probe != NULL) { stop_probe(probe); - INFO("[PROBE_MNG] Probe %s is stopped\n", probe->name); + INFO("[PROBE_MNG] Probe %s is stopped.\n", probe->name); } } } @@ -1121,6 +1513,255 @@ void destroy_probe_mng(void) del_pods(); } +void destroy_custom_ini(void) +{ + struct probe_s *probe; + + if (g_custom_ini == NULL) { + return; + } + for (int i = 0; i <= g_custom_ini->custom_num; i++) { + probe = g_custom_ini->custom[i]; + if (probe == NULL) { + continue; + } + stop_probe(probe); + INFO("[CUSTOM INI]Probe %s is stopped\n", probe->name); + destroy_probe(g_custom_ini->custom[i]); + g_custom_ini->custom[i] = NULL; + } + free(g_custom_ini); + g_custom_ini = NULL; +} + +static struct probe_s* new_custom(const char* name, const u32 custom_index) +{ + struct probe_s *probe = NULL; + size_t size = sizeof(probe_define) / sizeof(struct probe_define_s); + + for (int i = 0; i < size; i++) { + if (strcmp(name, probe_define[i].desc) == 0) { + ERROR("[CUSTOM INI]Custom name cannot be the same as internal probe."); + return NULL; + } + } + + probe = (struct probe_s *)calloc(1, sizeof(struct probe_s)); + if (probe == NULL) { + ERROR("[CUSTOM INI]Probe memory allocation failure.\n"); + return NULL; + } + + probe->name = strdup(name); + if (probe->name == NULL) { + ERROR("[CUSTOM INI]Probe name memory strdup failure.\n"); + free(probe); + return NULL; + } + + probe->probe_type = PROBE_CUSTOM; + probe->custom.index = custom_index; + probe->bin = NULL; + set_default_params(probe); + + return probe; +} + +static struct probe_s *creare_custom_by_name(char *name) +{ + u32 custom_index = g_custom_ini->custom_num; + + if (check_custom_range(name, "name")) { + ERROR("[CUSTOM INIT]The length of custom name has out of range, it must range from 0 to %d.\n", MAX_CUSTOM_NAME_LEN); + return NULL; + } + custom_index++; + if (custom_index >= MAX_CUSTOM_NUM) { + ERROR("[CUSTOM INIT]The number of custom probes has over the threshold.\n"); + return NULL; + } + g_custom_ini->custom[custom_index] = new_custom(name, custom_index); + if (g_custom_ini->custom[custom_index] != NULL) { + g_custom_ini->custom_num = custom_index; + } + return g_custom_ini->custom[custom_index]; +} +/* Read data from a file*/ +int file_handle(const char *file, char *data, size_t size) +{ + FILE *fp; + u32 fsize; + size_t file_size; + + fp = fopen(file, "r"); + if (fp == NULL) { + ERROR("[CUSTOM INI]Unable to open file.\n"); + return -1; + } + fseek(fp, 0, SEEK_END); + fsize = ftell(fp); + fseek(fp, 0, SEEK_SET); + file_size = fread(data, 1, fsize, fp); + if (file_size != fsize || file_size >= size) { + ERROR("[CUSTOM INI]Please verify the value of file_size.\n"); + fclose(fp); + return -1; + } + fclose(fp); + data[fsize] = '\0'; + return 0; +} + +static int init_custom_probe(const char* data) +{ + void *json_obj = NULL; + struct key_value_pairs *kv_pairs = NULL; + struct key_value *kv; + struct probe_s *probe; + + json_obj = Json_Parse(data); + if (json_obj == NULL) { + ERROR("[CUSTOM INI]invalid json format.\n"); + return -1; + } + + kv_pairs = Json_GetKeyValuePairs(json_obj); + if (!kv_pairs) { + ERROR("[CUSTOM INI]invalid json param pairs.\n"); + Json_Delete(json_obj); + return -1; + } + Json_ArrayForEach(kv, kv_pairs) { + probe = creare_custom_by_name(kv->key); + if (probe == NULL) { + ERROR("[CUSTOM INI]Failed to initialize the custom with name.\n"); + Json_DeleteKeyValuePairs(kv_pairs); + Json_Delete(json_obj); + return -1; + } + + if (custom_parser(probe, kv->valuePtr)) { + Json_DeleteKeyValuePairs(kv_pairs); + Json_Delete(json_obj); + return -1; + } + } + + Json_DeleteKeyValuePairs(kv_pairs); + Json_Delete(json_obj); + for(int i = 1; i <= g_custom_ini->custom_num; ++i) { + INFO("[CUSTOM INI] custom probe %s has been obtained successfully.\n", g_custom_ini->custom[i]->name); + } + return 0; +} + +static int init_custom(const char *custom_path) +{ + char *json_data; + int ret; + + json_data = calloc(1, MAX_CUSTOM_CONFIG + 1); + if (json_data == NULL) { + ERROR("[CUSTOM INI]Custom memory allocation error\n"); + return -1; + } + ret = file_handle(custom_path, json_data, MAX_CUSTOM_CONFIG + 1); + if (ret) { + free(json_data); + return ret; + } + + ret = init_custom_probe(json_data); + free(json_data); + if (ret) { + return ret; + } + + return 0; +} + +static int verify_single_permission(char *path, bool is_true, unsigned int user, unsigned int group, unsigned int other) +{ + struct stat st; + struct passwd *pw; + + if (lstat(path, &st)) { + ERROR("%s stat has error, Check whether the file exists.\n", path); + return -1; + } + + if ((st.st_mode & S_IFMT) == S_IFLNK) { + ERROR("%s is a symbolic link\n", path); + return -1; + } + + if ((st.st_mode & S_IFMT) != S_IFREG) { + ERROR("The path %s is not a standard path.\n", path); + return -1; + } + + if (is_true == true) { + if (st.st_uid != 0) { + ERROR("%s must owned by root.\n", path); + return -1; + } + } else { + pw = getpwuid(st.st_uid); + if (pw == NULL) { + ERROR("Failed to obtain the owner name. Check the owner.\n"); + return -1; + } + + if (strcmp(pw->pw_name, "gala-gopher") != 0) { + ERROR("Failed to verify %s, the owner is not gala-gopher.\n", path); + return -1; + } + } + + if (((st.st_mode & S_IRWXU) == user) && ((st.st_mode & S_IRWXG) == group) && ((st.st_mode & S_IRWXO) == other)) { + return 0; + } + ERROR("%s has permission error.\n", path); + return -1; + +} + +static int verify_permissions() +{ + int ret = 0; + int size = g_custom_ini->custom_num; + + for (int i = 1; i <= size; i++) { + ret = verify_single_permission(g_custom_ini->custom[i]->bin, true, (S_IRUSR | S_IXUSR), (S_IRGRP | S_IXGRP), 0); + if (ret) { + return -1; + } + } + ret = verify_single_permission(GALA_GOPHER_CUSTOM_PATH, true, (S_IRUSR | S_IWUSR), S_IRGRP, 0); + if (ret) { + return -1; + } + return 0; +} + +int is_file_exit(char *dir) +{ + FILE *file = fopen(dir, "r"); + + if (file != NULL) { + fseek(file, 0, SEEK_END); + if (ftell(file) != 0) { + (void)fclose(file); + return 0; + } + INFO("The custom probe json is null, gala-gopher continues.\n"); + (void)fclose(file); + return -1; + } + INFO("The custom probe json does not exist, gala-gopher continues.\n"); + return -1; +} + struct probe_mng_s *create_probe_mng(void) { int msq_id; @@ -1156,13 +1797,54 @@ struct probe_mng_s *create_probe_mng(void) g_probe_mng->keeplive_ts = (time_t)time(NULL); + if (is_file_exit(GALA_GOPHER_CUSTOM_PATH)) { + return g_probe_mng; + } + + g_custom_ini = (struct custom_ini *)calloc(1, sizeof(struct custom_ini)); + if (g_custom_ini == NULL) { + goto err; + } + ret = init_custom(GALA_GOPHER_CUSTOM_PATH); + if (ret) { + goto err; + } + + ret = verify_permissions(); + if (ret) { + goto err; + } return g_probe_mng; err: destroy_probe_mng(); + destroy_custom_ini(); return NULL; } +#define __PROBE_KEEPLIVE_TIMEOUT (60) // 60 Seconds +static int is_start_today(const struct probe_mng_s *probe_mng, u8 *restart) +{ + time_t time = probe_mng->keeplive_ts; + time_t time2 = probe_mng->keeplive_ts - __PROBE_KEEPLIVE_TIMEOUT * 2; + struct tm tm_now, tm_before; + + localtime_r(&time, &tm_now); + localtime_r(&time2, &tm_before); + + + if (*restart < MAX_RESTART_TIMES) { + return 1; + } + + if (tm_now.tm_mday == tm_before.tm_mday) { + return 0; + } + INFO("Time comes the next day, reset the restart times.\n"); + *restart = 0; + return 1; +} + static void keeplive_probes(struct probe_mng_s *probe_mng) { struct probe_s *probe; @@ -1180,9 +1862,24 @@ static void keeplive_probes(struct probe_mng_s *probe_mng) probe->resnd_snooper_for_restart = 0; } } + + for (int i = 1; i <= probe_mng->custom_index; i++) { + probe = probe_mng->custom[i]; + if (probe == NULL) { + continue; + } + + if (is_start_today(probe_mng, &probe->resnd_snooper_for_restart)) { + if(try_start_probe(probe) == 0 && (probe->resnd_snooper_for_restart > 0)) { + probe->is_params_chg = 0; + probe->is_snooper_chg = 0; + (void)send_snooper_obj(probe); + INFO("probe %s has been tested to start.\n", probe->name); + } + } + } } -#define __PROBE_KEEPLIVE_TIMEOUT (60) // 60 Seconds static char is_keeplive_tmout(struct probe_mng_s *probe_mng) { time_t current = (time_t)time(NULL); diff --git a/src/lib/probe/probe_mng.h b/src/lib/probe/probe_mng.h index b95e99f2..57972339 100644 --- a/src/lib/probe/probe_mng.h +++ b/src/lib/probe/probe_mng.h @@ -17,6 +17,7 @@ #pragma once #include +#include #include "base.h" #include "fifo.h" @@ -45,6 +46,10 @@ struct probe_define_s { char enable; }; +struct probe_threshold_verify { + char *name; + u32 max; +}; typedef int (*ParseParam)(const char*, struct probe_params *); struct param_define_s { char *desc; @@ -55,6 +60,17 @@ struct probe_status_s { u32 status_flags; // Refer to flags defined [PROBE_FLAGS_XXX] }; +struct custom { + u32 index; + bool privilege; + struct custom_ipc custom_ipc_msg; +}; + +struct custom_ini { + struct probe_s *custom[MAX_CUSTOM_NUM]; //The probe number starts from subscript 1. + u32 custom_num; +}; + struct probe_s; typedef int (*ProbeMain)(struct probe_s *); typedef void *(*ProbeCB)(void *); @@ -67,6 +83,7 @@ struct probe_s { 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 probe_type_e probe_type; + struct custom custom; // User-defined probe u32 probe_range_flags; // Refer to flags defined [PROBE_RANGE_XX_XX] ProbeMain probe_entry; // Main function for native probe ProbeCB cb; // Thread cb for probe @@ -88,6 +105,9 @@ struct probe_s { struct probe_mng_s { int msq_id; // ipc control msg channel struct probe_s *probes[PROBE_TYPE_MAX]; + struct probe_s *custom[MAX_CUSTOM_NUM]; //Used to manage external probes. + u32 custom_index; //Used to define external probes index. + void *snooper_skel; const char *btf_custom_path; void *snooper_proc_pb; // context in perf event @@ -112,10 +132,15 @@ int parse_probe_json(const char *probe_name, const char *probe_content); char *get_probe_json(const char *probe_name); struct probe_mng_s *create_probe_mng(void); void destroy_probe_mng(void); +void destroy_custom_ini(void); void destroy_probe_threads(void); u32 get_probe_status_flags(struct probe_s* probe); void set_probe_status_stopped(struct probe_s* probe); void set_probe_pid(struct probe_s *probe, int pid); +int check_custom_range(const char *key, const char *comp); +int file_handle(const char *file, char *data, size_t size); +char *probe_extern_cmd_param(const char *key, const void *item); +int is_file_exit(char *dir); #define IS_STOPPED_PROBE(probe) (get_probe_status_flags(probe) & PROBE_FLAGS_STOPPED) #define IS_STARTED_PROBE(probe) (get_probe_status_flags(probe) & PROBE_FLAGS_STARTED) diff --git a/src/lib/probe/probe_params_parser.c b/src/lib/probe/probe_params_parser.c index 18c3963c..dabd82a7 100644 --- a/src/lib/probe/probe_params_parser.c +++ b/src/lib/probe/probe_params_parser.c @@ -466,6 +466,96 @@ static int parser_cadvisor_port(struct probe_s *probe, const struct param_key_s return 0; } +static int back_probe_param(struct probe_s *probe, struct custom_params *probe_bak) +{ + if (probe == NULL) { + ERROR("Failed to back up probe data.\n"); + return -1; + } + memset(probe_bak, 0, sizeof(struct custom_params) * MAX_CUSTOM_NUM); + for (int i = 0; i < probe->custom.custom_ipc_msg.params_num; i++) { + snprintf(probe_bak[i].value, MAX_CUSTOM_PARAMS_LEN, "%s", probe->custom.custom_ipc_msg.custom_param[i].value); + } + return 0; +} + +static void roll_back_probe_param(struct probe_s *probe, struct custom_params *probe_bak) +{ + for (int i = 0; i < probe->custom.custom_ipc_msg.params_num; i++) { + memset(probe->custom.custom_ipc_msg.custom_param[i].value, 0, sizeof(char) * MAX_CUSTOM_PARAMS_LEN); + snprintf(probe->custom.custom_ipc_msg.custom_param[i].value, MAX_CUSTOM_PARAMS_LEN, "%s", probe_bak[i].value); + } +} + + +static int parser_custom_param(struct probe_s *probe, const struct param_key_s *param_key, const void *key_item) +{ + void *obj = NULL; + int size = Json_GetArraySize(key_item); + int custom_size = probe->custom.custom_ipc_msg.params_num; + struct key_value_pairs *kv; + int index = 0; + int ret; + struct custom_params *custom_params_bak = (struct custom_params *)calloc(1, sizeof(struct custom_params) * MAX_CUSTOM_NUM); + if (custom_params_bak == NULL) { + ERROR("custom_params_bak Failed to Apply for Memory\n"); + return -1; + } + ret = back_probe_param(probe, custom_params_bak); + if (ret) { + free(custom_params_bak); + return -1; + } + for (int i = 0; i < custom_size; i++) { + if (strlen(probe->custom.custom_ipc_msg.custom_param[i].label) > 0) { + memset(probe->custom.custom_ipc_msg.custom_param[i].value, 0, sizeof(char) * MAX_CUSTOM_PARAMS_LEN); + } + } + for (int i = 0; i < size; i++) { + obj = Json_GetArrayItem(key_item, i); + if (obj == NULL) { + PARSE_ERR("%s Get custom params from json error", param_key->key); + goto err; + } + kv = Json_GetKeyValuePairs(obj); + if (kv == NULL) { + PARSE_ERR("%s Custom params parsed error", param_key->key); + goto err; + } + for (index = 0; index < custom_size; index++) { + if (strcmp(probe->custom.custom_ipc_msg.custom_param[index].label, kv->kv_pairs->key) == 0) { + if (!Json_IsString(kv->kv_pairs->valuePtr)) { + PARSE_ERR("%s Custom Curl params parsed error", param_key->key); + Json_DeleteKeyValuePairs(kv); + goto err; + } + if (check_custom_range((char *)Json_GetValueString(kv->kv_pairs->valuePtr), "param")) { + PARSE_ERR("%s param value must range from 0 to %d.", param_key->key, MAX_CUSTOM_PARAMS_LEN); + Json_DeleteKeyValuePairs(kv); + goto err; + } + snprintf(probe->custom.custom_ipc_msg.custom_param[index].value, MAX_CUSTOM_PARAMS_LEN, + "%s", (char *)Json_GetValueString(kv->kv_pairs->valuePtr)); + break; + } + } + if (index == custom_size) { + PARSE_ERR("%s param value has unregistered param : %s.", param_key->key, kv->kv_pairs->key); + Json_DeleteKeyValuePairs(kv); + goto err; + } + Json_DeleteKeyValuePairs(kv); + kv = NULL; + } + free(custom_params_bak); + kv = NULL; + return 0; +err: + roll_back_probe_param(probe, custom_params_bak); + free(custom_params_bak); + return -1; +} + #define SET_DEFAULT_PARAMS_INTER(field) \ static void set_default_params_inter_##field(struct probe_params *params, const struct param_val_s *value) \ { \ @@ -537,10 +627,12 @@ SET_DEFAULT_PARAMS_STR(flame_dir); #define PROFLING_CHANNEL "profiling_channel" #define MIN_EXEC_DUR "min_exec_dur" #define MIN_AGGR_DUR "min_aggr_dur" +#define CUSTOM_PARAMS "custom_param" struct param_key_s param_keys[] = { {SAMPLE_PERIOD, {DEFAULT_SAMPLE_PERIOD, 100, 10000, ""}, parser_sample_peirod, set_default_params_inter_sample_period, JSON_NUMBER}, {REPORT_PERIOD, {DEFAULT_PERIOD, 5, 600, ""}, parser_report_peirod, set_default_params_inter_period, JSON_NUMBER}, + {CUSTOM_PARAMS, {0, 0, 0, ""}, parser_custom_param, NULL, JSON_ARRAY}, #ifdef ENABLE_REPORT_EVENT {LATENCY_THR, {0, 10, 100000, ""}, parser_latency_thr, set_default_params_inter_latency_thr, JSON_NUMBER}, {OFFLINE_THR, {0, 10, 100000, ""}, parser_offline_thr, set_default_params_inter_offline_thr, JSON_NUMBER}, @@ -628,12 +720,36 @@ static void *param_flags_to_json(unsigned int flags, struct param_flags_s param_ return arr; } +static void *param_custom_to_json(struct custom_params *custom_param, size_t size) +{ + void *item = Json_CreateArray(); + void *object; + + for (size_t i = 0; i < size; i++) { + if (custom_param[i].label[0] == 0 || custom_param[i].value[0] == 0) { + continue; + } + object = Json_CreateObject(); + Json_AddStringToObject(object, custom_param[i].label, custom_param[i].value); + Json_AddItemToArray(item, object); + Json_Delete(object); + } + return item; +} + +void print_custom_params(void *params, struct probe_params *probe_param) +{ + Json_AddUIntItemToObject(params, SAMPLE_PERIOD, probe_param->sample_period); + + Json_AddStringToObject(params, DEV_NAME_KEY, probe_param->target_dev); + Json_AddUIntItemToObject(params, CADVISOR_PORT, probe_param->cadvisor_port); +} void probe_params_to_json(struct probe_s *probe, void *params) { struct probe_params *probe_param = &probe->probe_param; enum probe_type_e probe_type = probe->probe_type; - void *flags_arr; - size_t flags_size; + void *arr; + size_t size; Json_AddUIntItemToObject(params, REPORT_PERIOD, probe_param->period); if (probe_type == PROBE_IO || probe_type == PROBE_TCP) { @@ -658,10 +774,10 @@ void probe_params_to_json(struct probe_s *probe, void *params) #endif if (probe_type == PROBE_L7) { - flags_size = sizeof(param_l7pro_flags) / sizeof(param_l7pro_flags[0]); - flags_arr = param_flags_to_json(probe_param->l7_probe_proto_flags, param_l7pro_flags, flags_size); - Json_AddItemToObject(params, L7_PROTOCOL, flags_arr); - Json_Delete(flags_arr); + size = sizeof(param_l7pro_flags) / sizeof(param_l7pro_flags[0]); + arr = param_flags_to_json(probe_param->l7_probe_proto_flags, param_l7pro_flags, size); + Json_AddItemToObject(params, L7_PROTOCOL, arr); + Json_Delete(arr); Json_AddCharItemToObject(params, SUPPORT_SSL, probe_param->support_ssl); } if (probe_type == PROBE_L7 || probe_type == PROBE_TCP) { @@ -695,4 +811,11 @@ void probe_params_to_json(struct probe_s *probe, void *params) if (probe_type == PROBE_CONTAINER) { Json_AddUIntItemToObject(params, CADVISOR_PORT, probe_param->cadvisor_port); } + if (probe_type == PROBE_CUSTOM) { + print_custom_params(params, probe_param); + size = probe->custom.custom_ipc_msg.params_num; + arr = param_custom_to_json(probe->custom.custom_ipc_msg.custom_param, size); + Json_AddItemToObject(params, CUSTOM_PARAMS, arr); + Json_Delete(arr); + } } diff --git a/src/lib/probe/snooper.c b/src/lib/probe/snooper.c index 15d3ad1d..b852abdf 100644 --- a/src/lib/probe/snooper.c +++ b/src/lib/probe/snooper.c @@ -648,13 +648,20 @@ static inline int need_send_snooper_obj(struct probe_s *probe) int send_snooper_obj(struct probe_s *probe) { struct ipc_body_s ipc_body; // Initialized at '__build_ipc_body' function + long probetype = 0; if (need_send_snooper_obj(probe) == 0) { return 0; } __build_ipc_body(probe, &ipc_body); - return send_ipc_msg(__probe_mng_snooper->msq_id, (long)probe->probe_type, &ipc_body); + if (probe->probe_type == PROBE_CUSTOM) { + probetype = (long)(PROBE_CUSTOM_IPC + probe->custom.index); + return send_custom_ipc_msg(__probe_mng_snooper->msq_id, probetype, &ipc_body, &(probe->custom.custom_ipc_msg)); + } + + probetype = (long)probe->probe_type; + return send_ipc_msg(__probe_mng_snooper->msq_id, probetype, &ipc_body); } int parse_snooper(struct probe_s *probe, const void *json) diff --git a/src/probes/extends/python.probe/common/ipc.py b/src/probes/extends/python.probe/common/ipc.py index d08415fc..5a1022e5 100644 --- a/src/probes/extends/python.probe/common/ipc.py +++ b/src/probes/extends/python.probe/common/ipc.py @@ -10,6 +10,9 @@ SNOOPER_MAX = 1000 IPC_EXCL = 0o2000 # copy from linux/ipc.h IPC_FLAGS_SNOOPER_CHG = 0x00000001 IPC_FLAGS_PARAMS_CHG = 0x00000002 +MAX_CUSTOM_PARAMS_LEN = 64 +MAX_CUSTOM_PARAMS_NUM = 9 +MAX_SUBPEOBE_NUM = 8 IPC_LIB = CDLL("/opt/gala-gopher/lib/ipc.so") @@ -19,6 +22,20 @@ ProbeType = IntEnum('ProbeType', ('PROBE_BASEINFO', 'PROBE_VIRT', 'PROBE_FG', 'P 'PROBE_SERMANT', 'PROBE_SLI', 'PROBE_FLOWTRACER', 'PROBE_TYPE_MAX')) SnooperObjEnum = IntEnum('SnooperObjEnum', ('SNOOPER_OBJ_PROC', 'SNOOPER_OBJ_CON', 'SNOOPER_OBJ_MAX'), start = 0) +class CustomParams(Structure): + _fields_ = [ + ("label", c_char * MAX_CUSTOM_PARAMS_LEN), + ("value", c_char * MAX_CUSTOM_PARAMS_LEN), + ] + +class CustomIpc(Structure): + _fields_ = [ + ("subprobe", c_char * MAX_SUBPEOBE_NUM * MAX_CUSTOM_PARAMS_LEN), + ("subprobe_num", c_uint), + ("custom_param", CustomParams * MAX_CUSTOM_PARAMS_NUM), + ("params_num", c_uint), + ] + class ProbeParams(Structure): _fields_ = [ ("period", c_uint), @@ -97,6 +114,14 @@ def recv_ipc_msg(msq_id, msg_type, ipc_body): IPC_LIB.recv_ipc_msg.restype = c_int return IPC_LIB.recv_ipc_msg(_msq_id, _msg_type, _ipc_body) +def recv_custom_ipc_msg(msq_id, msg_type, ipc_body, custom_ipc_msg): + _msq_id = c_int(msq_id) + _msg_type = c_long(msg_type) + _ipc_body = pointer(ipc_body) + _custom_ipc_msg = pointer(custom_ipc_msg) + IPC_LIB.recv_custom_ipc_msg.restype = c_int + return IPC_LIB.recv_custom_ipc_msg(_msq_id, _msg_type, _ipc_body, _custom_ipc_msg) + def destroy_ipc_body(ipc_body): _ipc_body = pointer(ipc_body) return IPC_LIB.destroy_ipc_body(_ipc_body) diff --git a/src/resource/resource.c b/src/resource/resource.c index 9866141e..229b6e5c 100644 --- a/src/resource/resource.c +++ b/src/resource/resource.c @@ -185,6 +185,7 @@ static int ProbeMngInit(ResourceMgr *resourceMgr) static void ProbeMngDeinit(ResourceMgr *resourceMgr) { destroy_probe_mng(); + destroy_custom_ini(); resourceMgr->probe_mng = NULL; } -- Gitee