GSerg1
November 26, 2025, 10:03am
1
Please help with openvpn DCO on subject device.
CPU still use 30-50% CPU per connection.
What should i do to make it work?
root@OpenWrt:~# uname -a
Linux OpenWrt 6.6.104 #0 Fri Sep 19 21:19:38 2025 mips GNU/Linux
root@OpenWrt:~# cat /etc/config/network
config interface 'loopback'
option device 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'
config globals 'globals'
option ula_prefix 'fd2f:8dd8:72db::/48'
option packet_steering '1'
config device
option name 'br-lan'
option type 'bridge'
list ports 'eth1.1'
list ports 'tap0'
config interface 'lan'
option device 'br-lan'
option proto 'static'
option ipaddr '192.168.234.1'
option netmask '255.255.255.0'
option ip6assign '60'
config interface 'wan'
option device 'eth0.2'
option proto 'dhcp'
config switch
option name 'switch0'
option reset '1'
option enable_vlan '1'
config switch_vlan
option device 'switch0'
option vlan '1'
option ports '2 3 4 5 0t'
config switch_vlan
option device 'switch0'
option vlan '2'
option ports '1 6t'
root@OpenWrt:~# cat /etc/config/firewall
config defaults
option syn_flood '1'
option input 'REJECT'
option output 'ACCEPT'
option forward 'REJECT'
config zone
option name 'lan'
option input 'ACCEPT'
option output 'ACCEPT'
option forward 'ACCEPT'
list network 'lan'
config zone
option name 'wan'
option input 'REJECT'
option output 'ACCEPT'
option forward 'REJECT'
option masq '1'
option mtu_fix '1'
list network 'wan'
config forwarding
option src 'lan'
option dest 'wan'
config rule
option name 'Allow-DHCP-Renew'
option src 'wan'
option proto 'udp'
option dest_port '68'
option target 'ACCEPT'
option family 'ipv4'
config rule
option name 'Allow-Ping'
option src 'wan'
option proto 'icmp'
option icmp_type 'echo-request'
option family 'ipv4'
option target 'ACCEPT'
config rule
option name 'Allow-IGMP'
option src 'wan'
option proto 'igmp'
option family 'ipv4'
option target 'ACCEPT'
config rule
option name 'Allow-DHCPv6'
option src 'wan'
option proto 'udp'
option dest_port '546'
option family 'ipv6'
option target 'ACCEPT'
config rule
option name 'Allow-MLD'
option src 'wan'
option proto 'icmp'
option src_ip 'fe80::/10'
list icmp_type '130/0'
list icmp_type '131/0'
list icmp_type '132/0'
list icmp_type '143/0'
option family 'ipv6'
option target 'ACCEPT'
config rule
option name 'Allow-ICMPv6-Input'
option src 'wan'
option proto 'icmp'
list icmp_type 'echo-request'
list icmp_type 'echo-reply'
list icmp_type 'destination-unreachable'
list icmp_type 'packet-too-big'
list icmp_type 'time-exceeded'
list icmp_type 'bad-header'
list icmp_type 'unknown-header-type'
list icmp_type 'router-solicitation'
list icmp_type 'neighbour-solicitation'
list icmp_type 'router-advertisement'
list icmp_type 'neighbour-advertisement'
option limit '1000/sec'
option family 'ipv6'
option target 'ACCEPT'
config rule
option name 'Allow-ICMPv6-Forward'
option src 'wan'
option dest '*'
option proto 'icmp'
list icmp_type 'echo-request'
list icmp_type 'echo-reply'
list icmp_type 'destination-unreachable'
list icmp_type 'packet-too-big'
list icmp_type 'time-exceeded'
list icmp_type 'bad-header'
list icmp_type 'unknown-header-type'
option limit '1000/sec'
option family 'ipv6'
option target 'ACCEPT'
config rule
option name 'Allow-IPSec-ESP'
option src 'wan'
option dest 'lan'
option proto 'esp'
option target 'ACCEPT'
config rule
option name 'Allow-ISAKMP'
option src 'wan'
option dest 'lan'
option dest_port '500'
option proto 'udp'
option target 'ACCEPT'
config redirect
option dest 'lan'
option target 'DNAT'
option name 'SSH_ROUTER'
option src 'wan'
option src_dport '9999'
option dest_ip '192.168.234.1'
option dest_port '9999'
config rule 'Allow_OpenVPN_Inbound'
option target 'ACCEPT'
option src '*'
option proto 'udp'
option dest_port '6994'
root@OpenWrt:~# cat /etc/config/openvpn
config openvpn 'myvpn'
option enabled '1'
option verb '3'
option proto 'udp'
option port '6994'
option dev 'tap0'
option mode 'server'
option tls_server '1'
option keepalive '10 120'
option ca '/etc/openvpn/ca.crt'
option cert '/etc/openvpn/my-server.crt'
option key '/etc/openvpn/my-server.key'
option dh '/etc/openvpn/dh.pem'
option client_config_dir '/etc/openvpn/ccd'
list route '192.168.234.0 255.255.255.0'
list route '192.168.231.0 255.255.255.0'
option cipher 'none'
option auth 'none'
list data_ciphers 'AES-128-GCM'
list data_ciphers 'AES-128-GCM'
root@OpenWrt:~# lsmod |grep dco
ip6_udp_tunnel 12288 1 ovpn_dco_v2
ovpn_dco_v2 53248 0
udp_tunnel 20480 1 ovpn_dco_v2
root@OpenWrt:~# logread -e openvpn |grep DCO
Tue Nov 25 19:56:45 2025 daemon.notice openvpn(myvpn)[15978]: OpenVPN 2.6.14 mips-openwrt-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [MH/PKTINFO] [AEAD] [DCO]
Tue Nov 25 19:56:45 2025 daemon.notice openvpn(myvpn)[15978]: DCO version: N/A
Tue Nov 25 20:17:57 2025 daemon.notice openvpn(myvpn)[22743]: OpenVPN 2.6.14 mips-openwrt-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [MH/PKTINFO] [AEAD] [DCO]
Tue Nov 25 20:17:57 2025 daemon.notice openvpn(myvpn)[22743]: DCO version: N/A
root@OpenWrt:~#
frollic
November 26, 2025, 10:04am
2
does the other end support DCO ?
swap to WireGuard and/or get a new(er) device.
egc
November 26, 2025, 11:02am
3
Use WireGuard which is more performant than openvpn even with dco
I do not think tap is compatible with dco
brada4
November 26, 2025, 12:42pm
4
The vlan tagging without offload on 2 cpu ports consumes 200% of CPU just routing flat....
brada4
November 26, 2025, 3:12pm
5
ip -d link show | grep -i dco
GSerg1
November 27, 2025, 8:57am
6
Have no idea how to get Wireguard working as L2 bridge.
Tun has same problem. But on client side on Ubuntu openvpn with DCO and TAP interface looks like workable :))
2025-11-19 16:16:39 us=153939 OpenVPN 2.6.16 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] [DCO]
2025-11-19 16:16:39 us=154238 DCO version: 0.2.20251017
GSerg1
November 27, 2025, 9:00am
7
root@OpenWrt:~# ip -d link show |grep -i dco
BusyBox v1.36.1 (2025-09-19 21:19:38 UTC) multi-call binary.
Usage: ip [OPTIONS] address|route|link|neigh|rule [ARGS]
OPTIONS := -f[amily] inet|inet6|link | -o[neline]
ip addr add|del IFADDR dev IFACE | show|flush [dev IFACE] [to PREFIX]
ip route list|flush|add|del|change|append|replace|test ROUTE
ip link set IFACE [up|down] [arp on|off] [multicast on|off]
[promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]
[master IFACE | nomaster] [netns PID]
ip neigh show|flush [to PREFIX] [dev DEV] [nud STATE]
ip rule [list] | add|del SELECTOR ACTION
Option -d not support.
Without -d empty output:
root@OpenWrt:~# ip link show |grep -i dco
root@OpenWrt:~#
pavelgl
November 27, 2025, 9:19am
9
Do you have anything HW accelerated in cat /proc/crypto output? If not... then you're stuck with least heavy SW encryption. Kernel-side encryption like WG will be the best because context switching (e.g. OpenVPN which works in userspace) will eat even more. If answer is 'yes' then you have to try to employ it somehow.
Well, in this case he should proceed with plan A, as it was already suggested )))
1 Like
GSerg1
November 27, 2025, 1:02pm
13
cat /proc/crypto output:
name : sha224
driver : sha224-generic
module : sha256_generic
priority : 100
refcnt : 1
selftest : passed
internal : no
type : shash
blocksize : 64
digestsize : 28
name : sha256
driver : sha256-generic
module : sha256_generic
priority : 100
refcnt : 1
selftest : passed
internal : no
type : shash
blocksize : 64
digestsize : 32
name : ccm(aes)
driver : ccm_base(ctr(aes-generic),cbcmac(aes-generic))
module : kernel
priority : 100
refcnt : 7
selftest : passed
internal : no
type : aead
async : no
blocksize : 1
ivsize : 16
maxauthsize : 16
geniv : <none>
name : ctr(aes)
driver : ctr(aes-generic)
module : kernel
priority : 100
refcnt : 7
selftest : passed
internal : no
type : skcipher
async : no
blocksize : 1
min keysize : 16
max keysize : 32
ivsize : 16
chunksize : 16
walksize : 16
name : cbcmac(aes)
driver : cbcmac(aes-generic)
module : kernel
priority : 100
refcnt : 13
selftest : passed
internal : no
type : shash
blocksize : 1
digestsize : 16
name : lzo
driver : lzo-scomp
module : lzo
priority : 0
refcnt : 1
selftest : passed
internal : no
type : scomp
name : lzo
driver : lzo-generic
module : lzo
priority : 0
refcnt : 1
selftest : passed
internal : no
type : compression
name : lzo-rle
driver : lzo-rle-scomp
module : lzo_rle
priority : 0
refcnt : 1
selftest : passed
internal : no
type : scomp
name : lzo-rle
driver : lzo-rle-generic
module : lzo_rle
priority : 0
refcnt : 1
selftest : passed
internal : no
type : compression
name : sha384
driver : sha384-generic
module : sha512_generic
priority : 100
refcnt : 1
selftest : passed
internal : no
type : shash
blocksize : 128
digestsize : 48
name : sha512
driver : sha512-generic
module : sha512_generic
priority : 100
refcnt : 1
selftest : passed
internal : no
type : shash
blocksize : 128
digestsize : 64
name : jitterentropy_rng
driver : jitterentropy_rng
module : jitterentropy_rng
priority : 100
refcnt : 1
selftest : passed
internal : no
type : rng
seedsize : 0
name : sha3-512
driver : sha3-512-generic
module : sha3_generic
priority : 0
refcnt : 1
selftest : passed
internal : no
type : shash
blocksize : 72
digestsize : 64
name : sha3-384
driver : sha3-384-generic
module : sha3_generic
priority : 0
refcnt : 1
selftest : passed
internal : no
type : shash
blocksize : 104
digestsize : 48
name : sha3-256
driver : sha3-256-generic
module : sha3_generic
priority : 0
refcnt : 1
selftest : passed
internal : no
type : shash
blocksize : 136
digestsize : 32
name : sha3-224
driver : sha3-224-generic
module : sha3_generic
priority : 0
refcnt : 1
selftest : passed
internal : no
type : shash
blocksize : 144
digestsize : 28
name : stdrng
driver : drbg_nopr_hmac_sha512
module : drbg
priority : 207
refcnt : 1
selftest : passed
internal : no
type : rng
seedsize : 0
name : stdrng
driver : drbg_nopr_hmac_sha256
module : drbg
priority : 206
refcnt : 1
selftest : passed
internal : no
type : rng
seedsize : 0
name : stdrng
driver : drbg_nopr_hmac_sha384
module : drbg
priority : 205
refcnt : 1
selftest : passed
internal : no
type : rng
seedsize : 0
name : stdrng
driver : drbg_nopr_hmac_sha1
module : drbg
priority : 204
refcnt : 1
selftest : passed
internal : no
type : rng
seedsize : 0
name : stdrng
driver : drbg_pr_hmac_sha512
module : drbg
priority : 203
refcnt : 1
selftest : passed
internal : no
type : rng
seedsize : 0
name : stdrng
driver : drbg_pr_hmac_sha256
module : drbg
priority : 202
refcnt : 1
selftest : passed
internal : no
type : rng
seedsize : 0
name : stdrng
driver : drbg_pr_hmac_sha384
module : drbg
priority : 201
refcnt : 1
selftest : passed
internal : no
type : rng
seedsize : 0
name : stdrng
driver : drbg_pr_hmac_sha1
module : drbg
priority : 200
refcnt : 1
selftest : passed
internal : no
type : rng
seedsize : 0
name : crc32c
driver : crc32c-generic
module : crc32c_generic
priority : 100
refcnt : 4
selftest : passed
internal : no
type : shash
blocksize : 1
digestsize : 4
name : ghash
driver : ghash-generic
module : kernel
priority : 100
refcnt : 1
selftest : passed
internal : no
type : shash
blocksize : 16
digestsize : 16
name : aes
driver : aes-generic
module : kernel
priority : 100
refcnt : 13
selftest : passed
internal : no
type : cipher
blocksize : 16
min keysize : 16
max keysize : 32
name : ecb(cipher_null)
driver : ecb-cipher_null
module : kernel
priority : 100
refcnt : 1
selftest : passed
internal : no
type : skcipher
async : no
blocksize : 1
min keysize : 0
max keysize : 0
ivsize : 0
chunksize : 1
walksize : 1
name : digest_null
driver : digest_null-generic
module : kernel
priority : 0
refcnt : 1
selftest : passed
internal : no
type : shash
blocksize : 1
digestsize : 0
name : compress_null
driver : compress_null-generic
module : kernel
priority : 0
refcnt : 1
selftest : passed
internal : no
type : compression
name : cipher_null
driver : cipher_null-generic
module : kernel
priority : 0
refcnt : 1
selftest : passed
internal : no
type : cipher
blocksize : 1
min keysize : 0
max keysize : 0
If not... then you're stuck with least heavy SW encryption. Kernel-side encryption like WG will be the best because context switching (e.g. OpenVPN which works in userspace) will eat even more.
Wg is routed only. There is no option for an l2 bridge with wireguard.
Why do you need to operate at l2 (vs L3)? What is the goal?
brada4
November 27, 2025, 1:55pm
17
You can run gretap over wg with increased MTU, it will be even slower on your hardware/
gretap is yet another memory copy, half speed from it on top of all you (dont) have.