Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix missing gRPC/HTTP2 events #867

Merged
merged 14 commits into from
May 27, 2024
Merged
10 changes: 10 additions & 0 deletions bpf/http_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,16 @@ int BPF_KPROBE(kprobe_tcp_close, struct sock *sk, long timeout) {

ensure_sent_event(id, &sock_p);


pid_connection_info_t info = {};

if (parse_sock_info(sk, &info.conn)) {
sort_connection_info(&info.conn);
//dbg_print_http_connection_info(&info.conn);
info.pid = pid_from_pid_tgid(id);
bpf_map_delete_elem(&ongoing_tcp_req, &info);
}

bpf_map_delete_elem(&active_send_args, &id);
bpf_map_delete_elem(&active_send_sock_args, &sock_p);

Expand Down
19 changes: 15 additions & 4 deletions bpf/http_sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ static __always_inline void handle_http_response(unsigned char *small_buf, pid_c
}
}

static __always_inline void http2_grpc_start(http2_conn_stream_t *s_key, void *u_buf, int len, u8 direction) {
static __always_inline void http2_grpc_start(http2_conn_stream_t *s_key, void *u_buf, int len, u8 direction, u8 ssl) {
http2_grpc_request_t *h2g_info = empty_http2_info();
if (h2g_info) {
http_connection_metadata_t *meta = connection_meta(&s_key->pid_conn, direction, PACKET_TYPE_REQUEST);
Expand All @@ -396,6 +396,7 @@ static __always_inline void http2_grpc_start(http2_conn_stream_t *s_key, void *u
h2g_info->flags = EVENT_K_HTTP2_REQUEST;
h2g_info->start_monotime_ns = bpf_ktime_get_ns();
h2g_info->len = len;
h2g_info->ssl = ssl;
h2g_info->conn_info = s_key->pid_conn.conn;
if (meta) { // keep verifier happy
h2g_info->pid = meta->pid;
Expand Down Expand Up @@ -423,7 +424,7 @@ static __always_inline void http2_grpc_end(http2_conn_stream_t *stream, http2_gr
bpf_map_delete_elem(&ongoing_http2_grpc, stream);
}

static __always_inline void process_http2_grpc_frames(pid_connection_info_t *pid_conn, void *u_buf, int bytes_len, u8 direction) {
static __always_inline void process_http2_grpc_frames(pid_connection_info_t *pid_conn, void *u_buf, int bytes_len, u8 direction, u8 ssl) {
int pos = 0;
u8 found_start_frame = 0;
u8 found_end_frame = 0;
Expand Down Expand Up @@ -488,7 +489,7 @@ static __always_inline void process_http2_grpc_frames(pid_connection_info_t *pid
}

if (found_start_frame) {
http2_grpc_start(&stream, (void *)((u8 *)u_buf + pos), bytes_len, direction);
http2_grpc_start(&stream, (void *)((u8 *)u_buf + pos), bytes_len, direction, ssl);
} else {
// We only loop 6 times looking for the stream termination. If the data packed is large we'll miss the
// frame saying the stream closed. In that case we try this backup path.
Expand Down Expand Up @@ -550,6 +551,16 @@ static __always_inline void handle_unknown_tcp_connection(pid_connection_info_t
bpf_ringbuf_submit(trace, get_flags());
}
bpf_map_delete_elem(&ongoing_tcp_req, pid_conn);
} else if (existing->len > 0 && existing->len < (K_TCP_MAX_LEN/2)) {
// Attempt to append one more packet. I couldn't convince the verifier
// to use a variable (K_TCP_MAX_LEN-existing->len). If needed we may need
// to try harder. Mainly needed for userspace detection of missed gRPC, where
// the protocol may sent a RST frame after we've done creating the event, so
// the next event has an RST frame prepended.
u32 off = existing->len;
bpf_clamp_umax(off, (K_TCP_MAX_LEN/2));
bpf_probe_read(existing->buf + off, (K_TCP_MAX_LEN/2), u_buf);
existing->len += bytes_len;
}
}

Expand Down Expand Up @@ -628,7 +639,7 @@ static __always_inline void handle_buf_with_connection(pid_connection_info_t *pi
} else {
u8 *h2g = bpf_map_lookup_elem(&ongoing_http2_connections, pid_conn);
if (h2g && *h2g == ssl) {
process_http2_grpc_frames(pid_conn, u_buf, bytes_len, direction);
process_http2_grpc_frames(pid_conn, u_buf, bytes_len, direction, ssl);
} else { // large request tracking
http_info_t *info = bpf_map_lookup_elem(&ongoing_http, pid_conn);

Expand Down
1 change: 1 addition & 0 deletions bpf/http_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ typedef struct http2_grpc_request {
// also to filter traces from unsolicited processes that share the executable
// with other instrumented processes
pid_info pid;
u8 ssl;
tp_info_t tp;
} http2_grpc_request_t;

Expand Down
Loading
Loading