PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Konzeptfrage: Netzwerk Treiber Programmierung



7.e.Q
20-06-2005, 10:44
Hallo Leute,

eine Konzeptfrage: ich programmiere einen Netzwerk Treiber, der auf einem Dual Port RAM basiert. Also ich habe zwei Systeme, die auf den Speicher des jeweils anderen Systems über einen VME Bus zugreifen können. Das Netzwerk Interface soll jetzt folgendes tun: es soll das Paket, das es vom Kernel bekommt in einen Bereich des Speichers des Zielsystems schreiben und dem Zielsystem dann mitteilen, daß dort ein Paket liegt. Das Zielsystem liest dieses Paket nun aus und gibt es hoch an den Kernel.

Im Augenblick mache ich das so: es gibt vier Bereiche im Dual Port RAM beider Systeme, genannt Frames. Jeder Frame ist folgendermaßen aufgebaut:



| ulong DP_SIGNATURE | ulong DP_FREE | ulong DP_LOCKED | ulong DP_AVAILABLE | char* DP_DATA |


- DP_SIGNATURE ist nur ein Identifikationsblock, damit die Gegenseite weiß, daß der Frame in Ordnung ist.
- DP_FREE ist ein Indikator dafür, ob in dem Frame ein Datenpaket vorhanden ist oder nicht (und ob dies bereits gelesen wurde oder nicht)
- DP_LOCKED ist gesetzt, solange die Quellseite am Daten schreiben ist, wird wieder gelöscht, sobald das Paket komplett im Speicher ist
- DP_AVAILABLE ist die Größe des Datenpaketes
- DP_DATA enthält nun das eigentliche Paket

Der Ablauf beim Schreiben eines Paketes ist nun folgender (der Treiber hier DPN genannt):
- DPN ermittelt in Schleife ersten Frame im Speicher des Zielsystems, in dem DP_FREE auf "frei" gesetzt ist
- DPN setzt DP_LOCKED im Frame auf "gesperrt"
- DPN schreibt Paket in den Puffer des Frames
- DPN setzt DP_FREE auf "belegt"
- DPN setzt DP_AVAILABLE auf die Größe des Paketes
- DPN setzt DP_LOCKED auf "offen"
- DPN löst Interrupt aus (woraufhin die Zielseite das Lesen beginnt...)

Der Ablauf beim Lesen auf der anderen Seite ist folgender:
- DPN sucht nach Frame mit DP_FREE auf "belegt"
- DPN prüft, ob DP_LOCKED auf "frei" (also das Paket vollständig) ist
- DPN liest DP_AVAILABLE ein
- DPN alloziiert entsprechend skb-Speicher
- DPN kopiert Paket aus Datenpuffer in den skb-Speicher
- DPN setzt DP_FREE auf "frei"
- DPN reicht skb-Speicher an den Kernel hoch


So... jetzt laufe ich damit aber in ein Problem. Nämlich ist Tatsache, daß die Zielseite die Daten nicht so schnell auslesen kann, wie die Quellseite sie schickt (fragt mich nicht, wieso). Jetzt kommt es immer wieder vor, daß bei großen Paketen kein Frame mehr "frei" ist. Daraufhin verwirft der DPN das Paket. Dadurch bricht natürlich jede TCP Verbindung ein... was kann ich jetzt an dem Konzept ändern, daß besagte Probleme nicht mehr auftreten? Ich habe schon probiert:

- Anzahl Frames zu erhöhen
- Framegröße zu erhöhen
- Schreiben zu verzögern

Keiner der Versuche war von Erfolg gekrönt.

Eventuell hat von euch einer 'ne Idee, 'nen Link auf ein Beispielkonzeptm 'nen Tipp etc., der/die/das mir helfen könnte.

Danke

Gruß,
Hendrik

PS: Danke für's Verschieben!

Joghurt
22-06-2005, 01:46
Kannst du das Problem nicht lösen, indem du ein ICMP Source Quench sendest?

Leider blockieren, IIRC, manche Personal Firewalls, diese Messages.

7.e.Q
27-06-2005, 08:08
Die Systeme sind völlig low-level. Das heißt, es gibt weder Firewalls noch irgendwas anderes, das den Netzwerktransfer über den DPN behindern würde, außer dem DPN selbst und der darunter liegenden Hardware.

Es geht auch nicht primär um den Flood-Ping, sondern allgemein um Datenübertragung auf IP Schicht. Sendet der Absender die Daten schneller, als der Empfänger sie auslesen kann, ist es klar, daß die Puffer Frames innerhalb kürzester Zeit voll laufen. Dies gilt es zu unterbinden. Das Vollaufen der Frames darf nur seltenst bis gar nicht passieren, da alle Pakete, die keinen freien Frame mehr bekommen, gedropped werden. Ich wüsste sonst auch nicht, wohin damit, anders als sie zu droppen.

Einzig das Ausbremsen des Absenders wäre hier eine praktikable Lösung. Aber wie macht man sowas am ehesten? Ist es da sinnvoll, einen Wert zwischenzuspeichern, der sich bei Verwerfen eines Paketes immer erhöht (zwischenzeitlich auch wieder verringert), und von dem abhängig eine Verzögerung per udelay() vor dem Schreiben des nächsten Paketes erfolgt? Ist das ein sinnvolles Vorgehen? Oder wie kann man das anders machen? Andere Ideen? :confused:

Joghurt
27-06-2005, 14:05
Einzig das Ausbremsen des Absenders wäre hier eine praktikable Lösung.Und dafür ist der Source Quench gedacht.

7.e.Q
28-06-2005, 10:21
Achso... Hmm... Also das erste Problem, das ich gefunden habe, war, daß das Auslesen nicht unmittelbar auf den Interrupt geschah, sondern innerhalb einer Schleife, die per wait_event gestoppt wurde. Die Interrupt Routine des Treibers hat diese Schleife nur aufgeweckt und in dieser Schleife wurde dann das Auslesen angestoßen. Diesen Anstoß zum Auslesen habe ich erstmal in die Interrupt Routine verlegt, was den Treiber schon um einiges schneller gemacht hat. Trotzdem gehen bei großen Datenpaketen immer noch Pakete verloren, weil die Frames voll laufen...

Source Quench... ich schau mich mal um danach. Kannst du (oder jemand anderes) dazu eventuell mal ein paar Zeilen schreiben? Wäre super.

EDIT: Also da ja der Absender die Puffer des Empfängers beschreibt und überprüft, wäre es wohl auch sinnvoll, den Absender das Source Quench Paket generieren zu lassen, wenn die Puffer des Empfängers voll sind. Der Absender reicht dieses Paket dann wohl einfach an den Kernel hoch.

Oder? :confused:

Gruß,
Hendrik

7.e.Q
28-06-2005, 14:20
Das ja ma starker Tobak. Gibt es schon eine Implementierung für ICMP Pakete für Linux 2.6 Treiber?

Mein Netzwerk Treiber (DPN, siehe oben) erhält vom Kernel ein Paket. Dieses Paket kann der Treiber nicht mehr an den Empfänger verschicken, da der Paketpuffer (Frames, siehe oben) des Empfängers voll ist. Jetzt soll der DPN des Absenders an seinen Kernel mit einem ICMP Source Quench antworten. Doch es ist ein verdammt langer Weg vom zu versendenden Paket bis hin zum ICMP Source Quench.

Gibt es schon eine Implementierung, Funktionen, irgendwas, das diesen Weg für mich geht? Also ich schmeiße auf der einen Seite das Paket vom Kernel rein und auf der anderen Seite kommt das ICMP Source Quench Paket komplett fertig geschnürt wieder raus?


Mal, wie Otto das erzählen würde:

Kernel A: "Kernel A an DPN A! Hier hast du ein Paket für DPN B!"
DPN A: "<denkt sich> Jo, schreib ich ma weg."
DPN A: "<stellt fest> Hey, der Puffer des Empfängers ist voll!"
DPN A: "DPN A an Kernel A! Hier haste ein ICMP Source Quench von mir!"
Kernel A: "<denkt sich> Jo, denn drehen wir mal die Ü-Rate bissl zurück."
Kernel A: "Kernel A an DPN A! So... hier haste das Paket nochmal. Mach ma nich so flott! Der Empfänger is nich mehr der jüngste."

So stell ich mir das gerade vor. Entspricht das so schematisch den Tatsachen?

Also ganz kurz gesagt, ich brauch eine (bzw. Hilfe bei der) Implementierung des ICMP Protokolls, speziell Source Quench (danke Joghurt!), für meinen Treiber (Linux 2.6). Wo finde ich sowas?

Danke!

Gruß,
Hendrik

7.e.Q
29-06-2005, 07:51
Kannst du das Problem nicht lösen, indem du ein ICMP Source Quench sendest?


Gut... das will ich jetzt machen. Wie geht das? :confused: