|
@@ -60,6 +60,13 @@ struct {
|
|
|
__uint(max_entries, MAX_CONCURRENT);
|
|
__uint(max_entries, MAX_CONCURRENT);
|
|
|
} golang_mapbucket_storage_map SEC(".maps");
|
|
} golang_mapbucket_storage_map SEC(".maps");
|
|
|
|
|
|
|
|
|
|
+struct {
|
|
|
|
|
+ __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
|
|
|
|
|
+ __uint(key_size, sizeof(u32));
|
|
|
|
|
+ __uint(value_size, sizeof(struct map_bucket_extended));
|
|
|
|
|
+ __uint(max_entries, MAX_CONCURRENT);
|
|
|
|
|
+} golang_mapbucket_extended_storage_map SEC(".maps");
|
|
|
|
|
+
|
|
|
struct {
|
|
struct {
|
|
|
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
|
|
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
|
|
|
__uint(key_size, sizeof(u32));
|
|
__uint(key_size, sizeof(u32));
|
|
@@ -247,7 +254,206 @@ static __always_inline struct span_context *extract_context_from_req_headers(voi
|
|
|
return NULL;
|
|
return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// 获取 get_map_bucket
|
|
|
|
|
|
|
+// 在单个bucket中搜索header值
|
|
|
|
|
+static __always_inline char *search_header_in_bucket(
|
|
|
|
|
+ struct go_bmap *bmap,
|
|
|
|
|
+ u32 start_idx,
|
|
|
|
|
+ u32 end_idx) {
|
|
|
|
|
+
|
|
|
|
|
+ for (u32 i = start_idx; i < end_idx && i < 8; i++) {
|
|
|
|
|
+ if (bmap->tophash[i] != 0 && bmap->keys[i].len == CW_HEADER_KEY_LENGTH) {
|
|
|
|
|
+ char current_header_key[CW_HEADER_KEY_LENGTH];
|
|
|
|
|
+ bpf_probe_read(current_header_key, sizeof(current_header_key), bmap->keys[i].str);
|
|
|
|
|
+
|
|
|
|
|
+ if ((current_header_key[0] == CW_HEADER_KEY_VAL[0] ||
|
|
|
|
|
+ current_header_key[0] == CW_HEADER_KEY_UFIRST_VAL[0]) &&
|
|
|
|
|
+ current_header_key[1] == CW_HEADER_KEY_UFIRST_VAL[1] &&
|
|
|
|
|
+ current_header_key[2] == CW_HEADER_KEY_UFIRST_VAL[2] &&
|
|
|
|
|
+ current_header_key[3] == CW_HEADER_KEY_UFIRST_VAL[3] &&
|
|
|
|
|
+ current_header_key[4] == CW_HEADER_KEY_UFIRST_VAL[4] &&
|
|
|
|
|
+ current_header_key[5] == CW_HEADER_KEY_UFIRST_VAL[5] &&
|
|
|
|
|
+ current_header_key[6] == CW_HEADER_KEY_UFIRST_VAL[6]) {
|
|
|
|
|
+
|
|
|
|
|
+ void *traceparent_header_value_ptr = bmap->values[i].array;
|
|
|
|
|
+ struct go_string_ot traceparent_header_value_go_str;
|
|
|
|
|
+ long res = bpf_probe_read(&traceparent_header_value_go_str,
|
|
|
|
|
+ sizeof(traceparent_header_value_go_str),
|
|
|
|
|
+ traceparent_header_value_ptr);
|
|
|
|
|
+ if (res == 0) {
|
|
|
|
|
+ cw_bpf_debug("Found header in bucket at index %d", i);
|
|
|
|
|
+ return traceparent_header_value_go_str.str;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 搜索header值(支持overflow bucket)
|
|
|
|
|
+static __always_inline char *get_header_val_with_overflow(
|
|
|
|
|
+ struct map_bucket_extended *bucket_ext,
|
|
|
|
|
+ u32 max_overflow_chain_length) {
|
|
|
|
|
+
|
|
|
|
|
+ // 首先在主bucket中搜索
|
|
|
|
|
+ char *val = search_header_in_bucket(&bucket_ext->bmap, 0, 8);
|
|
|
|
|
+ if (val != NULL) {
|
|
|
|
|
+ return val;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果主bucket没找到,搜索overflow bucket
|
|
|
|
|
+ if (bucket_ext->bmap.overflow != NULL) {
|
|
|
|
|
+ void *current_overflow = bucket_ext->bmap.overflow;
|
|
|
|
|
+ u32 chain_length = 0;
|
|
|
|
|
+
|
|
|
|
|
+ while (current_overflow != NULL && chain_length < max_overflow_chain_length) {
|
|
|
|
|
+ struct go_bmap overflow_bmap;
|
|
|
|
|
+ long res = bpf_probe_read(&overflow_bmap, sizeof(struct go_bmap), current_overflow);
|
|
|
|
|
+ if (res < 0) {
|
|
|
|
|
+ cw_bpf_debug("Failed to read overflow bucket at chain length %d", chain_length);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 在overflow bucket中搜索
|
|
|
|
|
+ val = search_header_in_bucket(&overflow_bmap, 0, 8);
|
|
|
|
|
+ if (val != NULL) {
|
|
|
|
|
+ cw_bpf_debug("Found header in overflow bucket at chain length %d", chain_length);
|
|
|
|
|
+ return val;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 移动到下一个overflow bucket
|
|
|
|
|
+ res = bpf_probe_read(¤t_overflow, sizeof(current_overflow),
|
|
|
|
|
+ current_overflow + offsetof(struct go_bmap, overflow));
|
|
|
|
|
+ if (res < 0) {
|
|
|
|
|
+ cw_bpf_debug("Failed to read next overflow bucket pointer");
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ chain_length++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ cw_bpf_debug("Searched %d overflow buckets, max allowed: %d", chain_length, max_overflow_chain_length);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 读取单个bucket(包括overflow chain)
|
|
|
|
|
+static __always_inline struct map_bucket_extended *read_bucket_with_overflow(
|
|
|
|
|
+ void *bucket_ptr,
|
|
|
|
|
+ u32 max_overflow_chain_length) {
|
|
|
|
|
+
|
|
|
|
|
+ u32 map_id = 0;
|
|
|
|
|
+ struct map_bucket_extended *result = bpf_map_lookup_elem(&golang_mapbucket_extended_storage_map, &map_id);
|
|
|
|
|
+ if (!result) {
|
|
|
|
|
+ cw_bpf_debug("Failed to get extended bucket storage");
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ __builtin_memset(result, 0, sizeof(struct map_bucket_extended));
|
|
|
|
|
+
|
|
|
|
|
+ // 读取主bucket
|
|
|
|
|
+ long res = bpf_probe_read(&result->bmap, sizeof(struct go_bmap), bucket_ptr);
|
|
|
|
|
+ if (res < 0) {
|
|
|
|
|
+ cw_bpf_debug("Failed to read main bucket");
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ result->is_overflow = 0;
|
|
|
|
|
+ result->overflow_chain_length = 0;
|
|
|
|
|
+
|
|
|
|
|
+ // 检查是否有overflow bucket
|
|
|
|
|
+ if (result->bmap.overflow != NULL) {
|
|
|
|
|
+ result->is_overflow = 1;
|
|
|
|
|
+ result->overflow_chain_length = 1;
|
|
|
|
|
+
|
|
|
|
|
+ // 遍历overflow chain(限制最大长度避免无限循环)
|
|
|
|
|
+ void *current_overflow = result->bmap.overflow;
|
|
|
|
|
+ u32 chain_length = 1;
|
|
|
|
|
+
|
|
|
|
|
+ while (current_overflow != NULL && chain_length < max_overflow_chain_length) {
|
|
|
|
|
+ void *next_overflow;
|
|
|
|
|
+ res = bpf_probe_read(&next_overflow, sizeof(next_overflow),
|
|
|
|
|
+ current_overflow + offsetof(struct go_bmap, overflow));
|
|
|
|
|
+ if (res < 0) {
|
|
|
|
|
+ cw_bpf_debug("Failed to read overflow chain at length %d", chain_length);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ current_overflow = next_overflow;
|
|
|
|
|
+ chain_length++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ result->overflow_chain_length = chain_length;
|
|
|
|
|
+ cw_bpf_debug("Found overflow chain with length %d", chain_length);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 获取 map_bucket(支持overflow)
|
|
|
|
|
+static __always_inline struct map_bucket_extended *get_map_bucket_with_overflow(
|
|
|
|
|
+ void *headers_ptr_ptr,
|
|
|
|
|
+ u32 max_overflow_chain_length) {
|
|
|
|
|
+
|
|
|
|
|
+ void *headers_ptr;
|
|
|
|
|
+ long res = bpf_probe_read(&headers_ptr, sizeof(headers_ptr), headers_ptr_ptr);
|
|
|
|
|
+ if (res < 0) {
|
|
|
|
|
+ cw_bpf_debug("Failed to read headers pointer");
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ u64 headers_count = 0;
|
|
|
|
|
+ res = bpf_probe_read(&headers_count, sizeof(headers_count), headers_ptr);
|
|
|
|
|
+ if (res < 0) {
|
|
|
|
|
+ cw_bpf_debug("Failed to read headers count");
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (headers_count == 0) {
|
|
|
|
|
+ cw_bpf_debug("Headers count is 0");
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ unsigned char log_2_bucket_count;
|
|
|
|
|
+ res = bpf_probe_read(&log_2_bucket_count, sizeof(log_2_bucket_count), headers_ptr + 9);
|
|
|
|
|
+ if (res < 0) {
|
|
|
|
|
+ cw_bpf_debug("Failed to read log_2_bucket_count");
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+ u64 bucket_count = 1 << log_2_bucket_count;
|
|
|
|
|
+
|
|
|
|
|
+ __u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
|
|
|
+ __u32 tgid = pid_tgid >> 32;
|
|
|
|
|
+ struct ebpf_proc_info *proc_info = bpf_map_lookup_elem(&proc_info_map, &tgid);
|
|
|
|
|
+ if (!proc_info) {
|
|
|
|
|
+ cw_bpf_debug("No proc info found");
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void *header_buckets;
|
|
|
|
|
+ res = bpf_probe_read(&header_buckets, sizeof(header_buckets),
|
|
|
|
|
+ (void *)(headers_ptr + proc_info->buckets_ptr_pos));
|
|
|
|
|
+ if (res < 0) {
|
|
|
|
|
+ cw_bpf_debug("Failed to read header buckets pointer");
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ cw_bpf_debug("Searching %d buckets with max overflow chain length %d", bucket_count, max_overflow_chain_length);
|
|
|
|
|
+
|
|
|
|
|
+ // 遍历所有buckets
|
|
|
|
|
+ for (u32 j = 0; j < bucket_count; j++) {
|
|
|
|
|
+ void *current_bucket = header_buckets + (j * sizeof(struct go_bmap));
|
|
|
|
|
+ struct map_bucket_extended *result = read_bucket_with_overflow(
|
|
|
|
|
+ current_bucket, max_overflow_chain_length);
|
|
|
|
|
+
|
|
|
|
|
+ if (result != NULL) {
|
|
|
|
|
+ cw_bpf_debug("Found valid bucket at index %d", j);
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ cw_bpf_debug("No valid bucket found");
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 获取 get_map_bucket(保持向后兼容)
|
|
|
static __always_inline struct map_bucket *get_map_bucket(void *headers_ptr_ptr) {
|
|
static __always_inline struct map_bucket *get_map_bucket(void *headers_ptr_ptr) {
|
|
|
void *headers_ptr;
|
|
void *headers_ptr;
|
|
|
long res;
|
|
long res;
|
|
@@ -301,6 +507,84 @@ static __always_inline struct map_bucket *get_map_bucket(void *headers_ptr_ptr)
|
|
|
return NULL;
|
|
return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// 简化的overflow bucket搜索函数
|
|
|
|
|
+static __always_inline char *get_header_val_with_overflow_simple(void *headers_ptr_ptr) {
|
|
|
|
|
+ void *headers_ptr;
|
|
|
|
|
+ long res = bpf_probe_read(&headers_ptr, sizeof(headers_ptr), headers_ptr_ptr);
|
|
|
|
|
+ if (res < 0) {
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ u64 headers_count = 0;
|
|
|
|
|
+ res = bpf_probe_read(&headers_count, sizeof(headers_count), headers_ptr);
|
|
|
|
|
+ if (res < 0 || headers_count == 0) {
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ unsigned char log_2_bucket_count;
|
|
|
|
|
+ res = bpf_probe_read(&log_2_bucket_count, sizeof(log_2_bucket_count), headers_ptr + 9);
|
|
|
|
|
+ if (res < 0) {
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+ u64 bucket_count = 1 << log_2_bucket_count;
|
|
|
|
|
+
|
|
|
|
|
+ __u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
|
|
|
+ __u32 tgid = pid_tgid >> 32;
|
|
|
|
|
+ struct ebpf_proc_info *proc_info = bpf_map_lookup_elem(&proc_info_map, &tgid);
|
|
|
|
|
+ if (!proc_info) {
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void *header_buckets;
|
|
|
|
|
+ res = bpf_probe_read(&header_buckets, sizeof(header_buckets),
|
|
|
|
|
+ (void *)(headers_ptr + proc_info->buckets_ptr_pos));
|
|
|
|
|
+ if (res < 0) {
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ u32 map_id = 0;
|
|
|
|
|
+ struct map_bucket *map_value = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id);
|
|
|
|
|
+ if (!map_value) {
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 遍历所有buckets
|
|
|
|
|
+ for (u32 j = 0; j < bucket_count; j++) {
|
|
|
|
|
+ __builtin_memset(map_value, 0, sizeof(struct map_bucket));
|
|
|
|
|
+
|
|
|
|
|
+ // 读取主bucket
|
|
|
|
|
+ res = bpf_probe_read(map_value, sizeof(struct map_bucket),
|
|
|
|
|
+ header_buckets + (j * sizeof(struct map_bucket)));
|
|
|
|
|
+ if (res < 0) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 在主bucket中搜索
|
|
|
|
|
+ char *val = get_header_val(map_value, 0, 8);
|
|
|
|
|
+ if (val != NULL) {
|
|
|
|
|
+ cw_bpf_debug("Found header in main bucket %d", j);
|
|
|
|
|
+ return val;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 检查是否有overflow bucket
|
|
|
|
|
+ if (map_value->overflow != NULL) {
|
|
|
|
|
+ cw_bpf_debug("Found overflow bucket for bucket %d", j);
|
|
|
|
|
+
|
|
|
|
|
+ // 读取overflow bucket
|
|
|
|
|
+ res = bpf_probe_read(map_value, sizeof(struct map_bucket), map_value->overflow);
|
|
|
|
|
+ if (res == 0) {
|
|
|
|
|
+ val = get_header_val(map_value, 0, 8);
|
|
|
|
|
+ if (val != NULL) {
|
|
|
|
|
+ cw_bpf_debug("Found header in overflow bucket for bucket %d", j);
|
|
|
|
|
+ return val;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// 获取 header_val
|
|
// 获取 header_val
|
|
|
static __always_inline char *get_header_val(struct map_bucket *map_value,u32 off,u32 count) {
|
|
static __always_inline char *get_header_val(struct map_bucket *map_value,u32 off,u32 count) {
|
|
|
for (u32 i = off; i < count; i++) {
|
|
for (u32 i = off; i < count; i++) {
|
|
@@ -387,13 +671,10 @@ int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) {
|
|
|
|
|
|
|
|
// Propagate context
|
|
// Propagate context
|
|
|
void *req_ptr = get_argument(ctx, 4);
|
|
void *req_ptr = get_argument(ctx, 4);
|
|
|
- struct map_bucket * map_bucket_p = get_map_bucket((void *) (req_ptr + proc_info->headers_ptr_pos));
|
|
|
|
|
-
|
|
|
|
|
- if (map_bucket_p == NULL) {
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- char * traceparent_header_value = get_header_val_off(map_bucket_p);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 使用改进的搜索函数,支持overflow bucket
|
|
|
|
|
+ char *traceparent_header_value = get_header_val_with_overflow_simple(
|
|
|
|
|
+ (void *)(req_ptr + proc_info->headers_ptr_pos));
|
|
|
struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&cw_parent_span_context_storage_map, &map_id);
|
|
struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&cw_parent_span_context_storage_map, &map_id);
|
|
|
if (!cw_parent_span_context) {
|
|
if (!cw_parent_span_context) {
|
|
|
return 0;
|
|
return 0;
|
|
@@ -401,7 +682,7 @@ int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) {
|
|
|
__builtin_memset(cw_parent_span_context, 0, sizeof(struct apm_span_context));
|
|
__builtin_memset(cw_parent_span_context, 0, sizeof(struct apm_span_context));
|
|
|
|
|
|
|
|
if (traceparent_header_value != NULL) {
|
|
if (traceparent_header_value != NULL) {
|
|
|
- cw_bpf_debug("traceparent_header_value != NULL");
|
|
|
|
|
|
|
+ bpf_printk("traceparent_header_value != NULL");
|
|
|
|
|
|
|
|
cw_string_to_span_context(traceparent_header_value, cw_parent_span_context);
|
|
cw_string_to_span_context(traceparent_header_value, cw_parent_span_context);
|
|
|
// found parent context in http headers
|
|
// found parent context in http headers
|
|
@@ -412,7 +693,7 @@ int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) {
|
|
|
generate_random_bytes(http_server_span->sc.SpanID, SPAN_ID_SIZE);
|
|
generate_random_bytes(http_server_span->sc.SpanID, SPAN_ID_SIZE);
|
|
|
cw_save_parent_tracking_span(cw_parent_span_context);
|
|
cw_save_parent_tracking_span(cw_parent_span_context);
|
|
|
} else {
|
|
} else {
|
|
|
- cw_bpf_debug("traceparent_header_value == NULL");
|
|
|
|
|
|
|
+ bpf_printk("traceparent_header_value == NULL");
|
|
|
http_server_span->sc = generate_span_context();
|
|
http_server_span->sc = generate_span_context();
|
|
|
|
|
|
|
|
struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&cw_parent_span_context_storage_map, &map_id);
|
|
struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&cw_parent_span_context_storage_map, &map_id);
|