Skip to content

Commit 3909f87

Browse files
committed
bpf: fallback to bounded loop if bpf_loop is not available
Signed-off-by: Mattia Meleleo <[email protected]>
1 parent 8416542 commit 3909f87

File tree

12 files changed

+297
-206
lines changed

12 files changed

+297
-206
lines changed

bpf/common/tcp_info.h

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,6 @@
1212

1313
enum { IP_V6_DEST_OPTS = 60 };
1414

15-
// Taken from uapi/linux/tcp.h
16-
struct __tcphdr {
17-
__be16 source;
18-
__be16 dest;
19-
__be32 seq;
20-
__be32 ack_seq;
21-
__u16 res1 : 4, doff : 4, fin : 1, syn : 1, rst : 1, psh : 1, ack : 1, urg : 1, ece : 1,
22-
cwr : 1;
23-
__be16 window;
24-
__sum16 check;
25-
__be16 urg_ptr;
26-
};
27-
2815
static __always_inline bool
2916
read_sk_buff(struct __sk_buff *skb, protocol_info_t *tcp, connection_info_t *conn) {
3017
// we read the protocol just like here linux/samples/bpf/parse_ldabs.c
@@ -107,41 +94,39 @@ read_sk_buff(struct __sk_buff *skb, protocol_info_t *tcp, connection_info_t *con
10794
}
10895

10996
u16 port;
110-
bpf_skb_load_bytes(skb, tcp->hdr_len + offsetof(struct __tcphdr, source), &port, sizeof(port));
97+
bpf_skb_load_bytes(skb, tcp->hdr_len + offsetof(struct tcphdr, source), &port, sizeof(port));
11198
conn->s_port = __bpf_htons(port);
11299

113-
bpf_skb_load_bytes(skb, tcp->hdr_len + offsetof(struct __tcphdr, dest), &port, sizeof(port));
100+
bpf_skb_load_bytes(skb, tcp->hdr_len + offsetof(struct tcphdr, dest), &port, sizeof(port));
114101
conn->d_port = __bpf_htons(port);
115102

116103
u32 seq;
117-
bpf_skb_load_bytes(skb, tcp->hdr_len + offsetof(struct __tcphdr, seq), &seq, sizeof(seq));
104+
bpf_skb_load_bytes(skb, tcp->hdr_len + offsetof(struct tcphdr, seq), &seq, sizeof(seq));
118105
tcp->seq = __bpf_htonl(seq);
119106

120107
u32 ack;
121-
bpf_skb_load_bytes(skb, tcp->hdr_len + offsetof(struct __tcphdr, ack_seq), &ack, sizeof(ack));
108+
bpf_skb_load_bytes(skb, tcp->hdr_len + offsetof(struct tcphdr, ack_seq), &ack, sizeof(ack));
122109
tcp->ack = __bpf_htonl(ack);
123110

124111
u8 doff;
125112
bpf_skb_load_bytes(
126113
skb,
127-
tcp->hdr_len + offsetof(struct __tcphdr, ack_seq) + 4,
114+
tcp->hdr_len + offsetof(struct tcphdr, ack_seq) + 4,
128115
&doff,
129-
sizeof(
130-
doff)); // read the first byte past __tcphdr->ack_seq, we can't do offsetof bit fields
131-
doff &= 0xf0; // clean-up res1
132-
doff >>= 4; // move the upper 4 bits to low
133-
doff *= 4; // convert to bytes length
116+
sizeof(doff)); // read the first byte past tcphdr->ack_seq, we can't do offsetof bit fields
117+
doff &= 0xf0; // clean-up res1
118+
doff >>= 4; // move the upper 4 bits to low
119+
doff *= 4; // convert to bytes length
134120

135121
u8 flags;
136122
bpf_skb_load_bytes(
137123
skb,
138-
tcp->hdr_len + offsetof(struct __tcphdr, ack_seq) + 4 + 1,
124+
tcp->hdr_len + offsetof(struct tcphdr, ack_seq) + 4 + 1,
139125
&flags,
140-
sizeof(flags)); // read the second byte past __tcphdr->doff, again bit fields offsets
126+
sizeof(flags)); // read the second byte past tcphdr->doff, again bit fields offsets
141127
tcp->flags = flags;
142128
tcp->h_proto = h_proto;
143-
tcp->opts_off =
144-
tcp->hdr_len + sizeof(struct __tcphdr); // must be done before we add data offset
129+
tcp->opts_off = tcp->hdr_len + sizeof(struct tcphdr); // must be done before we add data offset
145130

146131
tcp->hdr_len += doff;
147132

bpf/common/trace_common.h

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,7 @@ static __always_inline void trace_key_from_pid_tid(trace_key_t *t_key) {
5555
t_key->extra_id = extra_id;
5656
}
5757

58-
static int tp_match(u32 index, void *data) {
59-
if (!k_bpf_traceparent_enabled) {
60-
return 0;
61-
}
62-
58+
static __hidden int tp_match(u32 index, void *data) {
6359
if (index >= (TRACE_BUF_SIZE - TRACE_PARENT_HEADER_LEN)) {
6460
return 1;
6561
}
@@ -93,6 +89,26 @@ static __always_inline unsigned char *bpf_strstr_tp_loop(unsigned char *buf, int
9389
return NULL;
9490
}
9591

92+
static __always_inline unsigned char *bpf_strstr_tp_loop__legacy(unsigned char *buf) {
93+
if (!k_bpf_traceparent_enabled) {
94+
return NULL;
95+
}
96+
97+
const u16 k_besteffort_max_loops = 450; // Limit search to avoid burning too many instructions
98+
for (u16 i = 0; i + TRACE_PARENT_HEADER_LEN < k_besteffort_max_loops; i++) {
99+
// Only check at offset=0 or after '\n' to save instructions
100+
if (i != 0 && buf[i - 1] != '\n') {
101+
continue;
102+
}
103+
104+
if (is_traceparent(&buf[i])) {
105+
return &buf[i];
106+
}
107+
}
108+
109+
return NULL;
110+
}
111+
96112
static __always_inline const tp_info_pid_t *
97113
find_nginx_parent_trace(const pid_connection_info_t *p_conn, u16 orig_dport) {
98114
connection_info_part_t client_part = {};

bpf/common/trace_util.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
// 55+13
1010
#define TRACE_PARENT_HEADER_LEN 68
1111

12+
enum w3c_hdr_length : u8 {
13+
k_encode_decode_iter_max = 32,
14+
k_encode_decode_iter_max_mask = k_encode_decode_iter_max - 1,
15+
};
16+
1217
static unsigned char *hex = (unsigned char *)"0123456789abcdef";
1318
static unsigned char *reverse_hex =
1419
(unsigned char *)"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
@@ -34,8 +39,8 @@ static __always_inline void urand_bytes(unsigned char *buf, u32 size) {
3439
}
3540
}
3641

37-
static __always_inline void decode_hex(unsigned char *dst, const unsigned char *src, int src_len) {
38-
for (int i = 1, j = 0; i < src_len; i += 2) {
42+
static __always_inline void decode_hex(unsigned char *dst, const unsigned char *src, u8 src_len) {
43+
for (u8 i = 1, j = 0; i < (src_len & k_encode_decode_iter_max_mask); i += 2) {
3944
unsigned char p = src[i - 1];
4045
unsigned char q = src[i];
4146

@@ -49,8 +54,8 @@ static __always_inline void decode_hex(unsigned char *dst, const unsigned char *
4954
}
5055
}
5156

52-
static __always_inline void encode_hex(unsigned char *dst, const unsigned char *src, int src_len) {
53-
for (int i = 0, j = 0; i < src_len; i++) {
57+
static __always_inline void encode_hex(unsigned char *dst, const unsigned char *src, u8 src_len) {
58+
for (u8 i = 0, j = 0; i < (src_len & k_encode_decode_iter_max_mask); i++) {
5459
unsigned char p = src[i];
5560
dst[j++] = hex[(p >> 4) & 0xff];
5661
dst[j++] = hex[p & 0x0f];
@@ -63,6 +68,5 @@ static __always_inline bool is_traceparent(const unsigned char *p) {
6368
(p[8] == 'e') && (p[9] == 'n') && (p[10] == 't') && (p[11] == ':') && (p[12] == ' ')) {
6469
return true;
6570
}
66-
6771
return false;
6872
}

bpf/generictracer/protocol_http.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,13 @@ static __always_inline void http_get_or_create_trace_info(http_connection_metada
147147
bpf_clamp_umax(buf_len, TRACE_BUF_SIZE - 1);
148148

149149
bpf_probe_read(buf, buf_len, u_buf);
150-
unsigned char *res = bpf_strstr_tp_loop(buf, buf_len);
150+
151+
unsigned char *res = NULL;
152+
if (bpf_core_enum_value_exists(enum bpf_func_id, BPF_FUNC_loop)) {
153+
res = bpf_strstr_tp_loop(buf, buf_len);
154+
} else {
155+
res = bpf_strstr_tp_loop__legacy(buf);
156+
}
151157

152158
if (res) {
153159
bpf_dbg_printk("Found traceparent in headers [%s] overriding what was before", res);

bpf/gotracer/hpack.h

Lines changed: 0 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -8,164 +8,7 @@
88

99
#include <common/tracing.h>
1010

11-
uint32_t huffman_codes[256] = {
12-
0x1ff8, 0x7fffd8, 0xfffffe2, 0xfffffe3, 0xfffffe4, 0xfffffe5, 0xfffffe6, 0xfffffe7,
13-
0xfffffe8, 0xffffea, 0x3ffffffc, 0xfffffe9, 0xfffffea, 0x3ffffffd, 0xfffffeb, 0xfffffec,
14-
0xfffffed, 0xfffffee, 0xfffffef, 0xffffff0, 0xffffff1, 0xffffff2, 0x3ffffffe, 0xffffff3,
15-
0xffffff4, 0xffffff5, 0xffffff6, 0xffffff7, 0xffffff8, 0xffffff9, 0xffffffa, 0xffffffb,
16-
0x14, 0x3f8, 0x3f9, 0xffa, 0x1ff9, 0x15, 0xf8, 0x7fa,
17-
0x3fa, 0x3fb, 0xf9, 0x7fb, 0xfa, 0x16, 0x17, 0x18,
18-
0x0, 0x1, 0x2, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
19-
0x1e, 0x1f, 0x5c, 0xfb, 0x7ffc, 0x20, 0xffb, 0x3fc,
20-
0x1ffa, 0x21, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62,
21-
0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
22-
0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72,
23-
0xfc, 0x73, 0xfd, 0x1ffb, 0x7fff0, 0x1ffc, 0x3ffc, 0x22,
24-
0x7ffd, 0x3, 0x23, 0x4, 0x24, 0x5, 0x25, 0x26,
25-
0x27, 0x6, 0x74, 0x75, 0x28, 0x29, 0x2a, 0x7,
26-
0x2b, 0x76, 0x2c, 0x8, 0x9, 0x2d, 0x77, 0x78,
27-
0x79, 0x7a, 0x7b, 0x7ffe, 0x7fc, 0x3ffd, 0x1ffd, 0xffffffc,
28-
0xfffe6, 0x3fffd2, 0xfffe7, 0xfffe8, 0x3fffd3, 0x3fffd4, 0x3fffd5, 0x7fffd9,
29-
0x3fffd6, 0x7fffda, 0x7fffdb, 0x7fffdc, 0x7fffdd, 0x7fffde, 0xffffeb, 0x7fffdf,
30-
0xffffec, 0xffffed, 0x3fffd7, 0x7fffe0, 0xffffee, 0x7fffe1, 0x7fffe2, 0x7fffe3,
31-
0x7fffe4, 0x1fffdc, 0x3fffd8, 0x7fffe5, 0x3fffd9, 0x7fffe6, 0x7fffe7, 0xffffef,
32-
0x3fffda, 0x1fffdd, 0xfffe9, 0x3fffdb, 0x3fffdc, 0x7fffe8, 0x7fffe9, 0x1fffde,
33-
0x7fffea, 0x3fffdd, 0x3fffde, 0xfffff0, 0x1fffdf, 0x3fffdf, 0x7fffeb, 0x7fffec,
34-
0x1fffe0, 0x1fffe1, 0x3fffe0, 0x1fffe2, 0x7fffed, 0x3fffe1, 0x7fffee, 0x7fffef,
35-
0xfffea, 0x3fffe2, 0x3fffe3, 0x3fffe4, 0x7ffff0, 0x3fffe5, 0x3fffe6, 0x7ffff1,
36-
0x3ffffe0, 0x3ffffe1, 0xfffeb, 0x7fff1, 0x3fffe7, 0x7ffff2, 0x3fffe8, 0x1ffffec,
37-
0x3ffffe2, 0x3ffffe3, 0x3ffffe4, 0x7ffffde, 0x7ffffdf, 0x3ffffe5, 0xfffff1, 0x1ffffed,
38-
0x7fff2, 0x1fffe3, 0x3ffffe6, 0x7ffffe0, 0x7ffffe1, 0x3ffffe7, 0x7ffffe2, 0xfffff2,
39-
0x1fffe4, 0x1fffe5, 0x3ffffe8, 0x3ffffe9, 0xffffffd, 0x7ffffe3, 0x7ffffe4, 0x7ffffe5,
40-
0xfffec, 0xfffff3, 0xfffed, 0x1fffe6, 0x3fffe9, 0x1fffe7, 0x1fffe8, 0x7ffff3,
41-
0x3fffea, 0x3fffeb, 0x1ffffee, 0x1ffffef, 0xfffff4, 0xfffff5, 0x3ffffea, 0x7ffff4,
42-
0x3ffffeb, 0x7ffffe6, 0x3ffffec, 0x3ffffed, 0x7ffffe7, 0x7ffffe8, 0x7ffffe9, 0x7ffffea,
43-
0x7ffffeb, 0xffffffe, 0x7ffffec, 0x7ffffed, 0x7ffffee, 0x7ffffef, 0x7fffff0, 0x3ffffee,
44-
};
45-
46-
uint8_t huffman_code_len[256] = {
47-
13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 30, 28,
48-
28, 28, 28, 28, 28, 28, 28, 28, 6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6,
49-
5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10, 13, 6, 7, 7, 7, 7, 7, 7,
50-
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6,
51-
15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5, 6, 7, 6, 5, 5, 6, 7, 7,
52-
7, 7, 7, 15, 11, 14, 13, 28, 20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23,
53-
24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24, 22, 21, 20, 22, 22, 23, 23, 21,
54-
23, 22, 22, 24, 21, 22, 23, 23, 21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23,
55-
26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25, 19, 21, 26, 27, 27, 26, 27, 24,
56-
21, 21, 26, 26, 28, 27, 27, 27, 20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23,
57-
26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26,
58-
};
59-
60-
#define EOS_CODE (0x3fffffff)
61-
#define EOS_N_BITS (30)
62-
#define EOS_PAD_BYTE (EOS_CODE >> (EOS_N_BITS - 8))
63-
6411
#define TP_ENCODED_LEN 8
6512

6613
static unsigned char tp_encoded[TP_ENCODED_LEN] = {
6714
0x4d, 0x83, 0x21, 0x6b, 0x1d, 0x85, 0xa9, 0x3f}; // hpack encoded "traceparent"
68-
69-
struct hpack_ctx {
70-
uint8_t dst[TP_MAX_VAL_LENGTH];
71-
int32 dst_len;
72-
uint8_t src[TP_MAX_VAL_LENGTH];
73-
uint64_t m_bytes;
74-
uint32_t m_count;
75-
int32 len;
76-
};
77-
78-
static int encode_iter(u32 index, struct hpack_ctx *d) {
79-
int len = d->len;
80-
81-
if (len >= (TP_MAX_VAL_LENGTH - 4)) {
82-
d->len = -1;
83-
return 1;
84-
}
85-
86-
if (index >= TP_MAX_VAL_LENGTH) {
87-
return 1;
88-
}
89-
90-
uint8_t b = d->src[index];
91-
92-
d->m_count += (uint32_t)(huffman_code_len[b]);
93-
d->m_bytes <<= huffman_code_len[b] % 64;
94-
d->m_bytes |= huffman_codes[b];
95-
if (d->m_count >= 32) {
96-
d->m_count %= 32;
97-
uint32_t y = (uint32_t)(d->m_bytes >> d->m_count);
98-
d->dst[len] = (uint8_t)(y >> 24);
99-
d->dst[len + 1] = (uint8_t)(y >> 16);
100-
d->dst[len + 2] = (uint8_t)(y >> 8);
101-
d->dst[len + 3] = (uint8_t)(y);
102-
d->len += 4;
103-
}
104-
105-
return 0;
106-
}
107-
108-
static __always_inline int32_t hpack_encode_tp(struct hpack_ctx *d) {
109-
uint32_t nr_loops = TP_MAX_VAL_LENGTH;
110-
111-
bpf_loop(nr_loops, encode_iter, d, 0);
112-
113-
int len = d->len;
114-
115-
if (len < 0) {
116-
return -1;
117-
}
118-
119-
if (len > (TP_MAX_VAL_LENGTH - 4)) {
120-
return -1;
121-
}
122-
123-
uint32_t over = d->m_count % 8;
124-
125-
if (over > 0 && over < 8) {
126-
uint32_t pad = (8 - over) & 0x0ff;
127-
d->m_bytes = (d->m_bytes << pad) | (EOS_PAD_BYTE >> over);
128-
d->m_count += pad; // 8 now divides into n exactly
129-
}
130-
131-
uint32_t rem = (d->m_count / 8);
132-
133-
// n in (0, 8, 16, 24, 32)
134-
switch (rem) {
135-
case 0:
136-
return d->len;
137-
case 1:
138-
d->dst[len] = (uint8_t)(d->m_bytes);
139-
d->len += 1;
140-
return d->len;
141-
case 2: {
142-
uint16_t y = (uint16_t)(d->m_bytes);
143-
d->dst[len] = (uint8_t)(y >> 8);
144-
d->dst[len + 1] = (uint8_t)(y);
145-
146-
d->len += 2;
147-
148-
return d->len;
149-
}
150-
case 3: {
151-
uint16_t y = (uint16_t)(d->m_bytes >> 8);
152-
d->dst[len] = (uint8_t)(y >> 8);
153-
d->dst[len + 1] = (uint8_t)(y);
154-
d->dst[len + 2] = (uint8_t)(d->m_bytes);
155-
d->len += 3;
156-
return d->len;
157-
}
158-
default:
159-
break;
160-
}
161-
// case 4:
162-
uint32_t y = (uint32_t)(d->m_bytes);
163-
d->dst[len] = (uint8_t)(y >> 24);
164-
d->dst[len + 1] = (uint8_t)(y >> 16);
165-
d->dst[len + 2] = (uint8_t)(y >> 8);
166-
d->dst[len + 3] = (uint8_t)(y);
167-
168-
d->len += 4;
169-
170-
return d->len;
171-
}

bpf/tctracer/tctracer.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ static __always_inline void track_sock(struct __sk_buff *skb, const connection_i
211211

212212
SEC("tc_egress")
213213
int obi_app_egress(struct __sk_buff *skb) {
214-
//bpf_printk("egress");
215214
protocol_info_t tcp = {};
216215
connection_info_t conn = {};
217216
pid_connection_info_t p_conn = {};

pkg/components/ebpf/generictracer/generictracer.go

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,12 @@ func (p *Tracer) Load() (*ebpf.CollectionSpec, error) {
141141

142142
if p.cfg.EBPF.TrackRequestHeaders ||
143143
p.cfg.EBPF.ContextPropagation != config.ContextPropagationDisabled {
144-
if ebpfcommon.SupportsEBPFLoops(p.log, p.cfg.EBPF.OverrideBPFLoopEnabled) {
145-
p.log.Info("Found compatible Linux kernel, enabling trace information parsing")
146-
loader = LoadBpfTP
147-
if p.cfg.EBPF.BpfDebug {
148-
loader = LoadBpfTPDebug
149-
}
150-
} else {
151-
p.log.Info("Found incompatible Linux kernel, disabling trace information parsing")
144+
loader = LoadBpfTP
145+
if p.cfg.EBPF.BpfDebug {
146+
loader = LoadBpfTPDebug
152147
}
148+
149+
p.log.Info("Enabling trace information parsing", "bpf_loop_enabled", ebpfcommon.SupportsEBPFLoops(p.log, p.cfg.EBPF.OverrideBPFLoopEnabled))
153150
}
154151

155152
return loader()

pkg/components/kube/informer_provider.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ func loadKubeConfig(kubeConfigPath string) (*rest.Config, error) {
323323
// fallback: use in-cluster config
324324
config, err = rest.InClusterConfig()
325325
if err != nil {
326-
return nil, fmt.Errorf("can't access kubenetes. Tried using config from: "+
326+
return nil, fmt.Errorf("can't access kubernetes. Tried using config from: "+
327327
"config parameter, %s env, homedir and InClusterConfig. Got: %w",
328328
kubeConfigEnvVariable, err)
329329
}

pkg/kubecache/meta/informers_init.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ func loadKubeconfig(kubeConfigPath string) (*rest.Config, error) {
251251
// fallback: use in-cluster config
252252
config, err = rest.InClusterConfig()
253253
if err != nil {
254-
return nil, fmt.Errorf("can't access kubenetes. Tried using config from: "+
254+
return nil, fmt.Errorf("can't access kubernetes. Tried using config from: "+
255255
"config parameter, %s env, homedir and InClusterConfig. Got: %w",
256256
kubeConfigEnvVariable, err)
257257
}

pkg/obi/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ var DefaultConfig = Config{
8282
MySQLPreparedStatementsCacheSize: 1024,
8383
PostgresPreparedStatementsCacheSize: 1024,
8484
MongoRequestsCacheSize: 1024,
85+
OverrideBPFLoopEnabled: false,
8586
},
8687
NameResolver: &transform.NameResolverConfig{
8788
Sources: []string{"k8s"},

0 commit comments

Comments
 (0)