| # Deterministic, host-speed-independent zperf throughput measurement. |
| # |
| # Layer this on top of overlay-loopback.conf, e.g.: |
| # -DEXTRA_CONF_FILE="overlay-loopback.conf;overlay-loopback-icount.conf" |
| # |
| # All traffic stays inside the guest (loopback), so QEMU icount mode can be |
| # safely enabled. In icount mode the virtual CPU advances virtual time by |
| # 2^SHIFT ns per executed instruction, so the reported throughput becomes a |
| # deterministic function of instructions-per-byte instead of host wall clock. |
| |
| # Force QEMU icount on. It is disabled by default when networking + shell are |
| # enabled, but with loopback-only traffic there is no real host I/O in the |
| # measurement path. |
| CONFIG_QEMU_ICOUNT=y |
| CONFIG_QEMU_ICOUNT_SHIFT=5 |
| CONFIG_QEMU_ICOUNT_SLEEP=n |
| |
| # icount only works with a single CPU. |
| CONFIG_MP_MAX_NUM_CPUS=1 |
| |
| # Run the kernel tick at 10 kHz. The default qemu_x86 rate is 100 Hz, which |
| # (a) compiles in the UDP uploader's clock-compensation path that divides by |
| # the per-packet duration - a division by zero once the unlimited rate drives |
| # that duration to 0 - and (b) is far too coarse to pace traffic. A >1 kHz tick |
| # removes the compensation path and gives fine-grained timing. |
| CONFIG_SYS_CLOCK_TICKS_PER_SEC=10000 |
| |
| # Loopback-only: no QEMU SLIP/TAP host networking. This removes the external, |
| # real-time network backend that would otherwise make icount non-deterministic |
| # (and require a host-side slip.sock). |
| CONFIG_NET_QEMU_SLIP=n |
| CONFIG_NET_SLIP_TAP=n |
| |
| # Self-driven loopback runner (see src/main.c). Avoids the interactive shell, |
| # which can stall under icount waiting on real-time stdin. |
| CONFIG_ZPERF_LOOPBACK_SELFTEST=y |
| |
| # The UDP uploader needs a receive timeout to collect the server statistics. |
| CONFIG_NET_CONTEXT_RCVTIMEO=y |
| |
| # The zperf receivers register several sockets with the socket service; give |
| # zvfs_poll() enough slots for the TCP listener plus its sessions. |
| CONFIG_ZVFS_POLL_MAX=16 |
| |
| # The loopback driver delivers each packet synchronously in the sender's |
| # context, so the whole receive path (and, for this sample, the blocking client |
| # upload) runs on the caller's stack. Give the involved threads generous stacks |
| # to absorb that nesting; otherwise the guest overflows and faults at boot. |
| CONFIG_MAIN_STACK_SIZE=3072 |
| CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2560 |
| CONFIG_NET_RX_STACK_SIZE=2560 |
| CONFIG_NET_TX_STACK_SIZE=2560 |
| CONFIG_NET_MGMT_EVENT_STACK_SIZE=2560 |
| CONFIG_NET_SOCKETS_SERVICE_STACK_SIZE=2560 |
| |
| # Do not try to add IPv4/6 address to network interface but let the system |
| # use the localhost addresses. |
| CONFIG_NET_CONFIG_MY_IPV4_ADDR="" |
| CONFIG_NET_CONFIG_MY_IPV6_ADDR="" |
| |
| # Disable statistics so that the stats collection will not lower the numbers. |
| CONFIG_NET_STATISTICS=n |
| |
| # Push near-MTU-sized frames through the stack so the per-packet cost is |
| # dominated by data-touching work (checksums, buffer/fragment walking) rather |
| # than fixed per-call overhead. The selftest sends a 1220 byte payload (see the |
| # Kconfig default): that is the IPv6 TCP MSS at a 1280 byte MTU (1280 - 40 IPv6 |
| # - 20 TCP), so every TCP write is a single full-sized segment for both IPv4 and |
| # IPv6 (avoiding a tiny trailing segment that would otherwise halve IPv6 TCP), |
| # and the UDP datagrams stay under the MTU for both families so no IP |
| # fragmentation is needed. Raise the loopback L3 MTU accordingly and lift |
| # zperf's own packet ceiling above the (larger, fragmenting) payload below. |
| CONFIG_NET_LOOPBACK_MTU=1280 |
| CONFIG_NET_ZPERF_MAX_PACKET_SIZE=2100 |
| |
| # Keep the net_buf data size (1100, from overlay-loopback.conf) below the MTU so |
| # each 1280 byte packet spans two buffer fragments. This deliberately exercises |
| # the fragment-chain walk in net_pkt_get_len() and friends. |
| |
| # Exercise the IP fragmentation + reassembly subsystem: the runner adds an extra |
| # UDP run per family whose payload (see ZPERF_LOOPBACK_SELFTEST_FRAG_PACKET_SIZE) |
| # exceeds the MTU, so ipv4.c/ipv6.c must fragment on TX and reassemble on RX. |
| CONFIG_NET_IPV4_FRAGMENT=y |
| CONFIG_NET_IPV6_FRAGMENT=y |
| |
| # Exercise traffic classes and SO_PRIORITY: with more than one TX/RX queue the |
| # stack routes prioritised traffic through dedicated per-traffic-class threads |
| # (net_tc.c) instead of the caller's context. The runner sets a non-default |
| # priority on every upload so this path is always taken. |
| CONFIG_NET_TC_TX_COUNT=2 |
| CONFIG_NET_TC_RX_COUNT=2 |
| CONFIG_NET_CONTEXT_PRIORITY=y |
| CONFIG_NET_ALLOW_ANY_PRIORITY=y |