Those tests were done between two virtual machines on the same server using a AMD Ryzen 9955HX. The test were going from the iperf on the VPN client to iperf on the VPN server. Running iperf3 on the VPN server seemed to cause WireGuard to become single thread bound.
I did another test with 3 virtual machines with 8 virtual cores running on 3 different AMD EPYC 9124 physical servers and 20gb bonded networking. This tested iperf on the VPN client → switch → VPN server → switch → iperf server. This showed significantly better performance with WireGuard. OpenVPN DCO appears to still be single thread bound for a single connection. During the OpenVPN test one core was at 100% with WireGuard there was equal distribution across all 8 cores. This test won’t reflect most VPN deployments as there will be multiple clients that can be spread across different CPU cores. The OpenVPN results here are slower than the Ryzen one due to the significantly slower core speed on server processors.
My understanding is OpenVPN DCO won’t be single thread bound. It’s possible there’s some issue with my configuration but both adapters are shown as ovpn-dco type. The DCO going into the kernel is different then the DKMS code available. I did go back and check the development server on the AMD Ryzen 9955HX and it is also single thread bound. There is the message below in the ovpn-dco repository. It’s likely all development has been moved to the in-tree module and when that is ready it will not have these issues.
** MAINTENANCE MODE **
This repository is currently in maintenance mode and we only accept important
and meaningful bugfixes.
It’s likely that OpenVPN DCO support without needing DKMS modules is still at least a year away as it will take time for the in-tree module to become widespread in distributions, currently even Fedora does not appear to have a working DCO. Below is Fedora 43 which has a kernel with the in-tree ovpn module and the OpenVPN build is not detecting it. When I was looking through the OpenVPN source I noticed the current code in the OpenVPN repository appears to have updated all references from the ovpn-dco-v2 module to the in-tree ovpn module. The source for version 2.6.17 still references ovpn-dco-v2.
cloud@test-f43:~$ sudo modprobe ovpn
cloud@test-f43:~$ openvpn --version
OpenVPN 2.6.17 x86_64-redhat-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] [DCO]
library versions: OpenSSL 3.5.4 30 Sep 2025, LZO 2.10
DCO version: N/A
Originally developed by James Yonan
Copyright (C) 2002-2024 OpenVPN Inc <sales@openvpn.net>
Compile time defines: enable_async_push=yes enable_comp_stub=no enable_crypto_ofb_cfb=yes enable_dco=yes enable_dco_arg=yes enable_debug=yes enable_dependency_tracking=no enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown enable_fast_install=needless enable_fragment=yes enable_iproute2=no enable_libtool_lock=yes enable_lz4=yes enable_lzo=yes enable_management=yes enable_pam_dlopen=no enable_pedantic=no enable_pkcs11=yes enable_plugin_auth_pam=yes enable_plugin_down_root=yes enable_plugins=yes enable_port_share=yes enable_selinux=yes enable_shared=yes enable_shared_with_static_runtimes=no enable_silent_rules=yes enable_small=no enable_static=yes enable_strict=no enable_strict_options=no enable_systemd=yes enable_werror=no enable_win32_dll=yes enable_wolfssl_options_h=yes enable_x509_alt_username=yes with_aix_soname=aix with_crypto_library=openssl with_gnu_ld=yes with_mem_check=no with_openssl_engine=auto with_sysroot=no
OpenVPN DCO (AES-128-GCM)
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 117 MBytes 977 Mbits/sec 12 1.20 MBytes
[ 5] 1.00-2.00 sec 116 MBytes 970 Mbits/sec 0 1.27 MBytes
[ 5] 2.00-3.00 sec 114 MBytes 958 Mbits/sec 0 1.34 MBytes
[ 5] 3.00-4.00 sec 113 MBytes 945 Mbits/sec 0 1.40 MBytes
[ 5] 4.00-5.00 sec 123 MBytes 1.03 Gbits/sec 0 1.46 MBytes
[ 5] 5.00-6.00 sec 108 MBytes 901 Mbits/sec 47 1.14 MBytes
[ 5] 6.00-7.00 sec 112 MBytes 938 Mbits/sec 0 1.24 MBytes
[ 5] 7.00-8.00 sec 120 MBytes 1.01 Gbits/sec 0 1.32 MBytes
[ 5] 8.00-9.00 sec 122 MBytes 1.02 Gbits/sec 0 1.38 MBytes
[ 5] 9.00-10.00 sec 118 MBytes 993 Mbits/sec 0 1.42 MBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 1.13 GBytes 974 Mbits/sec 59 sender
[ 5] 0.00-10.01 sec 1.13 GBytes 971 Mbits/sec receiver
OpenVPN DCO (CHACHA20-POLY1305)
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 119 MBytes 994 Mbits/sec 57 1.20 MBytes
[ 5] 1.00-2.00 sec 121 MBytes 1.02 Gbits/sec 0 1.31 MBytes
[ 5] 2.00-3.00 sec 119 MBytes 1.00 Gbits/sec 0 1.40 MBytes
[ 5] 3.00-4.00 sec 119 MBytes 995 Mbits/sec 0 1.47 MBytes
[ 5] 4.00-5.00 sec 120 MBytes 1.00 Gbits/sec 3 1.10 MBytes
[ 5] 5.00-6.00 sec 120 MBytes 1.00 Gbits/sec 1 1.17 MBytes
[ 5] 6.00-7.00 sec 121 MBytes 1.02 Gbits/sec 0 1.24 MBytes
[ 5] 7.00-8.00 sec 121 MBytes 1.01 Gbits/sec 0 1.31 MBytes
[ 5] 8.00-9.00 sec 120 MBytes 1.01 Gbits/sec 0 1.38 MBytes
[ 5] 9.00-10.00 sec 120 MBytes 1.01 Gbits/sec 0 1.44 MBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 1.17 GBytes 1.01 Gbits/sec 61 sender
[ 5] 0.00-10.01 sec 1.17 GBytes 1.00 Gbits/sec receiver
WireGuard
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 734 MBytes 6.15 Gbits/sec 12 2.34 MBytes
[ 5] 1.00-2.00 sec 831 MBytes 6.97 Gbits/sec 23 3.14 MBytes
[ 5] 2.00-3.00 sec 849 MBytes 7.12 Gbits/sec 7 3.32 MBytes
[ 5] 3.00-4.00 sec 841 MBytes 7.05 Gbits/sec 0 3.50 MBytes
[ 5] 4.00-5.00 sec 814 MBytes 6.83 Gbits/sec 29 3.70 MBytes
[ 5] 5.00-6.00 sec 829 MBytes 6.95 Gbits/sec 1 3.79 MBytes
[ 5] 6.00-7.00 sec 844 MBytes 7.08 Gbits/sec 0 3.86 MBytes
[ 5] 7.00-8.00 sec 845 MBytes 7.08 Gbits/sec 0 3.90 MBytes
[ 5] 8.00-9.00 sec 846 MBytes 7.10 Gbits/sec 0 3.92 MBytes
[ 5] 9.00-10.00 sec 839 MBytes 7.04 Gbits/sec 4 3.98 MBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 8.08 GBytes 6.94 Gbits/sec 76 sender
[ 5] 0.00-10.00 sec 8.08 GBytes 6.94 Gbits/sec receiver