Skip to content

Commit 3fa1477

Browse files
committed
try tail calling
1 parent e39b906 commit 3fa1477

File tree

5 files changed

+123
-52
lines changed

5 files changed

+123
-52
lines changed

bpf/common/http_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ typedef struct call_protocol_args {
5757
u16 orig_dport;
5858
u16 _pad2;
5959
u64 u_buf;
60+
u64 self_ref_parent_id;
6061
} call_protocol_args_t;
6162

6263
// Here we keep information on the packets passing through the socket filter

bpf/common/trace_common.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ static __always_inline unsigned char *bpf_strstr_tp_loop__legacy(unsigned char *
9797
}
9898

9999
const u16 k_besteffort_max_loops = 400; // Limited best-effort search to stay within insns limit
100-
for (u16 i = 0; i + TRACE_PARENT_HEADER_LEN < k_besteffort_max_loops; i++) {
100+
101+
for (u16 i = 0; i < k_besteffort_max_loops; i++) {
101102
if (is_traceparent(&buf[i])) {
102103
return &buf[i];
103104
}

bpf/generictracer/k_tracer_tailcall.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,17 @@ struct bpf_map_def SEC("maps") jump_table = {
1010
.type = BPF_MAP_TYPE_PROG_ARRAY,
1111
.key_size = sizeof(__u32),
1212
.value_size = sizeof(__u32),
13-
.max_entries = 8,
13+
.max_entries = 16,
1414
};
1515

1616
enum {
1717
k_tail_protocol_http = 0,
18-
k_tail_protocol_http2 = 1,
19-
k_tail_protocol_tcp = 2,
20-
k_tail_protocol_http2_grpc_frames = 3,
21-
k_tail_protocol_http2_grpc_handle_start_frame = 4,
22-
k_tail_protocol_http2_grpc_handle_end_frame = 5,
23-
k_tail_handle_buf_with_args = 6,
18+
k_tail_continue_protocol_http = 1,
19+
k_tail_continue2_protocol_http = 2,
20+
k_tail_protocol_http2 = 3,
21+
k_tail_protocol_tcp = 4,
22+
k_tail_protocol_http2_grpc_frames = 5,
23+
k_tail_protocol_http2_grpc_handle_start_frame = 6,
24+
k_tail_protocol_http2_grpc_handle_end_frame = 7,
25+
k_tail_handle_buf_with_args = 8,
2426
};

bpf/generictracer/protocol_http.h

Lines changed: 103 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <common/trace_common.h>
1414

1515
#include <generictracer/maps/http_info_mem.h>
16+
17+
#include <generictracer/k_tracer_tailcall.h>
1618
#include <generictracer/protocol_common.h>
1719

1820
#include <maps/accepted_connections.h>
@@ -403,7 +405,100 @@ static __always_inline void handle_http_response(unsigned char *small_buf,
403405
cleanup_http_request_data(pid_conn, info);
404406
}
405407

406-
static __always_inline int __obi_protocol_http(unsigned char *(*tp_loop_fn)(unsigned char *, int)) {
408+
static __always_inline int __obi_continue2_protocol_http(void *ctx,
409+
call_protocol_args_t *args,
410+
http_info_t *info,
411+
http_connection_metadata_t *meta) {
412+
(void)ctx;
413+
414+
if (meta) {
415+
u32 type = trace_type_from_meta(meta);
416+
tp_info_pid_t *tp_p = trace_info_for_connection(&args->pid_conn.conn, type);
417+
if (tp_p) {
418+
info->tp = tp_p->tp;
419+
if (args->self_ref_parent_id) {
420+
bpf_dbg_printk("overwriting parent id from the self referencing client request");
421+
__builtin_memcpy(&info->tp.parent_id, &args->self_ref_parent_id, sizeof(u64));
422+
}
423+
} else {
424+
bpf_dbg_printk("Can't find trace info, this is a bug!");
425+
}
426+
} else {
427+
bpf_dbg_printk("No META!");
428+
}
429+
430+
// we copy some small part of the buffer to the info trace event, so that we can process an event even with
431+
// incomplete trace info in user space.
432+
bpf_probe_read(info->buf, FULL_BUF_SIZE, (void *)args->u_buf);
433+
process_http_request(info, args->bytes_len, meta, args->direction, args->orig_dport);
434+
435+
return 0;
436+
}
437+
438+
// k_tail_continue2_protocol_http
439+
SEC("kprobe/http")
440+
int obi_continue2_protocol_http(void *ctx) {
441+
call_protocol_args_t *args = protocol_args();
442+
if (!args) {
443+
return 0;
444+
}
445+
446+
http_info_t *info = bpf_map_lookup_elem(&ongoing_http, &args->pid_conn);
447+
if (!info) {
448+
return 0;
449+
}
450+
451+
http_connection_metadata_t *meta =
452+
connection_meta_by_direction(args->direction, PACKET_TYPE_REQUEST);
453+
454+
return __obi_continue2_protocol_http(ctx, args, info, meta);
455+
}
456+
457+
static __always_inline int
458+
__obi_continue_protocol_http(void *ctx,
459+
call_protocol_args_t *args,
460+
http_info_t *info,
461+
unsigned char *(*tp_loop_fn)(unsigned char *, int)) {
462+
http_connection_metadata_t *meta =
463+
connection_meta_by_direction(args->direction, PACKET_TYPE_REQUEST);
464+
465+
http_get_or_create_trace_info(meta,
466+
args->pid_conn.pid,
467+
&args->pid_conn.conn,
468+
(void *)args->u_buf,
469+
args->bytes_len,
470+
capture_header_buffer,
471+
args->ssl,
472+
args->orig_dport,
473+
tp_loop_fn);
474+
475+
if (tp_loop_fn == bpf_strstr_tp_loop__legacy) {
476+
bpf_tail_call(ctx, &jump_table, k_tail_continue2_protocol_http);
477+
} else {
478+
return __obi_continue2_protocol_http(ctx, args, info, meta);
479+
}
480+
481+
return 0;
482+
}
483+
484+
// k_tail_continue_protocol_http
485+
SEC("kprobe/http")
486+
int obi_continue_protocol_http(void *ctx) {
487+
call_protocol_args_t *args = protocol_args();
488+
if (!args) {
489+
return 0;
490+
}
491+
492+
http_info_t *info = bpf_map_lookup_elem(&ongoing_http, &args->pid_conn);
493+
if (!info) {
494+
return 0;
495+
}
496+
497+
return __obi_continue_protocol_http(ctx, args, info, bpf_strstr_tp_loop__legacy);
498+
}
499+
500+
static __always_inline int __obi_protocol_http(void *ctx,
501+
unsigned char *(*tp_loop_fn)(unsigned char *, int)) {
407502
call_protocol_args_t *args = protocol_args();
408503
if (!args) {
409504
return 0;
@@ -428,7 +523,7 @@ static __always_inline int __obi_protocol_http(unsigned char *(*tp_loop_fn)(unsi
428523
u64 self_ref_parent_id = 0;
429524
tp_info_t *self_ref_tp = self_referencing_request(&args->pid_conn, args->packet_type);
430525
if (self_ref_tp) {
431-
__builtin_memcpy(&self_ref_parent_id, &self_ref_tp->parent_id, sizeof(u64));
526+
__builtin_memcpy(&args->self_ref_parent_id, &self_ref_tp->parent_id, sizeof(u64));
432527
}
433528

434529
http_info_t *info =
@@ -446,40 +541,12 @@ static __always_inline int __obi_protocol_http(unsigned char *(*tp_loop_fn)(unsi
446541

447542
if (args->packet_type == PACKET_TYPE_REQUEST && (info->status == 0) &&
448543
(info->start_monotime_ns == 0)) {
449-
http_connection_metadata_t *meta =
450-
connection_meta_by_direction(args->direction, PACKET_TYPE_REQUEST);
451-
452-
http_get_or_create_trace_info(meta,
453-
args->pid_conn.pid,
454-
&args->pid_conn.conn,
455-
(void *)args->u_buf,
456-
args->bytes_len,
457-
capture_header_buffer,
458-
args->ssl,
459-
args->orig_dport,
460-
tp_loop_fn);
461-
462-
if (meta) {
463-
u32 type = trace_type_from_meta(meta);
464-
tp_info_pid_t *tp_p = trace_info_for_connection(&args->pid_conn.conn, type);
465-
if (tp_p) {
466-
info->tp = tp_p->tp;
467-
if (self_ref_parent_id) {
468-
bpf_dbg_printk(
469-
"overwriting parent id from the self referencing client request");
470-
__builtin_memcpy(&info->tp.parent_id, &self_ref_parent_id, sizeof(u64));
471-
}
472-
} else {
473-
bpf_dbg_printk("Can't find trace info, this is a bug!");
474-
}
544+
if (tp_loop_fn == bpf_strstr_tp_loop__legacy) {
545+
bpf_tail_call(ctx, &jump_table, k_tail_continue_protocol_http);
546+
return 0;
475547
} else {
476-
bpf_dbg_printk("No META!");
548+
return __obi_continue_protocol_http(ctx, args, info, tp_loop_fn);
477549
}
478-
479-
// we copy some small part of the buffer to the info trace event, so that we can process an event even with
480-
// incomplete trace info in user space.
481-
bpf_probe_read(info->buf, FULL_BUF_SIZE, (void *)args->u_buf);
482-
process_http_request(info, args->bytes_len, meta, args->direction, args->orig_dport);
483550
} else if ((args->packet_type == PACKET_TYPE_RESPONSE) && (info->status == 0)) {
484551
handle_http_response(
485552
args->small_buf, &args->pid_conn, info, args->bytes_len, args->direction, args->ssl);
@@ -494,13 +561,11 @@ static __always_inline int __obi_protocol_http(unsigned char *(*tp_loop_fn)(unsi
494561
// k_tail_protocol_http
495562
SEC("kprobe/http")
496563
int obi_protocol_http(void *ctx) {
497-
(void)ctx;
498-
return __obi_protocol_http(bpf_strstr_tp_loop);
564+
return __obi_protocol_http(ctx, bpf_strstr_tp_loop);
499565
}
500566

501567
// k_tail_protocol_http
502568
SEC("kprobe/http")
503569
int obi_protocol_http_legacy(void *ctx) {
504-
(void)ctx;
505-
return __obi_protocol_http(bpf_strstr_tp_loop__legacy);
570+
return __obi_protocol_http(ctx, bpf_strstr_tp_loop__legacy);
506571
}

pkg/components/ebpf/generictracer/generictracer.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,14 @@ func (p *Tracer) Load() (*ebpf.CollectionSpec, error) {
162162
func (p *Tracer) SetupTailCalls() {
163163
for i, prog := range []*ebpf.Program{
164164
p.bpfObjects.ObiProtocolHttp, // 0
165-
p.bpfObjects.ObiProtocolHttp2, // 1
166-
p.bpfObjects.ObiProtocolTcp, // 2
167-
p.bpfObjects.ObiProtocolHttp2GrpcFrames, // 3
168-
p.bpfObjects.ObiProtocolHttp2GrpcHandleStartFrame, // 4
169-
p.bpfObjects.ObiProtocolHttp2GrpcHandleEndFrame, // 5
170-
p.bpfObjects.ObiHandleBufWithArgs, // 6
165+
p.bpfObjects.ObiContinueProtocolHttp, // 1
166+
p.bpfObjects.ObiContinue2ProtocolHttp, // 2
167+
p.bpfObjects.ObiProtocolHttp2, // 3
168+
p.bpfObjects.ObiProtocolTcp, // 4
169+
p.bpfObjects.ObiProtocolHttp2GrpcFrames, // 5
170+
p.bpfObjects.ObiProtocolHttp2GrpcHandleStartFrame, // 6
171+
p.bpfObjects.ObiProtocolHttp2GrpcHandleEndFrame, // 7
172+
p.bpfObjects.ObiHandleBufWithArgs, // 8
171173
} {
172174
p.log.Debug("loading program into tail call jump table", "index", i, "program", prog.String())
173175
if err := p.bpfObjects.JumpTable.Update(uint32(i), uint32(prog.FD()), ebpf.UpdateAny); err != nil {

0 commit comments

Comments
 (0)