Ich möchte unserer Internetleitung eine Art Verkehrsmanagement hinzufügen. Nachdem ich viel Dokumentation gelesen habe, denke ich, dass HFSC für mich zu kompliziert ist (ich verstehe das ganze Kurvenzeug nicht und habe Angst, dass ich es nie richtig hinbekomme), CBQ ist nicht zu empfehlen und im Grunde ist HTB für die meisten Leute die beste Lösung.
Unser internes Netzwerk hat drei „Segmente“ und ich möchte die Bandbreite mehr oder weniger gleichmäßig zwischen diesen aufteilen (zumindest am Anfang). Außerdem muss ich den Verkehr nach mindestens drei Verkehrsarten priorisieren (Echtzeitverkehr, Standardverkehr und Massenverkehr). Die Bandbreitenaufteilung ist nicht so wichtig wie die Tatsache, dass Echtzeitverkehr nach Möglichkeit immer als Premiumverkehr behandelt werden sollte, aber natürlich darf auch keine andere Verkehrsklasse ausgehungert werden.
Die Frage ist, was sinnvoller ist und auch einen besseren Echtzeit-Durchsatz garantiert:
Erstellen einer Klasse pro Segment, die jeweils die gleiche Rate hat (die Priorität spielt laut HTB-Entwickler für Klassen keine Rolle, die keine Blätter sind) und jede dieser Klassen hat drei Unterklassen (Blätter) für die drei Prioritätsstufen (mit unterschiedlichen Prioritäten und unterschiedlichen Raten).
Es gibt eine Klasse pro Prioritätsstufe an der Spitze, jede mit einer anderen Rate (auch hier spielt die Priorität keine Rolle) und jede mit drei Unterklassen, eine pro Segment, wobei alle drei in der Echtzeitklasse die höchste Priorität haben, die niedrigste Priorität in der Bulk-Klasse und so weiter.
Ich versuche, dies anhand des folgenden ASCII-Art-Bildes deutlicher zu machen:
Case 1:
root --+--> Segment A
| +--> High Prio
| +--> Normal Prio
| +--> Low Prio
|
+--> Segment B
| +--> High Prio
| +--> Normal Prio
| +--> Low Prio
|
+--> Segment C
+--> High Prio
+--> Normal Prio
+--> Low Prio
Case 2:
root --+--> High Prio
| +--> Segment A
| +--> Segment B
| +--> Segment C
|
+--> Normal Prio
| +--> Segment A
| +--> Segment B
| +--> Segment C
|
+--> Low Prio
+--> Segment A
+--> Segment B
+--> Segment C
Fall 1 scheint die Vorgehensweise der meisten Leute zu sein, aber wenn ich die HTB-Implementierungsdetails nicht falsch lese, bietet Fall 2 möglicherweise eine bessere Priorisierung.
Im HTB-Handbuch steht, dass eine Klasse, wenn sie ihre Rate erreicht hat, von ihrer übergeordneten Klasse ausleihen kann und dass Klassen mit höherer Priorität beim Ausleihen immer zuerst Bandbreite angeboten bekommen. Es heißt jedoch auch, dass Klassen mit verfügbarer Bandbreite auf einer niedrigeren Baumebene immer denen auf einer höheren Baumebene vorgezogen werden.unabhängig von der Priorität.
Nehmen wir die folgende Situation an: Segment C sendet keinen Datenverkehr. Segment A sendet nur Echtzeitdatenverkehr, so schnell es kann (genug, um die Verbindung allein zu sättigen) und Segment B sendet nur Massendatenverkehr, so schnell es kann (wiederum genug, um die gesamte Verbindung allein zu sättigen). Was wird passieren?
Fall 1:
Segment A->High Prio und Segment B->Low Prio haben beide Pakete zu senden. Da A->High Prio die höhere Priorität hat, wird es immer zuerst eingeplant, bis es seine Rate erreicht. Jetzt versucht es, von Segment A zu leihen, aber da Segment A auf einem höheren Level ist und Segment B->Low Prio seine Rate noch nicht erreicht hat, wird diese Klasse jetzt zuerst bedient, bis sie auch die Rate erreicht und von Segment B leihen möchte. Sobald beide ihre Raten erreicht haben, sind beide wieder auf dem gleichen Level und jetzt wird Segment A->High Prio wieder gewinnen, bis es die Rate von Segment A erreicht. Jetzt versucht es, von Root zu leihen (das viel Datenverkehr übrig hat, da Segment C keinen seiner garantierten Datenverkehr nutzt), aber wieder muss es warten, bis Segment B->Low Prio auch das Root-Level erreicht. Sobald das passiert, wird die Priorität wieder berücksichtigt und dieses Mal erhält Segment A->High Prio die gesamte Bandbreite, die von Segment C übrig bleibt.
Fall 2:
High Prio->Segment A und Low Prio->Segment B haben beide Pakete zu senden, wieder wird High Prio->Segment A gewinnen, da es die höhere Priorität hat. Sobald es seine Rate erreicht hat, versucht es, von High Prio zu leihen, das Bandbreite übrig hat, aber da es auf einem höheren Level ist, muss es warten, bis Low Prio->Segment B wieder seine Rate erreicht. Sobald beide ihre Rate erreicht haben und beide leihen müssen, wird High Prio->Segment A wieder gewinnen, bis es die Rate der High Prio-Klasse erreicht. Sobald das passiert, versucht es, von Root zu leihen, das wieder reichlich Bandbreite übrig hat (die gesamte Bandbreite von Normal Prio wird im Moment nicht genutzt), aber es muss wieder warten, bis Low Prio->Segment B die Ratenbegrenzung der Low Prio-Klasse erreicht und auch versucht, von Root zu leihen. Schließlich versuchen beide Klassen, von Root zu leihen, die Priorität wird berücksichtigt und High Prio->Segment A erhält die gesamte Bandbreite, die Root übrig hat.
Beide Fälle scheinen nicht optimal, da der Echtzeitverkehr in beiden Fällen manchmal auf den Massenverkehr warten muss, obwohl noch genügend Bandbreite übrig ist, die er ausleihen könnte. Im zweiten Fall scheint der Echtzeitverkehr jedoch weniger warten zu müssen als im ersten, da er nur warten muss, bis die Massenverkehrsrate erreicht ist, die höchstwahrscheinlich niedriger ist als die Rate eines ganzen Segments (und im ersten Fall ist dies die Rate, auf die er warten muss). Oder liege ich da völlig falsch?
Ich habe über noch einfachere Setups nachgedacht, bei denen eine Prioritäts-Qdisc verwendet wird. Prioritätswarteschlangen haben jedoch das große Problem, dass sie zu einer Aushungerung führen, wenn sie nicht irgendwie begrenzt werden. Aushungern ist nicht akzeptabel. Natürlich kann man in jede Prioritätsklasse einen TBF (Token Bucket Filter) einfügen, um die Rate zu begrenzen und so Aushungern zu vermeiden, aber wenn man das macht, kann eine einzelne Prioritätsklasse die Verbindung nicht mehr alleine sättigen, selbst wenn alle anderen Prioritätsklassen leer sind, das verhindert der TBF. Und das ist auch nicht optimal, denn warum sollte eine Klasse nicht 100 % der Bandbreite der Leitung erhalten, wenn keine andere Klasse im Moment etwas davon benötigt?
Irgendwelche Kommentare oder Ideen zu diesem Setup? Es scheint so schwierig, es mit Standard-TC-Qdiscs zu machen. Als Programmierer wäre es eine so einfache Aufgabe, wenn ich einfach meinen eigenen Scheduler schreiben könnte (was ich nicht darf).
Antwort1
Wenn ich htb richtig verstehe, dann ist der Kurs "garantiert". Das heißt, SiehabenVorstellungen über die Rate des "Echtzeit"-Verkehrs. Erst wenn diese Rate überschritten wird, wird geliehen. Wenn mehrere Klassen leihen wollen, sollte die Prio greifen. Die garantierten Raten sollten sich bis zum physikalischen Limit addieren. Sonst ist das zu umständlich.
Meiner Meinung nach wird Fall A nie wirklich funktionieren, da Sie Prioritäten oder Ratenbegrenzungen auf Stammebene benötigen. Die Prioritäten/Raten in den verschiedenen Segmenten wissen nichts voneinander und werden gleich behandelt.
Was Sie wahrscheinlich wollen, ist: Setzen Sie die „Rate“ für niedrige und normale Priorität auf 0 oder nahe daran und fügen Sie eine „Obergrenze“ für die restliche Bandbreite hinzu. Für hohe Priorität garantieren Sie eine Rate von 100 % der physischen Rate.