Week 10 — Kernel Testing Tools¶
Goal¶
Learn the tools used to validate kernel changes: kselftest, kunit, static analysis (sparse, smatch, coccinelle), and the fuzzer syzkaller. These tools find real bugs and are expected in patch submissions.
Why This Matters¶
The netdev maintainers expect that patches have been tested. "I compiled it and it boots" is necessary but not sufficient. Running the networking selftests and static analysis before submitting a patch shows you're serious and saves reviewer time.
kselftest — Kernel Self Tests¶
The kernel ships with a test suite in tools/testing/selftests/. The networking tests
live in tools/testing/selftests/net/.
Running Network Selftests¶
cd ~/linux
# Build the networking selftests
make -C tools/testing/selftests/net
# Run them (as root, in the guest)
make -C tools/testing/selftests TARGETS=net run_tests
You can also run individual tests:
cd tools/testing/selftests/net
./run_tests.sh # Run all
./fcnal-test.sh # Run a specific test script
What to expect: Some tests will pass, some may skip (missing dependencies), some may fail on your config. Skips are fine — focus on passes and unexpected failures.
Running a Subset¶
Many test scripts accept arguments:
# Run only TCP tests
./fcnal-test.sh -t tcp
# Some tests need specific setup (namespaces, veth pairs)
# Read the test header comments for requirements
Writing a kselftest¶
If you contribute a networking feature, you're expected to include tests. A basic test:
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Test: verify that TCP connects work over loopback
source lib.sh # kselftest helper library
# Setup
setup_ns ns1 # Create a network namespace
# Test
ip netns exec $ns1 bash -c '
# Start a listener
nc -l 12345 &
sleep 0.5
echo "hello" | nc localhost 12345
wait
' && echo "PASS" || echo "FAIL"
# Cleanup
cleanup_ns $ns1
kunit — Unit Testing Framework¶
kunit is for testing small, isolated pieces of kernel code. It runs in-kernel (or in a UML build for fast iteration).
Running kunit¶
cd ~/linux
# Run all kunit tests using User Mode Linux (fast, no QEMU needed)
./tools/testing/kunit/kunit.py run
# Run only networking-related tests
./tools/testing/kunit/kunit.py run --kunitconfig=net/core/.kunitconfig
Expect: Output like:
[PASSED] net_test_example
[PASSED] skb_test_basic
...
Testing complete. Passed: 42, Failed: 0, Skipped: 3
Writing a kunit Test¶
// SPDX-License-Identifier: GPL-2.0
#include <kunit/test.h>
#include <linux/skbuff.h>
static void skb_alloc_test(struct kunit *test)
{
struct sk_buff *skb;
skb = alloc_skb(1024, GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, skb);
KUNIT_EXPECT_EQ(test, skb->len, 0);
skb_put(skb, 100);
KUNIT_EXPECT_EQ(test, skb->len, 100);
kfree_skb(skb);
}
static struct kunit_case my_test_cases[] = {
KUNIT_CASE(skb_alloc_test),
{}
};
static struct kunit_suite my_test_suite = {
.name = "my_net_tests",
.test_cases = my_test_cases,
};
kunit_test_suite(my_test_suite);
MODULE_LICENSE("GPL");
Static Analysis¶
sparse — Kernel Semantic Checker¶
sparse checks for common C mistakes, especially around address spaces (user vs kernel pointers), locking, and endianness.
# Install
sudo apt install -y sparse
# Run during build
make C=1 net/ipv4/tcp.o # Check a single file
make C=1 M=net/ipv4/ # Check a directory
make C=2 net/ipv4/tcp.o # Force recheck even if .o is up to date
Common sparse warnings you'll see:
warning: incorrect type in assignment (different address spaces)
warning: symbol 'xxx' was not declared. Should it be static?
warning: context imbalance - unexpected unlock
smatch — Advanced Static Analyzer¶
smatch finds deeper bugs: null pointer dereferences, buffer overflows, logic errors.
# Install
cd ~
git clone https://github.com/error27/smatch.git
cd smatch
make
sudo make install
# Run
cd ~/linux
make CHECK="smatch -p=kernel" C=1 net/ipv4/tcp.o
Coccinelle — Semantic Patching¶
Coccinelle is a tool for finding and transforming C code patterns. The kernel ships with coccinelle scripts (semantic patches) that find common issues:
# Install
sudo apt install -y coccinelle
# Run all kernel coccinelle checks
make coccicheck MODE=report
# Run on a specific directory
make coccicheck MODE=report M=net/ipv4/
Why this matters for contributors: Coccinelle is often used for tree-wide cleanup patches. A common first contribution is running a coccinelle script, finding issues, and sending fixes.
checkpatch.pl — Style and Convention Checker¶
You already saw this in Week 7. Run it on every patch before sending:
# Check a patch file
./scripts/checkpatch.pl 0001-my-change.patch
# Check a file directly
./scripts/checkpatch.pl --file net/ipv4/tcp.c
# Check your staged changes
git diff --cached | ./scripts/checkpatch.pl --stdin
Treat checkpatch errors as blockers. Warnings are worth fixing too — reviewers will ask about them.
syzkaller — Kernel Fuzzer (Overview)¶
syzkaller is Google's kernel fuzzer. It automatically generates sequences of system calls and looks for crashes, hangs, and memory bugs. It has found thousands of networking bugs.
You won't run syzkaller this week — it requires significant setup (multiple VMs, a corpus, etc.). But you should know it exists because:
- It generates bug reports on https://syzkaller.appspot.com/
- These reports contain reproducers you can use to find and fix bugs
- Fixing syzkaller bugs is a legitimate contribution path
A syzkaller report typically includes: - A C reproducer program - The crash log - The guilty commit (if identified) - A stack trace
You can run the reproducer in your QEMU setup to reproduce the bug, then work on a fix.
Putting It All Together: Pre-Submission Checklist¶
Before sending any patch, run:
# 1. Build cleanly
make -j$(nproc)
# 2. Static analysis
make C=1 net/ipv4/your_changed_file.o
# 3. checkpatch
./scripts/checkpatch.pl your-patch.patch
# 4. Boot test in QEMU
# Boot, verify basic networking works
# 5. Run relevant selftests
make -C tools/testing/selftests TARGETS=net run_tests
# 6. If applicable, run kunit
./tools/testing/kunit/kunit.py run
Exercises¶
- Build and run the networking selftests in your QEMU guest. Note which pass, skip, and fail. Investigate one failure.
- Run
make C=1 net/ipv4/tcp.oandmake C=1 net/ipv4/tcp_input.o. Are there any sparse warnings? (In mainline, there usually aren't — the code is well-maintained.) - Run
make coccicheck MODE=report M=net/(this takes a while). Read a few of the results. Do any look like real bugs? - Go to https://syzkaller.appspot.com/upstream and find a networking bug report with a C reproducer. Download the reproducer and try to understand what it does.
- Run kunit with
./tools/testing/kunit/kunit.py run. How many tests pass? Explorenet/core/.kunitconfigto see what's being tested.
What's Next¶
Next week: the git workflow and patch submission process. You'll learn git format-patch, git send-email, b4, and the netdev-specific conventions.