Aktualisierung des PTPPatch für Kernel 2.6.15 Überarbeitung des

Transcription

Aktualisierung des PTPPatch für Kernel 2.6.15 Überarbeitung des
Aktualisierung des PTP­Patch für Kernel 2.6.15
und Überarbeitung des Codes „Faster Initial Convergence“ von CADPC
Name: Martin Rabanser
Matrikelnr.: 0217224
Datum: 14.09.2006
Tutor: Michael Welzl
Inhaltsverzeichnis
1. Einführung in PTP..................................................................................................................................1
1.1 Problemstellung...............................................................................................................................1
1.2 Das Performance Transparency Protocol (PTP)..............................................................................1
1.3 Einsatzgebiete..................................................................................................................................2
1.4 Die Teststrecke................................................................................................................................3
2. Patchen des Kernels...............................................................................................................................4
2.1 Ausgangssituation...........................................................................................................................4
2.2 Wahl einer geeigneten aktuellen Kernelversion..............................................................................5
2.3 Die Änderungen im Detail..............................................................................................................5
2.4 Kritische Stellen..............................................................................................................................8
2.5 Generieren des PTP­Patches............................................................................................................9
2.6 Installation & Test des PTP­Patches.............................................................................................10
3. Aktualisierung von CADPC.................................................................................................................12
3.1 Einführung in CADPC..................................................................................................................12
3.2 Faster Initial Convergence.............................................................................................................13
4. Literaturverzeichnis.............................................................................................................................17
5. Anhang.................................................................................................................................................18
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
1. Einführung in PTP
1.1 Problemstellung
Aufgabe dieses Teils der Bakkalaureatsarbeit war es, den bestehenden Kernelpatch für die Version 2.4.26 auf einen aktuellen Kernel (2.6.15) umzuschreiben, damit die Verwendung des PTP­Protokolls bzw. dessen Weiterentwicklung auch für die nächste Zukunft gesichert ist. Arbeit und Aufwand dafür sind mit dem Versionssprung des Patches von 2.2 auf 2.4 vergleichbar.
1.2 Das Performance Transparency Protocol (PTP)
Bei Netzwerkverbindungen bei denen ständig viele Daten übertragen werden, beispielsweise Streaming, Videotelefonie etc. kommt es vor, dass die Übertragungsrate entweder grösser oder kleiner als die Kapazität eines Routers ist. Im ersten Fall hat die Verbindung einen Flaschenhals und Pakete werden verworfen. Im zweiten Fall wird die Verbindung nicht optimal ausgenutzt da zu wenig Pakete gesendet werden. Genau an diesem Punkt soll das PTP­Protokoll eingreifen und die Übertragungsrate an die größtmögliche Bandbreite auf einem Netzwerkpfad anpassen.
Das PTP­Protokoll wurde von Michael Welzl spezifiziert und soll dazu beitragen den Netzwerkverkehr zu optimieren und Router optimal auszulasten, indem Daten über deren Auslastung gesammelt und ausgewertet werden. Dabei Seite 1 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
werden Bandbreiteninformationen von jedem Router auf einem Netzwerkpfad an Pakete gehängt, welche am Endknoten die Grundlage für die Performanceberechnungen darstellen. Anschließend werden die errechneten Daten dem Sender zurückgeschickt, welcher angemessen auf die Informationen reagieren kann. Ziel ist es, dieses Teilprotokoll mit einem bestehenden Protokoll wie z.B. UDP zu kombinieren, sodass der Anwender (oder die Anwendung) auf einer höheren Schicht von der Optimierung nichts bemerkt und das Protokoll eigenständig und automatisch ein gesamtes Teilnetz optimiert.
1.3 Einsatzgebiete
Das PTP­Protokoll wurde dazu entwickelt, die Übertragungsraten für Applikationen an die Gegebenheiten des Pfades anzupassen. Ein aktuelles Beispiel dafür wäre die Videotelefonie.
Ein weiteres Einsatzgebiet wäre das PTP­Protokoll als Administrationstool für eine Domäne, in dem ein Administrator die Kontrolle über all seine Rechner hat. So könnte das Protokoll dazu eingesetzt werden, um dem Administrator zu signalisieren an welchen Stellen sein Netzwerk besonders stark ausgelastet ist bzw. wo es Flaschenhälse gibt. Da dies aber nicht das verfolgte Ziel bei der Spezifikation des Protokolls war, kann es für dieses Szenario durchaus notwendig sein, einige Anpassungen an der Implementierung vorzunehmen.
Grundsätzlich kann dieses Protokoll als Grundlage für Staukontrolleverfahren Seite 2 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
wie z.B. CADPC eingesetzt werden, welches weniger Paketverluste und teilweise höhere sowie glattere Übertragungsraten als TCP erreicht. [Michael Welzl: Scalable Performance Signalling And Congestion Avoidance. Kluwer Academic Publishers, August 2003]
1.4 Die Teststrecke
Das Testen des PTP­Protokolls ist mit einigem Aufwand verbunden, da 2 Endknoten nicht genügen, sondern ein Netzwerk mit mindestens 3 Rechnern zum Einsatz kommen muss, wobei einer davon als Router fungiert. Der Aufwand für den Betrieb der beiden Endknoten ist relativ gering. Es genügt die Installation eines beliebigen Linuxsystems, Voraussetzungen sind lediglich ein funktionierendes Netzwerk in der Version IPv4 und ein “gcc­Kompiler”. Dieser ist zwar nicht zwingend notwendig, aber die Kompilierung der Testprogramme auf dem Zielrechner garantiert deren korrekte Funktion. Eventuell kann auch eine Knoppixdistribution zum Einsatz herangezogen werden, sollten keine Linuxrechner zur Verfügung stehen und/oder eine Neuinstallation zu aufwendig sein. Andere Betriebssysteme kommen derzeit nicht in Frage, da die Sockets mit dem Protokoll Nr. 123 initiiert werden, welches zwar offiziell bei der Authorisierungsstelle angemeldet wurde, aber sicher noch nicht in jedem Betriebssystem verwendet werden kann. Weiters greifen sowohl Client als auch Server auf einen Handler zurück, der auf die posixkonforme IPC von Unix aufsetzt, welche bei weitem nicht von allen Systemen eingehalten wird.
Seite 3 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
Das Aufsetzen des PTP­Routers ist im Vergleich zu den Endknoten wesentlich aufwendiger. Voraussetzung hierfür sind ein beliebiges Linuxsystem sowie der Einsatz des richtigen Kernels und 2 Netzwerkinterfaces. Verwendet wird hier der Standard Vanillakernel dessen Versionsnummer mit der des PTP­Patches übereinstimmt, sodass er vor seinem Einsatz erfolgreich gepatcht werden kann. Bei Verwendung anderer Konfigurationen ist keinerlei Funktion gewährleistet. Damit die Pakete richtig geroutet werden muss der Kernel gepatcht und mit allen wichtigen Routerfunktionen übersetzt werden (IP­Forward). Anschließend wird dieser Kernel gestartet, die Netzwerkinterfaces richtig initialisiert und manuell die Bandbreite des aktuellen Router eingestellt, damit das PTP­Protokoll Daten sammeln und auswerten kann.
2. Patchen des Kernels
2.1 Ausgangssituation
Ausgangssituation für diese Version war der Patch für den Kernel 2.4.26. Die Vorgangsweise ist dieselbe, nachdem die Codezeilen des alten Patches in die Quelldateien des neuen Kernels eingefügt sind, kann mit dem Testen und Kompilieren begonnen werden. Dabei werden Veränderungen am Netzwerkinterface und den Strukturen geklärt, notiert und der Zugriff darauf so lange angepasst bis eine korrekte Funktion des PTP­Routers sichergestellt ist. Diese sollen im Folgenden genauer beschrieben werden.
Seite 4 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
2.2 Wahl einer geeigneten aktuellen Kernelversion
Zur Zeit dieser Entscheidung befand sich die aktuelle Kernelversion des Kernel 2.6 gerade auf Versionsnummer 2.6.15. Durch die stetige Weiterentwicklung des Kernels ist die Verbreitung dieser Version schwierig abzuschätzen, jedoch bedarf es für einen Versionssprung des Patches innerhalb des 2.6­er Kernels keinen großen Aufwand. Die relevanten Files des Netzwerkinterfaces werden innerhalb derselben Kernelversion bis auf Korrekturen von Bugs und Erweiterung der Funktionalität nicht verändert. Zur Zeit der Entstehung dieses Dokumentes existieren weder für Kernel 2.7 noch 2.8 Vorabversionen, sodass eine Portierung auf diese noch nicht in Betracht gezogen werden kann.
2.3 Die Änderungen im Detail
Da testweises Patchen des Kernel 2.6.15 mit dem Patch linux­2.4.26­ptp.patch mit unzähligen Fehlern abbrach, musste jede Zeile des Patches für den Kernel 2.4.26 manuell in den Quellcode des Kernels 2.6.15 eingefügt werden. Die Schwierigkeit bestand zum Einen darin die richtigen Stellen zu finden, da sich die Netzwerkimplementierung des IP­Protokolls v4 von Kernel 2.4 auf 2.6 wie schon von 2.2 auf 2.4 etwas geändert hatte. Weit aufwendiger war auch hier das Verstehen des Codes und die Suche von Funktionen, die es von Version 2.4 auf Version 2.6 entweder nicht mehr gab, oder veränderte Datentypen oder Aufrufe aufwiesen. Zu Gute kamen hier die die bereits gemachten Erfahrungen beim Seite 5 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
Anpassen des Patches von Version 2.2 auf 2.4, da die Funktionalität des Netzwerkinterfaces im Kernel 2.4 schon bekannt war. Auf die Angabe der Zeilenänderungen wird wiederum verzichtet, da der Kernel manuell gepatcht wurde und die richtigen Codestellen ohnehin gesucht werden mussten. Die Angaben der Zeilennummern werden später im Kernelpatch automatisch mitprotokolliert.
Die Deklaration
static
&ptp_inode.u.socket_i;
struct
wurde auf
socket
static
*ptp_socket; reduziert, da die Struktur static
*ptp_socket
struct
struct
=
socket
inode
ptp_inode; nicht mehr existiert.
Eine neue Bibliothek musste mittels #include
<linux/rtnetlink.h>
eingebunden werden, um auf die Konstante RT_SCOPE_UNIVERSE zugreifen zu können.
Weiters hat sich die Struktur struct net_device_stats so verändert, dass auf die übermittelten Bytes nun direkt zugegriffen werden kann. Also von htonl(stats->stats->tx_bytes); auf htonl(stats->tx_bytes);.
Um auf die Funktion ip_send_reply() zugreifen zu können, musste die Bibliothek #include <net/ip.h> eingebunden werden.
Eine große Anzahl von Fehlern mit der Information der Dereferenzierung eines Zeigers auf unvollständige Typen hat die mangelnde Einbindung der Bibliothek #include <linux/ip.h> bereitet. Auf diese Fehler wird hier nicht genauer Seite 6 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
eingegangen, die Datei mit dem Fehler log kann im Anhang eingesehen werden.
Die Codezeile arg.n_iov = 2; bereitete einen Fehler, da die Struktur arg
kein Element namens n_iov mehr hat. Da dies nicht weiter schlimm ist, wurde die Zeile einfach ausgeklammert.
In Struktur struct sock; hat sich der Name des Elementes allocation wie folgt verändert: Von ptp_socket->sk->allocation
=
GFP_ATOMIC; auf ptp_socket->sk->sk_allocation = GFP_ATOMIC;.
Auch das Setzen der maximalen TTL­Zeit muss nun anders gehandhabt werden: Aus ptp_socket->sk->protinfo.af_inet.ttl
= MAXTTL; wird inet_sk(ptp_socket->sk)->uc_ttl = MAXTTL;.
Folgende Zeilen sind im Netzwerkinterface des 2.6.15­er Kernels nicht mehr von Relevanz und wurden ausgeklammert: //
ptp_inode.i_mode = S_IFSOCK;
//
ptp_inode.i_sock = TRUE;
//
ptp_inode.i_uid
= 0;
//
ptp_inode.i_gid
= 0;
//
ptp_socket->inode = &ptp_inode;
Wiederum in Struktur struct sock; muss auf das Element num anders zugegriffen werden. Anstatt ptp_socket->sk->num = 256; wird der Wert Seite 7 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
nun mit inet_sk(ptp_socket->sk)->num = 256; gesetzt.
Die Versionen der „automake“­Pakete sind mit der neuen Kernelversion auch weitergereift, deshalb war es notwendig auch die Makefiles und Konfigurationsdateien des Kernels zu verändern. Wie deren Syntax gehandhabt wird kann sowohl im Anhang enthaltenen Quellcode des Patches eingesehen werden, sowie in der „automake“­ bzw. Kerneldokumentation nachgelesen werden.
Alle anderen Codezeilen des PTP­Protokolls wurden nur an den richtigen, zum Teil verschobenen, Zeilen eingefügt. Die Zeilennummern sind allein im Patch ersichtlich.
2.4 Kritische Stellen
Bei der Anpassung des Protokolls gab es schon bei der Portierung auf den Kernel 2.4 es einige Stellen die bis nach der Testphase als kritisch galten. Diese seien hier aufgeführt, auch weil diese bei der Portierung auf den aktuellen Kernel Schwierigkeiten bereiten hätten können.
In Datei linuxkernel/include/linux/sysctl.h wurden im Kernelpatch 2.4.26 zwischen Zeile 348 und 368 bei folgendem Enum weitere Einträge angefügt, sodass die Konstante NET_IPV4_CONF_IF_SPEED nun den Wert 20 erhält. Diese Zeile galt damals als kritisch, da nicht sicher war ob der Wert 20 in Zukunft von einer anderen Konstanten im Enum genutzt wird. Diese Seite 8 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
Initialisierung hat sich nun aber geändert und kann somit als unkritisch betrachtet werden.
Als kritisch gelten könnten auch die obengenannten entfernten Codezeilen. Da jedoch alle Berechnungen sowie Tests dagegen sprechen werden diese als überflüssig betrachtet und somit deren Entfernung gerechtfertigt.
2.5 Generieren des PTP­Patches
Nachdem alle Einträge des „alten“ Patches im neuen Kernel an deren richtigen Stellen eingefügt sind und die Kompilierung des manuell gepatchten Kernel keinen Fehler mehr ergibt, kann die erste Version des neuen Kernelpatches generiert werden. Wie dieser erstellt wird, kann jederzeit im Patch selbst überprüft bzw. nachgeschlagen werden. Verwendet wird hierbei der Befehl diff, welcher Unterschiede zwischen Dateien findet. Voraussetzung sind Verzeichnisse namens linux-2.6.15, welches den originalen entpackten Vanillakernel 2.6.15 enthält, und linux-2.6.15-ptp, welches einen entpackten und manuell gepatchten Kernel enthält. Vor dem Generieren des Patches muss sichergestellt sein, dass sich keine Objektdateien oder dergleichen in den Verzeichnissen befinden. Dies stellt der Befehl make
mrproper sicher, welcher die Verzeichnisse „säubert“. Anschließend vergleicht der Befehl diff -Naur linux-2.6.15/ linux-2.6.15.ptp/ > linux2.6.15-ptp.patch
den Inhalt aller Unterverzeichnisse und Dateien des originalen Kernels mit jenen des manuell Gepatchten und schreibt die Seite 9 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
Unterschiede in die Datei linux-2.6.15-ptp.patch mit.
Die vergleichsweise unkomplizierte Generierung des Patches ist somit abgeschlossen und erste Tests können gestartet werden.
2.6 Installation & Test des PTP­Patches
Damit das PTP­Protokoll nun mit dem neuen Kernel getestet werden kann, muss der Kernel gepatcht werden. Damit wird auch der Patch selbst auf dessen korrekte Funktion getestet werden. Der Befehl patch -p0 < linux-2.6.15ptp.patch, ausgeführt im selben Verzeichnis wo er erstellt wurde (impliziert die Option ­p0) auf einen neu entpackten Vanillakernel 2.6.15, modifiziert die Quelldateien wie gewünscht.
Im nächsten Schritt wird der Kernel kompiliert, wobei darauf geachtet werden muss, dass die Option, den PTP­Code mit zu übersetzen, auch aktiviert ist. Damit diese Option anwählbar ist, bedarf es der Aktivierung des Schalters Prompt
for
development
Menüpunkt Code
maturity
and/or
level
incomplete
code/drivers
im options. Standardmäßig ist diese Option schon aktiviert. Anschließend kann unter Networking->Networking
Options
der Punkt IP:
PTP
support
(EXPERIMENTAL)
(NEW)
angewählt werden. Zu beachten ist weiters die grundsätzliche Aktivierung der Netzwerkunterstützung inklusive der Auswahl der richtigen Treiber für die Netzwerkhardware, sowie für IP­Forwarding.
Seite 10 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
Sobald der Kernel erfolgreich übersetzt und der Router mit diesem gestartet wurde, benötigt das Protokoll für einen funktionierenden Einsatz noch die Information über die Kapazität der Netzwerkverbindung. Dies muss manuell im /proc
­Verzeichnis gesetzt werden und wird von folgenden Codezeilen automatisiert, vorausgesetzt die Netzwerkschnittstellen zwischen in Verbindung mit den beiden Endknoten sind jeweils eth0 und eth1:
echo 10000 > /proc/sys/net/ipv4/conf/all/mib2_if_speed
echo 10000 > /proc/sys/net/ipv4/conf/default/mib2_if_speed
echo 10000 > /proc/sys/net/ipv4/conf/eth0/mib2_if_speed
echo 10000 > /proc/sys/net/ipv4/conf/eth1/mib2_if_speed
Hierbei wird MIB2_IF_SPEED auf den Wert 10000 gesetzt. Dies ist kein reeller Wert und dient lediglich zum Testen.
Zur Überprüfung der korrekten Funktion des neuen PTP­Kernels wurden die bereits bestehenden Client/Server­Programme herangezogen. Da diese für den Kernel 2.4 umprogrammiert und verwendet wurden und bereits dort aktuelle Distributionen verwendet wurden, liefen sie auch beim Test für den Kernelpatch 2.6.15 ohne Probleme. Deren Funktionen sind im Dokument „Aktualisierung des PTP­Protokolls“ genauestens beschrieben.
Seite 11 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
3. Aktualisierung von CADPC
3.1 Einführung in CADPC
Congestion Avoidance with Distributed Proportional Control (CADPC) ist ein Netzwerkprotokoll, das von Michael Welzl für die Dissertation Scalable Performance Signalling and Congestion Avoidance entwickelt wurde.
Die Idee des Protokolls besteht darin, im Unterschied zu TCP und UDP Zusatzinformationen über einen Pfad im Internet zu sammeln und entsprechend zu verwerten. Diese Informationen bestehen vorwiegend aus Bandbreiteninformationen der einzelnen Router die Aufschluss über deren verfügbaren Kapazitäten geben.
Für das korrekte Sammeln dieser Informationen wird Performance Transparency Protocol (PTP) verwendet, ebenfalls von Michael Welzl entwickelt. PTP setzt auf IP auf, wobei die Informationen im selben Format gesammelt werden wie über SNMP, welches von Netzwerktools verwendet wird. Mit PTP werden Informationen abgefragt, die für SNMP­MIB2 zur Verfügung gestellt werden. Aus diesen Informationen kann CADPC am Endpunkt eines Pfades Staukollisionen berechnen. Im Unterschied zu TCP, welches jeweils Antwortpakete erwartet und so Kollisionen nur dadurch bemerkt indem es sie selbst erzeugt. Trotzdem bietet TCP sowohl eine zuverlässige Übertragung als auch eine intelligentes Bandbreitenhandling.
Seite 12 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
Im Vergleich ignoriert UDP Staukollisionen seinerseits völlig.
CADPC stellt weder eine Konkurrenz zu UDP noch zu TCP dar, da es einerseits selbst keine Netzwerkschicht definiert und andererseits die gesammelten Daten von anderen Protokollen bezieht, die zur Berechnung der Bandbreiteninformationen notwendig sind.
Beim Einsatz von PTP sind die Dienste von Client und Server nicht im eigentlichen Sinne zu verstehen. Der Server, welcher Daten mit limitierter Bandbreite schickt muss gleichzeitig PTP­Pakete erzeugen und an den Zielrechner bzw. Client schicken. Dieser wiederum muss jene Pakete abfangen, auswerten und das Ergebnis zurück an den eigentlichen Server schicken. Somit dient der Client während des Einsatzes von PTP als Informationsserver für den eigentlichen Sender.
3.2 Faster Initial Convergence
Der Einsatz von CADPC und PTP bietet für bestehende dauerhafte Verbindungen wie z.B. Streaming Vorteile. Messungen belegen aber ein Verhalten, dass bei wachsendem Netzwerkverkehr die Dauer der Konvergierung zur maximalen Übertragungsrate von hinzukommenden Verbindungen proportional zur bereits bestehenden Anzahl von Verbindungen ist. Zum Teil dauert das Konvergieren bis zur maximalen Übertragungsrate eines Streams länger als die Übertragung selbst dauert. Dieses Verhalten wird in Kapitel 4.4.2 Seite 13 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
der Originaldokumentation Scalable Performance Signalling and Congestion Avoidance ausführlich behandelt und mathematisch optimiert. Die Optimierung sieht vor die Verbindungsraten konstant zu überprüfen und im Falle einer neuen, hinzukommenden Verbindung deren Rate manuell zu steigern. In der Implementierung geschieht dies in Datei cadpc.cc in der Funktion updateRate(). Der bestehende Code wurde so umgeschrieben, dass er sich so eng wie möglich an die bereits aktualisierte Dokumentation hält. Zwar wurde der Code dadurch modifiziert, das Verhalten des schnellen Startup­Mechanismus verändert sich damit jedoch nicht, da die dokumentierten mathematischen Formeln optimiert sind und deshalb entsprechend implementiert sein müssen. Anschließen wurde er von veralteten und zum Teil überflüssigen Kommentaren sowie auskommentierten Aufrufen gesäubert und durch aktuelle ersetzt.
Mit dem Protokoll wurden keine Tests durchgeführt, um die Effizienz des schnelleren Startupmechanismus zu belegen. Diese Tests wurden bereits von Ben Lavender in seinem Report on using PTP for CADPC dokumentiert. Zwischen der dort verwendeten und der aktuellen Version von CADPC gibt es keine Unterschiede in der Funktionalität und den erzielten Ergebnissen.
Im Folgenden werden die verwendeten Variablen und Formeln erläutert.
In Tabelle 1 sind die verwendeten Variablen in den mathematischen Formeln zusammengefasst und mit deren Codependant aufgelistet. Da der theoretische Seite 14 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
Teil des Mechanismus durch mathematischen Berechnungen belegt ist, werden dort
naheliegenderweise
mathematische
Ausdrücke
und Variablenbezeichnungen verwendet. Im Code werden dagegen, zur besseren Übersicht des Programmierers, aussagekräftige Variablenbezeichnungen verwendet.
Mathematische Variable
Codevariable
m
addUsers
n
convUsers_
x
convRate_
x(t)
currentRate
x(t+1)
newRate
a
smoothness
lambda(0)
traffic
lambda(t)
convTraffic
ny
supConvTraffic
Tabelle 1: Mathematische Variablenbezeichnungen in Formeln und entsprechend im Code
Tabelle 2 zeigt wie die mathematischen Formeln im Code kommentiert sind. Für die Implementierung selbst werden die Variablen laut Tabelle 1 verwendet. Die jeweils darüberstehenden Kommentare dienen lediglich zur bessern Lesbarkeit des Codes.
Die Spalte der Kapitel bezieht sich auf den Abschnitt in der Seite 15 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
Originaldokumentation Scalable Performance Signalling and Congestion Avoidance.
Kapitel
4.11
Formel
Code
x t1=x t  a1− x t− t k x t  x(t + 1) = x(t) + x(t) * a * (1 ­ x(t) – k * lambda(t))
4.12
n=
t 
1−t
4.13
4.14
n y =n
x =
1−t
n = lambda(t) / (1 ­ lambda(t))" ; "m = (lambda(t) ­ ny) / x(t)
ny = (n * (1 ­ lambda(t)) / (n + 1)
n1
1
x = 1 / (n + m + 1)
nm1
Tabelle 2: Vergleich mathematische Formeln und Code
Seite 16 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
4. Literaturverzeichnis
• Michael Welzl.:Scalable Performance Signalling And Congestion Avoidance. Kluwer Academic Publishers, August 2003, ISBN 1­4020­7570­7
• Alessandro Rubini, Jonathan Corbet: Linux Device Drivers, 2nd Edition. O'Reilly Juni 2001, ISBN 0­596­00008­1
• The Linux Kernel API, GNU
Seite 17 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
5. Anhang
cadpc.cc
#include "cadpc.h"
#include <stdio.h>
int hdr_cadpc::offset_; // static offset of CADPC header
static class CADPCHeaderClass : public PacketHeaderClass
{
public:
CADPCHeaderClass() : PacketHeaderClass("PacketHeader/CADPC",
sizeof(hdr_cadpc)) {
bind_offset(&hdr_cadpc::offset_);
}
} class_cadpchdr;
static class CADPCClass : public TclClass
{
public:
CADPCClass() : TclClass("Agent/CADPC") {}
TclObject* create(int, const char*const*)
{ return (new CADPCAgent()); }
} class_cadpc;
void CADPCIpgTimer::expire(Event *)
{
a_->timeout(CADPC_IPG_TIMEOUT);
}
void CADPCRttTimer::expire(Event *)
{
a_->timeout(CADPC_RTT_TIMEOUT);
}
//---------------------------------------------------------------------// CADPCAgent::CADPCAgent
//
Initialize the CADPC agent.
//
Bind variables which have to be accessed in both Tcl and C++.
//
Initializes time values.
//---------------------------------------------------------------------CADPCAgent::CADPCAgent() : Agent(PT_CADPC_DATA), ipgTimer_(this), rttTimer_(this),
ipg_(2.0), timeout_(2.0), rttFactor_(2.0), smoothness_(1.0)
{
bind("packetSize_", &size_);
bind("timeout_", &timeout_); // Default 2 seconds
Seite 18 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
// multiply the RTT for feedback timeout with this factor
bind("rttFactor_", &rttFactor_); // Default 2.0
// smoothness of the control (factor a in equation)
bind("smoothness_", &smoothness_); // Default 0.5
bind("startup_", &startup_); // Default 1
bind("maxrate_", &maxrate_);
bind("rateMultiplier_", &rateMultiplier_);
firstTime_ = TRUE;
convRate_ = 0;
convTraffic_ = 0;
convUsers_ = 0;
addUsers_ = 1;
oldTraffic_ = 0;
feedback_received_ = 0;
timeoutOccured_ = FALSE;
running_ = 0;
ipg_ = 2.0;
// TRUE = remember: don't update rtt
// will be changed with the first PTP-ACK anyway
}
// Cancel all our timers before we quit
CADPCAgent::~CADPCAgent()
{
stop();
}
//---------------------------------------------------------------------// CADPCAgent::UpdateTimeValues
//
Update the values for srtt_, variance_ and timeout_ based on
//
the "sampleRtt". Use Jacobson/Karl's algorithm.
//
//
"sampleRtt" is the sample round trip time obtained from the
//
current ack packet.
//---------------------------------------------------------------------void CADPCAgent::UpdateTimeValues(double sampleRtt)
{
timeout_ = sampleRtt*rttFactor_;
}
//---------------------------------------------------------------------// CADPCAgent::UpdateRate
//
The core part of CADPC: update ipg; calculate rate according to the
//
CADPC formula: rate(t+1) = rate(t)*(r0+1-r0*rate(t)-traffic)
//
//
our traffic and rates are normalized, r0=1
//
this yields: rate(t+1)=rate(t)*(2-rate(t)-traffic)
//
//
"sampleRtt" is the sample round trip time obtained from the
//
current ack packet.
//----------------------------------------------------------------------
Seite 19 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
void CADPCAgent::updateRate(double traffic, double bottleneckBW,
double sampleRtt, int priority)
{
if(traffic>1) {
traffic=1;
}
/* ipg2rate conversion + normalization */
double currentRate = (size_ / ipg_) / bottleneckBW;
/* act like how many flows? */
currentRate /= rateMultiplier_;
/* "x(t+1) = x(t) + x(t) * a * (1-x(t) - lambda(t))" */
double newRate = currentRate +
currentRate*smoothness_*(1.0-currentRate-traffic);
/* startup mechanism */
if(startup_) {
/* if first time or traffic decreased*/
if(firstTime_
|| ((traffic-currentRate)<=convTraffic_)) {
/* "lambda = lambda(t) - x(t)" */
convTraffic_ = traffic-currentRate;
if(traffic>0.5) {
/* "n = lambda / (1 - x(t) - lambda)" special form of 4.12 */
convUsers_ = convTraffic_ / (1.0-currentRate-convTraffic_);
/* "x = 1 / (n + 1 + m)" see 4.14 */
convRate_ = (1.0)/(convUsers_+1.0+addUsers_);
}
else {
/* special case: total system startup "n = 0", "x = 0,5" */
convUsers_ = 0; convRate_ = 0.5;
}
firstTime_ = FALSE;
}
/* not firsttime, traffic not decreased, other new users (m) */
else {
/* no update if system is overloaded */
if(traffic < 1.0) {
/* addTraffic = additional traffic (without me) */
double addTraffic = traffic - currentRate - convTraffic_;
if(addTraffic > 0) {
/* "ny = lambda",
"ny = (n * (1 - x(t) - lambda(t)) / (n + 1)" see 4.13 */
double supConvTraffic = traffic < 0.5 ? convTraffic_ :
convUsers_*(1.0-currentRate-addTraffic)/(convUsers_+1.0);
/* update if m incrases - this is sure! */
Seite 20 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
if ((traffic-supConvTraffic)/currentRate > addUsers_) {
/* addUsers_ includes me "m = (lambda(t) - ny) / x(t)" */
addUsers_ = (traffic-supConvTraffic)/currentRate;
}
/* "x = 1 / (n + 1 + m)" see 4.14 */
convRate_ = (1.0)/(convUsers_+1.0+addUsers_);
}
}
}
/* rate update */
if((traffic < 1.0) && (traffic > 0.5))
/* "k = (1 - x - x(t)) / x"
"x(t + 1) = x(t) + x(t) * a * (1 - x(t) - k*lambda(t))" see 4.11 */
newRate = currentRate + currentRate*smoothness_*
(1.0-currentRate-(1.0-(convRate_ - currentRate)/(convRate_))*traffic);
else
/* "x(t + 1) = x(t) + x(t) * a * (1 - x(t) - lambda(t))" see 4.11 */
newRate = currentRate + currentRate*smoothness_*(1.0-currentRate-traffic);
/* when to end startup */
if (!firstTime_ && (
(newRate > convRate_) || (currentRate > convRate_)
|| (traffic < 0.5)) )
startup_ = FALSE;
} /* end startup mechanism */
/* de-normalize rate */
newRate = newRate * bottleneckBW;
if(newRate <= 0) {
printf("error: calc. rate <= 0! setting rate to 1 pkt/rtt...\n");
newRate = size_/sampleRtt;
}
/* limit */
if((maxrate_ > 0.0)&&(newRate > maxrate_)) {
newRate = maxrate_;
}
/* act like how many flows? */
newRate *= rateMultiplier_;
/* rate2ipg conversion */
ipg_ = size_ / newRate;
oldTraffic_ = traffic - currentRate;
feedback_received_ = 1;
}
//---------------------------------------------------------------------void CADPCAgent::stop()
Seite 21 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
{
// SHOULD BE CORRECTED: ALWAYS ACTIVATES STARTUP
startup_ = TRUE;
firstTime_ = TRUE;
convRate_ = 0;
convTraffic_ = 0;
convUsers_ = 0;
addUsers_ = 1;
oldTraffic_ = 0;
feedback_received_ = 0;
timeoutOccured_ = FALSE;
running_ = 0;
ipg_ = 2.0;
// remember: don't update rtt
// will be changed with the first PTP-ACK anyway
// Cancel the timer only when there is one
if (ipgTimer_.status() == TIMER_PENDING)
ipgTimer_.cancel();
if (rttTimer_.status() == TIMER_PENDING)
rttTimer_.cancel();
}
//---------------------------------------------------------------------// CADPCAgent::command
//
Called when a Tcl command for the CADPC agent is executed.
//
Two commands are supported
//
$cadpcsource start
//
$cadpcsource stop
//---------------------------------------------------------------------int CADPCAgent::command(int argc, const char*const* argv)
{
if (argc == 2) {
if (strcmp(argv[1], "stop") == 0) {
stop();
return (TCL_OK);
}
}
if (argc == 3) {
if (strcmp(argv[1], "updateSampleRTT") == 0) {
//
double pingRTT = atof(argv[2])/1000.0;
double pingRTT = atof(argv[2]);
UpdateTimeValues(pingRTT);
//
printf("parameter: %f\n", atof(argv[2]));
ipg_ = pingRTT;
feedback_received_ = 1; // no timeout at the beginning
RttTimeout();
// don't cause PTP packet loss at the beginning...
ipgTimer_.resched(pingRTT/2.0);
running_=1;
Seite 22 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
return (TCL_OK);
}
else
if (strcmp(argv[1], "start") == 0) {
ptpAgent_ = (PTPAgent*)TclObject::lookup(argv[2]);
ptpAgent_->ptpinit_ = 1;
feedback_received_ = 1; // no timeout at the beginning
RttTimeout();
return (TCL_OK);
}
}
else
{
if (strcmp(argv[1], "recvptp") == 0) {
// argv[2] = normalized traffic, argv[3]=bottleneckBW, argv[3] = sampled rtt
recvptp(atof(argv[2]), atof(argv[3]), atof(argv[4]), atoi(argv[5]));
//if(!running_) {
// IpgTimeout();
// running_=1;
//}
return (TCL_OK);
}
}
// If the command hasn't been processed by CADPCAgent()::command,
// call the command() function for the base class
return (Agent::command(argc, argv));
}
//---------------------------------------------------------------------// CADPCAgent::recv
//
Called when a packet is received.
//---------------------------------------------------------------------void CADPCAgent::recv(Packet* pkt, Handler*)
{
hdr_cadpc* hdr = hdr_cadpc::access(pkt); // Access CADPC header
// the receiver - maybe we want to do something with the packet?
// shouldn't really be necessary in CADPC
Packet::free(pkt);
// Discard the packet
}
//---------------------------------------------------------------------// CADPCAgent::recvptp
//
Called when a ptp packet is received:
//
update rate & srtt, resched rtt-timeout
//--------------------------------------------------------------------void CADPCAgent::recvptp(double normalizedTraffic, double bottleneckBW, double sampleRTT,
int priority)
{
// only update rtt if there was no timeout
Seite 23 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
if(!timeoutOccured_)
UpdateTimeValues(sampleRTT);
timeoutOccured_ = FALSE;
// printf("sample rtt: %f
", sampleRTT);
// printf("new timeout: %f\n", timeout_);
updateRate(normalizedTraffic, bottleneckBW, sampleRTT, priority);
if(priority==0)
stop();
// RttTimeout();
}
//---------------------------------------------------------------------// CADPCAgent::timeout
//
Called when a timer fires.
//
//
"type" is the type of Timeout event
//---------------------------------------------------------------------void CADPCAgent::timeout(int type)
{
if (type == CADPC_IPG_TIMEOUT)
IpgTimeout();
else if (type == CADPC_RTT_TIMEOUT)
RttTimeout();
else
assert(FALSE);
}
//---------------------------------------------------------------------// CADPCAgent::IpgTimeout
//
Called when the ipgTimer_ fires.
//---------------------------------------------------------------------void CADPCAgent::IpgTimeout()
{
Packet *pkt;
pkt = allocpkt();
// nothing to be done about the header
send(pkt, 0);
ipgTimer_.resched(ipg_);
}
//---------------------------------------------------------------------// CADPCAgent::RttTimeout
//
Called when the rttTimer_ fires.
//---------------------------------------------------------------------void CADPCAgent::RttTimeout()
{
if(!feedback_received_) {
//printf("PTP timeout!\n");
timeoutOccured_ = TRUE; // ignore the next sampleRtt
//ipg_ *= 2.0;
//timeout_ *= 2.0;
Seite 24 von 10
Aktualisierung des PTP­Patch für Kernel 2.6.15
Martin Rabanser
}
if(running_)
feedback_received_ = 0;
ptpAgent_->sendit();
rttTimer_.resched(timeout_);
}
Seite 25 von 10

Documents pareils