server.probe.bpf.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. // Copyright The OpenTelemetry Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "arguments.h"
  15. #include "span_context.h"
  16. #include "go_context.h"
  17. #include "go_types.h"
  18. #include "uprobe.h"
  19. //char __license[] SEC("license") = "Dual MIT/GPL";
  20. #define PATH_MAX_LEN 128
  21. #define MAX_BUCKETS 8
  22. #define METHOD_MAX_LEN 8
  23. #define MAX_CONCURRENT 50
  24. #define REMOTE_ADDR_MAX_LEN 256
  25. #define HOST_MAX_LEN 256
  26. #define PROTO_MAX_LEN 8
  27. struct http_server_span_t {
  28. BASE_SPAN_PROPERTIES
  29. u64 status_code;
  30. char method[METHOD_MAX_LEN];
  31. char path[PATH_MAX_LEN];
  32. char remote_addr[REMOTE_ADDR_MAX_LEN];
  33. char host[HOST_MAX_LEN];
  34. char proto[PROTO_MAX_LEN];
  35. };
  36. struct uprobe_data_t {
  37. struct http_server_span_t span;
  38. // bpf2go doesn't support pointers fields
  39. // saving the response pointer in the entry probe
  40. // and using it in the return probe
  41. u64 resp_ptr;
  42. };
  43. struct {
  44. __uint(type, BPF_MAP_TYPE_HASH);
  45. __type(key, void *);
  46. __type(value, struct uprobe_data_t);
  47. __uint(max_entries, MAX_CONCURRENT);
  48. } http_server_uprobes SEC(".maps");
  49. struct {
  50. __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
  51. __uint(key_size, sizeof(u32));
  52. __uint(value_size, sizeof(struct map_bucket));
  53. __uint(max_entries, MAX_CONCURRENT);
  54. } golang_mapbucket_storage_map SEC(".maps");
  55. struct {
  56. __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
  57. __uint(key_size, sizeof(u32));
  58. __uint(value_size, sizeof(struct cw_header_token));
  59. __uint(max_entries, MAX_CONCURRENT);
  60. } header_range SEC(".maps");
  61. //struct {
  62. // __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
  63. // __uint(key_size, sizeof(u32));
  64. // __uint(value_size, sizeof(struct span_context));
  65. // __uint(max_entries, 1);
  66. //} parent_span_context_storage_map SEC(".maps");
  67. //struct {
  68. // __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
  69. // __uint(key_size, sizeof(u32));
  70. // __uint(value_size, sizeof(struct apm_span_context));
  71. // __uint(max_entries, 1);
  72. //} cw_parent_span_context_storage_map SEC(".maps");
  73. struct {
  74. __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
  75. __uint(key_size, sizeof(u32));
  76. __uint(value_size, sizeof(struct uprobe_data_t));
  77. __uint(max_entries, 1);
  78. } http_server_uprobe_storage_map SEC(".maps");
  79. struct {
  80. __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
  81. } events SEC(".maps");
  82. struct header_key {
  83. char str[CW_HEADER_KEY_LENGTH];
  84. };
  85. struct {
  86. __uint(type, BPF_MAP_TYPE_HASH);
  87. __uint(key_size, sizeof(u32));
  88. __uint(value_size, sizeof(struct header_key));
  89. __uint(max_entries, 8);
  90. } header_keys_map SEC(".maps");
  91. struct {
  92. __uint(type, BPF_MAP_TYPE_LRU_HASH);
  93. __uint(key_size, sizeof(u64));
  94. __uint(value_size, sizeof(char [CW_HEADER_VAL_LENGTH]));
  95. __uint(max_entries, MAX_CONCURRENT);
  96. } http_server_context_headers SEC(".maps");
  97. struct {
  98. __uint(type, BPF_MAP_TYPE_LRU_HASH);
  99. __uint(key_size, sizeof(u64));
  100. __uint(value_size, sizeof(char [CW_SYS_HEADER_VAL_LENGTH]));
  101. __uint(max_entries, MAX_CONCURRENT);
  102. } http_server_context_sys_headers SEC(".maps");
  103. // Injected in init
  104. // volatile const u64 ctx_ptr_pos;
  105. // volatile const u64 headers_ptr_pos;
  106. // volatile const u64 buckets_ptr_pos;
  107. //for (int i = 0; i < W3C_KEY_LENGTH; i++)
  108. //{
  109. //if (current_header_key[i] != "traceparent"[i]){
  110. //goto outer_loop;
  111. //}
  112. //if (current_header_key[i] != "Traceparent"[i]){
  113. //goto outer_loop;
  114. //}
  115. //}
  116. MAP_BUCKET_DEFINITION(go_string_ot, go_slice_ot)
  117. static __always_inline char *
  118. extract_context_from_req_headers_pre_parsed(void *key) {
  119. char *header_val =
  120. bpf_map_lookup_elem(&http_server_context_headers, &key);
  121. if (!header_val) {
  122. return NULL;
  123. }
  124. return header_val;
  125. }
  126. static __always_inline char *
  127. extract_context_from_req_headers(void *key, void *headers_ptr_ptr, __u64 use_swiss) {
  128. // if (use_swiss == 1) {
  129. return extract_context_from_req_headers_pre_parsed(key);
  130. // }
  131. // return extract_context_from_req_headers_go_map(headers_ptr_ptr);
  132. }
  133. // This instrumentation attaches uprobe to the following function:
  134. // func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request)
  135. SEC("uprobe/HandlerFunc_ServeHTTP")
  136. int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) {
  137. cw_bpf_debug("[uprobe_HandlerFunc_ServeHTTP]");
  138. __u64 pid_tgid = bpf_get_current_pid_tgid();
  139. __u32 tgid = pid_tgid >> 32;
  140. struct ebpf_proc_info *proc_info =
  141. bpf_map_lookup_elem(&proc_info_map, &tgid);
  142. if(!proc_info)
  143. {
  144. cw_bpf_debug("[uprobe_HandlerFunc_ServeHTTP] no proc info");
  145. return 0;
  146. }
  147. void *req_ctx_ptr = get_Go_context(ctx, 4, proc_info->ctx_ptr_pos, false);
  148. void *key = get_consistent_key(ctx, req_ctx_ptr);
  149. void *httpReq_ptr = bpf_map_lookup_elem(&http_server_uprobes, &key);
  150. if (httpReq_ptr != NULL) {
  151. cw_bpf_debug("uprobe/HandlerFunc_ServeHTTP already tracked with the current request");
  152. return 0;
  153. }
  154. u32 map_id = 0;
  155. struct uprobe_data_t *uprobe_data = bpf_map_lookup_elem(&http_server_uprobe_storage_map, &map_id);
  156. if (uprobe_data == NULL) {
  157. cw_bpf_debug("uprobe/HandlerFunc_ServeHTTP: http_server_span is NULL");
  158. return 0;
  159. }
  160. __builtin_memset(uprobe_data, 0, sizeof(struct uprobe_data_t));
  161. // Save response writer
  162. void *resp_impl = get_argument(ctx, 3);
  163. uprobe_data->resp_ptr = (u64) resp_impl;
  164. struct http_server_span_t *http_server_span = &uprobe_data->span;
  165. http_server_span->start_time = bpf_ktime_get_ns();
  166. // return 1;
  167. // Propagate context
  168. void *req_ptr = get_argument(ctx, 4);
  169. // struct map_bucket * map_bucket_p = get_map_bucket((void *) (req_ptr + proc_info->headers_ptr_pos));
  170. char *traceparent_header_value = extract_context_from_req_headers(key,
  171. (void *) (req_ptr + proc_info->headers_ptr_pos),
  172. proc_info->use_swiss_map);
  173. // bpf_printk("111 %s",traceparent_header_value);
  174. // char * traceparent_header_value = get_header_val_off(map_bucket_p);
  175. struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&cw_parent_span_context_storage_map, &map_id);
  176. if (!cw_parent_span_context) {
  177. return 0;
  178. }
  179. __builtin_memset(cw_parent_span_context, 0, sizeof(struct apm_span_context));
  180. // parentSys parentService
  181. char *header_sys_val = bpf_map_lookup_elem(&http_server_context_sys_headers, &key);
  182. if (header_sys_val) {
  183. bpf_printk("has sys");
  184. bpf_probe_read(&cw_parent_span_context->sysvs, sizeof(cw_parent_span_context->sysvs), header_sys_val);
  185. bpf_printk("has sys %s", cw_parent_span_context->sysvs);
  186. }
  187. if (traceparent_header_value != NULL) {
  188. cw_bpf_debug("traceparent_header_value != NULL");
  189. cw_string_to_span_context(traceparent_header_value, cw_parent_span_context);
  190. // found parent context in http headers
  191. // http_server_span->psc = *parent_ctx;
  192. // copy traceID
  193. copy_byte_arrays(http_server_span->psc.TraceID, http_server_span->sc.TraceID, TRACE_ID_SIZE);
  194. // 生成随机SpanID
  195. generate_random_bytes(http_server_span->sc.SpanID, SPAN_ID_SIZE);
  196. cw_save_parent_tracking_span(cw_parent_span_context);
  197. } else {
  198. cw_bpf_debug("traceparent_header_value == NULL");
  199. http_server_span->sc = generate_span_context();
  200. struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&cw_parent_span_context_storage_map, &map_id);
  201. if (!cw_parent_span_context) {
  202. return 0;
  203. }
  204. // struct apm_span_context context = {};
  205. generate_random_bytes(cw_parent_span_context->trace_id, TRACE_ID_SIZE);
  206. // generate_random_bytes(context.span_id, SPAN_ID_SIZE);
  207. // 保存 trace_id 到psc
  208. cw_save_parent_tracking_span(cw_parent_span_context);
  209. }
  210. if (req_ctx_ptr == NULL) {
  211. // cw_bpf_debug("uprobe/HandlerFunc_ServeHTTP: req_ctx_ptr is NULL");
  212. return 0;
  213. }
  214. // cw_bpf_debug("found parent context in http headers");
  215. // cw_bpf_debug("parent_span_context-TraceID---");
  216. // for (int i = 0; i < TRACE_ID_SIZE; i++) {
  217. // cw_bpf_debug("%02x", uprobe_data->span.sc.TraceID[i]);
  218. // }
  219. // cw_bpf_debug("parent_span_context-SpanID---");
  220. // for (int i = 0; i < SPAN_ID_SIZE; i++) {
  221. // cw_bpf_debug("%02x", uprobe_data->span.sc.SpanID[i]);
  222. // }
  223. // bpf_map_update_elem(&http_server_uprobes, &key, uprobe_data, 0);
  224. // start_tracking_span(req_ctx_ptr, &http_server_span->sc);
  225. // void save_tracking_span(struct apm_span_context *sc)
  226. return 0;
  227. }
  228. // This instrumentation attaches uprobe to the following function:
  229. // func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request)
  230. SEC("uprobe/HandlerFunc_ServeHTTP")
  231. int uprobe_HandlerFunc_ServeHTTP_Returns(struct pt_regs *ctx) {
  232. // return 1;
  233. cw_bpf_debug("[uprobe_HandlerFunc_ServeHTTP_Returns]");
  234. // u64 end_time = bpf_ktime_get_ns();
  235. __u64 pid_tgid = bpf_get_current_pid_tgid();
  236. __u32 tgid = pid_tgid >> 32;
  237. struct ebpf_proc_info *proc_info =
  238. bpf_map_lookup_elem(&proc_info_map, &tgid);
  239. if(!proc_info)
  240. {
  241. return 0;
  242. }
  243. void *req_ctx_ptr = get_Go_context(ctx, 4, proc_info->ctx_ptr_pos, false);
  244. void *key = get_consistent_key(ctx, req_ctx_ptr);
  245. struct uprobe_data_t *uprobe_data = bpf_map_lookup_elem(&http_server_uprobes, &key);
  246. if (uprobe_data == NULL) {
  247. cw_bpf_debug("uprobe/HandlerFunc_ServeHTTP_Returns: entry_state is NULL");
  248. bpf_map_delete_elem(&http_server_context_headers, &key);
  249. bpf_map_delete_elem(&http_server_context_sys_headers, &key);
  250. return 0;
  251. }
  252. bpf_map_delete_elem(&http_server_uprobes, &key);
  253. bpf_map_delete_elem(&http_server_context_headers, &key);
  254. bpf_map_delete_elem(&http_server_context_sys_headers, &key);
  255. struct http_server_span_t *http_server_span = &uprobe_data->span;
  256. // void *resp_ptr = (void *) uprobe_data->resp_ptr;
  257. // void *req_ptr = NULL;
  258. // bpf_probe_read(&req_ptr, sizeof(req_ptr), (void *) (resp_ptr + req_ptr_pos));
  259. // http_server_span->end_time = end_time;
  260. //
  261. // void *url_ptr = 0;
  262. // bpf_probe_read(&url_ptr, sizeof(url_ptr), (void *) (req_ptr + url_ptr_pos));
  263. // // Collect fields from response
  264. // read_go_string(req_ptr, method_ptr_pos, http_server_span->method, sizeof(http_server_span->method),
  265. // "method from request");
  266. // read_go_string(url_ptr, path_ptr_pos, http_server_span->path, sizeof(http_server_span->path),
  267. // "path from Request.URL");
  268. // read_go_string(req_ptr, remote_addr_pos, http_server_span->remote_addr, sizeof(http_server_span->remote_addr),
  269. // "remote addr from Request.RemoteAddr");
  270. // read_go_string(req_ptr, host_pos, http_server_span->host, sizeof(http_server_span->host), "host from Request.Host");
  271. // read_go_string(req_ptr, proto_pos, http_server_span->proto, sizeof(http_server_span->proto),
  272. // "proto from Request.Proto");
  273. //
  274. // // status code
  275. // bpf_probe_read(&http_server_span->status_code, sizeof(http_server_span->status_code),
  276. // (void *) (resp_ptr + status_code_pos));
  277. //
  278. // bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, http_server_span, sizeof(*http_server_span));
  279. stop_tracking_span(&http_server_span->sc, &http_server_span->psc);
  280. clear_parent_span_context();
  281. cw_bpf_debug("HTTP_END");
  282. return 0;
  283. }
  284. // This instrumentation attaches uprobe to the following function:
  285. // func (r *Reader) readContinuedLineSlice(lim int64, validateFirstLine func([]byte) error) ([]byte, error) {
  286. SEC("uprobe/textproto_Reader_readContinuedLineSlice")
  287. int uprobe_textproto_Reader_readContinuedLineSlice_Returns(struct pt_regs *ctx) {
  288. void *key = (void *) GOROUTINE(ctx);
  289. u64 len = (u64) GO_PARAM2(ctx);
  290. u8 *buf = (u8 *) GO_PARAM1(ctx);
  291. if (len == (CW_HEADER_KEY_LENGTH + CW_HEADER_VAL_LENGTH + 2)) {
  292. long cw_header_native = 0x3A65636172747763LL; // 小端序下的 "cwtrace:"
  293. __u64 key64 = 0;
  294. bpf_probe_read_user(&key64, sizeof(key64), buf);
  295. if (key64 == cw_header_native) {
  296. char header_val[CW_HEADER_VAL_LENGTH] = {};
  297. bpf_probe_read_user(header_val, sizeof(header_val), buf + CW_HEADER_KEY_LENGTH + 2);
  298. cw_bpf_debug("Swiss Map:%s", header_val);
  299. bpf_map_update_elem(&http_server_context_headers, &key, &header_val, BPF_ANY);
  300. }
  301. }
  302. // cwother: 08:service:03:tag
  303. // 解析 cwother header (变长,需要检查是否匹配)
  304. if (len >= (CW_SYS_HEADER_KEY_LENGTH + 2 + 8)) { // 至少 "cwother: NN:name:MM " 的长度
  305. long cw_sys_header_native = 0x3A726568746F7763LL; // 小端序下的 "cwother:"
  306. __u64 key64 = 0;
  307. bpf_probe_read_user(&key64, sizeof(key64), buf);
  308. if (key64 == cw_sys_header_native) {
  309. char header_val[CW_SYS_HEADER_VAL_LENGTH] = {};
  310. bpf_probe_read_user(header_val, sizeof(header_val), buf + CW_SYS_HEADER_KEY_LENGTH + 2);
  311. cw_bpf_debug("Swiss Map:%s key %llu", header_val,key);
  312. bpf_map_update_elem(&http_server_context_sys_headers, &key, &header_val, BPF_ANY);
  313. }
  314. }
  315. return 0;
  316. }