test: Add memory/passt test cases

These show a summary of memory usage in kernel and userspace with
different port forwarding configurations, details of userspace usage
using 'nm' (passt only uses statically allocated memory), and details
of kernel memory from slab reporting facilities.

This adds a new test image, mbuto.mem.img, with harcoded IPv4 and
IPv6 addresses and routes, and just the tools we need to start and
stop passt, to report from /proc/slabinfo, /proc/meminfo, and to
print and parse symbol sizes using nm(1).

passt can't pivot_root() for sandboxing purposes on ramfs, so we need
to create another filesystem and chroot into it, first.

We don't want to use pane context functions, as we're checking memory
usage for sockets: resort to screen-scraping.

Configure a dummy interface to provide passt with an appearance of
working IPv4 and IPv6 connectivity, contributed by David.

Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
Stefano Brivio 2022-10-31 12:20:59 +01:00
parent ce2a0a5bb4
commit 40fc9e6e7b
6 changed files with 289 additions and 1 deletions

View file

@ -55,7 +55,7 @@ UBUNTU_IMGS = $(UBUNTU_OLD_IMGS) $(UBUNTU_NEW_IMGS)
DOWNLOAD_ASSETS = mbuto \ DOWNLOAD_ASSETS = mbuto \
$(DEBIAN_IMGS) $(FEDORA_IMGS) $(OPENSUSE_IMGS) $(UBUNTU_IMGS) $(DEBIAN_IMGS) $(FEDORA_IMGS) $(OPENSUSE_IMGS) $(UBUNTU_IMGS)
TESTDATA_ASSETS = small.bin big.bin medium.bin TESTDATA_ASSETS = small.bin big.bin medium.bin
LOCAL_ASSETS = mbuto.img QEMU_EFI.fd \ LOCAL_ASSETS = mbuto.img mbuto.mem.img QEMU_EFI.fd \
$(DEBIAN_IMGS:%=prepared-%) $(FEDORA_IMGS:%=prepared-%) \ $(DEBIAN_IMGS:%=prepared-%) $(FEDORA_IMGS:%=prepared-%) \
$(UBUNTU_NEW_IMGS:%=prepared-%) \ $(UBUNTU_NEW_IMGS:%=prepared-%) \
nsholder guest-key guest-key.pub \ nsholder guest-key guest-key.pub \
@ -76,6 +76,9 @@ guest-key guest-key.pub:
mbuto.img: passt.mbuto mbuto guest-key.pub $(TESTDATA_ASSETS) mbuto.img: passt.mbuto mbuto guest-key.pub $(TESTDATA_ASSETS)
./mbuto/mbuto -p ./$< -c lz4 -f $@ ./mbuto/mbuto -p ./$< -c lz4 -f $@
mbuto.mem.img: passt.mem.mbuto mbuto ../passt.avx2
./mbuto/mbuto -p ./$< -c lz4 -f $@
nsholder: nsholder.c nsholder: nsholder.c
$(CC) $(CFLAGS) -o $@ $^ $(CC) $(CFLAGS) -o $@ $^

View file

@ -81,3 +81,33 @@ layout_pasta_simple() {
sleep 1 sleep 1
} }
# layout_memory() - Screen-scraped panes for memory usage tests, big guest pane
layout_memory() {
sleep 3
tmux kill-pane -a -t 0
cmd_write 0 clear
tmux split-window -h -l '35%' -t passt_test
PANE_GUEST=0
PANE_INFO=1
get_info_cols
tmux send-keys -l -t ${PANE_INFO} 'while cat '"$STATEBASE/log_pipe"'; do :; done'
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T "test log"
if context_exists guest; then
pane_watch_contexts ${PANE_GUEST} guest guest
else
tmux pipe-pane -O -t ${PANE_GUEST} "cat >> ${LOGDIR}/pane_guest.log"
tmux select-pane -t ${PANE_GUEST} -T "guest"
fi
info_layout "memory usage"
sleep 1
}

View file

@ -13,6 +13,8 @@
# Copyright (c) 2022 Red Hat GmbH # Copyright (c) 2022 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com> # Author: Stefano Brivio <sbrivio@redhat.com>
INITRAMFS_MEM="${BASEPATH}/mbuto.mem.img"
# setup_distro() - Set up pane layout for distro tests # setup_distro() - Set up pane layout for distro tests
setup_distro() { setup_distro() {
layout_host layout_host
@ -25,6 +27,20 @@ setup_pasta_options() {
layout_pasta_simple layout_pasta_simple
} }
# setup_memory() - Start qemu in guest pane, and passt in passt context
setup_memory() {
layout_memory
pane_or_context_run guest 'qemu-system-$(uname -m)' \
' -machine accel=kvm' \
' -m '${VMEM}' -cpu host -smp '${VCPUS} \
' -kernel ' "/boot/vmlinuz-$(uname -r)" \
' -initrd '${INITRAMFS_MEM}' -nographic -serial stdio' \
' -nodefaults' \
' -append "console=ttyS0 mitigations=off apparmor=0"' \
" -pidfile ${STATESETUP}/qemu.pid"
}
# teardown_distro() - Nothing to do, yet # teardown_distro() - Nothing to do, yet
teardown_distro() { teardown_distro() {
: :
@ -36,3 +52,7 @@ teardown_pasta_options() {
teardown_context_watch ${PANE_PASST} passt teardown_context_watch ${PANE_PASST} passt
} }
# teardown_passt() - Kill qemu with ^C, remove passt PID file
teardown_memory() {
kill $(cat "${STATESETUP}/qemu.pid")
}

187
test/memory/passt Normal file
View file

@ -0,0 +1,187 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/memory/passt - Show memory usage of passt in kernel and userspace
#
# Copyright (c) 2022 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
gtools sed cat diff nm sort kill tee head tail chroot unshare mount mkdir cp
def meminfo_row
gout DIFF meminfo_diff /tmp/meminfo.before /tmp/meminfo.after __WHAT__
tl __NAME__
td __DIFF__ 3 0 0
endef
def meminfo_reverse_row
gout DIFF meminfo_diff /tmp/meminfo.after /tmp/meminfo.before __WHAT__
tl __NAME__
td __DIFF__ 3 0 0
endef
def nm_row
gout SIZE nm_size /tmp/nm.size __WHAT__
tl __WHAT__
td __SIZE__ 6 0 0
endef
def slab_row
gout COUNT slab_diff_count /tmp/slabinfo.before /tmp/slabinfo.after __WHAT__
gout SIZE slab_size /tmp/slabinfo.before __WHAT__
gout DIFF slab_diff_size /tmp/slabinfo.before /tmp/slabinfo.after __WHAT__
tl __WHAT__
td __COUNT__ 0 0 0
td __SIZE__ 0 0 0
td __DIFF__ 6 0 0
endef
def start_stop_diff
guest sed /proc/slabinfo -ne 's/^\([^ ]* *[^ ]* *[^ ]* *[^ ]*\).*/\\\1/p' > /tmp/slabinfo.before
guest cat /proc/meminfo > /tmp/meminfo.before
guest /usr/bin/passt.avx2 -l /tmp/log -s /tmp/sock -P /tmp/pid __OPTS__ --netns-only
sleep 2
guest cat /proc/meminfo > /tmp/meminfo.after
guest sed /proc/slabinfo -ne 's/^\([^ ]* *[^ ]* *[^ ]* *[^ ]*\).*/\\\1/p' > /tmp/slabinfo.after
guest kill \$(cat /tmp/pid)
guest diff -y --suppress-common-lines /tmp/meminfo.before /tmp/meminfo.after || :
guest nm -td -Sr --size-sort -P /usr/bin/passt.avx2 | head -30 | tee /tmp/nm.size
guest sed /proc/slabinfo -ne 's/\(.*<objsize>\).*$/\1/p' | tail -1; (diff -y --suppress-common-lines /tmp/slabinfo.before /tmp/slabinfo.after | sort -grk8)
endef
def summary
info Memory usage summary
info
th type MiB
set WHAT MemFree
set NAME used
meminfo_reverse_row
set WHAT AnonPages
set NAME userspace
meminfo_row
set WHAT Slab
set NAME kernel
meminfo_row
te
endef
guest mkdir /test
guest mount -t tmpfs none /test
guest mkdir /test/proc /test/dev /test/tmp
guest mount -o bind /proc /test/proc
guest mount -o bind /dev /test/dev
guest cp -Lr /bin /lib /lib64 /usr /sbin /test/
guest ulimit -Hn 300000
guest unshare -rUm -R /test
guest chroot .
guest meminfo_size() { grep "^$2:" $1 | tr -s ' ' | cut -f2 -d ' '; }
guest meminfo_diff() { echo $(( $(meminfo_size $2 $3) - $(meminfo_size $1 $3) )); }
guest nm_size() { grep -m1 "^$2 " $1 | cut -f4 -d ' '; }
guest slab_count() { grep "^$2 " $1 | tr -s ' ' | cut -f3 -d ' '; }
guest slab_size() { grep "^$2 " $1 | tr -s ' ' | cut -f4 -d ' '; }
guest slab_diff_count() { echo $(( $(slab_count $2 $3) - $(slab_count $1 $3) )); }
guest slab_diff_size() { echo $(( $(slab_count $2 $3) * $(slab_size $2 $3) - $(slab_count $1 $3) * $(slab_size $1 $3) )); }
test Memory usage: all TCP and UDP ports forwarded, IPv4 and IPv6
set OPTS -t all -u all
start_stop_diff
summary
info Userspace memory detail
info
th symbol MiB
set WHAT tcp_buf_discard
nm_row
set WHAT tcp6_l2_buf
nm_row
set WHAT tcp4_l2_buf
nm_row
set WHAT tc
nm_row
set WHAT pkt_buf
nm_row
set WHAT udp_splice_map
nm_row
set WHAT udp6_l2_buf
nm_row
set WHAT udp4_l2_buf
nm_row
set WHAT udp_tap_map
nm_row
set WHAT icmp_id_map
nm_row
set WHAT udp_splice_buf
nm_row
set WHAT tc_hash
nm_row
set WHAT pool_tap6_storage
nm_row
set WHAT pool_tap4_storage
nm_row
set WHAT tap6_l4
nm_row
set WHAT tap4_l4
nm_row
te
info Kernel memory detail
info
th objects count size MiB
set WHAT pid
slab_row
set WHAT dentry
slab_row
set WHAT Acpi-Parse
slab_row
set WHAT kmalloc-64
slab_row
set WHAT kmalloc-32
slab_row
set WHAT lsm_file_cache
slab_row
set WHAT filp
slab_row
set WHAT anon_vma_chain
slab_row
set WHAT ep_head
slab_row
set WHAT sock_inode_cache
slab_row
set WHAT signal_cache
slab_row
set WHAT TCPv6
slab_row
set WHAT TCP
slab_row
set WHAT UDPv6
slab_row
te
test Memory usage: all TCP ports forwarded, IPv4
set OPTS -t all -4
start_stop_diff
summary
test Memory usage: all TCP and UDP ports forwarded, IPv4
set OPTS -t all -u all -4
start_stop_diff
summary
test Memory usage: no ports forwarded
set OPTS -t none -u none
start_stop_diff
summary

44
test/passt.mem.mbuto Executable file
View file

@ -0,0 +1,44 @@
#!/bin/sh
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# test/passt.mem.mbuto - mbuto (https://mbuto.sh) profile for memory usage tests
#
# Copyright (c) 2022 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
PROGS="${PROGS:-ash,dash,bash chmod ip mount insmod mkdir ln cat chmod modprobe
grep mknod sed chown sleep bc ls ps mount unshare chroot cp kill diff
head tail sort tr tee cut nm which}"
KMODS="${KMODS:- dummy}"
NODES="${NODES:-console kmsg null ptmx random urandom zero}"
LINKS="${LINKS:-
ash,dash,bash /init
ash,dash,bash /bin/sh}"
DIRS="${DIRS} /tmp /sbin"
COPIES="${COPIES} ../passt.avx2,/bin/passt.avx2"
FIXUP="${FIXUP}"'
ln -s /bin /usr/bin
chmod 777 /tmp
ip link add eth0 type dummy
ip link set eth0 up
ip address add 192.0.2.2/24 dev eth0
ip address add 2001:db8::2/64 dev eth0
ip route add default via 192.0.2.1
ip -6 route add default via 2001:db8::1 dev eth0
sleep 2
sh +m
'
OUTPUT="KERNEL=__KERNEL__
INITRD=__INITRD__
"

View file

@ -79,6 +79,10 @@ run() {
test pasta_options/log_to_file test pasta_options/log_to_file
teardown pasta_options teardown pasta_options
setup memory
test memory/passt
teardown memory
setup passt setup passt
test passt/ndp test passt/ndp
test passt/dhcp test passt/dhcp