Technische Universität Ilmenau Fakultät für Elektrotechnik und Informationstechnik

Bachelorarbeit

Entwicklung eines programmierbaren User-Space-Switches

vorgelegt von: Carsten Andrich

eingereicht am: 15. 05. 2014

geboren am:

Studiengang: Elektrotechnik und Informationstechnik

Studienrichtung: Informations- und Kommunikationstechnik

Anfertigung im Fachgebiet: Kommunikationsnetze

Fakultät für Elektrotechnik und Informationstechnik

Verantwortlicher Professor: Prof. Dr. rer. nat. Jochen Seitz

Wissenschaftlicher Betreuer: M.Sc. Markus Hager

Kurzfassung

Unsere moderne Informationsgesellschaft ist auf leistungsfähige Netzwerktechnologien angewiesen. Dazu zählt auch Ethernet, das heute nahezu exklusiv für kabelgebundene lokale Netzwerke eingesetzt wird. Da die Anforderungen an solche Netze exponenti- ell wachsen, wird der Ethernet-Standard kontinuierlich weiterentwickelt, wobei neben einer Steigerung der Übertragungsgeschwindigkeit auch Protokolle für die Umsetzung von Dienstgütegarantien im Mittelpunkt der Forschung stehen. Zur Unterstützung der Entwicklung neuer Protokolle stellen sowohl computergestützte Simulationen als auch Testnetzwerke probate Erprobungsmittel dar, wobei für Letztere programmierba- re Switches benötigt werden. Ein solcher Switch wird in dieser Arbeit als Anwendung im User-Space entwickelt. Aufgrund von Unzulänglichkeiten bezüglich der Programmierbarkeit bestehender Software-Switches wird eine Neuimplementation in Angriff genommen. Im Fokus liegt dabei eine effiziente und skalierende Umsetzung der Ethernet-Frameweiterleitung mit- tels Multi-Threading. Es erfolgt zunächst eine detaillierte Untersuchung verschiede- ner Linux-APIs, Threading-Modelle, nebenläufigen Datenstrukturen und Synchroni- sationsoperationen. Unter Abwägung der Resultate wird dann ein simpler, program- mierbarer Switch implementiert. Abschließende Untersuchungen zeigen, dass dieser größtenteils mit Hardware-Switches vergleichbare Leistungscharakteristiken aufweist. Zusätzlich wird weiteres Optimierungspotenzial anhand konkreter Beispiele identifi- ziert.

Abstract

High-capacity networking technology plays an integral part in our modern information society. As such a technology, Ethernet is nowadays almost exclusively employed for wired local area networks. The associated standard is continuously refined to meet the exponentially growing requirements for these networks. Primary objects of current research are the increase of transfer rate and protocols for quality of service guarantees. To support the development of new protocols, both computer-aided simulations and test networks are used as suitable means of evaluation, whereupon the latter require programmable switches. In this thesis such a switch is being developed as a Linux user-space application. A reimplementation is conducted, since existing software switches suffer from shortcomings regarding programmability. The development focuses on an efficient and scalable realization of Ethernet frame-forwarding via multi-threading. Preparatorily, multiple Linux APIs, threading models, concurrent data structures and synchroniza- tion methods are examined in detail. Based on the results a simple yet programmable switch is then implemented. Concluding analyses show that it mostly features perfor- mance characteristics comparable to those of hardware switches. Additionally, further potential for optimization is identified with the help of concrete examples.

Inhaltsverzeichnis i

Inhaltsverzeichnis

1 Problemstellung 1 1.1 Motivation ...... 1 1.2 Aufgabe ...... 3 1.3 Related Work ...... 4 1.3.1 Linux Bridge ...... 4 1.3.2 OpenFlow Protokoll ...... 6 1.3.3 Open vSwitch ...... 9 1.3.4 Zusammenfassung ...... 12 1.4 Anforderungen ...... 13

2 Lösungsansatz 15 2.1 Entwicklungshardware ...... 15 2.1.1 NIC-Speicherzugriff ...... 16 2.1.2 CPU-Speicherzugriff ...... 17 2.1.2.1 Latenz ...... 18 2.1.2.2 Datenrate ...... 19 2.1.3 Zusammenfassung ...... 20 2.2 Messsoftware ...... 21 2.2.1 Paketgenerierung ...... 21 2.2.2 Paketempfang ...... 22 2.2.3 Fazit ...... 23 2.3 Messverfahren ...... 23 2.3.1 Ethernet-Paketformat ...... 23 2.3.2 Standardisierte Verfahren ...... 25 2.3.3 Vereinfachte Messmethodik ...... 25 2.3.3.1 Implementation ...... 27 2.3.3.2 Messergebnisse ...... 28 2.3.3.3 Folgerungen ...... 33 2.4 Zusammenfassung ...... 34

Bachelorarbeit Carsten Andrich ii Inhaltsverzeichnis

3 Implementation 35 3.1 Entwicklungsumgebung ...... 35 3.2 Grundlagen ...... 35 3.2.1 recvfrom()/sendto() ...... 36 3.2.2 PACKET_RX_RING/PACKET_TX_RING ...... 37 3.2.3 Fazit ...... 39 3.3 Multi-Threading ...... 40 3.3.1 Statisches Thread-Modell ...... 40 3.3.2 Synchronisationsmechanismen ...... 42 3.3.3 Zusammenfassung ...... 46 3.4 Prioritätswarteschlange ...... 47 3.4.1 Datentyp ...... 47 3.4.2 Umsetzung ...... 48 3.4.3 Optimierungsmöglichkeiten ...... 50 3.5 Programmierinterface ...... 51 3.5.1 Beispiele ...... 52 3.5.1.1 Hub ...... 52 3.5.1.2 Switch ...... 52

4 Ergebnisbewertung 55 4.1 Quantitativ ...... 55 4.1.1 PLUS-Konfigurationen ...... 55 4.1.1.1 Framerate ...... 56 4.1.1.2 Latenz ...... 57 4.1.1.3 Schlussfolgerungen ...... 59 4.1.2 Switches ...... 59 4.1.2.1 Framerate ...... 60 4.1.2.2 Latenz ...... 61 4.1.2.3 Schlussfolgerungen ...... 63 4.1.3 Zusammenfassung ...... 63 4.2 Qualitativ ...... 64

5 Zusammenfassung mit Ausblick 65

A Alternative Thread-Modelle 69 A.1 Dynamische Thread-Modelle ...... 69 A.1.1 Gemeinsamer Ringpuffer ...... 70

Bachelorarbeit Carsten Andrich Inhaltsverzeichnis iii

A.1.2 Private Ringpuffer ...... 71 A.1.3 Fazit ...... 72 A.2 Erweitertes statisches Thread-Modell ...... 72

B Inhaltsverzeichnis Datenträger 73

Literaturverzeichnis 75

Abbildungsverzeichnis 79

Tabellenverzeichnis 81

Quellcodeverzeichnis 83

Abkürzungsverzeichnis und Formelzeichen 85

Thesen zur Bachelorarbeit 87

Erklärung 89

Bachelorarbeit Carsten Andrich

1

1 Problemstellung

1.1 Motivation

Netzwerktechnologien spielen in unserer modernen Informationsgesellschaft eine zen- trale Rolle. Für Local Area Networks (LAN) hat sich Ethernet sowohl im privaten als auch im professionellen Umfeld als De-facto-Standardtechnik zur Vernetzung etabliert. Ethernet wurde im Jahr 1983 vom Institute of Electrical and Electronics Engineers (IEEE) in Form der IEEE-Norm 802.3 standardisiert und konnte die konkurrierenden Standards Token Ring [IEE01] und Token Bus [IEE90] faktisch vom Markt verdrängen. Im Verlauf der letzten 30 Jahre hat sich Ethernet einem erheblichen Wandel un- terzogen, um mit den exponentiell gestiegenen Anforderungen moderner Kommuni- kationsnetze schritthalten zu können. Anfänglich war lediglich 10-Mbit/s-Ethernet unter Verwendung von Kupfer-Koaxialkabel bei einer maximalen Segmentlänge von 100 Metern standardisiert. Inzwischen wird hauptsächlich Twisted-Pair-Kupfer- und Glasfaserkabel eingesetzt, wobei Letzteres 100-Gbit/s-Ethernet über Segmentlängen von mindestens 40 Kilometern ermöglicht. Das ursprünglich für Ethernet entwickel- te Mehrfachzugriffsverfahren Carrier Sense Multiple Access with Collision Detection (CSMA/CD) wurde mit dem flächendeckenden Einsatz von Switches und Vollduplex- Verbindungen obsolet. Natürlich stagniert die Weiterentwicklung des Ethernet-Standards nicht, sondern wird kontinuierlich vorangetrieben. Besonderes Interesse gilt hier nicht nur einer wei- teren Erhöhung der Übertragungsgeschwindigkeit, sondern ebenfalls neuen Möglich- keiten, die steigenden Dienstgüteanforderungen zu erfüllen und dabei die bewährte Switch-basierte Infrastruktur von Ethernet beizubehalten. Hierzu zählen unter ande- rem:

• IEEE 802.1Qau Congestion Notification

• IEEE 802.1aq Shortest Path Bridging

• IETF RFC 6326 Transparent Interconnection of Lots of Links

Bachelorarbeit Carsten Andrich 2 1 Problemstellung

Für die Entwicklung sowie Evaluation solcher neuer Standards stellen softwarebasierte Netzwerksimulatoren ein adäquates Werkzeug dar. Im Gegensatz zur Implementation in Hardware sind Simulationen kostengünstig, vergleichsweise wenig zeitaufwändig in der Realisierung und erlauben eine nahezu unbegrenzte Skalierung des untersuchten Systems. Letzteres ist für die Entwicklung von Standards im Bereich der Dienstgüte von besonderer Bedeutung, da sich Auswirkungen vor allem in großen Netzwerken erkennen lassen, deren testweiser Aufbau mit hohen Kosten verbunden ist. Allerdings setzen Simulationen meist ideale Rahmenbedingungen voraus, weshalb Simulationsergebnisse nicht direkt auf Produktivnetze1 übertragen werden können. Als besondere Herausforderung tritt hier die Heterogenität2 von Produktivnetzen her- vor, denn diese werden zumeist mit einer Vielzahl von Komponenten unterschiedlicher Hersteller und Baujahre betrieben, die auf verschiedene Hardware, Firmware und/oder Betriebssysteme setzen. Dies trifft sowohl auf die Switches, die im Netzinneren zum Einsatz kommen, als auch besonders ausgeprägt auf die Endknoten zu. Deren Cha- rakteristika können von Simulationen nur bedingt wiedergegeben werden, was unter anderem mit der Komplexität des zu simulierenden Gesamtsystems oder der Abge- schlossenheit proprietärer Komponenten begründet werden kann. Dennoch ist für die Wirtschaftlichkeit von Produktivnetzen ein Investitionsschutz in Form von Abwärts- kompatibilität erforderlich, die auch vom Ethernet-Standard vorgesehen wird, obwohl darin potentiell ein Innovationshemmnis besteht. Um neue Standards oder deren Entwürfe unter möglichst realitätsnahen Bedin- gungen evaluieren zu können, ist somit die Erprobung in einem Testnetz erforderlich. Switches, als zentrale Komponenten moderner Ethernet-Netzwerke, müssen folglich auch in Testnetzen herangezogen werden. Hardware-Switches sind jedoch im Regelfall proprietäre Systeme, die lediglich über einen vom Hersteller definierten Funktionsum- fang verfügen. Die Implementation liegt in der Regel nur in Binärform vor und kann darüber hinaus nicht erweitert werden, was eine Verwendung zur Erprobung experi- menteller Technologien ausschließt. Als Alternative bietet sich die Verwendung eines Software-Switches an, dessen gesamter Funktionsumfang in Software implementiert wird und somit einfach modifi- ziert werden kann. Aufbauend auf einem mit mehreren Netzwerkkarten ausgestatteten Server, einem vorzugsweise frei verfügbaren Betriebssystem und einer entsprechenden Software kann so ein vollständig programmierbarer Switch geschaffen werden.

1Ethernet-Netzwerke, die im Produktiveinsatz genutzt werden; also keine Testnetzwerke 2 Heterogenität bezieht sich hier auf Switches und Endknoten, sowie die Tatsache, dass mit Ethernet- Netzwerken auch Daten des Layer-2-kompatiblen Standards für Drahtlosnetzwerke IEEE 802.11 WLAN übertragen werden, ohne dass eine vorherige Umwandlung des Frameformats erfolgt.

Bachelorarbeit Carsten Andrich 1.2 Aufgabe 3

1.2 Aufgabe

Ziel dieser Arbeit ist die Entwicklung eines Software-Switches auf Basis des freien Betriebssystemkernels Linux. Im Fokus liegt hierbei eine möglichst einfache Program- mierbarkeit des Switches, weshalb sich von vornherein gegen eine Implementation im Kernel-Space entschieden wurde. Diese sollte zwar die bestmögliche Performance garantieren, da sich so zumin- dest theoretisch direkt auf die Netzwerk-Hardware zugreifen lässt, verkompliziert aber ansonsten die Programmierbarkeit erheblich. Der im User-Space sonst typische Ent- wicklungszyklus aus Programmieren, Kompilieren und Debuggen muss hier um das Laden bzw. Austauschen der kompilierten Kernelmodule ergänzt werden. Darüber hinaus ist die Programmierung von Kernelmodulen vergleichsweise an- spruchsvoll. Auf externe Bibliotheken, inklusive der C-Standardbibliothek, kann nicht zurückgegriffen werden. Als Programmiersprache kann lediglich C (kein C++) genutzt werden [LKM09] und sonst triviale Aufgaben wie die Laufzeit-Konfiguration erfordern die Kenntnis des Kernel Application Programming Interface (API). Dieses ist nicht stabil, was Kernel-Entwickler Greg Kroah-Hartman ausführlich begründet [KH+11]. Der im Rahmen dieser Arbeit zu entwickelnde Switch und darauf aufbauender Pro- grammcode, der vom Kernel API Gebrauch macht, läuft somit Gefahr für die Nutzung auf neueren Kernel-Versionen zuerst modifiziert werden zu müssen. Das Debuggen von Kernelmodulen gestaltet sich ebenfalls komplizierter als dies bei User-Space Programmen der Fall ist. Der eingesetzte Kernel muss für das Bereit- stellen der Debug-Schnittstelle konfiguriert sein3. Ist dies nicht der Fall, ist zunächst ein Neukompilieren des Kernels mit dieser Konfiguration erforderlich. Durch Ankopplung eines Debuggers an diese Schnittstelle kann das Verhalten des entwickelten Kernel- moduls untersucht werden. Im Vergleich zum Debuggen im User-Space müssen aber einige Besonderheiten beachtet werden. Z.B. ist ein Anhalten der Ausführung des Ker- nels zur Untersuchung von Datenstrukturen logischerweise nicht möglich, was im User- Space kein Problem darstellt. Darüber hinaus kann die in Entwicklungsumgebungen typische Debugger-Integration beim Debuggen von Kernelmodulen nicht in gewohnter Weise genutzt werden. Um diese Schwierigkeiten zu umgehen und insbesondere um Inkompatibilitäten mit Änderungen des instabilen Kernel-APIs vorzubeugen, soll die Implementation des programmierbaren Switches vollständig im User-Space erfolgen. Dennoch ist eine mög- lichst performante Umsetzung der Funktionalität als zentrales Designziel anzusehen.

3 erfordert die Kconfig Optionen CONFIG_PROC_KCORE=y, CONFIG_DEBUG_INFO

Bachelorarbeit Carsten Andrich 4 1 Problemstellung

1.3 Related Work

Es ist naheliegend, dass bereits mehrere Software-Switches auf Basis von Linux exis- tieren. Um zu untersuchen, ob sich eine der Implementationen als Grundlage für die Entwicklung eines programmierbaren Switches nutzen lässt, werden die folgenden Im- plementationen näher betrachtet:

• Linux Bridge Implementation eines Switches im Mainline Linux-Kernel

• OpenFlow Protokoll Offenes Protokoll zur Steuerung der Paket-Weiterleitung in Hardware-Switches über externe Software

• Open vSwitch Software-Switch für den Einsatz in Virtualisierungsumgebungen

Hierfür sollen soweit möglich die folgenden Kriterien zu Rate gezogen werden:

• Funktionsumfang Umfang der im unmodifizierten Zustand bereitgestellten Funktionen

• Performance Theoretische oder experimentell bestätigte Leistungsfähigkeit

• Programmierbarkeit Möglichkeit der Erweiterung bzw. Änderung des Verhaltens

Eine weitere, Linux Switching Appliance (LISA) genannte, Implementation wird hier nicht untersucht, da es sich um ein inoffizielles Kernel-Modul handelt. Problematisch hieran ist die mangelnde Unterstützung für aktuelle Kernel-Versionen [LIS10].

1.3.1 Linux Bridge

Der Linux Kernel stellt bereits seit Version 2.2 eine Switch-Funktionalität bereit [Lin09]. Die Einrichtung sowie Konfiguration erfolgt über die Userspace-Tools brctl, bridge und ip4 bzw. über das sysfs-Dateisystem. Zusätzlich dazu kann über ebtables der Linux netfilter konfiguriert und somit das Frame-Forwarding grundsätzlich beeinflusst werden. Der Shellcode-Auszug 1.1 zeigt exemplarisch die Einrichtung eines Switches mit 2 Ports. 4ip wird hier anstelle des obsoleten ifconfig eingesetzt

Bachelorarbeit Carsten Andrich 1.3 Related Work 5

Quellcode 1.1: Linux Bridge einrichten

1 # ip-konfiguration zuruecksetzen 2 ip addr flush dev eth0 3 ip addr flush dev eth1

5 # bridge anlegen und ports hinzufuegen 6 brctl addbr br0 7 brctl addif br0 eth0 8 brctl addif br0 eth1

10 # bridge aktivieren 11 ip link set dev br0 up

Funktionsumfang

Linux Bridge bietet in neueren Kernel Versionen unter anderem Unterstützung für

(STP),

• Virtual Local Area Network (VLAN) und

• effizientes Multicast-Forwarding mittels Internet Group Management Protocol (IGMP) und Multicast Listener Discovery (MLD) snooping.

Performance

Experimentelle Untersuchungen haben gezeigt, dass Latenz und Datendurchsatz, die mit Linux bridge erreicht werden, mit Hardware-Switches vergleichbar sind, sofern ausreichend Systemressourcen zur Verfügung stehen [Yu04][Ros11].

Programmierbarkeit

Als vollständig im Kernel umgesetzte Implementation gestaltet sich die Programmier- barkeit zumindest partiell problematisch, weshalb sich bereits in der Aufgabenstellung auf eine reine User-Space Umsetzung beschränkt wurde. Abhilfe kann hier potentiell der designierte netfilter-Ablöser nftables schaffen. Im Gegensatz zu netfilter, dessen gesamte Filter-Logik im Kernel implementiert ist, nutzt nftables lediglich eine vom Kernel bereitgestellte Bytecode-basierte State-Machine5. Die Filter-Regeln werden vollständig im User-Space definiert und im Bytecode über- setzt. Anschließend muss nur der Bytecode in den Kernel geladen werden.

5Funktionsweise ist vergleichbar mit Berkeley Packet Filter (BPF)

Bachelorarbeit Carsten Andrich 6 1 Problemstellung

Es bietet sich prinzipiell an, das Frame-Forwarding von Linux bridge mittels nftables-Regeln aus dem User-Space programmierbar zu machen. Zum Zeitpunkt der Erstellung dieser Arbeit wurde mit Linux 3.13 lediglich rudimentäre nftables-Unter- stützung implementiert. Insbesondere ein nützliches Debugging-Interface soll erst in eine zukünftige Linux-Version integriert werden. Hinzu kommt, dass die erforderli- chen User-Space Programme und Bibliotheken zusammen mit Kernel-Version 3.13 bis- her von keiner verbreiteten Linux-Distribution angeboten werden. Somit kann eine nftables-basierte Lösung vorerst nicht weiter verfolgt werden.

1.3.2 OpenFlow Protokoll

Bei OpenFlow handelt es sich um ein offenes Protokoll, das mit dem Ziel entwickelt wird, Software-Defined Networking (SDN) auf proprietärer Hardware zu ermöglichen. Hierfür wird die Funktionsweise eines Switches abstrahiert und auf zwei Komponenten aufgeteilt (Details erläutert das OpenFlow Whitepaper [Ope12]):

• Die control plane untersucht eingehende Pakete und entscheidet z.B. anhand von Protokollhea- dern und Adresstabellen ob bzw. auf welchen Ports diese gesendet werden sollen. Konzeptionell soll die control plane eine Abstraktion der Hardware-spezifischen Besonderheiten der Paketweiterleitung ermöglichen.

• Die data plane bzw. forwarding plane setzt die Entscheidung der control plane in Form der tatsächlichen Datenüber- tragung um. Hierzu gehören unter anderem Hardware-Interaktion und andere Switch-spezifische Operationen, für die keine Verallgemeinerung möglich ist.

Das OpenFlow Protokoll ermöglicht einen standardisierten Zugriff auf die control plane von Switches, während die data plane weiterhin unzugänglich bleibt, wie dies in pro- prietärer Hardware meist der Fall ist. Letzteres stellt jedoch für SDN kein Hindernis dar, da lediglich über die Weiterleitung von Paketen entschieden werden muss, jedoch kein Einfluss auf die tatsächliche Datenübertragung erforderlich ist. Der Zugriff auf die control plane erfolgt über einen sogenannten OpenFlow Con- troller, der in Software implementiert ist und auf einem gewöhnlichen Server betrie- ben werden kann. Der Controller kommuniziert über eine idealerweise verschlüsselte Netzwerkverbindung mit der control plane des Switches und trifft die Weiterleitungs- entscheidungen. Im Vergleich zur Funktionsweise herkömmlicher Hardware-Switches handelt es sich dabei um einen zeit- und ressourcenintensiven Prozess, der nicht für

Bachelorarbeit Carsten Andrich 1.3 Related Work 7 jedes einzelne Paket durchgeführt werden kann, da ansonsten die Performance des Switches erheblich degradiert würde. Pakete werden deshalb Datenflüssen (sog. Flows) zugeordnet und die Entschei- dung des Controllers zu Beginn eines neuen Datenflusses von der control plane zwi- schengespeichert. Die Weiterleitungsentscheidung kann dann für bestehende Flows von der control plane selbst getroffen werden. Abbildung 1.1 illustriert dieses Funktions- prinzip. Switch OpenFlow Controller OpenFlow-

Erstes Weitere Paket Pakete

Abbildung 1.1: Funktionsprinzip des OpenFlow Protokolls

MAC src MAC dst IP src IP dst TCP dpt ... Action Count * 10:20:... * * * * port 1 250 * * * 5.6.7.8 * * port 2 300 * * * * 25 * drop 892 * * * 192.* * * local 120 * * * * * * controller 11

Tabelle 1.1: Beispiel einer OpenFlow Flow-Tabelle

Die Gruppierung von Paketen in Datenströme erfolgt anhand der Kopfdaten diver- ser Protokolle der Schichten 2 bis 4 des Open Systems Interconnection (OSI) Modells und mithilfe einer sog. Flow-Tabelle, wie sie Tabelle 1.1 exemplarisch zeigt. Eingehende Pakete werden anhand der Header

• Media Access Control (MAC) Quell-/Zieladresse,

Bachelorarbeit Carsten Andrich 8 1 Problemstellung

(IP) Quell-/Zieladresse und

• Transmission Control Protocol (TCP) Zielport einer Aktion in der Flow-Tabelle zugeordnet. Zu den möglichen Aktionen gehören unter anderem

• die Weiterleitung des Pakets an einen oder mehrere Ports,

• das Verwerfen des Pakets oder

• die Konsultation eines Controllers.

In letzterem Fall wird das gesamte Paket an einen Controller weitergeleitet, der ent- scheidet, wie das Paket behandelt werden soll und gegebenenfalls die Flow-Tabelle des anfragenden Switches ergänzt oder modifiziert. Es besteht natürlich die Möglichkeit für mehrere Switches denselben Controller zu nutzen und somit eine zentrale Steuerung der Datenflüsse in größeren Netzwerken zu realisieren.

Funktionsumfang

Der Funktionsumfang ist abhängig von der dem OpenFlow-Switch zugrundeliegenden Software oder Hardware und der unterstützten OpenFlow Version.

Performance

Sowohl auf Software- als auch auf Hardware-Implementationen werden mit dem Open- Flow Protokoll vergleichbare Leistungsdaten erreicht, wie mit herkömmlichen Switching- Methoden [Mat09][Sü11].

Programmierbarkeit

OpenFlow abstrahiert die Übermittlung von Paketen in Form von Datenströmen und stellt lediglich die Möglichkeit zur Verfügung, diese zu dirigieren. Die Spezifikation definiert die jeweiligen Protokolle und deren Header, die als Felder in Flow-Tabellen genutzt werden können, und bietet keine Möglichkeit benutzerdefinierte Daten zu ver- senden. Dies schränkt die Programmierbarkeit von OpenFlow Switches erheblich ein und macht diese für die Protokollentwicklung ungeeignet, da unter anderem keine Wei- terleitungsentscheidungen auf Basis einzelner Pakete getroffen werden können, um z.B. Congestion-Management Algorithmen zu implementieren.

Bachelorarbeit Carsten Andrich 1.3 Related Work 9

1.3.3 Open vSwitch

Open vSwitch (OvS) ist ein sogenannter virtueller Switch, der primär für SDN in ver- teilten, virtualisierten Umgebungen konzipiert ist und das OpenFlow Protokoll mit einigen virtualisierungsspezifischen Erweiterungen unterstützt [OvS14]. Ein typisches Anwendungsszenario zeigt Abbildung 1.2. Open vSwitch verbindet dort virtuelle Netz- werkkarten (virtual Network Interface Controller (vNIC)) von mehreren virtuellen Maschinen (VM) mit physikalischen Netzwerkkarten (physical Network Interface Con- troller (pNIC)) des VM-Host, die die Verbindung zu einem physikalischen Netzwerk herstellen.

Abbildung 1.2: Anwendungsbeispiel Open vSwitch

Trotz dessen Fokus auf Virtualisierung lässt sich Open vSwitch natürlich dennoch ausschließlich zum Switchen von pNICs einsetzen. Das Shellcode-Snippet 1.2 zeigt die zum Linux Bridge Beispiel äquivalente Einrichtung eines Switches mit 2 Ports.

Quellcode 1.2: Open vSwitch einrichten

1 # ip-konfiguration zuruecksetzen 2 ip addr flush dev eth0 3 ip addr flush dev eth1

5 # bridge anlegen und ports hinzufuegen 6 ovs-vsctl -- --may-exist add-br br0 7 ovs-vsctl -- --may-exist add-port br0 eth0 8 ovs-vsctl -- --may-exist add-port br0 eth1

Bachelorarbeit Carsten Andrich 10 1 Problemstellung

Funktionsumfang

Open vSwitch bietet neben der bereits vom Linux Bridge bereitgestellten VLAN- und STP-Unterstützung unter anderem noch

• feinkörnig konfigurierbare Dienstgütekontrolle (Quality of Service (QoS)),

• Bündelung von Netzwerkkarten zur Lastverteilung oder als Rückfalloption,

• Spiegelung von Ports,

• Protokoll zur Fernkonfiguration mit C und Python Bindings und

• Unterstützung für das OpenFlow Protokoll.

Performance

Open vSwitch implementiert einen OpenFlow-kompatiblen Software-Switch, dessen control path als Kernelmodul6 implementiert ist, welches für den data path auf die im Kernel vorhandene Netzwerkinfrastruktur zurückgreift. Der verwendete Controller wird standardmäßig auf dem gleichen Computer im User-Space bereitgestellt. Das Kernelmodul ist für die Verwaltung der Flow-Tabelle zuständig. Sofern be- reits ein Tabelleneintrag existiert, werden eintreffende Pakete gemäß diesem unmittel- bar weitergeleitet. Ist dies nicht der Fall, wird der User-Space Dienst ovs-vswitchd konsultiert. In Abbildung 1.3 ist dieses von OpenFlow bekannte Funktionsprinzip ver- einfacht dargestellt. Es ist naheliegend, dass aufgrund dieser Funktionsweise für bestehende Flows ei- ne mit Linux Bridge vergleichbare Performance erzielt wird. Beim experimentellen Vergleich mit einem Hardware-Switch zeigt Open vSwitch ebenfalls mit Hardware ver- gleichbare Leistung [SG13].

Programmierbarkeit

Open vSwitch implementiert das OpenFlow Protokoll in Form eines reinen Software- Switches und weist somit auch die Unzulänglichkeiten von OpenFlow in Bezug auf die Protokollentwicklung auf. Um die erforderlichen Weiterleitungsentscheidungen auf

6seit Version 3.3 ist dieses Modul in den Mainline Kernel integriert

Bachelorarbeit Carsten Andrich 1.3 Related Work 11

ovs-vswitchd

User-Space Kernel-Space

OvS Kernelmodul

Erstes Weitere Paket Pakete

Abbildung 1.3: Funktionsweise von Open vSwitch

Grundlage individueller Pakete zu ermöglichen, wäre eine Modifikation von Open vS- witch notwendig. Obwohl grundsätzlich möglich, wäre dies jedoch wenig zukunftssi- cher, da Open vSwitch über keine dafür vorgesehene, stabile, dokumentierte API ver- fügt. Insbesondere die unvermeidliche Veränderung des Open vSwitch Kernelmoduls widerspricht der ausführlich begründeten Zielsetzung einer vollständigen User-Space Implementation.

Bachelorarbeit Carsten Andrich 12 1 Problemstellung

1.3.4 Zusammenfassung

Linux bridge

Als vollständig im Kernel implementierte Lösung eignet sich Linux bridge aufgrund von Herausforderungen bezüglich der Programmierbarkeit nicht als Grundlage für den zu entwickelnden Switch. Die Möglichkeit der Programmierung im User-Space mittels nftables kann erst zu einem späteren Zeitpunkt sinnvoll untersucht werden.

OpenFlow Protokoll

Das OpenFlow Protokoll stellt keine Möglichkeiten bereit, Weiterleitungsentscheidun- gen auf Basis individueller Pakete zu treffen, da lediglich eine Kontrolle über Daten- flüsse geboten wird. Erstere sind jedoch insbesondere für die Implementation von QoS- Algorithmen unumgänglich, weshalb das OpenFlow Protokoll für die Implementation eines programmierbaren Switches ungeeignet ist.

Open vSwitch

Open vSwitch bietet einen Software-Switch auf Basis des OpenFlow Protokolls und teilt somit dessen Unzulänglichkeiten in Bezug auf die Protokollentwicklung. Prinzipi- ell ließen sich diese durch entsprechende Anpassung von Open vSwitch zwar umgehen, hierfür müsste aber das Kernelmodul verändert werden, was bereits im Rahmen der Aufgabenstellung dieser Arbeit begründet ausgeschlossen wurde. Darüber hinaus wä- ren Modifikationen der User-Space Komponenten von Open vSwitch mangels eines stabilen API potentiell mit zukünftigen Versionen inkompatibel.

Bachelorarbeit Carsten Andrich 1.4 Anforderungen 13

1.4 Anforderungen

Aus der Aufgabenstellung sowie der Analyse bestehender Umsetzungen bzw. Protokolle ergeben sich die folgenden erweiterten Anforderungen an die Implementation eines programmierbaren Switches:

• Linux als Betriebssystem da Linux ein performanter Betriebssystem-Kernel mit guter Hardware-Unter- stützung und obendrein frei verfügbar ist

• stabiles, einfaches API für zukunftssichere Implementation auf Basis des programmierbaren Switches und geringen Aufwand in der Einarbeitungsphase

• Programmierbarkeit im User-Space für im Vergleich zum Kernel-Space vereinfachte Entwicklung mit flexiblen Mög- lichkeiten der Programmierung (u.a. Nutzung von Bibliotheken), sowie die Ver- meidung von Inkompatibilitäten mit neueren Kernel-Versionen aufgrund von API-Änderungen

• Weiterleitungsentscheidungen auf Basis individueller Pakete für maximal mögliche Kontrolle der Paketvermittlung des Switches

• Prioritätsbasierte Weiterleitung um auf dieser Grundfunktionalität aufbauend z.B. Dienstgüteanforderungen ef- fektiv garantieren zu können

• Performance vergleichbar mit Hardware-Switches damit Netze maximal ausgelastet werden können, um Protokolle unter Extrem- bedingungen evaluieren zu können

• Variable Portanzahl mit skalierender Performance damit eine dem Nutzungsszenario angepasste Anzahl an Switch-Ports möglich ist, ohne für deren Erhöhung signifikant degradierte Performance in Kauf nehmen zu müssen

• Schnittstelle für den Versand benutzerdefinierter Daten um z.B. die aktive Staukontrolle (mittels Senden von Pause-Frames) oder den Versand von Statusinformationen zu ermöglichen

Bachelorarbeit Carsten Andrich

15

2 Lösungsansatz

Da keine der betrachteten Implementationen den gestellten Anforderungen an einen programmierbaren Switch gerecht wird, ist eine vollständige Neuentwicklung unter Berücksichtigung ebendieser Anforderungen unvermeidlich.

2.1 Entwicklungshardware

Auf die Anwendung zugeschnittene Tests sind integraler Bestandteil eines ergebnis- orientierten Entwicklungsprozesses. Sie ermöglichen eine objektive Evaluation von Er- gebnissen und unterstützen beim Treffen kritischer Entscheidungen mit quantitativen Argumenten. Da keine spezialisierte Ethernet-Messhardware zur Verfügung steht, wird für Ent- wicklung und Tests auf eine Minimalkonfiguration für aussagekräftige Benchmarks zurückgegriffen, die aus 3 Computern besteht. Ein mit mehreren Netzwerkkarten be- stückter Server wird für die Bereitstellung des Switches genutzt, während die beiden Notebooks X201 und X301 für Paketgenerierung bzw. -empfang im Halb- respekti- ve Vollduplexmodus eingesetzt werden können. Neben der kabelgebundenen Gigabit Ethernet (GbE) Verbindung zwischen Switch und Notebooks kommt noch eine draht- lose Wireless LAN (WLAN) Verbindung zwischen den Notebooks zum Einsatz. Diese wird für die Übertragung von Messdaten über TCP genutzt, um einerseits die Mes- sung nicht zu beeinflussen und andererseits die dafür genutzten NICs unkonfiguriert belassen zu können, damit Ressourcen der Testsysteme geschont und somit potentiell eine höhere Performance erzielt werden kann. Abbildung 2.1 zeigt diese Hardwarekon- figuration. Um bereits im Vorfeld von Entwicklung und Tests Aussagen über die Leistungsfä- higkeit der Messhardware treffen zu können, ist eine kurze Betrachtung der verbauten Hardwarekomponenten, wie

• Prozessor (Central Processing Unit (CPU)),

• Netzwerkkarte (Network Interface Controller (NIC)) und

Bachelorarbeit Carsten Andrich 16 2 Lösungsansatz

X201 X301 Server

GbE WLAN

Abbildung 2.1: Entwicklungshardware

• Hauptspeicher (Random Access Memory (RAM)) hilfreich. Da die Datenübertragung zwischen Ports die Zentralaufgabe eines Switches ist, sind Bandbreite und Latenz der dafür erforderlichen Speicherzugriffe von besonde- rem Interesse.

2.1.1 NIC-Speicherzugriff

Netzwerkkarten verwenden im Allgemeinen Ringpuffer im RAM für den Datenaus- tausch mit dem Betriebssystem. Aufgrund der Beschleunigung des Speicherzugriffs mittels Direct Memory Access (DMA) besteht jedoch keine softwaretechnische Mög- lichkeit, hierfür Bandbreite oder Latenz zu messen. Ein Verfahren für die Messung von Bandbreite und Latenz des Peripheral Component Interconnect Express (PCIe) RAM-Zugriffs beschreiben Coleman und Taylor in ihrem Whitepaper Hardware Level IO Benchmarking of PCI Express [CT08]. Für dessen Umsetzung ist jedoch Spezial- hardware erforderlich, weshalb die gesuchten Parameter messtechnisch nicht bestimmt werden können. Lediglich eine (obere) Abschätzung der Bandbreite ist anhand der von PCIe spezi- fizierten Datenrate möglich. Für die im Server genutzten NICs, die PCIe 1.1 mit einer Lane nutzen, ergibt sich eine Vollduplex-Bandbreite von 250 MB/s, die ausreichend Spielraum für Vollduplex GbE bieten sollte. Für die Latenz lässt sich zumindest eine theoretische untere Abschätzung treffen, da aufgrund in die CPU integrierter Double Data Rate (DDR) RAM-Controller der RAM-Zugriff von der CPU aus mit der geringsten Verzögerung erfolgen sollte.

Bachelorarbeit Carsten Andrich 2.1 Entwicklungshardware 17

2.1.2 CPU-Speicherzugriff

Messungen von Datenrate und Latenz sind lediglich für Zugriffe von CPU auf die eigenen Level 1/2/3 (L1/2/3) Caches sowie RAM möglich. Hierfür kommt das von Intel-Ingenieur Joshua Ruggiero beschriebene Verfahren [Rug08] auf Basis der Tool- sammlung für Performance-Analyse LMbench [LMb07] zum Einsatz. Um möglichst repräsentative Ergebnisse zu erhalten, wurden vor Durchführung der Messung sämtliche nicht benötigten User-Space Applikationen inklusive der grafi- schen Oberfläche beendet. Darüber hinaus wurde Ruggieros Verfahren um die Bildung von Mittelwert und Standardabweichung über 50 Einzelmessungen ergänzt. Diese er- folgen nicht unmittelbar hintereinander, um eine potentielle Verfälschung von Mess- ergebnissen durch kurzfristige Ereignisse zu vermeiden. Die Quellcodeauszüge 2.1 und 2.2 zeigen die Aufnahme von Messwerten für Datenrate respektive Latenz.

Quellcode 2.1: Messung der Speicherdatenrate mit bw_mem

1 #!/bin/bash

3 for n in {1..50} ; do 4 echo -n"#$n" 5 for size in 512 1k 2k 3k 4k 6k 8k 12k 16k 24k 32k 48k 64k 96k 128k 192k 256k 384k 512k 768k 1m 2m 3m 4m 6m 8m 12m 16m 24m 32m 48m 64m 96m 128m 192m 256m 384m 512m ; do 6 echo -n"$size" 7 nice -n -20 taskset 0x01 ./bw_mem -P1 -W1 -N1 $size rd >> bw_mem.$n 2>&1 8 done 9 echo "zzz" 10 sleep 20 11 done

Quellcode 2.2: Messung der Speicherlatenz mit lat_mem_rd

1 #!/bin/bash

3 for n in {1..50} ; do 4 echo -n"#$n" 5 nice -n -20 taskset 0x01 ./lat_mem_rd -P1 -W1 -N1 512m 512 > lat_mem_rd.$n 2>&1 6 echo "zzz" 7 sleep 20 8 done

Bachelorarbeit Carsten Andrich 18 2 Lösungsansatz

2.1.2.1 Latenz

Abbildung 2.2 visualisiert die Resultate der Latenzmessungen1. Die Grenzen zwischen L1/2/3-Caches und RAM lassen sich anhand der Plateaus der Graphen gut erkennen. Insbesondere am Ende der L2- und L3-Caches erhöht sich die Latenz für Zugriffsgrö- ßen, die immer noch kleiner als die volle Cachegröße (siehe Tabelle 2.1) sind. Dies ist unter anderem darauf zurückzuführen, dass die hierarchisch höheren Caches meh- reren (bzw. allen) Kernen der CPU zugeordnet sind und somit nicht der gesamte Cache dem messenden Prozess zur Verfügung steht. Dass es sich dabei um einen nicht- deterministischen Vorgang handelt, ist wiederum klar an der hohen Varianz in den Übergangsbereichen zu sehen. Die in Tabelle 2.1 angegebenen Werte für die Latenz wurden deshalb dem Bereich des jeweiligen Plateaus entnommen, der die geringste Varianz aufweist.

100 Server X201 X301 80

60

Latenz [ns] 40

20

0 2-12 2-10 2-8 2-6 2-4 2-2 20 22 24 26 28 210 Zugriffsgröße [MiB]

Abbildung 2.2: Latenz von CPU-Speicherlesezugriffen

1 Als Latenz ist hier die Dauer eines einzelnen Speicherzugriffes definiert. Der Wert ist nicht invers zur Datenrate, da unter anderem aufgrund von superskalaren CPUs mehrere Zugriffe gleichzeitig stattfinden können, obwohl diese nur von einem Thread aus erfolgen.

Bachelorarbeit Carsten Andrich 2.1 Entwicklungshardware 19

2.1.2.2 Datenrate

Die in Abbildung 2.3 dargestellten Ergebnisse der Datenratenmessungen spiegeln grob die Charakteristik der Latenzen in Abbildung 2.2, wenn auch die Übergänge zwischen L2/3-Caches und RAM weniger markant ausgeprägt sind. Insbesondere im Fall des Servers sind die Messwerte für den L1-Cache unstimmig, weshalb sich hierfür lediglich ein grober Schätzwert angeben lässt. Für die restlichen Angaben in Tabelle 2.1 wurden wieder Plateau-Werte möglichst geringer Varianz gewählt. Untersuchungen mit perf stat haben gezeigt, dass trotz der Terminierung nahe- zu aller User-Space Applikationen und dem Setzen der höchsten Scheduling-Priorität immer noch Context-Switches für den messenden Prozess durchgeführt werden. Dies hat potentiell Einfluss auf die Messergebnisse, da zwischen Context-Switches laufende Prozesse die Caches des vermessenen Prozessorkerns modifizieren. Obwohl dies keine vollständige Erklärung für die stark variablen Messwerte für den L1-Cache der Server- CPU darstellt, ist eine weiterführende Untersuchung in Rahmen dieser Arbeit weder möglich noch erforderlich.

120 Server X201 X301 100

80

60

Datenrate [GB/s] 40

20

0 2-12 2-10 2-8 2-6 2-4 2-2 20 22 24 26 28 210 Zugriffsgröße [MiB]

Abbildung 2.3: Datenrate von CPU-Speicherlesezugriffen

Bachelorarbeit Carsten Andrich 20 2 Lösungsansatz

2.1.3 Zusammenfassung

Tabelle 2.1 führt die zentralen Eigenschaften der Entwicklungshardware auf und fasst die Ergebnisse der evaluierenden Messungen zusammen. Die Daten lassen vermuten, dass insbesondere die Server-Hardware den Anforderungen eines Switches mit meh- reren Ports genügen sollte und sich somit grundsätzlich ein performanter Switch auf Computer-Hardware umsetzen lassen sollte. Eine genauere Betrachtung der Leistungs- daten erfolgt an späterer Stelle in Verbindung mit einer Beschreibung des für den Switch zu implementierenden Testverfahrens.

Server X201 X301 Betriebssystem Fedora 20 Fedora 20 Fedora 20 Linux 3.14 Linux 3.14 Linux 3.14 CPU Intel Core i7-4770K Intel Core i7-620M Intel Core2 SU9400 Kerne / Threads 4 / 8 2 / 4 2 / 2 Basistakt (GHz) 3,5 2,66 1,4 L1-Cache (KiB) 32 32 32 Datenrate (GB/s) ≥ 110 ≈ 52 ≈ 25 Latenz (ns) 1,0 1,2 1,9 L2-Cache (KiB) 256 256 3072 Datenrate (GB/s) ≈ 76 35,3 12,6 Latenz (ns) 3,1 3,0 9,6 L3-Cache (KiB) 8192 4096 – Datenrate (GB/s) 47,8 26,2 Latenz (ns) 9,5 14,4 RAM 16 GiB DDR3-1600 8 GiB DDR3-1066 2 GiB DDR2-800 Datenrate (GB/s) 19,2 7,3 4,8 Latenz (ns) 55,7 97,8 85,6 NIC (GbE) 2x Intel 82574L Intel 82577LM Intel 82567LM Datenrate (MB/s) 250 (Vollduplex) 266 (Halbduplex) 266 (Halbduplex)

Tabelle 2.1: Konfiguration und Leistungsdaten der Entwicklungshardware

Bachelorarbeit Carsten Andrich 2.2 Messsoftware 21

2.2 Messsoftware

Da keine dedizierten Hardware-Paketgeneratoren zur Verfügung stehen, müssen Mes- sungen auf der bereits beschriebenen Entwicklungshardware mittels Software durchge- führt werden.

2.2.1 Paketgenerierung

Die Paketgenerierung kann sowohl im User-Space als auch im Kernel-Space erfolgen, wobei idealerweise die für das Übertragungsmedium maximal möglichen Frame- bzw. Datenraten erreicht werden sollen.

User-Space

Im User-Space stehen für die Paketgenerierung unter anderem die Programme trafgen und mausezahn des netsniff-ng Toolkits [net12] zur Verfügung. Bei mausezahn handelt es sich um ein bewährtes Werkzeug mit zahlreichen Konfigurationsmöglichkeiten für die Generierung unterschiedlicher Protokolle auf Schichten 3 und 4 des OSI-Modells. Das neuere trafgen verspricht aufgrund der Verwendung von zero-copy Mechanismen eine höhere Performance, ist dafür aber nur eingeschränkt konfigurierbar.

Kernel-Space

Als Alternative bietet sich die Generierung von Paketen im Kernel-Space mit pktgen an. Dieser Paketgenerator ist in den Linux-Kernel integriert und versucht durch diverse Optimierungen wie zero-copying innerhalb des Kernels die maximal mögliche Perfor- mance zu erreichen, wie der initiale Entwickler Robert Olsson beschreibt [Ols04]. Die in der aktuellen Kernel-Dokumentation aufgeführten [O+14] Konfigurationsmöglich- keiten für höhere Protokollschichten sind vergleichsweise minimalistisch, da pktgen lediglich die Erzeugung von IP-Paketen mit (UDP) Nutzlast unterstützt. Trotz dieser Einschränkung ist pktgen für die Tests von Switches sehr gut geeignet, da hierfür primär das Erreichen der theoretisch möglichen Frame- und Datenrate wich- tig ist. Da Switches meist nur Layer-2-Header für ihre Weiterleitungsentscheidungen nutzen, ist eine Konfigurierbarkeit der Nutzlast der versendeten Frames von geringer Bedeutung. Darüber hinaus lässt sich pktgen gut in automatisierte Tests integrieren, kann mit konfigurierbaren Frameraten senden und gibt nützliche Statistiken aus.

Bachelorarbeit Carsten Andrich 22 2 Lösungsansatz

2.2.2 Paketempfang

Für den Paketempfang ist primär das Messen von Frame- und Datenraten relevant, wobei die Messmethodik bis zu den theoretischen Grenzen des Übertragungsmediums verlässlich funktionieren sollte. Die Messungen sind sowohl im User- und Kernel-Space möglich.

User-Space

Zu den bekannten User-Space Programmen zählen unter anderem iftop und iptraf. Charakteristisch für diese beiden sowie vergleichbare Anwendungen ist die Analyse von Paketheadern der Schichten 3 und 4, weshalb implementationsbedingt Messungen bei hohen Frameraten nur eingeschränkt möglich sind und abhängig von der verwendeten Hardware mit erheblichen Paketverlusten einhergehen.

Kernel-Space

Im Kernel-Space sind Messungen bei höheren Frameraten möglich. Hierfür werden die Treiber-Statistiken der Netzwerkkarte ausgelesen, was unter anderem mit dem Kom- mando cat /proc/net/dev erfolgen kann. Falls Messungen mit vorheriger Filterung erforderlich sind, ist dies über das Anlegen spezieller Firewallregeln möglich, deren Zähler später ausgelesen werden. Beide Methoden liefern jedoch keine Empfangsraten, sondern nur die Anzahl der bisher empfangenen Bytes und Pakete. Durch Differenz- bildung lassen sich daraus mittlere Frame- und Datenraten über wählbare Zeiträume bestimmen. Das der netsniff-ng Toolsammlung zugehörige Programm ifpps imple- mentiert dieses Verfahren. Ein Vergleich der Kernel-Statistiken mit NIC- und Treiber-spezifischen Daten, die mittels ethtool -S ausgelesen werden können, zeigt identische Werte. Dies legt die Vermutung nahe, dass die Statistiken des Kernels direkt aus den Hardwareregistern des NICs entnommen werden. Somit lässt sich die Paket-Empfangsrate auch auf Hard- ware ermitteln, die aufgrund mangelnder Rechenleistung nicht alle eingehenden Pakete verarbeiten kann. Hierzu muss sowohl die Anzahl der vom Kernel empfangenen, als auch der verworfenen Pakete berücksichtigt werden.

Bachelorarbeit Carsten Andrich 2.3 Messverfahren 23

2.2.3 Fazit

Für die Paketgenerierung wird auf pktgen zurückgegriffen, da dieses die größtmögliche Performanz verspricht und gleichzeitig gut in automatisierte Messverfahren integrier- bar ist. Die Beschränkung auf den Versand von UDP-Paketen hat bei der Vermessung von Switches keine Nachteile, sofern es sich nicht um einen Layer-3/4-Switch handelt, der auch Protokollheader höherer Schichten untersucht. Die Vermessung des Paketempfangs erfolgt mittels der Kernel-Statistiken, wobei sowohl bearbeitete als auch verworfene Pakete als empfangen gezählt werden, um mög- lichst Systemleistungs-unabhängige Messdaten zu erhalten.

2.3 Messverfahren

Auf der vollständig im Kernel-Space durchgeführten Paketgenerierung und Empfangs- ratenmessung aufbauend, muss als nächstes ein konkretes Messverfahren definiert wer- den. Da hierfür die Kenntnis des Ethernet-Paketformates hilfreich ist, wird dieses im Folgenden kurz beschrieben.

2.3.1 Ethernet-Paketformat

Ethernet kann im OSI-Modell sowohl Schicht 1 als auch Schicht 2 zugeordnet werden, weshalb nachfolgend zwischen

• Ethernet-Paketen, die sämtliche auf Layer 1 übertragenen Daten umfassen und dem übertragenen Bitstrom entsprechen (vor Codierung und Modulierung),

• und Ethernet-Frames, die lediglich den der Schicht 2 zugehörigen Teil des Pakets beinhalten, unterschieden wird. Abbildung 2.4 zeigt die Bestandteile eines Ethernet-Pakets sowie deren Größe und stellt dar, welchen Schichten diese zuzuordnen sind. Die Pakete sind wie folgt zusammengesetzt:

• Präambel und Start of Frame Delimiter (SFD) markieren den Beginn eines neuen Frames, früher zur Synchronisation genutzt

• MAC Ziel- und Quelladresse

Bachelorarbeit Carsten Andrich 24 2 Lösungsansatz

• optionales IEEE 802.1Q Tag dient der Angabe von VLAN-Mitgliedschaften und Übertragungspriorität

• Ethertype (bzw. Länge) gibt beim meistgenutzten Ethernet II Frame-Format den Typ der Nutzdaten an, andere Frame-Formate nutzen das Feld zur Angabe der Länge der Nutzdaten in Byte

• Nutzdaten im Frame eingebettetes Paket eines Layer 3 Protokolls

• Frame Check Sequence (FCS) Cyclic Redundancy Check (CRC) Prüfsumme zum Erkennen von Bitfehlern, be- schädigte Pakete werden nicht wiederhergestellt oder neu übertragen, sondern verworfen

• Interpacket Gap (IPG) minimaler Abstand zweier unmittelbar aufeinander folgender Pakete, strikt be- trachtet kein Paketbestandteil Präambel SFD MAC Ziel MAC Quelle Ethertype Nutzdaten FCS IPG 7 1 6 6 2 46 – 1500 4 12 Paket (Layer 1) 72 – 1526 Frame (Layer 2) 64 – 1518

Abbildung 2.4: Ethernet-Paketformat (ohne IEEE 802.1Q Tag) mit Längenangaben in Byte für individuelle Bestandteile, sowie gesamtes Paket bzw. Frame

Bachelorarbeit Carsten Andrich 2.3 Messverfahren 25

2.3.2 Standardisierte Verfahren

Für Performancemessungen in Ethernet-Netzwerken existieren unter anderem die fol- genden durch Standardisierungsorganisationen spezifizierten Verfahren:

• RFC 2544 – Benchmarking Methodology for Network Interconnect Devices Von der IETF spezifiziertes Verfahren für Performancemessungen in generischen Netzwerken [RFC99], beinhaltet spezifische Vorgaben für Ethernet, Token Ring und Fiber Distributed Data Interface (FDDI), jedoch kein formeller Standard.

• ITU-T Y.1563: Ethernet frame transfer and availability performance Standard des ITU Telecommunication Standardization Sector (ITU-T) der In- ternational Telecommunication Union (ITU) für Ethernet-spezifische Verfahren zur Performancemessung [ITU09].

Beide Spezifikationen beschreiben umfangreiche Messverfahren, deren vollständige Um- setzung mit der vorhandenen Entwicklungshardware wenig aussichtsreich erscheint. ITU-T Y.1563 sieht unter anderem Messungen der möglichen Formen der Übertra- gungsverzögerung vor, welche ohne spezielle Hardware nicht realisierbar sind. Darüber hinaus ist eine Realisierung der Messverfahren im zeitlichen Rahmen dieser Arbeit nicht möglich und auch wenig zweckdienlich, da die Verfahren nicht auf eine Software-Implementation zugeschnitten sind.

2.3.3 Vereinfachte Messmethodik

Varis und Manner beschreiben ein Verfahren für Performanzmessungen an Software- Switches [VM11], welches eine Messung mithilfe der proprietären Lösung „Spirent Test- Center“ vorsieht. Da stattdessen nur die bereits beschriebene Entwicklungshardware sowie freie Software zur Verfügung stehen, kann darauf nicht zurückgegriffen werden. Das in ITU-T Y.1563 beschriebe Verfahren kann mit dieser Hardware ebenfalls nicht sinnvoll eingesetzt werden. Stattdessen wird ein auf RFC 2544 basierendes, jedoch vereinfachtes Messverfah- ren implementiert. Als zentrale Aufgabe eines Switches ist insbesondere die Framewei- terleitung für Messungen interessant. Im Fokus liegt hier klar die maximale Weiter- leitungsrate gemessen in packets per second (pps). Die theoretisch mögliche maximale Framerate lässt sich mit Formel 2.1 bestimmen:

Verbindungsgeschwindigkeit Framerate = (2.1) Framegröße + Paketoverhead (20 Byte)

Bachelorarbeit Carsten Andrich 26 2 Lösungsansatz

Für Ethernet ist insbesondere die minimal erlaubte Framegröße von 64 Byte inter- essant, da diese bei back-to-back Übertragung von Paketen, also maximaler Auslastung der Verbindung, besonders hohe Anforderungen an den Switch stellt. Für das von der Entwicklungshardware genutzte GbE berechnet sich die daraus folgende maximale Fra- merate gemäß Formel 2.2:

GBit 1 s Framerate = Bit ≈ 1488,1 kpps (2.2) (64 + 20) Byte · 8 Byte

RFC 2544 spezifiziert neben Tests mit den minimalen 64 Byte auch die Framegrößen 128, 256, 512, 1024, 1280 und die maximalen2 1518 Byte. Die sich nach Formel 2.1 ergebenden theoretischen Frameraten listet Tabelle 2.2 auf.

Framegröße (Byte) Framerate (kpps) 64 1488,1 128 844,6 256 452,9 512 235,0 1024 119,7 1280 96,2 1518 81,3

Tabelle 2.2: Theoretisches Limit für GbE-Frameraten

Zusätzlich zur Framerate werden ebenfalls Übertragungslatenzen vermessen. Die Ver- einfachung des Messverfahrens erfolgt indem unter anderem die von RFC 2544 vorge- sehenen Messungen mit

• Broadcast-Frames,

• paralleler Übertragung von Frames unterschiedlicher Größen und Protokollen,

• sowie impulsartigem (Bursts) oder bidirektionalem Datenverkehr nicht durchgeführt werden. Zur Aufwandsreduktion werden einige Anforderungen an den Messvorgang nicht vollständig umgesetzt, woraus sich jedoch keine spürbaren Ein- flüsse ergeben sollten. Ergänzend zu RFC 2544 werden ausschließlich Mehrfachmes- sungen mit Bildung von Mittelwert und Varianz durchgeführt, sowie der Einfluss von Hintergrunddatenübertragung in die Latenzmessungen mit einbezogen.

2von IEEE 802.3 spezifiziert, nicht standardkonforme Jumbo Frames ermöglichen höhere Framegrö- ßen

Bachelorarbeit Carsten Andrich 2.3 Messverfahren 27

2.3.3.1 Implementation

Eine Automatisierung dieser Messungen ist hilfreich, damit der manuelle Durchfüh- rungsaufwand möglichst gering ausfällt. Zur Minimierung potentieller Messeinflüsse werden zuvor sämtliche nicht benötigten User-Space Prozesse inklusive der grafischen Oberfläche beendet.

Framerate

Zur Frameratenmessung wird auf den Paketgenerator pktgen zurückgegriffen. Der Einfachheit halber wird die Messung lediglich im Simplex-Modus betrieben, d.h. ein Computer übernimmt den Paketversand und ein anderer den -empfang. Eine bidirek- tionale Datenübertragung findet nicht statt. Die Automatisierung implementiert ein Perl-Skript, das für die in Tabelle 2.2 angegebenen Frameraten jeweils 10 Messungen durchführt und daraus Mittelwert und Varianz bestimmt. Die ausgehenden Frameraten werden von pktgen ausgegeben. Eine Berechnung ist nicht notwendig. Die am Zielsystem eingehenden Frameraten werden aus dem Verhält- nis empfangener zu versandter Frames gemäß Formel 2.3 ermittelt. Um in Erfahrung zu bringen, wie viele Frames empfangen wurden, wird die Kernel-NIC-Statistik als zuverlässigste Informationsquelle des Zielsystems ausgelesen.

Anzahl empfangener Frames Framerate = Framerate · (2.3) ein aus Anzahl versandter Frames

Die hierfür notwendige Kommunikation zwischen Sende- und Empfangshardware er- folgt über eine alternative Verbindung (WLAN), um die Messung nicht durch die Übertragung von Kontrollinformationen zu beeinflussen. Einen wesentlich größeren Einflussfaktor stellt die von IEEE 802.3x für Vollduplex- Ethernet spezifizierte Flusskontrolle dar. Diese sieht den Versand von Pause-Frames im Staufall vor, deren Empfänger für einen definierbaren Zeitraum keine weiteren Pakete mehr versenden sollen. Da dieses Verhalten für Messungen hinderlich ist, wird die Bearbeitung und der Versand von Pause-Frames zuvor mittels ethtool deaktiviert3.

3 Pause-Frames sind in Hardware-Switches ohnehin meist standardmäßig deaktiviert, da diese zwar Stausituationen kurzfristig auflösen können, dabei jedoch „Kollateralschäden“ in Kauf nehmen, wie Pahlevanzadeh et. al. beschreiben [PSWB08]. Da Pause-Frames nur an den jeweils nächsten Netzknoten gesendet werden, sind diese insbesondere in größeren Netzen eher kontraproduktiv, da das Pause-Frame die involvierten Endknoten nicht erreicht.

Bachelorarbeit Carsten Andrich 28 2 Lösungsansatz

Latenz

Übertragungslatenzen lassen sich mit dem bewährten User-Space Programm ping in Form von Paketumlaufzeiten (Round Trip Time (RTT)) messen. Die Automatisierung erfolgt wieder durch ein Perl-Skript, das für die von RFC 2544 vorgesehenen Framegrö- ßen Messungen durchführt. Dabei gilt es zu beachten, dass sich die an ping übergebene Größe auf die Nutzlast des Internet Control Message Protocol (ICMP) Pakets bezieht. Um die gewünschte Framegröße zu erhalten, muss von dieser der Ethernet-Frame- (18 Byte), IP- (20 Byte) und der ICMP-Overhead (8 Byte) abgezogen werden. Es wer- den jeweils 300 Messungen im Abstand von 0,2 Sekunden durchgeführt, für die ping selbstständig Mittelwert und Standardabweichung berechnet. Zur Simulation von Hintergrunddatenverkehr kommt das eigentlich für die Band- breitenmessung entwickelte Programm iperf3 zum Einsatz [ipe14]. Da bei der RTT- Messung Daten in beide Richtungen übertragen werden, kommen zwei iperf3-Instanzen zum Einsatz, um symmetrischen Datenverkehr zu generieren.

CPU-Auslastung

Zur Untersuchung der CPU-Auslastung bietet sich der zum Linux-Kernel zugehöri- ge Profiler perf [per13] an. Gegenüber herkömmlichen instrumentierenden Profilern bietet perf aufgrund der Nutzung von hardware performance counters überlegene Per- formanz und die Möglichkeit Code-Ausführung im Kernel-Space zu analysieren. Aufgrund der vielfältigen Nutzungsmöglichkeiten von perf wird an dieser Stelle von einer allgemeinen Beschreibung abgesehen und stattdessen jeweils anwendungs- spezifisch auf die genutzten Analysemöglichkeiten eingegangen.

2.3.3.2 Messergebnisse

Als Ergänzung zu den bereits gesammelten und in Tabelle 2.1 zusammengefassten generischen Leistungsdaten der Entwicklungshardware ist eine Anwendung des soeben beschriebenen Messverfahrens naheliegend.

Framerate

Für die Frameratenmessung ist insbesondere von Interesse, ob die Entwicklungshard- ware für die herangezogenen Framegrößen die jeweils theoretisch mögliche Sendeframe- rate erreicht bzw. wie groß eine eventuell vorhandene Abweichung ist. Daraus ergeben sich unmittelbar die Beschränkungen eines von der Hardware bereitgestellten Switches

Bachelorarbeit Carsten Andrich 2.3 Messverfahren 29 sowie die Grenzen der durchführbaren Messungen. Tabelle 2.3 stellt die für GbE theo- retisch mögliche Framerate sowie die von der Entwicklungshardware erreichten Werte im Sendefall gegenüber.

Frame- Framerate [kpps] größe Server [Byte] Maximum X301 X201 NIC #1 NIC #2 64 1488,1 1388,7 ± 0,1 1370,4 ± 0,4 890,0 704,6 128 844,6 811,6 809,7 816,6 640,8 256 452,9 443,2 442,1 452,9 452,9 512 235,0 232,2 231,8 235,0 234,9 1024 119,7 119,0 118,7 119,7 119,7 1280 96,2 95,7 95,4 96,1 96,1 1518 81,3 80,8 80,6 81,3 81,3

Tabelle 2.3: Ausgehend maximal erreichbare Frameraten der Entwicklungshardware (nicht angegebene Unsicherheiten entsprechen ± 0,0 kpps)

Eine grafische Darstellung der Absolutwerte aus Tabelle 2.3 hat auch mit doppelt- logarithmischer Achsenskalierung wenig Aussagekraft, da die Zahlenwerte insbesondere für hohe Framegrößen wenig differieren. Um dennoch eine informative Visualisierung zu ermöglichen, stellt Abbildung 2.5 die erreichte Framerate relativ zum theoretischen Maximum dar. Für geringe Framegrößen ist eine besonders hohe Abweichung deutlich erkennbar. Aufgrund des erheblichen Overheads beim Paketversand durch das Betriebssystem4, stellt die Sättigung des Übertragungsmediums mit Frames minimaler Größe eine be- sondere Herausforderung dar. Formel 2.4 bestimmt das für den Versand solcher 64- Byte-Frames verfügbare Zeitfenster zu 672 ns, was auch für moderne Computer ein relativ kurzer Zeitraum ist.

1 1 Framedauer64 Byte = = ˆ=672 ns (2.4) Framerate64 Byte 1488,1 kpps

Beim Vergleich der 64-Byte-Frameraten fällt auf, dass X301 marginal besser als X201 abschneidet, beide wiederum aber deutlich unter der Abweichung der Server-NICs lie- gen. Dieses Verhalten steht in krassem Gegensatz zu den generischen Leistungsdaten der 3 Computer, da sich von performanterer Hardware logischerweise auch eine höhere Framerate erwarten lässt. Grundsätzlich sollte die von allen Computern bereitgestell-

4 Obwohl sich mit pktgen für die performanteste Lösung entschieden wurde, fällt dennoch beim Versenden einzelner Frames signifikanter Overhead durch den Aufruf diverser Netzwerkstack- Funktionen des Betriebssystems an.

Bachelorarbeit Carsten Andrich 30 2 Lösungsansatz

1

0,9

0,8

0,7

0,6

Server NIC #1 0,5 Server NIC #2

Framerate relativ zum theoretischen Maximum X201 X301 0,4 64 128 256 512 1024 2048 Framegröße [Byte]

Abbildung 2.5: Abweichung der ausgehenden Frameraten vom theoretischen Maximum te Speicherbandbreite und -latenz für sämtliche Framegrößen die maximale Senderate ermöglichen. Als zulässige Schlussfolgerung bleibt, dass die vergleichsweise geringe Fra- merate der Server-NICs nicht in pktgen oder den Leistungsdaten von CPU bzw. RAM begründet liegt. Prinzipiell könnten PCIe-DMA-Latenzen der Grund sein. Mangels einer Messmög- lichkeit lässt sich dies jedoch nicht schlüssig nachweisen. Allerdings ist der signifikante Unterschied zwischen den Frameraten der beiden Server-NICs ein deutliches Indiz für diese Theorie. Obwohl beide NICs identisch sind und auch ein Vertauschen zu keinen Veränderungen führt, zeigt jeweils die im unteren PCIe-Slot steckende Netzwerkkarte die deutlich geringere Framerate. Bei der Verwendung eines anderen Motherboards zeigten sich vergleichbare Diskrepanzen zwischen den PCIe-Steckplätzen. Ein weiterer Anhaltspunkt für DMA-Latenzen als Verursacher ist die Tatsache, dass die folgenden Versuche, die Framerate zu steigern, zu keinen nennenswerten Veränderungen geführt haben:

• Erhöhung der NIC-Ringpuffergröße, um Unterbrechungen der Paketverarbeitung durch das Betriebssystem aufgrund

Bachelorarbeit Carsten Andrich 2.3 Messverfahren 31

von Scheduling besser überbrücken zu können.

• Interrupt-Assoziation, also das Beschränken der Interrupt-Routinen auf CPU-Kerne mit aktiven pktgen Prozessen, wie von dessen Autor Robert Olsson empfohlen [Ols04], um durch CPU-Migration potentiell notwendige Cache-Synchronisation zu vermeiden.

• Multi-Threading, um die Ressourcen der genutzten Mehrkern-Prozessoren besser auszuschöpfen. Es ergeben sich jedoch nur geringfügige Verbesserungen. Eine Analyse mit perf zeigt, dass die pkgten Prozesse lediglich unverhältnismäßig viel Zeit mit aktivem Warten (Spinlocks) verbringen.

Eine Untersuchung des inversen Übertragungsweges, also der Rate mit der der Kernel Frames empfängt, ist hilfreich um zu überprüfen, ob sich auch beim Empfang eine Dis- krepanz zwischen realisierbarer Framerate und theoretischem Maximum ergibt. Hierfür wird X301 als Sender und die beiden Server NICs unabhängig voneinander als Empfän- ger konfiguriert. Somit sollte konform zum Versand mit pktgen eine näherungsweise exakte Umkehr der Übertragungsrichtung ermöglicht werden. Die in Tabelle 2.4 ange- gebenen Messwerte zeigen, dass im Empfangsfall Frames mit der von X301 maximal erreichbaren Framerate verarbeitet werden können. Die Rohdaten der Messung bestä- tigen, dass sämtliche Frames empfangen werden, also keinerlei Verluste auftreten.

Frame- Framerate [kpps] größe Server NIC #1 Server NIC #2 [Byte] Ist Soll Ist Soll 64 1388,3 ± 0,2 1388,3 ± 0,2 1388,3 ± 0,1 1388,3 ± 0,1 128 811,7 811,7 811,7 811,7 256 443,3 443,3 443,3 443,3 512 232,3 232,3 232,3 232,3 1024 119,0 119,0 119,0 119,0 1280 95,7 95,7 95,7 95,7 1518 80,9 80,9 80,9 80,9

Tabelle 2.4: Eingehende Frameraten der Server-NICs bei Versand durch X301 (nicht angegebene Unsicherheiten entsprechen ± 0,0 kpps)

Die sich aufzeigende erhebliche Asymmetrie zwischen den in Empfangs- und Sen- defall erreichbaren Frameraten kann nicht schlüssig erklärt werden, wobei eine Verur- sachung durch die eingesetzte Hardware jedoch wahrscheinlich ist. Es erscheint beson- ders schwer nachzuvollziehen, dass beim Empfang die theoretische Maximalframerate

Bachelorarbeit Carsten Andrich 32 2 Lösungsansatz

– trotz des notwendigen Parsens der Protokollheader durch den Kernel – im Rahmen der Messmöglichkeiten erreicht wird, während das theoretische Maximum beim ver- gleichsweise einfachen Versand signifikant unterschritten wird. Eine Intensivierung der Ursachenforschung erscheint deshalb wenig hilfreich und wird an dieser Stelle nicht weiterverfolgt.

Latenz

Um später die Übertragungslatenz der eingesetzten Switches vermessen zu können, müssen zunächst Referenzwerte für eine Direktübertragung zwischen den beiden No- tebooks ermittelt werden. Es werden Messungen ohne, sowie mit 100 MBit/s und 1000 MBit/s Vollduplex-Hintergrunddaten durchgeführt. Die Bandbreite bezieht sich auf den an iperf3 übergebenen entsprechenden Parameter. Natürlich lässt sich mit dem genutzten GbE eine Nettodatenrate in Höhe von 1000 MBit/s aufgrund der technischen Beschränkungen nicht erreichen. Ziel ist in diesem Fall lediglich, das Übertragungsme- dium voll auszulasten.

1000

800

600

400 RTT [µs]

200 ICMP 100 Mbit/s UDP + ICMP 0 1000 Mbit/s UDP + ICMP

64 128 256 512 1024 2048 Framegröße [Byte]

Abbildung 2.6: RTT zwischen X301 und X201

Anhand der Abbildung 2.6 zugrunde liegenden RTT-Referenzwerte tRTT,Ref des

Messsystems lässt sich die verursachte Latenz tLatenz des zu vermessenden Switches aus dessen RTT tRTT,Switch nach folgender Formel ermitteln:

t − t t = RTT,Switch RTT,Ref (2.5) Latenz 2

Bachelorarbeit Carsten Andrich 2.3 Messverfahren 33

Die Formel nimmt an, dass sich die RTT je zur Hälfte aus Hin- und Rückweg zusam- mensetzt. Dies sollte in guter Näherung zutreffen, da kein signifikanter Unterschied zwischen beiden Übertragungsrichtungen bestehen sollte, sowie Hin- und Rückweg demselben Pfad folgen. Allerdings stellen die in Abbildung 2.6 erkennbaren hohen Varianzen ein Problem bei der Berechnung der Unsicherheit der Latenz uLatenz dar, da sich die involvierten Unsicherheiten entsprechend dem Fehlerfortpflanzungsgesetz summieren:

q 2 2 uRTT,Switch + uRTT,Ref u = (2.6) Latenz 2

2.3.3.3 Folgerungen

Die Beschränkungen der Entwicklungshardware bezüglich der erreichbaren Framera- ten müssen als gegeben und unveränderlich akzeptiert werden. Bei den durchgeführten Simplex-Messungen werden jeweils 2 NICs nur zum Empfang und 2 NICs nur zum Ver- sand genutzt. Da die jeweiligen Sendeframeraten den limitierenden Faktor darstellen, lässt sich die maximale Framerate der NIC-Kette durch eine entsprechende Wahl des Übertragungsweges maximieren. Mit der folgenden Reihenfolge sollte sich die bestmög- liche Framerate erreichen lassen, die sich aus den maximal ausgehenden Frameraten von X301 und Server NIC #1 ergibt:

X301 −−−−−→Ethernet Server NIC#2 −−−→RAM Server NIC #1 −−−−−→Ethernet X201 (2.7)

Die Senderate des Server NIC #1 unterschreitet lediglich für 64-Byte-Frames die Sen- derate von X301 (vgl. Tabelle 2.3), was insofern problematisch ist, dass Software- Switches auf Basis dieser Entwicklungshardware die maximal messbare Framerate in diesem Fall grundsätzlich nicht erreichen können. Um dies bei der Messungsdurch- führung zu berücksichtigen, ist eine Limitierung der 64-Byte-Framerate auf 890 kpps sinnvoll, da dieser Wert von Server NIC #1 erreicht werden kann. Abbildung 2.7 zeigt die theoretisch erreichbare und im Rahmen des Messprozesses realisierbare Framerate als Absolutwerte (vgl. Abbildung 2.5 für eine relative Darstellung).

Bachelorarbeit Carsten Andrich 34 2 Lösungsansatz

Theoretisch Realisierbar 1000 Framerate [kpps]

100

64 128 256 512 1024 2048 Framegröße [Byte]

Abbildung 2.7: Theoretische/Realisierbare Messframerate

2.4 Zusammenfassung

Die Implementation eines programmierbaren Switches soll auf Basis von Entwicklungs- hardware erfolgen, die aus 3 Computern besteht, wobei ein Server die Rolle des Swit- ches übernimmt und 2 Notebooks die zu verbindenden Netzwerkteilnehmer darstel- len. Zur Evaluation der Leistung des Switches wurde eine von RFC 2544 abgeleitete, vereinfachte, jedoch hinreichende Messmethodik entwickelt, da vollständig standard- konforme Verfahren entweder mit der Entwicklungshardware inkompatibel oder in der Durchführung zu komplex sind. Die Anwendung dieses Messverfahrens hat gezeigt, dass die Entwicklungshardwa- re die theoretischen Grenzen von Gigabit Ethernet nicht vollständig erreichen kann. Untersuchungen dieses Sachverhalts unter Einbeziehung der Leistungsdaten der Hard- ware haben keine zufriedenstellenden Ergebnisse hervorgebracht, weshalb diese Be- schränkungen in das Messverfahren eingearbeitet wurden. Hieraus sollten sich jedoch keine Nachteile für die eigentliche Implementation ergeben, da die theoretischen Gren- zen größtenteils erreicht werden und das Messverfahren darüber hinaus lediglich Ver- gleichswerte bereitstellen muss.

Bachelorarbeit Carsten Andrich 35

3 Implementation

Die Implementation wird nachfolgend Programmierbarer Linux User-Space Switch (PLUS) genannt. Dieser Name repräsentiert die wichtigsten Design-Eigenschaften von PLUS und ist obendrein leicht zu merken.

3.1 Entwicklungsumgebung

Die Programmierung von PLUS erfolgt mit der Programmiersprache C, um mittels Hardware-naher Programmierung eine hohe Effizienz und somit Leistungsfähigkeit zu ermöglichen. Da PLUS ohne Multi-Threading nicht sinnvoll realisiert werden kann, kommt die Standardversion C11 zum Einsatz. Mit dieser werden erstmalig atomare Speicheroperationen möglich, die eine effiziente Thread-Synchronisation ermöglichen. Als Build-Systems wird CMake genutzt, mit dem sich auch kompliziertere Build- Vorgänge leicht umsetzen lassen. Auf Basis von statischen Bibliotheken lässt sich so eine Konfigurierbarkeit zur Kompilierzeit und eine gute Programmierbarkeit gewähr- leisten. Um darüber hinaus auch die Performance von PLUS zu steigern, werden Op- timierungen zur Linkzeit (Link Time Optimizations (LTO)) aktiviert. Ebenfalls über das Build-System realisiert ist eine automatische Dokumentation des Quellcodes mittels Doxygen. Hierfür wird der Quellcode mit speziellen Kommenta- ren versehen, die anschließend von Doxygen extrahiert werden, um automatisiert eine API-Dokumentation zu erstellen. Hierdurch soll sichergestellt werden, dass PLUS gut dokumentiert und somit einfach zu programmieren ist.

3.2 Grundlagen

Das für die Implementation eines Switches erforderliche Empfangen und Versenden von Ethernet-Frames erfolgt unter Linux mit sogenannten Packet Sockets, die sich über das gewohnte Berkeley Software Distribution (BSD) Socket-API nutzen lassen. Quellcode 3.1 zeigt vereinfacht die Initialisierung eines Packet Sockets, mit dem Frames auf einer einzigen wählbaren Netzwerkkarte empfangen sowie versendet werden können.

Bachelorarbeit Carsten Andrich 36 3 Implementation

Darüber hinaus wird ebenfalls der Promiscuous Modus aktiviert, damit vom NIC alle empfangenen Pakete an das Betriebssystem weitergegeben werden. Für gewöhnlich werden Frames, die nicht an die MAC-Adresse des NIC adressiert sind, unmittelbar verworfen, um eine unnötige und rechenintensive Verarbeitung durch das Netzwerk- subsystem des Betriebssystems zu vermeiden. Dieses Verhalten würde die Nutzung der Netzwerkkarte als Port eines Switches jedoch unmöglich machen, da so sämtliche weiterzuleitenden Frames verworfen werden würden.

Quellcode 3.1: Initialisierung eines Packet Sockets unter Linux

1 // open socket 2 int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

4 // bind socket to specific network interface 5 struct sockaddr_ll bindaddr; 6 bindaddr.sll_family = AF_PACKET; 7 bindaddr.sll_protocol = htons(ETH_P_ALL); 8 bindaddr.sll_ifindex = if_nametoindex("eth0"); 9 bind(sockfd, ( struct sockaddr *) &bindaddr, (socklen_t) sizeof (bindaddr);

11 // enable promiscuous mode 12 struct packet_mreq mr; 13 mr.mr_type = PACKET_MR_PROMISC; 14 mr.mr_ifindex = if_nametoindex("eth0"); 15 setsockopt(sockfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof (mr));

3.2.1 recvfrom()/sendto()

Die einfachste Möglichkeit auf Basis der initialisierten Packet Sockets Frames wei- terzuleiten, bieten die Syscalls recvfrom() und sendto(). Quellcode 3.2 zeigt ein entsprechendes, jedoch vereinfachtes, Beispiel der Simplex-Weiterleitung zwischen 2 NICs.

Quellcode 3.2: Simplex-Frameweiterleitung mittels recvfrom()/sendto()-Syscalls

1 uint8_t buf[BUFSIZE];

3 while (1) { 4 ssize_t bytes_rx = recvfrom(sockfd_rx, buf, BUFSIZE, 0, NULL , NULL ); 5 sendto(sockfd_tx, buf, bytes_rx, MSG_DONTWAIT, NULL , 0); 6 } Problematisch an dieser Variante ist jedoch, dass für jedes Unicast-Frame 2 Syscalls erforderlich sind. Im Fall von Multicast und Broadcast erhöht sich die Anzahl entspre- chend. Insbesondere wenn hohe Frameraten erzielt werden sollen, ist der Overhead von Syscalls ein entscheidendes Hindernis. Aufgrund der in Betriebssystemen üblichen Spei- cherschutzmechanismen müssen mittels Syscalls übertragene Daten implizit zwischen

Bachelorarbeit Carsten Andrich 3.2 Grundlagen 37

Kernel- und User-Space-Speicher kopiert werden. Die notwendigen Mode Switches1 nehmen ebenfalls eine gewisse Zeit in Anspruch. Diese Zeit lässt sich leicht mit dem von Michael Kerrisk [Ker10] beschriebenen Verfahren bestimmen. Mittels perf wird die Laufzeit zweier Programme gemessen, die sich lediglich darin unterscheiden, ob eine simple Funktion oder der Syscall getppid() wiederholt aufgerufen wird. Bei getppid() handelt es sich um einen sehr einfachen Sys- call, der lediglich eine Variable zurückgibt, weshalb seine Laufzeit die Dauer eines Mode Switches hinreichend genau approximiert. Durch Mehrfachmessung und Division der Laufzeitunterschiede der beiden Programme durch die Anzahl an getppid()-Aufrufen2 ergibt sich tMode Switch mitsamt Unsicherheit auf dem eingesetzten Server zu:

tMode Switch ≈ tgetppid() = (55,77 ± 0,15) ns (3.1)

Da, wie bereits erwähnt, pro Frameweiterleitung mindestens 2 Syscalls notwendig sind, beträgt der allein durch Mode Switches verursachte Overhead etwa 110 ns. Hin- zu kommt noch die eigentliche Laufzeit der recvfrom()/sendto()-Syscalls3 inklusive dem notwendigen Kopieren der Framedaten zwischen Kernel- und User-Space, wobei wieder die Latenzen der entsprechenden Speicherzugriffsoperationen anfallen. Hierbei geht bereits ein substanzieller Teil des in Formel 2.4 ermittelten 672-ns- Zeitfensters verloren, wodurch sich das Zeitbudget für das Treffen der Weiterleitungs- entscheidung entsprechend verkürzt.

3.2.2 PACKET_RX_RING/PACKET_TX_RING

Als Alternative bietet sich die Nutzung der Linux-spezifischen Packet Socket Erwei- terungen PACKET_RX_RING und PACKET_TX_RING an. Diese implementieren den Da- tenaustausch zwischen User- und Kernel-Space mittels jeweils eines Ringpuffers für Empfang (Receive (RX)) und Versand (Transmit (TX)). Deren Funktionsweise be- schreibt Donald Knuth [Knu01] ausführlicher. Hier ist es jedoch ausreichen zu wissen, dass Ringpuffer ohne die Notwendigkeit von Thread-sicheren Synchronisationsmecha-

1Wechsel zwischen User-Space und Kernel-Space 2 Problematisch an diesem Verfahren ist der häufige, konsekutive getppid()-Aufruf, da bereits nach dem ersten Aufruf die benötigten Instruktionen und Daten im CPU-Cache liegen. Somit wird die ideale Laufzeit des Syscalls ermittelt, die als untere Abschätzung dienen kann. In realistischen Anwendungsszenarien kann sich die Laufzeit deutlich erhöhen, da für Zugriffe auf hierarchisch höher liegende Caches bzw. den RAM entsprechend größere Latenzen anfallen. 3 Eine Messung der Laufzeit von recvfrom() und sendto() gestaltet sich insofern schwierig, als dass diese von zahlreichen Faktoren wie dem Füllstand der NIC-Queues abhängt. Es wird deshalb die für getppid() ermittelte untere Abschätzung genutzt.

Bachelorarbeit Carsten Andrich 38 3 Implementation nismen als nebenläufige Datenstrukturen genutzt werden können, sofern pro Puffer nur ein Leser und ein Schreiber existiert. Dies ist hier gegeben, da der RX-Ring nur im Kernel-Space beschrieben und im User-Space von einem einzigen Thread ausgele- sen wird. Gleiches gilt für den TX-Ring, nur mit vertauschtem Leser und Schreiber. Der Wegfall von Synchronisationsmechanismen ermöglicht zumindest theoretisch einen Sende-/Empfangsvorgang, der vollständig ohne Syscalls erfolgen kann. Aufgrund der vergleichsweise hohen Komplexität der Frameweiterleitung mittels Ringpuffern, wird hier auf ein Quellcodebeispiel verzichtet und stattdessen auf Ab- bildung 3.1 verwiesen. Beschriftungen im Inneren der Ringpuffer symbolisieren eine Ausführung des beschriebenen Vorganges im Kernel-Space, während Beschriftungen außerhalb eine Durchführung im User-Space anzeigen. Die zur Beschreibung verein- fachten Vorgänge für die Frameweiterleitung sind in der nummerierten Reihenfolge:

1. Der Kernel speichert empfangene Frames im RX-Ringpuffer.

2. Die Verfügbarkeit neuer Frames wird im User-Space erkannt. Dies kann entweder durch aktives Warten, also wiederholtem Abfragen des ent- sprechenden Ringpuffereintrages, oder mit dem poll()-Syscall erfolgen. Die Nut- zung eines hybriden Ansatzes empfiehlt sich. Bei geringem Frameaufkommen wird poll() genutzt, damit keine Systemressourcen mit aktivem Warten ver- schwendet werden, während bei einem hohen Aufkommen der von poll() ver- ursachte Overhead umgangen werden kann. Dieses Verhalten lässt sich einfach implementieren, indem nach jedem empfangenen Frame generell für eine gewisse Zeit4 aktiv gewartet wird.

3. Frames werden vom RX- in den TX-Ringpuffer kopiert.

4. Frames die im User-Space nicht mehr benötigt werden, werden freigegeben.

5. Der Kernel wird mittels sendto() über neue Frames im TX-Ring unterrichtet. Dies ist der einzige Syscall, der nicht vermieden werden kann. Es müssen jedoch keine Nutzdaten mehr zwischen Kernel- und User-Space ausgetauscht werden. Darüber hinaus können mit einem sendto()-Aufruf mehrere Frames gleichzeitig

4 Für eine effiziente Zeitmessung während des aktiven Wartens kann nicht auf Syscalls zurückgegrif- fen werden, da diese einen zu hohen Overhead aufweisen. Unter der x86-Architektur bietet sich stattdessen die RDTSC-Instruktion an, die den Zugriff auf einen Taktzyklen-Zähler ermöglicht. Mo- derne CPUs inkrementieren diese Zähler auf allen CPU-Kernen mit einer konstanten Frequenz, was eine sehr performante und dennoch präzise Zeitmessung ermöglicht. Da die Startwerte der Zähler nicht zwischen CPU-Kernen synchronisiert sind, muss jedoch sichergestellt werden, dass CPU-Migrationen keine deutlich verlängerten aktiven Wartezeiten nach sich ziehen.

Bachelorarbeit Carsten Andrich 3.2 Grundlagen 39

an den Kernel übergeben werden. Unter der Annahme, dass Frames schneller vom User-Space verarbeitet als vom Kernel-Space gesendet werden können, bietet sich hier die Nutzung von Frame-Aggregation an5. So kann die Anzahl der notwen- digen Syscalls erheblich reduziert werden, während eine gleichzeitige Erhöhung der Latenz vermieden wird.

6. Der Kernel versendet die markierten Frames.

7. Nach erfolgtem Versand werden die freigewordenen Ringpuffereinträge an den User-Space zurückgegeben.

Frame im Kernel-Space RX Kernel-Space TX Kernel-Space ① Frame Frame im empfangen ⑥ Frame User-Space versenden ⑦ Frame freigeben RX/TX User-Space Verarbeiten ⑤ Einreihen ② poll() sendto() ④ Frame freigeben

③ Frame von RX zu TX kopieren

Abbildung 3.1: Funktionsweise der Frameweiterleitung mittels PACKET_RX_RING und PACKET_TX_RING

3.2.3 Fazit

Die Ringpuffer-basierte Frameweiterleitung ist zwar deutlich anspruchsvoller als die simple recvfrom()/sendto()-Alternative, die komplexere Implementation wird aber mit der prinzipiell überlegenen Performance vergütet. Deshalb wird der Switch auf Basis von PACKET_RX_RING und PACKET_TX_RING umgesetzt.

5 Die Anzahl der gemeinsam an den Kernel übergebenen Frames wird z.B. exponentiell von initial 1 über 2, 4, 8, usw. bis zum Erreichen eines konfigurierbaren Maximums gesteigert. Hierfür muss die Bearbeitungsdauer der Frames deutlich weniger als die für das Senden benötigte Zeit betragen (für o.g. Beispiel die Hälfte). Alternativ kann auch der Füllstand des Ringpuffers aktiv überwacht werden, was jedoch zusätzlichen Aufwand verursacht.

Bachelorarbeit Carsten Andrich 40 3 Implementation

Da es sich dabei um Linux-spezifische Erweiterungen handelt, ist eine Implemen- tation auf Basis von recvfrom()/sendto() jedoch ebenfalls erstrebenswert. Aufgrund deren Simplizität wird diese ebenfalls in Angriff genommen. Das Build-System wird entsprechend erweitert, um beide Weiterleitungsmechanismen im gleichen Quellcode- zweig entwickeln zu können. Neben einer einfachen Portierbarkeit auf andere Portable Operating System Inter- face (POSIX) Betriebssysteme ergibt sich daraus außerdem eine praktische Vergleichs- möglichkeit beider Implementationen.

3.3 Multi-Threading

Die Leistungsfähigkeit der inzwischen flächendeckend verbreiteten Mehrkern- und Mehr- prozessorsysteme kann nur durch die Verwendung von Multi-Threading ausgeschöpft werden, weshalb dies auch für PLUS zwingend erforderlich ist. Bei der Wahl eines Thread-Modells, also dem Prinzip, nach welchem die abzuleis- tende Arbeit auf die verfügbaren Threads verteilt wird, muss sorgsam zwischen den Vor- und Nachteilen der zur Verfügung stehenden Möglichkeiten abgewogen werden. Für PLUS wurde ein vergleichsweise simples Modell gewählt, welches eine statische Assoziation zwischen Threads und Aufgabenpaketen vorsieht. Im Gegensatz zu den in Anhang A beschriebenen alternativen Thread-Modellen entfällt so eine aufwendige dynamische Thread-Verwaltung, die nicht notwendigerweise eine bessere Performance garantiert. Der entstehende Synchronisationsbedarf impliziert Verwaltungsoverhead, welcher die erforderliche Verarbeitungszeit erhöht. Darüber hinaus muss bei der Im- plementation dafür Sorge getragen werden, dass die Thread-Verwaltung skalierbar ist und sich bei hoher Last nicht zum Flaschenhals entwickelt.

3.3.1 Statisches Thread-Modell

Die Simplizität eines statischen Thread-Modells vermeidet derartige Overhead- sowie Skalierungs-Problematiken grundsätzlich. Threads werden bei deren Start mit einem RX-Port assoziiert und sind dann ausschließlich für diesen verantwortlich. Diese Ex- klusivität macht eine anfällige zentrale Verwaltung sowie Synchronisation der Threads nicht erforderlich. Abbildung 3.2 stellt das Funktionsprinzip des statischen Modells grafisch dar. Jeder Thread hat den alleinigen Zugriff auf einen einzigen RX-Ringpuffer und ist somit für das Weiterleiten aller auf dem zugehörigen Port eintreffenden Frames zuständig.

Bachelorarbeit Carsten Andrich 3.3 Multi-Threading 41

Sobald die Weiterleitungsentscheidung für ein Frame getroffen wurde muss dieses in die entsprechenden TX-Ringe kopiert und der Sendevorgang gestartet werden. Auf die TX-Ringpuffer muss deshalb von allen RX-Threads aus zugegriffen werden, wofür Synchronisationsmechanismen notwendig sind.

④ RX1 ② ② TX1 ④ ① ⑤

⑤ RX2 ① ③ TX2 ③ ①

Abbildung 3.2: Funktionsprinzip des statischen Thread-Modells (Vereinfachtes Bei- spiel ohne Anwendungsbezug: Nummerierung stellt Empfangsreihen- folge dar, Farben Thread-Zugehörigkeit)

Da für jeden RX-Port nur ein Thread zur Verfügung steht, darf die vollständige Verarbeitung eines Frames den in Formel 2.4 errechneten Zeitraum von 672 ns im Durchschnitt nicht überschreiten, da sonst die theoretisch mögliche Framerate nicht erreicht werden kann. Hierfür gilt es die Frameverarbeitung so effizient wie möglich zu gestalten. Ist dies nicht möglich, kann alternativ auf mehrere Threads pro RX-Port zurückge- griffen werden. Generell sollte jedoch sichergestellt werden, dass insgesamt nicht mehr Threads parallel aktiv sind, als CPU-Kerne zur Verfügung stehen, um Performance- Einbußen aufgrund von vermehrten Context Switches durch Scheduling seitens des Betriebssystems zu vermeiden. Die von Linux bereitgestellte PACKET_FANOUT-Erweiterung ermöglicht mehrere PACKET_RX_RING Sockets pro NIC einzusetzen. Bei der Nutzung mehrerer RX-Threads pro Port kann so dennoch jedem Thread exklusiver Zugriff auf einen Ringpuffer gewährt und somit die Notwendigkeit des synchronisierten Zugriffs auf einen einzigen Ringpuf- fer vermieden werden. Die konfigurierbaren Möglichkeiten der Verteilung von Frames auf die einzelnen Ringpuffer sowie weitere Details werden in der Linux-Dokumentation

Bachelorarbeit Carsten Andrich 42 3 Implementation

[B+14] beschrieben. 6

3.3.2 Synchronisationsmechanismen

Unabhängig davon, ob nur ein einziger oder mehrere RX-Threads pro Port Verwendung finden, wird auf die TX-Ringpuffer von allen Threads aus zugegriffen. Um dabei einen reibungslosen Betrieb zu ermöglichen, ist die Nutzung von Synchronisationsmechanis- men unvermeidlich, da sonst mehrere Threads parallel auf den gleichen Speicherbereich zugreifen könnten, was zwangsläufig Programmfehler zur Folge hätte. Für simple Datenstrukturen, wie die eingesetzten Ringpuffer, ist eine derartige Synchronisation vergleichsweise einfach und dennoch performant realisierbar. Ein ex- klusiver Zugriff einzelner Threads auf den Ringpuffer muss nicht erzwungen werden, da die Einträge des Rings voneinander unabhängig sind. Es ist stattdessen ausreichend sicherzustellen, dass Threads nicht parallel auf denselben Puffereintrag zugreifen und der Ring in der richtigen Reihenfolge beschrieben wird. Beides lässt sich mit einer atomaren Fetch-and-add Operation garantieren, die den Zeiger auf den nächsten TX-Ring-Eintrag innerhalb aller schreibenden Threads mit einer einzigen Transaktion ausliest und inkrementiert. Ein derartig synchroni- sierter Ringpuffer stellt eine hochgradig nebenläufige Datenstruktur dar, sofern der Transaktionsoverhead nicht unverhältnismäßig groß ausfällt. Im Folgenden sollen Implementationsmöglichkeiten derartiger Synchronisations- mechanismen beschrieben und untersucht werden.

Pthreads

Eine Möglichkeit, die Transaktion zu implementieren, sind die von POSIX Threads (Pthreads) bereitgestellten Locking-Mechanismen, die es ermöglichen, parallelen Zu- griff auf die TX-Ring-Zeiger zu unterbinden. Dadurch können mehrere nicht-atomare Operationen, wie das separate Auslesen und Inkrementieren, zu einer Transaktion zu- sammengefasst werden. Sobald ein Thread den TX-Ring-Zeiger modifizieren möchte, wird der Zugriff auf diesen für alle anderen Threads gesperrt, der Zeiger ausgelesen, inkrementiert und anschließend wieder freigegeben. Hierfür bieten sich die folgenden Pthreads Mechanismen an:

6 Es bietet sich an, den PACKET_FANOUT_ROLLOVER-Modus in Kombination mit einer hohen Schedu- ling-Priorität für diejenigen Threads zu nutzen, die die primären RX-Ringe aller Ports verarbeiten. Dadurch sollte sich prinzipiell ein zuverlässiger Betrieb mit mehr aktiven Threads als CPU-Kernen trotz auftretenden Context Switches ermöglichen lassen. Eine experimentelle Implementation die- ser Funktionalität ist aufgrund des Beschränkten Zeitrahmens dieser Arbeit jedoch nicht möglich.

Bachelorarbeit Carsten Andrich 3.3 Multi-Threading 43

• pthread_mutex_lock() Verwendet Mutual Exclusion (Mutex) Mechanismen des Betriebssystems. Ist für längere Wartezeiten konzipiert, da Syscalls genutzt werden, wodurch entspre- chender Overhead anfällt.

• pthread_spin_lock() Nutzt Spinlocks, also aktives Warten. Deshalb primär für kurze Wartezeiten aus- gelegt.

C11 Atomics

Alternativ bietet sich die Nutzung der mit C11 erstmalig in den C-Standard aufge- nommenen atomaren Operationen an. Interessant sind davon insbesondere:

• atomic_fetch_add() Ermöglicht direkt das atomare Auslesen und Inkrementieren von Variablen. Un- ter der x86-Architektur kommt hierfür die XADD-Instruktion mit LOCK-Präfix zum Einsatz, welche das notwendige Locking direkt in der CPU durchführt. Hieraus sollte sich eine signifikant bessere Performance ergeben, als mit Alternativen ohne Hardware-Unterstützung erreichbar ist7.

• atomic_flag_test_and_set() Implementiert das atomare Testen und Setzen von Bits in Variablen und kann somit für die Umsetzung von Spinlocks in C-Code genutzt werden.

Die beschriebenen Operationen können genauso mittels Inline-Assembler auf Basis von atomaren Operationen der x86-Architektur implementiert werden. Der Vorteil von C11 Atomics ist jedoch die simple Portierbarkeit auf andere Architekturen und ein einfacherer Quellcode. Die Performanceunterschiede zwischen C11- und Assembler- Implementationen der gleichen Operationen stellen dennoch einen interessanten Un- tersuchungsgegenstand dar.

7 Der Vorteil von LOCK XADD ist das de-facto Lock-freie Umsetzen von Fetch-and-Add. Ein Akquirie- ren und Freigeben separater Locks ist nicht erforderlich. Damit entfällt auch die Notwendigkeit von dedizierten Lock-Variablen, die entsprechend atomar modifiziert werden müssten. Das Locking fin- det direkt auf der zu inkrementierenden Variable statt, wobei die Atomizität der Operation durch die CPU sichergestellt wird.

Bachelorarbeit Carsten Andrich 44 3 Implementation

Cache Locking

Für die Performance von Locking-Mechanismen sind die Einflüsse der CPU-Caches ebenfalls von großer Bedeutung. Der Intel System Programming Guide [Int14] empfiehlt die Nutzung von Cache Locking, indem sichergestellt wird, dass vom Locking betroffene Speicherbereiche jeweils auf einzelne Cache Lines8 entfallen. Dies hat den Vorteil, dass nicht der Speicher-Bus gesperrt wird, sondern die für Cache-Kohärenz zuständigen Mechanismen der CPU sicherstellen, dass keine simultanen und somit inkonsistenten Schreibzugriffe mehrerer CPU-Kerne auf die gleiche Cache Line erfolgen. Die Anzahl derartiger paralleler Zugriffe lässt sich erheblich reduzieren, indem das Speicherlayout der Locking-Variablen entsprechend angepasst wird. Idealerweise steht für jede Variable eine eigene Cache Line zur Verfügung, sodass lediglich beim parallelen Zugriff auf dieselbe Variable die Cache-Kohärenz-Mechanismen der CPU eingreifen müssen. Dies lässt sich bewerkstelligen, indem für die Variablen ein Padding und Alignment auf Cache-Größe erfolgt. Für Ersteres bieten sich unions an, Letzte- res kann mittels des C11-_Alignas()-Operators umgesetzt werden, wie Quellcode 3.3 exemplarisch zeigt.

Quellcode 3.3: C11-konformes Alignment und Padding von Datentypen auf SIZE Byte

1 union data { 2 _Alignas (SIZE) uint_fast32_t payload ; 3 uint8_t _reserved[SIZE]; 4 };

Durch diese geschickte Nutzung von Cache Locking sollten sich signifikante Vorteile gegenüber herkömmlichen Locking-Mechanismen ergeben.

Vergleichsmessungen

Eine Implementation der genannten Mechanismen ist hilfreich um einen quantitativen Vergleich zu ermöglichen. Grundlage der Messung ist das von mehreren Threads paral- lel durchgeführte Inkrementieren einer Variable, die den TX-Ring-Zeiger darstellt. Mit 1, 2, 4, 8 und 16 Threads werden jeweils insgesamt 230 Locks mit und ohne Optimie- rung für Cache Locking durchgeführt. Dabei werden mit perf jeweils 10 Messungen der benötigten CPU-Zeit durchgeführt und daraus Mittelwert und Varianz gebildet. Es werden auf der Server-Hardware die folgenden Realisierungen vermessen:

8 Cache Lines sind fest beschränkte Bereiche des RAMs, die in CPU-Caches vorgelagert werden können. Unter modernen x86-64 Prozessoren umfasst eine Cache Line für gewöhnlich 64 Byte und beginnt auf Modulo-64-Adressen.

Bachelorarbeit Carsten Andrich 3.3 Multi-Threading 45

• Fetch-and-Add (Inline-Assembler und C11) Es ergeben sich keine statistisch signifikanten Unterschiede zwischen beiden Im- plementationsmöglichkeiten. Ein Disassemblieren beider Implementation zeigt nahezu identischen Maschinencode. Aufgrund von überlegener Portabilität und einfacherem Quellcode wird deshalb nur die C11-Variante weiterverfolgt.

• Spinlock (Inline-Assembler, C11 und Pthreads) Kaum Unterschiede zwischen allen 3 Realisierungen. Es wird nur die Pthreads- Implementation weiterverfolgt, da sich diese am einfachsten umsetzen lässt.

• Pthread Mutex Vergleichsimplementation, die aufgrund des anfallenden Syscall-Overheads hö- here Latenzen erwarten lässt.

1000

100

10 CPU-Zeit / Lock [ns] C11 Fetch-and-Add optimierter C11 Fetch-and-Add pthread_mutex_lock() optimierter pthread_mutex_lock() pthread_spin_lock() optimierter pthread_spin_lock() 1 1 2 4 8 16 Anzahl Threads

Abbildung 3.3: Messtechnischer Vergleich möglicher Synchronisationsmechanismen

Die Visualisierung der Messergebnisse in Abbildung 3.3 bestätigt erwartungsge- mäß, dass die Fetch-and-Add-Implementation die kürzesten Lock-Zeiten erreicht. Das Schlusslicht bildet ebenfalls wenig überraschend die Pthread Mutex Variante, aufgrund der Nutzung von Syscalls zur Konfliktauflösung. Lediglich sobald mehr Threads als

Bachelorarbeit Carsten Andrich 46 3 Implementation

CPU-Kerne zum Einsatz kommen, kann diese Variante aufgrund der einsetzenden Con- text Switches ihre Vorzüge gegenüber Spinlocks ausspielen. Es zeigt sich ebenfalls, dass sich mittels Optimierung der genutzten Datenstrukturen für Cache Locking deutlich geringere Wartezeiten erzielen lassen. Bei der Auswertung der Ergebnisse muss jedoch bedacht werden, dass es sich um ein sehr synthetisches Benchmark der Locking-Mechanismen handelt. Wie bereits er- läutert sind Ringpuffer hochgradig nebenläufige Datenstrukturen, weshalb ein Lock nur für einen vergleichsweise geringen Anteil der Thread-Laufzeiten notwendig sein sollte. Dies wird vom Benchmark nicht berücksichtigt, da sich alle Threads nur mit dem Ak- quirieren von Locks beschäftigen und es somit erheblich häufiger zu Lock Contention9 kommt, als in einem realistischen Anwendungsszenario. Deshalb sind die Messwerte der Zeit pro Lock mit einem einzigen Thread besonders aussagekräftig, da in diesem Fall keine Lock Contention auftritt. Auch hier kann sich das Fetch-and-Add-Verfahren mit 4,9 ns Lock-Zeit deutlich durchsetzen. Je kürzer ein Lock gehalten wird, desto geringer ist die Wahrscheinlichkeit von Lock Contention. Am Beispiel von PLUS betrachtet, beträgt die minimale Zeit zwischen dem Ak- quirieren von Locks im Fall von Unicast-GbE-Frames pro Port 672 ns (siehe Formel 2.4). Wenn Locks jedoch nur für 4,9 ns gehalten werden, tritt Lock Contention ver- gleichsweise selten ein. Die folgende Formel versucht die mittlere Wahrscheinlichkeit in Abhängigkeit von der Anzahl an Ports n ohne Berücksichtigung komplexer statistischer Modelle zu approximieren:

4,9 ns p (n) = n · ≈ n · 0,73% (3.2) Lock Contention 672 ns

3.3.3 Zusammenfassung

Die Nutzung von Multi-Threading ist zwingend erforderlich, um die Leistungsfähigkeit moderner CPUs ausschöpfen zu können. Hierfür ist jedoch eine sorgfältige Überlegung erforderlich, wie zu leistende Arbeit auf mehrere Threads aufgeteilt werden kann, ohne dabei unverhältnismäßig viel Overhead durch Synchronisationsbedarf hervorzurufen. Für PLUS wurde ein statisches Thread-Modell gewählt, das eine exklusive Assoziation zwischen Threads und RX-Ports vorsieht, da sich der Empfangsprozess so vollständig synchronisationsfrei umsetzen lässt.

9 Lock Contention tritt auf, wenn mehrere Threads simultan versuchen einen Lock zu akquirieren. Da nur ein Thread den Lock gleichzeitig halten darf, kommt es generell zu Wartezeiten. Darüber hinaus verursacht das „Kämpfen“ um Locks je nach Implementation zusätzlichen Overhead (insbesondere im Fall von Spinlocks).

Bachelorarbeit Carsten Andrich 3.4 Prioritätswarteschlange 47

Da der Zugriff auf die TX-Ringpuffer von allen Threads aus erfolgen muss, bedarf es dennoch eines effizienten Synchronisationsmechanismus, um ein korrektes Beschrei- ben des TX-Ringes zu garantieren. Hier konnte sich die mit dem C11-Standard ein- geführte atomare Fetch-and-Add Operation gegen mehrere Alternativen durchsetzen. Mittels Optimierung für Cache Locking konnte die Performance für den Fall von Lock Contention verbessert werden.

3.4 Prioritätswarteschlange

Damit Dienstgüteanforderungen garantiert werden können, ist eine Sendewarteschlan- ge mit Unterstützung für Prioritäten erforderlich.

3.4.1 Datentyp

Binärbaum

Prinzipiell sind für solche Warteschlange Datenstrukturen naheliegend, die auf Binär- bäumen oder binären Heaps aufsetzen, da diese mit geringem Overhead eine arbiträre Anzahl unterschiedlicher Prioritäten ermöglichen. Allerdings sind diese Datentypen nur vergleichsweise geringfügig für nebenläufigen Zugriff geeignet. Im Gegensatz zu den bisher eingesetzten Ringpuffern muss das Einreihen in die und das Entfernen aus der Warteschlange synchronisiert erfolgen. Die Komplexität beider Operationen liegt für typische Implementationen bei O(log n), was bei einem hohen Füllstand n der Warteschlange zu signifikantem Overhead führt. Die Nutzung einer hardwarebeschleunigten, atomaren Fetch-and-Add Operation ist darüber hinaus nicht möglich10, weshalb für die Synchronisation auf weniger performante Spinlocks zurückgegriffen werden müsste (vgl. Abbildung 3.3). Da sowohl der Synchronisationsmechanismus selbst als auch die eigentliche En- queue/Dequeue-Operation deutlich mehr Zeit in Anspruch nehmen, erhöht sich die Wahrscheinlichkeit von Lock Contention drastisch. Tritt diese ein, verschlechtert sich die Performance von Spinlocks nochmal erheblich. Prioritätswarteschlangen auf Basis binärer Datenstrukturen sind deshalb offensichtlich für die Nutzung in PLUS ungeeig- net.

10 Fetch-and-Add kann nur einzelne Operationen atomar durchführen. Für das Modifizieren von Binärbaumen ist jedoch eine vom Füllstand abhängige Anzahl an Operationen notwendig, die sich darüber hinaus nicht alle mit Fetch-an-Add implementieren lassen.

Bachelorarbeit Carsten Andrich 48 3 Implementation

Ringpuffer

Alternativ kann eine fixe Anzahl von Ringpuffern eingesetzt werden, wobei jedem Ring- puffer eine feste Priorität zugeordnet wird. Hiermit lassen sich numerische Prioritäten realisieren, deren Anzahl aufgrund von Performanceüberlegungen jedoch beschränkt werden sollte. Die Abarbeitung erfolgt dann entsprechend einer zu implementieren- den Bedientheorie. Es ergeben sich die für derartig eingesetzte Ringpuffer typischen Eigenschaften für beide möglichen Operationen (Enqueue, Dequeue):

• Komplexität der Operationen ist O(1)

• Kein Synchronisationsbedarf für parallele, differierende Operationen

• Performante Synchronisation simultaner, identischer Operationen mittels atoma- rem Fetch-and-Add

Die Nutzung mehrerer Ringpuffer als Prioritätswarteschlange ist also in Bezug auf Ne- benläufigkeit und Komplexität der Operationen den Binärbaum-basierten Alternativen überlegen, weshalb in PLUS die Implementation auf Basis von Ringpuffern erfolgt.

3.4.2 Umsetzung

Das statische Thread-Modell von PLUS ist bereits für die Verwendung von Ringpuffern ausgelegt, wobei bisher jedoch die RX-Threads die TX-Ringpuffer direkt beschreiben und somit keine Priorisierung der Frameweiterleitung ermöglichen. Eine entsprechen- de Ergänzung des Thread-Modells um Prioritätswarteschlangen auf Basis von Ring- puffern ist vergleichsweise einfach. Es müssen lediglich für jeden TX-Port zusätzliche Queue-Ringpuffer für die verfügbaren Prioritäten bereitgestellt werden, die von den RX-Threads anstelle der TX-Ringpuffer beschrieben werden. Das Kopieren der Fra- mes von den Queue- in die TX-Ringpuffer übernehmen dann zusätzliche TX-Threads. Die Funktionsweise der priorisierten Frameweiterleitung stellt Abbildung 3.4 dar. Die Nummerierung entspricht dabei der zeitlichen Abfolge der eintreffenden Frames. Unterschiedliche Farben verdeutlichen die Thread-Zugehörigkeit, wobei ausgefüllte Ring- puffer dem jeweiligen Thread exklusiv zur Verfügung stehen. Für eine bessere Über- sichtlichkeit wurde nur ein Teil der stattfindenden Kopiervorgänge mittels Pfeilen vi- sualisiert. An Beispiel von Frame #3 erfolgt der Weiterleitungsprozess wie folgt:

Bachelorarbeit Carsten Andrich 3.4 Prioritätswarteschlange 49

1. Frame wird auf Port #1 empfangen, Kernel stellt dieses in RX-Ring #1 bereit

2. RX-Thread #1 verarbeitet das Frame und trifft die Weiterleitungsentscheidung (TX-Ports und Priorität)

3a. RX-Thread #1 kopiert das Frame in Queue-Ring #1 (hohe Priorität)

3b. RX-Thread #1 kopiert das Frame in Queue-Ring #2 (hohe Priorität)

4a. TX-Thread #1 kopiert das Frame in TX-Ring #1

4b. TX-Thread #2 kopiert das Frame in TX-Ring #2

5. Die TX-Threads initiieren den Versand der Frames in den TX-Ringen

Q1:Hi ③ ⑤ ② RX1 ② ① TX1 ③ ③ ⑤ ⑤ ② Q1:Lo ①

④ ③ Q2:Hi

⑥ RX2 ① ④ TX2 ④ ③ ⑥

⑥ Q2:Lo

Abbildung 3.4: Funktionsweise der Prioritätswarteschlange (Vereinfachtes Beispiel oh- ne Anwendungsbezug: Nummerierung stellt Empfangsreihenfolge dar, Farben Thread-Zugehörigkeit)

Bachelorarbeit Carsten Andrich 50 3 Implementation

Wie an der Abbildung zu erkennen ist, sind die TX-Threads exklusiv für das Entfernen aus den zugehörigen Queue-Ringen und das Einreihen in den eigenen TX- Ring zuständig, was eine Synchronisation dieses Zugriffs überflüssig macht. Lediglich das Einreihen in die Queue-Ringe durch die RX-Threads wird mittels atomarem Fetch- and-Add performant implementiert.

3.4.3 Optimierungsmöglichkeiten

Die Implementation der Prioritätswarteschlangen erfolgt aufgrund des beschränkten Umfanges dieser Arbeit nur rudimentär. Falls ein Ausbau der Implementierung erfolgt, bestehen natürlich noch Optimierungsmöglichkeiten.

Queue-Bypass

Die Nutzung der Queue-Ringpuffer bietet nur einen Vorteil, wenn die TX-Ringe gefüllt sind. Sind diese leer, ist der Zwischenschritt über den Queue-Ring überflüssig und somit unnötiger Overhead. In diesem Fall bietet sich ein direkter Übergang von RX-Ring zu TX-Ring und somit ein Überspringen der Warteschlange an.

Referenzieren statt Kopieren

Eine weitere Quelle von vermeidbarem Overhead ist das doppelte Kopieren der Frames, also von RX- über Queue- in TX-Ring. Es wäre stattdessen günstiger, die Queue- Einträge lediglich auf die Frames im RX-Ring verweisen zu lassen, sodass der TX- Thread die Frames bei Bedarf direkt aus dem RX-Ring herauskopiert. Problematisch hieran ist jedoch, dass die RX-Threads keinen exklusiven Zugriff mehr auf ihre respektiven RX-Ringe haben und somit Synchronisationsbedarf entsteht. Insbesondere das rechtzeitige Freigeben der Frames in den RX-Ringen stellt eine Her- ausforderung dar, da ansonsten der Empfang neuer Frames blockiert wird. Ob sich durch das anspruchsvolle Referenzieren anstelle eines simplen Kopierens signifikante Vorteile ergeben, ist allerdings fragwürdig, da die Speicherbandbreite des genutzten Servers (vgl. Tabelle 2.1) mehr als ausreichend ist und darüber hinaus die Referenzierung einen signifikanten Synchronisationsoverhead impliziert.

Bachelorarbeit Carsten Andrich 3.5 Programmierinterface 51

3.5 Programmierinterface

Das API ist ein integraler Bestandteil von PLUS und hat die Aufgabe, die Programmie- rung der Frameweiterleitung zu ermöglichen, ohne den PLUS-Quellcode modifizieren zu müssen. Um dies möglichst einfach zu gestalten und darüber hinaus LTO zu ermög- lichen, erfolgt die Programmierung von PLUS mittels statischem Linking. Hierfür wird der Prototyp der Funktion plus_plugin_fwd() innerhalb des PLUS-Quellcodes dekla- riert (siehe Quellcode 3.4). Diese Funktion muss vom PLUS-Plugin, das die Weiterlei- tungsentscheidungen trifft, implementiert werden, damit diese zur Linkzeit verfügbar ist und in PLUS eingebunden werden kann. Die Funktion wird für jedes eingehende Frame aufgerufen. Anhand der Parameter

• portidx_rx, dem Index des Ports auf dem das Frame empfangen wurde,

• data, einem Zeiger auf die Daten des Frames (Layer 2 ohne FCS), und

• size, der Größe des Frames,

muss diese Funktion über die Weiterleitung des Frames entscheiden und PLUS das Ergebnis über Rückgabewert der Funktion mitteilen. Dieser besteht aus dem struct plus_fwd_spec mit den Komponenten

• destmask, eine Bitmaske der Portindizes an die das Frame weitergeleitet werden soll, und

• priority, der Weiterleitungspriorität des Frames.

Quellcode 3.4: Primäre PLUS API-Funktion plus_plugin_fwd()

1 struct plus_fwd_spec { 2 plus_portmask_t destmask ; 3 plus_priority_t priority ; 4 };

6 extern struct plus_fwd_spec 7 plus_plugin_fwd( plus_portidx_t portidx_rx, uint8_t *data , size_t size );

Bei der Implementation von plus_plugin_fwd() muss beachtet werden, dass die Funk- tion aufgrund des Multi-Threadings von PLUS Thread-sicher realisiert werden muss.

Bachelorarbeit Carsten Andrich 52 3 Implementation

3.5.1 Beispiele

Die Einfachheit der API-Nutzung lässt sich am besten anhand von Beispielen demons- trieren.

3.5.1.1 Hub

Quellcode 3.5 zeigt ein unverändertes, vollständiges Beispiel für die Implementation eines Hubs auf Basis von PLUS. Die Simplizität der Programmierung ist deutlich zu erkennen, wobei in diesem Fall noch nicht auf Thread-Sicherheit geachtet werden muss.

Quellcode 3.5: Beispiel für PLUS-Implementation eines Hubs

1 struct plus_fwd_spec 2 plus_plugin_fwd( plus_portidx_t portidx_rx, uint8_t *data , size_t size ) 3 { 4 UNUSED_ARG ( data ); 5 UNUSED_ARG ( size );

7 struct plus_fwd_spec fwd; 8 // broadcast frame, but exclude ingress port 9 fwd.destmask = plus_broadcast_mask & ~(1 << portidx_rx); 10 fwd.priority = 0;

12 return fwd ; 13 }

3.5.1.2 Switch

Quellcode 3.6 stellt die Implementation eines einfachen Switches auf Basis von C++11 Code dar. Als Datentyp für die Source Address Table (SAT) des Switches kommt eine std::unordered_map zum Einsatz. Für Thread-Sicherheit sorgt ein std::mutex. Das Erlernen der MAC-Adressen erfolgt anhand der Address Resolution Protocol (ARP) Pakete, welche den Switch passieren. Die Betrachtung von ARP-Paketen reicht hierfür aus, da die über den Switch verbundenen Endknoten zum Austausch von MAC-Adressinformationen auf ARP an- gewiesen sind. Aufgrund der periodischen Auffrischung von ARP-Tabellen annoncieren sich alle MAC-Adressen regelmäßig selbst mit ARP-Paketen. Es reicht darüber hinaus aus, die Quelladressen im Ethernet-Header von ARP-Paketen heranzuziehen, was ein Parsen des eigentlichen ARP-Paketes überflüssig macht und somit die Implementation zusätzlich vereinfacht.

Bachelorarbeit Carsten Andrich 3.5 Programmierinterface 53

Quellcode 3.6: Vereinfachtes Beispiel für PLUS-Implementation eines Switches

1 /// source address table 2 static std ::unordered_map< uint_fast64_t , plus_portidx_t > sat ;

4 /// source address table mutex 5 static std ::mutex sat_mutex;

7 struct plus_fwd_spec 8 plus_plugin_fwd( plus_portidx_t portidx_rx, uint8_t *data , size_t size ) 9 { 10 struct plus_fwd_spec fwd; 11 fwd.priority = 0;

13 struct ether_header *eth_hdr = ( struct ether_header *) data;

15 // updateSAT on every incomingARP packet 16 if ( UNLIKELY (eth_hdr->ether_type == htons(ETHERTYPE_ARP))) { 17 uint_fast64_t eth_src = 0; 18 memcpy(ð_src, ð_hdr->ether_shost, ETH_ALEN);

20 sat_mutex.lock(); 21 sat.insert({{eth_src, portidx_rx}}); 22 sat_mutex.unlock(); 23 }

25 uint_fast64_t eth_dst = 0; 26 memcpy(ð_dst, ð_hdr->ether_dhost, ETH_ALEN);

28 // lookup destination address in theSAT 29 std ::unordered_map< uint_fast64_t , plus_portidx_t >::const_iterator iter; 30 iter = sat.find(eth_dst);

32 if ( LIKELY (iter != sat.end())) 33 // forward frames to the port associated with the destination address 34 fwd.destmask = 1 << iter->second; 35 else 36 // broadcast frames withouta destination address in theSAT 37 fwd.destmask = plus_broadcast_mask & ~(1 << portidx_rx);

39 return fwd ; 40 }

Bachelorarbeit Carsten Andrich

55

4 Ergebnisbewertung

4.1 Quantitativ

Im Folgenden soll ein quantitativer Vergleich von PLUS mit anderen Switches gewagt werden. Hierfür werden die Parameter Framerate und Latenz anhand des in Kapitel 2.3.3 beschriebenen Verfahrens gemessen.

4.1.1 PLUS-Konfigurationen

Aufgrund der modularen Implementation ist vorbereitend eine Vermessung der unter- schiedlichen Konfigurationsmöglichkeiten von PLUS hilfreich. Zu diesen zählen:

• Frame-Empfang mit recvfrom()-Syscall oder PACKET_RX_RING

• Frame-Versand mit sendto()-Syscall oder PACKET_TX_RING

• Direkter Versand oder Einreihen in Prioritätswarteschlange (Queue)

• Aktives Warten oder Nutzung ressourcenschonender Synchronisationsmechanis- men (poll() in RX-Threads bzw. pthread_cond_wait() in TX-Threads)

Da sich nur wenige der Optionen gegenseitig ausschließen1 und sich so eine entspre- chend große Anzahl verschiedener Konfigurationen ergibt, wurde die folgende Voraus- wahl getroffen:

• Syscall recvfrom()/sendto()

• Ring PACKET_{RX,TX}_RING

• Hybrid PACKET_RX_RING und sendto()

1 Lediglich aktives Warten ist in Kombination mit recvfrom()-basiertem Frame-Empfang nicht möglich.

Bachelorarbeit Carsten Andrich 56 4 Ergebnisbewertung

• Hybrid+Queue PACKET_RX_RING und sendto() mit Queue

• Aktiv+Hybrid+Queue PACKET_RX_RING und sendto() mit Queue und aktivem Warten

4.1.1.1 Framerate

Abbildung 4.1 zeigt die Ergebnisse der Frameratenmessung für die 5 obigen PLUS- Konfigurationen.

1

0,9

0,8

0,7

0,6

Ring 0,5 Syscall Hybrid

Framerate relativ zum theoretischen Maximum Hybrid+Queue 0,4 Aktiv+Hybrid+Queue

64 128 256 512 1024 2048 Framegröße [Byte]

Abbildung 4.1: Erreichte Frameraten verschiedener PLUS-Konfigurationen

Es folgt eine differenzierte Untersuchung der Frameraten, die von den jeweiligen Kon- figurationen erreicht werden: • Ring Die PACKET_{RX,TX}_RING-basierte Frameweiterleitung zeigt erstaunlicherweise die mit signifikantem Abstand geringsten Frameraten und erreicht die Grenzen des Messsystems erst bei 512-Byte-Frames. Dieser Sachverhalt widerspricht den Erwartungen, dass die Ringpuffer-Implementation aufgrund von weniger Syscall- Overhead performanter arbeitet als die recvfrom()/sendto()-Variante.

Bachelorarbeit Carsten Andrich 4.1 Quantitativ 57

• Syscall Abgesehen von einer hohen Messunsicherheit für 64-Byte-Frames werden gute Frameraten erreicht.

• Hybrid Die resultierenden Frameraten liegen leicht über den Werten der vollständig Sys- call-basierten Konfiguration. Zumindest mit PACKET_RX_RING ergibt sich also eine messbare Verbesserung der Performance.

• Aktiv+Hybrid+Queue / Hybrid+Queue Die auf Warteschlangen zurückgreifenden Varianten der hybriden PLUS-Konfi- guration reizen die Grenzwerte des Messsystems für alle Framegrößen aus. Die Verbesserung gegenüber der hybriden Variante ohne Queue lässt sich auf die Nutzung separater RX- und TX-Threads zurückführen. Darüber hinaus hat das aktive Warten keinen statistisch aussagekräftigen Einfluss auf die Framerate.

4.1.1.2 Latenz

300

250

200

150

100

Latenz [µs] 50

0 Ring Syscall -50 Hybrid Hybrid+Queue Aktiv+Hybrid+Queue -100 64 128 256 512 1024 2048 Framegröße [Byte]

Abbildung 4.2: PLUS-Übertragungslatenzen ohne Hintergrunddatenverkehr

Bachelorarbeit Carsten Andrich 58 4 Ergebnisbewertung

Die Ergebnisse der Latenzmessungen ohne Hintergrunddatenverkehr (siehe Abbildung 4.2) lassen sich wie folgt interpretieren:

• Ring / Syscall / Hybrid Kein statistisch signifikanter Unterschied zwischen allen 3 Konfigurationen.

• Hybrid+Queue Mit Queue liegt die Latenz etwa 50 µs höher als bei den ersten 3 Variationen. Da mit Warteschlange separate RX- und TX-Threads zum Einsatz kommen und diese mit pthread_cond_{signal,wait}() synchronisiert werden, resultiert der Synchronisationsoverhead in einer Erhöhung der Latenz.

• Aktiv+Hybrid+Queue Erreicht mit im Mittel < 75µs die mit Abstand geringsten Latenzwerte, da das aktive Warten unter anderem den Synchronisationsoverhead vollständig vermei- det.

Abbildung 4.3 zeigt die Latenzen der verschiedenen PLUS-Konfigurationen bei einer Saturierung des Übertragungsmediums. Es sind keine statistisch aussagekräftigen Un- terschiede zwischen den Messwerten zu erkennen.

500

400

300

200 Latenz [µs] Ring Syscall 100 Hybrid Hybrid+Queue Aktiv+Hybrid+Queue 0 64 128 256 512 1024 2048 Framegröße [Byte]

Abbildung 4.3: PLUS-Übertragungslatenzen bei maximal saturiertem Medium

Bachelorarbeit Carsten Andrich 4.1 Quantitativ 59

4.1.1.3 Schlussfolgerungen

Die insbesondere für geringe Framegrößen stark differierenden Frameraten der be- trachteten PLUS-Konfigurationen bestätigen die Notwendigkeit einer gut konzipierten Frameweiterleitung, wenn maximale Frameraten erreicht werden sollen. Es zeigt sich insbesondere am Vergleich der hybriden mit den Ring- und Syscall-Implementationen, dass PACKET_TX_RING nicht die versprochene Performanz erreicht. Versuche, die Per- formance zu verbessern, unter anderem mittels

• Vergrößern des NIC-Ringpuffers (ethtool -K DEV tx N),

• Vergrößern/Verkleinern des Socket-Ringpuffers und

• Veränderung von Interrupt-Assoziation und Scheduling-Prioritäten, haben keine signifikanten Änderungen gezeigt. Vermutlich ist dieser Sachverhalt auf eine Problematik innerhalb des Linux Kernels zurückzuführen, wie Jesper Dangaard Brouer beschreibt [Bro13]. Da PACKET_RX_RING offensichtlich nicht betroffen scheint, bietet sich der hybride Ansatz als gute Alternative an. Mit der Nutzung getrennter RX- und TX-Threads durch die Einführung einer zusätzlichen Warteschlange lässt sich die Leistungsfähigkeit nochmal steigern. Hieran zeigt sich die Überlegenheit von Implementationen, die Multi-Threading nutzen, bereits bei der Simplex-Datenübertragung zwischen zwei Ports. In Kombination mit aktivem Warten können auch bei der Nutzung mehrerer Threads vergleichsweise geringe Laten- zen erzielt werden. Als leistungsfähigste PLUS-Konfiguration wird für den nachfolgenden Vergleich mit anderen Switches auf Aktiv+Hybrid+Queue zurückgegriffen.

4.1.2 Switches

Nachfolgend soll PLUS mit den folgenden Switches verglichen werden:

• Cisco SG 300-10 (Small Business Managed Switch von Cisco; Hardware),

• Open vSwitch (Version 2.0.1) und

• Linux Bridge (Kernel 3.14)

Die beiden letztgenannten Software-Switches werden genauso wie PLUS vom Server der Entwicklungshardware bereitgestellt und unterliegen somit den gleichen Beschrän- kungen.

Bachelorarbeit Carsten Andrich 60 4 Ergebnisbewertung

Hierbei gilt es zu berücksichtigen, dass PLUS von vornherein mit dem Fokus auf einfache Programmierbarkeit entwickelt wurde. Aufgrund der Implementation im User- Space ist PLUS somit Umsetzungen im Kernel-Space und natürlich Hardware-Switches in Bezug auf Performanz konzeptionell unterlegen.

4.1.2.1 Framerate

Die Ergebnisse der Frameratenmessung werden in Abbildung 4.4 wieder relativ zur theoretischen Maximalframerate dargestellt. Bei der Auswertung gilt es zu beachten, dass diese weder vermessen noch vom Server im Switchbetrieb erreicht werden kann (vgl. Abbildung 2.7).

1

0,9

0,8

0,7

0,6

PLUS 0,5 Cisco SG 300-10

Framerate relativ zum theoretischen Maximum Open vSwitch Linux Bridge 0,4 64 128 256 512 1024 2048 Framegröße [Byte]

Abbildung 4.4: Erreichte Frameraten verschiedener Switch-Implementationen

Es folgt eine differenzierte Bewertung der Messergebnisse der 4 Switches:

• Cisco SG 300-10 Wie von einem Hardware-Switch zu erwarten, werden die Grenzen der Messhard- ware ausgereizt. Es ist davon auszugehen, dass der Switch das theoretische Limit vollständig erreichen würde, sofern dies vermessen werden könnte.

Bachelorarbeit Carsten Andrich 4.1 Quantitativ 61

• Open vSwitch (OvS) Als Performantester der betrachteten Software-Switches erreicht OvS ebenfalls fast immer die Grenzen des Messsystems. Einzige Ausnahme bilden die gene- rell sehr herausfordernden 64-Byte-Frames, bei denen OvS interessanterweise die in Abbildung 2.5 dargestellten pktgen-Maximalframeraten des Server NIC #1 deutlich überschreitet.

• Linux Bridge Verzeichnet signifikant schlechtere Ergebnisse als OvS und erreicht die praktisch möglichen pktgen-Senderaten weder für 64- noch für 128-Byte-Frames (vgl. Ab- bildung 2.5).

• PLUS Die genutzte PLUS-Konfiguration erreicht die Realisierbarkeitsgrenzen der Hard- ware des Servers und überschreitet damit die Frameraten der Kernel-Space Im- plementation Linux Bridge erheblich. Lediglich Open vSwitch kann für 64-Byte- Frames bessere Frameraten verzeichnen.

4.1.2.2 Latenz

Abbildung 4.5 stellt Übertragungslatenzen ohne Hintergrunddatenverkehr dar.

200

150

100

50

0 Latenz [µs] -50 PLUS Cisco SG 300-10 -100 Open vSwitch Linux Bridge -150 64 128 256 512 1024 2048 Framegröße [Byte]

Abbildung 4.5: Switch-Übertragungslatenzen ohne Hintergrunddatenverkehr

Bachelorarbeit Carsten Andrich 62 4 Ergebnisbewertung

Die Messergebnisse sind wie folgt zu deuten:

• Open vSwitch / Linux Bridge Beide Kernel-Space Implementationen weisen im Rahmen der Messunsicherheit nicht unterscheidbare Latenzwerte auf.

• PLUS Erreicht trotz der Implementation im User-Space statistisch signifikant gerin- gere Latenzen als die beiden Kernel-Switches. Dieser Sachverhalt ist mit hoher Wahrscheinlichkeit auf das aktive Warten der genutzten PLUS-Konfiguration zu- rückzuführen.

• Cisco SG 300-10 Wie für einen Hardware-Switch zu erwarten, wird eine im Rahmen der Genauig- keit des Messsystems nicht bezifferbare, vernachlässigbar geringe Latenz erreicht.

Anhand der Messwerte für Latenzen bei Saturierung des Übertragungsmediums in Abbildung 4.6 lassen sich die Software-Switches wieder statistisch nicht separieren. Lediglich der Hardware-Switch weist hier erwartungsgemäß die geringste Latenz auf.

500 400 300 200 100 0 Latenz [µs] -100 PLUS -200 Cisco SG 300-10 Open vSwitch -300 Linux Bridge

64 128 256 512 1024 2048 Framegröße [Byte]

Abbildung 4.6: Switch-Übertragungslatenzen bei maximal saturiertem Medium

Bachelorarbeit Carsten Andrich 4.1 Quantitativ 63

4.1.2.3 Schlussfolgerungen

PLUS und andere Software-Implementationen sind Hardware-Switches sowohl in Be- zug auf erreichbare Frameraten als auch Übertragungslatenzen generell unterlegen. Dennoch können Software-Switches – auch im User-Space – Leistungsdaten erzielen, die mit denen von Hardware vergleichbar sind. Lediglich die vernachlässigbar gerin- gen Latenzen von Hardware-Switches sind mit Software-Realisierungen wohl auch in absehbarer Zeit nicht zu erreichen. Die Latenzen der betrachteten Software-Switches betragen jedoch auch bei Voll- auslastung des Übertragungsmediums im Mittel weniger als 0,4 ms und sollten so keine negativen Auswirkungen auf realistische Anwendungsszenarien haben. Weiterhin ist bemerkenswert, dass sich mit PLUS unter Verwendung von aktivem Warten signifikant geringe Latenzen erreichen lassen als mit Kernel-Space Implementationen. An den hohen Unsicherheiten der gemessenen Latenzen zeigt sich jedoch, dass Computer-Hardware für präzise Latenzmessungen ungeeignet ist. Dies ist naheliegend, da derartige Hardware diversen nicht-deterministischen Einflüssen wie Scheduling und Interrupts unterliegt.

4.1.3 Zusammenfassung

Die Messungen zusammenfassend lässt sich anmerken, dass mit PLUS ein Software- Switch geschaffen wurde, der die Möglichkeiten der Entwicklungshardware komplett ausschöpft und somit Kernel-Switches ebenbürtige oder überlegene Leistungsdaten er- reicht. Dies ist insofern unerwartet, als dass User-Space Applikationen konzeptionell weniger leistungsfähig als Umsetzungen im Kernel-Space sind. Lediglich Hardware- Switches bieten teilweise deutlich überlegene Leistungsdaten, wobei PLUS jedoch auf- grund der einfachen Programmierbarkeit dennoch als konkurrenzfähig angesehen wer- den kann.

Bachelorarbeit Carsten Andrich 64 4 Ergebnisbewertung

4.2 Qualitativ

Aufbauend auf der quantitativen Bewertung von PLUS erfolgt hier eine qualitative Betrachtung anhand eines Teils der in Kapitel 1.4 aufgestellten Anforderungen:

• stabiles, einfaches API und Programmierbarkeit im User-Space Die Simplizität des APIs wurde bereits demonstriert. Mit wenigen Zeilen Quell- code lässt sich ein Hub implementieren, ohne mit PLUS-Implementationsdetails in Berührung zu kommen. Die Nutzung externer Funktionen wie z.B. aus der C++ Standardbibliothek wurde ebenfalls gezeigt.

• Prioritätsbasierte Weiterleitung, Weiterleitungsentscheidungen auf Basis individueller Pakete und Schnittstelle für den Versand benutzerdefinierter Daten Vollständig über simples API implementiert. Die ausführliche Doxygen API- Dokumentation befindet sich auf dem zu dieser Arbeit gehörigen Datenträger (siehe Anhang B).

• Performance vergleichbar mit Hardware-Switches und Variable Portanzahl mit skalierender Performance Die durchgeführten Performancemessungen zeigen, dass PLUS bedingt mit Hard- ware-Switches mithalten kann. In Bezug auf Übertragungslatenzen ergeben sich zwar deutliche Unterschiede, da die Verzögerungen aber auch unter Last mit < 0,5 ms sehr gering ausfallen, sollten sich hierdurch keine Einschränkungen ergeben. Lediglich die Übertragung von Frames geringer Größe kann PLUS nicht mit der maximal möglichen Framerate bewerkstelligen. Da effizientes Multi-Threading eines der primären Designziele von PLUS dar- stellt, sollte PLUS – entsprechend performante Hardware vorausgesetzt – deut- lich über die getestete Anzahl von 2 Ports hinaus skalieren.

Die zu Beginn dieser Arbeit an einen programmierbaren Switch gestellten Anforderun- gen werden von PLUS also nahezu uneingeschränkt erfüllt, weshalb die Implementa- tion überaus positiv bewertet werden kann. Aufgrund des beschränkten Zeitrahmens konnten zwar nicht alle Realisierungsmöglichkeiten erprobt und alle Schnittstellen bis zur Serienreife entwickelt werden, um eine spätere Weiterentwicklung zu erleichtern wurden diese jedoch ausreichend dokumentiert.

Bachelorarbeit Carsten Andrich 65

5 Zusammenfassung mit Ausblick

Zusammenfassung

Ziel dieser Arbeit war die Entwicklung eines programmierbaren Switches. Ausgehend von Untersuchungen bestehender Software-Switches konnte hierfür ein Anforderungs- profil entwickelt werden. Im Rahmen der Analyse wurde deutlich, dass die betrachteten Realisierungen hierfür ungeeignet sind, weshalb sich für eine Neuimplementation ent- schieden wurde. Hierfür wurde zunächst die grundsätzliche Leistungsfähigkeit der zur Verfügung stehenden Entwicklungshardware untersucht und auf deren Basis ein automatisier- tes Verfahren entwickelt, mit dem die Leistungsfähigkeit von Switches in Bezug auf Framerate und Latenz vermessen werden kann. Dabei zeigte sich, dass die Netzwerk- Performance der Hardware nicht den Erwartungen entspricht und das theoretische Ma- ximum nicht erreicht werden kann. Untersuchungen dieses Sachverhalts haben keine schlüssigen Resultate hervorgebracht und auch mit der Abstimmung diverser System- parameter konnten keine signifikanten Verbesserungen erzielt werden. Im Anschluss wurden Implementationsmöglichkeiten miteinander verglichen, wo- bei hier insbesondere effizientes Multi-Threading durch die Wahl leistungsfähiger Thread- Modelle und Synchronisationsoperationen im Vordergrund stand. Darauf aufbauend wurde ein einfach programmierbarer, für Performanz optimierter Switch mit mehreren Konfigurationsmöglichkeiten für die Umsetzung der Frameweiterleitung realisiert. Die Implementation wurde anschließend mit mehreren Switches verglichen. Dabei hat sich gezeigt, dass Software-Switches mit Hardware in Bezug auf Performance nur bedingt konkurrieren können. Beim Vergleich mit anderen Software-Switches hat PLUS grundsätzlich ähnliche oder bessere Leistungsdaten erreicht, wobei ein signifikanter Unterschied zwischen den möglichen Konfigurationen auffällig war.

Bachelorarbeit Carsten Andrich 66 5 Zusammenfassung mit Ausblick

Ausblick

Aufgrund des begrenzten Zeitbudgets für die Ausfertigung dieser wissenschaftlichen Arbeit konnten leider nicht alle Implementationsmöglichkeiten verfolgt und miteinan- der verglichen werden. Für zukünftige Untersuchungen wäre insbesondere der messbare Leistungsunterschied zwischen dem gewählten und den in Anhang A beschriebenen al- ternativen Thread-Modellen von Interesse. Obwohl ein vergleichsweise großer Aufwand für eine effizient skalierende Imple- mentation betrieben wurde, war eine Messung der Resultate aufgrund der beschränkten Entwicklungshardware nicht möglich. Neben Frameratenmessungen mit mehr als nur 2 aktiven Ports, wären ebenfalls Fairness Tests, also Untersuchungen wie im Staufall die verfügbaren Ressourcen auf die konkurrierenden Ports aufgeteilt werden, relevant. Darüber hinaus bedarf die Diskrepanz zwischen erreichten und theoretisch mög- lichen Frameraten genauere Untersuchungen, wobei sowohl die Leistungsfähigkeit der eingesetzten Hardware (CPUs, NICs, RAM und Mainboards) als auch der Software (Kernel-API und NIC-Treiber) betrachtet werden sollte. Da PLUS die Beschränkun- gen der Testhardware ausgereizt hat, sollten die Messungen auf Hardware wiederholt werden, mit der die theoretischen Grenzen erreicht werden können. Parallel dazu bietet sich eine Analyse der Unterschiede zwischen Open vSwitch und Linux Bridge an, da erhebliche Leistungsunterschiede zwischen beiden Switches auftreten, obwohl es sich um Kernel-Space Implementationen handelt. Abschließend bleibt zu sagen, dass es sich bei der Implementation von Switches auf Basis gewöhnlicher Desktop- bzw. Server-Betriebssystemen um eine herausfordernde Thematik handelt, für die weiterer Forschungsbedarf besteht.

Bachelorarbeit Carsten Andrich 67

Anhang

Bachelorarbeit Carsten Andrich

69

A Alternative Thread-Modelle

Alternativ zu dem in Kapitel 3.3.1 beschriebenen einfachen, statischen Thread-Modell bieten sich fortgeschrittene Möglichkeiten der Arbeitsverteilung auf mehrere Threads an. Da diese im Zeitrahmen der Arbeit nicht implementiert und evaluiert werden konn- ten, soll im Folgenden eine kurze theoretische Betrachtung durchgeführt werden.

A.1 Dynamische Thread-Modelle

Dynamische Thread-Modelle bieten den Vorteil, dass nicht statisch zwischen Switch- Ports und Threads assoziiert wird. Stattdessen kommen 2 verschiedene Typen von Threads zum Einsatz:

• Dispatcher untersuchen die anfallende Arbeit grob und verteilen diese entsprechend auf sog. Worker-Threads, wobei diese möglichst gleichmäßig belastet werden sollen.

• Worker erledigen die ihnen zugeteilten Aufgaben.

Dies hat den entscheidenden Vorteil, dass nicht wie im statischen Fall bei hoher Belas- tung eines oder weniger Ports die zugehörigen Threads überlastet werden während die verbleibenden Threads nur sporadisch arbeiten. Stattdessen wird die Last gleichmäßig auf alle vorhandenen Threads verteilt und somit die verfügbaren Ressourcen besser genutzt. Die Kommunikation zwischen den Dispatcher- und Worker-Threads erfolgt idealerweise mit effizienten Ringpuffern. Dieses Prinzip wird auf PLUS vereinfachend anhand von PACKET_{RX,TX}_RING abgebildet. Anstelle des ineffizienten PACKET_TX_RING kann in einer Implementation entweder ein Direktversand mittels sendto() oder das Einreihen in eine Prioritätswar- teschlange genutzt werden.

Bachelorarbeit Carsten Andrich 70 A Alternative Thread-Modelle

A.1.1 Gemeinsamer Ringpuffer

Abbildung A.1 stellt eine Realisierung dar, die einen Dispatcher und 3 Worker, sowie einen gemeinsamen Worker-Ringpuffer nutzt. Die Anzahl beider Thread-Typen ist natürlich variierbar.

⑤ ③ RX1 ① ② TX1 ③ ① ⑤ ① ② W1-3 ③ ④ ⑥ ⑤ ⑥ RX2 ② ④ TX2 ④ ③ ⑥

Abbildung A.1: Funktionprinzip des dynamischen Thread-Modells mit geteiltem Ring- puffer (Vereinfachtes Beispiel ohne Anwendungsbezug: Nummerierung stellt Empfangsreihenfolge dar, Farben Thread-Zugehörigkeit)

Wie die Abbildung zeigt, hat der Dispatcher (rot) exklusiven Zugriff auf die RX-Ringe und beschreibt den geteilten Worker-Ring mit Arbeitsanweisungen. Diese bestehen idealerweise lediglich aus Referenzen auf die zu bearbeitenden Einträge der RX-Ringe, damit keine unnötigen Kopien durchgeführt werden müssen und der Dispatcher-Thread möglichst effizient arbeiten kann. Die Worker-Threads lesen diese Referenzen aus dem Worker-Ring. Da der Zugriff auf diesen parallel erfolgt, muss eine Thread-Synchronisation sichergestellt werden. Hierfür sollte das erprobte und effiziente Fetch-and-Add-Verfahren verwendet werden. Anschließend verarbeiten die Worker die referenzierten Frames (Treffen der Weiter- leitungsentscheidung und Versenden über die entsprechenden Ports) und geben die RX-Ringeinträge wieder frei. Problematisch an diesem Verfahren ist der simultane, lesende Zugriff auf den ge- meinsamen Worker-Ringpuffer, da daraus eine vergleichsweise hohe Wahrscheinlichkeit von Lock Contention resultiert. Dies kann umgangen werden, indem separate Grup- pen aus Dispatchern und Workern verwendet werden, die jeweils für ein Subset der Switch-Ports zuständig sind. Dabei findet allerdings keine Lastverteilung außerhalb der Gruppen mehr statt.

Bachelorarbeit Carsten Andrich A.1 Dynamische Thread-Modelle 71

A.1.2 Private Ringpuffer

Die Lock Contention Problematik des zwischen allen Worker-Threads geteilten Ring- puffers tritt nicht auf, wenn stattdessen private Ringpuffer genutzt werden. Abbildung A.2 stellt dieses Prinzip wieder auf Basis eines Dispatchers und 3 Workern dar.

① W1 ④ ⑤ ③ RX1 ① ② TX1 ③ ① ⑤ ② ⑤ W2

⑥ RX2 ② ④ TX2 ④ ③ ⑥ ③ ⑥ W3

Abbildung A.2: Funktionprinzip des dynamischen Thread-Modells mit privaten Ring- puffern (Vereinfachtes Beispiel ohne Anwendungsbezug: Nummerie- rung stellt Empfangsreihenfolge dar, Farben Thread-Zugehörigkeit)

Der Dispatcher (rot) hat immer noch exklusiven Zugriff auf die RX-Ringe, beschreibt nun aber für jeden Worker einen separaten Ringpuffer. Somit haben die Worker- Threads exklusiven Zugriff auf ihre Ringe und es kann synchronisationsfrei gearbeitet werden. Die Abbildung zeigt eine einfache Round-Robin-basierte Arbeitsverteilung durch den Dispatcher, aber natürlich können hier ausgeklügeltere Verfahren angewandt wer- den. Dies ist insbesondere erforderlich wenn die einzelnen Worker die zugeteilten Fra- mes nicht gleich schnell bearbeiten. Idealerweise überwacht der Dispatcher den Füll- stand der Worker-Ringe und verteilt die Arbeit entsprechend.

Bachelorarbeit Carsten Andrich 72 A Alternative Thread-Modelle

A.1.3 Fazit

Dynamische Thread-Modelle erlauben prinzipiell eine bessere Lastverteilung auf die verfügbaren Threads, insbesondere wenn das Verkehrsaufkommen nicht über alle Ports symmetrisch ist. Der durch den Dispatcher sowie Synchronisation verursachte Over- head1 ist aber genauso kritisch zu bewerten wie die komplexere und somit fehleranfäl- ligere Implementation.

A.2 Erweitertes statisches Thread-Modell

Zur Vermeidung der genannten Overhead-Problematik kann auch das statische Thread- Modell erweitert werden. Bereits in Kapitel 3.3.1 wurde die Möglichkeit erwähnt, auf Basis von PACKET_FANOUT mehrere Threads pro RX-Port zu nutzen. Sofern dies statisch geschieht und mehr Threads als CPU-Kerne verwendet werden, verursachen die einsetz- enden Context Switches jedoch einen nicht vernachlässigbaren Scheduling-Overhead. Alternativ zum dauerhaften Betreiben mehrerer Threads pro Port können im Überlastfall adaptiv neue Threads zugeschaltet werden. Wenn pro Port immer ein Thread für die Grundlast bereitsteht, hält dies die Latenz gering und die zusätzlich verfügbaren Threads ermöglichen dennoch im Bedarfsfall die Rechenleistung mehrerer CPU-Kerne pro Switch-Port zu nutzen. Die Spitzenlast-Threads können schlafen gelegt werden, sobald diese nicht mehr benötigt werden. Hierfür muss eine Überwachung der Lastsituation erfolgen. PACKET_RX_RING stellt dafür unter anderem die Möglichkeit bereit, den beim Überlaufen des Ringpuffers auftretenden Paketverlust zu erkennen. Somit ist dieses erweiterte statische Thread- Modell problemlos realisierbar.

1 Insbesondere die Latenz leidet unter einer Aufspaltung von Frame-Empfang, -Bearbeitung und - Versand auf mehrere Threads, sofern kein aktives Warten zum Einsatz kommt (vgl. Kapitel 4.1.1.2).

Bachelorarbeit Carsten Andrich 73

B Inhaltsverzeichnis Datenträger

Der Inhalt des angehängten Datenträgers ist wie folgt strukturiert:

|-- Ausarbeitung LaTeX-Quellen der Ausarbeitung | | | |-- bilder Grafiken | | | \-- messdaten Realisierung/Visualisierung der Messungen | | (Quellcode der Messsysteme und Messdaten | | jeweils im Rohformat und verarbeitet sowie zur | | Visualisierung erforderliche .gnuplot Dateien) | | | |-- atomic_bench Benchmark Assembler/C11/Pthreads Locking | | | |-- framerate Messung Ethernet Frameraten mittels pktgen | | | |-- latency Messung Ethernet Latenz mittels ping/iperf3 | | | |-- lmbench Benchmark CPU-Speicherzugriff mittels lmbench | | | \-- syscall_bench Benchmark getppid() Syscall | |-- Implementation PLUS Implementation | | | |-- doc Doxygen Dokumentation | | | \-- src Quellcode | | | |-- plus PLUS | | | | | \-- include PLUS API Header | | | |-- plus_hub PLUS Plugin Hub | | | \-- plus_switch PLUS Plugin Switch | \-- Quellen Abgespeicherte Internet-Quellen

Bachelorarbeit Carsten Andrich

Literaturverzeichnis 75

Literaturverzeichnis

[B+14] Borkmann, Daniel u. a.: packet_mmap.txt. The Linux Kernel Ar- chives, Dokumentation. https://www.kernel.org/doc/Documentation/ networking/packet_mmap.txt. Version: 2014, Abruf: 30.04.2014

[Bro13] Brouer, Jesper D.: trafgen: speedup TX only path by avoiding kernel packet_rcv() call. GitHub, netsniff-ng. https://github.com/netsniff-ng/netsniff-ng/commit/ c3602a995b21e8133c7f4fd1fb1e7e21b6a844f1. Version: 2013, Ab- ruf: 05.05.2014

[CT08] Coleman, James ; Taylor, Perry: Hardware Level IO Bench- marking of PCI Express, Intel Corporation, Whitepaper, 2008. http://www.intel.com/content/dam/www/public/us/en/documents/ white-papers/pcie-hw-level-io-benchmarking-paper.pdf, Abruf: 08.04.2014

[IEE90] IEEE Standards Association: 802.4-1990 – IEEE Standard for Token-Passing Bus Access Method and Physical Layer Specificati- ons. http://standards.ieee.org/findstds/standard/802.4-1990. html. Version: 1990, Abruf: 14.04.2014

[IEE01] IEEE Standards Association: 802.5v-2001 – IEEE Standard for Informa- tion Technology – Telecommunications and information exchange between systems – Local and metropolitan area networks – Part 5: Token Ring ac- cess method and physical layer specifications Gigabit Token Ring Opera- tion. http://standards.ieee.org/findstds/standard/802.5v-2001. html. Version: 2001, Abruf: 13.04.2014

[Int14] Intel 64 and IA-32 Architectures Software Developer’s Manuals. Bd. 3: Sys- tem Programming Guide. Intel Corporation, 2014. – Kapitel 8.1

Bachelorarbeit Carsten Andrich 76 Literaturverzeichnis

[ipe14] iperf3: A TCP, UDP, and SCTP network bandwidth measurement tool. https://github.com/esnet/iperf. Version: 2014, Abruf: 15.04.2014

[ITU09] International Telegraph Union: ITU-T Y.1563: Ethernet frame trans- fer and availability performance. http://www.itu.int/rec/T-REC-Y. 1563-200901-I/en. Version: 2009, Abruf: 07.04.2014

[Ker10] Kerrisk, Michael T.: The Linux Programming Interface. No Starch Press, 2010. – ISBN 978–1–59327–220–3

[KH+11] Kroah-Hartman, Greg u. a.: Stable API Nonsense. The Linux Kernel Ar- chives, Dokumentation. https://www.kernel.org/doc/Documentation/ stable_api_nonsense.txt. Version: 2011, Abruf: 10.03.2014

[Knu01] Knuth, Donald E.: The Art of Computer Programming. Bd. 1. Addison- Wesley, 2001. – ISBN 0–201–89683–4

[Lin09] The Linux Foundation: Linux Bridge. http://www.linuxfoundation. org/collaborate/workgroups/networking/bridge. Version: 2009, Ab- ruf: 13.04.2014

[LIS10] The LISA Project: LISA Downloads. http://lisa.mindbit.ro/ download.html. Version: 2010, Abruf: 09.05.2014

[LKM09] The linux-kernel mailing list FAQ. http://www.tux.org/lkml/#s15-3. Version: 2009, Abruf: 09.05.2014

[LMb07] LMbench – Tools for Performance Analysis. http://sourceforge.net/ projects/lmbench/. Version: 2007, Abruf: 07.04.2014

[Mat09] Mateo, Manuel P.: OpenFlow Switching Performance, Politecni- co Di Torino, Master’s Thesis, 2009. http://www.openflow.org/ downloads/technicalreports/MS_Thesis_Polito_2009_Manuel_ Palacin_OpenFlow.pdf, Abruf: 11.03.2014

[net12] netsniff-ng toolkit. http://netsniff-ng.org/. Version: 2012, Abruf: 14.04.2014

[O+14] Olsson, Robert u. a.: HOWTO for the linux packet generator. The Linux Kernel Archives, Dokumentation. https://www.kernel.org/ doc/Documentation/networking/pktgen.txt. Version: 2014, Abruf: 09.04.2014

Bachelorarbeit Carsten Andrich Literaturverzeichnis 77

[Ols04] Olsson, Robert: pktgen the linux packet generator, Uppsala Universitet & SLU, Paper, 2004. ftp://robur.slu.se/pub/Linux/net-development/ pktgen-testing/pktgen_paper.pdf, Abruf: 09.04.2014

[Ope12] Open Networking Foundation: Software-Defined Networking: The New Norm for Networks. https://www.opennetworking.org/images/ stories/downloads/sdn-resources/white-papers/wp-sdn-newnorm. pdf. Version: 2012, Abruf: 11.03.2014

[OvS14] Open vSwitch. http://openvswitch.org/. Version: 2014, Abruf: 08.03.2014

[per13] perf: Linux profiling with performance counters. https://perf.wiki. kernel.org/index.php/Main_Page. Version: 2013, Abruf: 13.04.2014

[PSWB08] Pahlevanzadeh, B. ; Seno, S.A.H. ; Wan, Tat-Chee ; Budiarto, R.: New approach for flow control using PAUSE frame management. In: Distri- buted Framework and Applications, 2008. DFmA 2008. First International Conference on, 2008, S. 214–219

[RFC99] Internet Engineering Task Force: RFC 2544 – Benchmarking Methodo- logy for Network Interconnect Devices. https://tools.ietf.org/html/ rfc2544. Version: 1999, Abruf: 07.04.2014

[Ros11] Roska, Radim: Performance evaluation of GNU/Linux network bridge, Czech Technical University in Prague, Master’s Thesis, 2011. https:// dip.felk.cvut.cz/browse/pdfcache/roskarad_2011dipl.pdf, Abruf: 08.03.2014

[Rug08] Ruggiero, Joshua: Measuring Cache and Memory Latency and CPU to Memory Bandwidth, Intel Corporation, Whitepaper, 2008. http://www.intel.com/content/dam/www/public/us/en/documents/ white-papers/ia-cache-latency-bandwidth-paper.pdf, Abruf: 07.04.2014

[SG13] Sans, Francisco ; Gamess, Eric: Analytical Performance Evaluation of Different Switch Solutions. In: Journal of Computer Networks and Com- munications (2013). http://www.hindawi.com/journals/jcnc/2013/ 953797/, Abruf: 11.03.2014

Bachelorarbeit Carsten Andrich 78 Literaturverzeichnis

[Sü11] Sünnen, Dany: Performance Evaluation of OpenFlow Switches, Eidge- nössische Technische Hochschule Zürich, Semester Thesis, 2011. ftp:// ftp.tik.ee.ethz.ch/pub/students/2011-FS/SA-2011-07.pdf, Abruf: 11.03.2014

[VM11] Varis, N. ; Manner, J.: Performance of a software switch. In: High Per- formance Switching and Routing (HPSR), 2011 IEEE 12th International Conference on, 2011, S. 256–263

[Yu04] Yu, James T.: Performance Evaluation of Linux Bridge, DePaul Uni- versity, Forschungsbericht, 2004. http://facweb.cti.depaul.edu/jyu/ Publications/Yu-Linux-TSM2004.pdf, Abruf: 08.03.2014

Bachelorarbeit Carsten Andrich Abbildungsverzeichnis 79

Abbildungsverzeichnis

1.1 Funktionsprinzip des OpenFlow Protokolls ...... 7 1.2 Anwendungsbeispiel Open vSwitch ...... 9 1.3 Funktionsweise von Open vSwitch ...... 11

2.1 Entwicklungshardware ...... 16 2.2 Latenz von CPU-Speicherlesezugriffen ...... 18 2.3 Datenrate von CPU-Speicherlesezugriffen ...... 19 2.4 Ethernet-Paketformat (ohne IEEE 802.1Q Tag) mit Längenangaben in Byte für individuelle Bestandteile, sowie gesamtes Paket bzw. Frame . . 24 2.5 Abweichung der ausgehenden Frameraten vom theoretischen Maximum 30 2.6 RTT zwischen X301 und X201 ...... 32 2.7 Theoretische/Realisierbare Messframerate ...... 34

3.1 Funktionsweise der Frameweiterleitung mittels PACKET_RX_RING und PACKET_TX_RING ...... 39 3.2 Funktionsprinzip des statischen Thread-Modells ...... 41 3.3 Messtechnischer Vergleich möglicher Synchronisationsmechanismen . . . 45 3.4 Funktionsweise der Prioritätswarteschlange ...... 49

4.1 Erreichte Frameraten verschiedener PLUS-Konfigurationen ...... 56 4.2 PLUS-Übertragungslatenzen ohne Hintergrunddatenverkehr ...... 57 4.3 PLUS-Übertragungslatenzen bei maximal saturiertem Medium . . . . . 58 4.4 Erreichte Frameraten verschiedener Switch-Implementationen ...... 60 4.5 Switch-Übertragungslatenzen ohne Hintergrunddatenverkehr ...... 61 4.6 Switch-Übertragungslatenzen bei maximal saturiertem Medium . . . . 62

A.1 Funktionprinzip des dynamischen Thread-Modells mit geteiltem Ring- puffer ...... 70 A.2 Funktionprinzip des dynamischen Thread-Modells mit privaten Ring- puffern ...... 71

Bachelorarbeit Carsten Andrich

Tabellenverzeichnis 81

Tabellenverzeichnis

1.1 Beispiel einer OpenFlow Flow-Tabelle ...... 7

2.1 Konfiguration und Leistungsdaten der Entwicklungshardware ...... 20 2.2 Theoretisches Limit für GbE-Frameraten ...... 26 2.3 Ausgehend maximal erreichbare Frameraten der Entwicklungshardware 29 2.4 Eingehende Frameraten der Server-NICs bei Versand durch X301 . . . 31

Bachelorarbeit Carsten Andrich

Quellcodeverzeichnis 83

Quellcodeverzeichnis

1.1 Linux Bridge einrichten ...... 5 1.2 Open vSwitch einrichten ...... 9

2.1 Messung der Speicherdatenrate mit bw_mem ...... 17 2.2 Messung der Speicherlatenz mit lat_mem_rd ...... 17

3.1 Initialisierung eines Packet Sockets unter Linux ...... 36 3.2 Simplex-Frameweiterleitung mittels recvfrom()/sendto()-Syscalls .. 36 3.3 C11-konformes Alignment und Padding von Datentypen auf SIZE Byte 44 3.4 Primäre PLUS API-Funktion plus_plugin_fwd() ...... 51 3.5 Beispiel für PLUS-Implementation eines Hubs ...... 52 3.6 Vereinfachtes Beispiel für PLUS-Implementation eines Switches . . . . 53

Bachelorarbeit Carsten Andrich

Abkürzungsverzeichnis und Formelzeichen 85

Abkürzungsverzeichnis und Formelzeichen

API ...... Application Programming Interface ARP ...... Address Resolution Protocol BPF ...... Berkeley Packet Filter BSD ...... Berkeley Software Distribution CPU ...... Central Processing Unit CRC ...... Cyclic Redundancy Check CSMA/CD ...... Carrier Sense Multiple Access with Collision Detection DDR ...... Double Data Rate FCS ...... Frame Check Sequence FDDI ...... Fiber Distributed Data Interface GbE ...... Gigabit Ethernet ICMP ...... Internet Control Message Protocol IEEE ...... Institute of Electrical and Electronics Engineers IETF ...... Internet Engineering Task Force IGMP ...... Internet Group Management Protocol IP ...... Internet Protocol IPG ...... Interpacket Gap ITU ...... International Telecommunication Union ITU-T ...... ITU Telecommunication Standardization Sector L1 ...... Level 1 L2 ...... Level 2 L3 ...... Level 3 LAN ...... Local Area Network LISA ...... Linux Switching Appliance LTO ...... Link Time Optimizations MAC ...... Media Access Control MLD ...... Multicast Listener Discovery

Bachelorarbeit Carsten Andrich 86 Abkürzungsverzeichnis und Formelzeichen

Mutex ...... Mutual exclusion NIC ...... Network Interface Controller OSI ...... Open Systems Interconnection OvS ...... Open vSwitch PCIe ...... Peripheral Component Interconnect express PLUS ...... Programmierbarer Linux User-Space Switch pNIC ...... physical Network Interface Controller POSIX ...... Portable Operating System Interface Pthreads ...... POSIX Threads QoS ...... Quality of Service RAM ...... Random Access Memory RFC ...... Request For Comments RTT ...... Round Trip Time RX ...... Receive SAT ...... Source Address Table SDN ...... Software-Defined Networking SFD ...... Start of Frame Delimiter STP ...... Spanning Tree Protocol TCP ...... Transmission Control Protocol TX ...... Transmit UDP ...... User Datagram Protocol VLAN ...... Virtual Local Area Network VM ...... Virtuelle Maschine vNIC ...... virtual Network Interface Controller WLAN ...... Wireless Local Area Network

Bachelorarbeit Carsten Andrich Thesen zur Bachelorarbeit 87

Thesen zur Bachelorarbeit

1. Netzwerksimulatoren und programmierbare Software-Switches stellen wichtige Werkzeuge der Protokollentwicklung dar und ergänzen sich gegenseitig.

2. Programmierung im User-Space ermöglicht hohe Flexibilität und garantiert War- tungsfreiheit durch die Nutzung des stabilen und abwärtskompatiblen Syscall- APIs.

3. Linux bietet mehrere Implementationsansätze für User-Space-Switches. Ein sorg- fältiger Vergleich ist erforderlich, damit optimale Leistungscharakteristiken er- reicht werden.

4. Parallelisierung ermöglicht prinzipiell bessere Performanz als sequenzielle Reali- sierungen. Damit die Gesamtleistung mit der Thread-Anzahl skaliert, sind jedoch geschickt konzipierte Synchronisationsmechanismen erforderlich.

5. User-Space-Switches können Kernel-Implementationen gleichwertige Leistungs- daten erzielen. Eine Konkurrenzfähigkeit mit Hardware-Switches besteht jedoch nur bedingt.

Coburg, den 14. 05. 2014 Carsten Andrich

Bachelorarbeit Carsten Andrich

Erklärung 89

Erklärung

Die vorliegende Arbeit habe ich selbstständig ohne Benutzung anderer als der angege- benen Quellen angefertigt. Alle Stellen, die wörtlich oder sinngemäß aus veröffentlich- ten Quellen entnommen wurden, sind als solche kenntlich gemacht. Die Arbeit ist in gleicher oder ähnlicher Form oder auszugsweise im Rahmen einer oder anderer Prü- fungen noch nicht vorgelegt worden.

Coburg, den 14. 05. 2014 Carsten Andrich

Bachelorarbeit Carsten Andrich