Skip to content

Commit

Permalink
Use struct with pid and Go routine addr for Go BPF maps (#1201)
Browse files Browse the repository at this point in the history
  • Loading branch information
marctc authored Sep 30, 2024
1 parent 5006cbd commit 79d6d2b
Show file tree
Hide file tree
Showing 52 changed files with 273 additions and 248 deletions.
36 changes: 18 additions & 18 deletions bpf/go_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,62 +32,62 @@ char __license[] SEC("license") = "Dual MIT/GPL";
// Then it is retrieved in the return uprobes and used to know the HTTP call duration as well as its
// attributes (method, path, and status code).

typedef struct goroutine_key {
typedef struct go_addr_key {
u64 pid; // PID of the process
u64 addr; // Address of the goroutine
} goroutine_key_t;
} go_addr_key_t;

typedef struct goroutine_metadata_t {
goroutine_key_t parent;
go_addr_key_t parent;
u64 timestamp;
} goroutine_metadata;

struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, goroutine_key_t); // key: pointer to the goroutine
__type(key, go_addr_key_t); // key: pointer to the goroutine
__type(value, goroutine_metadata); // value: timestamp of the goroutine creation
__uint(max_entries, MAX_CONCURRENT_SHARED_REQUESTS);
__uint(pinning, LIBBPF_PIN_BY_NAME);
} ongoing_goroutines SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, goroutine_key_t); // key: pointer to the request goroutine
__type(key, go_addr_key_t); // key: pointer to the request goroutine
__type(value, connection_info_t);
__uint(max_entries, MAX_CONCURRENT_SHARED_REQUESTS);
__uint(pinning, LIBBPF_PIN_BY_NAME);
} ongoing_server_connections SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, goroutine_key_t); // key: pointer to the request goroutine
__type(key, go_addr_key_t); // key: pointer to the request goroutine
__type(value, connection_info_t);
__uint(max_entries, MAX_CONCURRENT_REQUESTS);
} ongoing_client_connections SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, goroutine_key_t); // key: pointer to the goroutine
__type(value, tp_info_t); // value: traceparent info
__type(key, go_addr_key_t); // key: pointer to the goroutine
__type(value, tp_info_t); // value: traceparent info
__uint(max_entries, MAX_CONCURRENT_SHARED_REQUESTS);
__uint(pinning, LIBBPF_PIN_BY_NAME);
} go_trace_map SEC(".maps");

static __always_inline void goroutine_key_from_id(goroutine_key_t *current, void *goroutine) {
static __always_inline void go_addr_key_from_id(go_addr_key_t *current, void *addr) {
u64 pid_tid = bpf_get_current_pid_tgid();
u32 pid = pid_from_pid_tgid(pid_tid);

current->addr = (u64)goroutine;
current->addr = (u64)addr;
current->pid = pid;
}

static __always_inline u64 find_parent_goroutine(goroutine_key_t *current) {
static __always_inline u64 find_parent_goroutine(go_addr_key_t *current) {
if (!current) {
return 0;
}

u64 r_addr = current->addr;
goroutine_key_t *parent = current;
go_addr_key_t *parent = current;

int attempts = 0;
do {
Expand Down Expand Up @@ -151,8 +151,8 @@ server_trace_parent(void *goroutine_addr, tp_info_t *tp, void *req_header) {
tp->flags = 1;
// Get traceparent from the Request.Header
void *traceparent_ptr = extract_traceparent_from_req_headers(req_header);
goroutine_key_t g_key = {};
goroutine_key_from_id(&g_key, goroutine_addr);
go_addr_key_t g_key = {};
go_addr_key_from_id(&g_key, goroutine_addr);
if (traceparent_ptr != NULL) {
unsigned char buf[TP_MAX_VAL_LENGTH];
long res = bpf_probe_read(buf, sizeof(buf), traceparent_ptr);
Expand Down Expand Up @@ -223,12 +223,12 @@ static __always_inline u8 client_trace_parent(void *goroutine_addr,

if (!found_trace_id) {
tp_info_t *tp = 0;
goroutine_key_t g_key = {};
goroutine_key_from_id(&g_key, goroutine_addr);
go_addr_key_t g_key = {};
go_addr_key_from_id(&g_key, goroutine_addr);

u64 parent_id = find_parent_goroutine(&g_key);
goroutine_key_t p_key = {};
goroutine_key_from_id(&p_key, (void *)parent_id);
go_addr_key_t p_key = {};
go_addr_key_from_id(&p_key, (void *)parent_id);

if (parent_id) { // we found a parent request
tp = (tp_info_t *)bpf_map_lookup_elem(&go_trace_map, &p_key);
Expand Down
67 changes: 35 additions & 32 deletions bpf/go_grpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ typedef struct grpc_srv_func_invocation {

struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, goroutine_key_t); // key: pointer to the request goroutine
__type(key, go_addr_key_t); // key: pointer to the request goroutine
__type(value, u16);
__uint(max_entries, MAX_CONCURRENT_REQUESTS);
} ongoing_grpc_request_status SEC(".maps");
Expand All @@ -47,6 +47,7 @@ typedef struct grpc_transports {
connection_info_t conn;
} grpc_transports_t;

// TODO: use go_addr_key_t as key
struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, void *); // key: pointer to the transport pointer
Expand All @@ -56,33 +57,35 @@ struct {

struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, goroutine_key_t); // key: goroutine
__type(value, void *); // the transport *
__type(key, go_addr_key_t); // key: goroutine
__type(value, void *); // the transport *
__uint(max_entries, MAX_CONCURRENT_REQUESTS);
} ongoing_grpc_operate_headers SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, goroutine_key_t); // key: pointer to the request goroutine
__type(key, go_addr_key_t); // key: pointer to the request goroutine
__type(value, grpc_client_func_invocation_t);
__uint(max_entries, MAX_CONCURRENT_REQUESTS);
} ongoing_grpc_client_requests SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, goroutine_key_t); // key: pointer to the request goroutine
__type(key, go_addr_key_t); // key: pointer to the request goroutine
__type(value, grpc_srv_func_invocation_t);
__uint(max_entries, MAX_CONCURRENT_REQUESTS);
} ongoing_grpc_server_requests SEC(".maps");

// Context propagation
// TODO: use go_addr_key_t as key
struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, u32); // key: stream id
__type(value, grpc_client_func_invocation_t); // stored info for the client request
__uint(max_entries, MAX_CONCURRENT_REQUESTS);
} ongoing_streams SEC(".maps");

// TODO: use go_addr_key_t as key
struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, void *); // key: pointer to the request goroutine
Expand All @@ -101,8 +104,8 @@ int uprobe_server_handleStream(struct pt_regs *ctx) {
bpf_dbg_printk("=== uprobe/server_handleStream === ");
void *goroutine_addr = GOROUTINE_PTR(ctx);
bpf_dbg_printk("goroutine_addr %lx", goroutine_addr);
goroutine_key_t g_key = {};
goroutine_key_from_id(&g_key, goroutine_addr);
go_addr_key_t g_key = {};
go_addr_key_from_id(&g_key, goroutine_addr);

void *stream_ptr = GO_PARAM4(ctx);
off_table_t *ot = get_offsets_table();
Expand Down Expand Up @@ -143,8 +146,8 @@ SEC("uprobe/netFdReadGRPC")
int uprobe_netFdReadGRPC(struct pt_regs *ctx) {
void *goroutine_addr = GOROUTINE_PTR(ctx);
bpf_dbg_printk("=== uprobe/proc netFD read goroutine %lx === ", goroutine_addr);
goroutine_key_t g_key = {};
goroutine_key_from_id(&g_key, goroutine_addr);
go_addr_key_t g_key = {};
go_addr_key_from_id(&g_key, goroutine_addr);

void *tr = bpf_map_lookup_elem(&ongoing_grpc_operate_headers, &g_key);
bpf_dbg_printk("tr %llx", tr);
Expand All @@ -167,8 +170,8 @@ int uprobe_http2Server_operateHeaders(struct pt_regs *ctx) {
void *tr = GO_PARAM1(ctx);
bpf_dbg_printk(
"=== uprobe/http2Server_operateHeaders tr %llx goroutine %lx === ", tr, goroutine_addr);
goroutine_key_t g_key = {};
goroutine_key_from_id(&g_key, goroutine_addr);
go_addr_key_t g_key = {};
go_addr_key_from_id(&g_key, goroutine_addr);

grpc_transports_t t = {
.type = TRANSPORT_HTTP2,
Expand All @@ -190,14 +193,14 @@ int uprobe_server_handler_transport_handle_streams(struct pt_regs *ctx) {
tr,
goroutine_addr);

goroutine_key_t g_key = {};
goroutine_key_from_id(&g_key, goroutine_addr);
go_addr_key_t g_key = {};
go_addr_key_from_id(&g_key, goroutine_addr);

void *parent_go = (void *)find_parent_goroutine(&g_key);
if (parent_go) {
bpf_dbg_printk("found parent goroutine for transport handler [%llx]", parent_go);
goroutine_key_t p_key = {};
goroutine_key_from_id(&p_key, parent_go);
go_addr_key_t p_key = {};
go_addr_key_from_id(&p_key, parent_go);
connection_info_t *conn = bpf_map_lookup_elem(&ongoing_server_connections, &p_key);
bpf_dbg_printk("conn %llx", conn);
if (conn) {
Expand All @@ -221,8 +224,8 @@ int uprobe_server_handleStream_return(struct pt_regs *ctx) {
off_table_t *ot = get_offsets_table();

bpf_dbg_printk("goroutine_addr %lx", goroutine_addr);
goroutine_key_t g_key = {};
goroutine_key_from_id(&g_key, goroutine_addr);
go_addr_key_t g_key = {};
go_addr_key_from_id(&g_key, goroutine_addr);

grpc_srv_func_invocation_t *invocation =
bpf_map_lookup_elem(&ongoing_grpc_server_requests, &g_key);
Expand Down Expand Up @@ -323,8 +326,8 @@ int uprobe_transport_writeStatus(struct pt_regs *ctx) {
off_table_t *ot = get_offsets_table();

bpf_dbg_printk("goroutine_addr %lx", goroutine_addr);
goroutine_key_t g_key = {};
goroutine_key_from_id(&g_key, goroutine_addr);
go_addr_key_t g_key = {};
go_addr_key_from_id(&g_key, goroutine_addr);

void *status_ptr = GO_PARAM3(ctx);
bpf_dbg_printk("status_ptr %lx", status_ptr);
Expand Down Expand Up @@ -364,8 +367,8 @@ static __always_inline void clientConnStart(
.flags = 0,
};
off_table_t *ot = get_offsets_table();
goroutine_key_t g_key = {};
goroutine_key_from_id(&g_key, goroutine_addr);
go_addr_key_t g_key = {};
go_addr_key_from_id(&g_key, goroutine_addr);

if (ctx_ptr) {
void *val_ptr = 0;
Expand Down Expand Up @@ -426,8 +429,8 @@ int uprobe_ClientConn_NewStream(struct pt_regs *ctx) {
static __always_inline int grpc_connect_done(struct pt_regs *ctx, void *err) {
void *goroutine_addr = GOROUTINE_PTR(ctx);
bpf_dbg_printk("goroutine_addr %lx", goroutine_addr);
goroutine_key_t g_key = {};
goroutine_key_from_id(&g_key, goroutine_addr);
go_addr_key_t g_key = {};
go_addr_key_from_id(&g_key, goroutine_addr);

grpc_client_func_invocation_t *invocation =
bpf_map_lookup_elem(&ongoing_grpc_client_requests, &g_key);
Expand Down Expand Up @@ -509,8 +512,8 @@ int uprobe_ClientConn_Close(struct pt_regs *ctx) {

void *goroutine_addr = GOROUTINE_PTR(ctx);
bpf_dbg_printk("goroutine_addr %lx", goroutine_addr);
goroutine_key_t g_key = {};
goroutine_key_from_id(&g_key, goroutine_addr);
go_addr_key_t g_key = {};
go_addr_key_from_id(&g_key, goroutine_addr);

bpf_map_delete_elem(&ongoing_grpc_client_requests, &g_key);

Expand Down Expand Up @@ -547,8 +550,8 @@ int uprobe_transport_http2Client_NewStream(struct pt_regs *ctx) {
void *goroutine_addr = GOROUTINE_PTR(ctx);
void *t_ptr = GO_PARAM1(ctx);
off_table_t *ot = get_offsets_table();
goroutine_key_t g_key = {};
goroutine_key_from_id(&g_key, goroutine_addr);
go_addr_key_t g_key = {};
go_addr_key_from_id(&g_key, goroutine_addr);

u64 grpc_t_conn_pos = go_offset_of(ot, (go_offset){.v = _grpc_t_scheme_pos});
bpf_dbg_printk(
Expand Down Expand Up @@ -627,7 +630,7 @@ typedef struct grpc_framer_func_invocation {

struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, goroutine_key_t); // key: go routine doing framer write headers
__type(key, go_addr_key_t); // key: go routine doing framer write headers
__type(
value,
grpc_framer_func_invocation_t); // the goroutine of the round trip request, which is the key for our traceparent info
Expand Down Expand Up @@ -660,8 +663,8 @@ int uprobe_grpcFramerWriteHeaders(struct pt_regs *ctx) {
if (invocation) {
bpf_dbg_printk("Found invocation info %llx", invocation);
void *goroutine_addr = GOROUTINE_PTR(ctx);
goroutine_key_t g_key = {};
goroutine_key_from_id(&g_key, goroutine_addr);
go_addr_key_t g_key = {};
go_addr_key_from_id(&g_key, goroutine_addr);

void *w_ptr = (void *)(framer + framer_w_pos + 16);
bpf_probe_read(&w_ptr, sizeof(w_ptr), (void *)(framer + framer_w_pos + 8));
Expand Down Expand Up @@ -713,8 +716,8 @@ int uprobe_grpcFramerWriteHeaders_returns(struct pt_regs *ctx) {

void *goroutine_addr = GOROUTINE_PTR(ctx);
off_table_t *ot = get_offsets_table();
goroutine_key_t g_key = {};
goroutine_key_from_id(&g_key, goroutine_addr);
go_addr_key_t g_key = {};
go_addr_key_from_id(&g_key, goroutine_addr);

grpc_framer_func_invocation_t *f_info =
bpf_map_lookup_elem(&grpc_framer_invocation_map, &g_key);
Expand Down
Loading

0 comments on commit 79d6d2b

Please sign in to comment.