Преглед изворни кода

Feature #TASK_QT-18250 header

Feature #TASK_QT-18250 header

Feature #TASK_QT-18250 header

Feature #TASK_QT-18250 header

Feature #TASK_QT-18250 header2
Carl пре 8 месеци
родитељ
комит
9b32d25eb7

+ 4 - 0
ebpftracer/ebpf/include/apm_trace.h

@@ -104,5 +104,9 @@ static __always_inline void cw_copy_byte_arrays(unsigned char *src, unsigned cha
 		dst[i] = src[i];
 	}
 }
+static __inline __u32 has_cw_header(const char *data);
+static __always_inline void copy_byte_arrays(unsigned char *src, unsigned char *dst, __u32 size);
+static __always_inline void generate_random_bytes(unsigned char *buff, __u32 size);
+static __always_inline void hex_string_to_bytes(char *str, __u32 size, unsigned char *out);
 
 #endif //EUSPACES_APM_TRACE_H

+ 2 - 1
ebpftracer/ebpf/include/common.h

@@ -74,7 +74,8 @@ enum code_type {
 	CodeTypeNetCoreAot = 1108,
 	CodeTypeLua        = 1009,
 	CodeTypeJavaC      = 1010,
-	CodeTypeRuby       = 1012
+	CodeTypeRuby       = 1012,
+	CodeTypeNginx      = 1019
 };
 
 #endif /* DF_BPF_COMMON_H */

+ 149 - 0
ebpftracer/ebpf/l7/apm_trace.c

@@ -86,6 +86,12 @@ struct {
 	__uint(max_entries, 1);
 } socket_heap SEC(".maps");
 
+struct {
+	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
+	__type(key, int);
+	__type(value, struct apm_span_context);
+	__uint(max_entries, 1);
+} apm_span_context_heap SEC(".maps");
 
 static __inline __attribute__((__always_inline__))
 struct apm_trace_key_t get_apm_trace_key(__u64 timeout, bool is_socket_io) {
@@ -523,3 +529,146 @@ struct apm_trace_info_t cw_save_trace_info(__u64 id, __u32 pid, __u64 fd) {
 	bpf_map_update_elem(&trace_event_count_heap, &trace_info.trace_id, &event_count, BPF_NOEXIST);
 	return trace_info;
 }
+
+/* 直接从 ip_net (u32 network order) + port_field (u32 raw msg->remote_port)
+ * 提取高16位 port(network order),并直接生成 8 字节 每字节 0..9 的 assumed_app_id_out
+ */
+static __always_inline void ipport_to_16digits_from_u32_high(__u32 ip_net, __u32 port_field, unsigned char out[16]) {
+	// 1) 提取 port 高 16 位(network-order),和 ip 的 4 字节(network-order)
+	__u16 port_net_high = (__u16)((port_field >> 16) & 0xffff);
+
+	__u8 b0 = (ip_net >> 24) & 0xFF;
+	__u8 b1 = (ip_net >> 16) & 0xFF;
+	__u8 b2 = (ip_net >> 8) & 0xFF;
+	__u8 b3 = (ip_net) & 0xFF;
+	__u8 p0 = (port_net_high >> 8) & 0xFF;
+	__u8 p1 = (port_net_high) & 0xFF;
+
+	// 2) 两轮 FNV-1a:h1 和 h2(h2 用不同种子/tweak),各自产出 8 字节,共 16 字节 raw
+	uint64_t h1 = 14695981039346656037ULL; // FNV offset basis
+#pragma clang loop unroll(full)
+	for (int i = 0; i < 6; i++) {
+		__u8 v = (i==0)?b0: (i==1)?b1: (i==2)?b2: (i==3)?b3: (i==4)?p0: p1;
+		h1 ^= (uint64_t)v;
+		h1 *= (uint64_t)1099511628211ULL;
+	}
+	uint64_t h2 = 14695981039346656037ULL ^ 0x9e3779b97f4a7c15ULL; // tweak seed
+#pragma clang loop unroll(full)
+	for (int i = 0; i < 6; i++) {
+		__u8 v = (i==0)?b0: (i==1)?b1: (i==2)?b2: (i==3)?b3: (i==4)?p0: p1;
+		h2 ^= (uint64_t)v;
+		h2 *= (uint64_t)1099511628211ULL;
+	}
+
+	__u8 raw[16];
+	// h1 -> raw[0..7] (big-endian)
+	raw[0] = (h1 >> 56) & 0xFF;
+	raw[1] = (h1 >> 48) & 0xFF;
+	raw[2] = (h1 >> 40) & 0xFF;
+	raw[3] = (h1 >> 32) & 0xFF;
+	raw[4] = (h1 >> 24) & 0xFF;
+	raw[5] = (h1 >> 16) & 0xFF;
+	raw[6] = (h1 >> 8) & 0xFF;
+	raw[7] = (h1) & 0xFF;
+	// h2 -> raw[8..15] (big-endian)
+	raw[8]  = (h2 >> 56) & 0xFF;
+	raw[9]  = (h2 >> 48) & 0xFF;
+	raw[10] = (h2 >> 40) & 0xFF;
+	raw[11] = (h2 >> 32) & 0xFF;
+	raw[12] = (h2 >> 24) & 0xFF;
+	raw[13] = (h2 >> 16) & 0xFF;
+	raw[14] = (h2 >> 8) & 0xFF;
+	raw[15] = (h2) & 0xFF;
+
+	// 3) 把每个 raw byte 映射到 0..9(用 mod10_u8 不用除法)
+#pragma clang loop unroll(full)
+	for (int i = 0; i < 16; i++) {
+		__u8 x = raw[i];
+		__u32 q = ((__u32)x * 205U) >> 11; // approximate x/10
+		__u8 r = ( __u8 )( x - ( (__u8)(q * 10U) ) ); // r == x % 10 for 0..255
+		out[i] = (unsigned char) r;
+	}
+
+	// 4) 确保第 0 字节不是 0(按你历史逻辑)
+	if (out[0] == 0) out[0] = 1;
+}
+
+
+static __inline struct apm_span_context * build_sc_by_ipport(struct ebpf_proc_info proc_info, __u32 rip_net, __u32 raw_port) {
+	__u32 key = 0;
+	struct apm_span_context *cw_sc = bpf_map_lookup_elem(&apm_span_context_heap, &key);
+
+	if (cw_sc == NULL) {
+		return NULL;
+	}
+
+	struct apm_span_context *cw_psc = cw_get_parent_tracking_span();
+	if (cw_psc) {
+		copy_byte_arrays(cw_psc->trace_id, cw_sc->trace_id, APM_TRACE_ID_SIZE);
+	}
+	// new spanid
+	generate_random_bytes(cw_sc->span_id, APM_SPAN_ID_SIZE);
+
+	// set host_id/appid
+	__u32 k0 = 0;
+	struct trace_conf_t *trace_conf = trace_conf_map__lookup(&k0);
+	if (trace_conf) {
+//		for (int i = 0; i < 8; ++i) {
+//			cw_bpf_debug("[Client] host_id:%02x", trace_conf->host_id[i]);
+//		}
+		copy_byte_arrays(trace_conf->host_id, cw_sc->host_id, APM_HOST_ID_SIZE);
+//		copy_byte_arrays(trace_conf->app_id, cw_sc->app_id, APM_APP_ID_SIZE);
+	}
+
+	copy_byte_arrays(proc_info.instance_id, cw_sc->instance_id, APM_APP_ID_SIZE);
+	copy_byte_arrays(proc_info.app_id, cw_sc->app_id, APM_APP_ID_SIZE);
+
+	// set assumed_app_id
+	unsigned char assumed_app_id[APM_ASSUMED_APP_ID_STRING_SIZE];
+	ipport_to_16digits_from_u32_high(rip_net, raw_port, assumed_app_id);
+	hex_string_to_bytes((char *) assumed_app_id, APM_ASSUMED_APP_ID_STRING_SIZE, cw_sc->assumed_app_id);
+
+//	set_assumed_app_id_arrays(host, cw_sc->assumed_app_id, APM_ASSUMED_APP_ID_STRING_SIZE);
+	return cw_sc;
+}
+
+/* 返回语言名称的函数:例如 "Go","Java","Nodejs","Nginx", ".net" ... */
+static __always_inline const char *code_type_to_name(__u16 code_type) {
+	switch (code_type) {
+		case CodeTypeGo:                  return "Go";        // 1006
+		case CodeTypeJava:
+		case CodeTypeJavaAot:
+		case CodeTypeJavaC:               return "Java";      // 1002,1102,1010 -> Java family
+		case CodeTypeNode:                return "Nodejs";    // 1005
+		case CodeTypePHP:                 return "PHP";       // 1001
+		case CodeTypePython:              return "Python";    // 1003
+		case CodeTypeDotNet:              return ".net";      // 1004
+		case CodeTypeNetCore:
+		case CodeTypeNetCoreAot:          return ".netCore";  // 1008,1108
+		case CodeTypeC:                   return "C";         // 1007
+		case CodeTypeWaitCheck:           return "WaitCheck"; // 0
+//		case CodeTypeUnknown:             return "Unknown";   // -1
+		default:
+			return "Unknown";
+	}
+}
+
+/* 返回两位数字码的函数:例如 "00" -> Go, "01" -> Java ... */
+static __always_inline  char code_type_to_code(__u16 code_type) {
+	switch (code_type) {
+		case CodeTypeGo:                  return '0'; // Go
+		case CodeTypeJava:
+		case CodeTypeJavaAot:
+		case CodeTypeJavaC:               return '1'; // Java family
+		case CodeTypeNode:                return '2'; // Nodejs
+		case CodeTypeNginx:               return '3'; // Nginx
+		case CodeTypeDotNet:              return '4'; // .net
+		case CodeTypeNetCore:
+		case CodeTypeNetCoreAot:          return '5'; // .netCore
+		case CodeTypePHP:                 return '6'; // PHP
+		case CodeTypePython:              return '7'; // Python
+		case CodeTypeC:                   return '8'; // C
+		default:
+			return '0'; // unknown / fallback
+	}
+}

+ 53 - 63
ebpftracer/ebpf/l7/l7.c

@@ -276,8 +276,9 @@ struct {
 } apm_span_context_heap3 SEC(".maps");
 
 #define TRACE_ID_SIZE 16
-static __inline __u32 has_cw_header(const char *data);
-static __always_inline struct apm_span_context *build_sc(struct ebpf_proc_info proc_info, char *host);
+
+
+
 static __always_inline void span_context_to_cw_string_stream(struct apm_span_context *ctx, char *buff, char type_from);
 static __always_inline void cw_string_to_span_context(char *str, struct apm_span_context *ctx);
 static __always_inline void generate_random_bytes(unsigned char *buff, __u32 size);
@@ -1402,13 +1403,13 @@ int sockops_cb(struct bpf_sock_ops *skops) {
 
 	// 只处理TCP连接
 	if (skops->family != AF_INET) {
-//		return 0;
+		return 0;
 	}
 
 	// 只处理客户端主动建立的连接(出站连接)
 	// 这样stream_verdict就能看到客户端发送的HTTP请求
 	if (skops->op != BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB) {
-//		return 0;
+		return 0;
 	}
 	__u32 saddr = bpf_ntohl(skops->local_ip4);
 	__u32 daddr = bpf_ntohl(skops->remote_ip4);
@@ -1431,7 +1432,7 @@ int sockops_cb(struct bpf_sock_ops *skops) {
 	// 同时将socket添加到sockmap(用于sk_msg程序)
 	bpf_sock_map_update(skops, &sk_msg_map, &cookie, BPF_ANY);
 
-//	bpf_printk("sockops: added socket to sockhash and sockmap, cookie=%u\n", cookie);
+	bpf_printk("sockops: added socket to sockhash and sockmap, cookie=%u\n", cookie);
 
 	return 0;
 }
@@ -1495,14 +1496,6 @@ int http_request_handler(struct __sk_buff *skb) {
 	return 1; // 允许数据包通过
 }
 
-static __always_inline int load_u8(const char *data, const char *data_end, int off, char *out)
-{
-	const char *p = data + off;
-	if (p + 1 > data_end)
-		return -1;
-	*out = *(const char *)p;
-	return 0;
-}
 // sk_msg program for handling socket messages
 SEC("sk_msg")
 int sk_msg_handler(struct sk_msg_md *msg)
@@ -1517,6 +1510,14 @@ int sk_msg_handler(struct sk_msg_md *msg)
 		return SK_PASS;
 	}
 
+	// todo 进程过滤
+	__u32 tgid = (__u32) (bpf_get_current_pid_tgid() >> 32);
+	struct ebpf_proc_info *proc_info = bpf_map_lookup_elem(&proc_info_map, &tgid);
+	if (!proc_info) {
+		return SK_PASS;
+	}
+
+
 	__u32 max_buf = msg->size < MAX_L7_IOVEC_BUF_SIZE ? msg->size : MAX_L7_IOVEC_BUF_SIZE;
 
 	// 拉满整条消息查Header
@@ -1571,26 +1572,52 @@ int sk_msg_handler(struct sk_msg_md *msg)
 	}
 
 	// TODO real Header
-	const char insert[] = "AA: a\r\n";   // 要插入的 7 字节
+//	const char insert[] = "AA: a\r\n";   // 要插入的 7 字节
 //	const char insert[CW_STREAM_HEADER_LEN] = "cwtrace: 00:00:1015481350055581:5450531005555981:5610250100539899:304775019cd3218a304775019cd3218a:1001025098564810:140acc88cde8773f\r\n";
 
-	int ins_len = sizeof(insert) - 1;  // 不含 '\0'
+//	int ins_len = sizeof(insert) - 1;  // 不含 '\0'
 
-	__u32 tgid = (__u32) (bpf_get_current_pid_tgid() >> 32);
-	struct ebpf_proc_info *proc_info = bpf_map_lookup_elem(&proc_info_map, &tgid);
-	if (!proc_info) {
-		return SK_PASS;
-	}
 
-	struct apm_span_context *cw_sc = build_sc(*proc_info, "host");
+//	__u32 rip_net = msg->remote_ip4;           // network order
+//	__u32 raw_port = msg->remote_port;         // 32-bit field
+//	unsigned char assumed_app_id[16];
+//	ipport_to_8digits_from_u32_high(rip_net, raw_port, assumed_app_id);
+
+//	for (int i = 0; i < APM_ASSUMED_APP_ID_SIZE; i++) {
+//	    bpf_printk("assumed_app_id-assumed_app_id[%d] = %02x", i, assumed_app_id[i]);
+//	}
+
+	struct apm_span_context *cw_sc = build_sc_by_ipport(*proc_info, msg->remote_ip4, msg->remote_port);
 	if (cw_sc == NULL) {
 		return SK_PASS;
 	}
 
-	span_context_to_cw_string_stream(cw_sc, map_data->header_stream, '1');
+
+	span_context_to_cw_string_stream(cw_sc, map_data->header_stream, code_type_to_code(proc_info->code_type));
+//	for (int i = 0; i < APM_ASSUMED_APP_ID_SIZE; i++) {
+//		bpf_printk("cw-assumed_app_id[%d] = %02x", i, cw_sc->assumed_app_id[i]);
+//	}
+
 	bpf_printk("[java client] header:[%s],sizeof %d ", map_data->header_stream, sizeof(map_data->header_stream));
 
+	__u32 raw = msg->remote_port;
+	bpf_printk("raw_port=0x%x low_net=0x%x high_net=0x%x\n",
+	           raw, (raw & 0xffff), ((raw >> 16) & 0xffff));
+	__u16 port_host = ( __u16 )( __builtin_bswap32(msg->remote_port) & 0xffff );
+
 
+//	__u32 rip = __builtin_bswap32(msg->remote_ip4); // host order
+//	__u8 b0 = (rip >> 24) & 0xff;
+//	__u8 b1 = (rip >> 16) & 0xff;
+//	__u8 b2 = (rip >> 8) & 0xff;
+//	__u8 b3 = rip & 0xff;
+//	__u16 rport = __builtin_bswap32(msg->remote_port);
+//	bpf_printk("remote %u.%u.%u\n", b0, b1, b2);
+//	bpf_printk("remote port %u:%u\n", b3, rport);
+//	bpf_printk("remote port %u\n", rport);
+
+
+	__u32 ins_len = sizeof(map_data->header_stream) - 1;
 	__u32 header_offset = map_data->header_offset_idx;
 
 	if (header_offset > msg->size){
@@ -1629,42 +1656,14 @@ int sk_msg_handler(struct sk_msg_md *msg)
 	if (header_offset > len)
 		return SK_PASS;
 
-//	if (n > MAX_INS) n = MAX_INS;
-//	if (n > len - header_off) n = len - header_off;   // 用 len - off 规避加法溢出
-
-
-//	char *dst = data + header_off;
-
-
-//#pragma clang loop unroll(full)
-//	for (__u32 i = 0; i < MAX_INS; i++) {
-//		if (i >= n) break;
-//		data[0] = insert[0];
-//		break;
-//	}
-//	if (ins_len >= len)
-//		return SK_PASS;
-//	if (data + 0 <= data_end)
-//		data[0] = insert[0];
-//	*(char *)(data  + 0) = insert[0];
-//#pragma clang loop unroll(full)
-//	for (int i = 0; i < ins_len; i++) {
-//		if (data + header_off + i + 1 > data_end) break;
-//		*(char *)(data + header_off + i) = insert[i];
-//		bpf_printk("%d",i);
-//
-//	}
-//
-//	return SK_PASS;
-//	__u32 max_buf;
 #pragma clang loop unroll(full)
 	for (int i = 0; i < MAX_L7_IOVEC_BUF_SIZE; i++) {
 		/*test1*/
 		if (i >= header_offset) {
 			for (int j = 0; j < ins_len; j++) {
 				if (data + i + 1 > data_end) break;
-				*(char *) (data + i) = insert[j];
-				bpf_printk("set-%d %d", i, j);
+				*(char *) (data + i) = map_data->header_stream[j];
+//				bpf_printk("set-%d %d", i, j);
 				i++;
 			}
 			break;
@@ -1693,17 +1692,8 @@ int sk_msg_handler(struct sk_msg_md *msg)
 
 	}
 
-
-//	if (data + header_off + 0 + 1 <=data_end) {
-//		*(char *)(data + header_off + 0) = insert[0];
-//	}
-//	if (data + header_off + 1 + 1 <=data_end) {
-//		*(char *)(data + header_off + 1) = insert[1];
-//	}
-
-
-//		if (data1 + i + 1 > data_end) break;
-//		*(char *)(data1 + i) = insert[i];
+	// 保存span context
+	cw_save_current_tracking_span(cw_sc);
 	char vb[200] = {};
 	if (bpf_probe_read_kernel(vb, 200, (void *)data) == 0) {
 		bpf_printk("Modified HTTP request: %s\n", vb);

+ 6 - 6
ebpftracer/ebpf/utrace/java/net/server.probe.bpf.c

@@ -22,12 +22,12 @@
 //	__uint(max_entries, 1);
 //} socket_heap SEC(".maps");
 
-struct {
-	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
-	__type(key, int);
-	__type(value, struct apm_span_context);
-	__uint(max_entries, 1);
-} apm_span_context_heap SEC(".maps");
+//struct {
+//	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
+//	__type(key, int);
+//	__type(value, struct apm_span_context);
+//	__uint(max_entries, 1);
+//} apm_span_context_heap SEC(".maps");
 
  struct {
 	 __uint(type, BPF_MAP_TYPE_PROG_ARRAY);