Skip to content

test(ebpf): add eBPF program unit tests via BPF_PROG_TEST_RUN#2049

Open
nddq wants to merge 1 commit intomainfrom
test/ebpf-program-unit-tests
Open

test(ebpf): add eBPF program unit tests via BPF_PROG_TEST_RUN#2049
nddq wants to merge 1 commit intomainfrom
test/ebpf-program-unit-tests

Conversation

@nddq
Copy link
Member

@nddq nddq commented Feb 13, 2026

Description

Add an eBPF program unit test framework that executes compiled eBPF bytecode in the kernel using BPF_PROG_TEST_RUN (prog.Run() in cilium/ebpf). This validates actual kernel-side packet parsing logic rather than mocking the Go wrapper layer, catching bugs like wrong offsets, missing bounds checks, or incorrect flag handling that would otherwise only surface at runtime in a cluster.

Shared test infrastructure (pkg/plugin/ebpftest/):

  • helpers.go — privilege checks, map pinning removal, generic perf event reader, IP/port byte-order helpers, LPM trie filter map population, program runner
  • packet.go — TCP/UDP/ICMP/ARP packet construction via gopacket with configurable flags, timestamps, and payloads

Packetparser tests (pkg/plugin/packetparser/packetparser_ebpf_test.go) — 25 test functions covering:

  • Packet parsing: TCP flags (all 9 combinations), TCP timestamps, UDP, observation points, packet bytes field
  • Filter map: IP matching produces events, missing IPs produce none
  • Edge cases: runt packets, truncated IP/TCP headers, non-IPv4 (ARP/IPv6), ICMP
  • Conntrack perf events: is_reply across SYN/SYN-ACK/ACK, traffic direction per observation point, conntrack metrics counters, HIGH aggregation suppression, previously_observed_* fields
  • Conntrack map state (direct map reads): entry field initialization after SYN, flag bitmask accumulation across packets, reply packets updating RX-direction fields, is_direction_unknown for mid-stream connections, since-last-report counter accumulation and reset on FIN, lifetime metadata counters with ENABLE_CONNTRACK_METRICS, eviction time extension from SYN timeout to established
  • Recompilation variants: custom dynamic.h via loader.CompileEbpf for DATA_AGGREGATION_LEVEL=HIGH and ENABLE_CONNTRACK_METRICS=1

CI (.github/workflows/test-ebpf.yaml): matrix strategy on amd64 (ubuntu-latest) and arm64 (ubuntu-24.04-arm), compiles eBPF via go generate, runs tests with sudo.

Makefile: make test-ebpf target.

Related Issue

N/A — new test coverage for previously untested eBPF programs.

Checklist

  • I have read the contributing documentation.
  • I signed and signed-off the commits (git commit -S -s ...). See this documentation on signing commits.
  • I have correctly attributed the author(s) of the code.
  • I have tested the changes locally.
  • I have followed the project's style guidelines.
  • I have updated the documentation, if necessary.
  • I have added tests, if applicable.

Screenshots (if applicable) or Testing Completed

All 25 eBPF tests pass locally on Linux amd64 with kernel 6.14.0:

=== RUN   TestEndpointIngressFilter_TCP           PASS (0.27s)
=== RUN   TestAllObservationPoints                 PASS (0.19s)
=== RUN   TestTCPFlags                             PASS (0.19s)
=== RUN   TestTCPTimestamps                        PASS (0.18s)
=== RUN   TestUDPPacket                            PASS (0.17s)
=== RUN   TestFilterMapFiltering                   PASS (0.68s)
=== RUN   TestNonTCPUDP_NoEvent                    PASS (0.68s)
=== RUN   TestNonIPv4_NoEvent                      PASS (1.17s)
=== RUN   TestMalformedPackets                     PASS (0.68s)
=== RUN   TestReturnValue                          PASS (0.57s)
=== RUN   TestPacketBytesField                     PASS (0.18s)
=== RUN   TestConntrackMapUpdated                  PASS (0.18s)
=== RUN   TestConntrackIsReply                     PASS (0.17s)
=== RUN   TestConntrackTrafficDirection            PASS (0.18s)
=== RUN   TestConntrackMetricsEnabled              PASS (0.55s)
=== RUN   TestHighAggregationLevel                 PASS (0.95s)
=== RUN   TestHighAggregationPreviouslyObserved    PASS (0.66s)
=== RUN   TestConntrackEntryCreation               PASS (0.20s)
=== RUN   TestConntrackFlagAccumulation            PASS (0.19s)
=== RUN   TestConntrackReplyUpdatesEntry           PASS (0.19s)
=== RUN   TestConntrackDirectionUnknown            PASS (0.17s)
=== RUN   TestConntrackSinceLastReportAccumulation PASS (0.85s)
=== RUN   TestConntrackCounterResetOnReport        PASS (0.86s)
=== RUN   TestConntrackMetadataCountersInMap       PASS (0.55s)
=== RUN   TestConntrackEvictionTimeExtended        PASS (0.18s)
ok      github.com/microsoft/retina/pkg/plugin/packetparser   14.127s

Lint passes cleanly (make lint — 0 new issues).

Existing unit tests unaffected (different build tag: ebpf vs unit).

Additional Notes

  • Tests use //go:build ebpf && linux — they do not run during make test
  • Requires CAP_BPF + CAP_NET_ADMIN (or root) and Linux kernel >= 5.x
  • The ebpftest package is designed for reuse by other plugin tests (dropreason, dns, etc.)
  • Recompilation tests use loader.CompileEbpf (same as production) and require clang

Please refer to the CONTRIBUTING.md file for more information on how to contribute to this project.

@nddq nddq marked this pull request as ready for review February 13, 2026 16:21
@nddq nddq requested a review from a team as a code owner February 13, 2026 16:21
@nddq nddq requested review from skosuri1 and timraymond February 13, 2026 16:21
Add a test framework that executes compiled eBPF programs in the kernel
using BPF_PROG_TEST_RUN with crafted packets, validating actual bytecode
behavior rather than mocking the Go wrapper layer.

Shared infrastructure in pkg/plugin/ebpftest/:
- helpers.go: privilege checks, map pinning removal, perf event
  reading, IP/port byte-order helpers, filter map population
- packet.go: TCP/UDP/ICMP/ARP packet construction via gopacket

Packetparser tests (25 test functions) covering:
- Packet parsing: TCP flags, timestamps, UDP, observation points
- Filter map: IP matching and rejection
- Malformed packets: runt, truncated IP/TCP, non-IPv4
- Conntrack perf events: is_reply, traffic direction, metrics
- Conntrack map state: entry creation fields, flag accumulation,
  reply updates RX fields, direction-unknown for mid-stream flows,
  since-last-report counter accumulation and reset, lifetime
  metadata counters, eviction time extension
- Recompilation variants: HIGH aggregation suppression,
  ENABLE_CONNTRACK_METRICS

Includes CI workflow (.github/workflows/test-ebpf.yaml) running on
both amd64 and arm64 runners, and a `make test-ebpf` target.

Signed-off-by: Quang Nguyen <nguyenquang@microsoft.com>
@nddq nddq force-pushed the test/ebpf-program-unit-tests branch from 2a83e29 to 6fa7245 Compare March 4, 2026 22:19
@github-actions
Copy link

github-actions bot commented Mar 4, 2026

Retina Code Coverage Report

Total coverage no change

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant