Linux kernel Virtio-net test research
-
./tools/testing/kunit/kunit.py run "virt*"
- run all kunit tests that starts withvirt
-
./tools/testing/kunit/kunit.py run --arch=x86_64
- run on other architectures using qemu -
./tools/testing/kunit/kunit.py run --arch=s390 --cross_compile=s390x-linux-gnu
- specify toolchain for compilation -
scripts/decode_stacktrace.sh .kunit/vmlinux .kunit < .kunit/test.log | tee .kunit/decoded.log | ./tools/testing/kunit/kunit.py parse
- get more detailed, advantage is that stacktrace contains filenames of the functions -
qemu-system-x86_64 -kernel ./arch/x86_64/boot/bzImage -initrd ramdisk.img -m 4G
- run kernel image in qemu -
mkinitramfs -o ramdiks.img
- create ramfs -
unmkinitramfs <file> <target directory>
- unwrap ramfs into a dircetory -
mount -t debugfs none /sys/kernel/debug
- mount debugfs and get the coverage gdna gdno files -
lcov -t "virtio_test" -o coverage.info -c -d gcovFiles
- get coverage from gcda & gcno files which lay in gcovFiles directory -
genhtml -o coverage.result coverage.info
- generates coverage visualisation in directory coverage.results
-
To run kuint tests for
virtio_net
add configuration in filelinux/drivers/net/Kconfig
config VIRTIO_NET_TEST tristate "Test for virtio_net" if !KUNIT_ALL_TESTS depends on KUNIT=y select NETDEVICES select NET_CORE select VIRTIO select VIRTIO_NET select NET default KUNIT_ALL_TESTS
-
Select
will add the dependencies and they will compile with ourVIRTIO_NET_TEST
, also we add our file with test ot the configVIRTIO_NET_TEST
inlinux/drivers/net/Makefile
obj-$(CONFIG_VIRTIO_NET_TEST) += virtio_net.o
-
Finally enable test configuration in
linux/.kunit/.config
andlinux/.kunit/.config
. Note that we should enable the configuration in both files because,kunit.py
script parses both the existing.config
and the.kunitconfig
files to ensure that.config
is a superset of.kunitconfig
CONFIG_VIRTIO_NET_TEST=y
-
Configs for kernel address sanitizer
CONFIG_KASAN=y CONFIG_KASAN_VMALLOC=y CONFIG_KASAN_INLINE=y CONFIG_KASAN_GENERIC=y CONFIG_STACKTRACE=y
-
Configs for gdb debugger
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_DEBUG_KERNEL=y
-
Confgis for gcov to get coverage data for kernel
CONFIG_DEBUG_FS=y CONFIG_GCOV_KERNEL=y
-
Configs for virtio-fs
CONFIG_VIRTIO=y CONFIG_VIRTIO_FS=y CONFIG_DAX=y CONFIG_FS_DAX=y CONFIG_DAX_DRIVER=y CONFIG_ZONE_DEVICE=y
-
Run test isolated using arg
--run_isolated "test"
-
./tools/testing/kunit/kunit.py run --arch=x86_64 --run_isolated "test"
-
In order to get coverage .gcno .gcda files, we need to compile and run the kernel.
-
We can do it manually installing compiled kernel into our OS, or run a VM with compiled kernel using qemu.
-
We want virtio_net.c to be profiled with
gcov
, so we add these line inlinux/drivers/net/Makefile
GCOV_PROFILE_virtio_net.o := y
-
Also to run with gcov we should add appropriate configs to
.config
.CONFIG_DEBUG_FS=y CONFIG_GCOV_KERNEL=y
-
Compile the kernel and run in VM
-
In guest VM terminal run next command to get the appropiate files
mount -t debugfs none /sys/kernel/debug
-
After that you can find .gcda file in /sys/kernel/debug/gcov
-
The .gcno file must be available after compiling the kernel
-
Compile the kernel with required configs on
CONFIG_VIRTIO=y CONFIG_VIRTIO_FS=y CONFIG_DAX=y CONFIG_FS_DAX=y CONFIG_DAX_DRIVER=y CONFIG_ZONE_DEVICE=y
-
After compilation finishes we can find bzImage with path
arch/x86/boot/bzImage
which is a binary file -
Create ramfs
ramdisk.img
file with commandmkinitramfs -o ramdiks.img
and keep it in one directory withbzImage
-
Download, install and open Virtual Machine Manager
-
Click
Create new instance
and choose manual installaion -
As operating system choose Generic linux 2020
-
Memory 4096, and cpu 2 (recommended parameters)
-
Disable storage for this virtual machine
-
Name VM and enable option
Customize configuration before isntall
-
In
Memory
section enable Shared Memory option -
In
Boot options
section open kernel manual boot and clickBrowse
for Kernel Path -
In opened menu click
Add pool
and choose the directory wherebzImage
andramdisk.img
already lay -
Then from your new pool choose file
bzImage
, and click choose Volume -
Click
Browse
for initrd path, and chooseramdisk.img
from the same pool, clickapply
-
Click
add Hardware
in the left bottom corner, choose sectionfilesystem
, choosevirtiofs
, choose path to the future shared directory, and also give it a name intarget path
field -
Click start installation, after which you should see terminal of the VM
-
mount -t virtiofs <name> <path where you want to mount shared directory>
- run this command to mount virtiofs shared folder -
Now we can transfer files from
host machine
toVM
and vice versa
-
make menuconfig
- creates .config file in linux directory -
Add next configs in order to compile with kunit test, gcov and virtiofs
CONFIG_KUNIT=y CONFIG_KUNIT_ALL_TESTS=y CONFIG_KUNIT_DEBUGFS=y CONFIG_KUNIT_TEST=y CONFIG_KUNIT_DEFAULT_ENABLED=y CONFIG_VIRTIO=y CONFIG_VIRTIO_FS=y CONFIG_DAX=y CONFIG_FS_DAX=y CONFIG_DAX_DRIVER=y CONFIG_ZONE_DEVICE=y CONFIG_DEBUG_FS=y CONFIG_GCOV_KERNEL=y CONFIG_GCOV_PROFILE_FTRACE=y
-
If you have error like this on ubuntu
CC certs/system_keyring.o make[2]: *** No rule to make target 'debian/canonical-certs.pem', needed by 'certs/x509_certificate_list'. Stop. make[1]: *** [scripts/Makefile.build:504: certs] Error 2 make: *** [Makefile:2021: .] Error 2
- Then this commands can help
scripts/config --disable SYSTEM_TRUSTED_KEYS
scripts/config --disable SYSTEM_REVOCATION_KEYS
- After running both commands above, run
make
and tabenter
for both new options
Classes
Classes are not a construct that is built into the C programming language; however, it is an easily derived concept. Accordingly, in most cases, every project that does not use a standardized object oriented library (like GNOME’s GObject) has their own slightly different way of doing object oriented programming; the Linux kernel is no exception.
The central concept in kernel object oriented programming is the class. In the kernel, a class is a struct that contains function pointers. This creates a contract between implementers and users since it forces them to use the same function signature without having to call the function directly. To be a class, the function pointers must specify that a pointer to the class, known as a class handle, be one of the parameters. Thus the member functions (also known as methods) have access to member variables (also known as fields) allowing the same implementation to have multiple instances.
A class can be overridden by child classes by embedding the parent class in the child class. Then when the child class method is called, the child implementation knows that the pointer passed to it is of a parent contained within the child. Thus, the child can compute the pointer to itself because the pointer to the parent is always a fixed offset from the pointer to the child. This offset is the offset of the parent contained in the child struct.
Introduction to virtio-networking and vhost-net
Booting custom linux kernel in qemu
List of maintainers and how to submit kernel changes
Kcov code coverage for fuzzing
Securely booting confidential VMs with encrypting disk
linux kernel testing and debugging
virtio net failover introduction
deep into vhost, virtio-networking
-
cd ~
-
mkdir workspace
-
cd workspace
-
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.3.tar.xz
-
tar xvf linux-5.10.3.tar.xz
-
wget https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/11.3.0/x86_64-gcc-11.3.0-nolibc-x86_64-linux.tar.xz
-
tar xvf x86_64-gcc-11.3.0-nolibc-x86_64-linux.tar.xz
-
cd linux-5.10.3
-
./tools/testing/kunit/kunit.py run
-
cd drivers/net
-
touch virtio_net_test.c virtio_net_test.h
-
cd ../..