Blame

85e264 Samuli Seppänen 2025-02-11 09:28:36 1
# Optimizing Performance on Gigabit Networks
2
3
**NOTE:** This article is very outdated. Double-check against recent documentation before following the steps outlined here.
4
5
It is possible to saturate a 100 Mbps network using an OpenVPN tunnel, achieving throughput very close to that of a regular network interface. However, achieving similar results on gigabit networks and faster is not as straightforward. This page details how to increase the throughput of a VPN tunnel to near-line speed for a 1 Gbps network, with some initial explorations into 10 Gbps networks also discussed.
6
7
## Network Setup
8
For this setup, several machines were used, all connected to gigabit switches:
9
- Two servers running CentOS 5.5 64bit, with an Intel Xeon E5440 CPU at 2.83GHz and an L2 cache size of 6 MB.
10
- A server running CentOS 5.5 64bit, with an Intel Xeon X5660 CPU at 2.80GHz and an L2 cache size of 12 MB. This CPU supports AES-NI instructions.
11
- A laptop running Fedora 14 64bit, with an Intel i5-560M CPU at 2.66GHz and an L2 cache size of 3 MB. This CPU also supports AES-NI instructions.
12
13
Before starting, the raw network speed was measured using `iperf`, consistently reporting around 940 Mbps, which is almost optimal for a gigabit LAN. The MTU size on all switches in the gigabit LAN was set to 1500.
14
15
## Understanding the Flow of Packets
16
Understanding how packets flow from the `iperf` client via the OpenVPN tunnel to the `iperf` server is crucial. The following diagram helps to clarify this process:
17
8417ea Samuli Seppänen 2025-02-11 09:29:37 18
![OpenVPN Packet Flow Diagram](./OpenVPN-packetflow.png)
85e264 Samuli Seppänen 2025-02-11 09:28:36 19
20
When an `iperf` packet is sent to the VPN server IP address, it enters the kernel's `tun0` device. The packet is then forwarded to the userspace OpenVPN process, where headers are stripped. The packet is encrypted and signed using OpenSSL calls, configurable via the `--cipher` and `--auth` options.
21
22
The packet is then fragmented according to the `--fragment` and `--mssfix` options, and the encrypted packet is sent over the regular network to the OpenVPN server. On the server side, the process is reversed: the packet is reassembled, decrypted, and finally sent out the `tun0` interface.
23
24
## Standard Setup
25
The default OpenVPN for CentOS 5 is version 2.1.4; the system OpenSSL version is 0.9.8e-fips.
26
27
Using a simple shared secret key setup for both server (listener)
28
29
```bash
30
openvpn --dev tun --proto udp --port 11000 --secret secret.key --ifconfig 192.168.222.11 192.168.222.10
31
```
32
33
and client
34
35
```bash
36
openvpn --dev tun --proto udp --port 11000 --secret secret.key --ifconfig 192.168.222.10 192.168.222.11 --remote server
37
```
38
39
an `iperf` result of 156 Mbps is obtained.
40
41
Switching to the cipher `aes-256-cbc` results in a performance drop to 126 Mbps. These results were obtained using the two E5440 based servers.
42
43
## Tweaked Setup
44
The first tweaks made were:
45
- Increase the MTU size of the tun adapter (`--tun-mtu`) to 6000 bytes, resembling Jumbo frames on a regular Ethernet LAN. Note that the MTU size on the underlying network switches was not altered.
46
- Disable OpenVPN's internal fragmentation algorithm using `--fragment 0`.
47
- Disable OpenVPN's 'TCP Maximum Segment Size' limiter using `--mssfix 0`.
48
c5dc97 Samuli Seppänen 2025-02-11 09:30:27 49
Server:
50
85e264 Samuli Seppänen 2025-02-11 09:28:36 51
```bash
52
openvpn --dev tun --proto udp --port 11000 --secret secret.key --ifconfig 192.168.222.11 192.168.222.10 --tun-mtu 6000 --fragment 0 --mssfix 0
53
```
54
c5dc97 Samuli Seppänen 2025-02-11 09:30:27 55
and client:
56
85e264 Samuli Seppänen 2025-02-11 09:28:36 57
```bash
58
openvpn --dev tun --proto udp --port 11000 --secret secret.key --ifconfig 192.168.222.10 192.168.222.11 --tun-mtu 6000 --fragment 0 --mssfix 0 --remote server
59
```
60
Now an **iperf** result of **307 Mbps** is obtained.
61
62
By playing with the '--tun-mtu' size we obtain (all speeds in Mbps)
63
64
| MTU | Blowfish | AES256 |
65
|-------|----------|--------|
66
| 1500 | 158 | 126 |
67
| 6000 | 307 | 220 |
68
| 9000 | 370 | 249 |
69
| 12000 | 416 | 252 |
70
| 24000 | 466 | 259 |
71
| 36000 | 470 | 244 |
72
| 48000 | **510** | 247 |
73
| 60000 | 488 | 221 |
74
75
(Please note that for all measurement a standard deviation of ~5% applies)
76
77
For the default Blowfish cipher the optimal value for the 'tun-mtu' parameters for a link between these two servers seems to be **48000** bytes. For this 'tun-mtu' setting the VPN throughput increases from 160 Mbps to **510** Mbps.
78
79
Similarly, for the AES-256 cipher the optimal value is **24000** bytes.
80
81
### Explanation
82
By increasing the MTU size of the tun adapter **and** by disabling OpenVPN's internal fragmentation routines the throughput can be increased quite dramatically. The reason behind this is that by feeding larger packets to the OpenSSL encryption and decryption routines the performance will go up. The second advantage of not internally fragmenting packets is that this is left to the operating system and to the kernel network device drivers. For a LAN-based setup this can work, but when handling various types of remote users (road warriors, cable modem users, etc) this is not always a possibility.
83
84
## **txqueuelen**
85
86
The default value for **tx_queue_len** in linux is 1000, however, openvpn overrides this default and sets it to 100. You can re-set it to the original default of 1000 by specifying **--txqueuelen 1000**. This can greatly improve throughput in scenarios where using jumbo frames (**--tun-mtu**) is not possible, such as over the internet. The expected performance gain is around 5x, being from 60mbps to almost 300mbps on some tests I carried on a real coast-to-coast scenario (with different ISPs).
87
88
| **txqueuelen** | **bandwidth** |
89
|----------------|---------------|
90
| 100 | 63 |
91
| 1000 | 292 |
92
93
Please note that, as the name indicates, this only affects the transmission, not the reception. So in case an asymmetric connection is used, this parameter will only have an observable effect on a peer whose transmission speed is greater than ~100mbps.
94
95
## Using OpenSSL 1.0.0 with AES-NI patch
96
The second tweak made was to relink OpenVPN 2.1.4 using the OpenSSL 1.0.0a libraries with the Intel AES-NI patch applied. This patch is included by default in Fedora 12 and higher.
97
98
Previously it was reported that the Intel AES-NI patch caused the performance on non-AES-NI capable hardware to improve by a factor of 2. Closer investigation showed that the system OpenSSL library 0.9.8e-fips is actually at fault: after recompiling OpenSSL from source, with or without the Intel AES-NI patch, the performance also doubled. The Fedora 12 version of OpenSSL, 1.0.0-fips, and higher do not show this performance penalty.
99
100
Testing was done similar to the previous tweak
101
```bash
102
./openvpn --dev tun --proto udp --port 11000 --secret secret.key --ifconfig 192.168.222.11 192.168.222.10
103
--tun-mtu 6000 --fragment 0 --mssfix 0 --cipher aes-256-cbc
104
```
105
106
and client
107
108
```bash
109
./openvpn --dev tun --proto udp --port 11000 --secret secret.key --ifconfig 192.168.222.10 192.168.222.11
110
--tun-mtu 6000 --fragment 0 --mssfix 0 --cipher aes-256-cbc --remote server
111
```
112
113
Now an **iperf** result of **407 Mbps** is obtained.
114
115
By playing with the '--tun-mtu' size we obtain (all speeds in Mbps)
116
117
| MTU | Blowfish | AES256 |
118
|-------|----------|--------|
119
| 6000 | 310 | 407 |
120
| 9000 | 385 | 410 |
121
| 12000 | 417 | 478 |
122
| 24000 | 470 | 540 |
123
| 36000 | 510 | 561 |
124
| 48000 | 500 | **585**|
125
| 60000 | 500 | 582 |
126
127
(Please note that for all measurement a standard deviation of ~5% applies)
128
129
For the default Blowfish cipher the optimal value for the 'tun-mtu' parameters for a link between these two servers now seems to be **36000** bytes, although the difference for higher MTU sizes is minimal. Also note that the performance numbers are nearly identical to those generated using the system OpenSSL 0.9.8e-fips library.
130
131
When using the AES-256 cipher there is huge performance gain. The optimal MTU value now is **48000** bytes, but overall performance increased by a factor of 2 for nearly all MTU sizes.
132
133
### Explanation
134
Compiling OpenSSL from scratch doubles the OpenSSL speed by a factor of 2. This can also be seen when running
135
136
```plaintext
137
openssl speed -evp aes-256-cbc
138
```
139
140
This is caused mainly by the fact that the CentOS-supplied OpenSSL 0.9.8e-fips library seems broken. The Fedora 12+ supplied OpenSSL 1.0.0-fips library does not induce the same penalty.
141
142
## Using OpenSSL 1.0.0 with AES-NI capable hardware
143
The real performance gain is expected from the AES-NI capable hardware, such as the Intel Xeon X5660 and i5-560M CPUs.
144
Using the exact same setup as above, but now using
145
a5b5f1 Samuli Seppänen 2025-02-27 09:34:02 146
```
85e264 Samuli Seppänen 2025-02-11 09:28:36 147
engine aesni
148
```
149
150
and by using
151
a5b5f1 Samuli Seppänen 2025-02-27 09:34:02 152
```
85e264 Samuli Seppänen 2025-02-11 09:28:36 153
./openvpn --dev tun --proto udp --port 11000 --secret secret.key --ifconfig 192.168.222.11 192.168.222.10
154
--tun-mtu 9000 --fragment 0 --mssfix 0 --cipher aes-256-cbc --engine aesni
155
```
156
157
for the server and
158
a5b5f1 Samuli Seppänen 2025-02-27 09:34:02 159
```
85e264 Samuli Seppänen 2025-02-11 09:28:36 160
./openvpn --dev tun --proto udp --port 11000 --secret secret.key --ifconfig 192.168.222.10 192.168.222.11
161
--tun-mtu 9000 --fragment 0 --mssfix 0 --cipher aes-256-cbc --engine aesni --remote server
162
```
163
164
for the client we obtain the following results (all speeds in Mbps):
165
166
| | AES128 | AES256 |
167
|---------------|--------|--------|
168
| X5660 -> i5-560 | 885 | 878 |
169
| i5-560 -> X5660 | 748 | 543 |
170
171
(Please note that for all measurement a standard deviation of ~5% applies)
172
173
Some initial conclusions:
174
* the AES-NI capable server CPU clearly shows a huge performance gain: it is nearly capable of saturating the gigabit network.
317afa Samuli Seppänen 2025-02-11 09:31:56 175
* It was not possible to run this test with a more capable client CPU. The i5-560M is not capable of keeping up with the X5660, as can be seen from the performance difference between encryption and decryption. In the first entry in the table above, the X5660 encrypted all traffic, and the i5-560M decrypted it. The second entry shows the results for the reverse.
85e264 Samuli Seppänen 2025-02-11 09:28:36 176
177
## For reference: using no encryption
178
For reference, the above test was also run with encryption and signing disabled:
179
180
```bash
181
openvpn --dev tun --proto udp --port 11000 --secret secret.key --ifconfig 192.168.222.11 192.168.222.10 --tun-mtu 9000 --fragment 0 --mssfix 0 --cipher none --auth none
182
```
183
184
Now an **iperf** result of **930 Mbps** is obtained, which shows that performance is not so much limited by the division between kernel-space and user-space processes, but mostly by the encryption and decryption routines as found in the OpenSSL libraries.
185
186
## 10 Gigabit networks
187
The "plaintext" test (i.e., encryption and signing disabled) was repeated on two machines connected to a 10 Gbps switch.
188
189
Again, all results were obtained using `iperf`.
190
191
| Mode | MTU | Speed |
192
|------------------------------|-------|-------------|
193
| "raw" | 1500 | 8.8 Gbps |
194
| "raw", no cksum offloading | 1500 | 3.8 Gbps |
195
| via tun | 60000 | 3.6 Gbps |
196
| via tun | 48000 | 2.4 Gbps |
197
| via tun | 9000 | 1.3 Gbps |
198
199
This shows the limits of the kernel-space/user-space division that is present in Linux. It also shows how important TCP offloading is: if the TCP checksums need to be calculated in kernel space the performance drops by 50%!
200
201
The performance of OpenVPN over this network is not yet understood, as the raw OpenSSL speed of the computers in this network is much lower than that of servers listed above. Unfortunately, it was not possible to use two AES-NI capable PCs on this network.