From 40136174633ff742594a111a4c97a541b368379f Mon Sep 17 00:00:00 2001 From: cp3yeye Date: Thu, 27 Nov 2025 23:44:36 +0800 Subject: [PATCH] backport some bugfix patches from sourcehub (cherry picked from commit e018e3e1565e916d1dc2baab22fe98436a495f82) --- Fix-some-resource-leak-and-oob-issues.patch | 53 + ...it-path-has-missing-return-statement.patch | 24 + ...imize-the-type-of-record-value-and-a.patch | 631 +++++++++ ...-merge-win-sockbuf-rtt-rate-subprobe.patch | 1142 +++++++++++++++++ ...-reduce-the-scanning-times-of-tracke.patch | 151 +++ ...reduce-memory-usage-of-metric-record.patch | 794 ++++++++++++ ...or-handling-process-by-using-goto-st.patch | 122 ++ ...-mismatch-between-metric-data-and-me.patch | 90 ++ ...g-level-info-to-logs-of-main-process.patch | 191 +++ ...f-kprobe-between-tcp_link-and-tcp_rx.patch | 54 + ...ing-error-when-gala-gopher-running-i.patch | 151 +++ ...ok-point-of-req_drops-according-to-k.patch | 146 +++ fix-Memory-leak.patch | 74 ++ fix-OOB-write-when-getting-proc-cmdline.patch | 51 + ...obe-bin-after-parsing-invalid-config.patch | 27 + ...fer-overflow-and-ret-value-of-sscanf.patch | 126 ++ fix-buffer-overflow-in-sscanf.patch | 129 ++ fix-extra-length-of-task-comm.patch | 60 + fix-home-check.patch | 93 ++ ...llptr-dereference-in-libevent-openss.patch | 31 + ...oad-failure-due-to-loops-in-toa-code.patch | 68 + ...er-failed-for-check-gopher-pid-multi.patch | 44 + ...-thread-block-by-resetting-probe-pid.patch | 24 + ...nder-core-for-probe-mng-create-later.patch | 27 + ...ed-when-cmd-server-thread-starts-lat.patch | 88 ++ fix-strdup-relative-error.patch | 547 ++++++++ gala-gopher.spec | 69 +- ...be_flags-to-0-when-restarting-probes.patch | 26 + ...patible-struct-definition-of-Snooper.patch | 25 + ...utput-of-extend-probes-when-failed-t.patch | 28 + ...len-and-snprintf-when-writing-metric.patch | 72 ++ ...ion-of-toa-and-make-it-valid-on-olde.patch | 359 ++++++ ...channel-map-and-shorten-poll-timeout.patch | 55 + ...correct-flags-when-resending-ipc-msg.patch | 26 + ...site-judgment-logic-of-container-inf.patch | 46 + snooper-optimize-the-size-of-proc-event.patch | 101 ++ ...correct-flags-when-resending-ipc-msg.patch | 25 + ...-op-to-read-proc-comm-and-stat-inste.patch | 115 ++ ...os-fix-oob-of-arrays-and-double-free.patch | 116 ++ ...flush-snooped-procs-to-avoid-deletin.patch | 92 ++ tcpprobe-fix-inaccurate-notack_bytes.patch | 140 ++ ...orret-struct-type-of-tracepoint-even.patch | 53 + ...om-last-buffer-to-adapt-for-pinned-p.patch | 36 + ...superfluous-buffer__open-to-reduce-m.patch | 167 +++ ...all-metrics-of-a-tracker-in-one-outp.patch | 679 ++++++++++ ...k-link-state-when-tcp-link-was-delet.patch | 69 + 46 files changed, 7236 insertions(+), 1 deletion(-) create mode 100644 Fix-some-resource-leak-and-oob-issues.patch create mode 100644 Found-a-exit-path-has-missing-return-statement.patch create mode 100644 PFM_OPT-imdb-optimize-the-type-of-record-value-and-a.patch create mode 100644 PFM_OPT-tcpprobe-merge-win-sockbuf-rtt-rate-subprobe.patch create mode 100644 PFM_OPT-tcpprobe-reduce-the-scanning-times-of-tracke.patch create mode 100644 Refactor-to-reduce-memory-usage-of-metric-record.patch create mode 100644 Simplify-the-error-handling-process-by-using-goto-st.patch create mode 100644 add-error-log-of-mismatch-between-metric-data-and-me.patch create mode 100644 add-log-level-info-to-logs-of-main-process.patch create mode 100644 avoid-conflict-of-kprobe-between-tcp_link-and-tcp_rx.patch create mode 100644 bugfix-path-parsing-error-when-gala-gopher-running-i.patch create mode 100644 epprobe-adapt-hook-point-of-req_drops-according-to-k.patch create mode 100644 fix-Memory-leak.patch create mode 100644 fix-OOB-write-when-getting-proc-cmdline.patch create mode 100644 fix-UAF-of-probe-bin-after-parsing-invalid-config.patch create mode 100644 fix-buffer-overflow-and-ret-value-of-sscanf.patch create mode 100644 fix-buffer-overflow-in-sscanf.patch create mode 100644 fix-extra-length-of-task-comm.patch create mode 100644 fix-home-check.patch create mode 100644 fix-potential-nullptr-dereference-in-libevent-openss.patch create mode 100644 fix-prog-load-failure-due-to-loops-in-toa-code.patch create mode 100644 fix-restart-gopher-failed-for-check-gopher-pid-multi.patch create mode 100644 fix-restart-thread-block-by-resetting-probe-pid.patch create mode 100644 fix-run-sig-hander-core-for-probe-mng-create-later.patch create mode 100644 fix-service-failed-when-cmd-server-thread-starts-lat.patch create mode 100644 fix-strdup-relative-error.patch create mode 100644 ipc-reset-probe_flags-to-0-when-restarting-probes.patch create mode 100644 ipc.py-fix-incompatible-struct-definition-of-Snooper.patch create mode 100644 keep-consuming-output-of-extend-probes-when-failed-t.patch create mode 100644 remove-extra-strlen-and-snprintf-when-writing-metric.patch create mode 100644 simplify-dissection-of-toa-and-make-it-valid-on-olde.patch create mode 100644 snooper-enlarge-channel-map-and-shorten-poll-timeout.patch create mode 100644 snooper-fix-incorrect-flags-when-resending-ipc-msg.patch create mode 100644 snooper-fix-opposite-judgment-logic-of-container-inf.patch create mode 100644 snooper-optimize-the-size-of-proc-event.patch create mode 100644 snooper-refix-incorrect-flags-when-resending-ipc-msg.patch create mode 100644 snooper-use-file-op-to-read-proc-comm-and-stat-inste.patch create mode 100644 system_infos-fix-oob-of-arrays-and-double-free.patch create mode 100644 tcpprobe-do-not-flush-snooped-procs-to-avoid-deletin.patch create mode 100644 tcpprobe-fix-inaccurate-notack_bytes.patch create mode 100644 tcpprobe-fix-incorret-struct-type-of-tracepoint-even.patch create mode 100644 tcpprobe-poll-from-last-buffer-to-adapt-for-pinned-p.patch create mode 100644 tcpprobe-remove-superfluous-buffer__open-to-reduce-m.patch create mode 100644 tcpprobe-report-all-metrics-of-a-tracker-in-one-outp.patch create mode 100644 tcpprobe-reset-sk-link-state-when-tcp-link-was-delet.patch diff --git a/Fix-some-resource-leak-and-oob-issues.patch b/Fix-some-resource-leak-and-oob-issues.patch new file mode 100644 index 0000000..c2c73bb --- /dev/null +++ b/Fix-some-resource-leak-and-oob-issues.patch @@ -0,0 +1,53 @@ +From eb8c635b318632e51109c8edf5df47171aeef202 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Sat, 12 Jul 2025 14:59:40 +0800 +Subject: [PATCH 84/99] Fix some resource leak and oob issues + +--- + src/common/tc_loader.c | 2 +- + src/ingress/ingress.c | 2 +- + src/lib/imdb/container_cache.c | 1 + + src/lib/probe/snooper.c | 1 + + 4 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/common/tc_loader.c b/src/common/tc_loader.c +index a5a5edd3..52960612 100644 +--- a/src/common/tc_loader.c ++++ b/src/common/tc_loader.c +@@ -63,7 +63,7 @@ static int excute_cmd(const char *format, ...) + va_start(args, format); + ret = vsnprintf(g_cmdBuf, MAX_CMD_LEN, format, args); + va_end(args); +- if (ret < 0) { ++ if (ret < 0 || ret >= MAX_CMD_LEN) { + return TC_ERR; + } + +diff --git a/src/ingress/ingress.c b/src/ingress/ingress.c +index 5f0fa93a..cbd66d46 100644 +--- a/src/ingress/ingress.c ++++ b/src/ingress/ingress.c +@@ -40,7 +40,7 @@ void IngressMgrDestroy(IngressMgr *mgr) + return; + } + +- if (mgr->epoll_fd > 0) { ++ if (mgr->epoll_fd >= 0) { + close(mgr->epoll_fd); + } + free(mgr); +diff --git a/src/lib/imdb/container_cache.c b/src/lib/imdb/container_cache.c +index 5c6e3e30..ba96a09f 100644 +--- a/src/lib/imdb/container_cache.c ++++ b/src/lib/imdb/container_cache.c +@@ -155,6 +155,7 @@ static void fill_pod_info(struct pod_cache *pod_cache, const char *container_id) + } + struct key_value_pairs *kv_pairs = Json_GetKeyValuePairs(pod_labels_json); + if (!kv_pairs) { ++ Json_Delete(pod_labels_json); + return; + } + struct key_value *kv; +-- +2.33.0 + diff --git a/Found-a-exit-path-has-missing-return-statement.patch b/Found-a-exit-path-has-missing-return-statement.patch new file mode 100644 index 0000000..ee031a1 --- /dev/null +++ b/Found-a-exit-path-has-missing-return-statement.patch @@ -0,0 +1,24 @@ +From 44f6d2ab1e7a4bf468115b5fa982b7391c6f0ffc Mon Sep 17 00:00:00 2001 +From: chengjun +Date: Tue, 19 Nov 2024 15:04:08 +0800 +Subject: [PATCH 15/99] Found a exit path has missing return statement. + +--- + src/probes/system_infos.probe/system_meminfo.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/probes/system_infos.probe/system_meminfo.c b/src/probes/system_infos.probe/system_meminfo.c +index 1ee8a2ce..2e0f5c9c 100644 +--- a/src/probes/system_infos.probe/system_meminfo.c ++++ b/src/probes/system_infos.probe/system_meminfo.c +@@ -271,4 +271,5 @@ int system_meminfo_probe(struct ipc_body_s *ipc_body) + ERROR("[SYSTEM_PROBE] failed to collect fs dentry_state.\n"); + return -1; + } +-} +\ No newline at end of file ++ return 0; ++} +-- +2.33.0 + diff --git a/PFM_OPT-imdb-optimize-the-type-of-record-value-and-a.patch b/PFM_OPT-imdb-optimize-the-type-of-record-value-and-a.patch new file mode 100644 index 0000000..78c9b37 --- /dev/null +++ b/PFM_OPT-imdb-optimize-the-type-of-record-value-and-a.patch @@ -0,0 +1,631 @@ +From 72f978e69515799428530511dcf39bda3f5e31c3 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Wed, 5 Feb 2025 16:25:59 +0800 +Subject: [PATCH 52/99] [PFM_OPT] imdb: optimize the type of record value and + arrange records in doubly-linked list + +--- + src/lib/imdb/imdb.c | 238 +++++++++++----------------------------- + src/lib/imdb/imdb.h | 30 ++--- + src/resource/resource.c | 5 +- + 3 files changed, 74 insertions(+), 199 deletions(-) + +diff --git a/src/lib/imdb/imdb.c b/src/lib/imdb/imdb.c +index 1d7d7985..24a00a1a 100644 +--- a/src/lib/imdb/imdb.c ++++ b/src/lib/imdb/imdb.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include "common.h" + #include "java_support.h" + #include "histogram.h" +@@ -61,35 +62,6 @@ IMDB_Metric *IMDB_MetricCreate(char *name, char *description, char *type) + return metric; + } + +-static IMDB_MetricValue *IMDB_MetricValueCreate(const char *val) +-{ +- int ret; +- IMDB_MetricValue *value; +- +- value = (IMDB_MetricValue *)malloc(sizeof(IMDB_MetricValue)); +- if (value == NULL) { +- return NULL; +- } +- +- ret = snprintf(value->val, sizeof(value->val), "%s", val); +- if (ret < 0 || ret >= sizeof(value->val)) { +- free(value); +- return NULL; +- } +- +- return value; +-} +- +-static void IMDB_MetricValueDestroy(IMDB_MetricValue *value) +-{ +- if (value == NULL) { +- return; +- } +- +- free(value); +- return; +-} +- + void IMDB_MetricDestroy(IMDB_Metric *metric) + { + if (metric == NULL) { +@@ -151,55 +123,27 @@ IMDB_Record *IMDB_RecordCreate(uint32_t capacity) + } + memset(record, 0, sizeof(IMDB_Record)); + +- record->value = (IMDB_MetricValue **)malloc(sizeof(IMDB_MetricValue *) * capacity); ++ record->value = (char **)malloc(sizeof(char *) * capacity); + if (record->value == NULL) { + free(record); + return NULL; + } +- memset(record->value, 0, sizeof(IMDB_MetricValue *) * capacity); ++ memset(record->value, 0, sizeof(char *) * capacity); + return record; + } + + IMDB_Record *IMDB_RecordCreateWithTable(const IMDB_Table *table) + { +- uint32_t keySize = table->recordKeySize; + uint32_t capacity = table->meta->metricsCapacity; +- if (keySize == 0) { +- return NULL; +- } +- + IMDB_Record *record = IMDB_RecordCreate(capacity); + +- if (record != NULL) { +- record->key = (char *)malloc(sizeof(char) * keySize); +- if (record->key == NULL) { +- IMDB_RecordDestroy(record); +- return NULL; +- } +- memset(record->key, 0, sizeof(char) * keySize); ++ if (record) { + record->table = table; + } + + return record; + } + +-int IMDB_RecordAppendKey(IMDB_Record *record, uint32_t keyIdx, char *val) +-{ +- int ret = 0; +- uint32_t offset = keyIdx * MAX_IMDB_METRIC_VAL_LEN; +- +- if (offset + MAX_IMDB_METRIC_VAL_LEN > record->table->recordKeySize) { +- return -1; +- } +- +- ret = snprintf(record->key + offset, MAX_IMDB_METRIC_VAL_LEN, "%s", val); +- if (ret < 0) { +- return -1; +- } +- +- return 0; +-} +- + void IMDB_RecordUpdateTime(IMDB_Record *record, time_t seconds) + { + record->updateTime = seconds; +@@ -211,13 +155,9 @@ void IMDB_RecordDestroy(IMDB_Record *record) + if (record == NULL) + return; + +- if (record->key != NULL) { +- free(record->key); +- } +- + if (record->value != NULL) { + for (int i = 0; i < record->table->meta->metricsCapacity; i++) { +- IMDB_MetricValueDestroy(record->value[i]); ++ free(record->value[i]); + } + free(record->value); + } +@@ -234,15 +174,7 @@ IMDB_Table *IMDB_TableCreate(char *name, uint32_t capacity) + } + memset(table, 0, sizeof(IMDB_Table)); + +- table->records = (IMDB_Record **)malloc(sizeof(IMDB_Record *)); +- if (table->records == NULL) { +- free(table); +- return NULL; +- } +- *(table->records) = NULL; // necessary +- + if (pthread_rwlock_init(&table->ext_label_conf.rwlock, NULL)) { +- free(table->records); + free(table); + return NULL; + } +@@ -263,32 +195,14 @@ void IMDB_TableSetMeta(IMDB_Table *table, IMDB_Meta *meta) + table->meta = meta; + } + +-int IMDB_TableSetRecordKeySize(IMDB_Table *table, uint32_t keyNum) +-{ +- if (keyNum == 0) { +- ERROR("[IMDB] Meta must contain at least one key field, table: %s\n", table->name); +- return -1; +- } +- table->recordKeySize = keyNum * MAX_IMDB_METRIC_VAL_LEN; +- return 0; +-} +- + int IMDB_TableAddRecord(IMDB_Table *table, IMDB_Record *record) + { +- IMDB_Record *old_record; +- +- old_record = HASH_findRecord((const IMDB_Record **)table->records, (const IMDB_Record *)record); +- if (old_record != NULL) { +- HASH_deleteRecord(table->records, old_record); +- IMDB_RecordDestroy(old_record); +- } +- +- if (HASH_recordCount((const IMDB_Record **)table->records) >= table->recordsCapability) { ++ if (table->recordNum >= table->recordsCapability) { + ERROR("[IMDB] Can not add new record to table %s: table full.\n", table->name); + return -1; + } + IMDB_RecordUpdateTime(record, (time_t)time(NULL)); +- HASH_addRecord(table->records, record); ++ AddRecord(table, record); + + return 0; + } +@@ -313,11 +227,7 @@ void IMDB_TableDestroy(IMDB_Table *table) + return; + } + +- if (table->records != NULL) { +- HASH_deleteAndFreeRecords(table->records); +- free(table->records); +- } +- ++ DeleteAndFreeRecords(table); + if (table->meta != NULL) { + IMDB_MetaDestroy(table->meta); + } +@@ -577,12 +487,11 @@ IMDB_Table *IMDB_DataBaseMgrFindTable(IMDB_DataBaseMgr *mgr, const char *tableNa + static int IMDB_DataBaseMgrParseContent(IMDB_DataBaseMgr *mgr, IMDB_Table *table, + IMDB_Record *record, const char *content) + { +- int ret = 0; +- IMDB_MetricValue *value; ++ char *value; + char *token, *buffer; + char delim[] = "|"; + char *buffer_head = NULL; +- uint32_t keyIdx = 0, index = 0, metricsCapacity = table->meta->metricsCapacity; ++ uint32_t index = 0, metricsCapacity = table->meta->metricsCapacity; + + buffer = strdup(content); + if (buffer == NULL) { +@@ -615,22 +524,13 @@ static int IMDB_DataBaseMgrParseContent(IMDB_DataBaseMgr *mgr, IMDB_Table *table + break; + } + +- value = IMDB_MetricValueCreate(token); ++ value = strdup(token); + if (value == NULL) { + ERROR("[IMDB] Set metrics value failed.(%s, %s).\n", table->name, table->meta->metrics[index]->name); + goto ERR; + } + + record->value[index] = value; +- if (strcmp(METRIC_TYPE_KEY, table->meta->metrics[index]->type) == 0) { +- ret = IMDB_RecordAppendKey(record, keyIdx, token); +- if (ret < 0) { +- ERROR("[IMDB] Can not set record key.\n"); +- goto ERR; +- } +- keyIdx++; +- } +- + index += 1; + } + +@@ -701,6 +601,16 @@ static int MetricTypeSatisfyPrometheus(IMDB_Metric *metric) + return -1; + } + ++// return 0 if satisfy, return -1 if not ++static int MetricTypeSatisfyJson(IMDB_Metric *metric) ++{ ++ if (strcmp(metric->type, "gauge") == 0) { ++ return 0; ++ } ++ ++ return -1; ++} ++ + static int MetricTypeIsLabel(IMDB_Metric *metric) + { + const char *label[] = {METRIC_TYPE_LABEL, METRIC_TYPE_KEY}; +@@ -747,7 +657,7 @@ static int IMDB_BuildMetrics(const char *entity_name, + } + + // eg: gala_gopher_tcp_link_rx_bytes(label) 128 1586960586000000000 +-static int IMDB_BuildPrometheusMetrics(const IMDB_MetricValue *value, const char *metric_name, ++static int IMDB_BuildPrometheusMetrics(const char *value, const char *metric_name, + char *buffer, uint32_t maxLen, + const char *entity_name, const char *labels) + { +@@ -767,7 +677,7 @@ static int IMDB_BuildPrometheusMetrics(const IMDB_MetricValue *value, const char + p += len; + size -= len; + (void)time(&now); +- ret = __snprintf(&p, size, &size, fmt, labels, value->val, now * THOUSAND); ++ ret = __snprintf(&p, size, &size, fmt, labels, value, now * THOUSAND); + if (ret < 0) { + return ret; + } +@@ -992,6 +902,9 @@ static int IMDB_BuildLabels(IMDB_DataBaseMgr *mgr, + IMDB_Meta *meta = table->meta; + + for (i = 0; i < meta->metricsCapacity; i++) { ++ if (MetricTypeIsLabel(meta->metrics[i]) == 0) { ++ continue; ++ } + if (MetricNameIsTgid(meta->metrics[i]) == 1) { + tgid_idx = i; + } +@@ -999,21 +912,17 @@ static int IMDB_BuildLabels(IMDB_DataBaseMgr *mgr, + con_id_idx = i; + } + +- if (MetricTypeIsLabel(meta->metrics[i]) == 0) { +- continue; +- } +- +- if (!strcmp(record->value[i]->val, INVALID_METRIC_VALUE)) { ++ if (!strcmp(record->value[i], INVALID_METRIC_VALUE)) { + // ignore label whose value is (null) + continue; + } + + if (first_flag) { + ret = __snprintf(&p, size, &size, first_fmt, +- meta->metrics[i]->name, record->value[i]->val); ++ meta->metrics[i]->name, record->value[i]); + } else { + ret = __snprintf(&p, size, &size, fmt, +- meta->metrics[i]->name, record->value[i]->val); ++ meta->metrics[i]->name, record->value[i]); + } + if (ret < 0) { + return IMDB_BUFFER_FULL; +@@ -1028,7 +937,7 @@ static int IMDB_BuildLabels(IMDB_DataBaseMgr *mgr, + + // Append 'COMM, Container and POD' label for ALL process-level metrics. + if (tgid_idx >= 0) { +- tgid_str = (char *)(record->value[tgid_idx]->val); ++ tgid_str = (char *)(record->value[tgid_idx]); + ret = append_proc_level_labels(tgid_str, &p, &size, mgr, table, type_json); + if (ret < 0) { + DEBUG("[IMDB] Failed to append process-level labels(tgid=%s, ret=%d)\n", tgid_str, ret); +@@ -1037,7 +946,7 @@ static int IMDB_BuildLabels(IMDB_DataBaseMgr *mgr, + } + + if (con_id_idx >= 0) { +- con_id = (char *)(record->value[con_id_idx]->val); ++ con_id = (char *)(record->value[con_id_idx]); + ret = append_container_level_labels(con_id, &p, &size, mgr, table, 1, type_json); + if (ret < 0) { + DEBUG("[IMDB] Failed to append container-level labels(container_id=%s, ret=%d)\n", con_id, ret); +@@ -1145,7 +1054,7 @@ static int append_label_histo_le_inf(strbuf_t *labels_buf) + return append_label(labels_buf, __HISTO_LABEL_NAME, __HISTO_LABEL_VAL_INF); + } + +-static int IMDB_BuildPrometheusHistoMetrics(const IMDB_MetricValue *value, const char *metric_name, ++static int IMDB_BuildPrometheusHistoMetrics(const char *value, const char *metric_name, + char *buffer, uint32_t maxLen, + const char *entity_name, strbuf_t *labels_buf) + { +@@ -1162,7 +1071,7 @@ static int IMDB_BuildPrometheusHistoMetrics(const IMDB_MetricValue *value, const + u64 sum = 0, bkt_sum = 0; + int i; + +- ret = deserialize_histo(value->val, &bkt, &bkt_sz, &bkt_sum); ++ ret = deserialize_histo(value, &bkt, &bkt_sz, &bkt_sum); + if (ret) { + ERROR("[IMDB] Failed to deserialize histogram metric %s\n", metric_name); + return -1; +@@ -1232,7 +1141,7 @@ static int IMDB_Rec2Prometheus(IMDB_DataBaseMgr *mgr, IMDB_Record *record, IMDB_ + continue; + } + +- if (!strcmp(record->value[i]->val, INVALID_METRIC_VALUE)) { ++ if (!strcmp(record->value[i], INVALID_METRIC_VALUE)) { + // Do not report metric whose value is (null) + continue; + } +@@ -1255,7 +1164,7 @@ static int IMDB_Rec2Prometheus(IMDB_DataBaseMgr *mgr, IMDB_Record *record, IMDB_ + return total; + } + +-static int IMDB_BuildJsonHistosBkt(const IMDB_MetricValue *value, const char *metric_name, char **buffer, int *maxLen) ++static int IMDB_BuildJsonHistosBkt(const char *value, const char *metric_name, char **buffer, int *maxLen) + { + int ret, i; + char buf[INT_LEN]; +@@ -1264,7 +1173,7 @@ static int IMDB_BuildJsonHistosBkt(const IMDB_MetricValue *value, const char *me + u64 count = 0, bkt_sum = 0; + char first_flag = 1; + +- ret = deserialize_histo(value->val, &bkt, &bkt_sz, &bkt_sum); ++ ret = deserialize_histo(value, &bkt, &bkt_sz, &bkt_sum); + if (ret) { + ERROR("[IMDB] Failed to deserialize histogram metric %s\n", metric_name); + return IMDB_BUILD_ERR; +@@ -1311,7 +1220,7 @@ static int IMDB_BuildJsonHistos(IMDB_DataBaseMgr *mgr, IMDB_Record *record, IMDB + continue; + } + +- if (strcmp(record->value[i]->val, INVALID_METRIC_VALUE) == 0) { ++ if (strcmp(record->value[i], INVALID_METRIC_VALUE) == 0) { + continue; + } + +@@ -1354,27 +1263,22 @@ static int IMDB_BuildJsonMetrics(IMDB_DataBaseMgr *mgr, IMDB_Record *record, IMD + } + + for (int i = 0; i < meta->metricsCapacity; i++) { +- ret = MetricTypeSatisfyPrometheus(meta->metrics[i]); ++ ret = MetricTypeSatisfyJson(meta->metrics[i]); + if (ret != 0) { + continue; + } + +- if (!strcmp(record->value[i]->val, INVALID_METRIC_VALUE)) { ++ if (!strcmp(record->value[i], INVALID_METRIC_VALUE)) { + // Do not report metric whose value is (null) + continue; + } + +- if (strcmp(meta->metrics[i]->type, "histogram") == 0) { +- // skip histogram type metrics +- continue; +- } +- + if (first_flag) { + ret = __snprintf(buffer, *maxLen, maxLen, "\"%s\":\"%s\"", +- meta->metrics[i]->name, record->value[i]->val); ++ meta->metrics[i]->name, record->value[i]); + } else { + ret = __snprintf(buffer, *maxLen, maxLen, ",\"%s\":\"%s\"", +- meta->metrics[i]->name, record->value[i]->val); ++ meta->metrics[i]->name, record->value[i]); + } + if (ret < 0) { + return IMDB_BUFFER_FULL; +@@ -1469,7 +1373,6 @@ static int IMDB_Tbl2Metrics(IMDB_DataBaseMgr *mgr, IMDB_Table *table, char *buff + IMDB_Record *record, *tmp; + char *curBuffer = buffer; + uint32_t curMaxLen = maxLen; +- uint32_t period_records = DEFAULT_PERIOD_RECORD_NUM; + uint32_t index = 0; + + #define __RESERVED_BUF_SIZE 2 +@@ -1478,18 +1381,14 @@ static int IMDB_Tbl2Metrics(IMDB_DataBaseMgr *mgr, IMDB_Table *table, char *buff + } + curMaxLen -= __RESERVED_BUF_SIZE; + +- if (HASH_recordCount((const IMDB_Record **)table->records) == 0) { ++ if (table->recordNum == 0) { + return 0; + } +- HASH_ITER(hh, *table->records, record, tmp) { +- // check record num +- if (index >= period_records) { +- break; +- } ++ DL_FOREACH_SAFE(table->records, record, tmp) { + // check timeout + if (record->updateTime + g_recordTimeout < time(NULL)) { + // remove invalid record +- HASH_deleteRecord(table->records, record); ++ DeleteRecord(table, record); + IMDB_RecordDestroy(record); + continue; + } +@@ -1502,7 +1401,7 @@ static int IMDB_Tbl2Metrics(IMDB_DataBaseMgr *mgr, IMDB_Table *table, char *buff + + if (ret < 0) { + // if build label fail, we just delete record +- HASH_deleteRecord(table->records, record); ++ DeleteRecord(table, record); + IMDB_RecordDestroy(record); + continue; + } +@@ -1516,7 +1415,7 @@ static int IMDB_Tbl2Metrics(IMDB_DataBaseMgr *mgr, IMDB_Table *table, char *buff + total += ret; + + // delete record after to string +- HASH_deleteRecord(table->records, record); ++ DeleteRecord(table, record); + IMDB_RecordDestroy(record); + + index++; +@@ -1619,7 +1518,7 @@ int IMDB_Record2Json(const IMDB_DataBaseMgr *mgr, const IMDB_Table *table, const + } + + for (int i = 0; i < meta->metricsCapacity; i++) { +- ret = snprintf(json_cursor, maxLen, ", \"%s\": \"%s\"", meta->metrics[i]->name, record->value[i]->val); ++ ret = snprintf(json_cursor, maxLen, ", \"%s\": \"%s\"", meta->metrics[i]->name, record->value[i]); + if (ret < 0) { + return -1; + } +@@ -1638,46 +1537,33 @@ int IMDB_Record2Json(const IMDB_DataBaseMgr *mgr, const IMDB_Table *table, const + return 0; + } + +-IMDB_Record *HASH_findRecord(const IMDB_Record **records, const IMDB_Record *record) ++void AddRecord(IMDB_Table *table, IMDB_Record *record) + { +- IMDB_Record *r; +- HASH_FIND(hh, *records, record->key, record->table->recordKeySize, r); +- return r; ++ DL_APPEND(table->records, record); ++ table->recordNum++; + } + +-void HASH_addRecord(IMDB_Record **records, IMDB_Record *record) ++void DeleteRecord(IMDB_Table *table, IMDB_Record *record) + { +- HASH_ADD_KEYPTR(hh, *records, record->key, record->table->recordKeySize, record); +- return; +-} +- +-void HASH_deleteRecord(IMDB_Record **records, IMDB_Record *record) +-{ +- if (records == NULL || record == NULL) { ++ if (table == NULL || record == NULL) { + return; + } + +- HASH_DEL(*records, record); +- return; ++ DL_DELETE(table->records, record); ++ table->recordNum--; + } + +-void HASH_deleteAndFreeRecords(IMDB_Record **records) ++void DeleteAndFreeRecords(IMDB_Table *table) + { +- if (records == NULL) { ++ IMDB_Record *r, *tmp; ++ ++ if (table->records == NULL) { + return; + } + +- IMDB_Record *r, *tmp; +- HASH_ITER(hh, *records, r, tmp) { +- HASH_deleteRecord(records, r); ++ DL_FOREACH_SAFE(table->records, r, tmp) { ++ DL_DELETE(table->records, r); + IMDB_RecordDestroy(r); + } +- return; +-} +- +-uint32_t HASH_recordCount(const IMDB_Record **records) +-{ +- uint32_t num = 0; +- num = (uint32_t)HASH_COUNT(*records); +- return num; +-} ++ table->recordNum = 0; ++} +\ No newline at end of file +diff --git a/src/lib/imdb/imdb.h b/src/lib/imdb/imdb.h +index e2b74a12..138ad5b0 100644 +--- a/src/lib/imdb/imdb.h ++++ b/src/lib/imdb/imdb.h +@@ -52,9 +52,6 @@ + + #define INVALID_METRIC_VALUE "(null)" + +-// NUMS OF RECORD TO STRING EVERY PERIOD +-#define DEFAULT_PERIOD_RECORD_NUM 100 +- + typedef enum { + METRIC_LOG_NULL = 0, + METRIC_LOG_PROM, +@@ -76,18 +73,14 @@ typedef struct { + char name[MAX_IMDB_METRIC_NAME_LEN]; + } IMDB_Metric; + +-typedef struct { +- char val[MAX_IMDB_METRIC_VAL_LEN]; +-} IMDB_MetricValue; +- + struct IMDB_Table_s; + typedef struct IMDB_Table_s IMDB_Table; +-typedef struct { +- char *key; ++typedef struct IMDB_Record_s { + time_t updateTime; // Unit: second +- IMDB_MetricValue **value; ++ char **value; + const IMDB_Table *table; // table that this record belongs to +- UT_hash_handle hh; ++ struct IMDB_Record_s *next; ++ struct IMDB_Record_s *prev; + } IMDB_Record; + + typedef struct { +@@ -102,8 +95,8 @@ typedef struct IMDB_Table_s { + char weighting; // 0: Highest Level(Entitlement to priority); >0: Low priority + char pad[3]; // rsvd + uint32_t recordsCapability; // Capability for records count in one table +- uint32_t recordKeySize; +- IMDB_Record **records; ++ uint32_t recordNum; ++ IMDB_Record *records; + struct ext_label_conf ext_label_conf; + } IMDB_Table; + +@@ -142,21 +135,18 @@ void IMDB_MetricDestroy(IMDB_Metric *metric); + IMDB_Meta *IMDB_MetaCreate(uint32_t capacity); + void IMDB_MetaDestroy(IMDB_Meta *meta); + ++IMDB_Record *IMDB_RecordCreate(uint32_t capacity); + IMDB_Record *IMDB_RecordCreateWithTable(const IMDB_Table *table); +-int IMDB_RecordAppendKey(IMDB_Record *record, uint32_t keyIdx, char *val); + void IMDB_RecordUpdateTime(IMDB_Record *record, time_t seconds); + void IMDB_RecordDestroy(IMDB_Record *record); + +-IMDB_Record *HASH_findRecord(const IMDB_Record **records, const IMDB_Record *record); +-void HASH_deleteRecord(IMDB_Record **records, IMDB_Record *record); +-void HASH_deleteAndFreeRecords(IMDB_Record **records); +-void HASH_addRecord(IMDB_Record **records, IMDB_Record *record); +-uint32_t HASH_recordCount(const IMDB_Record **records); ++void DeleteRecord(IMDB_Table *table, IMDB_Record *record); ++void DeleteAndFreeRecords(IMDB_Table *table); ++void AddRecord(IMDB_Table *table, IMDB_Record *record); + + IMDB_Table *IMDB_TableCreate(char *name, uint32_t capacity); + void IMDB_TableSetEntityName(IMDB_Table *table, char *entity_name); + void IMDB_TableSetMeta(IMDB_Table *table, IMDB_Meta *meta); +-int IMDB_TableSetRecordKeySize(IMDB_Table *table, uint32_t keyNum); + int IMDB_TableAddRecord(IMDB_Table *table, IMDB_Record *record); + void IMDB_TableUpdateExtLabelConf(IMDB_Table *table, struct ext_label_conf *conf); + void IMDB_TableDestroy(IMDB_Table *table); +diff --git a/src/resource/resource.c b/src/resource/resource.c +index b64b626a..e68d48d5 100644 +--- a/src/resource/resource.c ++++ b/src/resource/resource.c +@@ -314,7 +314,6 @@ static void KafkaMgrDeinit(ResourceMgr *resourceMgr) + + static int IMDBMgrTableLoad(IMDB_Table *table, Measurement *mm) + { +- int ret = 0; + uint32_t metricsCapacity = mm->fieldsNum; + IMDB_Metric *metric = NULL; + uint32_t keyNum = 0; +@@ -338,8 +337,8 @@ static int IMDBMgrTableLoad(IMDB_Table *table, Measurement *mm) + } + } + +- ret = IMDB_TableSetRecordKeySize(table, keyNum); +- if (ret != 0) { ++ if (keyNum == 0) { ++ ERROR("[RESOURCE] Meta must contain at least one key field, table: %s\n", table->name); + goto ERR; + } + +-- +2.33.0 + diff --git a/PFM_OPT-tcpprobe-merge-win-sockbuf-rtt-rate-subprobe.patch b/PFM_OPT-tcpprobe-merge-win-sockbuf-rtt-rate-subprobe.patch new file mode 100644 index 0000000..05b2efa --- /dev/null +++ b/PFM_OPT-tcpprobe-merge-win-sockbuf-rtt-rate-subprobe.patch @@ -0,0 +1,1142 @@ +From cd3fde7d2af961b296ad61901cf00bace61944ff Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Thu, 6 Feb 2025 01:40:35 +0800 +Subject: [PATCH 55/99] [PFM_OPT] tcpprobe: merge win/sockbuf/rtt/rate + subprobes to reduce ebpf event + +--- + .../ebpf.probe/src/tcpprobe/tcp_abn.bpf.c | 4 +- + .../ebpf.probe/src/tcpprobe/tcp_delay.bpf.c | 4 +- + .../ebpf.probe/src/tcpprobe/tcp_link.bpf.c | 9 +- + .../ebpf.probe/src/tcpprobe/tcp_link.h | 21 +- + .../ebpf.probe/src/tcpprobe/tcp_probe.c | 149 ++---------- + .../ebpf.probe/src/tcpprobe/tcp_rate.bpf.c | 103 -------- + .../ebpf.probe/src/tcpprobe/tcp_rtt.bpf.c | 102 -------- + .../ebpf.probe/src/tcpprobe/tcp_sockbuf.bpf.c | 114 --------- + .../ebpf.probe/src/tcpprobe/tcp_stats.bpf.c | 221 ++++++++++++++++++ + .../ebpf.probe/src/tcpprobe/tcp_tx_rx.bpf.c | 4 +- + .../ebpf.probe/src/tcpprobe/tcp_windows.bpf.c | 156 ------------- + .../ebpf.probe/src/tcpprobe/tcpprobe.c | 7 +- + .../ebpf.probe/src/tcpprobe/tcpprobe.h | 17 +- + 13 files changed, 278 insertions(+), 633 deletions(-) + delete mode 100644 src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rate.bpf.c + delete mode 100644 src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rtt.bpf.c + delete mode 100644 src/probes/extends/ebpf.probe/src/tcpprobe/tcp_sockbuf.bpf.c + create mode 100644 src/probes/extends/ebpf.probe/src/tcpprobe/tcp_stats.bpf.c + delete mode 100644 src/probes/extends/ebpf.probe/src/tcpprobe/tcp_windows.bpf.c + +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_abn.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_abn.bpf.c +index 3fe0f563..54b7be48 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_abn.bpf.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_abn.bpf.c +@@ -38,8 +38,8 @@ static __always_inline char is_tmout_abn(struct sock *sk) + + u64 ts = bpf_ktime_get_ns(); + u64 period = get_period(); +- if ((ts > sock_stats->ts_stats.abn_ts) && ((ts - sock_stats->ts_stats.abn_ts) >= period)) { +- sock_stats->ts_stats.abn_ts = ts; ++ if ((ts > sock_stats->ts.abn_ts) && ((ts - sock_stats->ts.abn_ts) >= period)) { ++ sock_stats->ts.abn_ts = ts; + return 1; + } + return 0; +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_delay.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_delay.bpf.c +index 692d7499..452ea04e 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_delay.bpf.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_delay.bpf.c +@@ -31,8 +31,8 @@ static __always_inline char is_tmout_delay(struct sock_stats_s *sock_stats) + u64 curr_ts; + + curr_ts = bpf_ktime_get_ns(); +- if (curr_ts > sock_stats->ts_stats.delay_ts + HIST_SAMPLE_PERIOD) { +- sock_stats->ts_stats.delay_ts = curr_ts; ++ if (curr_ts > sock_stats->ts.delay_ts + HIST_SAMPLE_PERIOD) { ++ sock_stats->ts.delay_ts = curr_ts; + return 1; + } + return 0; +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c +index d171068e..2a1a8c88 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c +@@ -31,9 +31,12 @@ char g_linsence[] SEC("license") = "GPL"; + + static __always_inline void report_srtt(void *ctx, struct tcp_metrics_s *metrics) + { +- metrics->report_flags |= TCP_PROBE_SRTT; +- (void)bpfbuf_output(ctx, &tcp_output, metrics, sizeof(struct tcp_metrics_s)); +- metrics->report_flags &= ~TCP_PROBE_SRTT; ++ u32 probe_flags = get_probe_flags(); ++ if (probe_flags & PROBE_RANGE_TCP_SRTT) { ++ metrics->report_flags |= TCP_PROBE_SRTT; ++ (void)bpfbuf_output(ctx, &tcp_output, metrics, sizeof(struct tcp_metrics_s)); ++ metrics->report_flags &= ~TCP_PROBE_SRTT; ++ } + } + + static __always_inline struct sock_info_s* is_exist_tcp_link(struct sock *sk, char *is_exist) +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h +index 71533b00..65d477c4 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h +@@ -94,6 +94,19 @@ static __always_inline __maybe_unused u64 get_period(void) + return period; // units from second to nanosecond + } + ++static __always_inline __maybe_unused u32 get_probe_flags(void) ++{ ++ u32 key = 0; ++ struct tcp_args_s *args; ++ ++ args = (struct tcp_args_s *)bpf_map_lookup_elem(&args_map, &key); ++ if (args) { ++ return args->probe_flags; ++ } ++ ++ return 0; ++} ++ + static __always_inline __maybe_unused char is_valid_tgid(u32 tgid) + { + struct proc_s obj = {.proc_id = tgid}; +@@ -108,12 +121,8 @@ static __always_inline __maybe_unused int create_tcp_link(struct sock *sk, struc + sock_stats.metrics.srtt_stats.syn_srtt = syn_srtt; + __builtin_memcpy(&(sock_stats.metrics.link), link, sizeof(struct tcp_link_s)); + u64 ts = bpf_ktime_get_ns(); +- sock_stats.ts_stats.abn_ts = ts; +- sock_stats.ts_stats.win_ts = ts; +- sock_stats.ts_stats.rtt_ts = ts; +- sock_stats.ts_stats.txrx_ts = ts; +- sock_stats.ts_stats.sockbuf_ts = ts; +- sock_stats.ts_stats.rate_ts = ts; ++ sock_stats.ts.abn_ts = ts; ++ sock_stats.ts.txrx_ts = ts; + + return bpf_map_update_elem(&tcp_link_map, &sk, &sock_stats, BPF_ANY); + } +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 acbb231b..ff5e5e15 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c +@@ -35,10 +35,7 @@ + #include "tcp_tracker.h" + #include "tcp_event.h" + #include "tcp_tx_rx.skel.h" +-#include "tcp_windows.skel.h" +-#include "tcp_sockbuf.skel.h" +-#include "tcp_rtt.skel.h" +-#include "tcp_rate.skel.h" ++#include "tcp_stats.skel.h" + #include "tcp_abn.skel.h" + #include "tcp_link.skel.h" + #include "tcp_delay.skel.h" +@@ -775,28 +772,28 @@ static int proc_tcp_metrics_evt(void *ctx, void *data, u32 size) + + #endif + +-static int tcp_load_probe_sockbuf(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *prog, char is_load) ++static int tcp_load_probe_stats(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *prog, char is_load) + { + int err; + struct bpf_buffer *buffer = NULL; + +- __OPEN_PROBE_WITH_OUTPUT(tcp_sockbuf, err, is_load, buffer); ++ __OPEN_PROBE_WITH_OUTPUT(tcp_stats, err, is_load, buffer); + + if (is_load) { +- __SELECT_RCV_ESTABLISHED_HOOKPOINT(tcp_sockbuf); ++ __SELECT_RCV_ESTABLISHED_HOOKPOINT(tcp_stats); + } + +- __LOAD_PROBE(tcp_sockbuf, err, is_load); ++ __LOAD_PROBE(tcp_stats, err, is_load); + + if (is_load) { +- prog->skels[prog->num].skel = tcp_sockbuf_skel; +- prog->skels[prog->num].fn = (skel_destroy_fn)tcp_sockbuf_bpf__destroy; +- prog->custom_btf_paths[prog->num] = tcp_sockbuf_open_opts.btf_custom_path; ++ prog->skels[prog->num].skel = tcp_stats_skel; ++ prog->skels[prog->num].fn = (skel_destroy_fn)tcp_stats_bpf__destroy; ++ prog->custom_btf_paths[prog->num] = tcp_stats_open_opts.btf_custom_path; + + if (prog->num == 0) { // All sub-probes share a output buffer + err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); + if (err) { +- ERROR("[TCPPROBE] Open 'tcp_sockbuf' bpf_buffer failed.\n"); ++ ERROR("[TCPPROBE] Open 'tcp_stats' bpf_buffer failed.\n"); + goto err; + } + } +@@ -807,115 +804,7 @@ static int tcp_load_probe_sockbuf(struct tcp_mng_s *tcp_mng, struct bpf_prog_s * + return 0; + err: + bpf_buffer__free(buffer); +- __UNLOAD_PROBE(tcp_sockbuf); +- return -1; +-} +- +-static int tcp_load_probe_rtt(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *prog, char is_load) +-{ +- int err; +- struct bpf_buffer *buffer = NULL; +- +- __OPEN_PROBE_WITH_OUTPUT(tcp_rtt, err, is_load, buffer); +- +- if (is_load) { +- __SELECT_RCV_ESTABLISHED_HOOKPOINT(tcp_rtt); +- } +- +- __LOAD_PROBE(tcp_rtt, err, is_load); +- +- if (is_load) { +- prog->skels[prog->num].skel = tcp_rtt_skel; +- prog->skels[prog->num].fn = (skel_destroy_fn)tcp_rtt_bpf__destroy; +- prog->custom_btf_paths[prog->num] = tcp_rtt_open_opts.btf_custom_path; +- +- if (prog->num == 0) { // All sub-probes share a output buffer +- err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); +- if (err) { +- ERROR("[TCPPROBE] Open 'tcp_rtt' bpf_buffer failed.\n"); +- goto err; +- } +- } +- prog->buffers[prog->num] = buffer; +- prog->num++; +- } +- +- return 0; +-err: +- bpf_buffer__free(buffer); +- __UNLOAD_PROBE(tcp_rtt); +- return -1; +-} +- +-static int tcp_load_probe_win(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *prog, char is_load) +-{ +- int err; +- struct bpf_buffer *buffer = NULL; +- +- __OPEN_PROBE_WITH_OUTPUT(tcp_windows, err, is_load, buffer); +- +- if (is_load) { +- __SELECT_SPACE_ADJUST_HOOKPOINT(tcp_windows); +- } +- +- __LOAD_PROBE(tcp_windows, err, is_load); +- +- if (is_load) { +- prog->skels[prog->num].skel = tcp_windows_skel; +- prog->skels[prog->num].fn = (skel_destroy_fn)tcp_windows_bpf__destroy; +- prog->custom_btf_paths[prog->num] = tcp_windows_open_opts.btf_custom_path; +- +- if (prog->num == 0) { // All sub-probes share a output buffer +- err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); +- if (err) { +- ERROR("[TCPPROBE] Open 'tcp_windows' bpf_buffer failed.\n"); +- goto err; +- } +- } +- prog->buffers[prog->num] = buffer; +- prog->num++; +- } +- +- return 0; +-err: +- bpf_buffer__free(buffer); +- __UNLOAD_PROBE(tcp_windows); +- return -1; +-} +- +-static int tcp_load_probe_rate(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *prog, char is_load) +-{ +- int err; +- struct bpf_buffer *buffer = NULL; +- +- __OPEN_PROBE_WITH_OUTPUT(tcp_rate, err, is_load, buffer); +- +- if (is_load) { +- __SELECT_SPACE_ADJUST_HOOKPOINT(tcp_rate); +- } +- +- __LOAD_PROBE(tcp_rate, err, is_load); +- +- if (is_load) { +- prog->skels[prog->num].skel = tcp_rate_skel; +- prog->skels[prog->num].fn = (skel_destroy_fn)tcp_rate_bpf__destroy; +- prog->custom_btf_paths[prog->num] = tcp_rate_open_opts.btf_custom_path; +- +- if (prog->num == 0) { // All sub-probes share a output buffer +- err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); +- if (err) { +- ERROR("[TCPPROBE] Open 'tcp_rate' bpf_buffer failed.\n"); +- goto err; +- } +- } +- prog->buffers[prog->num] = buffer; +- prog->num++; +- } +- +- return 0; +-err: +- bpf_buffer__free(buffer); +- __UNLOAD_PROBE(tcp_rate); ++ __UNLOAD_PROBE(tcp_stats); + return -1; + } + +@@ -1057,7 +946,7 @@ err: + + 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; ++ char is_load = 0, is_load_stats = 0; + struct bpf_prog_s *prog; + char is_load_txrx, is_load_abn, is_load_win, is_load_rate, is_load_rtt, is_load_sockbuf, is_load_delay, is_load_srtt; + +@@ -1071,6 +960,8 @@ int tcp_load_probe(struct tcp_mng_s *tcp_mng, struct ipc_body_s *ipc_body, struc + is_load_srtt = ipc_body->probe_range_flags & PROBE_RANGE_TCP_SRTT; + + is_load = is_load_txrx | is_load_abn | is_load_rate | is_load_win | is_load_rtt | is_load_sockbuf | is_load_delay | is_load_srtt; ++ is_load_stats = is_load_rate | is_load_win | is_load_rtt | is_load_sockbuf; ++ + if (!is_load) { + return 0; + } +@@ -1094,19 +985,7 @@ int tcp_load_probe(struct tcp_mng_s *tcp_mng, struct ipc_body_s *ipc_body, struc + goto err; + } + +- if (tcp_load_probe_rate(tcp_mng, prog, is_load_rate)) { +- goto err; +- } +- +- if (tcp_load_probe_win(tcp_mng, prog, is_load_win)) { +- goto err; +- } +- +- if (tcp_load_probe_rtt(tcp_mng, prog, is_load_rtt)) { +- goto err; +- } +- +- if (tcp_load_probe_sockbuf(tcp_mng, prog, is_load_sockbuf)) { ++ if (tcp_load_probe_stats(tcp_mng, prog, is_load_stats)) { + goto err; + } + +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rate.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rate.bpf.c +deleted file mode 100644 +index 5416f530..00000000 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rate.bpf.c ++++ /dev/null +@@ -1,103 +0,0 @@ +-/* +- * bpf code runs in the Linux kernel +- * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; either version 2 +- * of the License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +- * +- * SPDX-License-Identifier: GPL-2.0 +- */ +- +-#ifdef BPF_PROG_USER +-#undef BPF_PROG_USER +-#endif +-#define BPF_PROG_KERN +-#include +-#include "bpf.h" +-#include "tcp_link.h" +- +-char g_linsence[] SEC("license") = "GPL"; +- +-static __always_inline char is_tmout_rate(struct sock *sk) +-{ +- struct sock_stats_s *sock_stats = bpf_map_lookup_elem(&tcp_link_map, &sk); +- if (!sock_stats) { +- return 0; +- } +- +- u64 ts = bpf_ktime_get_ns(); +- u64 period = get_period(); +- if ((ts > sock_stats->ts_stats.rate_ts) && ((ts - sock_stats->ts_stats.rate_ts) >= period)) { +- sock_stats->ts_stats.rate_ts = ts; +- return 1; +- } +- return 0; +-} +- +-static __always_inline void report_rate(void *ctx, struct tcp_metrics_s *metrics) +-{ +- metrics->report_flags |= TCP_PROBE_RATE; +- (void)bpfbuf_output(ctx, &tcp_output, metrics, sizeof(struct tcp_metrics_s)); +- metrics->report_flags &= ~TCP_PROBE_RATE; +- //__builtin_memset(&(metrics->rate_stats), 0x0, sizeof(metrics->rate_stats)); +-} +- +-// when CONFIG_HZ is 1000 +-static void get_tcp_rate(struct sock *sk, struct tcp_rate* stats) +-{ +- struct inet_connection_sock *icsk = (struct inet_connection_sock *)sk; +- // For the conversion method of jiffies to ms, please refer to: +- // jiffies_to_clock_t(in kernel) and get_user_hz(in iproute2) +- stats->tcpi_rto = _(icsk->icsk_rto); // ms +- stats->tcpi_ato = _(icsk->icsk_ack.ato); // ms +-} +- +-static void tcp_rate_probe_func(void *ctx, struct sock *sk) +-{ +- struct tcp_metrics_s *metrics; +- +- // Avoid high performance costs +- if (!is_tmout_rate(sk)) { +- return; +- } +- +- metrics = get_tcp_metrics(sk); +- if (metrics) { +- get_tcp_rate(sk, &(metrics->rate_stats)); +- report_rate(ctx, metrics); +- } +-} +- +-KRAWTRACE(tcp_rcv_space_adjust, bpf_raw_tracepoint_args) +-{ +- struct sock *sk = (struct sock*)ctx->args[0]; +- tcp_rate_probe_func(ctx, sk); +- return 0; +-} +- +-KPROBE(tcp_rcv_space_adjust, pt_regs) +-{ +- struct sock *sk = (struct sock *)PT_REGS_PARM1(ctx); +- tcp_rate_probe_func(ctx, sk); +- return 0; +-} +- +-SEC("tracepoint/tcp/tcp_rcv_space_adjust") +-int bpf_trace_tcp_rcv_space_adjust_func(struct trace_event_raw_tcp_event_sk *ctx) +-{ +- struct sock *sk = (struct sock*)ctx->skaddr; +- tcp_rate_probe_func(ctx, sk); +- return 0; +-} +- +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rtt.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rtt.bpf.c +deleted file mode 100644 +index 36a8cb23..00000000 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rtt.bpf.c ++++ /dev/null +@@ -1,102 +0,0 @@ +-/* +- * bpf code runs in the Linux kernel +- * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; either version 2 +- * of the License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +- * +- * SPDX-License-Identifier: GPL-2.0 +- */ +- +-#ifdef BPF_PROG_USER +-#undef BPF_PROG_USER +-#endif +-#define BPF_PROG_KERN +-#include +-#include "bpf.h" +-#include "tcp_link.h" +- +-char g_linsence[] SEC("license") = "GPL"; +- +-static __always_inline char is_tmout_rtt(struct sock *sk) +-{ +- struct sock_stats_s *sock_stats = bpf_map_lookup_elem(&tcp_link_map, &sk); +- if (!sock_stats) { +- return 0; +- } +- +- u64 ts = bpf_ktime_get_ns(); +- u64 period = get_period(); +- if ((ts > sock_stats->ts_stats.rtt_ts) && ((ts - sock_stats->ts_stats.rtt_ts) >= period)) { +- sock_stats->ts_stats.rtt_ts = ts; +- return 1; +- } +- return 0; +-} +- +-static __always_inline void report_rtt(void *ctx, struct tcp_metrics_s *metrics) +-{ +- metrics->report_flags |= TCP_PROBE_RTT; +- +- (void)bpfbuf_output(ctx, &tcp_output, metrics, sizeof(struct tcp_metrics_s)); +- +- metrics->report_flags &= ~TCP_PROBE_RTT; +- //__builtin_memset(&(metrics->rtt_stats), 0x0, sizeof(metrics->rtt_stats)); +-} +- +-static void get_tcp_rtt(struct sock *sk, struct tcp_rtt* stats) +-{ +- u32 tmp; +- struct tcp_sock *tcp_sk = (struct tcp_sock *)sk; +- +- tmp = _(tcp_sk->srtt_us) >> 3; // srtt_us is averaged rtt << 3 in usecs +- stats->tcpi_srtt = tmp; +- +- tmp = _(tcp_sk->rcv_rtt_est.rtt_us); +- tmp = tmp >> 3; // likewise +- stats->tcpi_rcv_rtt = tmp; +- return; +-} +- +-static void tcp_rtt_probe_func(void *ctx, struct sock *sk) +-{ +- struct tcp_metrics_s *metrics; +- +- metrics = get_tcp_metrics(sk); +- if (metrics) { +- get_tcp_rtt(sk, &(metrics->rtt_stats)); +- +- // Avoid high performance costs +- if (!is_tmout_rtt(sk)) { +- return; +- } +- +- report_rtt(ctx, metrics); +- } +-} +- +-KRAWTRACE(tcp_probe, bpf_raw_tracepoint_args) +-{ +- struct sock *sk = (struct sock*)ctx->args[0]; +- tcp_rtt_probe_func(ctx, sk); +- return 0; +-} +- +-KPROBE(tcp_rcv_established, pt_regs) +-{ +- struct sock *sk = (struct sock*)PT_REGS_PARM1(ctx); +- tcp_rtt_probe_func(ctx, sk); +- return 0; +-} +- +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_sockbuf.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_sockbuf.bpf.c +deleted file mode 100644 +index d03976e8..00000000 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_sockbuf.bpf.c ++++ /dev/null +@@ -1,114 +0,0 @@ +-/* +- * bpf code runs in the Linux kernel +- * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; either version 2 +- * of the License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +- * +- * SPDX-License-Identifier: GPL-2.0 +- */ +- +-#ifdef BPF_PROG_USER +-#undef BPF_PROG_USER +-#endif +-#define BPF_PROG_KERN +-#include +-#include "bpf.h" +-#include "tcp_link.h" +- +-char g_linsence[] SEC("license") = "GPL"; +- +-static __always_inline char is_tmout_sockbuf(struct sock *sk) +-{ +- struct sock_stats_s *sock_stats = bpf_map_lookup_elem(&tcp_link_map, &sk); +- if (!sock_stats) { +- return 0; +- } +- +- u64 ts = bpf_ktime_get_ns(); +- u64 period = get_period(); +- if ((ts > sock_stats->ts_stats.sockbuf_ts) && ((ts - sock_stats->ts_stats.sockbuf_ts) >= period)) { +- sock_stats->ts_stats.sockbuf_ts = ts; +- return 1; +- } +- return 0; +-} +- +-static __always_inline void report_sockbuf(void *ctx, struct tcp_metrics_s *metrics) +-{ +- metrics->report_flags |= TCP_PROBE_SOCKBUF; +- +- (void)bpfbuf_output(ctx, &tcp_output, metrics, sizeof(struct tcp_metrics_s)); +- +- metrics->report_flags &= ~TCP_PROBE_SOCKBUF; +- //__builtin_memset(&(metrics->sockbuf_stats), 0x0, sizeof(metrics->sockbuf_stats)); +-} +- +-static void get_tcp_sock_buf(struct sock *sk, struct tcp_sockbuf* stats) +-{ +- stats->sk_rcvbuf = (int)_(sk->sk_rcvbuf); +- stats->sk_sndbuf = (int)_(sk->sk_sndbuf); +- +-} +- +-static void set_last_sockbuf_stats(struct tcp_sockbuf* stats, struct tcp_sockbuf* last_stats) +-{ +- __builtin_memcpy(last_stats, stats, sizeof(struct tcp_sockbuf)); +-} +- +-static int is_sockbuf_stats_changed(struct tcp_sockbuf* stats, struct tcp_sockbuf* last_stats) +-{ +- if (last_stats->sk_rcvbuf != stats->sk_rcvbuf) { +- return 1; +- } +- +- if (last_stats->sk_sndbuf != stats->sk_sndbuf) { +- return 1; +- } +- return 0; +-} +- +-static void tcp_sockbuf_probe_func(void *ctx, struct sock *sk) +-{ +- struct tcp_metrics_s *metrics; +- struct tcp_sockbuf last_sockbuf_stats = {0}; +- +- // Avoid high performance costs +- if (!is_tmout_sockbuf(sk)) { +- return; +- } +- +- metrics = get_tcp_metrics(sk); +- if (metrics) { +- set_last_sockbuf_stats(&(metrics->sockbuf_stats), &last_sockbuf_stats); +- get_tcp_sock_buf(sk, &(metrics->sockbuf_stats)); +- if (is_sockbuf_stats_changed(&(metrics->sockbuf_stats), &last_sockbuf_stats)) { +- report_sockbuf(ctx, metrics); +- } +- } +-} +- +-KRAWTRACE(tcp_probe, bpf_raw_tracepoint_args) +-{ +- struct sock *sk = (struct sock*)ctx->args[0]; +- tcp_sockbuf_probe_func(ctx, sk); +- return 0; +-} +- +-KPROBE(tcp_rcv_established, pt_regs) +-{ +- struct sock *sk = (struct sock*)PT_REGS_PARM1(ctx); +- tcp_sockbuf_probe_func(ctx, sk); +- return 0; +-} +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_stats.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_stats.bpf.c +new file mode 100644 +index 00000000..d89641b1 +--- /dev/null ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_stats.bpf.c +@@ -0,0 +1,221 @@ ++/* ++ * bpf code runs in the Linux kernel ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * ++ * SPDX-License-Identifier: GPL-2.0 ++ */ ++#ifdef BPF_PROG_USER ++#undef BPF_PROG_USER ++#endif ++#define BPF_PROG_KERN ++#include ++#include "bpf.h" ++#include "tcp_link.h" ++ ++char g_linsence[] SEC("license") = "GPL"; ++ ++static __always_inline char is_tmout_stats(struct sock *sk) ++{ ++ struct sock_stats_s *sock_stats = bpf_map_lookup_elem(&tcp_link_map, &sk); ++ if (!sock_stats) { ++ return 0; ++ } ++ ++ u64 ts = bpf_ktime_get_ns(); ++ u64 period = get_period(); ++ if ((ts > sock_stats->ts.stats_ts) && ((ts - sock_stats->ts.stats_ts) >= period)) { ++ sock_stats->ts.stats_ts = ts; ++ return 1; ++ } ++ return 0; ++} ++ ++static __always_inline void report_tcp_stats(void *ctx, struct tcp_metrics_s *metrics, u32 report_flags) ++{ ++ if (report_flags == 0) { ++ return; ++ } ++ ++ metrics->report_flags |= report_flags; ++ (void)bpfbuf_output(ctx, &tcp_output, metrics, sizeof(struct tcp_metrics_s)); ++ metrics->report_flags &= ~report_flags; ++} ++ ++static void get_tcp_rtt(struct sock *sk, struct tcp_rtt* stats) ++{ ++ u32 tmp; ++ struct tcp_sock *tcp_sk = (struct tcp_sock *)sk; ++ ++ tmp = _(tcp_sk->srtt_us) >> 3; // srtt_us is averaged rtt << 3 in usecs ++ stats->tcpi_srtt = tmp; ++ ++ tmp = _(tcp_sk->rcv_rtt_est.rtt_us); ++ tmp = tmp >> 3; // likewise ++ stats->tcpi_rcv_rtt = tmp; ++ return; ++} ++ ++static void get_tcp_wnd(struct sock *sk, struct tcp_windows* stats) ++{ ++ struct tcp_sock *tcp_sk = (struct tcp_sock *)sk; ++ ++ u32 write_seq = _(tcp_sk->write_seq); ++ u32 snd_nxt = _(tcp_sk->snd_nxt); ++ u32 snd_wnd = _(tcp_sk->snd_wnd); ++ u32 snd_una = _(tcp_sk->snd_una); ++ u32 rcv_wnd = _(tcp_sk->rcv_wnd); ++ ++ if (write_seq > snd_nxt) { ++ stats->tcpi_notsent_bytes = write_seq - snd_nxt; ++ } ++ ++ if (snd_nxt > snd_una) { ++ stats->tcpi_notack_bytes = snd_nxt - snd_una; ++ } ++ ++ stats->tcpi_snd_wnd = snd_wnd; ++ stats->tcpi_avl_snd_wnd = snd_una + snd_wnd - snd_nxt; ++ stats->tcpi_rcv_wnd = rcv_wnd; ++ stats->tcpi_reordering = _(tcp_sk->reordering); ++ stats->tcpi_snd_cwnd = _(tcp_sk->snd_cwnd); ++ ++ return; ++} ++ ++static void set_last_win_stats(struct tcp_windows* stats, struct tcp_windows* last_stats) ++{ ++ __builtin_memcpy(last_stats, stats, sizeof(struct tcp_windows)); ++} ++ ++static int is_win_stats_changed(struct tcp_windows* stats, struct tcp_windows* last_stats) ++{ ++ if (stats->tcpi_notsent_bytes != last_stats->tcpi_notsent_bytes) { ++ return 1; ++ } ++ if (stats->tcpi_notack_bytes != last_stats->tcpi_notack_bytes) { ++ return 1; ++ } ++ if (stats->tcpi_snd_wnd != last_stats->tcpi_snd_wnd) { ++ return 1; ++ } ++ if (stats->tcpi_avl_snd_wnd != last_stats->tcpi_avl_snd_wnd) { ++ return 1; ++ } ++ if (stats->tcpi_rcv_wnd != last_stats->tcpi_rcv_wnd) { ++ return 1; ++ } ++ if (stats->tcpi_reordering != last_stats->tcpi_reordering) { ++ return 1; ++ } ++ if (stats->tcpi_snd_cwnd != last_stats->tcpi_snd_cwnd) { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void get_tcp_sock_buf(struct sock *sk, struct tcp_sockbuf* stats) ++{ ++ stats->sk_rcvbuf = (int)_(sk->sk_rcvbuf); ++ stats->sk_sndbuf = (int)_(sk->sk_sndbuf); ++ ++} ++ ++static void set_last_sockbuf_stats(struct tcp_sockbuf* stats, struct tcp_sockbuf* last_stats) ++{ ++ __builtin_memcpy(last_stats, stats, sizeof(struct tcp_sockbuf)); ++} ++ ++static int is_sockbuf_stats_changed(struct tcp_sockbuf* stats, struct tcp_sockbuf* last_stats) ++{ ++ if (last_stats->sk_rcvbuf != stats->sk_rcvbuf) { ++ return 1; ++ } ++ ++ if (last_stats->sk_sndbuf != stats->sk_sndbuf) { ++ return 1; ++ } ++ return 0; ++} ++ ++// when CONFIG_HZ is 1000 ++static void get_tcp_rate(struct sock *sk, struct tcp_rate* stats) ++{ ++ struct inet_connection_sock *icsk = (struct inet_connection_sock *)sk; ++ // For the conversion method of jiffies to ms, please refer to: ++ // jiffies_to_clock_t(in kernel) and get_user_hz(in iproute2) ++ stats->tcpi_rto = _(icsk->icsk_rto); // ms ++ stats->tcpi_ato = _(icsk->icsk_ack.ato); // ms ++} ++ ++static void tcp_stats_probe_func(void *ctx, struct sock *sk) ++{ ++ struct tcp_metrics_s *metrics; ++ u32 report_flags = 0; ++ ++ // Avoid high performance costs ++ if (!is_tmout_stats(sk)) { ++ return; ++ } ++ ++ metrics = get_tcp_metrics(sk); ++ if (metrics) { ++ u32 probe_flags = get_probe_flags(); ++ if (probe_flags & PROBE_RANGE_TCP_RTT) { ++ get_tcp_rtt(sk, &(metrics->rtt_stats)); ++ report_flags |= TCP_PROBE_RTT; ++ } ++ ++ if (probe_flags & PROBE_RANGE_TCP_WINDOWS) { ++ struct tcp_windows last_win_stats = {0}; ++ set_last_win_stats(&(metrics->win_stats), &last_win_stats); ++ get_tcp_wnd(sk, &(metrics->win_stats)); ++ if (is_win_stats_changed(&(metrics->win_stats), &last_win_stats)) { ++ report_flags |= TCP_PROBE_WINDOWS; ++ } ++ } ++ ++ if (probe_flags & PROBE_RANGE_TCP_SOCKBUF) { ++ struct tcp_sockbuf last_sockbuf_stats = {0}; ++ set_last_sockbuf_stats(&(metrics->sockbuf_stats), &last_sockbuf_stats); ++ get_tcp_sock_buf(sk, &(metrics->sockbuf_stats)); ++ if (is_sockbuf_stats_changed(&(metrics->sockbuf_stats), &last_sockbuf_stats)) { ++ report_flags |= TCP_PROBE_SOCKBUF; ++ } ++ } ++ ++ if (probe_flags & PROBE_RANGE_TCP_RATE) { ++ get_tcp_rate(sk, &(metrics->rate_stats)); ++ report_flags |= TCP_PROBE_RATE; ++ } ++ report_tcp_stats(ctx, metrics, report_flags); ++ } ++} ++ ++KRAWTRACE(tcp_probe, bpf_raw_tracepoint_args) ++{ ++ struct sock *sk = (struct sock*)ctx->args[0]; ++ tcp_stats_probe_func(ctx, sk); ++ return 0; ++} ++ ++KPROBE(tcp_rcv_established, pt_regs) ++{ ++ struct sock *sk = (struct sock*)PT_REGS_PARM1(ctx); ++ tcp_stats_probe_func(ctx, sk); ++ return 0; ++} +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tx_rx.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tx_rx.bpf.c +index bbd28359..878ece70 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tx_rx.bpf.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tx_rx.bpf.c +@@ -38,8 +38,8 @@ static __always_inline char is_tmout_txrx(struct sock *sk) + + u64 ts = bpf_ktime_get_ns(); + u64 period = get_period(); +- if ((ts > sock_stats->ts_stats.txrx_ts) && ((ts - sock_stats->ts_stats.txrx_ts) >= period)) { +- sock_stats->ts_stats.txrx_ts = ts; ++ if ((ts > sock_stats->ts.txrx_ts) && ((ts - sock_stats->ts.txrx_ts) >= period)) { ++ sock_stats->ts.txrx_ts = ts; + return 1; + } + return 0; +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_windows.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_windows.bpf.c +deleted file mode 100644 +index 5cced8a5..00000000 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_windows.bpf.c ++++ /dev/null +@@ -1,156 +0,0 @@ +-/* +- * bpf code runs in the Linux kernel +- * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; either version 2 +- * of the License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +- * +- * SPDX-License-Identifier: GPL-2.0 +- */ +- +-#ifdef BPF_PROG_USER +-#undef BPF_PROG_USER +-#endif +-#define BPF_PROG_KERN +-#include +-#include "bpf.h" +-#include "tcp_link.h" +- +-char g_linsence[] SEC("license") = "GPL"; +- +-static __always_inline char is_tmout_win(struct sock *sk) +-{ +- struct sock_stats_s *sock_stats = bpf_map_lookup_elem(&tcp_link_map, &sk); +- if (!sock_stats) { +- return 0; +- } +- +- u64 ts = bpf_ktime_get_ns(); +- u64 period = get_period(); +- if ((ts > sock_stats->ts_stats.win_ts) && ((ts - sock_stats->ts_stats.win_ts) >= period)) { +- sock_stats->ts_stats.win_ts = ts; +- return 1; +- } +- return 0; +-} +- +-static __always_inline void report_windows(void *ctx, struct tcp_metrics_s *metrics) +-{ +- metrics->report_flags |= TCP_PROBE_WINDOWS; +- (void)bpfbuf_output(ctx, &tcp_output, metrics, sizeof(struct tcp_metrics_s)); +- +- metrics->report_flags &= ~TCP_PROBE_WINDOWS; +- //__builtin_memset(&(metrics->win_stats), 0x0, sizeof(metrics->win_stats)); +-} +- +-static void get_tcp_wnd(struct sock *sk, struct tcp_windows* stats) +-{ +- struct tcp_sock *tcp_sk = (struct tcp_sock *)sk; +- +- u32 write_seq = _(tcp_sk->write_seq); +- u32 snd_nxt = _(tcp_sk->snd_nxt); +- u32 snd_wnd = _(tcp_sk->snd_wnd); +- u32 snd_una = _(tcp_sk->snd_una); +- u32 rcv_wnd = _(tcp_sk->rcv_wnd); +- +- if (write_seq > snd_nxt) { +- stats->tcpi_notsent_bytes = write_seq - snd_nxt; +- } +- +- if (snd_nxt > snd_una) { +- stats->tcpi_notack_bytes = snd_nxt - snd_una; +- } +- +- stats->tcpi_snd_wnd = snd_wnd; +- stats->tcpi_avl_snd_wnd = snd_una + snd_wnd - snd_nxt; +- stats->tcpi_rcv_wnd = rcv_wnd; +- stats->tcpi_reordering = _(tcp_sk->reordering); +- stats->tcpi_snd_cwnd = _(tcp_sk->snd_cwnd); +- +- return; +-} +- +-static void set_last_win_stats(struct tcp_windows* stats, struct tcp_windows* last_stats) +-{ +- __builtin_memcpy(last_stats, stats, sizeof(struct tcp_windows)); +-} +- +-static int is_win_stats_changed(struct tcp_windows* stats, struct tcp_windows* last_stats) +-{ +- if (stats->tcpi_notsent_bytes != last_stats->tcpi_notsent_bytes) { +- return 1; +- } +- if (stats->tcpi_notack_bytes != last_stats->tcpi_notack_bytes) { +- return 1; +- } +- if (stats->tcpi_snd_wnd != last_stats->tcpi_snd_wnd) { +- return 1; +- } +- if (stats->tcpi_avl_snd_wnd != last_stats->tcpi_avl_snd_wnd) { +- return 1; +- } +- if (stats->tcpi_rcv_wnd != last_stats->tcpi_rcv_wnd) { +- return 1; +- } +- if (stats->tcpi_reordering != last_stats->tcpi_reordering) { +- return 1; +- } +- if (stats->tcpi_snd_cwnd != last_stats->tcpi_snd_cwnd) { +- return 1; +- } +- +- return 0; +-} +- +-static void tcp_wnd_probe_func(void *ctx, struct sock *sk) +-{ +- struct tcp_metrics_s *metrics; +- struct tcp_windows last_win_stats = {0}; +- +- // Avoid high performance costs +- if (!is_tmout_win(sk)) { +- return; +- } +- +- metrics = get_tcp_metrics(sk); +- if (metrics) { +- set_last_win_stats(&(metrics->win_stats), &last_win_stats); +- get_tcp_wnd(sk, &(metrics->win_stats)); +- if (is_win_stats_changed(&(metrics->win_stats), &last_win_stats)) { +- report_windows(ctx, metrics); +- } +- } +-} +- +-KRAWTRACE(tcp_rcv_space_adjust, bpf_raw_tracepoint_args) +-{ +- struct sock *sk = (struct sock*)ctx->args[0]; +- tcp_wnd_probe_func(ctx, sk); +- return 0; +-} +- +-KPROBE(tcp_rcv_space_adjust, pt_regs) +-{ +- struct sock *sk = (struct sock *)PT_REGS_PARM1(ctx); +- tcp_wnd_probe_func(ctx, sk); +- return 0; +-} +- +-SEC("tracepoint/tcp/tcp_rcv_space_adjust") +-int bpf_trace_tcp_rcv_space_adjust_func(struct trace_event_raw_tcp_event_sk *ctx) +-{ +- struct sock *sk = (struct sock*)ctx->skaddr; +- tcp_wnd_probe_func(ctx, sk); +- return 0; +-} +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c +index 49dd2e43..7784ac8d 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c +@@ -261,12 +261,13 @@ static void clean_tcp_pin_map() + } + } + +-static void tcp_load_args(int args_fd, struct probe_params* params) ++static void tcp_load_args(int args_fd, struct ipc_body_s *ipc_body) + { + u32 key = 0; + struct tcp_args_s args = {0}; + +- args.sample_period = MS2NS(params->sample_period); ++ args.probe_flags = ipc_body->probe_range_flags; ++ args.sample_period = MS2NS(ipc_body->probe_param.sample_period); + + (void)bpf_map_update_elem(args_fd, &key, &args, BPF_ANY); + } +@@ -344,7 +345,7 @@ int main(int argc, char **argv) + } + + if (ipc_body.probe_flags & IPC_FLAGS_PARAMS_CHG || ipc_body.probe_flags == 0) { +- tcp_load_args(args_map_fd, &ipc_body.probe_param); ++ tcp_load_args(args_map_fd, &ipc_body); + } + + if (ipc_body.probe_flags & IPC_FLAGS_SNOOPER_CHG || ipc_body.probe_flags == 0) { +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.h b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.h +index 7478abf9..db517911 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.h ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.h +@@ -27,6 +27,15 @@ + #define TCP_LINK_TCP_PATH "/sys/fs/bpf/gala-gopher/__tcplink_tcp" + #define TCP_LINK_FD_PATH "/sys/fs/bpf/gala-gopher/__tcplink_tcp_fd" + ++#define PROBE_RANGE_TCP_ABNORMAL 0x00000001 ++#define PROBE_RANGE_TCP_WINDOWS 0x00000002 ++#define PROBE_RANGE_TCP_RTT 0x00000004 ++#define PROBE_RANGE_TCP_STATS 0x00000008 ++#define PROBE_RANGE_TCP_SOCKBUF 0x00000010 ++#define PROBE_RANGE_TCP_RATE 0x00000020 ++#define PROBE_RANGE_TCP_SRTT 0x00000040 ++#define PROBE_RANGE_TCP_DELAY 0x00000080 ++ + #define TCP_PROBE_ABN (u32)(1) + #define TCP_PROBE_WINDOWS (u32)(1 << 1) + #define TCP_PROBE_RTT (u32)(1 << 2) +@@ -188,20 +197,18 @@ struct sock_info_s { + + struct tcp_ts { + u64 abn_ts; +- u64 win_ts; +- u64 rtt_ts; + u64 txrx_ts; +- u64 sockbuf_ts; +- u64 rate_ts; ++ u64 stats_ts; + u64 delay_ts; + }; + + struct sock_stats_s { +- struct tcp_ts ts_stats; ++ struct tcp_ts ts; + struct tcp_metrics_s metrics; + }; + + struct tcp_args_s { ++ __u32 probe_flags; + __u64 sample_period; // Sampling period, unit ns + }; + +-- +2.33.0 + diff --git a/PFM_OPT-tcpprobe-reduce-the-scanning-times-of-tracke.patch b/PFM_OPT-tcpprobe-reduce-the-scanning-times-of-tracke.patch new file mode 100644 index 0000000..f3c1023 --- /dev/null +++ b/PFM_OPT-tcpprobe-reduce-the-scanning-times-of-tracke.patch @@ -0,0 +1,151 @@ +From 98b9e639245afc6ace7a91af715a113b4d2d7ad4 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Wed, 5 Feb 2025 14:53:14 +0800 +Subject: [PATCH 51/99] [PFM_OPT] tcpprobe: reduce the scanning times of + trackers per second + +--- + .../ebpf.probe/src/tcpprobe/tcp_probe.c | 34 +++++++++++++++---- + .../ebpf.probe/src/tcpprobe/tcp_tracker.h | 1 + + .../ebpf.probe/src/tcpprobe/tcpprobe.c | 20 +++++++++-- + 3 files changed, 45 insertions(+), 10 deletions(-) + +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 acbb231b..c3720409 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c +@@ -598,9 +598,8 @@ static char is_flow_tracker_inactive(struct tcp_flow_tracker_s *tracker) + return 0; + } + +-static char is_track_tmout(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker) ++static char is_track_tmout(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker, time_t current) + { +- time_t current = (time_t)time(NULL); + time_t secs; + + if (current > tracker->last_report) { +@@ -618,9 +617,8 @@ static char is_track_tmout(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *trac + return 0; + } + +-static char is_flow_track_tmout(struct tcp_mng_s *tcp_mng, struct tcp_flow_tracker_s *tracker) ++static char is_flow_track_tmout(struct tcp_mng_s *tcp_mng, struct tcp_flow_tracker_s *tracker, time_t current) + { +- time_t current = (time_t)time(NULL); + time_t secs; + + if (current > tracker->last_report) { +@@ -1154,16 +1152,27 @@ void aging_tcp_flow_trackers(struct tcp_mng_s *tcp_mng) + } + } + +-#define __STEP (200) ++#define __STEP (5000) + void scan_tcp_trackers(struct tcp_mng_s *tcp_mng) + { + int count = 0; + struct tcp_tracker_s *tracker, *tmp; ++ time_t current = (time_t)time(NULL); ++ int max_step = max(__STEP, (tcp_mng->tcp_tracker_count / tcp_mng->ipc_body.probe_param.period) + 1); + + H_ITER(tcp_mng->trackers, tracker, tmp) { +- if ((count < __STEP) && is_track_tmout(tcp_mng, tracker)) { ++ if (count < max_step) { ++ if (!is_track_tmout(tcp_mng, tracker, current)) { ++ break; ++ } + count += output_tcp_metrics(tcp_mng, tracker); ++ ++ // Put it to the tail to avoid extra scan in next loop, this can improve some performance. ++ H_DEL(tcp_mng->trackers, tracker); ++ H_ADD_KEYPTR(tcp_mng->trackers, &tracker->id, sizeof(struct tcp_tracker_id_s), tracker); ++ continue; + } ++ break; + } + } + +@@ -1171,10 +1180,21 @@ void scan_tcp_flow_trackers(struct tcp_mng_s *tcp_mng) + { + int count = 0; + struct tcp_flow_tracker_s *tracker, *tmp; ++ time_t current = (time_t)time(NULL); ++ int max_step = max(__STEP, (tcp_mng->tcp_flow_tracker_count / tcp_mng->ipc_body.probe_param.period) + 1); + + H_ITER(tcp_mng->flow_trackers, tracker, tmp) { +- if ((count < __STEP) && is_flow_track_tmout(tcp_mng, tracker)) { ++ if (count < max_step) { ++ if (!is_flow_track_tmout(tcp_mng, tracker, current)) { ++ break; ++ } + count += output_tcp_flow_metrics(tcp_mng, tracker); ++ ++ // Put it to the tail to avoid extra scan in next loop, this can improve some performance. ++ H_DEL(tcp_mng->flow_trackers, tracker); ++ H_ADD_KEYPTR(tcp_mng->flow_trackers, &tracker->id, sizeof(struct tcp_flow_tracker_id_s), tracker); ++ continue; + } ++ break; + } + } +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tracker.h b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tracker.h +index 0f870783..11365e2d 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tracker.h ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tracker.h +@@ -265,6 +265,7 @@ struct tcp_mng_s { + u32 tcp_tracker_count; + u32 tcp_flow_tracker_count; + time_t last_aging; ++ time_t last_scanning; + struct ipc_body_s ipc_body; + struct bpf_prog_s *tcp_progs; + struct toa_socket_s *toa_socks; +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c +index 49dd2e43..2e8ecf98 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c +@@ -165,6 +165,18 @@ static void reload_tc_bpf(struct ipc_body_s* ipc_body) + } + } + ++static char is_need_scanning(struct tcp_mng_s *tcp_mng) ++{ ++ time_t current = (time_t)time(NULL); ++ ++ if (current > tcp_mng->last_scanning) { ++ tcp_mng->last_scanning = current; ++ return 1; ++ } ++ ++ return 0; ++} ++ + static char is_need_aging(struct tcp_mng_s *tcp_mng) + { + #define __AGING_TIME_SECS (5 * 60) // 5min +@@ -237,7 +249,7 @@ static int load_established_tcps_mngt(int proc_obj_map_fd, int tcp_fd_map_fd) + } + last_load_time = now; + } else { +- if (now > last_load_time + UNLOAD_TCP_FD_PROBE) { ++ if (is_tcp_fd_probe_loaded() && (now > last_load_time + UNLOAD_TCP_FD_PROBE)) { + tcp_unload_fd_probe(); + empty_tcp_fd_map(tcp_fd_map_fd); + } +@@ -384,8 +396,10 @@ int main(int argc, char **argv) + sleep(1); + } + +- scan_tcp_trackers(tcp_mng); +- scan_tcp_flow_trackers(tcp_mng); ++ if (is_need_scanning(tcp_mng)) { ++ scan_tcp_trackers(tcp_mng); ++ scan_tcp_flow_trackers(tcp_mng); ++ } + + // Aging all invalid TCP trackers trackers. + if (is_need_aging(tcp_mng)) { +-- +2.33.0 + diff --git a/Refactor-to-reduce-memory-usage-of-metric-record.patch b/Refactor-to-reduce-memory-usage-of-metric-record.patch new file mode 100644 index 0000000..6b41467 --- /dev/null +++ b/Refactor-to-reduce-memory-usage-of-metric-record.patch @@ -0,0 +1,794 @@ +From fd4bc5e155b7b84db99fbaa2b56c1d634bf9419d Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Mon, 6 Jan 2025 16:16:04 +0800 +Subject: [PATCH 42/99] Refactor to reduce memory usage of metric record + +--- + src/lib/imdb/imdb.c | 253 ++++++++++++++++++++--------------- + src/lib/imdb/imdb.h | 30 +++-- + src/lib/probe/extend_probe.c | 42 ++---- + src/resource/resource.c | 25 ++-- + 4 files changed, 184 insertions(+), 166 deletions(-) + +diff --git a/src/lib/imdb/imdb.c b/src/lib/imdb/imdb.c +index 0d152185..23309627 100644 +--- a/src/lib/imdb/imdb.c ++++ b/src/lib/imdb/imdb.c +@@ -61,15 +61,33 @@ IMDB_Metric *IMDB_MetricCreate(char *name, char *description, char *type) + return metric; + } + +-int IMDB_MetricSetValue(IMDB_Metric *metric, char *val) ++static IMDB_MetricValue *IMDB_MetricValueCreate(const char *val) + { +- int ret = 0; +- ret = snprintf(metric->val, MAX_IMDB_METRIC_VAL_LEN, "%s", val); +- if (ret < 0) { +- return -1; ++ int ret; ++ IMDB_MetricValue *value; ++ ++ value = (IMDB_MetricValue *)malloc(sizeof(IMDB_MetricValue)); ++ if (value == NULL) { ++ return NULL; + } + +- return 0; ++ ret = snprintf(value->val, sizeof(value->val), "%s", val); ++ if (ret < 0 || ret >= sizeof(value->val)) { ++ free(value); ++ return NULL; ++ } ++ ++ return value; ++} ++ ++static void IMDB_MetricValueDestroy(IMDB_MetricValue *value) ++{ ++ if (value == NULL) { ++ return; ++ } ++ ++ free(value); ++ return; + } + + void IMDB_MetricDestroy(IMDB_Metric *metric) +@@ -82,6 +100,45 @@ void IMDB_MetricDestroy(IMDB_Metric *metric) + return; + } + ++IMDB_Meta *IMDB_MetaCreate(uint32_t capacity) ++{ ++ IMDB_Meta *meta = NULL; ++ if (capacity == 0) { ++ return NULL; ++ } ++ meta = (IMDB_Meta *)malloc(sizeof(IMDB_Meta)); ++ if (meta == NULL) { ++ return NULL; ++ } ++ memset(meta, 0, sizeof(IMDB_Meta)); ++ ++ meta->metrics = (IMDB_Metric **)malloc(sizeof(IMDB_Metric *) * capacity); ++ if (meta->metrics == NULL) { ++ free(meta); ++ return NULL; ++ } ++ memset(meta->metrics, 0, sizeof(IMDB_Metric *) * capacity); ++ ++ meta->metricsCapacity = capacity; ++ return meta; ++} ++ ++void IMDB_MetaDestroy(IMDB_Meta *meta) ++{ ++ if (meta == NULL) { ++ return; ++ } ++ ++ if (meta->metrics != NULL) { ++ for (int i = 0; i < meta->metricsCapacity; i++) { ++ IMDB_MetricDestroy(meta->metrics[i]); ++ } ++ free(meta->metrics); ++ } ++ free(meta); ++ return; ++} ++ + IMDB_Record *IMDB_RecordCreate(uint32_t capacity) + { + IMDB_Record *record = NULL; +@@ -94,19 +151,19 @@ IMDB_Record *IMDB_RecordCreate(uint32_t capacity) + } + memset(record, 0, sizeof(IMDB_Record)); + +- record->metrics = (IMDB_Metric **)malloc(sizeof(IMDB_Metric *) * capacity); +- if (record->metrics == NULL) { ++ record->value = (IMDB_MetricValue **)malloc(sizeof(IMDB_MetricValue *) * capacity); ++ if (record->value == NULL) { + free(record); + return NULL; + } +- memset(record->metrics, 0, sizeof(IMDB_Metric *) * capacity); +- +- record->metricsCapacity = capacity; ++ memset(record->value, 0, sizeof(IMDB_MetricValue *) * capacity); + return record; + } + +-IMDB_Record *IMDB_RecordCreateWithKey(uint32_t capacity, uint32_t keySize) ++IMDB_Record *IMDB_RecordCreateWithTable(const IMDB_Table *table) + { ++ uint32_t keySize = table->recordKeySize; ++ uint32_t capacity = table->meta->metricsCapacity; + if (keySize == 0) { + return NULL; + } +@@ -120,29 +177,18 @@ IMDB_Record *IMDB_RecordCreateWithKey(uint32_t capacity, uint32_t keySize) + return NULL; + } + memset(record->key, 0, sizeof(char) * keySize); +- record->keySize = keySize; ++ record->table = table; + } + + return record; + } + +-int IMDB_RecordAddMetric(IMDB_Record *record, IMDB_Metric *metric) +-{ +- if (record->metricsNum == record->metricsCapacity) { +- return -1; +- } +- +- record->metrics[record->metricsNum] = metric; +- record->metricsNum++; +- return 0; +-} +- + int IMDB_RecordAppendKey(IMDB_Record *record, uint32_t keyIdx, char *val) + { + int ret = 0; + uint32_t offset = keyIdx * MAX_IMDB_METRIC_VAL_LEN; + +- if (offset + MAX_IMDB_METRIC_VAL_LEN > record->keySize) { ++ if (offset + MAX_IMDB_METRIC_VAL_LEN > record->table->recordKeySize) { + return -1; + } + +@@ -169,11 +215,11 @@ void IMDB_RecordDestroy(IMDB_Record *record) + free(record->key); + } + +- if (record->metrics != NULL) { +- for (int i = 0; i < record->metricsNum; i++) { +- IMDB_MetricDestroy(record->metrics[i]); ++ if (record->value != NULL) { ++ for (int i = 0; i < record->table->meta->metricsCapacity; i++) { ++ IMDB_MetricValueDestroy(record->value[i]); + } +- free(record->metrics); ++ free(record->value); + } + free(record); + return; +@@ -212,10 +258,9 @@ void IMDB_TableSetEntityName(IMDB_Table *table, char *entity_name) + return; + } + +-int IMDB_TableSetMeta(IMDB_Table *table, IMDB_Record *metaRecord) ++void IMDB_TableSetMeta(IMDB_Table *table, IMDB_Meta *meta) + { +- table->meta = metaRecord; +- return 0; ++ table->meta = meta; + } + + int IMDB_TableSetRecordKeySize(IMDB_Table *table, uint32_t keyNum) +@@ -274,7 +319,7 @@ void IMDB_TableDestroy(IMDB_Table *table) + } + + if (table->meta != NULL) { +- IMDB_RecordDestroy(table->meta); ++ IMDB_MetaDestroy(table->meta); + } + + destroy_ext_label_conf_locked(&table->ext_label_conf); +@@ -530,16 +575,14 @@ IMDB_Table *IMDB_DataBaseMgrFindTable(IMDB_DataBaseMgr *mgr, const char *tableNa + } + + static int IMDB_DataBaseMgrParseContent(IMDB_DataBaseMgr *mgr, IMDB_Table *table, +- IMDB_Record *record, const char *content, char needKey) ++ IMDB_Record *record, const char *content) + { + int ret = 0; +- IMDB_Metric *metric; +- ++ IMDB_MetricValue *value; + char *token, *buffer; + char delim[] = "|"; + char *buffer_head = NULL; +- +- uint32_t keyIdx = 0, index = 0; ++ uint32_t keyIdx = 0, index = 0, metricsCapacity = table->meta->metricsCapacity; + + buffer = strdup(content); + if (buffer == NULL) { +@@ -550,8 +593,9 @@ static int IMDB_DataBaseMgrParseContent(IMDB_DataBaseMgr *mgr, IMDB_Table *table + // start analyse record string + strsep(&buffer, delim); + for (token = strsep(&buffer, delim); token != NULL; token = strsep(&buffer, delim)) { +- if (strcmp(token, "\n") == 0) ++ if (strcmp(token, "\n") == 0){ + break; ++ } + + if (strcmp(token, "") == 0) { + if (index == 0) { +@@ -563,7 +607,7 @@ static int IMDB_DataBaseMgrParseContent(IMDB_DataBaseMgr *mgr, IMDB_Table *table + } + + // if index > metricNum, it's invalid +- if (index >= table->meta->metricsNum) { ++ if (index >= metricsCapacity) { + if (strcmp(token, INVALID_METRIC_VALUE) != 0) { + ERROR("[IMDB] Raw ingress data exceeds metrics num of table(%s)\n", table->name); + goto ERR; +@@ -571,31 +615,14 @@ static int IMDB_DataBaseMgrParseContent(IMDB_DataBaseMgr *mgr, IMDB_Table *table + break; + } + +- // fill record by the rest substrings +- metric = IMDB_MetricCreate(table->meta->metrics[index]->name, +- table->meta->metrics[index]->description, +- table->meta->metrics[index]->type); +- if (metric == NULL) { +- ERROR("[IMDB] Can't create metrics(%s, %s).\n", table->name, +- table->meta->metrics[index]->name); +- goto ERR; +- } +- +- ret = IMDB_MetricSetValue(metric, token); +- if (ret != 0) { +- ERROR("[IMDB] Set metrics value failed.(%s, %s).\n", table->name, metric->name); +- IMDB_MetricDestroy(metric); ++ value = IMDB_MetricValueCreate(token); ++ if (value == NULL) { ++ ERROR("[IMDB] Set metrics value failed.(%s, %s).\n", table->name, table->meta->metrics[index]->name); + goto ERR; + } + +- ret = IMDB_RecordAddMetric(record, metric); +- if (ret != 0) { +- ERROR("[IMDB] Add metrics failed.(%s, %s).\n", table->name, metric->name); +- IMDB_MetricDestroy(metric); +- goto ERR; +- } +- +- if (needKey && strcmp(METRIC_TYPE_KEY, table->meta->metrics[index]->type) == 0) { ++ record->value[index] = value; ++ if (strcmp(METRIC_TYPE_KEY, table->meta->metrics[index]->type) == 0) { + ret = IMDB_RecordAppendKey(record, keyIdx, token); + if (ret < 0) { + ERROR("[IMDB] Can not set record key.\n"); +@@ -607,7 +634,7 @@ static int IMDB_DataBaseMgrParseContent(IMDB_DataBaseMgr *mgr, IMDB_Table *table + index += 1; + } + +- if (index != table->meta->metricsNum) { ++ if (index != metricsCapacity) { + ERROR("[IMDB] Raw ingress data does not reach metrics num of table(%s)\n", table->name); + goto ERR; + } +@@ -631,12 +658,12 @@ IMDB_Record* IMDB_DataBaseMgrCreateRec(IMDB_DataBaseMgr *mgr, IMDB_Table *table, + int ret = 0; + IMDB_Record *record; + +- record = IMDB_RecordCreateWithKey(table->meta->metricsCapacity, table->recordKeySize); ++ record = IMDB_RecordCreateWithTable(table); + if (record == NULL) { + goto ERR; + } + +- ret = IMDB_DataBaseMgrParseContent(mgr, table, record, content, 1); ++ ret = IMDB_DataBaseMgrParseContent(mgr, table, record, content); + if (ret != 0) { + goto ERR; + } +@@ -650,10 +677,7 @@ IMDB_Record* IMDB_DataBaseMgrCreateRec(IMDB_DataBaseMgr *mgr, IMDB_Table *table, + + ERR: + pthread_rwlock_unlock(&mgr->rwlock); +- if (record != NULL) { +- IMDB_RecordDestroy(record); +- } +- ++ IMDB_RecordDestroy(record); + return NULL; + } + +@@ -723,7 +747,8 @@ static int IMDB_BuildMetrics(const char *entity_name, + } + + // eg: gala_gopher_tcp_link_rx_bytes(label) 128 1586960586000000000 +-static int IMDB_BuildPrometheusMetrics(const IMDB_Metric *metric, char *buffer, uint32_t maxLen, ++static int IMDB_BuildPrometheusMetrics(const IMDB_MetricValue *value, const char *metric_name, ++ char *buffer, uint32_t maxLen, + const char *entity_name, const char *labels) + { + int ret; +@@ -733,7 +758,7 @@ static int IMDB_BuildPrometheusMetrics(const IMDB_Metric *metric, char *buffer, + time_t now; + const char *fmt = "{%s} %s %lld\n"; // Metrics##labels MetricsVal timestamp + +- ret = IMDB_BuildMetrics(entity_name, metric->name, buffer, (uint32_t)size); ++ ret = IMDB_BuildMetrics(entity_name, metric_name, buffer, (uint32_t)size); + if (ret < 0) { + return ret; + } +@@ -742,7 +767,7 @@ static int IMDB_BuildPrometheusMetrics(const IMDB_Metric *metric, char *buffer, + p += len; + size -= len; + (void)time(&now); +- ret = __snprintf(&p, size, &size, fmt, labels, metric->val, now * THOUSAND); ++ ret = __snprintf(&p, size, &size, fmt, labels, value->val, now * THOUSAND); + if (ret < 0) { + return ret; + } +@@ -964,30 +989,31 @@ static int IMDB_BuildLabels(IMDB_DataBaseMgr *mgr, + int i; + const char *first_fmt = type_json ? "\"%s\":\"%s\"" : "%s=\"%s\""; + const char *fmt = type_json ? ",\"%s\":\"%s\"" : ",%s=\"%s\""; ++ IMDB_Meta *meta = table->meta; + +- for (i = 0; i < record->metricsNum; i++) { +- if (MetricNameIsTgid(record->metrics[i]) == 1) { ++ for (i = 0; i < meta->metricsCapacity; i++) { ++ if (MetricNameIsTgid(meta->metrics[i]) == 1) { + tgid_idx = i; + } +- if (MetricNameIsContainerId(record->metrics[i])) { ++ if (MetricNameIsContainerId(meta->metrics[i])) { + con_id_idx = i; + } + +- if (MetricTypeIsLabel(record->metrics[i]) == 0) { ++ if (MetricTypeIsLabel(meta->metrics[i]) == 0) { + continue; + } + +- if (!strcmp(record->metrics[i]->val, INVALID_METRIC_VALUE)) { ++ if (!strcmp(record->value[i]->val, INVALID_METRIC_VALUE)) { + // ignore label whose value is (null) + continue; + } + + if (first_flag) { + ret = __snprintf(&p, size, &size, first_fmt, +- record->metrics[i]->name, record->metrics[i]->val); ++ meta->metrics[i]->name, record->value[i]->val); + } else { + ret = __snprintf(&p, size, &size, fmt, +- record->metrics[i]->name, record->metrics[i]->val); ++ meta->metrics[i]->name, record->value[i]->val); + } + if (ret < 0) { + return IMDB_BUFFER_FULL; +@@ -1002,7 +1028,7 @@ static int IMDB_BuildLabels(IMDB_DataBaseMgr *mgr, + + // Append 'COMM, Container and POD' label for ALL process-level metrics. + if (tgid_idx >= 0) { +- tgid_str = (char *)(record->metrics[tgid_idx]->val); ++ tgid_str = (char *)(record->value[tgid_idx]->val); + ret = append_proc_level_labels(tgid_str, &p, &size, mgr, table, type_json); + if (ret < 0) { + DEBUG("[IMDB] Failed to append process-level labels(tgid=%s, ret=%d)\n", tgid_str, ret); +@@ -1011,7 +1037,7 @@ static int IMDB_BuildLabels(IMDB_DataBaseMgr *mgr, + } + + if (con_id_idx >= 0) { +- con_id = (char *)(record->metrics[con_id_idx]->val); ++ con_id = (char *)(record->value[con_id_idx]->val); + ret = append_container_level_labels(con_id, &p, &size, mgr, table, 1, type_json); + if (ret < 0) { + DEBUG("[IMDB] Failed to append container-level labels(container_id=%s, ret=%d)\n", con_id, ret); +@@ -1119,8 +1145,9 @@ static int append_label_histo_le_inf(strbuf_t *labels_buf) + return append_label(labels_buf, __HISTO_LABEL_NAME, __HISTO_LABEL_VAL_INF); + } + +-static int IMDB_BuildPrometheusHistoMetrics(const IMDB_Metric *metric, char *buffer, uint32_t maxLen, +- const char *entity_name, strbuf_t *labels_buf) ++static int IMDB_BuildPrometheusHistoMetrics(const IMDB_MetricValue *value, const char *metric_name, ++ char *buffer, uint32_t maxLen, ++ const char *entity_name, strbuf_t *labels_buf) + { + int ret; + size_t len; +@@ -1135,15 +1162,15 @@ static int IMDB_BuildPrometheusHistoMetrics(const IMDB_Metric *metric, char *buf + u64 sum = 0, bkt_sum = 0; + int i; + +- ret = deserialize_histo(metric->val, &bkt, &bkt_sz, &bkt_sum); ++ ret = deserialize_histo(value->val, &bkt, &bkt_sz, &bkt_sum); + if (ret) { +- ERROR("[IMDB] Failed to deserialize histogram metric %s\n", metric->name); ++ ERROR("[IMDB] Failed to deserialize histogram metric %s\n", metric_name); + return -1; + } + + (void)time(&now); + for (i = 0; i < bkt_sz + 1; i++) { +- ret = IMDB_BuildMetrics(entity_name, metric->name, p, (uint32_t)size); ++ ret = IMDB_BuildMetrics(entity_name, metric_name, p, (uint32_t)size); + if (ret < 0) { + free(bkt); + return ret; +@@ -1187,6 +1214,7 @@ static int IMDB_Rec2Prometheus(IMDB_DataBaseMgr *mgr, IMDB_Record *record, IMDB_ + char *curBuffer = buffer; + uint32_t curMaxLen = maxLen; + strbuf_t labels_buf; ++ IMDB_Meta *meta = table->meta; + + char labels[MAX_LABELS_BUFFER_SIZE] = {0}; + ret = IMDB_BuildLabels(mgr, record, table, labels, MAX_LABELS_BUFFER_SIZE, 0); +@@ -1198,21 +1226,21 @@ static int IMDB_Rec2Prometheus(IMDB_DataBaseMgr *mgr, IMDB_Record *record, IMDB_ + labels_buf.len = strlen(labels); + labels_buf.size = MAX_LABELS_BUFFER_SIZE; + +- for (int i = 0; i < record->metricsNum; i++) { +- ret = MetricTypeSatisfyPrometheus(record->metrics[i]); ++ for (int i = 0; i < meta->metricsCapacity; i++) { ++ ret = MetricTypeSatisfyPrometheus(meta->metrics[i]); + if (ret != 0) { + continue; + } + +- if (!strcmp(record->metrics[i]->val, INVALID_METRIC_VALUE)) { ++ if (!strcmp(record->value[i]->val, INVALID_METRIC_VALUE)) { + // Do not report metric whose value is (null) + continue; + } + +- if (strcmp(record->metrics[i]->type, "histogram") == 0) { +- ret = IMDB_BuildPrometheusHistoMetrics(record->metrics[i], curBuffer, curMaxLen, table->entity_name, &labels_buf); ++ if (strcmp(meta->metrics[i]->type, "histogram") == 0) { ++ ret = IMDB_BuildPrometheusHistoMetrics(record->value[i], meta->metrics[i]->name, curBuffer, curMaxLen, table->entity_name, &labels_buf); + } else { +- ret = IMDB_BuildPrometheusMetrics(record->metrics[i], curBuffer, curMaxLen, table->entity_name, labels); ++ ret = IMDB_BuildPrometheusMetrics(record->value[i], meta->metrics[i]->name, curBuffer, curMaxLen, table->entity_name, labels); + } + + if (ret < 0) { +@@ -1227,7 +1255,7 @@ static int IMDB_Rec2Prometheus(IMDB_DataBaseMgr *mgr, IMDB_Record *record, IMDB_ + return total; + } + +-static int IMDB_BuildJsonHistosBkt(const IMDB_Metric *metric, char **buffer, int *maxLen) ++static int IMDB_BuildJsonHistosBkt(const IMDB_MetricValue *value, const char *metric_name, char **buffer, int *maxLen) + { + int ret, i; + char buf[INT_LEN]; +@@ -1236,9 +1264,9 @@ static int IMDB_BuildJsonHistosBkt(const IMDB_Metric *metric, char **buffer, int + u64 count = 0, bkt_sum = 0; + char first_flag = 1; + +- ret = deserialize_histo(metric->val, &bkt, &bkt_sz, &bkt_sum); ++ ret = deserialize_histo(value->val, &bkt, &bkt_sz, &bkt_sum); + if (ret) { +- ERROR("[IMDB] Failed to deserialize histogram metric %s\n", metric->name); ++ ERROR("[IMDB] Failed to deserialize histogram metric %s\n", metric_name); + return IMDB_BUILD_ERR; + } + +@@ -1271,32 +1299,33 @@ static int IMDB_BuildJsonHistos(IMDB_DataBaseMgr *mgr, IMDB_Record *record, IMDB + { + int ret = 0; + char first_flag = 1; ++ IMDB_Meta *meta = table->meta; + + ret = __snprintf(buffer, *maxLen, maxLen, "%s", "\"histos\":{"); + if (ret) { + return IMDB_BUFFER_FULL; + } + +- for (int i = 0; i < record->metricsNum; i++) { +- if (strcmp(record->metrics[i]->type, "histogram") != 0) { ++ for (int i = 0; i < meta->metricsCapacity; i++) { ++ if (strcmp(meta->metrics[i]->type, "histogram") != 0) { + continue; + } + +- if (strcmp(record->metrics[i]->val, INVALID_METRIC_VALUE) == 0) { ++ if (strcmp(record->value[i]->val, INVALID_METRIC_VALUE) == 0) { + continue; + } + + if (first_flag) { + ret = __snprintf(buffer, *maxLen, maxLen, "\"%s\":{", +- record->metrics[i]->name); ++ meta->metrics[i]->name); + } else { + ret = __snprintf(buffer, *maxLen, maxLen, ",\"%s\":{", +- record->metrics[i]->name); ++ meta->metrics[i]->name); + } + if (ret < 0) { + return IMDB_BUFFER_FULL; + } +- ret = IMDB_BuildJsonHistosBkt(record->metrics[i], buffer, maxLen); ++ ret = IMDB_BuildJsonHistosBkt(record->value[i], meta->metrics[i]->name, buffer, maxLen); + if (ret < 0) { + return ret; + } +@@ -1317,34 +1346,35 @@ static int IMDB_BuildJsonMetrics(IMDB_DataBaseMgr *mgr, IMDB_Record *record, IMD + { + int ret = 0; + char first_flag = 1; ++ IMDB_Meta *meta = table->meta; + + ret = __snprintf(buffer, *maxLen, maxLen, "%s", "\"metrics\":{"); + if (ret) { + return IMDB_BUFFER_FULL; + } + +- for (int i = 0; i < record->metricsNum; i++) { +- ret = MetricTypeSatisfyPrometheus(record->metrics[i]); ++ for (int i = 0; i < meta->metricsCapacity; i++) { ++ ret = MetricTypeSatisfyPrometheus(meta->metrics[i]); + if (ret != 0) { + continue; + } + +- if (!strcmp(record->metrics[i]->val, INVALID_METRIC_VALUE)) { ++ if (!strcmp(record->value[i]->val, INVALID_METRIC_VALUE)) { + // Do not report metric whose value is (null) + continue; + } + +- if (strcmp(record->metrics[i]->type, "histogram") == 0) { ++ if (strcmp(meta->metrics[i]->type, "histogram") == 0) { + // skip histogram type metrics + continue; + } + + if (first_flag) { + ret = __snprintf(buffer, *maxLen, maxLen, "\"%s\":\"%s\"", +- record->metrics[i]->name, record->metrics[i]->val); ++ meta->metrics[i]->name, record->value[i]->val); + } else { + ret = __snprintf(buffer, *maxLen, maxLen, ",\"%s\":\"%s\"", +- record->metrics[i]->name, record->metrics[i]->val); ++ meta->metrics[i]->name, record->value[i]->val); + } + if (ret < 0) { + return IMDB_BUFFER_FULL; +@@ -1552,6 +1582,7 @@ int IMDB_Record2Json(const IMDB_DataBaseMgr *mgr, const IMDB_Table *table, const + int ret = 0; + char *json_cursor = jsonStr; + int maxLen = (int)jsonStrLen; ++ IMDB_Meta *meta = table->meta; + + time_t now; + (void)time(&now); +@@ -1587,8 +1618,8 @@ int IMDB_Record2Json(const IMDB_DataBaseMgr *mgr, const IMDB_Table *table, const + return -1; + } + +- for (int i = 0; i < record->metricsNum; i++) { +- ret = snprintf(json_cursor, maxLen, ", \"%s\": \"%s\"", record->metrics[i]->name, record->metrics[i]->val); ++ for (int i = 0; i < meta->metricsCapacity; i++) { ++ ret = snprintf(json_cursor, maxLen, ", \"%s\": \"%s\"", meta->metrics[i]->name, record->value[i]->val); + if (ret < 0) { + return -1; + } +@@ -1610,13 +1641,13 @@ int IMDB_Record2Json(const IMDB_DataBaseMgr *mgr, const IMDB_Table *table, const + IMDB_Record *HASH_findRecord(const IMDB_Record **records, const IMDB_Record *record) + { + IMDB_Record *r; +- HASH_FIND(hh, *records, record->key, record->keySize, r); ++ HASH_FIND(hh, *records, record->key, record->table->recordKeySize, r); + return r; + } + + void HASH_addRecord(IMDB_Record **records, IMDB_Record *record) + { +- HASH_ADD_KEYPTR(hh, *records, record->key, record->keySize, record); ++ HASH_ADD_KEYPTR(hh, *records, record->key, record->table->recordKeySize, record); + return; + } + +diff --git a/src/lib/imdb/imdb.h b/src/lib/imdb/imdb.h +index 564768e2..e2b74a12 100644 +--- a/src/lib/imdb/imdb.h ++++ b/src/lib/imdb/imdb.h +@@ -74,23 +74,31 @@ typedef struct { + // MetricType type; + char type[MAX_IMDB_METRIC_TYPE_LEN]; + char name[MAX_IMDB_METRIC_NAME_LEN]; +- char val[MAX_IMDB_METRIC_VAL_LEN]; + } IMDB_Metric; + + typedef struct { +- uint32_t keySize; ++ char val[MAX_IMDB_METRIC_VAL_LEN]; ++} IMDB_MetricValue; ++ ++struct IMDB_Table_s; ++typedef struct IMDB_Table_s IMDB_Table; ++typedef struct { + char *key; + time_t updateTime; // Unit: second +- uint32_t metricsCapacity; // Capability for metrics count in one record +- uint32_t metricsNum; +- IMDB_Metric **metrics; ++ IMDB_MetricValue **value; ++ const IMDB_Table *table; // table that this record belongs to + UT_hash_handle hh; + } IMDB_Record; + + typedef struct { ++ uint32_t metricsCapacity; // Capability for metrics count in one record ++ IMDB_Metric **metrics; ++} IMDB_Meta; ++ ++typedef struct IMDB_Table_s { + char name[MAX_IMDB_TABLE_NAME_LEN]; + char entity_name[MAX_IMDB_TABLE_NAME_LEN]; +- IMDB_Record *meta; ++ IMDB_Meta *meta; + char weighting; // 0: Highest Level(Entitlement to priority); >0: Low priority + char pad[3]; // rsvd + uint32_t recordsCapability; // Capability for records count in one table +@@ -129,12 +137,12 @@ typedef struct { + } IMDB_DataBaseMgr; + + IMDB_Metric *IMDB_MetricCreate(char *name, char *description, char *type); +-int IMDB_MetricSetValue(IMDB_Metric *metric, char *val); + void IMDB_MetricDestroy(IMDB_Metric *metric); + +-IMDB_Record *IMDB_RecordCreate(uint32_t capacity); +-IMDB_Record *IMDB_RecordCreateWithKey(uint32_t capacity, uint32_t keySize); +-int IMDB_RecordAddMetric(IMDB_Record *record, IMDB_Metric *metric); ++IMDB_Meta *IMDB_MetaCreate(uint32_t capacity); ++void IMDB_MetaDestroy(IMDB_Meta *meta); ++ ++IMDB_Record *IMDB_RecordCreateWithTable(const IMDB_Table *table); + int IMDB_RecordAppendKey(IMDB_Record *record, uint32_t keyIdx, char *val); + void IMDB_RecordUpdateTime(IMDB_Record *record, time_t seconds); + void IMDB_RecordDestroy(IMDB_Record *record); +@@ -147,7 +155,7 @@ uint32_t HASH_recordCount(const IMDB_Record **records); + + IMDB_Table *IMDB_TableCreate(char *name, uint32_t capacity); + void IMDB_TableSetEntityName(IMDB_Table *table, char *entity_name); +-int IMDB_TableSetMeta(IMDB_Table *table, IMDB_Record *metaRecord); ++void IMDB_TableSetMeta(IMDB_Table *table, IMDB_Meta *meta); + int IMDB_TableSetRecordKeySize(IMDB_Table *table, uint32_t keyNum); + int IMDB_TableAddRecord(IMDB_Table *table, IMDB_Record *record); + void IMDB_TableUpdateExtLabelConf(IMDB_Table *table, struct ext_label_conf *conf); +diff --git a/src/lib/probe/extend_probe.c b/src/lib/probe/extend_probe.c +index a51832b6..aeb04744 100644 +--- a/src/lib/probe/extend_probe.c ++++ b/src/lib/probe/extend_probe.c +@@ -46,35 +46,18 @@ repeat: + static void sendOutputToIngresss(struct probe_s *probe, char *buffer, uint32_t bufferSize) + { + int ret = 0; +- char *dataStr = NULL; +- uint32_t index = 0; +- +- for (int i = 0; i < bufferSize; i++) { +- if (dataStr == NULL) { +- dataStr = (char *)malloc(MAX_DATA_STR_LEN); +- if (dataStr == NULL) { +- break; +- } +- // memset(dataStr, 0, sizeof(MAX_DATA_STR_LEN)); +- index = 0; +- } ++ char *dataStr; + +- if (buffer[i] == '\n') { +- dataStr[index] = '\0'; +- ret = FifoPut(probe->fifo, (void *)dataStr); +- if (ret != 0) { +- ERROR("[E-PROBE %s] fifo put failed.\n", probe->name); +- (void)free(dataStr); +- dataStr = NULL; +- break; +- } ++ buffer[bufferSize - 1] = '\0'; ++ dataStr = strdup(buffer); ++ if (dataStr == NULL) { ++ return; ++ } + +- // reset dataStr +- dataStr = NULL; +- } else { +- dataStr[index] = buffer[i]; +- index++; +- } ++ ret = FifoPut(probe->fifo, (void *)dataStr); ++ if (ret) { ++ ERROR("[E-PROBE %s] fifo put failed.\n", probe->name); ++ (void)free(dataStr); + } + + return; +@@ -118,8 +101,9 @@ static void parseExtendProbeOutput(struct probe_s *probe, FILE *f) + continue; + } + +- if ((bufferSize = strlen(buffer)) >= MAX_DATA_STR_LEN) { +- ERROR("[E-PROBE %s] stdout buf(len:%u) is too long\n", probe->name, bufferSize); ++ bufferSize = strlen(buffer); ++ if (bufferSize == 0 || buffer[bufferSize - 1] != '\n') { ++ ERROR("[E-PROBE %s] stdout buf is empty or exceeds max length %lu\n", probe->name, bufferSize); + continue; + } + +diff --git a/src/resource/resource.c b/src/resource/resource.c +index 9866141e..57c0b84d 100644 +--- a/src/resource/resource.c ++++ b/src/resource/resource.c +@@ -314,45 +314,40 @@ static void KafkaMgrDeinit(ResourceMgr *resourceMgr) + static int IMDBMgrTableLoad(IMDB_Table *table, Measurement *mm) + { + int ret = 0; +- IMDB_Record *meta = IMDB_RecordCreate(mm->fieldsNum); ++ uint32_t metricsCapacity = mm->fieldsNum; ++ IMDB_Metric *metric = NULL; ++ uint32_t keyNum = 0; ++ IMDB_Meta *meta; ++ ++ meta = IMDB_MetaCreate(metricsCapacity); + if (meta == NULL) { + return -1; + } + +- IMDB_Metric *metric = NULL; +- uint32_t keyNum = 0; +- for (int i = 0; i < mm->fieldsNum; i++) { ++ for (int i = 0; i < metricsCapacity; i++) { + metric = IMDB_MetricCreate(mm->fields[i].name, mm->fields[i].description, mm->fields[i].type); + if (metric == NULL) { + goto ERR; + } + +- ret = IMDB_RecordAddMetric(meta, metric); +- if (ret != 0) { +- goto ERR; +- } +- ++ meta->metrics[i] = metric; + metric = NULL; + if (strcmp(mm->fields[i].type, METRIC_TYPE_KEY) == 0) { + keyNum++; + } + } + +- ret = IMDB_TableSetMeta(table, meta); +- if (ret != 0) { +- goto ERR; +- } +- + ret = IMDB_TableSetRecordKeySize(table, keyNum); + if (ret != 0) { + goto ERR; + } + ++ IMDB_TableSetMeta(table, meta); + IMDB_TableSetEntityName(table, mm->entity); + + return 0; + ERR: +- IMDB_RecordDestroy(meta); ++ IMDB_MetaDestroy(meta); + IMDB_MetricDestroy(metric); + return -1; + } +-- +2.33.0 + diff --git a/Simplify-the-error-handling-process-by-using-goto-st.patch b/Simplify-the-error-handling-process-by-using-goto-st.patch new file mode 100644 index 0000000..54ffd0c --- /dev/null +++ b/Simplify-the-error-handling-process-by-using-goto-st.patch @@ -0,0 +1,122 @@ +From 71a66e372d172b7cfb87d381ae9dbd428329fdad Mon Sep 17 00:00:00 2001 +From: Susanooo +Date: Tue, 12 Nov 2024 03:14:04 +0000 +Subject: [PATCH 10/99] Simplify the error handling process by using goto + statements + +Signed-off-by: Susanooo +--- + src/lib/kafka/kafka.c | 34 ++++++++++++++-------------------- + 1 file changed, 14 insertions(+), 20 deletions(-) + +diff --git a/src/lib/kafka/kafka.c b/src/lib/kafka/kafka.c +index da4dc00d..ecac7871 100644 +--- a/src/lib/kafka/kafka.c ++++ b/src/lib/kafka/kafka.c +@@ -41,8 +41,7 @@ KafkaMgr *KafkaMgrCreate(const ConfigMgr *configMgr, const char *topic_type) + + if (topic_type == NULL) { + ERROR("input kafka topic_type NULL, please input valid topic type.\n"); +- free(mgr); +- return NULL; ++ goto err; + } + if (strcmp(topic_type, "kafka_topic") == 0) { + /* metric topic */ +@@ -55,8 +54,7 @@ KafkaMgr *KafkaMgrCreate(const ConfigMgr *configMgr, const char *topic_type) + (void)snprintf(mgr->kafkaTopic, sizeof(mgr->kafkaTopic), "%s", configMgr->eventOutConfig->kafka_topic); + } else { + ERROR("input kafka topic_type(%s) error.\n", topic_type); +- free(mgr); +- return NULL; ++ goto err; + } + + (void)snprintf(mgr->kafkaBroker, sizeof(mgr->kafkaBroker), "%s", configMgr->kafkaConfig->broker); +@@ -71,8 +69,7 @@ KafkaMgr *KafkaMgrCreate(const ConfigMgr *configMgr, const char *topic_type) + ret = rd_kafka_conf_set(mgr->conf, "bootstrap.servers", mgr->kafkaBroker, errstr, sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) { + ERROR("set rdkafka bootstrap.servers failed(%s).\n", errstr); +- free(mgr); +- return NULL; ++ goto err; + } + rd_kafka_conf_set_dr_msg_cb(mgr->conf, dr_msg_cb); + +@@ -81,16 +78,14 @@ KafkaMgr *KafkaMgrCreate(const ConfigMgr *configMgr, const char *topic_type) + ret = rd_kafka_conf_set(mgr->conf, "batch.num.messages", batchNumMessages, errstr, sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) { + ERROR("set rdkafka batch.num.messages failed(%s).\n", errstr); +- free(mgr); +- return NULL; ++ goto err; + } + rd_kafka_conf_set_dr_msg_cb(mgr->conf, dr_msg_cb); + + ret = rd_kafka_conf_set(mgr->conf, "compression.codec", mgr->compressionCodec, errstr, sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) { + ERROR("set rdkafka compression.codec failed(%s).\n", errstr); +- free(mgr); +- return NULL; ++ goto err; + } + rd_kafka_conf_set_dr_msg_cb(mgr->conf, dr_msg_cb); + +@@ -99,8 +94,7 @@ KafkaMgr *KafkaMgrCreate(const ConfigMgr *configMgr, const char *topic_type) + ret = rd_kafka_conf_set(mgr->conf, "queue.buffering.max.messages", queueBufferingMaxMessages, errstr, sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) { + ERROR("set rdkafka queue.buffering.max.messages failed(%s).\n", errstr); +- free(mgr); +- return NULL; ++ goto err; + } + rd_kafka_conf_set_dr_msg_cb(mgr->conf, dr_msg_cb); + +@@ -109,8 +103,7 @@ KafkaMgr *KafkaMgrCreate(const ConfigMgr *configMgr, const char *topic_type) + ret = rd_kafka_conf_set(mgr->conf, "queue.buffering.max.kbytes", queueBufferingMaxKbytes, errstr, sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) { + ERROR("set rdkafka queue.buffering.max.kbytes failed(%s).\n", errstr); +- free(mgr); +- return NULL; ++ goto err; + } + rd_kafka_conf_set_dr_msg_cb(mgr->conf, dr_msg_cb); + +@@ -119,27 +112,28 @@ KafkaMgr *KafkaMgrCreate(const ConfigMgr *configMgr, const char *topic_type) + ret = rd_kafka_conf_set(mgr->conf, "queue.buffering.max.ms", queueBufferingMaxMs, errstr, sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) { + ERROR("set rdkafka queue.buffering.max.ms failed(%s).\n", errstr); +- free(mgr); +- return NULL; ++ goto err; + } + rd_kafka_conf_set_dr_msg_cb(mgr->conf, dr_msg_cb); + + mgr->rk = rd_kafka_new(RD_KAFKA_PRODUCER, mgr->conf, errstr, sizeof(errstr)); + if (mgr->rk == NULL) { + ERROR("failed to create new kafka_producer, errstr(%s).\n", errstr); +- free(mgr); +- return NULL; ++ goto err; + } + + mgr->rkt = rd_kafka_topic_new(mgr->rk, mgr->kafkaTopic, NULL); + if (mgr->rkt == NULL) { + ERROR("failed to create new kafka topic object.\n"); + rd_kafka_destroy(mgr->rk); +- free(mgr); +- return NULL; ++ goto err; + } + + return mgr; ++ ++err: ++ free(mgr); ++ return NULL; + } + + void KafkaMgrDestroy(KafkaMgr *mgr) +-- +2.33.0 + diff --git a/add-error-log-of-mismatch-between-metric-data-and-me.patch b/add-error-log-of-mismatch-between-metric-data-and-me.patch new file mode 100644 index 0000000..14df848 --- /dev/null +++ b/add-error-log-of-mismatch-between-metric-data-and-me.patch @@ -0,0 +1,90 @@ +From 2614efa15e9d121bc0ba4e8b810070b19722fa7b Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Mon, 11 Nov 2024 19:16:37 +0800 +Subject: [PATCH 08/99] add error log of mismatch between metric data and meta + file + +--- + src/ingress/ingress.c | 7 +++++-- + src/lib/imdb/imdb.c | 16 +++++++++++++++- + 2 files changed, 20 insertions(+), 3 deletions(-) + +diff --git a/src/ingress/ingress.c b/src/ingress/ingress.c +index f074fe76..cc9de06f 100644 +--- a/src/ingress/ingress.c ++++ b/src/ingress/ingress.c +@@ -270,8 +270,12 @@ static int ProcessMetricData(IngressMgr *mgr, const char *content, const char *t + int ret = 0; + + table = IMDB_DataBaseMgrFindTable(mgr->imdbMgr, tblName); +- if (table == NULL || table->recordKeySize == 0) ++ if (table == NULL) { ++ ERROR("[INGRESS] failed to find tablename \"%s\" of metrics reported by probe %s\n", ++ tblName, probe ? probe->name : "unknown"); + return -1; ++ } ++ + if (probe) { + IMDB_TableUpdateExtLabelConf(table, &probe->ext_label_conf); + } +@@ -280,7 +284,6 @@ static int ProcessMetricData(IngressMgr *mgr, const char *content, const char *t + // save metric to imdb + rec = IMDB_DataBaseMgrCreateRec(mgr->imdbMgr, table, content); + if (rec == NULL) { +- ERROR("[INGRESS] insert metric data into imdb failed.\n"); + return -1; + } + } +diff --git a/src/lib/imdb/imdb.c b/src/lib/imdb/imdb.c +index 6fec6cf6..2d00e306 100644 +--- a/src/lib/imdb/imdb.c ++++ b/src/lib/imdb/imdb.c +@@ -220,6 +220,10 @@ int IMDB_TableSetMeta(IMDB_Table *table, IMDB_Record *metaRecord) + + int IMDB_TableSetRecordKeySize(IMDB_Table *table, uint32_t keyNum) + { ++ if (keyNum == 0) { ++ ERROR("[IMDB] Meta must contain at least one key field, table: %s\n", table->name); ++ return -1; ++ } + table->recordKeySize = keyNum * MAX_IMDB_METRIC_VAL_LEN; + return 0; + } +@@ -560,8 +564,13 @@ static int IMDB_DataBaseMgrParseContent(IMDB_DataBaseMgr *mgr, IMDB_Table *table + + // if index > metricNum, it's invalid + if (index >= table->meta->metricsNum) { ++ if (strcmp(token, INVALID_METRIC_VALUE) != 0) { ++ ERROR("[IMDB] Raw ingress data exceeds metrics num of table(%s)\n", table->name); ++ goto ERR; ++ } + break; + } ++ + // fill record by the rest substrings + metric = IMDB_MetricCreate(table->meta->metrics[index]->name, + table->meta->metrics[index]->description, +@@ -597,6 +606,12 @@ static int IMDB_DataBaseMgrParseContent(IMDB_DataBaseMgr *mgr, IMDB_Table *table + + index += 1; + } ++ ++ if (index != table->meta->metricsNum) { ++ ERROR("[IMDB] Raw ingress data does not reach metrics num of table(%s)\n", table->name); ++ goto ERR; ++ } ++ + if (buffer_head != NULL) { + free(buffer_head); + } +@@ -623,7 +638,6 @@ IMDB_Record* IMDB_DataBaseMgrCreateRec(IMDB_DataBaseMgr *mgr, IMDB_Table *table, + + ret = IMDB_DataBaseMgrParseContent(mgr, table, record, content, 1); + if (ret != 0) { +- ERROR("[IMDB]Raw ingress data to rec failed(CREATEREC).\n"); + goto ERR; + } + ret = IMDB_TableAddRecord(table, record); +-- +2.33.0 + diff --git a/add-log-level-info-to-logs-of-main-process.patch b/add-log-level-info-to-logs-of-main-process.patch new file mode 100644 index 0000000..665483c --- /dev/null +++ b/add-log-level-info-to-logs-of-main-process.patch @@ -0,0 +1,191 @@ +From baf5b6f3a27f2e6c014d73fda274339fca77adab Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Sat, 7 Dec 2024 17:06:41 +0800 +Subject: [PATCH 29/99] add log level info to logs of main process + +--- + src/common/common.h | 1 + + src/common/logs.c | 42 ++++++++++++++++++++++++------------------ + src/common/logs.h | 5 +++-- + 3 files changed, 28 insertions(+), 20 deletions(-) + +diff --git a/src/common/common.h b/src/common/common.h +index 8f7d58a3..235ec860 100644 +--- a/src/common/common.h ++++ b/src/common/common.h +@@ -108,6 +108,7 @@ static inline int __debug_printf(const char *format, ...) + #define WARN warn_logs + #define ERROR error_logs + ++#define LOG_LEVEL_STR_LEN 10 + #define DEBUG_STR "[DEBUG]" + #define INFO_STR "[INFO]" + #define WARN_STR "[WARN]" +diff --git a/src/common/logs.c b/src/common/logs.c +index f4b00150..75621c34 100644 +--- a/src/common/logs.c ++++ b/src/common/logs.c +@@ -20,6 +20,7 @@ + + static struct log_mgr_s *local = NULL; + static pthread_mutex_t metric_mutex = PTHREAD_MUTEX_INITIALIZER; ++static char logger_level_str[LOGGER_MAX][LOG_LEVEL_STR_LEN] = {DEBUG_STR, INFO_STR, WARN_STR, ERROR_STR}; + + static int mkdirp(const char *path, mode_t mode) + { +@@ -519,8 +520,6 @@ static void set_debug_log_level(char *logLevel) + g_debug_logger.level = LOGGER_WARN; + } else if (strcmp(logLevel, "error") == 0) { + g_debug_logger.level = LOGGER_ERROR; +- } else if (strcmp(logLevel, "fatal") == 0) { +- g_debug_logger.level = LOGGER_FATAL; + } + } + +@@ -814,12 +813,13 @@ static int get_log_time(struct tm *t) + return 0; + } + +-#define MAX_PATTERN_STR 200 ++#define MAX_PATTERN_STR 50 + #define TM_YEAR_BEGIN 1900 + #define TM_YEAR_SHOW_OFFSET 2000 +-static void log_with_date(struct logger *logger, const char *detail) ++static void log_with_date(struct logger *logger, const char *detail, enum logger_level_t level) + { +- if ((detail == NULL) || (!logger) || (!logger->pattern) || (strlen(logger->pattern) == 0)) { ++ if (detail == NULL || level >= LOGGER_MAX || ++ logger == NULL || logger->pattern == NULL || strlen(logger->pattern) == 0) { + return; + } + struct tm t; +@@ -831,7 +831,7 @@ static void log_with_date(struct logger *logger, const char *detail) + + int ret = snprintf(msg, __DEBUG_LEN + MAX_PATTERN_STR, logger->pattern, + t.tm_mon + 1, t.tm_mday, t.tm_year + TM_YEAR_BEGIN - TM_YEAR_SHOW_OFFSET, +- t.tm_hour, t.tm_min, t.tm_sec, detail); ++ t.tm_hour, t.tm_min, t.tm_sec, logger_level_str[level], detail); + if (ret == -1) { + return; + } +@@ -840,24 +840,30 @@ static void log_with_date(struct logger *logger, const char *detail) + + void convert_output_to_log(char *buffer, int bufferSize) + { ++ size_t offset = 0; ++ char *content = buffer; ++ enum logger_level_t logger_level = LOGGER_DEBUG; + if (buffer == NULL || bufferSize < 1) { + return; + } + + buffer[bufferSize - 1] = 0; +- enum logger_level_t logger_level; ++ + if (strncmp(buffer, INFO_STR, sizeof(INFO_STR) - 1) == 0) { + logger_level = LOGGER_INFO; ++ offset = sizeof(INFO_STR) - 1; + } else if (strncmp(buffer, WARN_STR, sizeof(WARN_STR) - 1) == 0) { + logger_level = LOGGER_WARN; ++ offset = sizeof(WARN_STR) - 1; + } else if (strncmp(buffer, ERROR_STR, sizeof(ERROR_STR) - 1) == 0) { + logger_level = LOGGER_ERROR; +- } else { +- logger_level = LOGGER_DEBUG; ++ offset = sizeof(ERROR_STR) - 1; + } ++ ++ content += offset; + if (g_debug_logger.level <= logger_level) { + reappend_debug_logger(local); +- log_with_date(&g_debug_logger, buffer); ++ log_with_date(&g_debug_logger, content, logger_level); + } + } + +@@ -867,12 +873,12 @@ void debug_logs(const char* format, ...) + + __FMT_LOGS(buf, __DEBUG_LEN, format); + if (!local) { +- printf("%s: %s", DEBUG_STR, buf); ++ printf("%s%s", DEBUG_STR, buf); + (void)fflush(stdout); + } else { + if (g_debug_logger.level <= LOGGER_DEBUG) { + reappend_debug_logger(local); +- log_with_date(&g_debug_logger, buf); ++ log_with_date(&g_debug_logger, buf, LOGGER_DEBUG); + } + } + } +@@ -884,12 +890,12 @@ void info_logs(const char* format, ...) + + __FMT_LOGS(buf, __DEBUG_LEN, format); + if (!local) { +- printf("%s: %s", INFO_STR, buf); ++ printf("%s%s", INFO_STR, buf); + (void)fflush(stdout); + } else { + if (g_debug_logger.level <= LOGGER_INFO) { + reappend_debug_logger(local); +- log_with_date(&g_debug_logger, buf); ++ log_with_date(&g_debug_logger, buf, LOGGER_INFO); + } + } + } +@@ -900,12 +906,12 @@ void warn_logs(const char* format, ...) + + __FMT_LOGS(buf, __DEBUG_LEN, format); + if (!local) { +- printf("%s: %s", WARN_STR, buf); ++ printf("%s%s", WARN_STR, buf); + (void)fflush(stdout); + } else { + if (g_debug_logger.level <= LOGGER_WARN) { + reappend_debug_logger(local); +- log_with_date(&g_debug_logger, buf); ++ log_with_date(&g_debug_logger, buf, LOGGER_WARN); + } + } + } +@@ -915,12 +921,12 @@ void error_logs(const char *format, ...) { + + __FMT_LOGS(buf, __DEBUG_LEN, format); + if (!local) { +- printf("%s: %s", ERROR_STR, buf); ++ printf("%s%s", ERROR_STR, buf); + (void)fflush(stdout); + } else { + if (g_debug_logger.level <= LOGGER_ERROR) { + reappend_debug_logger(local); +- log_with_date(&g_debug_logger, buf); ++ log_with_date(&g_debug_logger, buf, LOGGER_ERROR); + } + } + } +diff --git a/src/common/logs.h b/src/common/logs.h +index 80a2ca7f..4feab4d9 100644 +--- a/src/common/logs.h ++++ b/src/common/logs.h +@@ -45,7 +45,7 @@ + + #define LOGS_SWITCH_ON 1 + #define PATTERN_META_LOGGER_STR "%s\n" // "%m%n" +-#define PATTERN_DEBUG_LOGGER_STR "%02d/%02d/%02d %02d:%02d:%02d - %s" // "%D{%m/%d/%y %H:%M:%S} - %m" ++#define PATTERN_DEBUG_LOGGER_STR "%02d/%02d/%02d %02d:%02d:%02d - %s %s" // "%D{%m/%d/%y %H:%M:%S} - %m" + #define PATTERN_METRICS_LOGGER_STR "%s" // "%m" + #define PATTERN_EVENT_LOGGER_STR "%s\n" // "%m%n" + +@@ -85,7 +85,8 @@ enum logger_level_t { + LOGGER_INFO, + LOGGER_WARN, + LOGGER_ERROR, +- LOGGER_FATAL ++ ++ LOGGER_MAX + }; + + struct logger { +-- +2.33.0 + diff --git a/avoid-conflict-of-kprobe-between-tcp_link-and-tcp_rx.patch b/avoid-conflict-of-kprobe-between-tcp_link-and-tcp_rx.patch new file mode 100644 index 0000000..6b7991e --- /dev/null +++ b/avoid-conflict-of-kprobe-between-tcp_link-and-tcp_rx.patch @@ -0,0 +1,54 @@ +From 830d685c06f3d220e1c2f47ecd6220a38c7c9f7c Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Fri, 16 May 2025 23:41:46 +0800 +Subject: [PATCH 73/99] avoid conflict of kprobe between tcp_link and tcp_rx_rx + +--- + src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c | 7 ------- + src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tx_rx.bpf.c | 2 +- + 2 files changed, 1 insertion(+), 8 deletions(-) + +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 c91e46a8..bfe6e17c 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c +@@ -970,11 +970,9 @@ int tcp_load_probe(struct tcp_mng_s *tcp_mng, struct ipc_body_s *ipc_body, struc + return -1; + } + +-#if defined(__x86_64__) || defined(__riscv) + if (tcp_load_probe_link(tcp_mng, &(ipc_body->probe_param), prog)) { + goto err; + } +-#endif + + if (tcp_load_probe_txrx(tcp_mng, prog, is_load_txrx)) { + goto err; +@@ -991,11 +989,6 @@ int tcp_load_probe(struct tcp_mng_s *tcp_mng, struct ipc_body_s *ipc_body, struc + if (tcp_load_probe_delay(tcp_mng, prog, is_load_delay)) { + goto err; + } +-#ifdef __aarch64__ +- if (tcp_load_probe_link(tcp_mng, &(ipc_body->probe_param), prog)) { +- goto err; +- } +-#endif + + INFO("[TCPPROBE]: Successfully load ebpf prog.\n"); + *new_prog = prog; +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tx_rx.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tx_rx.bpf.c +index 878ece70..c0bc0fd8 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tx_rx.bpf.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tx_rx.bpf.c +@@ -73,7 +73,7 @@ static void get_tcp_tx_rx_segs(struct sock *sk, struct tcp_tx_rx* stats) + stats->segs_out = _(tcp_sk->segs_out); + } + +-KPROBE(tcp_sendmsg, pt_regs) ++KPROBE(tcp_sendmsg_locked, pt_regs) + { + struct tcp_metrics_s *metrics; + struct sock *sk = (struct sock *)PT_REGS_PARM1(ctx); +-- +2.33.0 + diff --git a/bugfix-path-parsing-error-when-gala-gopher-running-i.patch b/bugfix-path-parsing-error-when-gala-gopher-running-i.patch new file mode 100644 index 0000000..ce4f58f --- /dev/null +++ b/bugfix-path-parsing-error-when-gala-gopher-running-i.patch @@ -0,0 +1,151 @@ +From 1067065b01391cd19bd36defa9a94f35cf9ad4e7 Mon Sep 17 00:00:00 2001 +From: wo_cow +Date: Mon, 13 Jan 2025 16:23:53 +0800 +Subject: [PATCH 44/99] bugfix: path parsing error when gala-gopher running in + container + +--- + src/common/gopher_elf.c | 7 +----- + src/common/util.c | 10 ++------ + src/lib/probe/probe_params_parser.c | 25 ++++++++++++++++--- + .../extends/ebpf.probe/src/lib/elf_reader.c | 15 ++--------- + 4 files changed, 26 insertions(+), 31 deletions(-) + +diff --git a/src/common/gopher_elf.c b/src/common/gopher_elf.c +index bae4c7b5..f644eef4 100644 +--- a/src/common/gopher_elf.c ++++ b/src/common/gopher_elf.c +@@ -53,12 +53,7 @@ static int open_elf_fd(int fd, Elf **elf_bin) + + static int open_elf(const char *elf_file, Elf **elf_bin, int *elf_fd) + { +- char elf_path[PATH_MAX]; +- if (realpath(elf_file, elf_path) == NULL) { +- goto err; +- } +- +- *elf_fd = open(elf_path, O_RDONLY); ++ *elf_fd = open(elf_file, O_RDONLY); + if (*elf_fd < 0) { + goto err; + } +diff --git a/src/common/util.c b/src/common/util.c +index 69d08f83..cc3bb9a4 100644 +--- a/src/common/util.c ++++ b/src/common/util.c +@@ -284,17 +284,11 @@ int get_system_hostname(char *buf, unsigned int size) + + int copy_file(const char *dst_file, const char *src_file) + { +- char dst_path[PATH_MAX]; +- char src_path[PATH_MAX]; +- if (realpath(dst_file, dst_path) == NULL || realpath(src_file, src_path) == NULL) { +- return -1; +- } +- +- FILE *fp1 = fopen(dst_path, "w"); ++ FILE *fp1 = fopen(dst_file, "w"); + if (fp1 == NULL) { + return -1; + } +- FILE *fp2 = fopen(src_path, "r"); ++ FILE *fp2 = fopen(src_file, "r"); + if(fp2 == NULL) { + fclose(fp1); + return -1; +diff --git a/src/lib/probe/probe_params_parser.c b/src/lib/probe/probe_params_parser.c +index 18c3963c..0023f891 100644 +--- a/src/lib/probe/probe_params_parser.c ++++ b/src/lib/probe/probe_params_parser.c +@@ -235,7 +235,12 @@ static int parser_svg_dir(struct probe_s *probe, const struct param_key_s *pa + return -1; + } + +- (void)snprintf(probe->probe_param.svg_dir, sizeof(probe->probe_param.svg_dir), "%s", value); ++ char real_path[PATH_LEN]; ++ if (realpath(value, real_path) == NULL) { ++ return -1; ++ } ++ ++ (void)snprintf(probe->probe_param.svg_dir, sizeof(probe->probe_param.svg_dir), "%s", real_path); + return 0; + } + +@@ -251,7 +256,13 @@ static int parser_flame_dir(struct probe_s *probe, const struct param_key_s *par + PARSE_ERR("params.%s contains unsafe characters", param_key->key); + return -1; + } +- (void)snprintf(probe->probe_param.flame_dir, sizeof(probe->probe_param.flame_dir), "%s", value); ++ ++ char real_path[PATH_LEN]; ++ if (realpath(value, real_path) == NULL) { ++ return -1; ++ } ++ ++ (void)snprintf(probe->probe_param.flame_dir, sizeof(probe->probe_param.flame_dir), "%s", real_path); + return 0; + } + +@@ -449,7 +460,13 @@ static int parser_elf_path(struct probe_s *probe, const struct param_key_s *para + PARSE_ERR("params.%s contains unsafe characters", param_key->key); + return -1; + } +- (void)snprintf(probe->probe_param.elf_path, sizeof(probe->probe_param.elf_path), "%s", value); ++ ++ char real_path[MAX_PATH_LEN]; ++ if (realpath(value, real_path) == NULL) { ++ return -1; ++ } ++ ++ (void)snprintf(probe->probe_param.elf_path, sizeof(probe->probe_param.elf_path), "%s", real_path); + return 0; + } + +diff --git a/src/probes/extends/ebpf.probe/src/lib/elf_reader.c b/src/probes/extends/ebpf.probe/src/lib/elf_reader.c +index 4dd8da02..f7da64ca 100644 +--- a/src/probes/extends/ebpf.probe/src/lib/elf_reader.c ++++ b/src/probes/extends/ebpf.probe/src/lib/elf_reader.c +@@ -29,22 +29,11 @@ + + #define DEFAULT_PATH_LIST "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin" + +-#define COMMAND_REAL_PATH "/usr/bin/realpath %s" +- + #define COMMAND_GLIBC_PATH \ + "/usr/bin/ldd /bin/ls | grep \"libc.so\" | awk -F '=>' '{print $2}' | awk '{print $1}'" + #define COMMAND_ENV_PATH "/usr/bin/env | grep PATH | awk -F '=' '{print $2}'" + + #if BPF_ELF_DESC("get glibc path") +-static int __get_link_path(const char* link, char *path, unsigned int len) +-{ +- char command[COMMAND_LEN]; +- +- command[0] = 0; +- (void)snprintf(command, COMMAND_LEN, COMMAND_REAL_PATH, link); +- return exec_cmd_chroot(command, path, len); +-} +- + static int __do_get_glibc_path_host(char *path, unsigned int len) + { + int ret; +@@ -65,7 +54,7 @@ static int __do_get_glibc_path_host(char *path, unsigned int len) + } + + split_newline_symbol(line); +- ret = __get_link_path((const char *)line, path_buf, len); ++ ret = exec_cmd_chroot((const char *)line, path_buf, len); + if (ret < 0) { + (void)pclose(f); + return -1; +@@ -98,7 +87,7 @@ static int __do_get_glibc_path_container(const char *container_id, char *path, u + (void)snprintf(glibc_abs_path, PATH_LEN, "%s/%s", container_abs_path, glibc_path); + + split_newline_symbol(glibc_abs_path); +- ret = __get_link_path((const char *)glibc_abs_path, path, len); ++ ret = exec_cmd_chroot((const char *)glibc_abs_path, path, len); + if (ret < 0) + return -1; + +-- +2.33.0 + diff --git a/epprobe-adapt-hook-point-of-req_drops-according-to-k.patch b/epprobe-adapt-hook-point-of-req_drops-according-to-k.patch new file mode 100644 index 0000000..8310a4c --- /dev/null +++ b/epprobe-adapt-hook-point-of-req_drops-according-to-k.patch @@ -0,0 +1,146 @@ +From ca82a6b41a96cee79e9f0a2da2feffb7847941cc Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Sat, 12 Jul 2025 21:10:22 +0800 +Subject: [PATCH 86/99] epprobe: adapt hook point of req_drops according to + kernel changes + +Due to patch of kernel vulnerability CVE-2024-50154 changes the call of +inet_csk_reqsk_queue_drop_and_put() to __inet_csk_reqsk_queue_drop() in +reqsk_timer_handler(), so we need to first check which function to +hook before started. +--- + .../ebpf.probe/src/endpointprobe/endpoint.c | 56 +++++++++++++++++++ + .../ebpf.probe/src/endpointprobe/tcp.bpf.c | 22 ++++++++ + 2 files changed, 78 insertions(+) + +diff --git a/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.c b/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.c +index ac8144a2..04c341d2 100644 +--- a/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.c ++++ b/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -163,6 +164,7 @@ 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 is_snooper(struct endpoint_probe_s *probe, int tgid) + { +@@ -1023,6 +1025,8 @@ static int endpoint_load_probe_tcp(struct endpoint_probe_s *probe, struct bpf_pr + 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)); ++ PROG_ENABLE_ONLY_IF(tcp, bpf_inet_csk_reqsk_queue_drop_and_put, !new_reqsk_drop_func_exist); ++ PROG_ENABLE_ONLY_IF(tcp, bpf___inet_csk_reqsk_queue_drop, new_reqsk_drop_func_exist); + + LOAD_ATTACH(endpoint, tcp, err, is_load); + +@@ -1216,6 +1220,52 @@ static void clean_endpoint_pin_map() + } + } + ++static int read_kprobe_perf_type(void) ++{ ++ const char *file = "/sys/bus/event_source/devices/kprobe/type"; ++ int ret, type; ++ FILE *f; ++ ++ f = fopen(file, "r"); ++ if (!f) { ++ return -1; ++ } ++ ret = fscanf(f, "%d\n", &type); ++ if (ret != 1) { ++ fclose(f); ++ return -1; ++ } ++ fclose(f); ++ return type; ++} ++ ++static void select_req_drop_hook(void) ++{ ++ int fd; ++ struct perf_event_attr pea = {}; ++ char *func = "__inet_csk_reqsk_queue_drop"; ++ int kprobe_perf_type = read_kprobe_perf_type(); ++ ++ if (kprobe_perf_type < 0) { ++ return; ++ } ++ ++ pea.type = (__u32)kprobe_perf_type; ++ pea.size = sizeof(struct perf_event_attr); ++ pea.config1 = 0; ++ pea.config1 = (__u64)(unsigned long)func; ++ ++ fd = syscall(__NR_perf_event_open, &pea, 0, -1, -1, 0); ++ if (fd == -1) { ++ return; ++ } ++ ++ INFO("[ENDPOINTPROBE] New hook point of tcp_req_drops detected.\n"); ++ new_reqsk_drop_func_exist = 1; ++ close(fd); ++ return; ++} ++ + int main(int argc, char **argv) + { + int ret = -1, msq_id; +@@ -1245,6 +1295,12 @@ int main(int argc, char **argv) + INIT_BPF_APP(endpoint, EBPF_RLIM_LIMITED); + INFO("[ENDPOINTPROBE] Successfully started!\n"); + ++ /* ++ * Due to patch of CVE-2024-50154 changes the call of inet_csk_reqsk_queue_drop_and_put ++ * to __inet_csk_reqsk_queue_drop in reqsk_timer_handler, so we need to first check which ++ * function to hook before started. ++ */ ++ select_req_drop_hook(); + while(!g_stop) { + ret = recv_ipc_msg(msq_id, (long)PROBE_SOCKET, &ipc_body); + if (ret == 0) { +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 0937e086..6cec8c35 100644 +--- a/src/probes/extends/ebpf.probe/src/endpointprobe/tcp.bpf.c ++++ b/src/probes/extends/ebpf.probe/src/endpointprobe/tcp.bpf.c +@@ -949,6 +949,28 @@ KPROBE(inet_csk_reqsk_queue_drop_and_put, pt_regs) + return 0; + } + ++KPROBE(__inet_csk_reqsk_queue_drop, pt_regs) ++{ ++ struct sock *sk = (struct sock *)PT_REGS_PARM1(ctx); ++ struct request_sock *req = (struct request_sock *)PT_REGS_PARM2(ctx); ++ ++ struct sock_info_s* info = lkup_sock((const struct sock *)sk); ++ if (info == NULL) { ++ return 0; ++ } ++ ++ struct tcp_socket_event_s evt = {0}; ++ get_request_sockaddr(&evt, req); ++ evt.evt = EP_STATS_REQ_DROP; ++ evt.tgid = info->tgid; ++ evt.is_multi = info->is_multi; ++ ++ // report; ++ evt.role = TCP_SERVER; ++ (void)bpfbuf_output(ctx, &tcp_evt_map, &evt, sizeof(struct tcp_socket_event_s)); ++ return 0; ++} ++ + #define TCPHDR_FIN 0x01 + #define TCPHDR_SYN 0x02 + #define TCPHDR_RST 0x04 +-- +2.33.0 + diff --git a/fix-Memory-leak.patch b/fix-Memory-leak.patch new file mode 100644 index 0000000..45a5f7a --- /dev/null +++ b/fix-Memory-leak.patch @@ -0,0 +1,74 @@ +From f04fbdc70a422b13f27514b7c85f61bbc22562d4 Mon Sep 17 00:00:00 2001 +From: chengjun +Date: Tue, 19 Nov 2024 14:21:09 +0800 +Subject: [PATCH 14/99] fix Memory leak + +--- + .../ebpf.probe/src/l7probe/protocol/kafka/kafka_parser.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + mode change 100644 => 100755 src/probes/extends/ebpf.probe/src/l7probe/protocol/kafka/kafka_parser.c + +diff --git a/src/probes/extends/ebpf.probe/src/l7probe/protocol/kafka/kafka_parser.c b/src/probes/extends/ebpf.probe/src/l7probe/protocol/kafka/kafka_parser.c +old mode 100644 +new mode 100755 +index d92dc425..6a5236e1 +--- a/src/probes/extends/ebpf.probe/src/l7probe/protocol/kafka/kafka_parser.c ++++ b/src/probes/extends/ebpf.probe/src/l7probe/protocol/kafka/kafka_parser.c +@@ -75,6 +75,7 @@ parse_state_t kafka_parse_frame(enum message_type_t msg_type, struct raw_data_s + decode_status = decoder_extract_int16_t(raw_data, &api_key_int); + if (decode_status != STATE_SUCCESS) { + ERROR("[Kafka] Decode request key failed.\n"); ++ free(raw_data_copy);//释放申请的内存 + return STATE_INVALID; + } + api_key = (enum kafka_api) api_key_int; +@@ -82,16 +83,19 @@ parse_state_t kafka_parse_frame(enum message_type_t msg_type, struct raw_data_s + decode_status = decoder_extract_int16_t(raw_data, &api_version); + if (decode_status != STATE_SUCCESS) { + ERROR("[Kafka] Decode request version failed.\n"); ++ free(raw_data_copy);//释放申请的内存 + return STATE_INVALID; + } + + if (!is_api_key_valid(api_key)) { + ERROR("[Kafka] Decode request key is invalid.\n"); ++ free(raw_data_copy);//释放申请的内存 + return STATE_INVALID; + } + + if (!is_api_version_support(api_key, api_version)) { + ERROR("[Kafka] Decode request version is invalid.\n"); ++ free(raw_data_copy);//释放申请的内存 + return STATE_INVALID; + } + } +@@ -101,22 +105,26 @@ parse_state_t kafka_parse_frame(enum message_type_t msg_type, struct raw_data_s + decode_status = decoder_extract_int32_t(raw_data, &correlation_id); + if (decode_status != STATE_SUCCESS) { + ERROR("[Kafka] Decode correlation id failed.\n"); ++ free(raw_data_copy);//释放申请的内存 + return STATE_INVALID; + } + + if (correlation_id < 0) { + ERROR("[Kafka] Decode correlation id is invalid.\n"); ++ free(raw_data_copy);//释放申请的内存 + return STATE_INVALID; + } + + if (raw_data_len - KAFKA_PAYLOAD_LENGTH < msg_length) { + INFO("[Kafka] Decode needs more data.\n"); ++ free(raw_data_copy);//释放申请的内存 + return STATE_NEEDS_MORE_DATA; + } + + struct kafka_frame_s *kafka_frame = (struct kafka_frame_s *) malloc(sizeof(struct kafka_frame_s)); + if (kafka_frame == NULL) { + ERROR("[Kafka] Malloc kafka frame failed.\n"); ++ free(raw_data_copy);//释放申请的内存 + return STATE_INVALID; + } + +-- +2.33.0 + diff --git a/fix-OOB-write-when-getting-proc-cmdline.patch b/fix-OOB-write-when-getting-proc-cmdline.patch new file mode 100644 index 0000000..0adb16a --- /dev/null +++ b/fix-OOB-write-when-getting-proc-cmdline.patch @@ -0,0 +1,51 @@ +From 0ef54206efa01dece9e6ca3f32ccdc3cf6d7cca1 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Thu, 14 Nov 2024 03:04:22 +0800 +Subject: [PATCH 13/99] fix OOB write when getting proc cmdline + +--- + src/common/util.c | 2 +- + src/lib/probe/snooper.c | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/common/util.c b/src/common/util.c +index 290c4a7e..c8bdff6b 100644 +--- a/src/common/util.c ++++ b/src/common/util.c +@@ -426,7 +426,7 @@ int get_proc_cmdline(u32 pid, char *buf, u32 buf_len) + /* parse line */ + while (feof(f) == 0) { + if (index >= buf_len - 1) { +- buf[index] = '\0'; ++ buf[buf_len - 1] = '\0'; + break; + } + buf[index] = fgetc(f); +diff --git a/src/lib/probe/snooper.c b/src/lib/probe/snooper.c +index 48088285..82cf3679 100644 +--- a/src/lib/probe/snooper.c ++++ b/src/lib/probe/snooper.c +@@ -848,7 +848,7 @@ static int __read_proc_cmdline(const char *dir_name, char *cmdline, u32 size) + /* parse line */ + while (!feof(f)) { + if (index >= size - 1) { +- cmdline[index] = '\0'; ++ cmdline[size - 1] = '\0'; + break; + } + cmdline[index] = fgetc(f); +@@ -1123,9 +1123,9 @@ static int gen_snooper_by_container_name(struct probe_s *probe) + if (snooper_conf->type != SNOOPER_CONF_CONTAINER_NAME) { + continue; + } +- ++ + cmd[0] = 0; +- (void)snprintf(cmd, COMMAND_LEN, ++ (void)snprintf(cmd, COMMAND_LEN, + "docker ps -q --filter \"name=%s\"", (const char *)snooper_conf->conf.container_name); + f = popen_chroot(cmd, "r"); + if (f == NULL) { +-- +2.33.0 + diff --git a/fix-UAF-of-probe-bin-after-parsing-invalid-config.patch b/fix-UAF-of-probe-bin-after-parsing-invalid-config.patch new file mode 100644 index 0000000..31349f8 --- /dev/null +++ b/fix-UAF-of-probe-bin-after-parsing-invalid-config.patch @@ -0,0 +1,27 @@ +From 9a7c955e86cae8f8030f1af5b9614332fdf2653b Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Wed, 5 Feb 2025 20:58:49 +0800 +Subject: [PATCH 53/99] fix UAF of probe bin after parsing invalid config + +--- + src/lib/probe/probe_mng.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/src/lib/probe/probe_mng.c b/src/lib/probe/probe_mng.c +index e31baff0..44c187bc 100644 +--- a/src/lib/probe/probe_mng.c ++++ b/src/lib/probe/probe_mng.c +@@ -1021,10 +1021,6 @@ static void probe_backup_cmd(struct probe_s *probe, struct probe_s *probe_backup + + static void probe_rollback_cmd(struct probe_s *probe, struct probe_s *probe_backup) + { +- if (probe->bin) { +- free(probe->bin); +- } +- + probe->is_extend_probe = probe_backup->is_extend_probe; + probe->probe_entry = probe_backup->probe_entry; + probe->cb = probe_backup->cb; +-- +2.33.0 + diff --git a/fix-buffer-overflow-and-ret-value-of-sscanf.patch b/fix-buffer-overflow-and-ret-value-of-sscanf.patch new file mode 100644 index 0000000..046af77 --- /dev/null +++ b/fix-buffer-overflow-and-ret-value-of-sscanf.patch @@ -0,0 +1,126 @@ +From adab5d396d83ef7c8f4923e0d3760b74d9e4eb9f Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Fri, 27 Dec 2024 15:24:37 +0800 +Subject: [PATCH 37/99] fix buffer overflow and ret value of sscanf + +--- + src/common/util.c | 2 +- + src/probes/extends/ebpf.probe/src/lib/pystack/py_stack.c | 2 +- + src/probes/system_infos.probe/system_cpu.c | 4 ++-- + src/probes/system_infos.probe/system_procs.c | 6 ++++-- + src/probes/virtualized_infos.probe/virt_proc.c | 6 +++++- + 5 files changed, 13 insertions(+), 7 deletions(-) + +diff --git a/src/common/util.c b/src/common/util.c +index c8bdff6b..69d08f83 100644 +--- a/src/common/util.c ++++ b/src/common/util.c +@@ -479,7 +479,7 @@ int get_so_path(int pid, char *elf_path, int size, const char *so_keyword) + + while (fgets(buf, sizeof(buf), fp)) { + so_path[0] = 0; +- if (sscanf(buf, "%*x-%*x %*s %*s %*s %*s %s", so_path) != 1) { ++ if (sscanf(buf, "%*x-%*x %*s %*s %*s %*s %255s", so_path) != 1) { + continue; + } + if (so_path[0] != '/') { +diff --git a/src/probes/extends/ebpf.probe/src/lib/pystack/py_stack.c b/src/probes/extends/ebpf.probe/src/lib/pystack/py_stack.c +index bfa55fd5..cf05b545 100644 +--- a/src/probes/extends/ebpf.probe/src/lib/pystack/py_stack.c ++++ b/src/probes/extends/ebpf.probe/src/lib/pystack/py_stack.c +@@ -187,7 +187,7 @@ int try_init_py_proc_data(int pid, struct py_proc_data *data) + } + + while (fgets(buf, sizeof(buf), fp) != NULL) { +- if (sscanf(buf, "%llx-%llx %4s %llx %*s %*u %s", ++ if (sscanf(buf, "%llx-%llx %4s %llx %*s %*u %255s", + &mod_info.start, &mod_info.end, perm, &mod_info.f_offset, so_path) != 5) { + continue; + } +diff --git a/src/probes/system_infos.probe/system_cpu.c b/src/probes/system_infos.probe/system_cpu.c +index 19d1316c..5a2c6900 100644 +--- a/src/probes/system_infos.probe/system_cpu.c ++++ b/src/probes/system_infos.probe/system_cpu.c +@@ -29,7 +29,7 @@ + #define SYSTEM_PROC_STAT_PATH "/proc/stat" + #define SYSTEM_CPU_MHZ_INFO "cat /proc/cpuinfo | grep MHz" + #define SOFTNET_STAT_PATH "/proc/net/softnet_stat" +-#define PROC_STAT_FILEDS_NUM 6 ++#define PROC_STAT_FILEDS_NUM 8 + #define PROC_STAT_COL_NUM 8 + #define PROC_STAT_IDLE_COL 4 + #define PROC_STAT_IOWAIT_COL 5 +@@ -160,7 +160,7 @@ static int get_proc_stat_info(void) + &cur_cpus[index]->cpu_softirq_total_second, + &cur_cpus[index]->cpu_steal_total_second); + if (ret < PROC_STAT_FILEDS_NUM) { +- DEBUG("system_cpu.probe failed get proc_stat metrics.\n"); ++ ERROR("system_cpu.probe failed to get proc_stat metrics.\n"); + } + index++; + } +diff --git a/src/probes/system_infos.probe/system_procs.c b/src/probes/system_infos.probe/system_procs.c +index b3f46093..dd1411b8 100644 +--- a/src/probes/system_infos.probe/system_procs.c ++++ b/src/probes/system_infos.probe/system_procs.c +@@ -367,6 +367,7 @@ static int get_proc_mss(u32 pid, proc_info_t *proc_info) + u32 value = 0; + char line[LINE_BUF_LEN]; + char key[LINE_BUF_LEN]; ++ char format[SSCANF_FORMAT_LEN]; + char smap_key_list[PROC_MSS_MAX][LINE_BUF_LEN] = {"Shared_Clean:", "Shared_Dirty:", "Private_Clean:", + "Private_Dirty:", "Referenced:", "LazyFree:", "Swap:", "SwapPss:"}; + int smap_index = 0; +@@ -376,6 +377,7 @@ static int get_proc_mss(u32 pid, proc_info_t *proc_info) + return -1; + } + ++ (void)snprintf(format, sizeof(format), "%%%lus %%u %%*s", sizeof(key) - 1); + while (!feof(f)) { + line[0] = 0; + key[0] = 0; +@@ -387,8 +389,8 @@ static int get_proc_mss(u32 pid, proc_info_t *proc_info) + continue; + } + value = 0; +- int ret = sscanf(line, "%s %u %*s", key, &value); +- if (ret < 1) { ++ int ret = sscanf(line, format, key, &value); ++ if (ret < 2) { + goto out; + } + if (strcmp(smap_key_list[smap_index], key) != 0) { +diff --git a/src/probes/virtualized_infos.probe/virt_proc.c b/src/probes/virtualized_infos.probe/virt_proc.c +index 7a6848bc..d5b39779 100644 +--- a/src/probes/virtualized_infos.probe/virt_proc.c ++++ b/src/probes/virtualized_infos.probe/virt_proc.c +@@ -160,6 +160,7 @@ int virt_proc_probe(void) + FILE *f = NULL; + char cmd[COMMAND_LEN]; + char line[LINE_BUF_LEN]; ++ char format[SSCANF_FORMAT_LEN]; + struct proc_infos one_proc; + + if (g_host_type_is_pm == 0) { +@@ -177,6 +178,9 @@ int virt_proc_probe(void) + if (f == NULL) { + return -1; + } ++ ++ (void)snprintf(format, sizeof(format), "%%%lus %%%lus", ++ sizeof(one_proc.uuid) - 1, sizeof(one_proc.vm_name) - 1); + while (!feof(f)) { + (void)memset(line, 0, LINE_BUF_LEN); + if (fgets(line, LINE_BUF_LEN, f) == NULL) { +@@ -184,7 +188,7 @@ int virt_proc_probe(void) + return -1; + } + (void)memset(&one_proc, 0, sizeof(struct proc_infos)); +- if (sscanf(line, "%s %s", one_proc.uuid, one_proc.vm_name) < 2) { ++ if (sscanf(line, format, one_proc.uuid, one_proc.vm_name) < 2) { + break; + } + (void)get_qemu_proc_tgid(&one_proc); +-- +2.33.0 + diff --git a/fix-buffer-overflow-in-sscanf.patch b/fix-buffer-overflow-in-sscanf.patch new file mode 100644 index 0000000..d252875 --- /dev/null +++ b/fix-buffer-overflow-in-sscanf.patch @@ -0,0 +1,129 @@ +From 54f8ae2c75ddee508fbdbe3cc0aecf0dd1c5e52e Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Thu, 26 Dec 2024 18:01:15 +0800 +Subject: [PATCH 36/99] fix buffer overflow in sscanf + +--- + src/common/common.h | 1 + + src/common/container.c | 6 ++++- + src/probes/system_infos.probe/system_disk.c | 25 ++++++++++++++++----- + 3 files changed, 25 insertions(+), 7 deletions(-) + +diff --git a/src/common/common.h b/src/common/common.h +index 235ec860..a2d177d6 100644 +--- a/src/common/common.h ++++ b/src/common/common.h +@@ -70,6 +70,7 @@ + #define LINE_BUF_LEN 512 + #define PATH_LEN 256 + #define CG_PATH_LEN 2048 ++#define SSCANF_FORMAT_LEN 128 + + #if !defined INET6_ADDRSTRLEN + #define INET6_ADDRSTRLEN 46 +diff --git a/src/common/container.c b/src/common/container.c +index fbf0935f..9be1b55e 100644 +--- a/src/common/container.c ++++ b/src/common/container.c +@@ -530,6 +530,7 @@ static int get_container_btrfs_subvol(unsigned int pid, char *subvol, unsigned i + char fs_file[PATH_LEN]; + char fs_type[PATH_LEN]; + char fs_mntops[PATH_LEN]; ++ char format[SSCANF_FORMAT_LEN]; + int ret; + + command[0] = 0; +@@ -539,6 +540,9 @@ static int get_container_btrfs_subvol(unsigned int pid, char *subvol, unsigned i + return -1; + } + ++ (void)snprintf(format, sizeof(format), "%%*s %%%lus %%%lus %%%lus", ++ sizeof(fs_file) - 1, sizeof(fs_type) - 1, ++ sizeof(fs_mntops) - 1); + while (!feof(f)) { + line[0] = 0; + if (fgets(line, sizeof(line), f) == NULL) { +@@ -547,7 +551,7 @@ static int get_container_btrfs_subvol(unsigned int pid, char *subvol, unsigned i + fs_file[0] = 0; + fs_type[0] = 0; + fs_mntops[0] = 0; +- ret = sscanf(line, "%*s %s %s %s", fs_file, fs_type, fs_mntops); ++ ret = sscanf(line, format, fs_file, fs_type, fs_mntops); + if (ret != 3) { + break; + } +diff --git a/src/probes/system_infos.probe/system_disk.c b/src/probes/system_infos.probe/system_disk.c +index 63c5075e..867bcfd9 100644 +--- a/src/probes/system_infos.probe/system_disk.c ++++ b/src/probes/system_infos.probe/system_disk.c +@@ -37,8 +37,12 @@ static df_stats *g_df_tbl = NULL; + static int get_df_inode_fields(char *line, df_stats *stats) + { + int ret; ++ char format[SSCANF_FORMAT_LEN]; + +- ret = sscanf(line, "%s %s %ld %ld %ld %ld%*s %s", ++ (void)snprintf(format, sizeof(format), "%%%lus %%%lus %%ld %%ld %%ld %%ld%%*s %%%lus", ++ sizeof(stats->fsname) - 1, sizeof(stats->fstype) - 1, ++ sizeof(stats->mount_on) - 1); ++ ret = sscanf(line, format, + &stats->fsname, &stats->fstype, &stats->inode_sum, &stats->inode_used, + &stats->inode_free, &stats->inode_used_per, &stats->mount_on); + if (ret < DF_INODE_FIELD_NUM) { +@@ -52,8 +56,13 @@ static int get_df_inode_fields(char *line, df_stats *stats) + static int get_df_block_fields(char *line, df_stats *stats) + { + int ret; ++ char format[SSCANF_FORMAT_LEN]; + +- ret = sscanf(line, "%*s %*s %ld %ld %ld %ld%*s %s", ++ (void)snprintf(format, sizeof(format), ++ "%%*s %%*s %%ld %%ld %%ld %%ld%%*s %%%lus", ++ sizeof(stats->mount_on) - 1); ++ ++ ret = sscanf(line, format, + &stats->blk_sum, &stats->blk_used, + &stats->blk_free, &stats->blk_used_per, &stats->mount_on); + if (ret < DF_BLOCK_FIELD_NUM) { +@@ -64,14 +73,18 @@ static int get_df_block_fields(char *line, df_stats *stats) + } + + #define MNT_FIELD_NUM 2 +-static int get_fs_mount_status(char *line, char mountOn[MOUNTON_LEN], char mountStatus[MOUNTSTATUS_LEN]) ++static int get_fs_mount_status(char *line, char *mountOn, size_t mounton_len, ++ char *mountStatus, size_t mountstatus_len) + { + int ret; + char buf[LINE_BUF_LEN]; + char *firstComma; ++ char format[SSCANF_FORMAT_LEN]; + ++ (void)snprintf(format, sizeof(format), "%%*s %%%lus %%*s %%%lus", ++ mounton_len - 1, sizeof(buf) - 1); + buf[0] = 0; +- ret = sscanf(line, "%*s %s %*s %s", mountOn, buf); ++ ret = sscanf(line, format, mountOn, buf); + if (ret < MNT_FIELD_NUM) { + DEBUG("[SYSTEM_DISK] get fs mount status fail.\n"); + return -1; +@@ -83,7 +96,7 @@ static int get_fs_mount_status(char *line, char mountOn[MOUNTON_LEN], char mount + return -1; + } + *firstComma = '\0'; +- (void)snprintf(mountStatus, MOUNTSTATUS_LEN, "%s", buf); ++ (void)snprintf(mountStatus, mountstatus_len, "%s", buf); + return 0; + } + +@@ -252,7 +265,7 @@ static int init_fs_status(void) + + mountOn[0] = 0; + mountStatus[0] = 0; +- if (get_fs_mount_status(line, mountOn, mountStatus)) { ++ if (get_fs_mount_status(line, mountOn, sizeof(mountOn), mountStatus, sizeof(mountStatus))) { + continue; + } + +-- +2.33.0 + diff --git a/fix-extra-length-of-task-comm.patch b/fix-extra-length-of-task-comm.patch new file mode 100644 index 0000000..aaf1bc7 --- /dev/null +++ b/fix-extra-length-of-task-comm.patch @@ -0,0 +1,60 @@ +From a7676ea8b11a4da5755200d28aa66d154363d925 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Tue, 20 May 2025 23:44:22 +0800 +Subject: [PATCH 77/99] fix extra length of task comm + +--- + src/lib/imdb/imdb.c | 4 ++-- + src/lib/imdb/imdb.h | 2 +- + src/lib/probe/snooper.h | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/lib/imdb/imdb.c b/src/lib/imdb/imdb.c +index ebadda95..afa111c1 100644 +--- a/src/lib/imdb/imdb.c ++++ b/src/lib/imdb/imdb.c +@@ -372,13 +372,13 @@ static TGID_Record* IMDB_TgidCreateRecord(IMDB_DataBaseMgr *mgr, const char *tgi + int ret; + int pid; + u64 startup_ts; +- char comm[TASK_COMM_LEN + 1]; ++ char comm[TASK_COMM_LEN]; + TGID_Record *record; + + comm[0] = 0; + pid = strtol(tgid, NULL, 10); + +- ret = get_proc_comm(pid, comm, TASK_COMM_LEN + 1); ++ ret = get_proc_comm(pid, comm, TASK_COMM_LEN); + if (ret) { + return NULL; + } +diff --git a/src/lib/imdb/imdb.h b/src/lib/imdb/imdb.h +index 257cea56..650cdeaa 100644 +--- a/src/lib/imdb/imdb.h ++++ b/src/lib/imdb/imdb.h +@@ -108,7 +108,7 @@ typedef struct { + typedef struct { + TGID_RecordKey key; + char container_id[CONTAINER_ABBR_ID_LEN + 1]; +- char comm[TASK_COMM_LEN + 1]; ++ char comm[TASK_COMM_LEN]; + char cmdline[PROC_CMDLINE_LEN]; + H_HANDLE; + } TGID_Record; +diff --git a/src/lib/probe/snooper.h b/src/lib/probe/snooper.h +index c11a186b..d147a2a4 100644 +--- a/src/lib/probe/snooper.h ++++ b/src/lib/probe/snooper.h +@@ -34,7 +34,7 @@ enum snooper_conf_e { + }; + + struct snooper_app_s { +- char comm[TASK_COMM_LEN + 1]; ++ char comm[TASK_COMM_LEN]; + char *cmdline; + char *debuging_dir; + }; +-- +2.33.0 + diff --git a/fix-home-check.patch b/fix-home-check.patch new file mode 100644 index 0000000..15799c6 --- /dev/null +++ b/fix-home-check.patch @@ -0,0 +1,93 @@ +From ff7c6a55dd5c5e5323b3c0a5cd2cf0c85f455b20 Mon Sep 17 00:00:00 2001 +From: yangyongguang +Date: Fri, 3 Jan 2025 10:52:35 +0800 +Subject: [PATCH] fix home check + +--- + src/common/json_tool.cpp | 2 +- + src/lib/probe/probe_mng.c | 20 +------------------- + src/probes/system_infos.probe/system_cpu.c | 4 ++++ + src/resource/resource.c | 1 + + 4 files changed, 7 insertions(+), 20 deletions(-) + +diff --git a/src/common/json_tool.cpp b/src/common/json_tool.cpp +index 96fceb9..54469da 100644 +--- a/src/common/json_tool.cpp ++++ b/src/common/json_tool.cpp +@@ -286,7 +286,7 @@ void Json_AddCharItemToObject(void *jsonObj, const char *nameCStr, char valChar) + + void Json_AddItemToObject(void *jsonObj, const char *nameCStr, void *item) + { +- if (!jsonObj or CHECK_STRING_INPUT(nameCStr)) { ++ if (!jsonObj or CHECK_STRING_INPUT(nameCStr) or CHECK_STRING_INPUT(item)) { + return; + } + const std::string &nameStr = std::string(nameCStr); +diff --git a/src/lib/probe/probe_mng.c b/src/lib/probe/probe_mng.c +index cb54a82..e1c97a5 100644 +--- a/src/lib/probe/probe_mng.c ++++ b/src/lib/probe/probe_mng.c +@@ -394,24 +394,6 @@ err: + return NULL; + } + +-static int is_extend_probe(struct probe_s *probe) +-{ +- if (probe->bin == NULL) { +- return 0; +- } +- +- // Independent running binary for extend probe, Otherwise, it's a native probe +- if (access(probe->bin, 0) == 0) { +- return 1; +- } +- +- if (strchr(probe->bin, '/') != NULL) { +- return 1; +- } +- +- return 0; +-} +- + static int set_probe_entry(struct probe_s *probe) + { + int ret = 0; +@@ -450,7 +432,7 @@ static int init_probe_bin(struct probe_s *probe, enum probe_type_e probe_type) + return -1; + } + +- if (is_extend_probe(probe)) { ++ if ((probe_type != PROBE_BASEINFO) && (probe_type != PROBE_VIRT)) { + probe->is_extend_probe = 1; + probe->cb = extend_probe_thread_cb; + } else { +diff --git a/src/probes/system_infos.probe/system_cpu.c b/src/probes/system_infos.probe/system_cpu.c +index e94fefd..ba18c56 100644 +--- a/src/probes/system_infos.probe/system_cpu.c ++++ b/src/probes/system_infos.probe/system_cpu.c +@@ -184,6 +184,10 @@ static int get_softirq_info(void) + } + while (fgets(softirq_line, softirq_line_num - 1, f) != NULL) { + field = __strtok_r(softirq_line, " ", &save); ++ if (!field) { ++ softirq_line[0] = 0; ++ continue; ++ } + if (strcmp(field, "RCU:") == 0) { + for (size_t i = 0; i < cpus_num; i++) { + cur_cpus[i]->rcu = strtoul(__strtok_r(NULL, " ", &save), NULL, 10); +diff --git a/src/resource/resource.c b/src/resource/resource.c +index 74888d5..25015b2 100644 +--- a/src/resource/resource.c ++++ b/src/resource/resource.c +@@ -559,6 +559,7 @@ static int LogsMgrInit(ResourceMgr *resourceMgr) + (void)snprintf(logsMgr->meta_path, sizeof(logsMgr->meta_path), "%s", configMgr->logsConfig->metaDir); + + if (init_log_mgr(logsMgr, is_meta_out_log, configMgr->globalConfig->logLevel) < 0) { ++ umask(old_mask); + return -1; + } + resourceMgr->logsMgr = logsMgr; +-- +2.33.0 + diff --git a/fix-potential-nullptr-dereference-in-libevent-openss.patch b/fix-potential-nullptr-dereference-in-libevent-openss.patch new file mode 100644 index 0000000..3e21882 --- /dev/null +++ b/fix-potential-nullptr-dereference-in-libevent-openss.patch @@ -0,0 +1,31 @@ +From 0d02bd42803a17c6365a640f878c034e8f26e2aa Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Fri, 13 Dec 2024 14:47:38 +0800 +Subject: [PATCH 30/99] fix potential nullptr dereference in libevent openssl + cb + +--- + src/lib/http_server/http_server.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/lib/http_server/http_server.c b/src/lib/http_server/http_server.c +index 29afa779..375eefec 100644 +--- a/src/lib/http_server/http_server.c ++++ b/src/lib/http_server/http_server.c +@@ -34,7 +34,12 @@ static struct bufferevent* http_server_bevcb_ssl(struct event_base *evbase, void + return NULL; + } + +- return bufferevent_openssl_socket_new(evbase, -1, SSL_new(ssl_ctx), ++ SSL *ssl = SSL_new(ssl_ctx); ++ if (ssl == NULL) { ++ return NULL; ++ } ++ ++ return bufferevent_openssl_socket_new(evbase, -1, ssl, + BUFFEREVENT_SSL_ACCEPTING, + BEV_OPT_CLOSE_ON_FREE); + } +-- +2.33.0 + diff --git a/fix-prog-load-failure-due-to-loops-in-toa-code.patch b/fix-prog-load-failure-due-to-loops-in-toa-code.patch new file mode 100644 index 0000000..205b156 --- /dev/null +++ b/fix-prog-load-failure-due-to-loops-in-toa-code.patch @@ -0,0 +1,68 @@ +From 76c70de47b5b78832a1f95f718a7b928ad4475c1 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Thu, 14 Nov 2024 07:57:41 +0800 +Subject: [PATCH 26/99] fix prog load failure due to loops in toa code + +--- + src/probes/extends/ebpf.probe/src/endpointprobe/tcp.bpf.c | 3 +-- + src/probes/extends/ebpf.probe/src/include/toa.h | 1 + + src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c | 3 +-- + 3 files changed, 3 insertions(+), 4 deletions(-) + +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 ef8f85b3..43832917 100644 +--- a/src/probes/extends/ebpf.probe/src/endpointprobe/tcp.bpf.c ++++ b/src/probes/extends/ebpf.probe/src/endpointprobe/tcp.bpf.c +@@ -690,7 +690,7 @@ static void *get_toa_data(struct sk_buff *skb, int af, enum toa_type *type, stru + + u16 _doff = BPF_CORE_READ_BITFIELD_PROBED(th, doff); + length = _doff * 4 - sizeof(struct tcphdr); +- if (length <= 0) { ++ if (length <= 0 || length > MAX_TCP_OPTIONS_LEN) { + return NULL; + } + +@@ -699,7 +699,6 @@ static void *get_toa_data(struct sk_buff *skb, int af, enum toa_type *type, stru + return NULL; + } + +- // todo: while循环需要在4.18/4.19内核版本验证 + while (length > 0) { + int opcode = _(*ptr); + ptr++; +diff --git a/src/probes/extends/ebpf.probe/src/include/toa.h b/src/probes/extends/ebpf.probe/src/include/toa.h +index aaaf8884..b5f5fdd5 100644 +--- a/src/probes/extends/ebpf.probe/src/include/toa.h ++++ b/src/probes/extends/ebpf.probe/src/include/toa.h +@@ -23,6 +23,7 @@ + #define TCPOPT_NOP 1 + #define ETH_P_IP 0x0800 + #define ETH_P_IPV6 0x86DD ++#define MAX_TCP_OPTIONS_LEN 40 // 15(max u4) * 4 - sizeof(tcphdr) + + struct toa_opt { + u8 opcode; +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c +index aaf19301..1d4208b5 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c +@@ -274,7 +274,7 @@ static void *get_toa_data(struct sk_buff *skb, int af, enum toa_type *type, stru + + u16 _doff = BPF_CORE_READ_BITFIELD_PROBED(th, doff); + length = _doff * 4 - sizeof(struct tcphdr); +- if (length <= 0) { ++ if (length <= 0 || length > MAX_TCP_OPTIONS_LEN) { + return NULL; + } + +@@ -284,7 +284,6 @@ static void *get_toa_data(struct sk_buff *skb, int af, enum toa_type *type, stru + } + + // todo: 流程可优化为:先解套opcode&偏移opsize,再解出toa_opt或toa_opt_v6 +- // todo: 避免在低版本OS内核中因ebpf对循环的限制而导致不可用 + while (length > 0) { + int opcode = _(*ptr); + ptr++; +-- +2.33.0 + diff --git a/fix-restart-gopher-failed-for-check-gopher-pid-multi.patch b/fix-restart-gopher-failed-for-check-gopher-pid-multi.patch new file mode 100644 index 0000000..830278a --- /dev/null +++ b/fix-restart-gopher-failed-for-check-gopher-pid-multi.patch @@ -0,0 +1,44 @@ +From e3a77ff7f036737133dee6ed426c6793e2975225 Mon Sep 17 00:00:00 2001 +From: yangyongguang +Date: Wed, 27 Nov 2024 12:58:08 +0800 +Subject: [PATCH 19/99] fix restart gopher failed for check gopher pid multi + times + +--- + script/init_probes.sh | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/script/init_probes.sh b/script/init_probes.sh +index 1cb8c242..5a86ea05 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 ++MAX_ATTEMPTS=20 + + PROBES=( + "baseinfo" +@@ -44,8 +45,16 @@ PROBES=( + + function check_gopher_running() + { +- [ -f ${GOPHER_PIDFILE} ] && [ ! -L ${GOPHER_PIDFILE} ] +- return $? ++ local attempt=0 ++ ++ while [ $attempt -lt $MAX_ATTEMPTS ]; do ++ if [ -f ${GOPHER_PIDFILE} ] && [ ! -L ${GOPHER_PIDFILE} ]; then ++ return 0 ++ fi ++ attempt=$((attempt + 1)) ++ sleep 0.5 ++ done ++ return 1 + } + + function check_unix_socket_listen() +-- +2.33.0 + diff --git a/fix-restart-thread-block-by-resetting-probe-pid.patch b/fix-restart-thread-block-by-resetting-probe-pid.patch new file mode 100644 index 0000000..299fa72 --- /dev/null +++ b/fix-restart-thread-block-by-resetting-probe-pid.patch @@ -0,0 +1,24 @@ +From a38754ee32e95f914c65afa1c422aba583a03f32 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Mon, 4 Nov 2024 21:14:30 +0800 +Subject: [PATCH 05/99] fix restart thread block by resetting probe pid + +--- + src/lib/probe/probe_mng.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/lib/probe/probe_mng.c b/src/lib/probe/probe_mng.c +index bf30f240..89aff375 100644 +--- a/src/lib/probe/probe_mng.c ++++ b/src/lib/probe/probe_mng.c +@@ -523,6 +523,7 @@ static int try_start_probe(struct probe_s *probe) + // In case that probe exited abnormally, we can clean up thread resources here + if (probe->tid != 0) { + pthread_join(probe->tid, NULL); ++ set_probe_pid(probe, -1); + probe->tid = 0; + } + +-- +2.33.0 + diff --git a/fix-run-sig-hander-core-for-probe-mng-create-later.patch b/fix-run-sig-hander-core-for-probe-mng-create-later.patch new file mode 100644 index 0000000..e57dce7 --- /dev/null +++ b/fix-run-sig-hander-core-for-probe-mng-create-later.patch @@ -0,0 +1,27 @@ +From 2bdc3e8e93c506700bd4663409b1b463b441e51c Mon Sep 17 00:00:00 2001 +From: yangyongguang +Date: Wed, 27 Nov 2024 15:48:54 +0800 +Subject: [PATCH 24/99] fix run sig hander core for probe mng create later + +--- + src/daemon/main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/daemon/main.c b/src/daemon/main.c +index c3b4eb3d..8b28902b 100644 +--- a/src/daemon/main.c ++++ b/src/daemon/main.c +@@ -258,7 +258,9 @@ static void *run_sig_handler(void *arg) + prctl(PR_SET_NAME, "[SIGHANDLER]"); + + pthread_mutex_lock(&sig_mutex); +- (void)pthread_rwlock_wrlock(&g_resourceMgr->probe_mng->rwlock); ++ if (g_resourceMgr && g_resourceMgr->probe_mng) { ++ (void)pthread_rwlock_wrlock(&g_resourceMgr->probe_mng->rwlock); ++ } + destroy_probe_threads(); + // probe_mng创建的ipc消息队列是跟随内核的,进程结束消息队列还会存在,需要显示调用函数销毁 + destroy_ipc_msg_queue(g_probe_mng_ipc_msgid); +-- +2.33.0 + diff --git a/fix-service-failed-when-cmd-server-thread-starts-lat.patch b/fix-service-failed-when-cmd-server-thread-starts-lat.patch new file mode 100644 index 0000000..50cbb6f --- /dev/null +++ b/fix-service-failed-when-cmd-server-thread-starts-lat.patch @@ -0,0 +1,88 @@ +From fa2801f2caae481dc77d1b7988b74a63f77c92b6 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Thu, 7 Nov 2024 17:03:58 +0800 +Subject: [PATCH 07/99] fix service failed when cmd server thread starts late + +--- + script/init_probes.sh | 22 ++++++++++++++++------ + src/daemon/main.c | 13 ++++++------- + 2 files changed, 22 insertions(+), 13 deletions(-) + +diff --git a/script/init_probes.sh b/script/init_probes.sh +index 374dc6bc..1cb8c242 100755 +--- a/script/init_probes.sh ++++ b/script/init_probes.sh +@@ -15,7 +15,7 @@ + + GOPHER_INITIAL_CONF="/etc/gala-gopher/probes.init" + GOPHER_CMD_SOCK_PATH="/var/run/gala_gopher/gala_gopher_cmd.sock" +-RETRY_COUNT=5 ++GOPHER_PIDFILE="/var/run/gala_gopher/gala-gopher.pid" + MAX_INIT_NUM=25 + + PROBES=( +@@ -42,15 +42,25 @@ PROBES=( + "flowtracer" + ) + ++function check_gopher_running() ++{ ++ [ -f ${GOPHER_PIDFILE} ] && [ ! -L ${GOPHER_PIDFILE} ] ++ return $? ++} ++ ++function check_unix_socket_listen() ++{ ++ ss -xl src ${GOPHER_CMD_SOCK_PATH} | grep -q ${GOPHER_CMD_SOCK_PATH} ++ return $? ++} ++ + function check_cmd_server() + { +- i=0 +- while ! ss -xl src ${GOPHER_CMD_SOCK_PATH} | grep -q ${GOPHER_CMD_SOCK_PATH} ; do +- sleep 0.5 +- let i+=1 +- if [ $i -ge ${RETRY_COUNT} ] ; then ++ while ! check_unix_socket_listen ; do ++ if ! check_gopher_running ; then + exit 1 + fi ++ sleep 0.5 + done + } + +diff --git a/src/daemon/main.c b/src/daemon/main.c +index 59c5e11f..c3b4eb3d 100644 +--- a/src/daemon/main.c ++++ b/src/daemon/main.c +@@ -306,6 +306,12 @@ int main(int argc, char *argv[]) + goto err; + } + ++ ret = is_singleton(); ++ if (ret != 0) { ++ goto err; ++ } ++ delete_pid_file = 1; ++ + g_resourceMgr = ResourceMgrCreate(); + if (g_resourceMgr == NULL) { + ERROR("[MAIN] create resource manager failed.\n"); +@@ -318,13 +324,6 @@ int main(int argc, char *argv[]) + goto err; + } + +- ret = is_singleton(); +- if (ret != 0) { +- goto err; +- } +- +- delete_pid_file = 1; +- + g_probe_mng_ipc_msgid = g_resourceMgr->probe_mng->msq_id; + + ret = DaemonRun(g_resourceMgr); +-- +2.33.0 + diff --git a/fix-strdup-relative-error.patch b/fix-strdup-relative-error.patch new file mode 100644 index 0000000..fba2525 --- /dev/null +++ b/fix-strdup-relative-error.patch @@ -0,0 +1,547 @@ +From 25feca9f644693cbe42a662bdc3cb61862819d46 Mon Sep 17 00:00:00 2001 +From: yangyongguang +Date: Thu, 2 Jan 2025 19:17:40 +0800 +Subject: [PATCH 45/99] fix strdup relative error + +--- + src/common/core_btf.c | 3 + + src/common/json_tool.cpp | 9 +++ + src/lib/probe/probe_mng.c | 25 +++++--- + src/lib/probe/snooper.c | 61 ++++++++++++++----- + .../ebpf.probe/src/endpointprobe/endpoint.c | 11 ++-- + .../extends/ebpf.probe/src/ioprobe/ioprobe.c | 10 +++ + .../ebpf.probe/src/l7probe/conn_tracker.c | 9 +++ + .../extends/ebpf.probe/src/l7probe/l7probe.c | 4 ++ + .../extends/ebpf.probe/src/lib/conntrack.c | 12 ++++ + .../extends/ebpf.probe/src/lib/symbol.c | 17 +++++- + .../ebpf.probe/src/tcpprobe/tcp_tracker.c | 15 +++-- + 11 files changed, 138 insertions(+), 38 deletions(-) + +diff --git a/src/common/core_btf.c b/src/common/core_btf.c +index ce7c67c5..f8afa936 100644 +--- a/src/common/core_btf.c ++++ b/src/common/core_btf.c +@@ -60,6 +60,9 @@ int ensure_core_btf(struct bpf_object_open_opts* opts) + } + + opts->btf_custom_path = strdup(btf_file); ++ if (!opts->btf_custom_path) { ++ return -1; ++ } + return 0; + } + +diff --git a/src/common/json_tool.cpp b/src/common/json_tool.cpp +index d5cf52fe..96fceb90 100644 +--- a/src/common/json_tool.cpp ++++ b/src/common/json_tool.cpp +@@ -148,10 +148,16 @@ 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) { ++ goto err; ++ } + kv.valuePtr = (void *)(&(*it)); + ++kv_pairs->len; + } + return kv_pairs; ++err: ++ Json_DeleteKeyValuePairs(kv_pairs); ++ return nullptr; + } + + void Json_DeleteKeyValuePairs(struct key_value_pairs *kv_pairs) +@@ -307,5 +313,8 @@ char *Json_PrintUnformatted(void *jsonObj) + Json::FastWriter writer; + std::string strJson = writer.write(*jsObj); + char *res = strdup(strJson.c_str()); ++ if (!res) { ++ return nullptr; ++ } + return res; + } +diff --git a/src/lib/probe/probe_mng.c b/src/lib/probe/probe_mng.c +index 24027ce9..d0713788 100644 +--- a/src/lib/probe/probe_mng.c ++++ b/src/lib/probe/probe_mng.c +@@ -35,7 +35,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}, +@@ -359,6 +359,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) { ++ goto err; ++ } + + ret = pthread_rwlock_init(&probe->rwlock, NULL); + if (ret) { +@@ -376,7 +379,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 +445,16 @@ 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->bin) { ++ return -1; ++ } + + if (is_extend_probe(probe)) { + probe->is_extend_probe = 1; +@@ -453,13 +462,13 @@ 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) +@@ -703,7 +712,6 @@ static int probe_parser_cmd(struct probe_s *probe, const void *item) + + static void probe_backup_cmd(struct probe_s *probe, struct probe_s *probe_backup) + { +- probe_backup->bin = probe->bin ? strdup(probe->bin) : NULL; + probe_backup->is_extend_probe = probe->is_extend_probe; + probe_backup->probe_entry = probe->probe_entry; + probe_backup->cb = probe->cb; +@@ -716,9 +724,6 @@ static void probe_rollback_cmd(struct probe_s *probe, struct probe_s *probe_back + free(probe->bin); + } + +- probe->bin = probe_backup->bin; +- probe_backup->bin = NULL; +- + probe->is_extend_probe = probe_backup->is_extend_probe; + probe->probe_entry = probe_backup->probe_entry; + probe->cb = probe_backup->cb; +diff --git a/src/lib/probe/snooper.c b/src/lib/probe/snooper.c +index 15d3ad1d..476aa73e 100644 +--- a/src/lib/probe/snooper.c ++++ b/src/lib/probe/snooper.c +@@ -149,9 +149,17 @@ static int add_snooper_conf_procname(struct probe_s *probe, + (void)snprintf(snooper_conf->conf.app.comm, sizeof(snooper_conf->conf.app.comm), "%s", comm); + if (cmdline && cmdline[0] != 0) { + snooper_conf->conf.app.cmdline = strdup(cmdline); ++ if (!snooper_conf->conf.app.cmdline) { ++ free_snooper_conf(snooper_conf); ++ return -1; ++ } + } + if (dbgdir && dbgdir[0] != 0) { + snooper_conf->conf.app.debuging_dir = strdup(dbgdir); ++ if (!snooper_conf->conf.app.debuging_dir) { ++ free_snooper_conf(snooper_conf); ++ return -1; ++ } + } + snooper_conf->type = SNOOPER_CONF_APP; + +@@ -733,7 +741,6 @@ void free_snooper_obj(struct snooper_obj_s* snooper_obj) + (void)free(snooper_obj->obj.con_info.libssl_path); + } + } +- + (void)free(snooper_obj); + snooper_obj = NULL; + } +@@ -970,20 +977,37 @@ static int add_snooper_obj_con_info(struct probe_s *probe, struct con_info_s *co + DEBUG("[SNOOPER] Adding container %s to snooper obj\n", con_info->con_id ?:"unknown"); + snooper_obj->type = SNOOPER_OBJ_CON; + snooper_obj->obj.con_info.cpucg_inode = con_info->cpucg_inode; +- if (con_info->con_id) { ++ if (con_info->con_id[0] != 0) { + snooper_obj->obj.con_info.con_id = strdup(con_info->con_id); ++ if (!snooper_obj->obj.con_info.con_id) { ++ goto err; ++ } + } +- if (probe->probe_type == PROBE_SLI && con_info->container_name) { ++ if (probe->probe_type == PROBE_SLI && (!con_info->container_name[0])) { + snooper_obj->obj.con_info.container_name = strdup(con_info->container_name); ++ if (!snooper_obj->obj.con_info.container_name) { ++ goto err; ++ } + } +- if (probe->probe_type == PROBE_PROC && con_info->libc_path) { ++ if (probe->probe_type == PROBE_PROC && (!con_info->libc_path[0])) { + snooper_obj->obj.con_info.libc_path = strdup(con_info->libc_path); ++ if (!snooper_obj->obj.con_info.libc_path) { ++ goto err; ++ } + } +- if (probe->probe_type == PROBE_L7 && con_info->libssl_path) { ++ if (probe->probe_type == PROBE_L7 && (!con_info->libssl_path[0])) { + snooper_obj->obj.con_info.libssl_path = strdup(con_info->libssl_path); ++ if (!snooper_obj->obj.con_info.libssl_path) { ++ goto err; ++ } + } + probe->snooper_objs[pos] = snooper_obj; + return 0; ++ ++err: ++ WARN("add_snooper_obj_con_info add snooper obj failed !\n"); ++ free_snooper_obj(snooper_obj); ++ return -1; + } + + static int gen_snooper_by_procname(struct probe_s *probe) +@@ -1149,7 +1173,11 @@ static int gen_snooper_by_container_name(struct probe_s *probe) + continue; + } + +- (void)add_snooper_obj_con_info(probe, con_info); ++ if (add_snooper_obj_con_info(probe, con_info) == -1) { ++ WARN("[SNOOPER] Fail to add snooper to con info from container name %s\n", ++ con_info->con_id[0] == 0 ? "null" : con_info->con_id, snooper_conf->conf.container_name); ++ continue; ++ } + } + (void)pclose(f); + } +@@ -1179,7 +1207,11 @@ static int gen_snooper_by_container(struct probe_s *probe) + free_con_id_list(con_id_list); + return -1; + } +- (void)add_snooper_obj_con_info(probe, con_info); ++ if (add_snooper_obj_con_info(probe, con_info) == -1) { ++ WARN("[SNOOPER] Fail to add snooper to container info from container name %s\n", ++ con_info->con_id[0] == 0 ? "null" : con_info->con_id, snooper_conf->conf.container_name); ++ continue; ++ } + } + + if (con_id_list) { +@@ -1218,7 +1250,11 @@ static int gen_snooper_by_pod(struct probe_s *probe) + free_con_id_list(con_id_list); + return -1; + } +- (void)add_snooper_obj_con_info(probe, &con->con_info); ++ if (add_snooper_obj_con_info(probe, &con->con_info) == -1) { ++ WARN("[SNOOPER] Fail to add snooper to pod info from container name %s\n", ++ con->con_info.con_id[0] == 0 ? "null" : con->con_info.con_id, snooper_conf->conf.container_name); ++ continue; ++ } + } + } + } +@@ -1426,18 +1462,15 @@ static char __rcv_snooper_cgrp_exec_sub(struct probe_s *probe, struct con_info_s + if (snooper_conf->type == SNOOPER_CONF_POD_ID) { + if (con_info->pod_info_ptr->pod_id[0] != 0 && + !strcasecmp(con_info->pod_info_ptr->pod_id, snooper_conf->conf.pod_id)) { +- add_snooper_obj_con_info(probe, con_info); +- snooper_obj_added = 1; ++ snooper_obj_added = add_snooper_obj_con_info(probe, con_info) == -1 ? 0 : 1; + } + } else if (snooper_conf->type == SNOOPER_CONF_CONTAINER_ID) { + if (con_info->con_id[0] != 0 && !strcasecmp(con_info->con_id, snooper_conf->conf.container_id)) { +- add_snooper_obj_con_info(probe, con_info); +- snooper_obj_added = 1; ++ snooper_obj_added = add_snooper_obj_con_info(probe, con_info) == -1 ? 0: 1; + } + } else if (snooper_conf->type == SNOOPER_CONF_CONTAINER_NAME) { + if (strstr((const char *)con_info->container_name, (const char *)(snooper_conf->conf.container_name)) != NULL) { +- add_snooper_obj_con_info(probe, con_info); +- snooper_obj_added = 1; ++ snooper_obj_added = add_snooper_obj_con_info(probe, con_info) == -1 ? 0 : 1; + } + } + } +diff --git a/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.c b/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.c +index 616c639c..76fa6076 100644 +--- a/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.c ++++ b/src/probes/extends/ebpf.probe/src/endpointprobe/endpoint.c +@@ -625,15 +625,16 @@ static int add_tcp_sock_evt(struct endpoint_probe_s * probe, struct tcp_socket_e + ip_str(new_tcp->id.server_ipaddr.family, (unsigned char *)&(new_tcp->id.server_ipaddr.ip), server_ip_str, INET6_ADDRSTRLEN); + new_tcp->client_ip = strdup((const char *)client_ip_str); + new_tcp->server_ip = strdup((const char *)server_ip_str); ++ if (new_tcp->client_ip == NULL || new_tcp->server_ip == NULL) { ++ goto err; ++ } + if (new_tcp->id.toa_client_ipaddr.family == AF_INET || new_tcp->id.toa_client_ipaddr.family == AF_INET6) { + ip_str(new_tcp->id.toa_client_ipaddr.family, (unsigned char *)&(new_tcp->id.toa_client_ipaddr.ip), toa_client_ip_str, INET6_ADDRSTRLEN); + new_tcp->toa_client_ip = strdup((const char *)toa_client_ip_str); ++ if (!new_tcp->toa_client_ip) { ++ goto err; ++ } + } +- +- if (new_tcp->client_ip == NULL || new_tcp->server_ip == NULL) { +- goto err; +- } +- + H_ADD_KEYPTR(probe->tcps, &new_tcp->id, sizeof(struct tcp_socket_id_s), new_tcp); + probe->tcp_socks_num++; + return 0; +diff --git a/src/probes/extends/ebpf.probe/src/ioprobe/ioprobe.c b/src/probes/extends/ebpf.probe/src/ioprobe/ioprobe.c +index 3c508e72..b0123cfd 100644 +--- a/src/probes/extends/ebpf.probe/src/ioprobe/ioprobe.c ++++ b/src/probes/extends/ebpf.probe/src/ioprobe/ioprobe.c +@@ -257,6 +257,7 @@ static void free_blk_cache(struct blk_cache_s *cache) + } + + free(cache); ++ cache = NULL; + return; + } + +@@ -293,14 +294,23 @@ static struct blk_cache_s *add_blk_cache(struct blk_cache_s **caches, int major, + + if (dev_name[0] != 0) { + new_cache->dev_name = strdup((const char *)dev_name); ++ if (!new_cache->dev_name) { ++ goto err; ++ } + } + if (disk_name[0] != 0) { + new_cache->disk_name = strdup((const char *)disk_name); ++ if (!new_cache->disk_name) { ++ goto err; ++ } + } + + H_ADD_KEYPTR(*caches, &new_cache->id, sizeof(struct blk_id_s), new_cache); + + return new_cache; ++err: ++ free_blk_cache(new_cache); ++ return NULL; + } + + static struct blk_cache_s *get_blk_cache(struct blk_tbl_s *tbl, int major, int minor) +diff --git a/src/probes/extends/ebpf.probe/src/l7probe/conn_tracker.c b/src/probes/extends/ebpf.probe/src/l7probe/conn_tracker.c +index 8b446a29..de991685 100644 +--- a/src/probes/extends/ebpf.probe/src/l7probe/conn_tracker.c ++++ b/src/probes/extends/ebpf.probe/src/l7probe/conn_tracker.c +@@ -236,6 +236,10 @@ static struct l7_link_s* create_l7_link(const struct l7_link_id_s *id) + ip_str(link->id.client_addr.family, (unsigned char *)&(link->id.client_addr.ip), ip, INET6_ADDRSTRLEN); + if (ip[0] != 0) { + link->client_ip = strdup((const char *)ip); ++ if (!link->client_ip) { ++ free(link); ++ return NULL; ++ } + } + } + +@@ -244,6 +248,11 @@ static struct l7_link_s* create_l7_link(const struct l7_link_id_s *id) + ip_str(link->id.server_addr.family, (unsigned char *)&(link->id.server_addr.ip), ip, INET6_ADDRSTRLEN); + if (ip[0] != 0) { + link->server_ip = strdup((const char *)ip); ++ if (!link->server_ip) { ++ free(link->client_ip); ++ free(link); ++ return NULL; ++ } + } + } + +diff --git a/src/probes/extends/ebpf.probe/src/l7probe/l7probe.c b/src/probes/extends/ebpf.probe/src/l7probe/l7probe.c +index cb6738f0..b8fee8ba 100644 +--- a/src/probes/extends/ebpf.probe/src/l7probe/l7probe.c ++++ b/src/probes/extends/ebpf.probe/src/l7probe/l7probe.c +@@ -162,6 +162,10 @@ static int __add_libssl_prog(struct l7_mng_s *l7_mng, struct bpf_prog_s *prog, c + if (l7_mng->bpf_progs.libssl_progs[i].prog == NULL) { + l7_mng->bpf_progs.libssl_progs[i].prog = prog; + l7_mng->bpf_progs.libssl_progs[i].libssl_path = strdup(libssl); ++ if (!l7_mng->bpf_progs.libssl_progs[i].libssl_path) { ++ l7_mng->bpf_progs.libssl_progs[i].prog = NULL; ++ return -1; ++ } + return 0; + } + } +diff --git a/src/probes/extends/ebpf.probe/src/lib/conntrack.c b/src/probes/extends/ebpf.probe/src/lib/conntrack.c +index ead0f88c..6a43d845 100644 +--- a/src/probes/extends/ebpf.probe/src/lib/conntrack.c ++++ b/src/probes/extends/ebpf.probe/src/lib/conntrack.c +@@ -113,6 +113,9 @@ static struct tcp_conntrack_s *parse_conntrack_tcp(const char *s) + goto err; + } + conn_tcp->src = strdup((const char *)sub_str); ++ if (!conn_tcp->src) { ++ goto err; ++ } + + // parse conntrack tcp dst ip address + p = strstr((const char *)s, "dst="); +@@ -124,6 +127,9 @@ static struct tcp_conntrack_s *parse_conntrack_tcp(const char *s) + goto err; + } + conn_tcp->dst = strdup((const char *)sub_str); ++ if (!conn_tcp->dst) { ++ goto err; ++ } + + // parse conntrack tcp src port + p = strstr((const char *)p, "sport="); +@@ -157,6 +163,9 @@ static struct tcp_conntrack_s *parse_conntrack_tcp(const char *s) + goto err; + } + conn_tcp->reply_src = strdup((const char *)sub_str); ++ if (!conn_tcp->reply_src) { ++ goto err; ++ } + + // parse conntrack tcp reply dst ip address + p = strstr((const char *)p, "dst="); +@@ -168,6 +177,9 @@ static struct tcp_conntrack_s *parse_conntrack_tcp(const char *s) + goto err; + } + conn_tcp->reply_dst = strdup((const char *)sub_str); ++ if (!conn_tcp->reply_src) { ++ goto err; ++ } + + // parse conntrack tcp reply src port + p = strstr((const char *)p, "sport="); +diff --git a/src/probes/extends/ebpf.probe/src/lib/symbol.c b/src/probes/extends/ebpf.probe/src/lib/symbol.c +index 42270a36..8345769b 100644 +--- a/src/probes/extends/ebpf.probe/src/lib/symbol.c ++++ b/src/probes/extends/ebpf.probe/src/lib/symbol.c +@@ -519,7 +519,7 @@ static int get_mod_type(struct mod_info_s* mod_info) + return GET_MOD_TYPE; + } + +-static void __do_get_mod_path_byname(struct mod_info_s* mod_info, int proc_id) ++static int __do_get_mod_path_byname(struct mod_info_s* mod_info, int proc_id) + { + char *fmt = "/proc/%d/root%s"; + char path[PATH_LEN]; +@@ -527,7 +527,10 @@ static void __do_get_mod_path_byname(struct mod_info_s* mod_info, int proc_id) + path[0] = 0; + (void)snprintf(path, PATH_LEN, fmt, proc_id, mod_info->name); + mod_info->path = strdup(path); +- return; ++ if (!mod_info->path) { ++ return -1; ++ } ++ return 0; + } + + #define IS_CONTAIN_STR(s, contain_s) (strstr(s, contain_s)) +@@ -548,10 +551,15 @@ static int get_mod_path(struct mod_info_s* mod_info, int proc_id) + } + if (mod_info->type == MODULE_JVM) { + mod_info->path = strdup(mod_info->name); ++ if (!mod_info->path) { ++ return -1; ++ } + return 0; + } + if (!IS_BACKEND_MOD(mod_info->name)) { +- __do_get_mod_path_byname(mod_info, proc_id); ++ if (__do_get_mod_path_byname(mod_info, proc_id) == -1) { ++ goto err; ++ } + return 0; + } + +@@ -572,6 +580,9 @@ static int get_mod_path(struct mod_info_s* mod_info, int proc_id) + + if (f_stat.st_ino == mod_info->inode) { + mod_info->path = strdup(fd_file); ++ if (!mod_info->path) { ++ goto err; ++ } + ret = 0; + break; + } +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tracker.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tracker.c +index 79ed2320..959ed0e4 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tracker.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tracker.c +@@ -141,14 +141,14 @@ struct toa_socket_s *create_toa_sock(const struct toa_sock_id_s *id) + return toa_sock; + } + ++#define TCP_TRACKER_MAX (4 * 1024) + static struct tcp_tracker_s* create_tcp_tracker(struct tcp_mng_s *tcp_mng, const struct tcp_tracker_id_s *id) + { + unsigned char src_ip_str[INET6_ADDRSTRLEN]; + unsigned char dst_ip_str[INET6_ADDRSTRLEN]; + unsigned char toa_src_ip_str[INET6_ADDRSTRLEN]; + +-#define __TCP_TRACKER_MAX (4 * 1024) +- if (tcp_mng->tcp_tracker_count >= __TCP_TRACKER_MAX) { ++ if (tcp_mng->tcp_tracker_count >= TCP_TRACKER_MAX) { + ERROR("[TCPPROBE]: Create 'tcp_tracker' failed(upper to limited).\n"); + return NULL; + } +@@ -168,6 +168,9 @@ static struct tcp_tracker_s* create_tcp_tracker(struct tcp_mng_s *tcp_mng, const + if (tracker->id.toa_famlily == AF_INET || tracker->id.toa_famlily == AF_INET6) { + ip_str(tracker->id.toa_famlily, (unsigned char *)&(tracker->id.toa_c_ip), toa_src_ip_str, INET6_ADDRSTRLEN); + tracker->toa_src_ip = strdup((const char *)toa_src_ip_str); ++ if (!tracker->toa_src_ip) { ++ goto err; ++ } + } + + if (tracker->src_ip == NULL || tracker->dst_ip == NULL) { +@@ -180,9 +183,7 @@ static struct tcp_tracker_s* create_tcp_tracker(struct tcp_mng_s *tcp_mng, const + return tracker; + + err: +- if (tracker) { +- destroy_tcp_tracker(tracker); +- } ++ destroy_tcp_tracker(tracker); + return NULL; + } + +@@ -395,6 +396,9 @@ struct tcp_tracker_s *get_tcp_tracker(struct tcp_mng_s *tcp_mng, const void *lin + + void destroy_tcp_tracker(struct tcp_tracker_s* tracker) + { ++ if (!tracker) { ++ return; ++ } + if (tracker->src_ip) { + free(tracker->src_ip); + } +@@ -407,7 +411,6 @@ void destroy_tcp_tracker(struct tcp_tracker_s* tracker) + free(tracker->toa_src_ip); + } + free(tracker); +- return; + } + + void destroy_tcp_trackers(struct tcp_mng_s *tcp_mng) +-- +2.33.0 + diff --git a/gala-gopher.spec b/gala-gopher.spec index 5016ae8..687e513 100644 --- a/gala-gopher.spec +++ b/gala-gopher.spec @@ -25,12 +25,13 @@ %define disable_report_event 0 %define disable_kafka_channel 0 %define disable_flamegraph_svg 0 +%define disable_l4_toa 1 Summary: Intelligent ops toolkit for openEuler Name: gala-gopher Version: 2.0.2 -Release: 3 +Release: 4 License: Mulan PSL v2 URL: https://gitee.com/openeuler/gala-gopher Source: %{name}-%{version}.tar.gz @@ -96,6 +97,51 @@ Requires: jsoncpp conntrack-tools Requires: lsof %endif +Patch1: fix-restart-thread-block-by-resetting-probe-pid.patch +Patch2: fix-service-failed-when-cmd-server-thread-starts-lat.patch +Patch3: add-error-log-of-mismatch-between-metric-data-and-me.patch +Patch4: Simplify-the-error-handling-process-by-using-goto-st.patch +Patch5: fix-OOB-write-when-getting-proc-cmdline.patch +Patch6: fix-Memory-leak.patch +Patch7: Found-a-exit-path-has-missing-return-statement.patch +Patch8: fix-restart-gopher-failed-for-check-gopher-pid-multi.patch +Patch9: fix-run-sig-hander-core-for-probe-mng-create-later.patch +Patch10: ipc.py-fix-incompatible-struct-definition-of-Snooper.patch +Patch11: fix-prog-load-failure-due-to-loops-in-toa-code.patch +Patch12: add-log-level-info-to-logs-of-main-process.patch +Patch13: fix-potential-nullptr-dereference-in-libevent-openss.patch +Patch14: ipc-reset-probe_flags-to-0-when-restarting-probes.patch +Patch15: tcpprobe-do-not-flush-snooped-procs-to-avoid-deletin.patch +Patch16: tcpprobe-poll-from-last-buffer-to-adapt-for-pinned-p.patch +Patch17: tcpprobe-reset-sk-link-state-when-tcp-link-was-delet.patch +Patch18: fix-buffer-overflow-in-sscanf.patch +Patch19: fix-buffer-overflow-and-ret-value-of-sscanf.patch +Patch20: snooper-enlarge-channel-map-and-shorten-poll-timeout.patch +Patch21: system_infos-fix-oob-of-arrays-and-double-free.patch +Patch22: tcpprobe-report-all-metrics-of-a-tracker-in-one-outp.patch +Patch23: tcpprobe-remove-superfluous-buffer__open-to-reduce-m.patch +Patch24: Refactor-to-reduce-memory-usage-of-metric-record.patch +Patch25: bugfix-path-parsing-error-when-gala-gopher-running-i.patch +Patch26: fix-strdup-relative-error.patch +Patch27: tcpprobe-fix-incorret-struct-type-of-tracepoint-even.patch +Patch28: simplify-dissection-of-toa-and-make-it-valid-on-olde.patch +Patch29: PFM_OPT-tcpprobe-reduce-the-scanning-times-of-tracke.patch +Patch30: PFM_OPT-imdb-optimize-the-type-of-record-value-and-a.patch +Patch31: fix-UAF-of-probe-bin-after-parsing-invalid-config.patch +Patch32: remove-extra-strlen-and-snprintf-when-writing-metric.patch +Patch33: PFM_OPT-tcpprobe-merge-win-sockbuf-rtt-rate-subprobe.patch +Patch34: fix-home-check.patch +Patch35: keep-consuming-output-of-extend-probes-when-failed-t.patch +Patch36: snooper-optimize-the-size-of-proc-event.patch +Patch37: snooper-fix-opposite-judgment-logic-of-container-inf.patch +Patch38: snooper-use-file-op-to-read-proc-comm-and-stat-inste.patch +Patch39: avoid-conflict-of-kprobe-between-tcp_link-and-tcp_rx.patch +Patch40: snooper-fix-incorrect-flags-when-resending-ipc-msg.patch +Patch41: fix-extra-length-of-task-comm.patch +Patch42: snooper-refix-incorrect-flags-when-resending-ipc-msg.patch +Patch43: Fix-some-resource-leak-and-oob-issues.patch +Patch44: epprobe-adapt-hook-point-of-req_drops-according-to-k.patch +Patch45: tcpprobe-fix-inaccurate-notack_bytes.patch %description gala-gopher is a low-overhead eBPF-based probes framework @@ -132,6 +178,7 @@ BUILD_OPTS=( -DENABLE_REPORT_EVENT=%[0%{?disable_report_event}?0:1] -DKAFKA_CHANNEL=%[0%{?disable_kafka_channel}?0:1] -DFLAMEGRAPH_SVG=%[0%{?disable_flamegraph_svg}?0:1] + -DL4_TOA=%[0%{?disable_l4_toa}?0:1] ) pushd build @@ -193,6 +240,26 @@ fi %attr(0550,root,root) /usr/libexec/gala-gopher/start_pre.sh %changelog +* Fri Nov 28 2025 Chenzhen - 2.0.2-4 +- fix restart thread block by resetting probe pid + fix service failed when cmd server thread starts late + fix OOB write when getting proc cmdline + fix restart gopher failed for check gopher pid multi times + fix run sig hander core for probe mng create later + fix potential nullptr dereference in libevent openssl cb + ipc: reset probe_flags to 0 when restarting probes + tcpprobe: do not flush snooped procs to avoid deleting tcp link by accident + fix buffer overflow in sscanf + fix buffer overflow and ret value of sscanf + snooper: enlarge channel map and shorten poll timeout to ease event loss + system_infos: fix oob of arrays and double free + Refactor to reduce memory usage of metric record + bugfix: path parsing error when gala-gopher running in container + fix strdup relative error + tcpprobe: fix incorret struct type of tracepoint event + fix UAF of probe bin after parsing invalid config + snooper: fix opposite judgment logic of container info + * Thu Jul 24 2025 Haitao Peng - 2.0.2-3 - Modify openEuler to %{_vendor} diff --git a/ipc-reset-probe_flags-to-0-when-restarting-probes.patch b/ipc-reset-probe_flags-to-0-when-restarting-probes.patch new file mode 100644 index 0000000..2c3d607 --- /dev/null +++ b/ipc-reset-probe_flags-to-0-when-restarting-probes.patch @@ -0,0 +1,26 @@ +From 0566a56c896d17972fd246acc217a053823ef1d7 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Tue, 24 Dec 2024 13:23:01 +0800 +Subject: [PATCH 32/99] ipc: reset probe_flags to 0 when restarting probes + +--- + src/lib/probe/snooper.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/lib/probe/snooper.c b/src/lib/probe/snooper.c +index 82cf3679..15d3ad1d 100644 +--- a/src/lib/probe/snooper.c ++++ b/src/lib/probe/snooper.c +@@ -625,6 +625,9 @@ static void __build_ipc_body(struct probe_s *probe, struct ipc_body_s* ipc_body) + if (probe->is_snooper_chg) { + ipc_body->probe_flags |= IPC_FLAGS_SNOOPER_CHG; + } ++ if (probe->resnd_snooper_for_restart) { ++ ipc_body->probe_flags = 0; ++ } + memcpy(&(ipc_body->probe_param), &probe->probe_param, sizeof(struct probe_params)); + return; + } +-- +2.33.0 + diff --git a/ipc.py-fix-incompatible-struct-definition-of-Snooper.patch b/ipc.py-fix-incompatible-struct-definition-of-Snooper.patch new file mode 100644 index 0000000..436225c --- /dev/null +++ b/ipc.py-fix-incompatible-struct-definition-of-Snooper.patch @@ -0,0 +1,25 @@ +From c049dde1a45e020a9941c2d81abcdf7dbcccd2b5 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Fri, 29 Nov 2024 10:49:35 +0800 +Subject: [PATCH 25/99] ipc.py: fix incompatible struct definition of + SnooperConnInfo + +--- + src/probes/extends/python.probe/common/ipc.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/probes/extends/python.probe/common/ipc.py b/src/probes/extends/python.probe/common/ipc.py +index 0fa5fbfb..bb211898 100644 +--- a/src/probes/extends/python.probe/common/ipc.py ++++ b/src/probes/extends/python.probe/common/ipc.py +@@ -60,6 +60,7 @@ class SnooperConnInfo(Structure): + _fields_ = [ + ("cpucg_inode", c_uint), + ("con_id", c_char_p), ++ ("container_name", c_char_p), + ("libc_path", c_char_p), + ("libssl_path", c_char_p), + ] +-- +2.33.0 + diff --git a/keep-consuming-output-of-extend-probes-when-failed-t.patch b/keep-consuming-output-of-extend-probes-when-failed-t.patch new file mode 100644 index 0000000..b483ee1 --- /dev/null +++ b/keep-consuming-output-of-extend-probes-when-failed-t.patch @@ -0,0 +1,28 @@ +From 7e56fbeb88fad20d83f3417c2731a5d29fd39881 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Mon, 24 Feb 2025 20:59:35 +0800 +Subject: [PATCH 61/99] keep consuming output of extend probes when failed to + stop them due to lkup pid failed + +--- + src/lib/probe/extend_probe.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/src/lib/probe/extend_probe.c b/src/lib/probe/extend_probe.c +index ceba2580..1be4a1c7 100644 +--- a/src/lib/probe/extend_probe.c ++++ b/src/lib/probe/extend_probe.c +@@ -82,10 +82,6 @@ static void parseExtendProbeOutput(struct probe_s *probe, FILE *f) + time_t secs; + + while (feof(f) == 0 && ferror(f) == 0) { +- if (IS_STOPPING_PROBE(probe)) { +- break; +- } +- + if (FifoFull(probe->fifo)) { + writeIngressEvt(probe); + sleep(1); // Rate limiting for probes +-- +2.33.0 + diff --git a/remove-extra-strlen-and-snprintf-when-writing-metric.patch b/remove-extra-strlen-and-snprintf-when-writing-metric.patch new file mode 100644 index 0000000..ef0f113 --- /dev/null +++ b/remove-extra-strlen-and-snprintf-when-writing-metric.patch @@ -0,0 +1,72 @@ +From 7c1794cca42f6c47bf2f753abfba4dfd73e44068 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Thu, 6 Feb 2025 00:49:31 +0800 +Subject: [PATCH 54/99] remove extra strlen and snprintf when writing metrics + +--- + src/common/logs.c | 15 +++++++-------- + 1 file changed, 7 insertions(+), 8 deletions(-) + +diff --git a/src/common/logs.c b/src/common/logs.c +index 75621c34..085c03fd 100644 +--- a/src/common/logs.c ++++ b/src/common/logs.c +@@ -659,7 +659,7 @@ static void check_file_state(struct logger *logger) + } + } + +-static void write_log(const char *msg, struct logger *logger) ++static void write_log(const char *msg, size_t msg_len, struct logger *logger) + { + if (logger == NULL) { + return; +@@ -682,12 +682,11 @@ static void write_log(const char *msg, struct logger *logger) + } + } + (void)lseek(logger->file_fd, 0, SEEK_END); +- const size_t buffer_length = strlen(msg); +- write_ret = write(logger->file_fd, msg, buffer_length); ++ write_ret = write(logger->file_fd, msg, msg_len); + if (write_ret == -1) { + (void)printf("[ERROR]: write to log file failed, errno[%d].\n", errno); + } +- logger->buf_len += buffer_length; ++ logger->buf_len += msg_len; + (void)pthread_rwlock_unlock(&logger->rwlock); + } + +@@ -708,11 +707,11 @@ static void log_without_date(struct logger *logger, const char *detail) + free(msg); + return; + } +- write_log(msg, logger); ++ write_log(msg, strlen(msg), logger); + free(msg); + } + +-int wr_metrics_logs(const char* logs, size_t logs_len) ++int wr_metrics_logs(const char *logs, size_t logs_len) + { + struct log_mgr_s *mgr = local; + if (!mgr) { +@@ -726,7 +725,7 @@ int wr_metrics_logs(const char* logs, size_t logs_len) + return -1; + } + } +- log_without_date(&g_metrics_logger, logs); ++ write_log(logs, logs_len, &g_metrics_logger); + que_current_set_size(mgr->metrics_files, logs_len); + pthread_mutex_unlock(&metric_mutex); + return 0; +@@ -835,7 +834,7 @@ static void log_with_date(struct logger *logger, const char *detail, enum logger + if (ret == -1) { + return; + } +- write_log(msg, logger); ++ write_log(msg, strlen(msg), logger); + } + + void convert_output_to_log(char *buffer, int bufferSize) +-- +2.33.0 + diff --git a/simplify-dissection-of-toa-and-make-it-valid-on-olde.patch b/simplify-dissection-of-toa-and-make-it-valid-on-olde.patch new file mode 100644 index 0000000..a7f7489 --- /dev/null +++ b/simplify-dissection-of-toa-and-make-it-valid-on-olde.patch @@ -0,0 +1,359 @@ +From c2b272539e0e25433637934e2cfecb1e8dba6dee Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Thu, 16 Jan 2025 02:51:21 +0800 +Subject: [PATCH 50/99] simplify dissection of toa and make it valid on older + kernel + +--- + .../ebpf.probe/src/endpointprobe/tcp.bpf.c | 137 +++++++----------- + .../extends/ebpf.probe/src/include/toa.h | 2 +- + .../ebpf.probe/src/tcpprobe/tcp_link.bpf.c | 137 +++++++----------- + 3 files changed, 102 insertions(+), 174 deletions(-) + +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 43832917..6b0aa820 100644 +--- a/src/probes/extends/ebpf.probe/src/endpointprobe/tcp.bpf.c ++++ b/src/probes/extends/ebpf.probe/src/endpointprobe/tcp.bpf.c +@@ -679,74 +679,65 @@ end: + * @return NULL if we don't get client ip/port; + * value of toa_data in ret_ptr if we get client ip/port. + */ +-static void *get_toa_data(struct sk_buff *skb, int af, enum toa_type *type, struct toa_v6_entry *v6_toa_data) ++static __always_inline bool get_toa_data(const struct tcphdr *th, int af, struct tcp_socket_event_s *evt) + { +- const struct tcphdr *th = NULL; + int length; +- const unsigned char *ptr = NULL; +- void *ret_ptr = NULL; ++ u8 buffer[MAX_TCPOPT_LEN]; ++ u8 opcode, opsize = 0; + +- th = tcp_hdr(skb); ++ length = (BPF_CORE_READ_BITFIELD_PROBED(th, doff) << 2) - sizeof(struct tcphdr); ++ if (length < TCPOLEN_TOA) ++ return false; + +- u16 _doff = BPF_CORE_READ_BITFIELD_PROBED(th, doff); +- length = _doff * 4 - sizeof(struct tcphdr); +- if (length <= 0 || length > MAX_TCP_OPTIONS_LEN) { +- return NULL; +- } ++ if (bpf_probe_read_kernel(buffer, MAX_TCPOPT_LEN, (const unsigned char *)(th + 1)) < 0) ++ return false; + +- ptr = (const unsigned char *) (th + 1); +- if (ptr == NULL) { +- return NULL; +- } ++ #pragma unroll(MAX_TCPOPT_LEN - sizeof(struct toa_opt) + 1) ++ for (int i = 0; i <= MAX_TCPOPT_LEN - sizeof(struct toa_opt); i++) { ++ if (i > length - TCPOLEN_TOA) { ++ return false; ++ } ++ ++ // old version clang cannot unroll "i += opsize", so skip opsize of i in this way. ++ if (opsize) { ++ opsize--; ++ continue; ++ } ++ ++ opcode = buffer[i]; ++ if (opcode == TCPOPT_EOL) ++ return false; ++ ++ if (opcode == TCPOPT_NOP) { ++ opsize = 0; ++ continue; ++ } + +- while (length > 0) { +- int opcode = _(*ptr); +- ptr++; +- int opsize; +- switch (opcode) { +- case TCPOPT_EOL: { +- *type = TOA_NOT; +- return NULL; +- } +- case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */ +- length--; +- continue; +- default: +- opsize = _(*ptr); +- ptr++; +- if (opsize < 2) { +- /* "silly options" */ +- *type = TOA_NOT; +- return NULL; +- } +- if (opsize > length) { +- /* don't parse partial options */ +- *type = TOA_NOT; +- return NULL; +- } +- +- if (af == AF_INET && opcode == TCPOPT_TOA && opsize == TCPOLEN_TOA) { +- bpf_core_read(&ret_ptr, sizeof(struct toa_opt), ptr - 2); +- *type = TOA_IPV4; +- return ret_ptr; +- } else if (af == AF_INET6 && opcode == TCPOPT_TOA_V6 && opsize == TCPOLEN_TOA_V6) { +- bpf_core_read(&v6_toa_data->toa_data, sizeof(struct toa_opt_v6), ptr - 2); +- *type = TOA_IPV6; +- return v6_toa_data; +- } else if (af == AF_INET6 && opcode == TCPOPT_TOA && opsize == TCPOLEN_TOA) { +- bpf_core_read(&ret_ptr, sizeof(struct toa_opt), ptr - 2); +- *type = TOA_IPV4; +- return ret_ptr; +- } +- ptr += opsize - 2; +- length -= opsize; ++ opsize = buffer[i + 1]; ++ if (opsize < 2) ++ return false; ++ ++ if (opcode == TCPOPT_TOA && opsize == TCPOLEN_TOA) { ++ __builtin_memcpy(&evt->toa_client_ipaddr.ip, buffer + i + 4, sizeof(evt->toa_client_ipaddr.ip)); ++ evt->toa_client_ipaddr.family = AF_INET; ++ evt->server_ipaddr.family = af; ++ return true; ++ } ++ ++ if (af == AF_INET6 && opcode == TCPOPT_TOA_V6 && opsize == TCPOLEN_TOA_V6) { ++ if (i > length - TCPOLEN_TOA_V6 || i > MAX_TCPOPT_LEN - TCPOLEN_TOA_V6) ++ return false; ++ __builtin_memcpy(evt->toa_client_ipaddr.ip6, buffer + i + 4, IP6_LEN); ++ evt->toa_client_ipaddr.family = AF_INET6; ++ evt->server_ipaddr.family = af; ++ return true; + } + } + +- *type = TOA_NOT; +- return NULL; ++ return false; + } + ++ + /** + * Modify s_ip of link from TCP Option + * +@@ -766,36 +757,10 @@ static bool get_toa_from_opt(struct sk_buff *skb, struct tcp_socket_event_s *evt + return false; + } + +- // 2. Get toa_data from skb, and set is_toa flag +- void *toa_data_ptr = NULL; +- struct toa_v6_entry v6_toa_data = {0}; +- enum toa_type type = TOA_NOT; +- toa_data_ptr = get_toa_data(skb, af, &type, &v6_toa_data); +- if (toa_data_ptr == NULL || type == TOA_NOT) { +- return false; +- } +- +- // 3. Transfer Returned data into toa_opt or toa_v6_entry, and then extract ip and port +- switch (type) { +- case TOA_IPV4: { +- struct toa_opt opt = {0}; +- bpf_core_read(&opt, sizeof(struct toa_opt), &toa_data_ptr); +- evt->toa_client_ipaddr.ip = opt.ip; +- evt->toa_client_ipaddr.family = AF_INET; +- evt->server_ipaddr.family = af; +- break; +- } +- case TOA_IPV6: { +- __builtin_memcpy(evt->toa_client_ipaddr.ip6, v6_toa_data.toa_data.ip6, IP6_LEN); +- evt->toa_client_ipaddr.family = AF_INET6; +- evt->server_ipaddr.family = af; +- break; +- } +- default: +- return false; +- } + +- return true; ++ // 2. Get toa_data from skb ++ struct tcphdr *th = tcp_hdr((const struct sk_buff *)skb); ++ return get_toa_data(th, af, evt); + } + #else + static bool get_toa_from_opt(struct sk_buff *skb, struct tcp_socket_event_s *evt) +diff --git a/src/probes/extends/ebpf.probe/src/include/toa.h b/src/probes/extends/ebpf.probe/src/include/toa.h +index b5f5fdd5..cbc09cf4 100644 +--- a/src/probes/extends/ebpf.probe/src/include/toa.h ++++ b/src/probes/extends/ebpf.probe/src/include/toa.h +@@ -23,7 +23,7 @@ + #define TCPOPT_NOP 1 + #define ETH_P_IP 0x0800 + #define ETH_P_IPV6 0x86DD +-#define MAX_TCP_OPTIONS_LEN 40 // 15(max u4) * 4 - sizeof(tcphdr) ++#define MAX_TCPOPT_LEN 40 // 15(max u4) * 4 - sizeof(tcphdr) + + struct toa_opt { + u8 opcode; +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c +index 1d4208b5..d171068e 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c +@@ -263,73 +263,62 @@ static __always_inline struct tcphdr *tcp_hdr(const struct sk_buff *skb) + * @return NULL if we don't get client ip/port; + * value of toa_data in ret_ptr if we get client ip/port. + */ +-static void *get_toa_data(struct sk_buff *skb, int af, enum toa_type *type, struct toa_v6_entry *v6_toa_data) ++static __always_inline bool get_toa_data(const struct tcphdr *th, int af, struct tcp_link_s *link) + { +- const struct tcphdr *th = NULL; + int length; +- const unsigned char *ptr = NULL; +- void *ret_ptr = NULL; ++ u8 buffer[MAX_TCPOPT_LEN]; ++ u8 opcode, opsize = 0; + +- th = tcp_hdr((const struct sk_buff *) skb); ++ length = (BPF_CORE_READ_BITFIELD_PROBED(th, doff) << 2) - sizeof(struct tcphdr); ++ if (length < TCPOLEN_TOA) ++ return false; + +- u16 _doff = BPF_CORE_READ_BITFIELD_PROBED(th, doff); +- length = _doff * 4 - sizeof(struct tcphdr); +- if (length <= 0 || length > MAX_TCP_OPTIONS_LEN) { +- return NULL; +- } ++ if (bpf_probe_read_kernel(buffer, MAX_TCPOPT_LEN, (const unsigned char *)(th + 1)) < 0) ++ return false; + +- ptr = (const unsigned char *) (th + 1); +- if (ptr == NULL) { +- return NULL; +- } ++ #pragma unroll(MAX_TCPOPT_LEN - sizeof(struct toa_opt) + 1) ++ for (int i = 0; i <= MAX_TCPOPT_LEN - sizeof(struct toa_opt); i++) { ++ if (i > length - TCPOLEN_TOA) { ++ return false; ++ } ++ ++ // old version clang cannot unroll "i += opsize", so skip opsize of i in this way. ++ if (opsize) { ++ opsize--; ++ continue; ++ } ++ ++ opcode = buffer[i]; ++ if (opcode == TCPOPT_EOL) ++ return false; ++ ++ if (opcode == TCPOPT_NOP) { ++ opsize = 0; ++ continue; ++ } ++ ++ opsize = buffer[i + 1]; ++ if (opsize < 2) ++ return false; ++ ++ if (opcode == TCPOPT_TOA && opsize == TCPOLEN_TOA) { ++ __builtin_memcpy(&link->opt_c_ip, buffer + i + 4, sizeof(link->opt_c_ip)); ++ link->family = af; ++ link->opt_family = AF_INET; ++ return true; ++ } + +- // todo: 流程可优化为:先解套opcode&偏移opsize,再解出toa_opt或toa_opt_v6 +- while (length > 0) { +- int opcode = _(*ptr); +- ptr++; +- int opsize; +- switch (opcode) { +- case TCPOPT_EOL: { +- *type = TOA_NOT; +- return NULL; +- } +- case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */ +- length--; +- continue; +- default: +- opsize = _(*ptr); +- ptr++; +- if (opsize < 2) { +- /* "silly options" */ +- *type = TOA_NOT; +- return NULL; +- } +- if (opsize > length) { +- /* don't parse partial options */ +- *type = TOA_NOT; +- return NULL; +- } +- +- if (af == AF_INET && opcode == TCPOPT_TOA && opsize == TCPOLEN_TOA) { +- bpf_core_read(&ret_ptr, sizeof(struct toa_opt), ptr - 2); +- *type = TOA_IPV4; +- return ret_ptr; +- } else if (af == AF_INET6 && opcode == TCPOPT_TOA_V6 && opsize == TCPOLEN_TOA_V6) { +- bpf_core_read(&v6_toa_data->toa_data, sizeof(struct toa_opt_v6), ptr - 2); +- *type = TOA_IPV6; +- return v6_toa_data; +- } else if (af == AF_INET6 && opcode == TCPOPT_TOA && opsize == TCPOLEN_TOA) { +- bpf_core_read(&ret_ptr, sizeof(struct toa_opt), ptr - 2); +- *type = TOA_IPV4; +- return ret_ptr; +- } +- ptr += opsize - 2; +- length -= opsize; ++ if (af == AF_INET6 && opcode == TCPOPT_TOA_V6 && opsize == TCPOLEN_TOA_V6) { ++ if (i > length - TCPOLEN_TOA_V6 || i > MAX_TCPOPT_LEN - TCPOLEN_TOA_V6) ++ return false; ++ __builtin_memcpy(link->opt_c_ip6, buffer + i + 4, IP6_LEN); ++ link->family = af; ++ link->opt_family = AF_INET6; ++ return true; + } + } + +- *type = TOA_NOT; +- return NULL; ++ return false; + } + + /** +@@ -352,35 +341,9 @@ static bool get_toa_from_opt(struct sk_buff *skb, struct tcp_link_s *link) + return false; + } + +- // 2. Get toa_data from skb, and set is_toa flag +- void *toa_data_ptr = NULL; +- struct toa_v6_entry v6_toa_data = {0}; +- enum toa_type type = TOA_NOT; +- toa_data_ptr = get_toa_data(skb, af, &type, &v6_toa_data); +- if (toa_data_ptr == NULL || type == TOA_NOT) { +- return false; +- } +- +- // 3. Transfer Returned data into toa_opt or toa_v6_entry, and then extract ip and port +- switch (type) { +- case TOA_IPV4: { +- struct toa_opt opt = {0}; +- bpf_core_read(&opt, sizeof(struct toa_opt), &toa_data_ptr); +- link->opt_c_ip = opt.ip; +- link->family = af; +- link->opt_family = AF_INET; +- break; +- } +- case TOA_IPV6: { +- __builtin_memcpy(link->opt_c_ip6, v6_toa_data.toa_data.ip6, IP6_LEN); +- link->family = af; +- link->opt_family = AF_INET6; +- break; +- } +- default: +- return false; +- } +- return true; ++ // 2. Get toa_data from skb ++ struct tcphdr *th = tcp_hdr((const struct sk_buff *)skb); ++ return get_toa_data(th, af, link); + } + + static __always_inline int init_link_from_skb(struct sk_buff *skb, struct tcp_link_s *link) +-- +2.33.0 + diff --git a/snooper-enlarge-channel-map-and-shorten-poll-timeout.patch b/snooper-enlarge-channel-map-and-shorten-poll-timeout.patch new file mode 100644 index 0000000..c670dc4 --- /dev/null +++ b/snooper-enlarge-channel-map-and-shorten-poll-timeout.patch @@ -0,0 +1,55 @@ +From acbb0061547463fab7bf6cc5939f9e6818cc67c3 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Sat, 28 Dec 2024 15:15:20 +0800 +Subject: [PATCH 38/99] snooper: enlarge channel map and shorten poll timeout + to ease event loss + +--- + src/lib/probe/probe_mng.c | 5 +++-- + src/lib/probe/snooper.bpf.c | 2 +- + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/lib/probe/probe_mng.c b/src/lib/probe/probe_mng.c +index 89aff375..24027ce9 100644 +--- a/src/lib/probe/probe_mng.c ++++ b/src/lib/probe/probe_mng.c +@@ -1198,20 +1198,21 @@ static char is_keeplive_tmout(struct probe_mng_s *probe_mng) + return 0; + } + ++#define SNOOPER_POLL_TMOUT 100 // 100ms + void run_probe_mng_daemon(struct probe_mng_s *probe_mng) + { + int ret; + + for (;;) { + if (probe_mng->snooper_proc_pb != NULL) { +- ret = bpf_buffer__poll((struct bpf_buffer *)probe_mng->snooper_proc_pb, THOUSAND); ++ ret = bpf_buffer__poll((struct bpf_buffer *)probe_mng->snooper_proc_pb, SNOOPER_POLL_TMOUT); + if (ret < 0 && ret != -EINTR) { + break; + } + } + + if (probe_mng->snooper_cgrp_pb != NULL) { +- ret = bpf_buffer__poll((struct bpf_buffer *)probe_mng->snooper_cgrp_pb, THOUSAND); ++ ret = bpf_buffer__poll((struct bpf_buffer *)probe_mng->snooper_cgrp_pb, SNOOPER_POLL_TMOUT); + if (ret < 0 && ret != -EINTR) { + break; + } +diff --git a/src/lib/probe/snooper.bpf.c b/src/lib/probe/snooper.bpf.c +index 30bcc7f5..58846b6f 100644 +--- a/src/lib/probe/snooper.bpf.c ++++ b/src/lib/probe/snooper.bpf.c +@@ -33,7 +33,7 @@ char g_linsence[] SEC("license") = "GPL"; + + struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); +- __uint(max_entries, 256 *1024); ++ __uint(max_entries, 1024 * 1024); + } snooper_proc_channel SEC(".maps"); + + static __always_inline void process_new_forked_task(struct task_struct *child, void *ctx) +-- +2.33.0 + diff --git a/snooper-fix-incorrect-flags-when-resending-ipc-msg.patch b/snooper-fix-incorrect-flags-when-resending-ipc-msg.patch new file mode 100644 index 0000000..4b9701f --- /dev/null +++ b/snooper-fix-incorrect-flags-when-resending-ipc-msg.patch @@ -0,0 +1,26 @@ +From 0b9865937636eb3753105b3ca3055d1b53ef8a4a Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Sat, 17 May 2025 00:07:54 +0800 +Subject: [PATCH 74/99] snooper: fix incorrect flags when resending ipc msg + +Fixes: 0566a56c896(ipc: reset probe_flags to 0 when restarting probes) +--- + src/lib/probe/snooper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lib/probe/snooper.c b/src/lib/probe/snooper.c +index 1fa67a82..57aec210 100644 +--- a/src/lib/probe/snooper.c ++++ b/src/lib/probe/snooper.c +@@ -634,7 +634,7 @@ static void __build_ipc_body(struct probe_s *probe, struct ipc_body_s* ipc_body) + ipc_body->probe_flags |= IPC_FLAGS_SNOOPER_CHG; + } + if (probe->resnd_snooper_for_restart) { +- ipc_body->probe_flags = 0; ++ ipc_body->probe_flags = (IPC_FLAGS_SNOOPER_CHG | IPC_FLAGS_SNOOPER_CHG); + } + memcpy(&(ipc_body->probe_param), &probe->probe_param, sizeof(struct probe_params)); + return; +-- +2.33.0 + diff --git a/snooper-fix-opposite-judgment-logic-of-container-inf.patch b/snooper-fix-opposite-judgment-logic-of-container-inf.patch new file mode 100644 index 0000000..f7a70b2 --- /dev/null +++ b/snooper-fix-opposite-judgment-logic-of-container-inf.patch @@ -0,0 +1,46 @@ +From 60ed413c0ec3ccff22e5ae10c7758eeaadd7c94f Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Sat, 1 Mar 2025 12:12:25 +0800 +Subject: [PATCH 64/99] snooper: fix opposite judgment logic of container info + +--- + src/lib/probe/snooper.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/lib/probe/snooper.c b/src/lib/probe/snooper.c +index 989b5c90..85878f26 100644 +--- a/src/lib/probe/snooper.c ++++ b/src/lib/probe/snooper.c +@@ -984,25 +984,25 @@ static int add_snooper_obj_con_info(struct probe_s *probe, struct con_info_s *co + DEBUG("[SNOOPER] Adding container %s to snooper obj\n", con_info->con_id ?:"unknown"); + snooper_obj->type = SNOOPER_OBJ_CON; + snooper_obj->obj.con_info.cpucg_inode = con_info->cpucg_inode; +- if (con_info->con_id[0] != 0) { ++ if (con_info->con_id[0]) { + snooper_obj->obj.con_info.con_id = strdup(con_info->con_id); + if (!snooper_obj->obj.con_info.con_id) { + goto err; + } + } +- if (probe->probe_type == PROBE_SLI && (!con_info->container_name[0])) { ++ if (probe->probe_type == PROBE_SLI && (con_info->container_name[0])) { + snooper_obj->obj.con_info.container_name = strdup(con_info->container_name); + if (!snooper_obj->obj.con_info.container_name) { + goto err; + } + } +- if (probe->probe_type == PROBE_PROC && (!con_info->libc_path[0])) { ++ if (probe->probe_type == PROBE_PROC && (con_info->libc_path[0])) { + snooper_obj->obj.con_info.libc_path = strdup(con_info->libc_path); + if (!snooper_obj->obj.con_info.libc_path) { + goto err; + } + } +- if (probe->probe_type == PROBE_L7 && (!con_info->libssl_path[0])) { ++ if (probe->probe_type == PROBE_L7 && (con_info->libssl_path[0])) { + snooper_obj->obj.con_info.libssl_path = strdup(con_info->libssl_path); + if (!snooper_obj->obj.con_info.libssl_path) { + goto err; +-- +2.33.0 + diff --git a/snooper-optimize-the-size-of-proc-event.patch b/snooper-optimize-the-size-of-proc-event.patch new file mode 100644 index 0000000..44bd413 --- /dev/null +++ b/snooper-optimize-the-size-of-proc-event.patch @@ -0,0 +1,101 @@ +From ad466f7160a395013fdffa7b6f78bf6d4d4f61d0 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Sat, 1 Mar 2025 12:04:47 +0800 +Subject: [PATCH 63/99] snooper: optimize the size of proc event + +--- + src/lib/probe/snooper.bpf.c | 11 ++++------- + src/lib/probe/snooper.c | 11 +---------- + src/lib/probe/snooper_bpf.h | 2 +- + 3 files changed, 6 insertions(+), 18 deletions(-) + +diff --git a/src/lib/probe/snooper.bpf.c b/src/lib/probe/snooper.bpf.c +index 58846b6f..65e60343 100644 +--- a/src/lib/probe/snooper.bpf.c ++++ b/src/lib/probe/snooper.bpf.c +@@ -48,7 +48,7 @@ static __always_inline void process_new_forked_task(struct task_struct *child, v + + event.pid = pid; + event.proc_event = PROC_EXEC; +- bpf_core_read_str(event.filename, sizeof(child->comm), &child->comm); ++ bpf_core_read_str(event.comm, sizeof(child->comm), &child->comm); + + bpfbuf_output(ctx, &snooper_proc_channel, &event, sizeof(event)); + } +@@ -76,7 +76,7 @@ int bpf_trace_sched_process_fork_func(struct trace_event_raw_sched_process_fork + + event.pid = ctx->child_pid; + event.proc_event = PROC_EXEC; +- bpf_core_read_str(event.filename, sizeof(ctx->child_comm), &ctx->child_comm); ++ bpf_core_read_str(event.comm, sizeof(ctx->child_comm), &ctx->child_comm); + + bpfbuf_output(ctx, &snooper_proc_channel, &event, sizeof(event)); + return 0; +@@ -86,13 +86,11 @@ KRAWTRACE(sched_process_exec, bpf_raw_tracepoint_args) + { + struct snooper_proc_evt_s event = {0}; + struct task_struct* task = (struct task_struct *)ctx->args[0]; +- struct linux_binprm *bprm = (struct linux_binprm *)ctx->args[2]; + pid_t pid = _(task->pid); +- const char *filename = _(bprm->filename); + + event.pid = (u32)pid; + event.proc_event = PROC_EXEC; +- bpf_core_read(&event.filename, PATH_LEN, filename); ++ bpf_get_current_comm(&event.comm, sizeof(event.comm)); + + bpfbuf_output(ctx, &snooper_proc_channel, &event, sizeof(event)); + return 0; +@@ -102,11 +100,10 @@ SEC("tracepoint/sched/sched_process_exec") + int bpf_trace_sched_process_exec_func(struct trace_event_raw_sched_process_exec *ctx) + { + struct snooper_proc_evt_s event = {0}; +- unsigned fname_off = ctx->__data_loc_filename & 0xFFFF; + + event.pid = bpf_get_current_pid_tgid() >> 32; + event.proc_event = PROC_EXEC; +- bpf_core_read_str(&event.filename, sizeof(event.filename), (void *)ctx + fname_off); ++ bpf_get_current_comm(&event.comm, sizeof(event.comm)); + + bpfbuf_output(ctx, &snooper_proc_channel, &event, sizeof(event)); + return 0; +diff --git a/src/lib/probe/snooper.c b/src/lib/probe/snooper.c +index 8a196ea1..989b5c90 100644 +--- a/src/lib/probe/snooper.c ++++ b/src/lib/probe/snooper.c +@@ -1438,18 +1438,9 @@ static void __rcv_snooper_proc_exit(struct probe_mng_s *probe_mng, u32 proc_id) + static int rcv_snooper_proc_evt(void *ctx, void *data, __u32 size) + { + struct snooper_proc_evt_s *evt = data; +- char comm[TASK_COMM_LEN]; +- +- comm[0] = 0; +- char *p = strrchr(evt->filename, '/'); +- if (p) { +- (void)snprintf(comm, sizeof(comm), "%s", p + 1); +- } else { +- (void)snprintf(comm, sizeof(comm), "%s", evt->filename); +- } + + if (evt->proc_event == PROC_EXEC) { +- __rcv_snooper_proc_exec(__probe_mng_snooper, (const char *)comm, (u32)evt->pid); ++ __rcv_snooper_proc_exec(__probe_mng_snooper, (const char *)evt->comm, (u32)evt->pid); + } else { + __rcv_snooper_proc_exit(__probe_mng_snooper, (u32)evt->pid); + } +diff --git a/src/lib/probe/snooper_bpf.h b/src/lib/probe/snooper_bpf.h +index 848d6787..ab8ddd1a 100644 +--- a/src/lib/probe/snooper_bpf.h ++++ b/src/lib/probe/snooper_bpf.h +@@ -35,7 +35,7 @@ enum proc_event_t { + }; + struct snooper_proc_evt_s { + enum proc_event_t proc_event; +- char filename[PATH_LEN]; ++ char comm[TASK_COMM_LEN]; + u32 pid; + }; + +-- +2.33.0 + diff --git a/snooper-refix-incorrect-flags-when-resending-ipc-msg.patch b/snooper-refix-incorrect-flags-when-resending-ipc-msg.patch new file mode 100644 index 0000000..2cdc3d8 --- /dev/null +++ b/snooper-refix-incorrect-flags-when-resending-ipc-msg.patch @@ -0,0 +1,25 @@ +From 28b20936625110ae82372315a4056271c1ca85ba Mon Sep 17 00:00:00 2001 +From: cp3yeye +Date: Wed, 21 May 2025 16:47:41 +0800 +Subject: [PATCH 78/99] snooper: refix incorrect flags when resending ipc msg + +--- + src/lib/probe/snooper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lib/probe/snooper.c b/src/lib/probe/snooper.c +index f5008c76..0fd6431a 100644 +--- a/src/lib/probe/snooper.c ++++ b/src/lib/probe/snooper.c +@@ -698,7 +698,7 @@ static void __build_ipc_body(struct probe_s *probe, struct ipc_body_s* ipc_body) + ipc_body->probe_flags |= IPC_FLAGS_SNOOPER_CHG; + } + if (probe->resnd_snooper_for_restart) { +- ipc_body->probe_flags = (IPC_FLAGS_SNOOPER_CHG | IPC_FLAGS_SNOOPER_CHG); ++ ipc_body->probe_flags = (IPC_FLAGS_PARAMS_CHG | IPC_FLAGS_SNOOPER_CHG); + } + memcpy(&(ipc_body->probe_param), &probe->probe_param, sizeof(struct probe_params)); + return; +-- +2.33.0 + diff --git a/snooper-use-file-op-to-read-proc-comm-and-stat-inste.patch b/snooper-use-file-op-to-read-proc-comm-and-stat-inste.patch new file mode 100644 index 0000000..e853216 --- /dev/null +++ b/snooper-use-file-op-to-read-proc-comm-and-stat-inste.patch @@ -0,0 +1,115 @@ +From 10662bd12b9239cb9aeeb690926790f14c7a7908 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Thu, 6 Mar 2025 05:59:08 +0800 +Subject: [PATCH 67/99] snooper: use file op to read proc comm and stat instead + of popen + +--- + src/lib/probe/snooper.c | 51 +++++++++++++++++++++++++---------------- + 1 file changed, 31 insertions(+), 20 deletions(-) + +diff --git a/src/lib/probe/snooper.c b/src/lib/probe/snooper.c +index 85878f26..1fa67a82 100644 +--- a/src/lib/probe/snooper.c ++++ b/src/lib/probe/snooper.c +@@ -828,24 +828,31 @@ static char __chk_snooper_pattern(const char *conf_pattern, const char *target) + } + + #define __SYS_PROC_COMM "/proc/%s/comm" +-#define __CAT_SYS_PROC_COMM "/usr/bin/cat /proc/%s/comm 2> /dev/null" +-#define __PROC_NAME_MAX 64 + #define __PROC_CMDLINE_MAX 4096 + static int __read_proc_comm(const char *dir_name, char *comm, size_t size) + { + char proc_comm_path[PATH_LEN]; +- char cat_comm_cmd[COMMAND_LEN]; ++ FILE *f; + + proc_comm_path[0] = 0; +- (void)snprintf(proc_comm_path, PATH_LEN, __SYS_PROC_COMM, dir_name); +- if (access((const char *)proc_comm_path, 0) != 0) { ++ (void)snprintf(proc_comm_path, sizeof(proc_comm_path), __SYS_PROC_COMM, dir_name); ++ ++ f = fopen(proc_comm_path, "r"); ++ if (f == NULL) { + return -1; + } + +- cat_comm_cmd[0] = 0; +- (void)snprintf(cat_comm_cmd, COMMAND_LEN, __CAT_SYS_PROC_COMM, dir_name); ++ if (fgets(comm, size, f) == NULL) { ++ fclose(f); ++ return -1; ++ } + +- return exec_cmd((const char *)cat_comm_cmd, comm, size); ++ char *p = strchr(comm, '\n'); ++ if (p) { ++ *p = 0; ++ } ++ fclose(f); ++ return 0; + } + + #define __SYS_PROC_CMDLINE "/proc/%s/cmdline" +@@ -892,25 +899,29 @@ static int __read_proc_cmdline(const char *dir_name, char *cmdline, u32 size) + return 0; + } + +-#define PROC_STAT_CMD "cat /proc/%s/stat 2>/dev/null" ++#define PROC_STAT_PATH "/proc/%s/stat" + static int __need_to_add_proc(const char *pid) + { +- char cmd[LINE_BUF_LEN]; +- char line[LINE_BUF_LEN]; +- cmd[0] = 0; +- line[0] = 0; ++ char proc_stat_path[PATH_LEN]; ++ pid_t ppid; ++ FILE *f; ++ int ret; + +- (void)snprintf(cmd, LINE_BUF_LEN, PROC_STAT_CMD, pid); +- if (exec_cmd(cmd, line, LINE_BUF_LEN) != 0) { ++ proc_stat_path[0] = 0; ++ (void)snprintf(proc_stat_path, sizeof(proc_stat_path), PROC_STAT_PATH, pid); ++ f = fopen(proc_stat_path, "r"); ++ if (f == NULL) { + return 0; + } + +- cmd[0] = 0; +- (void)snprintf(cmd, LINE_BUF_LEN, "%d", getpid()); +- if (strstr(line, cmd) != NULL) { ++ /* /proc/pid/stat: pid comm task_state ppid ..., so skip first 3 fields */ ++ ret = fscanf(f, "%*s %*s %*s %d", &ppid); ++ if (ret != 1 || ppid == getpid()) { ++ fclose(f); + return 0; + } + ++ fclose(f); + return 1; + } + +@@ -1024,7 +1035,7 @@ static int gen_snooper_by_procname(struct probe_s *probe) + DIR *dir = NULL; + struct dirent *entry; + struct snooper_conf_s * snooper_conf; +- char comm[__PROC_NAME_MAX]; ++ char comm[TASK_COMM_LEN]; + char cmdline[__PROC_CMDLINE_MAX]; + + dir = opendir(__SYS_PROC_DIR); +@@ -1042,7 +1053,7 @@ static int gen_snooper_by_procname(struct probe_s *probe) + } + + comm[0] = 0; +- ret = __read_proc_comm(entry->d_name, comm, __PROC_NAME_MAX); ++ ret = __read_proc_comm(entry->d_name, comm, sizeof(comm)); + if (ret) { + continue; + } +-- +2.33.0 + diff --git a/system_infos-fix-oob-of-arrays-and-double-free.patch b/system_infos-fix-oob-of-arrays-and-double-free.patch new file mode 100644 index 0000000..91bc9c0 --- /dev/null +++ b/system_infos-fix-oob-of-arrays-and-double-free.patch @@ -0,0 +1,116 @@ +From b181591b876c8bf42d5cf181188655d3b3958f9f Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Fri, 27 Dec 2024 14:55:42 +0800 +Subject: [PATCH 39/99] system_infos: fix oob of arrays and double free + +--- + src/probes/system_infos.probe/system_cpu.c | 31 +++++++++++----------- + src/probes/system_infos.probe/system_net.c | 10 ++++--- + 2 files changed, 23 insertions(+), 18 deletions(-) + +diff --git a/src/probes/system_infos.probe/system_cpu.c b/src/probes/system_infos.probe/system_cpu.c +index 19d1316c..bb584f99 100644 +--- a/src/probes/system_infos.probe/system_cpu.c ++++ b/src/probes/system_infos.probe/system_cpu.c +@@ -133,7 +133,7 @@ static int get_proc_stat_info(void) + fclose(f); + return 0; + } +- strncpy(dst_line, line, LINE_BUF_LEN - 1); ++ snprintf(dst_line, sizeof(dst_line), "%s", line); + if (is_first_line) { + util_per = get_cpu_util(dst_line, &last_time_total, &last_time_used, + &cur_time_total, &cur_time_used); +@@ -145,6 +145,10 @@ static int get_proc_stat_info(void) + if (strstr(line, "cpu") == NULL) { + continue; + } ++ ++ if (index >= cpus_num) { ++ break; ++ } + cur_cpus[index]->cpu_util_per = get_cpu_util(dst_line, &old_cpus[index]->cpu_time_total, + &old_cpus[index]->cpu_time_used, + &cur_cpus[index]->cpu_time_total, +@@ -299,11 +303,7 @@ static struct cpu_stat **alloc_memory(void) + for (size_t i = 0; i < cpus_num; i++) { + cpus[i] = (struct cpu_stat *)malloc(sizeof(struct cpu_stat)); + if (cpus[i] == NULL) { +- for (size_t j = 0; j < i; j++) { +- free(cpus[j]); +- } +- free(cpus); +- cpus = NULL; ++ // dealloc_memory will free previous allocated memory + return NULL; + } + cpus[i]->cpu_num = i; +@@ -313,8 +313,12 @@ static struct cpu_stat **alloc_memory(void) + + static void dealloc_memory(struct cpu_stat **cpus) + { ++ if (cpus == NULL) { ++ return; ++ } + for (size_t i = 0; i < cpus_num; i++) { + free(cpus[i]); ++ cpus[i] = NULL; + } + free(cpus); + } +@@ -335,18 +339,15 @@ int system_cpu_init(void) + old_cpus = alloc_memory(); + if (cur_cpus == NULL || old_cpus == NULL) { + ERROR("[SYSTEM_PROBE] fail alloc memory for cpu probe structure\n"); +- if (cur_cpus != NULL) { +- dealloc_memory(cur_cpus); +- cur_cpus = NULL; +- } +- if (old_cpus != NULL) { +- dealloc_memory(old_cpus); +- old_cpus = NULL; +- } ++ system_cpu_destroy(); + return -1; + } + softirq_line_num = MAX_COL_NUM * (1 + cpus_num); +- softirq_line = (char*)malloc(softirq_line_num); ++ softirq_line = (char *)malloc(softirq_line_num); ++ if (softirq_line == NULL) { ++ system_cpu_destroy(); ++ return -1; ++ } + return 0; + } + +diff --git a/src/probes/system_infos.probe/system_net.c b/src/probes/system_infos.probe/system_net.c +index 352fde07..6c259e4a 100644 +--- a/src/probes/system_infos.probe/system_net.c ++++ b/src/probes/system_infos.probe/system_net.c +@@ -365,9 +365,9 @@ int system_net_probe(struct ipc_body_s *ipc_body) + if (strchr(line, '|') != NULL) { + continue; + } +- if (index > g_netdev_num) { +- ERROR("[SYSTEM_NET] net_probe records beyond max netdev nums(%d).\n", g_netdev_num); +- continue; ++ if (index >= g_netdev_num) { ++ WARN("[SYSTEM_NET] net_probe records beyond max netdev nums(%d).\n", g_netdev_num); ++ break; + } + (void)get_netdev_name(line, dev_name); + if (is_physical_netdev(dev_name, g_netdev_num) != 1) { +@@ -429,6 +429,10 @@ static int load_physical_device(void) + fpath[0] = 0; + (void)snprintf(fpath, COMMAND_LEN, "/sys/devices/virtual/net/%s", entry->d_name); + if (access((const char *)fpath, 0) < 0) { ++ if (g_netdev_num >= MAX_NETDEV_NUM) { ++ WARN("[SYSTEM_NET] num of physical net devices exceeds %d, some will be ignored\n", MAX_NETDEV_NUM); ++ break; ++ } + // this is not virtual device + (void)snprintf(g_phy_netdev_list[g_netdev_num++], NET_DEVICE_NAME_SIZE, "%s", entry->d_name); + } +-- +2.33.0 + diff --git a/tcpprobe-do-not-flush-snooped-procs-to-avoid-deletin.patch b/tcpprobe-do-not-flush-snooped-procs-to-avoid-deletin.patch new file mode 100644 index 0000000..535038c --- /dev/null +++ b/tcpprobe-do-not-flush-snooped-procs-to-avoid-deletin.patch @@ -0,0 +1,92 @@ +From ed325a0d5ac5a2e148d4c4c087c57f691751e0ea Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Sat, 21 Dec 2024 11:57:40 +0800 +Subject: [PATCH 33/99] tcpprobe: do not flush snooped procs to avoid deleting + tcp link by accident + +--- + .../ebpf.probe/src/tcpprobe/tcpprobe.c | 47 +++++++++++-------- + 1 file changed, 28 insertions(+), 19 deletions(-) + +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c +index 88ccf1a0..52013152 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c +@@ -61,37 +61,47 @@ static void sig_int(int signo) + g_stop = 1; + } + +-static void load_tcp_snoopers(int fd, struct ipc_body_s *ipc_body) ++static void clear_unref_proc_map(int fd) + { +- struct proc_s proc = {0}; +- struct obj_ref_s ref = {.count = 1}; +- +- if (fd <= 0) { +- return; +- } +- +- for (int i = 0; i < ipc_body->snooper_obj_num && i < SNOOPER_MAX; i++) { +- if (ipc_body->snooper_objs[i].type == SNOOPER_OBJ_PROC) { +- proc.proc_id = ipc_body->snooper_objs[i].obj.proc.proc_id; +- (void)bpf_map_update_elem(fd, &proc, &ref, BPF_ANY); ++ struct proc_s key = {0}; ++ struct proc_s next_key = {0}; ++ struct obj_ref_s value = {0}; ++ ++ while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { ++ (void)bpf_map_lookup_elem(fd, &next_key, &value); ++ if (value.count == 0) { ++ (void)bpf_map_delete_elem(fd, &next_key); + } ++ key = next_key; + } + } + +-static void unload_tcp_snoopers(int fd, struct ipc_body_s *ipc_body) ++static void reload_tcp_snoopers(int fd, struct ipc_body_s *ipc_old, struct ipc_body_s *ipc_new) + { + struct proc_s proc = {0}; ++ struct obj_ref_s ref = {.count = 1}; ++ struct obj_ref_s ref_zero = {.count = 0}; ++ int i; + + if (fd <= 0) { + return; + } + +- for (int i = 0; i < ipc_body->snooper_obj_num && i < SNOOPER_MAX; i++) { +- if (ipc_body->snooper_objs[i].type == SNOOPER_OBJ_PROC) { +- proc.proc_id = ipc_body->snooper_objs[i].obj.proc.proc_id; +- (void)bpf_map_delete_elem(fd, &proc); ++ for (i = 0; i < ipc_old->snooper_obj_num && i < SNOOPER_MAX; i++) { ++ if (ipc_old->snooper_objs[i].type == SNOOPER_OBJ_PROC) { ++ proc.proc_id = ipc_old->snooper_objs[i].obj.proc.proc_id; ++ (void)bpf_map_update_elem(fd, &proc, &ref_zero, BPF_ANY); + } + } ++ ++ for (i = 0; i < ipc_new->snooper_obj_num && i < SNOOPER_MAX; i++) { ++ if (ipc_new->snooper_objs[i].type == SNOOPER_OBJ_PROC) { ++ proc.proc_id = ipc_new->snooper_objs[i].obj.proc.proc_id; ++ (void)bpf_map_update_elem(fd, &proc, &ref, BPF_ANY); ++ } ++ } ++ ++ clear_unref_proc_map(fd); + } + + static void reload_tc_bpf(struct ipc_body_s* ipc_body) +@@ -299,8 +309,7 @@ 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); +- unload_tcp_snoopers(proc_obj_map_fd, &(tcp_mng->ipc_body)); +- load_tcp_snoopers(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)); + (void)memcpy(&(tcp_mng->ipc_body), &ipc_body, sizeof(tcp_mng->ipc_body)); +-- +2.33.0 + diff --git a/tcpprobe-fix-inaccurate-notack_bytes.patch b/tcpprobe-fix-inaccurate-notack_bytes.patch new file mode 100644 index 0000000..1db1f74 --- /dev/null +++ b/tcpprobe-fix-inaccurate-notack_bytes.patch @@ -0,0 +1,140 @@ +From d42cbc3bd7f744b16a5ab7eeb2a4655d011edf39 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Tue, 29 Jul 2025 19:32:12 +0800 +Subject: [PATCH 88/99] tcpprobe: fix inaccurate notack_bytes + +--- + .../ebpf.probe/src/tcpprobe/tcp_link.h | 15 ++++++++ + .../ebpf.probe/src/tcpprobe/tcp_stats.bpf.c | 37 ++++++++++++++----- + 2 files changed, 42 insertions(+), 10 deletions(-) + +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h +index ea6a4157..0b22d31b 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h +@@ -157,6 +157,21 @@ static __always_inline __maybe_unused struct tcp_metrics_s *get_tcp_metrics(stru + return NULL; + } + ++ ++static __always_inline struct tcp_metrics_s *get_tcp_metrics_fast(struct sock *sk, struct sock_stats_s *sock_stats) ++{ ++ if (sock_stats == NULL) { ++ return NULL; ++ } ++ ++ if (is_valid_tgid(sock_stats->metrics.link.tgid)) { ++ return &(sock_stats->metrics); ++ } ++ (void)delete_tcp_link(sk); ++ reset_sock_obj_link_state(sk); ++ return NULL; ++} ++ + static __always_inline __maybe_unused int create_sock_obj(u32 tgid, struct sock *sk, struct sock_info_s *info) + { + info->proc_id = tgid; +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_stats.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_stats.bpf.c +index d89641b1..37547987 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_stats.bpf.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_stats.bpf.c +@@ -28,7 +28,7 @@ + + char g_linsence[] SEC("license") = "GPL"; + +-static __always_inline char is_tmout_stats(struct sock *sk) ++static __always_inline char is_tmout_stats(struct sock *sk, struct sock_stats_s **want) + { + struct sock_stats_s *sock_stats = bpf_map_lookup_elem(&tcp_link_map, &sk); + if (!sock_stats) { +@@ -39,6 +39,7 @@ static __always_inline char is_tmout_stats(struct sock *sk) + u64 period = get_period(); + if ((ts > sock_stats->ts.stats_ts) && ((ts - sock_stats->ts.stats_ts) >= period)) { + sock_stats->ts.stats_ts = ts; ++ *want = sock_stats; + return 1; + } + return 0; +@@ -103,12 +104,14 @@ static void set_last_win_stats(struct tcp_windows* stats, struct tcp_windows* la + + static int is_win_stats_changed(struct tcp_windows* stats, struct tcp_windows* last_stats) + { +- if (stats->tcpi_notsent_bytes != last_stats->tcpi_notsent_bytes) { ++ if (stats->tcpi_notsent_bytes && (stats->tcpi_notsent_bytes != last_stats->tcpi_notsent_bytes)) { + return 1; + } +- if (stats->tcpi_notack_bytes != last_stats->tcpi_notack_bytes) { ++ ++ if (stats->tcpi_notack_bytes && (stats->tcpi_notack_bytes != last_stats->tcpi_notack_bytes)) { + return 1; + } ++ + if (stats->tcpi_snd_wnd != last_stats->tcpi_snd_wnd) { + return 1; + } +@@ -162,19 +165,28 @@ static void get_tcp_rate(struct sock *sk, struct tcp_rate* stats) + stats->tcpi_ato = _(icsk->icsk_ack.ato); // ms + } + +-static void tcp_stats_probe_func(void *ctx, struct sock *sk) ++static void tcp_stats_probe_func(void *ctx, struct sock *sk, struct sk_buff *skb) + { + struct tcp_metrics_s *metrics; + u32 report_flags = 0; ++ u32 is_data_segment = 1; ++ struct tcp_sock *tcp_sk; ++ struct sock_stats_s *sock_stats = NULL; + + // Avoid high performance costs +- if (!is_tmout_stats(sk)) { ++ if (!is_tmout_stats(sk, &sock_stats)) { + return; + } + +- metrics = get_tcp_metrics(sk); ++ metrics = get_tcp_metrics_fast(sk, sock_stats); + if (metrics) { + u32 probe_flags = get_probe_flags(); ++ tcp_sk = (struct tcp_sock *)sk; ++ unsigned int len = _(skb->len); ++ if (len <= _(tcp_sk->tcp_header_len)) { ++ is_data_segment = 0; ++ } ++ + if (probe_flags & PROBE_RANGE_TCP_RTT) { + get_tcp_rtt(sk, &(metrics->rtt_stats)); + report_flags |= TCP_PROBE_RTT; +@@ -184,6 +196,9 @@ static void tcp_stats_probe_func(void *ctx, struct sock *sk) + struct tcp_windows last_win_stats = {0}; + set_last_win_stats(&(metrics->win_stats), &last_win_stats); + get_tcp_wnd(sk, &(metrics->win_stats)); ++ if (!is_data_segment) { ++ metrics->win_stats.tcpi_notack_bytes = 0; ++ } + if (is_win_stats_changed(&(metrics->win_stats), &last_win_stats)) { + report_flags |= TCP_PROBE_WINDOWS; + } +@@ -208,14 +223,16 @@ static void tcp_stats_probe_func(void *ctx, struct sock *sk) + + KRAWTRACE(tcp_probe, bpf_raw_tracepoint_args) + { +- struct sock *sk = (struct sock*)ctx->args[0]; +- tcp_stats_probe_func(ctx, sk); ++ struct sock *sk = (struct sock *)ctx->args[0]; ++ struct sk_buff *skb = (struct sk_buff *)ctx->args[1]; ++ tcp_stats_probe_func(ctx, sk, skb); + return 0; + } + + KPROBE(tcp_rcv_established, pt_regs) + { +- struct sock *sk = (struct sock*)PT_REGS_PARM1(ctx); +- tcp_stats_probe_func(ctx, sk); ++ struct sock *sk = (struct sock *)PT_REGS_PARM1(ctx); ++ struct sk_buff *skb = (struct sk_buff *)PT_REGS_PARM2(ctx); ++ tcp_stats_probe_func(ctx, sk, skb); + return 0; + } +-- +2.33.0 + diff --git a/tcpprobe-fix-incorret-struct-type-of-tracepoint-even.patch b/tcpprobe-fix-incorret-struct-type-of-tracepoint-even.patch new file mode 100644 index 0000000..87266e4 --- /dev/null +++ b/tcpprobe-fix-incorret-struct-type-of-tracepoint-even.patch @@ -0,0 +1,53 @@ +From fc81be26f12e966ad206c27933de0c8ee2864f19 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Wed, 22 Jan 2025 10:41:45 +0800 +Subject: [PATCH 48/99] tcpprobe: fix incorret struct type of tracepoint event + +--- + src/probes/extends/ebpf.probe/src/tcpprobe/tcp_abn.bpf.c | 2 +- + src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rate.bpf.c | 2 +- + src/probes/extends/ebpf.probe/src/tcpprobe/tcp_windows.bpf.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_abn.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_abn.bpf.c +index 5492f036..3fe0f563 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_abn.bpf.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_abn.bpf.c +@@ -298,7 +298,7 @@ int bpf_trace_tcp_send_reset_func(struct trace_event_raw_tcp_event_sk_skb *ctx) + } + + SEC("tracepoint/tcp/tcp_receive_reset") +-int bpf_trace_tcp_receive_reset_func(struct trace_event_raw_tcp_event_sk_skb *ctx) ++int bpf_trace_tcp_receive_reset_func(struct trace_event_raw_tcp_event_sk *ctx) + { + struct sock *sk = (struct sock *)ctx->skaddr; + return tcp_abn_rcv_rsts_probe_func(ctx, sk); +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rate.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rate.bpf.c +index 7770bebe..5416f530 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rate.bpf.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rate.bpf.c +@@ -94,7 +94,7 @@ KPROBE(tcp_rcv_space_adjust, pt_regs) + } + + SEC("tracepoint/tcp/tcp_rcv_space_adjust") +-int bpf_trace_tcp_rcv_space_adjust_func(struct trace_event_raw_tcp_event_sk_skb *ctx) ++int bpf_trace_tcp_rcv_space_adjust_func(struct trace_event_raw_tcp_event_sk *ctx) + { + struct sock *sk = (struct sock*)ctx->skaddr; + tcp_rate_probe_func(ctx, sk); +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_windows.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_windows.bpf.c +index 89efae06..5cced8a5 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_windows.bpf.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_windows.bpf.c +@@ -148,7 +148,7 @@ KPROBE(tcp_rcv_space_adjust, pt_regs) + } + + SEC("tracepoint/tcp/tcp_rcv_space_adjust") +-int bpf_trace_tcp_rcv_space_adjust_func(struct trace_event_raw_tcp_event_sk_skb *ctx) ++int bpf_trace_tcp_rcv_space_adjust_func(struct trace_event_raw_tcp_event_sk *ctx) + { + struct sock *sk = (struct sock*)ctx->skaddr; + tcp_wnd_probe_func(ctx, sk); +-- +2.33.0 + diff --git a/tcpprobe-poll-from-last-buffer-to-adapt-for-pinned-p.patch b/tcpprobe-poll-from-last-buffer-to-adapt-for-pinned-p.patch new file mode 100644 index 0000000..74760ca --- /dev/null +++ b/tcpprobe-poll-from-last-buffer-to-adapt-for-pinned-p.patch @@ -0,0 +1,36 @@ +From 9dfd9ea173104b10e46735036fdccab0e492e7f2 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Thu, 26 Dec 2024 16:15:38 +0800 +Subject: [PATCH 34/99] tcpprobe: poll from last buffer to adapt for pinned + perf event map + +--- + src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c +index 52013152..972fa2d4 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c +@@ -316,12 +316,17 @@ int main(int argc, char **argv) + } + + if (tcp_mng->tcp_progs) { ++ if (tcp_mng->tcp_progs->num == 0 || tcp_mng->tcp_progs->num > SKEL_MAX_NUM) { ++ goto err; ++ } ++ + ret = load_established_tcps_mngt(proc_obj_map_fd, tcp_fd_map_fd); + if (ret) { + goto err; + } + +- for (int i = 0; i < tcp_mng->tcp_progs->num && i < SKEL_MAX_NUM; i++) { ++ // poll from last buffer to adapt for pinned perf event map ++ for (int i = (int)tcp_mng->tcp_progs->num - 1; i >= 0; i--) { + if (tcp_mng->tcp_progs->buffers[i]) { + err = bpf_buffer__poll(tcp_mng->tcp_progs->buffers[i], THOUSAND); + if (err < 0 && err != -EINTR) { +-- +2.33.0 + diff --git a/tcpprobe-remove-superfluous-buffer__open-to-reduce-m.patch b/tcpprobe-remove-superfluous-buffer__open-to-reduce-m.patch new file mode 100644 index 0000000..1bba538 --- /dev/null +++ b/tcpprobe-remove-superfluous-buffer__open-to-reduce-m.patch @@ -0,0 +1,167 @@ +From 67176cd2e8de4ca05428245198acaacbf1e0fbb7 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Mon, 6 Jan 2025 11:15:09 +0800 +Subject: [PATCH 41/99] tcpprobe: remove superfluous buffer__open to reduce + memory usage + +--- + .../ebpf.probe/src/tcpprobe/tcp_probe.c | 80 +++++++++++-------- + .../ebpf.probe/src/tcpprobe/tcpprobe.c | 2 +- + 2 files changed, 49 insertions(+), 33 deletions(-) + +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 d438c48c..baaecbea 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c +@@ -828,10 +828,12 @@ static int tcp_load_probe_sockbuf(struct tcp_mng_s *tcp_mng, struct bpf_prog_s * + prog->skels[prog->num].fn = (skel_destroy_fn)tcp_sockbuf_bpf__destroy; + prog->custom_btf_paths[prog->num] = tcp_sockbuf_open_opts.btf_custom_path; + +- err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); +- if (err) { +- ERROR("[TCPPROBE] Open 'tcp_sockbuf' bpf_buffer failed.\n"); +- goto err; ++ if (prog->num == 0) { // All sub-probes share a output buffer ++ err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); ++ if (err) { ++ ERROR("[TCPPROBE] Open 'tcp_sockbuf' bpf_buffer failed.\n"); ++ goto err; ++ } + } + prog->buffers[prog->num] = buffer; + prog->num++; +@@ -862,10 +864,12 @@ static int tcp_load_probe_rtt(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *prog + prog->skels[prog->num].fn = (skel_destroy_fn)tcp_rtt_bpf__destroy; + prog->custom_btf_paths[prog->num] = tcp_rtt_open_opts.btf_custom_path; + +- err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); +- if (err) { +- ERROR("[TCPPROBE] Open 'tcp_rtt' bpf_buffer failed.\n"); +- goto err; ++ if (prog->num == 0) { // All sub-probes share a output buffer ++ err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); ++ if (err) { ++ ERROR("[TCPPROBE] Open 'tcp_rtt' bpf_buffer failed.\n"); ++ goto err; ++ } + } + prog->buffers[prog->num] = buffer; + prog->num++; +@@ -896,10 +900,12 @@ static int tcp_load_probe_win(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *prog + prog->skels[prog->num].fn = (skel_destroy_fn)tcp_windows_bpf__destroy; + prog->custom_btf_paths[prog->num] = tcp_windows_open_opts.btf_custom_path; + +- err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); +- if (err) { +- ERROR("[TCPPROBE] Open 'tcp_windows' bpf_buffer failed.\n"); +- goto err; ++ if (prog->num == 0) { // All sub-probes share a output buffer ++ err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); ++ if (err) { ++ ERROR("[TCPPROBE] Open 'tcp_windows' bpf_buffer failed.\n"); ++ goto err; ++ } + } + prog->buffers[prog->num] = buffer; + prog->num++; +@@ -930,10 +936,12 @@ static int tcp_load_probe_rate(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *pro + prog->skels[prog->num].fn = (skel_destroy_fn)tcp_rate_bpf__destroy; + prog->custom_btf_paths[prog->num] = tcp_rate_open_opts.btf_custom_path; + +- err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); +- if (err) { +- ERROR("[TCPPROBE] Open 'tcp_rate' bpf_buffer failed.\n"); +- goto err; ++ if (prog->num == 0) { // All sub-probes share a output buffer ++ err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); ++ if (err) { ++ ERROR("[TCPPROBE] Open 'tcp_rate' bpf_buffer failed.\n"); ++ goto err; ++ } + } + prog->buffers[prog->num] = buffer; + prog->num++; +@@ -967,10 +975,12 @@ static int tcp_load_probe_abn(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *prog + prog->skels[prog->num].fn = (skel_destroy_fn)tcp_abn_bpf__destroy; + prog->custom_btf_paths[prog->num] = tcp_abn_open_opts.btf_custom_path; + +- err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); +- if (err) { +- ERROR("[TCPPROBE] Open 'tcp_abn' bpf_buffer failed.\n"); +- goto err; ++ if (prog->num == 0) { // All sub-probes share a output buffer ++ err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); ++ if (err) { ++ ERROR("[TCPPROBE] Open 'tcp_abn' bpf_buffer failed.\n"); ++ goto err; ++ } + } + prog->buffers[prog->num] = buffer; + prog->num++; +@@ -993,10 +1003,12 @@ static int tcp_load_probe_txrx(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *pro + prog->skels[prog->num].skel = tcp_tx_rx_skel; + prog->skels[prog->num].fn = (skel_destroy_fn)tcp_tx_rx_bpf__destroy; + prog->custom_btf_paths[prog->num] = tcp_tx_rx_open_opts.btf_custom_path; +- err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); +- if (err) { +- ERROR("[TCPPROBE] Open 'tcp_tx_rx' bpf_buffer failed.\n"); +- goto err; ++ if (prog->num == 0) { // All sub-probes share a output buffer ++ err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); ++ if (err) { ++ ERROR("[TCPPROBE] Open 'tcp_txrx' bpf_buffer failed.\n"); ++ goto err; ++ } + } + prog->buffers[prog->num] = buffer; + prog->num++; +@@ -1030,10 +1042,12 @@ static int tcp_load_probe_delay(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *pr + prog->skels[prog->num].fn = (skel_destroy_fn)tcp_delay_bpf__destroy; + prog->custom_btf_paths[prog->num] = tcp_delay_open_opts.btf_custom_path; + +- err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); +- if (err) { +- ERROR("[TCPPROBE] Open 'tcp_delay' bpf_buffer failed.\n"); +- goto err; ++ if (prog->num == 0) { // All sub-probes share a output buffer ++ err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); ++ if (err) { ++ ERROR("[TCPPROBE] Open 'tcp_delay' bpf_buffer failed.\n"); ++ goto err; ++ } + } + prog->buffers[prog->num] = buffer; + prog->num++; +@@ -1059,10 +1073,12 @@ static int tcp_load_probe_link(struct tcp_mng_s *tcp_mng, struct probe_params *a + prog->skels[prog->num].fn = (skel_destroy_fn)tcp_link_bpf__destroy; + prog->custom_btf_paths[prog->num] = tcp_link_open_opts.btf_custom_path; + +- err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); +- if (err) { +- ERROR("[TCPPROBE] Open 'tcp_link' bpf_buffer failed.\n"); +- goto err; ++ if (prog->num == 0) { // All sub-probes share a output buffer ++ err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); ++ if (err) { ++ ERROR("[TCPPROBE] Open 'tcp_link' bpf_buffer failed.\n"); ++ goto err; ++ } + } + prog->buffers[prog->num] = buffer; + prog->num++; +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c +index 972fa2d4..1ff1fd8d 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c +@@ -327,7 +327,7 @@ int main(int argc, char **argv) + + // poll from last buffer to adapt for pinned perf event map + for (int i = (int)tcp_mng->tcp_progs->num - 1; i >= 0; i--) { +- if (tcp_mng->tcp_progs->buffers[i]) { ++ if (tcp_mng->tcp_progs->buffers[i] && tcp_mng->tcp_progs->buffers[i]->inner) { + err = bpf_buffer__poll(tcp_mng->tcp_progs->buffers[i], THOUSAND); + if (err < 0 && err != -EINTR) { + ERROR("[TCPPROBE]: perf poll prog_%d failed.\n", i); +-- +2.33.0 + diff --git a/tcpprobe-report-all-metrics-of-a-tracker-in-one-outp.patch b/tcpprobe-report-all-metrics-of-a-tracker-in-one-outp.patch new file mode 100644 index 0000000..c6a19cf --- /dev/null +++ b/tcpprobe-report-all-metrics-of-a-tracker-in-one-outp.patch @@ -0,0 +1,679 @@ +From 2726031623cee04fe79e50744acf5674b40a22c5 Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Sat, 4 Jan 2025 15:19:23 +0800 +Subject: [PATCH 40/99] tcpprobe: report all metrics of a tracker in one output + +--- + src/lib/imdb/imdb.c | 4 + + .../ebpf.probe/src/tcpprobe/tcp_link.meta | 254 +----------------- + .../ebpf.probe/src/tcpprobe/tcp_probe.c | 206 ++++++-------- + 3 files changed, 89 insertions(+), 375 deletions(-) + +diff --git a/src/lib/imdb/imdb.c b/src/lib/imdb/imdb.c +index 2d00e306..0d152185 100644 +--- a/src/lib/imdb/imdb.c ++++ b/src/lib/imdb/imdb.c +@@ -1282,6 +1282,10 @@ static int IMDB_BuildJsonHistos(IMDB_DataBaseMgr *mgr, IMDB_Record *record, IMDB + continue; + } + ++ if (strcmp(record->metrics[i]->val, INVALID_METRIC_VALUE) == 0) { ++ continue; ++ } ++ + if (first_flag) { + ret = __snprintf(buffer, *maxLen, maxLen, "\"%s\":{", + record->metrics[i]->name); +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 655e3d4a..87475d52 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.meta ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.meta +@@ -2,7 +2,7 @@ version = "1.0.0" + measurements: + ( + { +- table_name: "tcp_tx_rx", ++ table_name: "tcp_metric", + entity_name: "tcp_link", + fields: + ( +@@ -60,48 +60,6 @@ measurements: + description: "total number of segments sent", + type: "gauge", + name: "segs_out", +- } +- ) +- }, +- { +- table_name: "tcp_rtt", +- entity_name: "tcp_link", +- fields: +- ( +- { +- description: "id of process", +- type: "key", +- name: "tgid", +- }, +- { +- description: "role", +- type: "key", +- name: "role", +- }, +- { +- description: "client ip", +- type: "key", +- name: "client_ip", +- }, +- { +- description: "client ip before toa", +- type: "key", +- name: "toa_client_ip", +- }, +- { +- description: "server ip", +- type: "key", +- name: "server_ip", +- }, +- { +- description: "server port", +- type: "key", +- name: "server_port", +- }, +- { +- description: "protocol", +- type: "key", +- name: "protocol", + }, + { + description: "Smoothed Round Trip Time(us).", +@@ -112,48 +70,6 @@ measurements: + description: "Receive end RTT (unidirectional measurement).", + type: "histogram", + name: "rcv_rtt", +- } +- ) +- }, +- { +- table_name: "tcp_windows", +- entity_name: "tcp_link", +- fields: +- ( +- { +- description: "id of process", +- type: "key", +- name: "tgid", +- }, +- { +- description: "role", +- type: "key", +- name: "role", +- }, +- { +- description: "client ip", +- type: "key", +- name: "client_ip", +- }, +- { +- description: "client ip before toa", +- type: "key", +- name: "toa_client_ip", +- }, +- { +- description: "server ip", +- type: "key", +- name: "server_ip", +- }, +- { +- description: "server port", +- type: "key", +- name: "server_port", +- }, +- { +- description: "protocol", +- type: "key", +- name: "protocol", + }, + { + description: "Congestion Control Window Size.", +@@ -209,48 +125,6 @@ measurements: + description: "TCP zero send windows ratio", + type: "gauge", + name: "zero_win_tx_ratio", +- } +- ) +- }, +- { +- table_name: "tcp_rate", +- entity_name: "tcp_link", +- fields: +- ( +- { +- description: "id of process", +- type: "key", +- name: "tgid", +- }, +- { +- description: "role", +- type: "key", +- name: "role", +- }, +- { +- description: "client ip", +- type: "key", +- name: "client_ip", +- }, +- { +- description: "client ip before toa", +- type: "key", +- name: "toa_client_ip", +- }, +- { +- description: "server ip", +- type: "key", +- name: "server_ip", +- }, +- { +- description: "server port", +- type: "key", +- name: "server_port", +- }, +- { +- description: "protocol", +- type: "key", +- name: "protocol", + }, + { + description: "Retransmission timeOut(ms)", +@@ -261,48 +135,6 @@ measurements: + description: "Estimated value of delayed ACK(ms)", + type: "histogram", + name: "ato", +- } +- ) +- }, +- { +- table_name: "tcp_srtt", +- entity_name: "tcp_link", +- fields: +- ( +- { +- description: "id of process", +- type: "key", +- name: "tgid", +- }, +- { +- description: "role", +- type: "key", +- name: "role", +- }, +- { +- description: "client ip", +- type: "key", +- name: "client_ip", +- }, +- { +- description: "client ip before toa", +- type: "key", +- name: "toa_client_ip", +- }, +- { +- description: "server ip", +- type: "key", +- name: "server_ip", +- }, +- { +- description: "server port", +- type: "key", +- name: "server_port", +- }, +- { +- description: "protocol", +- type: "key", +- name: "protocol", + }, + { + description: "RTT of syn packet(us).", +@@ -313,48 +145,6 @@ measurements: + description: "RTT of syn packet(us).", + type: "gauge", + name: "syn_srtt_max", +- } +- ) +- }, +- { +- table_name: "tcp_sockbuf", +- entity_name: "tcp_link", +- fields: +- ( +- { +- description: "id of process", +- type: "key", +- name: "tgid", +- }, +- { +- description: "role", +- type: "key", +- name: "role", +- }, +- { +- description: "client ip", +- type: "key", +- name: "client_ip", +- }, +- { +- description: "client ip before toa", +- type: "key", +- name: "toa_client_ip", +- }, +- { +- description: "server ip", +- type: "key", +- name: "server_ip", +- }, +- { +- description: "server port", +- type: "key", +- name: "server_port", +- }, +- { +- description: "protocol", +- type: "key", +- name: "protocol", + }, + { + description: "Byte length of the RX buffer.", +@@ -365,48 +155,6 @@ measurements: + description: "Byte length of the TX buffer.", + type: "histogram", + name: "sk_sndbuf", +- } +- ) +- }, +- { +- table_name: "tcp_abn", +- entity_name: "tcp_link", +- fields: +- ( +- { +- description: "id of process", +- type: "key", +- name: "tgid", +- }, +- { +- description: "role", +- type: "key", +- name: "role", +- }, +- { +- description: "client ip", +- type: "key", +- name: "client_ip", +- }, +- { +- description: "client ip before toa", +- type: "key", +- name: "toa_client_ip", +- }, +- { +- description: "server ip", +- type: "key", +- name: "server_ip", +- }, +- { +- description: "server port", +- type: "key", +- name: "server_port", +- }, +- { +- description: "protocol", +- type: "key", +- name: "protocol", + }, + { + description: "retrans packets", +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 d438c48c..2d9d89d8 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c +@@ -43,13 +43,7 @@ + #include "tcp_link.skel.h" + #include "tcp_delay.skel.h" + +-#define TCP_TBL_ABN "tcp_abn" +-#define TCP_TBL_SYNRTT "tcp_srtt" +-#define TCP_TBL_RTT "tcp_rtt" +-#define TCP_TBL_WIN "tcp_windows" +-#define TCP_TBL_RATE "tcp_rate" +-#define TCP_TBL_SOCKBUF "tcp_sockbuf" +-#define TCP_TBL_TXRX "tcp_tx_rx" ++#define TCP_TBL_METRIC "tcp_metric" + #define TCP_TBL_DELAY "proc_flow_perf" + + static int is_load_probe(struct tcp_mng_s *tcp_mng, u32 probe_load_flag) +@@ -60,7 +54,8 @@ static int is_load_probe(struct tcp_mng_s *tcp_mng, u32 probe_load_flag) + return 0; + } + +-static void output_tcp_abn(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker) ++static void output_tcp_abn(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker, ++ char *buffer, size_t size) + { + float retrans_ratio = 0.0; + report_tcp_abn_evt(&(tcp_mng->ipc_body.probe_param), tracker); +@@ -70,17 +65,8 @@ static void output_tcp_abn(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *trac + (float) tracker->stats[SEGS_SENT]); + } + +- (void)fprintf(stdout, +- "|%s|%u|%s|%s|%s|%s|%u|%u" +- "|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%.2f|\n", +- TCP_TBL_ABN, +- tracker->id.tgid, +- (tracker->id.role == 0) ? "server" : "client", +- tracker->src_ip, +- tracker->toa_src_ip ? : "", +- tracker->dst_ip, +- tracker->id.port, +- tracker->id.family, ++ (void)snprintf(buffer, size, ++ "|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%.2f", + + tracker->stats[RETRANS], + tracker->stats[BACKLOG_DROPS], +@@ -95,10 +81,10 @@ static void output_tcp_abn(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *trac + tracker->stats[SEND_RSTS], + tracker->stats[RECEIVE_RSTS], + retrans_ratio); +- (void)fflush(stdout); + } + +-static void output_tcp_syn_rtt(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker) ++static void output_tcp_syn_rtt(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker, ++ char *buffer, size_t size) + { + char *syn_srtt_historm = tcp_mng->historms[TCP_HISTORM_RTT_SYN_SRTT]; + +@@ -110,24 +96,14 @@ static void output_tcp_syn_rtt(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s * + + report_tcp_syn_rtt_evt(&(tcp_mng->ipc_body.probe_param), tracker); + +- (void)fprintf(stdout, +- "|%s|%u|%s|%s|%s|%s|%u|%u" +- "|%s|%llu|\n", +- TCP_TBL_SYNRTT, +- tracker->id.tgid, +- (tracker->id.role == 0) ? "server" : "client", +- tracker->src_ip, +- tracker->toa_src_ip ? : "", +- tracker->dst_ip, +- tracker->id.port, +- tracker->id.family, +- ++ (void)snprintf(buffer, size, ++ "|%s|%llu", + syn_srtt_historm, + tracker->stats[SYN_SRTT_MAX]); +- (void)fflush(stdout); + } + +-static void output_tcp_rtt(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker) ++static void output_tcp_rtt(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker, ++ char *buffer, size_t size) + { + char *srtt_historm = tcp_mng->historms[TCP_HISTORM_RTT_SRTT]; + char *rcv_rtt_historm = tcp_mng->historms[TCP_HISTORM_RTT_RCV_RTT]; +@@ -142,45 +118,25 @@ static void output_tcp_rtt(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *trac + return; + } + +- (void)fprintf(stdout, +- "|%s|%u|%s|%s|%s|%s|%u|%u" +- "|%s|%s|\n", +- TCP_TBL_RTT, +- tracker->id.tgid, +- (tracker->id.role == 0) ? "server" : "client", +- tracker->src_ip, +- tracker->toa_src_ip ? : "", +- tracker->dst_ip, +- tracker->id.port, +- tracker->id.family, +- ++ (void)snprintf(buffer, size, ++ "|%s|%s", + srtt_historm, + rcv_rtt_historm); +- (void)fflush(stdout); + } + +-static void output_tcp_txrx(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker) ++static void output_tcp_txrx(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker, ++ char *buffer, size_t size) + { +- (void)fprintf(stdout, +- "|%s|%u|%s|%s|%s|%s|%u|%u" +- "|%llu|%llu|%llu|%llu|\n", +- TCP_TBL_TXRX, +- tracker->id.tgid, +- (tracker->id.role == 0) ? "server" : "client", +- tracker->src_ip, +- tracker->toa_src_ip ? : "", +- tracker->dst_ip, +- tracker->id.port, +- tracker->id.family, +- ++ (void)snprintf(buffer, size, ++ "|%llu|%llu|%llu|%llu", + tracker->stats[BYTES_RECV], + tracker->stats[BYTES_SENT], + tracker->stats[SEGS_RECV], + tracker->stats[SEGS_SENT]); +- (void)fflush(stdout); + } + +-static void output_tcp_win(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker) ++static void output_tcp_win(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker, ++ char *buffer, size_t size) + { + char *snd_cwnd_historm = tcp_mng->historms[TCP_HISTORM_WIND_SND_CWND]; + char *not_sent_historm = tcp_mng->historms[TCP_HISTORM_WIND_NOT_SENT]; +@@ -232,22 +188,10 @@ static void output_tcp_win(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *trac + + report_tcp_win_evt(&(tcp_mng->ipc_body.probe_param), tracker); + +- (void)fprintf(stdout, +- "|%s|%u|%s|%s|%s|%s|%u|%u" ++ (void)snprintf(buffer, size, + "|%s|%s|%s|%s|%s|%s|%s" +- + "|%llu|%llu" +- +- "|%.2f|%.2f|\n", +- TCP_TBL_WIN, +- tracker->id.tgid, +- (tracker->id.role == 0) ? "server" : "client", +- tracker->src_ip, +- tracker->toa_src_ip ? : "", +- tracker->dst_ip, +- tracker->id.port, +- tracker->id.family, +- ++ "|%.2f|%.2f", + snd_cwnd_historm, + not_sent_historm, + not_acked_historm, +@@ -260,10 +204,10 @@ static void output_tcp_win(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *trac + tracker->stats[ZERO_WIN_TX], + + tracker->zero_win_rx_ratio, tracker->zero_win_tx_ratio); +- (void)fflush(stdout); + } + +-static void output_tcp_rate(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker) ++static void output_tcp_rate(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker, ++ char *buffer, size_t size) + { + char *rto_historm = tcp_mng->historms[TCP_HISTORM_RTO]; + char *ato_historm = tcp_mng->historms[TCP_HISTORM_ATO]; +@@ -278,23 +222,13 @@ static void output_tcp_rate(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tra + return; + } + +- (void)fprintf(stdout, +- "|%s|%u|%s|%s|%s|%s|%u|%u" +- "|%s|%s|\n", +- TCP_TBL_RATE, +- tracker->id.tgid, +- (tracker->id.role == 0) ? "server" : "client", +- tracker->src_ip, +- tracker->toa_src_ip ? : "", +- tracker->dst_ip, +- tracker->id.port, +- tracker->id.family, +- ++ (void)snprintf(buffer, size, ++ "|%s|%s", + rto_historm, ato_historm); +- (void)fflush(stdout); + } + +-static void output_tcp_sockbuf(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker) ++static void output_tcp_sockbuf(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker, ++ char *buffer, size_t size) + { + char *rcv_buf_historm = tcp_mng->historms[TCP_HISTORM_SOCKBUF_RCV]; + char *snd_buf_historm = tcp_mng->historms[TCP_HISTORM_SOCKBUF_SND]; +@@ -309,20 +243,9 @@ static void output_tcp_sockbuf(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s * + return; + } + +- (void)fprintf(stdout, +- "|%s|%u|%s|%s|%s|%s|%u|%u" +- "|%s|%s|\n", +- TCP_TBL_SOCKBUF, +- tracker->id.tgid, +- (tracker->id.role == 0) ? "server" : "client", +- tracker->src_ip, +- tracker->toa_src_ip ? : "", +- tracker->dst_ip, +- tracker->id.port, +- tracker->id.family, +- ++ (void)snprintf(buffer, size, ++ "|%s|%s", + rcv_buf_historm, snd_buf_historm); +- (void)fflush(stdout); + } + + static void output_tcp_flow_delay(struct tcp_mng_s *tcp_mng, struct tcp_flow_tracker_s *tracker) +@@ -419,53 +342,92 @@ static void reset_tcp_flow_tracker_stats(struct tcp_flow_tracker_s *tracker) + return; + } + ++/* ++ * 1. Max length of u64 is 20 ++ * 2. The longest histogram str is like this, it's length will not exceed 24 + 16 * bucket_size ++ * |8 xxxxxxxx xxxxxx (* bucket size) %llu ++ * ++ * tx_rx: |%llu|%llu|%llu|%llu, most 4 * 21 ++ * win: |histo|histo|histo|histo|histo|histo|histo|%llu|%llu|%.2f|%.2f, most 7 * 104 + 2 * 21 + 2 * 7 ++ * abn: |%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%llu|%.2f, most 12 * 21 + 7 ++ * rtt: |histo|histo, most 2 * 104 ++ * rate: |histo|histo, most 2 * 104 ++ * sockbuf: |histo|histo, most 2 * 152 ++ * synrtt: |histo|%llu, most 104 + 21 ++ * So 1024 is big enough for all types of metric ++*/ ++#define METRIC_DATA_STR_LEN 1024 + static int output_tcp_metrics(struct tcp_mng_s *tcp_mng, struct tcp_tracker_s *tracker) + { + int outputted = 0; +- u32 flags = tracker->report_flags & TCP_PROBE_ALL; +- +- if ((flags & TCP_PROBE_ABN) && is_load_probe(tcp_mng, PROBE_RANGE_TCP_ABNORMAL)) { ++ u32 report_flags = tracker->report_flags & TCP_PROBE_ALL; ++ u32 load_flags = tcp_mng->ipc_body.probe_range_flags; ++ char txrx_buf[METRIC_DATA_STR_LEN] = "||||"; ++ char rtt_buf[METRIC_DATA_STR_LEN] = "||"; ++ char win_buf[METRIC_DATA_STR_LEN] = "|||||||||||"; ++ char rate_buf[METRIC_DATA_STR_LEN] = "||"; ++ char syn_rtt_buf[METRIC_DATA_STR_LEN] = "||"; ++ char sockbuf_buf[METRIC_DATA_STR_LEN] = "||"; ++ char abn_buf[METRIC_DATA_STR_LEN] = "|||||||||||||"; ++ ++ if ((report_flags & TCP_PROBE_ABN) && (load_flags & PROBE_RANGE_TCP_ABNORMAL)) { + outputted = 1; +- output_tcp_abn(tcp_mng, tracker); ++ output_tcp_abn(tcp_mng, tracker, abn_buf, sizeof(abn_buf)); + reset_tcp_abn_stats(tracker); + } + +- if ((flags & TCP_PROBE_SRTT) && is_load_probe(tcp_mng, PROBE_RANGE_TCP_SRTT)) { ++ if ((report_flags & TCP_PROBE_SRTT) && (load_flags & PROBE_RANGE_TCP_SRTT)) { + outputted = 1; +- output_tcp_syn_rtt(tcp_mng, tracker); ++ output_tcp_syn_rtt(tcp_mng, tracker, syn_rtt_buf, sizeof(syn_rtt_buf)); + reset_tcp_syn_rtt_stats(tracker); + } + +- if ((flags & TCP_PROBE_WINDOWS) && is_load_probe(tcp_mng, PROBE_RANGE_TCP_WINDOWS)) { ++ if ((report_flags & TCP_PROBE_WINDOWS) && (load_flags & PROBE_RANGE_TCP_WINDOWS)) { + outputted = 1; +- output_tcp_win(tcp_mng, tracker); ++ output_tcp_win(tcp_mng, tracker, win_buf, sizeof(win_buf)); + reset_tcp_win_stats(tracker); + } + +- if ((flags & TCP_PROBE_RTT) && is_load_probe(tcp_mng, PROBE_RANGE_TCP_RTT)) { ++ if ((report_flags & TCP_PROBE_RTT) && (load_flags & PROBE_RANGE_TCP_RTT)) { + outputted = 1; +- output_tcp_rtt(tcp_mng, tracker); ++ output_tcp_rtt(tcp_mng, tracker, rtt_buf, sizeof(rtt_buf)); + reset_tcp_rtt_stats(tracker); + } + +- if ((flags & TCP_PROBE_TXRX) && is_load_probe(tcp_mng, PROBE_RANGE_TCP_STATS)) { ++ if ((report_flags & TCP_PROBE_TXRX) && (load_flags & PROBE_RANGE_TCP_STATS)) { + outputted = 1; +- output_tcp_txrx(tcp_mng, tracker); ++ output_tcp_txrx(tcp_mng, tracker, txrx_buf, sizeof(txrx_buf)); + reset_tcp_txrx_stats(tracker); + } + +- if ((flags & TCP_PROBE_SOCKBUF) && is_load_probe(tcp_mng, PROBE_RANGE_TCP_SOCKBUF)) { ++ if ((report_flags & TCP_PROBE_SOCKBUF) && (load_flags & PROBE_RANGE_TCP_SOCKBUF)) { + outputted = 1; +- output_tcp_sockbuf(tcp_mng, tracker); ++ output_tcp_sockbuf(tcp_mng, tracker, sockbuf_buf, sizeof(sockbuf_buf)); + reset_tcp_sockbuf_stats(tracker); + } + +- if ((flags & TCP_PROBE_RATE) && is_load_probe(tcp_mng, PROBE_RANGE_TCP_RATE)) { ++ if ((report_flags & TCP_PROBE_RATE) && (load_flags & PROBE_RANGE_TCP_RATE)) { + outputted = 1; +- output_tcp_rate(tcp_mng, tracker); ++ output_tcp_rate(tcp_mng, tracker, rate_buf, sizeof(rate_buf)); + reset_tcp_rate_stats(tracker); + } + ++ if (outputted) { ++ (void)fprintf(stdout, ++ "|%s|%u|%s|%s|%s|%s|%u|%u" ++ "%s%s%s%s%s%s%s|\n", ++ TCP_TBL_METRIC, ++ tracker->id.tgid, ++ (tracker->id.role == 0) ? "server" : "client", ++ tracker->src_ip, ++ tracker->toa_src_ip ? : "", ++ tracker->dst_ip, ++ tracker->id.port, ++ tracker->id.family, ++ ++ txrx_buf, rtt_buf, win_buf, rate_buf, syn_rtt_buf, sockbuf_buf, abn_buf); ++ (void)fflush(stdout); ++ } + tracker->report_flags = 0; + return outputted; + } +-- +2.33.0 + diff --git a/tcpprobe-reset-sk-link-state-when-tcp-link-was-delet.patch b/tcpprobe-reset-sk-link-state-when-tcp-link-was-delet.patch new file mode 100644 index 0000000..908a169 --- /dev/null +++ b/tcpprobe-reset-sk-link-state-when-tcp-link-was-delet.patch @@ -0,0 +1,69 @@ +From a70dfcbd2e37a16de4fa341a3ad46056caac19aa Mon Sep 17 00:00:00 2001 +From: Vchanger +Date: Thu, 26 Dec 2024 16:30:28 +0800 +Subject: [PATCH 35/99] tcpprobe: reset sk link state when tcp link was deleted + due to out of snooper + +--- + .../ebpf.probe/src/tcpprobe/tcp_link.h | 26 +++++++------------ + 1 file changed, 9 insertions(+), 17 deletions(-) + +diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h +index 78b88414..71533b00 100644 +--- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h ++++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h +@@ -94,19 +94,6 @@ static __always_inline __maybe_unused u64 get_period(void) + return period; // units from second to nanosecond + } + +-static __always_inline __maybe_unused int is_gopher_comm(void) +-{ +- char comm[TASK_COMM_LEN] = {0}; +- +- (void)bpf_get_current_comm(&comm, sizeof(comm)); +- +- // TODO: need to modify when we drop libmicrohttpd +- if (comm[0] == 'M' && comm[1] == 'H' && comm[2] == 'D' && comm[3] == '-') { +- return 1; +- } +- return 0; +-} +- + static __always_inline __maybe_unused char is_valid_tgid(u32 tgid) + { + struct proc_s obj = {.proc_id = tgid}; +@@ -136,6 +123,14 @@ static __always_inline __maybe_unused int delete_tcp_link(struct sock *sk) + return bpf_map_delete_elem(&tcp_link_map, &sk); + } + ++static __always_inline __maybe_unused void reset_sock_obj_link_state(struct sock *sk) ++{ ++ struct sock_info_s *sock_info = bpf_map_lookup_elem(&sock_map, &sk); ++ if (sock_info) { ++ sock_info->tcp_link_ok = 0; ++ } ++} ++ + static __always_inline __maybe_unused struct tcp_metrics_s *get_tcp_metrics(struct sock *sk) + { + struct sock_stats_s *sock_stats; +@@ -149,15 +144,12 @@ static __always_inline __maybe_unused struct tcp_metrics_s *get_tcp_metrics(stru + return &(sock_stats->metrics); + } + (void)delete_tcp_link(sk); ++ reset_sock_obj_link_state(sk); + return NULL; + } + + static __always_inline __maybe_unused int create_sock_obj(u32 tgid, struct sock *sk, struct sock_info_s *info) + { +- if (is_gopher_comm()) { +- return 0; +- } +- + info->proc_id = tgid; + return bpf_map_update_elem(&sock_map, &sk, info, BPF_ANY); + } +-- +2.33.0 + -- Gitee