Skip to content

test: add unit tests for legacy ADS mode bpf programs#1765

Open
Aryanburnwal05 wants to merge 2 commits into
kmesh-net:mainfrom
Aryanburnwal05:test-ads-bpf
Open

test: add unit tests for legacy ADS mode bpf programs#1765
Aryanburnwal05 wants to merge 2 commits into
kmesh-net:mainfrom
Aryanburnwal05:test-ads-bpf

Conversation

@Aryanburnwal05

Copy link
Copy Markdown

Added BPF_PROG_TEST_RUN unit tests for the cgroup_sock and sockops eBPF programs in legacy ADS mode (test/bpf_ut/bpftest/ads_test.go).

Also had to add a custom loader (load_bpf_prog_to_cgroup_ads) to skip loading heavy tail-call programs like cluster_manager during testing, otherwise the eBPF verifier hits complexity limits and throws an invalid argument error due to the massive unrolled loops. With this bypass the core attach logic and map interactions get tested in isolation perfectly.

Tests passed locally :-
go test -v ./test/bpf_ut/bpftest -run TestBPF/Ads

Signed-off-by: Aryan Burnwal <burnwalaryan922@gmail.com>
Copilot AI review requested due to automatic review settings June 18, 2026 07:02
@kmesh-bot kmesh-bot requested review from YaoZengzeng and lec-bit June 18, 2026 07:02
@kmesh-bot

Copy link
Copy Markdown
Collaborator

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign yaozengzeng for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces comprehensive unit testing for legacy ADS mode eBPF programs. By implementing a custom loader, the changes allow for testing core attach logic and map interactions in isolation, effectively bypassing verifier constraints associated with complex tail-call structures.

Highlights

  • Unit Testing: Added BPF_PROG_TEST_RUN unit tests for cgroup_sock and sockops eBPF programs in legacy ADS mode.
  • Custom Loader: Implemented a custom loader to bypass heavy tail-call programs, preventing eBPF verifier complexity limit errors.
  • Build Integration: Updated the build script to compile the new test objects and registered the tests in the main test suite.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.


In kernels deep where programs run, / We test the code to have some fun. / With loaders smart we skip the weight, / And keep the verifier from its fate.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces unit tests for the ADS BPF programs, specifically targeting cgroup_sock and sockops functionalities. It adds test source files in C, updates the build script to compile them, and implements Go-based test runners to verify the behavior of the km_manage map. The reviewer feedback highlights critical reliability issues in the Go test code, including potential nil pointer dereferences when loading BPF programs and socket leaks caused by not closing connections returned by net.DialTimeout.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +56 to +60
lk, err := link.AttachCgroup(link.CgroupOptions{
Path: cgroupPath,
Attach: spec.Programs[progName].AttachType,
Program: coll.Programs[progName],
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The program progName is retrieved from spec.Programs and coll.Programs without checking if it exists. If the program is missing, this will cause a nil pointer dereference panic. We should check if the program exists and close the collection before failing the test.

Suggested change
lk, err := link.AttachCgroup(link.CgroupOptions{
Path: cgroupPath,
Attach: spec.Programs[progName].AttachType,
Program: coll.Programs[progName],
})
progSpec, ok := spec.Programs[progName]
if !ok {
coll.Close()
t.Fatalf("Program %s not found in spec", progName)
}
prog := coll.Programs[progName]
if prog == nil {
coll.Close()
t.Fatalf("Program %s not found in collection", progName)
}
lk, err := link.AttachCgroup(link.CgroupOptions{
Path: cgroupPath,
Attach: progSpec.AttachType,
Program: prog,
})

Comment thread test/bpf_ut/bpftest/ads_test.go Outdated
Comment on lines +86 to +98
var prog *ebpf.Program
for _, p := range coll.Programs {
if p.Type() == ebpf.SockOps {
prog = p
break
}
}

lk, err := link.AttachCgroup(link.CgroupOptions{
Path: cgroupPath,
Attach: ebpf.AttachCGroupSockOps,
Program: prog,
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If no program of type ebpf.SockOps is found in the collection, prog will remain nil. Passing a nil program to link.AttachCgroup can cause a panic or failure. We should check if prog is nil and close the collection before failing the test.

Suggested change
var prog *ebpf.Program
for _, p := range coll.Programs {
if p.Type() == ebpf.SockOps {
prog = p
break
}
}
lk, err := link.AttachCgroup(link.CgroupOptions{
Path: cgroupPath,
Attach: ebpf.AttachCGroupSockOps,
Program: prog,
})
var prog *ebpf.Program
for _, p := range coll.Programs {
if p.Type() == ebpf.SockOps {
prog = p
break
}
}
if prog == nil {
coll.Close()
t.Fatal("No SockOps program found in collection")
}
lk, err := link.AttachCgroup(link.CgroupOptions{
Path: cgroupPath,
Attach: ebpf.AttachCGroupSockOps,
Program: prog,
})

Comment thread test/bpf_ut/bpftest/ads_test.go Outdated
Comment on lines +130 to +131
enableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperEnableControl))
net.DialTimeout("tcp4", enableAddr, 2*time.Second)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

net.DialTimeout returns a net.Conn and an error. Ignoring the returned connection leaks the socket/file descriptor if the connection succeeds. We should close the connection if it was successfully established.

Suggested change
enableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperEnableControl))
net.DialTimeout("tcp4", enableAddr, 2*time.Second)
enableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperEnableControl))
if conn, err := net.DialTimeout("tcp4", enableAddr, 2*time.Second); err == nil {
conn.Close()
}

Comment thread test/bpf_ut/bpftest/ads_test.go Outdated
Comment on lines +152 to +153
disableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperDisableControl))
net.DialTimeout("tcp4", disableAddr, 2*time.Second)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

net.DialTimeout returns a net.Conn and an error. Ignoring the returned connection leaks the socket/file descriptor if the connection succeeds. We should close the connection if it was successfully established.

Suggested change
disableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperDisableControl))
net.DialTimeout("tcp4", disableAddr, 2*time.Second)
disableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperDisableControl))
if conn, err := net.DialTimeout("tcp4", disableAddr, 2*time.Second); err == nil {
conn.Close()
}

Comment thread test/bpf_ut/bpftest/ads_test.go Outdated
Comment on lines +194 to +195
enableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperEnableControl))
net.DialTimeout("tcp4", enableAddr, 2*time.Second)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

net.DialTimeout returns a net.Conn and an error. Ignoring the returned connection leaks the socket/file descriptor if the connection succeeds. We should close the connection if it was successfully established.

Suggested change
enableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperEnableControl))
net.DialTimeout("tcp4", enableAddr, 2*time.Second)
enableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperEnableControl))
if conn, err := net.DialTimeout("tcp4", enableAddr, 2*time.Second); err == nil {
conn.Close()
}

Comment thread test/bpf_ut/bpftest/ads_test.go Outdated
Comment on lines +228 to +229
disableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperDisableControl))
net.DialTimeout("tcp4", disableAddr, 2*time.Second)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

net.DialTimeout returns a net.Conn and an error. Ignoring the returned connection leaks the socket/file descriptor if the connection succeeds. We should close the connection if it was successfully established.

Suggested change
disableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperDisableControl))
net.DialTimeout("tcp4", disableAddr, 2*time.Second)
disableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperDisableControl))
if conn, err := net.DialTimeout("tcp4", disableAddr, 2*time.Second); err == nil {
conn.Close()
}

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the existing eBPF unit test suite under test/bpf_ut/bpftest to cover legacy ADS-mode programs by adding new Go tests and build steps for ADS-specific eBPF test objects.

Changes:

  • Add ADS test entrypoint in the top-level BPF test runner.
  • Introduce ADS-specific Go tests that load/attach ADS cgroup_sock and sockops programs and validate km_manage map behavior.
  • Extend the test build script to compile new ADS eBPF test object files.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/bpf_ut/build_bpf_ut_tests.sh Builds new ADS eBPF test objects (ads_cgroup_sock_test.o, ads_sockops_test.o).
test/bpf_ut/bpftest/bpf_test.go Registers the new Ads subtest suite under TestBPF.
test/bpf_ut/bpftest/ads_test.go Adds ADS-mode tests and custom loaders that skip heavy tail-call programs.
test/bpf_ut/ads_sockops_test.c Test object source that includes ADS sockops.c.
test/bpf_ut/ads_cgroup_sock_test.c Test object source that includes ADS cgroup_sock.c.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +56 to +64
lk, err := link.AttachCgroup(link.CgroupOptions{
Path: cgroupPath,
Attach: spec.Programs[progName].AttachType,
Program: coll.Programs[progName],
})
if err != nil {
coll.Close()
t.Fatalf("Failed to attach cgroup: %v", err)
}
Comment thread test/bpf_ut/bpftest/ads_test.go Outdated
Comment on lines +86 to +103
var prog *ebpf.Program
for _, p := range coll.Programs {
if p.Type() == ebpf.SockOps {
prog = p
break
}
}

lk, err := link.AttachCgroup(link.CgroupOptions{
Path: cgroupPath,
Attach: ebpf.AttachCGroupSockOps,
Program: prog,
})
if err != nil {
coll.Close()
t.Fatalf("Failed to attach cgroup: %v", err)
}
return coll, lk
Comment on lines +106 to +109
func testAds(t *testing.T) {
t.Run("CgroupSock", testAdsCgroupSock)
t.Run("SockOps", testAdsSockOps)
}
Signed-off-by: Aryan Burnwal <burnwalaryan922@gmail.com>
Copilot AI review requested due to automatic review settings June 18, 2026 07:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Comment on lines +167 to +174
iter = kmManageMap.Iterate()
count = 0
for iter.Next(&key, &value) {
count++
}
if count != 0 {
t.Fatalf("Expected 0 entry in km_manage map, but got %d", count)
}
Comment on lines +247 to +255
iter = kmManageMap.Iterate()
count = 0
for iter.Next(&keyBytes, &value) {
count++
}

if count != 0 {
t.Fatalf("Expected 0 entry in km_manage map, but got %d", count)
}
Comment on lines +96 to +106
prog := coll.Programs["sockops_prog"]
if prog == nil {
coll.Close()
t.Fatal("No SockOps program found in collection")
}

lk, err := link.AttachCgroup(link.CgroupOptions{
Path: cgroupPath,
Attach: ebpf.AttachCGroupSockOps,
Program: prog,
})
Comment on lines +38 to +40
func load_bpf_prog_to_cgroup_ads(t *testing.T, objFilePath string, progName string, cgroupPath string) (*ebpf.Collection, link.Link) {
spec := loadAndPrepSpec(t, path.Join(*testPath, objFilePath))

Comment on lines +78 to +80
func load_bpf_2_cgroup_ads(t *testing.T, objFilePath string, cgroupPath string) (*ebpf.Collection, link.Link) {
spec := loadAndPrepSpec(t, path.Join(*testPath, objFilePath))

Comment on lines +114 to +117
func testAds(t *testing.T) {
t.Run("CgroupSock", testAdsCgroupSock)
t.Run("SockOps", testAdsSockOps)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants