Skip to content

Commit 1e6c404

Browse files
committed
Remove pow2 limitation, fallback to base buffer if large buffer not found
1 parent 891737a commit 1e6c404

File tree

6 files changed

+22
-54
lines changed

6 files changed

+22
-54
lines changed

bpf/common/large_buffers.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ enum {
1717
// of the maximum payload size as a guard.
1818
k_large_buf_max_size = 1 << 14, // 16K
1919
k_large_buf_max_size_mask = k_large_buf_max_size - 1,
20+
21+
// Maximum size for a large buffer payload.
22+
k_large_buf_payload_max_size = 1 << 13, // 8K
23+
k_large_buf_payload_max_size_mask = k_large_buf_payload_max_size - 1,
2024
};
2125

2226
SCRATCH_MEM_SIZED(http_large_buffers, k_large_buf_max_size);

bpf/generictracer/protocol_http.h

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -413,12 +413,6 @@ static __always_inline int http_send_large_buffer(http_info_t *req,
413413
return 0;
414414
}
415415

416-
if (!is_pow2(http_buffer_size)) {
417-
bpf_dbg_printk("http_send_large_buffer: bug: http_buffer_size is not a power of 2");
418-
return -1;
419-
}
420-
const u32 buf_len_mask = http_buffer_size - 1;
421-
422416
tcp_large_buffer_t *large_buf = (tcp_large_buffer_t *)http_large_buffers_mem();
423417
if (!large_buf) {
424418
bpf_dbg_printk("http_send_large_buffer: failed to reserve space for HTTP large buffer");
@@ -436,7 +430,7 @@ static __always_inline int http_send_large_buffer(http_info_t *req,
436430
bpf_dbg_printk("WARN: http_send_large_buffer: buffer is full, truncating data");
437431
}
438432

439-
bpf_probe_read(large_buf->buf, large_buf->len & buf_len_mask, u_buf);
433+
bpf_probe_read(large_buf->buf, large_buf->len & k_large_buf_payload_max_size_mask, u_buf);
440434

441435
u32 total_size = sizeof(tcp_large_buffer_t);
442436
total_size += large_buf->len > sizeof(void *) ? large_buf->len : sizeof(void *);
@@ -524,13 +518,8 @@ int obi_protocol_http(void *ctx) {
524518
bpf_dbg_printk("No META!");
525519
}
526520

527-
if (http_buffer_size > 0) {
528-
http_send_large_buffer(info,
529-
(void *)args->u_buf,
530-
args->bytes_len,
531-
args->packet_type,
532-
k_large_buf_action_init);
533-
}
521+
http_send_large_buffer(
522+
info, (void *)args->u_buf, args->bytes_len, args->packet_type, k_large_buf_action_init);
534523

535524
// we copy some small part of the buffer to the info trace event, so that we can process an event even with
536525
// incomplete trace info in user space.

bpf/generictracer/protocol_mysql.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,6 @@ static __always_inline int mysql_read_fixup_buffer(const connection_info_t *conn
124124
u32 data_len) {
125125
u8 offset = 0;
126126

127-
if (!is_pow2(mysql_buffer_size)) {
128-
bpf_dbg_printk("mysql_read_fixup_buffer: bug: mysql_buffer_size is not a power of 2");
129-
return -1;
130-
}
131-
const u32 buf_len_mask = mysql_buffer_size - 1;
132-
133127
struct mysql_state_data *state_data = bpf_map_lookup_elem(&mysql_state, conn_info);
134128
if (state_data != NULL) {
135129
bpf_probe_read(buf, k_mysql_hdr_without_command_size, (const void *)state_data);
@@ -148,7 +142,7 @@ static __always_inline int mysql_read_fixup_buffer(const connection_info_t *conn
148142
bpf_dbg_printk("WARN: mysql_read_fixup_buffer: buffer is full, truncating data");
149143
}
150144

151-
bpf_probe_read(buf + offset, *buf_len & buf_len_mask, (const void *)data);
145+
bpf_probe_read(buf + offset, *buf_len & k_large_buf_payload_max_size_mask, (const void *)data);
152146

153147
return *buf_len;
154148
}

bpf/generictracer/protocol_postgres.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,6 @@ static __always_inline int postgres_send_large_buffer(tcp_req_t *req,
5353
u32 bytes_len,
5454
u8 packet_type,
5555
enum large_buf_action action) {
56-
if (!is_pow2(postgres_buffer_size)) {
57-
bpf_dbg_printk("postgres_send_large_buffer: bug: postgres_buffer_size is not a power of 2");
58-
return -1;
59-
}
60-
const u32 buf_len_mask = postgres_buffer_size - 1;
61-
6256
tcp_large_buffer_t *large_buf = (tcp_large_buffer_t *)postgres_large_buffers_mem();
6357
if (!large_buf) {
6458
bpf_dbg_printk(
@@ -76,7 +70,7 @@ static __always_inline int postgres_send_large_buffer(tcp_req_t *req,
7670
large_buf->len = postgres_buffer_size;
7771
bpf_dbg_printk("WARN: postgres_send_large_buffer: buffer is full, truncating data");
7872
}
79-
bpf_probe_read(large_buf->buf, large_buf->len & buf_len_mask, u_buf);
73+
bpf_probe_read(large_buf->buf, large_buf->len & k_large_buf_payload_max_size_mask, u_buf);
8074

8175
u32 total_size = sizeof(tcp_large_buffer_t);
8276
total_size += large_buf->len > sizeof(void *) ? large_buf->len : sizeof(void *);

pkg/components/ebpf/common/httpfltr_transform.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,16 @@ func HTTPInfoEventToSpan(parseCtx *EBPFParseContext, event *BPFHTTPInfo) (reques
8686
bufHost string
8787
bufPort int
8888
parsedHost bool
89-
requestBuffer []byte
89+
requestBuffer = event.Buf[:]
9090
)
9191

9292
if event.HasLargeBuffers == 1 {
9393
b, ok := extractTCPLargeBuffer(parseCtx, event.Tp.TraceId, event.Tp.SpanId, packetTypeRequest)
94-
if !ok {
94+
if ok {
95+
requestBuffer = b
96+
} else {
9597
slog.Debug("missing large buffer for HTTP request", "traceID", event.Tp.TraceId, "spanID", event.Tp.SpanId)
96-
return request.Span{}, false, nil
9798
}
98-
requestBuffer = b
99-
} else {
100-
requestBuffer = event.Buf[:]
10199
}
102100

103101
// When we can't find the connection info, we signal that through making the

pkg/config/ebpf_tracer.go

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ const (
2525
ContextPropagationDisabled
2626
)
2727

28+
const bufferSizeMax = 8192
29+
2830
// EBPFTracer configuration for eBPF programs
2931
type EBPFTracer struct {
3032
// Enables logging of eBPF program events
@@ -103,9 +105,7 @@ type EBPFTracer struct {
103105
}
104106

105107
// Per-protocol data buffer size in bytes.
106-
// Min: 128 bytes, Max: 8192 bytes.
107-
// Valid values: 0, 128, 256, 512, 1024, 2048, 4096, 8192.
108-
//
108+
// Max: 8192 bytes.
109109
// Default: 0 (disabled).
110110
type EBPFBufferSizes struct {
111111
HTTP uint32 `yaml:"http" env:"OTEL_EBPF_BPF_BUFFER_SIZE_HTTP"`
@@ -116,25 +116,14 @@ type EBPFBufferSizes struct {
116116
func (c *EBPFTracer) Validate() error {
117117
// TODO(matt): validate all the existing attributes
118118

119-
switch c.BufferSizes.HTTP {
120-
case 0, 128, 256, 512, 1024, 2048, 4096, 8192:
121-
// valid sizes
122-
default:
123-
return fmt.Errorf("invalid HTTP buffer size: %d, must be one of 0, 128, 256, 512, 1024, 2048, 4096, 8192", c.BufferSizes.HTTP)
119+
if c.BufferSizes.HTTP > bufferSizeMax {
120+
return fmt.Errorf("buffer size too large (HTTP): %d, max is %d", c.BufferSizes.HTTP, bufferSizeMax)
124121
}
125-
126-
switch c.BufferSizes.MySQL {
127-
case 0, 128, 256, 512, 1024, 2048, 4096, 8192:
128-
// valid sizes
129-
default:
130-
return fmt.Errorf("invalid MySQL buffer size: %d, must be one of 0, 128, 256, 512, 1024, 2048, 4096, 8192", c.BufferSizes.MySQL)
122+
if c.BufferSizes.MySQL > bufferSizeMax {
123+
return fmt.Errorf("buffer size too large (MySQL): %d, max is %d", c.BufferSizes.MySQL, bufferSizeMax)
131124
}
132-
133-
switch c.BufferSizes.Postgres {
134-
case 0, 128, 256, 512, 1024, 2048, 4096, 8192:
135-
// valid sizes
136-
default:
137-
return fmt.Errorf("invalid Postgres buffer size: %d, must be one of 0, 128, 256, 512, 1024, 2048, 4096, 8192", c.BufferSizes.Postgres)
125+
if c.BufferSizes.Postgres > bufferSizeMax {
126+
return fmt.Errorf("buffer size too large (Postgres): %d, max is %d", c.BufferSizes.Postgres, bufferSizeMax)
138127
}
139128

140129
return nil

0 commit comments

Comments
 (0)