-
Notifications
You must be signed in to change notification settings - Fork 111
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
(Experimental) Trace context propagation via HTTP headers #1291
Conversation
|
||
struct seq_offset_map { | ||
__uint(type, BPF_MAP_TYPE_HASH); | ||
__type(key, __u32); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is currently only indexing on the ephemeral port - I reckon we require something a bit smarter here.
bpf/tc_http_tp.c
Outdated
buf = check_pkt_access(buf, EXTEND_SIZE, end); | ||
|
||
if (!buf) | ||
return; | ||
|
||
*buf++ = 'T'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This keeps the verifier happy, both in terms of register offset validation, and in terms of keeping the program complexity at bay.
return seq ? *seq : 0; | ||
} | ||
|
||
static __always_inline int is_http_request(struct __sk_buff *ctx) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to merge the logic from is_http
here, again, for complexity reasons (in this case, doing without unnecessary branching and storing the packet_type
).
bpf/tc_http_tp.c
Outdated
} | ||
|
||
static __always_inline unsigned char * | ||
memchar(unsigned char *haystack, char needle, unsigned char *end, __u32 size) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps the inner checks here can be avoided if check_pkt_access()
is used
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1291 +/- ##
==========================================
- Coverage 81.25% 81.07% -0.18%
==========================================
Files 142 143 +1
Lines 14295 14499 +204
==========================================
+ Hits 11615 11755 +140
- Misses 2116 2170 +54
- Partials 564 574 +10
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
539b6ee
to
6baec39
Compare
6baec39
to
faff19a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Looks great, amazing work. I left a few comments about code reuse, they can be done in a follow-up.
//go:generate $BPF2GO -cc $BPF_CLANG -cflags $BPF_CFLAGS -target amd64,arm64 bpf ../../../../bpf/tc_http_tp.c -- -I../../../../bpf/headers | ||
//go:generate $BPF2GO -cc $BPF_CLANG -cflags $BPF_CFLAGS -target amd64,arm64 bpf_debug ../../../../bpf/tc_http_tp.c -- -I../../../../bpf/headers -DBPF_DEBUG | ||
|
||
type Tracer struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can common some code here with the tctracer. Maybe we can make those qdisc routines helpers that can be reused?
return 0; | ||
} | ||
|
||
return (req_buf[0] == 'G' && req_buf[1] == 'E' && req_buf[2] == 'T' && req_buf[3] == ' ' && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense the code duplication, not critical, but perhaps we can just extract this code into a macro or __always_inline to avoid having to change this in two places, no that we ever will :).
// we've only received ACK, but no FIN, wait for it | ||
http_ctx->state = FIN_WAIT_2; | ||
} | ||
} else if (http_ctx->state == CLOSING && tcp->ack) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can turn these into OR statements to save some instructions, that way delete_http_ctx will get inlined once only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent idea, will also do it on a follow up PR
Any way we can keep that image you have here in a doc, perhaps a markdown file in the same folder as the bpfs? |
Inject
Traceparent
into HTTP headers for trace context propagation. This is done using a pair oftc
programs: the egress program monitors connection metadata and, upon encountering a HTTP request, it will attempt to inject theTraceparent:
string directly into the packet. This entails extending the packet, writing the traceparent, and recalculating the relevant checksums. The engress program stores the new expected sequence number in a map. It ensures packets that follow are correctly adjusted.The egress program, conversely, adjusts the arriving sequence number back to what is expected by the higher-level kernel layers. If left unchanged, the kernel will drop the packet and will trigger a TCP retransmission.
For the handling of closing TCP connections, please refer to the following diagram to assist understanding the code: