Wie bereits mehrmals erwähnt, bin ich seit vielen Jahren mit meinem Glasfaser-Internetanschluss bei der Telepark Passau. Mit der Leistung der Telepark bin ich vollumfänglich zufrieden, allerdings passen sie von Zeit zu Zeit ihre Konfiguration an, was für mich bedeutet, dass ich diese irgendwie in OPNsense abbilden muss, nachdem ich den zur Verfügung gestellten Router in Form einer Firtz!Box nicht nutze.
Telepark hat sich dazu entschieden ab 01. Oktober das Einwahlverfahren auf PPPoE umzustellen und damit eine Authentifizierung mit Usernamen und Passwort einzuführen. Bis vor kurzem erfolgte die „Einwahl“ mit der einfachen Vergabe einer IP-Adresse per DHCP. Internet und Telefonie wurden per VLAN auf dem WAN Port voneinander getrennt – VLAN40 für VoIP und VLAN50 für Internet. In Zukunft erfolgt die Einwahl per PPPoE und VLAN7 auf dieser Verbindung. VoIP und Internet werden nicht mehr voneinander getrennt, beide nutzen VLAN7. Im Endeffekt genauso, wie es auch die Telekom auf ihrem Glasfasernetz macht.
Auf dem Papier klingt das zunächst nach einer relativ überschaubaren Änderung. VLAN anlegen, PPPoE konfigurieren, Zugangsdaten eintragen – fertig.
In der Praxis gab es allerdings eine interessante Nebenwirkung: Mein bisheriger OPNsense-Router erreichte über VLAN 50 an meinem 500Mbit/s-Anschluss rund 550–560 Mbit/s. Nach der Umstellung auf PPPoE waren zunächst nur noch etwa 330 Mbit/s möglich. Die Ursache war nicht die Internetleitung und auch nicht die Firewall selbst. Sie lag in der Art und Weise, wie FreeBSD den PPPoE-Verkehr über Netgraph und NetISR verarbeitete und der Tatsache, dass meine OPNsense Appliance mittlerweile 8 Jahre auf dem Buckel hat und der Pentium N3700 nicht die beste Singlecore-Performance aufweist.
Ausgangssituation
Als Router läuft bei mir eine kleine Supermicro-Plattform (ausführliche Infos und eine Bauanleitung findet ihr hier: Selfmade OPNsense Appliance):
- Supermicro X11SBA-LN4F
- Intel Pentium N3700, 4 Kerne
- 4 × Intel i210 Gigabit Ethernet
- OPNsense 26.7.3_11
- FreeBSD 15.1
- mehrere VLANs
- LAN: 192.168.2.0/24
- DMZ: 192.168.5.0/24
- UniFi-Switches und Access Points
Der bisherige Internetzugang lief über:
igb1
└── VLAN 50
└── WAN
Damit waren etwa 550–560 Mbit/s problemlos möglich (Danke Telepark für den performanten 500Mbit/s-Anschluss!).
Durch die Umstellung des Providers sieht die Struktur nun so aus:
Telepark
│
│ VLAN 7
▼
igb1
│
▼
igb1_vlan7
│
▼
PPPoE
│
▼
pppoe0
│
▼
PPPoE_WAN
Die öffentliche IPv4-Adresse wird dabei über PPPoE bezogen.
Die Umstellung auf PPPoE
Auf OPNsense wird zunächst das neue VLAN auf dem bisherigen WAN-Port eingerichtet:
Parent interface: igb1
VLAN ID: 7
Darauf wird anschließend die PPPoE-Verbindung aufgebaut. Die Zugangsdaten stellt Telepark in ihrem Kundenportal bereit.
In meinem Fall ergibt sich damit:
WAN-Port: igb1
Provider-VLAN: VLAN 7
PPPoE: pppoe0
OPNsense: PPPoE_WAN
MTU/MRU: 1492
Die alte VLAN-50-Konfiguration habe ich an dieser Stelle noch nicht gelöscht. Das ist sinnvoll, da man zunächst prüfen sollte, ob der neue Zugang vollständig funktioniert. Mit der alten VLAN50-Verbindung hat man einen Rückfallweg und kann die PPPoE Verbindung zuerst ausgiebig testen.
Firewallregeln und Port Forwards
Ein wichtiger Punkt bei der Umstellung: PPPoE ist in OPNsense nicht einfach nur ein anderer Weg ins Internet. Das neue PPPoE-Interface wird zu einem eigenen WAN-Interface.
Firewallregeln, NAT-Regeln und Port Forwards müssen deshalb kontrolliert werden.
Beispielsweise kann eine bisherige Regel sinngemäß so ausgesehen haben:
Interface: VLAN50_WAN
TCP 443
→ 192.168.5.100:443
Nach der Umstellung muss diese Regel auf das neue WAN-Interface zeigen:
Interface: PPPoE_WAN
TCP 443
→ 192.168.5.100:443
Dasselbe gilt für weitere von außen erreichbare Dienste.
Unbedingt daran denken, auch die VoIP-Einstellungen anzupassen, die vorher noch auf VLAN40 liefen! Das alte Problem, dass mein Telefon den Namen ngn.telepark-passau.de über VLAN50 nicht auflösen konnte, hat sich übrigens mit der PPPoE-Umstellung erledigt. Internet und VoIP nutzen jetzt das gleiche VLAN, damit funktioniert die Namensauflösung endlich auch im Telefon und ich muss die IP nicht mehr fest hinterlegen.
Kontrolle nach der Umstellung
Mindestens diese Punkte sollte man überprüfen:
- Firewallregeln auf dem WAN
- Port Forwards
- automatisch erzeugte NAT-Regeln
- Outbound NAT
- VPN-Verbindungen
- Gateway und Default Route
- Gateway Groups bzw. Policy Routing
- statische Routen
- DNS
- Dynamic DNS
- Monitoring und Dienste, die explizit das alte WAN-Interface verwenden
Wer Manual oder Hybrid Outbound NAT verwendet, sollte insbesondere kontrollieren, ob dort noch das alte WAN-Interface eingetragen ist. Bei Automatic Outbound NAT sollte OPNsense die neue PPPoE-Adresse normalerweise automatisch berücksichtigen.
Auch Dynamic DNS sollte überprüft werden. Bei PPPoE kann sich die öffentliche Adresse bei einer neuen Verbindung ändern, weshalb der DDNS-Client zuverlässig die aktuelle PPPoE-Adresse erkennen muss.
Erst wenn Internetzugang, NAT, Port Forwards, VPN und DDNS funktionieren, würde ich die alte VLAN-50-Konfiguration endgültig entfernen.
Der erste Geschwindigkeitstest
Nach erfolgreicher Umstellung kam allerdings die Überraschung.
Vorher:
VLAN 50
≈ 550–560 Mbit/s
Nachher:
PPPoE über VLAN 7
≈ 330–350 Mbit/s
Die Internetverbindung selbst war also deutlich langsamer geworden.
Zunächst liegt der Verdacht nahe, dass entweder PPPoE grundsätzlich mehr CPU benötigt oder der kleine Pentium N3700 schlicht an seine Grenzen kommt. Interessant wurde es bei einem Blick auf die CPU-Auslastung.
top -aSH zeigt den eigentlichen Flaschenhals
Während eines Speedtests habe ich mir die Threads mit
top -aSH
angesehen.
Dabei war ein Thread besonders auffällig:
ng_queue{ng_queue1}
Dieser lag während des Downloads bei ungefähr 90 % CPU-Auslastung auf einem einzelnen Kern.
Die anderen Kerne waren dagegen weitgehend unbeschäftigt. Das war der entscheidende Hinweis. Der N3700 hatte nicht einfach insgesamt zu wenig Rechenleistung. Vielmehr wurde ein wesentlicher Teil der PPPoE-/Netgraph-Paketverarbeitung auf einem einzelnen CPU-Kern abgearbeitet.
Die Situation sah vereinfacht so aus:
PPPoE-Verkehr
│
▼
FreeBSD / Netgraph
│
▼
ein CPU-Kern
│
▼
~90 % Last
Der restliche Prozessor hatte noch Reserven, konnte diesen Engpass aber nicht einfach ausgleichen.
NetISR
FreeBSD verwendet für die Verarbeitung von Netzwerkpaketen unter anderem das NetISR-System.
Bei meiner ursprünglichen Konfiguration sahen die relevanten Werte so aus:
net.isr.numthreads: 1
net.isr.maxthreads: 1
net.isr.bindthreads: 0
net.isr.dispatch: direct
Damit war klar, warum die zusätzlichen CPU-Kerne kaum helfen konnten.
Der erste Test war:
sysctl net.isr.dispatch=deferred
Damit wurde die Verarbeitung nicht mehr ausschließlich direkt im jeweiligen Netzwerkpfad abgearbeitet.
Anschließend habe ich die Konfiguration dauerhaft angepasst.
Die drei entscheidenden Einstellungen
In OPNsense lassen sich die Einstellungen über
System → Settings → Tunables
als Loader-Tunables dauerhaft setzen:
net.isr.dispatch = deferred
net.isr.maxthreads = -1
net.isr.bindthreads = 1
Die Bedeutung ist vereinfacht:
net.isr.dispatch = deferred
Die NetISR-Verarbeitung wird in die dafür vorgesehenen NetISR-Threads verschoben, anstatt sie unmittelbar im ursprünglichen Netzwerkpfad abzuarbeiten.
net.isr.maxthreads = -1
Damit wird die maximal mögliche Anzahl der NetISR-Threads automatisch aus der Anzahl der verfügbaren CPU-Kerne abgeleitet.
Auf meinem N3700 mit vier Kernen ergibt sich:
net.isr.maxthreads: 4
net.isr.bindthreads = 1
Die NetISR-Threads werden an CPU-Kerne gebunden. Gerade bei einem kleinen Mehrkernprozessor kann das helfen, die Paketverarbeitung besser über die vorhandenen Kerne zu verteilen.
Wichtig: Neustart erforderlich
Die Einstellungen
net.isr.maxthreads
net.isr.bindthreads
sind Boot-Tunables und lassen sich nicht einfach zur Laufzeit mit sysctl verändern.
Deshalb müssen sie als Loader-Tunables eingetragen und anschließend muss OPNsense neu gestartet werden.
Nach dem Neustart sah die Konfiguration bei mir so aus:
net.isr.numthreads: 4
net.isr.maxthreads: 4
net.isr.bindthreads: 1
net.isr.dispatch: deferred
Damit waren nun tatsächlich mehrere NetISR-Threads vorhanden.
Das Ergebnis
Nach den Änderungen stieg die Geschwindigkeit zunächst auf etwa 400 Mbit/s. Nach der vollständigen Anpassung und dem anschließenden Test erreichte die Verbindung schließlich wieder um die 560 MBit/s!
Damit war praktisch wieder die gleiche Geschwindigkeit wie beim ursprünglichen VLAN-50-Zugang erreicht.
Das Gute daran: Die Hardware musste dafür nicht ausgetauscht werden. Der Pentium N3700 ist keineswegs eine besonders leistungsfähige CPU. Für eine einfache Firewall ist er aber noch völlig ausreichend. Das Problem war vielmehr die Art der Paketverarbeitung. Außerdem: Wer will momentan schon freiwillig neue Hardware anschaffen, bei den utopischen Speicherpreisen. Wobei ich ehrlicherweise sagen muss, dass ich kurz überlegt habe, auf eine Dream Machine Pro Max umzusteigen, da das Problem der doppelten VLANs auf WAN – was die UDMs leider nicht beherrschen – mit der PPPoE-Umstellung passé ist. Dafür verliert man mit einer UDM gegenüber OPNsense die umfangreiche Flexibilität was Addons und Konfigurationsmöglichkeiten angeht.
Was ist mit der CPU-Auslastung?
Bei weiteren Tests tauchten teilweise andere CPU-intensive Prozesse auf. Beispielsweise kann mein NetFlow-Aggregator flowd_aggrega zeitweise einen kompletten CPU-Kern stark auslasten.
Das ist allerdings von der ursprünglichen PPPoE-Problematik zu unterscheiden. Der entscheidende Befund beim ursprünglichen Geschwindigkeitsproblem war der stark ausgelastete Netgraph-/NetISR-Pfad während des PPPoE-Verkehrs.
Die Lösung bestand deshalb nicht darin, wahllos CPU-intensive Dienste abzuschalten, sondern die Netzwerkpaketverarbeitung besser auf die vorhandenen CPU-Kerne zu verteilen.
Und warum schafft eine Fritzbox das scheinbar problemlos?
Eine Fritzbox als Standardgerät, das auch von Telepark zur Verfügung gestellt wird, kann mit einem auf den ersten Blick deutlich schwächeren Prozessor trotzdem hohe PPPoE-Datenraten erreichen.
Der Grund ist, dass man die CPU nicht allein anhand von Taktfrequenz oder Kernanzahl vergleichen sollte.
Ein typischer Consumer-Router verwendet einen hochintegrierten SoC und eine speziell auf die Netzwerkverarbeitung optimierte Firmware. Bestimmte Verarbeitungsschritte können dort wesentlich effizienter oder teilweise hardwarebeschleunigt erfolgen.
Bei OPNsense auf einem x86-System läuft dagegen ein deutlich allgemeinerer Netzwerk-Stack:
Intel i210
│
▼
Ethernet
│
▼
VLAN
│
▼
PPPoE / Netgraph
│
▼
NetISR
│
▼
Firewall / NAT
│
▼
Routing
Diese Flexibilität ist einer der großen Vorteile von OPNsense. Sie bedeutet aber auch, dass ein kleiner x86-Prozessor bei bestimmten Paketverarbeitungsaufgaben an seine Grenzen kommen kann.
Muss man deshalb RSS konfigurieren?
FreeBSD bietet mit RSS (Receive Side Scaling) noch weitere Möglichkeiten, Netzwerkverkehr auf mehrere CPU-Kerne zu verteilen. Bei meiner Installation war das jedoch nicht mehr notwendig.
Nachdem die nachfolgende Tunables gesetzt waren, erreichte die Verbindung bereits wieder die volle Geschwindigkeit von rund 560 Mbit/s
net.isr.dispatch = deferred
net.isr.maxthreads = -1
net.isr.bindthreads = 1
Deshalb würde ich bei einer vergleichbaren Konfiguration nicht einfach weitere Netzwerk-Tuning-Parameter verändern, solange die gewünschte Leistung bereits erreicht wird.
Fazit – TL;DR
Die Umstellung von VLAN 50 auf PPPoE über VLAN 7 war zunächst eine reine Provider- bzw. Konfigurationsänderung. Die eigentliche Überraschung kam anschließend beim Geschwindigkeitstest.
Aus rund 560 Mbit/s wurden zunächst nur etwa 330–350 Mbit/s. Ein Blick mit top -aSH zeigte schließlich, dass nicht die gesamte CPU überlastet war. Stattdessen lief ein wesentlicher Teil der PPPoE-Paketverarbeitung auf einem einzelnen CPU-Kern.
Die entscheidende Änderung waren deshalb:
net.isr.dispatch = deferred
net.isr.maxthreads = -1
net.isr.bindthreads = 1
Nach einem Neustart verteilte FreeBSD die NetISR-Verarbeitung besser auf die vier CPU-Kerne des Pentium N3700.
Das Ergebnis:
VLAN 50: ~550–560 Mbit/s
PPPoE, Standard: ~330–350 Mbit/s
PPPoE + NetISR-Tuning: ~560 Mbit/s
Damit läuft die alte Supermicro-Hardware weiterhin mit voller Anschlussgeschwindigkeit.
Der interessante Teil dieser Umstellung ist für mich deshalb weniger PPPoE selbst als die Erkenntnis, dass bei einer Firewall nicht allein die nominelle CPU-Leistung entscheidend ist. Entscheidend ist auch, wie der Netzwerk-Stack die Paketverarbeitung auf die vorhandenen CPU-Ressourcen verteilt.
Meine finale OPNsense-Konfiguration für PPPoE
WAN-Port: igb1
Provider-VLAN: VLAN 7
PPPoE-Interface: pppoe0
MTU/MRU: 1492
net.isr.dispatch: deferred
net.isr.maxthreads: -1
net.isr.bindthreads: 1
Für andere Hardware oder andere OPNsense-/FreeBSD-Versionen muss das Ergebnis nicht identisch sein. Die drei Einstellungen sind daher kein allgemeines Rezept für eine bestimmte Geschwindigkeit, sondern die Lösung, die auf dieser konkreten Kombination aus OPNsense 26.7, FreeBSD 15.1, Pentium N3700, Intel i210 und PPPoE funktioniert hat.
Ob mit diesen Einstellungen ein Pentium N3700 auch einen 1Gbit/s-Anschluss mit PPPoE bedienen kann, weiß ich nicht, könnte aber durchaus knapp werden – v.a. wenn auf der OPNsense weitere rechenintensive Dienste laufen, wie IDS/IPS. Ob ich langfristig auf eine andere Hardware setzen werde, liegt rein an den Marktpreisen für IT-Hardware, mit dieser Konfiguration konnte ich mir jedenfalls noch etwas Zeit verschaffen :-)
Du hast Fragen, Anregungen oder gar weiteren Input? Gerne einen Kommentar da lassen!
Der Artikel enthält Affiliate-Links zu Amazon die mit einem * gekennzeichnet sind. Kaufst du ein von mir verlinktes Produkt bei Amazon, bekomme ich eine kleine Provision und du unterstützt mich und meine Arbeit. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Dir entstehen keine Nachteile oder Mehrkosten.
