|
|
@@ -33,6 +33,15 @@ struct grpc_header_ctx_t {
|
|
|
u32 frame_stream_id_pod_offset;
|
|
|
};
|
|
|
|
|
|
+// 用于处理头部的临时结构,减少栈使用
|
|
|
+struct grpc_header_work_t {
|
|
|
+ struct hpack_header_field hf;
|
|
|
+ char val[W3C_VAL_LENGTH];
|
|
|
+ u32 part1;
|
|
|
+ u32 part2;
|
|
|
+ u32 part3;
|
|
|
+};
|
|
|
+
|
|
|
struct {
|
|
|
__uint(type, BPF_MAP_TYPE_HASH);
|
|
|
__type(key, void *);
|
|
|
@@ -70,6 +79,14 @@ struct {
|
|
|
__uint(max_entries, 1);
|
|
|
} grpc_header_ctx_storage SEC(".maps");
|
|
|
|
|
|
+// 工作缓冲区,避免栈空间超限
|
|
|
+struct {
|
|
|
+ __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
|
|
|
+ __uint(key_size, sizeof(u32));
|
|
|
+ __uint(value_size, sizeof(struct grpc_header_work_t));
|
|
|
+ __uint(max_entries, 1);
|
|
|
+} grpc_header_work_storage SEC(".maps");
|
|
|
+
|
|
|
struct hpack_header_field {
|
|
|
struct go_string_ot name;
|
|
|
struct go_string_ot value;
|
|
|
@@ -512,13 +529,20 @@ PROGUP(grpc_server_process_headers)(struct pt_regs *ctx) {
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+ // 获取工作缓冲区,避免栈溢出
|
|
|
+ struct grpc_header_work_t *work =
|
|
|
+ bpf_map_lookup_elem(&grpc_header_work_storage, &zero);
|
|
|
+ if (work == NULL) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
void *frame_ptr = header_ctx->frame_ptr;
|
|
|
void *header_fields_ptr = header_ctx->header_fields_ptr;
|
|
|
s64 header_fields_len = header_ctx->header_fields_len;
|
|
|
s32 start_idx = header_ctx->current_index;
|
|
|
|
|
|
- // 每次处理最多 5 个头部,避免指令数过多
|
|
|
- #define BATCH_SIZE 5
|
|
|
+ // 每次处理最多 3 个头部,进一步减少复杂度
|
|
|
+ #define BATCH_SIZE 3
|
|
|
s32 end_idx = start_idx + BATCH_SIZE;
|
|
|
if (end_idx > header_fields_len) {
|
|
|
end_idx = header_fields_len;
|
|
|
@@ -531,40 +555,35 @@ PROGUP(grpc_server_process_headers)(struct pt_regs *ctx) {
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- // 读取头部字段
|
|
|
- struct hpack_header_field hf = {};
|
|
|
- long res = bpf_probe_read(&hf, sizeof(hf),
|
|
|
- (void *)(header_fields_ptr + (i * sizeof(hf))));
|
|
|
+ // 读取头部字段到 work 缓冲区
|
|
|
+ long res = bpf_probe_read(&work->hf, sizeof(work->hf),
|
|
|
+ (void *)(header_fields_ptr + (i * sizeof(work->hf))));
|
|
|
if (res != 0) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
// 快速检查:长度必须匹配
|
|
|
- if (hf.name.len != W3C_KEY_LENGTH || hf.value.len != W3C_VAL_LENGTH) {
|
|
|
+ if (work->hf.name.len != W3C_KEY_LENGTH || work->hf.value.len != W3C_VAL_LENGTH) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
// 分段比较 "traceparent" (11 字节)
|
|
|
- // 避免使用 bpf_memcmp,使用简单的整数比较
|
|
|
- u32 part1 = 0, part2 = 0, part3 = 0;
|
|
|
- bpf_probe_read(&part1, 4, hf.name.str); // "trac" = 0x63617274
|
|
|
- bpf_probe_read(&part2, 4, hf.name.str + 4); // "epar" = 0x72617065
|
|
|
- bpf_probe_read(&part3, 3, hf.name.str + 8); // "ent" = 0x746e65
|
|
|
+ work->part1 = 0;
|
|
|
+ work->part2 = 0;
|
|
|
+ work->part3 = 0;
|
|
|
+ bpf_probe_read(&work->part1, 4, work->hf.name.str);
|
|
|
+ bpf_probe_read(&work->part2, 4, work->hf.name.str + 4);
|
|
|
+ bpf_probe_read(&work->part3, 3, work->hf.name.str + 8);
|
|
|
|
|
|
// 检查是否匹配 "traceparent"
|
|
|
- if (part1 != 0x63617274 || part2 != 0x72617065 ||
|
|
|
- (part3 & 0xFFFFFF) != 0x746e65) {
|
|
|
+ if (work->part1 != 0x63617274 || work->part2 != 0x72617065 ||
|
|
|
+ (work->part3 & 0xFFFFFF) != 0x746e65) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- // 找到 traceparent 头部!
|
|
|
- bpf_printk("grpc:server:operateHeader: found traceparent at index %d", i);
|
|
|
-
|
|
|
- // 读取 traceparent 值
|
|
|
- char val[W3C_VAL_LENGTH];
|
|
|
- res = bpf_probe_read(val, W3C_VAL_LENGTH, hf.value.str);
|
|
|
+ // 找到 traceparent 头部!读取值到 work 缓冲区
|
|
|
+ res = bpf_probe_read(work->val, W3C_VAL_LENGTH, work->hf.value.str);
|
|
|
if (res != 0) {
|
|
|
- bpf_printk("grpc:server:operateHeader: failed to read traceparent value");
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
@@ -572,7 +591,6 @@ PROGUP(grpc_server_process_headers)(struct pt_regs *ctx) {
|
|
|
void *headers_frame = NULL;
|
|
|
res = bpf_probe_read(&headers_frame, sizeof(headers_frame), frame_ptr);
|
|
|
if (res != 0) {
|
|
|
- bpf_printk("grpc:server:operateHeader: failed to read headers_frame");
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
@@ -580,27 +598,23 @@ PROGUP(grpc_server_process_headers)(struct pt_regs *ctx) {
|
|
|
res = bpf_probe_read(&stream_id, sizeof(stream_id),
|
|
|
(void *)(headers_frame + header_ctx->frame_stream_id_pod_offset));
|
|
|
if (res != 0) {
|
|
|
- bpf_printk("grpc:server:operateHeader: failed to read stream_id");
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- bpf_printk("grpc:server:operateHeader: stream_id=%u", stream_id);
|
|
|
-
|
|
|
// 使用临时存储
|
|
|
struct grpc_request_t *grpcReq =
|
|
|
bpf_map_lookup_elem(&operate_header_storage, &zero);
|
|
|
if (grpcReq == NULL) {
|
|
|
- bpf_printk("grpc:server:operateHeader: failed to get storage");
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
// 清零并初始化
|
|
|
__builtin_memset(grpcReq, 0, sizeof(struct grpc_request_t));
|
|
|
|
|
|
- // 解析 W3C trace context (可选,如果需要的话)
|
|
|
- // w3c_string_to_span_context(val, &grpcReq->psc);
|
|
|
+ // 解析 W3C trace context (可选)
|
|
|
+ // w3c_string_to_span_context(work->val, &grpcReq->psc);
|
|
|
|
|
|
- // 保存到 map,供后续 handleStream 使用
|
|
|
+ // 保存到 map
|
|
|
bpf_map_update_elem(&streamid_to_grpc_events, &stream_id, grpcReq, 0);
|
|
|
|
|
|
// 找到就退出
|