Einleitung
Eigentlich wollte ich nur wissen, warum die Synology Snapshot Replication über WireGuard mit gemütlichen 8 MB/s vor sich hin dümpelt. Bei symmetrischen 10 Gbit/s und potenter OPNsense-Hardware auf beiden Seiten wäre da eigentlich noch deutlich Luft nach oben. 🤨
Also etwas genauer unter die Haube geschaut. Dabei fielen mir Packetloss beziehungsweise Drops auf - und aus dem kurzen Nachschauen wurde, wie so oft, eine etwas längere Tuning-Session. 🔧
Der Vorzustand
Die 8 MB/s der Snapshot Replication waren der Auslöser. Bevor ich an OPNsense etwas verändert habe, wollte ich deshalb erst einmal wissen, was der Tunnel unabhängig von Synology überhaupt hergibt.
Die ersten iPerf3-Tests waren ziemlich ernüchternd. Ein einzelner TCP-Stream in Reverse-Richtung startete noch mit knapp 400 bis 550 Mbit/s, brach während des Tests aber immer weiter ein:
|
|
Auch vier parallele gaben ein ähnliches Bild ab:
|
|
Dazu kamen 4154 Retransmits auf Senderseite.
In der Gegenrichtung sah es ebenfalls nicht wirklich nach einem 10G-Setup aus:
|
|
Ein einzelner Stream lag bei etwa 356 Mbit/s:
|
|
Damit war zumindest klar: Das Problem war nicht nur die Snapshot Replication. Im Netzwerkpfad selbst gab es ebenfalls etwas zu untersuchen.
Hardware
| Hardware | Site A | Site B |
|---|---|---|
| Mainboard | Supermicro X11SDV-4C-TP8F | Supermicro X10SDV-8C-TLN4F |
| CPU-Generation | Xeon D, Skylake | Xeon D, Broadwell |
| CPU-Kerne | 4 | 8 |
| RAM | 32 GB ECC | 32 GB ECC |
| Anschluss | 10 Gbit/s | 10 Gbit/s |
| WireGuard | Dual Stack (IPv4 + IPv6) | Dual Stack (IPv4 + IPv6) |
Site A setzt mit dem X11SDV-4C-TP8F zwar nur auf vier CPU-Kerne, dafür aber auf die neuere Skylake-basierte Xeon-D-Generation. Site B bringt mit dem X10SDV-8C-TLN4F acht Kerne mit, basiert jedoch noch auf den älteren und pro Kern langsameren Broadwell-Xeon-Ds.
OPNsense
Auf beiden Seiten sind aktuelle Versionen von OPNsense im Einsatz:
| Software | Site A | Site B |
|---|---|---|
| OPNsense | Business Edition 26.4.1p2 | Community 26.7.1_1 |
Drops und netisr
Auf Site A wurde es dann konkreter. netstat -Q zeigte, dass ein
IPv4-Workstream seine Queue tatsächlich bis zum Limit von 1000 gefüllt
hatte:
|
|
Passend dazu:
|
|
Die 589 Drops waren für mich der erste handfeste Hinweis, dass die Paketverarbeitung unter Last tatsächlich an eine Grenze gelaufen war.
RSS
Eine der Änderungen war das Aktivieren von Receive Side Scaling(RSS). Gerade bei 10-Gbit-Interfaces ist es sinnvoll, die Paketverarbeitung auf mehrere CPUs beziehungsweise Queues verteilen zu können.
Auf beiden Firewalls ist nun RSS aktiviert:
|
|
Dazu laufen auf beiden Seiten:
|
|
maxthreads=-1 lässt FreeBSD die Anzahl der verwendeten CPUs
automatisch bestimmen. Mit bindthreads=1 werden die netisr-Threads an
CPUs gebunden.
Queues
Die relevanten Queues habe ich nach diversen Tests auf beiden Firewalls auf 2048 gesetzt:
|
|
IPv4 und IPv6 sind damit an dieser Stelle gleich behandelt. Nach der
Änderung zeigte netstat -Q für IPv4 entsprechend:
|
|
Der bereits aufgelaufene Drop-Counter wird dadurch natürlich nicht zurückgesetzt. Entscheidend war, dass er bei den anschliessenden Tests nicht weiter hochlief.
Das Ganze ist übrigens nicht WireGuard-spezifisch. Die Queue- und RSS-Anpassungen betreffen den normalen Netzwerk-Stack und sind damit auch für den übrigen Traffic interessant.
Tunables
| Tunable | Site A | Site B | Zweck |
|---|---|---|---|
net.inet.rss.enabled |
1 |
1 |
RSS aktivieren |
net.inet.rss.bits |
2 |
3 |
4 bzw. 8 RSS-Buckets |
net.isr.maxthreads |
-1 |
-1 |
Thread-Anzahl automatisch |
net.isr.bindthreads |
1 |
1 |
netisr-Threads an CPUs binden |
net.isr.defaultqlimit |
2048 |
2048 |
netisr Queue-Limit |
net.link.ifqmaxlen |
2048 |
2048 |
Interface Send Queue |
net.inet.ip.intr_queue_maxlen |
2048 |
2048 |
IPv4 Input Queue |
net.inet6.ip6.intr_queue_maxlen |
2048 |
2048 |
IPv6 Input Queue |
hw.ixl.enable_head_writeback |
0 |
0 |
ixl Head Writeback |
hw.vtnet.csum_disable |
1 |
1 |
vtnet Checksum-Offload deaktivieren |
vm.numa.disabled |
1 |
0 |
NUMA-Verhalten der Plattform |
Die unterschiedlichen RSS-Bits sind Absicht: 2 entspricht vier
RSS-Buckets auf Site A, 3 entsprechend acht auf Site B.
Nicht jede Zeile in dieser Tabelle war die Lösung für mein Problem. Sie dokumentiert aber den relevanten Stand der beiden Firewalls.
MTU & MSS
An der WireGuard-MTU selbst habe ich bewusst nicht herumoptimiert. Sie steht auf beiden Seiten beim Default von:
|
|
Statt die MTU des Tunnels zu verändern, habe ich mich bei den Tests auf MSS Clamping über die Firewall-Normalization-Regeln von OPNsense konzentriert.
Mit MSS 1360 wurde das Bild bereits deutlich besser. Bei vier Reverse-Streams waren über 1 Gbit/s drin:
|
|
Danach habe ich noch MSS 1340 getestet. Nicht jeder einzelne Lauf war damit schneller – die Resultate schwankten teilweise deutlich –, insgesamt gefiel mir das Verhalten aber besser.
Aktuell laufen deshalb beide Seiten mit:
|
|
Die WireGuard-MTU bleibt damit unangetastet. Mit XGS-PON irgendwo im Pfad nehme ich beim MSS lieber ein paar Bytes Reserve mit.
UDP war unschuldig
Da WireGuard UDP verwendet, hatte ich zwischendurch auch die UDP-Buffer im Verdacht.
Die Statistik war allerdings ziemlich eindeutig:
|
|
Auch bei den mbufs gab es keinen Hinweis auf einen Engpass:
|
|
An den UDP- und Socket-Buffern habe ich deshalb nichts verändert. Man muss ja nicht an jeder Schraube drehen, nur weil sie da ist.
Nach den Änderungen
Ein guter Single-Stream-Lauf mit MSS 1340 sah danach beispielsweise so aus:
|
|
Der Durchschnitt erzählt hier nur einen Teil der Geschichte. Vorher war schon bei einem einzelnen Stream gut zu sehen, wie der Durchsatz im Test bis auf 76 Mbit/s absackte. Nach den Anpassungen waren Peaks von 700 bis knapp 800 Mbit/s möglich.
Noch deutlicher wird der Unterschied mit vier parallelen Streams:
|
|
Zum Vergleich: Einer der frühen -R -P 4-Tests kam auf 553 Mbit/s
im Mittel. Nach den Anpassungen waren es in diesem Lauf 1.28 Gbit/s.
Ganz verschwunden sind die TCP-Retransmits allerdings nicht. Das Setup ist also nicht plötzlich perfekt – aber das Bild ist ein deutlich anderes als am Anfang. 😎
Fazit
Auslöser für die ganze Aktion waren die 8 MB/s bei der Synology Snapshot Replication. Dabei kamen mit Packetloss, Queue-Drops und vielen TCP-Retransmits allerdings noch ein paar andere Baustellen zum Vorschein.
Nach RSS, grösseren Queues und MSS-Clamping sieht der Netzwerkpfad deutlich besser aus. Aus rund 553 Mbit/s mit vier Streams wurden in späteren Tests bis zu 1.28 Gbit/s über WireGuard.
Das eigentliche Problem konnte ich damit allerdings nicht lösen: Die Synology Snapshot Replication blieb langsam.
Für die Replikation bin ich deshalb schliesslich auf rclone mit mehreren parallelen Streams umgestiegen. Damit stieg der Durchsatz massiv – und die optimierte Netzwerkverbindung kann nun auch tatsächlich besser ausgenutzt werden.
Unterm Strich also nicht ganz die Lösung, nach der ich ursprünglich gesucht hatte, aber immerhin läuft der 10G-/WireGuard-Pfad jetzt deutlich besser. 🙂