mrproliu opened a new pull request, #209:
URL: https://github.com/apache/skywalking-rover/pull/209

   ## Problem
   
   On newer kernels (reproduced on GKE COS `6.12` / amd64), the access log 
module fails to start and the pod enters `CrashLoopBackOff`:
   
   ```
   Error: start module access_log failure: field GoTlsReadRet: program 
go_tls_read_ret:
   load program: argument list too long: 2367: (b7) r1 = 2048:
   BPF program is too large. Processed 1000001 insn (truncated, 449 line(s) 
omitted)
   ```
   
   Despite the `argument list too long` wording, this is **not** an arguments 
problem — it is the eBPF **verifier complexity limit**. The verifier processed 
more than 1,000,000 instructions (`Processed 1000001 insn`) without converging 
and rejected the program.
   
   ## Root cause
   
   `go_tls_read_ret` fully `__always_inline`-expands the entire data path into 
a single program:
   
   - `process_write_data`
     - → `read_socket_data` + `analyze_protocol` (HTTP/2 inference with nested 
unrolled loops)
     - → `get_or_create_active_conn`
     - → `upload_socket_data` → `upload_socket_data_buf` (6× unrolled) **and** 
`upload_socket_data_iov` (6× unrolled), each inlining 
`__upload_socket_data_with_buffer`
   
   The verifier explores both the buf and iov branches × 6 chunks × per-chunk 
branches, multiplied by the protocol-analysis branches. This produces a 
combinatorial path explosion. `go_tls` trips the limit first because it carries 
the extra arch-specific `get_goid` / `go_regabi_regs` register reads on top of 
the shared path; the other SSL probes (`openssl`, `node_tls`) walk the same 
data path and are next in line.
   
   ## Fix
   
   Convert the heaviest **shared** inline helpers on the data path into 
**BPF-to-BPF sub-program calls** (`__noinline`). A non-inlined sub-program is 
verified **once** instead of being re-verified for every inlined copy on every 
code path, which sharply lowers the processed-instruction count.
   
   Functions converted (all ≤ 5 args, so they fit the BPF calling convention 
with no signature changes):
   
   | File | Function |
   |------|----------|
   | `bpf/include/api.h` | new `__noinline` macro (guarded with `#ifndef`) |
   | `bpf/include/socket_data.h` | `upload_socket_data_buf`, 
`upload_socket_data_iov` |
   | `bpf/include/protocol_analyzer.h` | `analyze_protocol` |
   | `bpf/include/socket_reader.h` | `read_socket_data` |
   | `bpf/accesslog/common/connection.h` | `get_or_create_active_conn` |
   
   Because these live in shared headers, every program on the data path 
benefits at once (`go_tls`, `openssl`, `node_tls`, syscall transfer).
   
   This is purely an inlining-strategy change — **no maps, structs, or upload 
semantics are modified**, so runtime behavior is unchanged.
   
   ## Compatibility
   
   BPF-to-BPF calls require kernel **≥ 4.16**. The access log / network 
monitoring path already requires 4.16+ (see `docs/en/setup/overview.md`), so 
the supported-kernel matrix is unchanged.
   
   ## Verification
   
   Built the amd64 object and loaded `go_tls_read_ret` through the real kernel 
verifier on amd64 (kernel `6.1`, same architecture and verifier generation as 
the failing GKE node):
   
   | Build | Processed insns | Result |
   |-------|----------------:|--------|
   | Before (original GKE error, amd64 / 6.12) | 1,000,001 | ❌ rejected (> 1M 
limit) |
   | After (this PR, amd64 / 6.1)              |   178,670 | ✅ verified |
   
   The program now verifies at roughly 1/6 of the instruction limit.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to