Tempesta Technologies
  • Home
  • Tempesta FW
    • Features
      • Web acceleration
      • Load balancing
      • Application performance monitoring
    • Performance
    • How it works
    • Deployment
    • Support
    • Knowledge base
  • Services
    • Software development
      • High performance
      • Networking
      • Databases
      • Linux kernel
      • Machine learning
      • How we work
      • Case studies
    • Performance analysis
    • Network security
      • DDoS protection
      • Application security
      • Cryptography
      • Security assessment
      • How we work
      • Case Studies
  • Solutions
    • CDN
  • Blog
  • Company
    • Research
    • Careers
    • Contact
Tempesta Technologies

Testing

Tempesta Kernel Emulation Framework for Unit Testing🔗

Ktest is just a set of C headers with very close hierarchy to the original Linux, but much simplified and combined with some additional helpers. This headers provide only most usable stubs for real kernel headers to launch a relatively standalone logic under the test.

The good examples of the code suitable for the testing with the framework are data strucures like HTrie, mathematic functions like APM maths or multi-precission math.

The framework emphasises simplicity to make debugging of complicated and standalone logic as productive as possible: (re-)run quickly, easily traced with gdb and valgrind.

What about KUnit?🔗

KUnit, available in the mainstream kernels at linux/tools/testing/kunit/, is essentially a bunch of Python scripts around User-mode Linux (UML). UML is also in the mainstream kernel and one just needs to buid the kernel for um architecture.

The most important thing bout KUnit/UML is that this is a fully functional Linux kernel, so you need a fake filesystem, login to the console and so on. It can be debugged with gdb (see example), but special steps are required. All in all, this can be and should be treated as a virtualization solution.

Tests are developed for KUnit/UML as Linux kernel modules (this LWN article provides a good intro into the framework), which is somewhat close to current tempesta_fw/t/unit framework operation. As discussed in another LWN article the framework emulates device initialization, making tests (re-)run faster than in KVM, which we use. Ext4 tests, as one of the good use case for the framework, require a filesystem anyhow and they do required significant underlaying layers (block IO) emulation. This is example of non-standalone logic, which can not be tested with our ktest framework.

Thus, KUnit/UML is closer to tempesta_fw/t/unit tests than to ktest. In future, if tempesta_fw/t/unit grows or become more complex, e.g. require the TCP stack, it could make sense to port tempesta_fw/t/unit to KUnit/UML.

Linux Kernel Library🔗

Linux Kernel Library (see also LWN anritcle) build the Linux kernel as a library, so a user space application can use the Linux API. Unfortunately, the project isn’t mainstream and it looks like an overkill for us to apply and support the Tempesta patch for the LKL kernel and build the separate kernel just for the couple tests for the standalone logic.

NUMA test environment.🔗

Debugging some parts of code requires setups which contain more than one NUMA node. Here is an instruction on how to create a VM with NUMA support.

Install prerequisites🔗

sudo apt install qemu-kvm

sudo apt install cloud-image-utils

Create VM🔗

Download image🔗

wget https://cloud-images.ubuntu.com/releases/noble/release/ubuntu-24.04-server-cloudimg-amd64.img

Resize image🔗

qemu-img resize ubuntu-24.04-server-cloudimg-amd64.img +40G

Create a user data and place it on the disk image.🔗

Standard cloud image is user agnostic. To save credentials and other user information we need to create yet another disk image and connect it to our VM.

$ cat > user-data <<EOF
#cloud-config
password: <password>
chpasswd: { expire: False }
ssh_pwauth: True
EOF

cloud-localds seed.img user-data

Run VM with NUMA🔗

Run VM with distributive kernel.🔗

qemu-system-x86_64 \
 -enable-kvm \
 -cpu host \
 -m 8G \
 -drive if=virtio,format=qcow2,file=ubuntu-24.04-server-cloudimg-amd64.img \
 -drive if=virtio,format=raw,file=seed.img \
 -smp 16,sockets=4,cores=4,threads=1,maxcpus=16 \
 -object memory-backend-ram,size=2G,id=m0 \
 -object memory-backend-ram,size=2G,id=m1 \
 -object memory-backend-ram,size=2G,id=m2 \
 -object memory-backend-ram,size=2G,id=m3 \
 -numa node,nodeid=0,memdev=m0,cpus=0-3 \
 -numa node,nodeid=1,memdev=m1,cpus=4-7 \
 -numa node,nodeid=2,memdev=m2,cpus=8-11 \
 -numa node,nodeid=3,memdev=m3,cpus=12-15 \
 -device virtio-net-pci,netdev=net0 \
 -netdev user,id=net0,hostfwd=tcp::2222-:22 \
 -nographic 

Credentials🔗

Login: ubuntu

Password: <password from the user-data file>

SSH access🔗

ssh -p 2222 ubuntu@localhost

Check NUMA🔗

On the VM run: sudo apt install numactl

numactl -H

Should see NUMA configuration: 4 nodes with 4 CPUs and 2G memory as for configuration described above.

Build custom kernel🔗

Inside created VM install build tools, download sources and patches.

Perform standard build commands.

make -j $(nproc)

make install

Then copy bzImage and initrd.img to the host.

On the host run:

scp -P 2222 ubuntu@localhost:linux-<version>/arch/x86/boot/bzImage .

scp -P 2222 ubuntu@localhost:/boot/initrd.img-<version> .

Run VM with custom kernel.🔗

qemu-system-x86_64 \
 -enable-kvm \
 -cpu host \
 -m 8G \
 -drive if=virtio,format=qcow2,file=ubuntu-24.04-server-cloudimg-amd64.img \
 -drive if=virtio,format=raw,file=seed.img \
 -smp 16,sockets=4,cores=4,threads=1,maxcpus=16 \
 -object memory-backend-ram,size=2G,id=m0 \
 -object memory-backend-ram,size=2G,id=m1 \
 -object memory-backend-ram,size=2G,id=m2 \
 -object memory-backend-ram,size=2G,id=m3 \
 -numa node,nodeid=0,memdev=m0,cpus=0-3 \
 -numa node,nodeid=1,memdev=m1,cpus=4-7 \
 -numa node,nodeid=2,memdev=m2,cpus=8-11 \
 -numa node,nodeid=3,memdev=m3,cpus=12-15 \
 -device virtio-net-pci,netdev=net0 \
 -netdev user,id=net0,hostfwd=tcp::2222-:22 \
 -kernel bzImage \
 -initrd initrd.img-<version>
 -nographic \
 -append "root=/dev/vda1 console=ttyS0" \
 -serial mon:stdio

Further development🔗

At the moment we have only 3 types of tests and they are well covered by the current frameworks:

  1. The most developed and the largest framework is the functional test Python framework (https://github.com/tempesta-tech/tempesta-test/). This type of the tests are most beneficial because (1) they emulate cases very close to the real life scenatios and (2) they test quite a bunch of logic at once.

  2. Complex standalone logic (HTrie, TLS, math in tempesta_fw/t/unit/user_space/) are covered with the ktest.

  3. Linux kernel module for unit tests (https://github.com/tempesta-tech/tempesta/tree/master/tempesta_fw/t). At the moment the module is quite small and some of the tests, e.g. HTTP parser or TfwStr, are likely to be moved to ktest framework. However, at some point we might need to develop tests which (1) require to reproduce specific and rare scenarios unreachable for the functional tests framework and (2) depend on significant Linux kernel logic unmockable by the ktest. At this moment we might need to use either LKL or KUnit/UML.


Share this article
  • Home
  • Requirements
  • Installation
    • Install from packages
    • Install from Sources
  • Configuration
    • Migration from Nginx
    • On the fly Reconfiguration
    • Handling clients
    • Backend servers
    • Scheduling and Load Balancing
    • Caching Responses
    • Non Idempotent Requests
    • Modify HTTP Messages
    • Virtual hosts and locations
    • Sticky Cookie
    • HTTP tables
    • HTTP security
    • Header Via
    • Health monitor
    • Tempesta TLS
    • Vhost Confusion
    • Traffic Filtering by Fingerprints
    • Access Log Analytics
  • Run and stop
  • Application Performance Monitoring
    • Performance statistics
    • Servers statistics
  • Use cases
    • Clouds
    • High availability
    • DDoS mitigation
    • Web security
    • WAF acceleration
    • Best practices
    • WordPress tips and tricks
  • Performance
    • Hardware virtualization performance
    • HTTP cache performance
    • HTTP transactions performance
    • HTTPS performance
    • HTTP2 streams prioritization
  • Bot Protection
    • Tempesta Webshield
    • Setup and Run The Webshield
    • Webshield Configuration
    • Webshield Detectors
    • Webshield Observability
    • Webshield Use Cases
  • Contributing
    • Report issues and send patches
    • Development guidelines
    • Memory safety guideline
    • Debugging and troubleshooting
    • Prepare a new release
    • Testing
    • QTCreator project

Powered by Tempesta FW

Stay up to date with our latest developments

Useful Links

Home
Blog

Tempesta® FW

Features
Performance
Deployment
Support
Knowledge Base

Services

Software Development
Performance analysis
Network Security

Solutions

CDN

Company

Research
Careers
Contact