Forum: Projekte & Code AVR Netzwerk Stack (IP, UDP, TCP,...)


von Jon (Gast)


Lesenswert?

Hallo,

aus den Bedürfnissen des Ulrich Radig Webserver Threads
(http://www.mikrocontroller.net/forum/read-4-87092.html#157645)
entstanden, gibt es nun diesen Thread zur Diskussion von
tiefgründigerem Netzwerkwissen.

Als Projekt zu einer Vorlesung habe ich mit 3 Kommilitonen einen
relativ vollständigen TCP/UDP/IP Stack implementiert, inklusive GET
Parser für HTTP Requests und DHCP Client. Angefangen hat das ganze bei
Ulrichs Webserver, inzwischen ist aber nur noch die unterste Schicht
davon übrig ;-)

Das Wiki zum Projekt ist grad im Umzug begriffen, aber in den nächsten
Tagen werde ich das ganze inklusive Source hier posten, so dass alle
etwas davon haben. Bis dahin können wir ja gern hier weitere Fragen zu
TCP/IP und Co. klären :-)

Gruß, Jon

:
von hebel23 (Gast)


Lesenswert?

Hi Jon,
das mit dem DHCP-Client würde mich auch interessieren. Sicher ist es
diskussionswürdig bei einem kleinen AVR-System mit dynamischer
IP-Vergabe zu arbeiten aber allein das Prinzip zu verstehen ist ja
schon interessant.
Wie schon im erwähnten Thread angesprochen ist mir eben aufgefallen,
dass in den verschiedenen TCP/IP-Implementationen, die so im Netz
rumgeistern, teilweise gravierende Abweichungen auftreten.
Vor allem beim Socket-Status.
Laut RFC793 (dem TCP/IP-Spezifikation
http://www.faqs.org/rfcs/rfc793.html) durchläuft eine TCP/IP-Verbindung
die Stadien:

CLOSED
-----------------------------------------------------------------
LISTEN, SYN-SENT, SYN-RECEIVED, ESTABLISHED,
-----------------------------------------------------------------
{Datenaustausch}
-----------------------------------------------------------------
FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT,
-----------------------------------------------------------------
CLOSED

So habe ich das allerdings nirgendwo implementiert gesehen. Die Frage
ist eben nun, ob man sich die Mühe machen sollte das zu tun oder nicht
.

Gruß Andreas

von Andreas (Gast)


Lesenswert?

Für kleine Controller würde natürlich auch RARP reichen, oder halt
BOOTP. DHCP ist in der Tat eine Nummer zu gross.

Gibt es eigentlich schon irgendwo eine
Netzwerkdateisystemimplementierung, z.B. NFS?
Als Client und/oder als Server?

von Jon (Gast)


Lesenswert?

@Hebel
Wir haben die Connection Status genau so implementiert. Lediglich die
Statusnummern könnten abweichen, aber wie schon erläutert macht das ja
nicht. Achja: Den Status Closed gibt es bei uns auch nicht, weil die
Connections sofort wieder in den Listen Status wechselt. Ach ja, ein
Socket kann durchaus an mehreren Verbindungen mit unterschiedlichen
Status teilnehmen, die Formulierung "Socket Status" ist also
eigentlich etwas unglücklich.

@Andreas
Naja.. DHCP nutzt ja Bootp als Protokoll. Natürlich implementieren wir
nicht alle Optionen von DHCP, aber das ist ja auch nicht nötig. Wir
haben das so auf einem ATmega32 am Laufen.

An NFS habe ich auch schon gedacht, würde mich brennend interessieren
wie aufwendig das ist.


ps. Zweimal Andreas? ;-)

von Andreas D (Gast)


Angehängte Dateien:

Lesenswert?

Und noch ein Andreas ;-)

Unser CVS-Server ist leider nicht oeffentlich deswegen hier ein
Source-Tarball vom CVS gezogen. Eine Wiki-site ist schon da aber
momentan noch offline, kurze Erlaeuterungen deswegen hier:

- Die Software ist noch ziemlich Alpha und im Moment wenig mehr als ein
Proof-of-Concept
- Das ganze wurde geschrieben fuer einen ATmega32 und eine RTL8019AS
ISA-Karte. Die oberen Schichten (arp/ip und aufwaerts) sind
einigermassen portabel, die unteren nicht. Auch im Makefile sind
Anpassungen noetig fuer das jeweilige Setup.
- Ethernet: Nicht jedes Ethernet Paket wird korrekt hochgereicht. Wir
wissen nicht genau, woran es liegt.
- ARP: Die Cache ist noch nicht intensiv getestet, da wir einfach zu
wenig Platz hatten, um sie groesser zu machen.
- IP: Der ARP-Check von IP_SEND ist nicht ideal, funkioniert aber.
Leider streikt hier die globale Clock, deswegen sind Retransmitts nicht
timetriggered.
- TCP: arbeitet nicht vollständig korrekt mit manchen Browsern.
Retransmitts wie IP.

Es gibt noch mehr, aber das sind die wichtigsten. Also wer mutig ist,
der ziehe seine Gummistiefel an und ab in den Sandkasten :-)

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Was sind die Vorteile gegenüber uIP oder lwIP?

von Jon (Gast)


Lesenswert?

@Andreas#4 ;-)

Keine Ahnung, wir haben beide nicht angeschaut.

Unser Ziel ist die vollständige Implementation von IP, TCP, UDP den
entsprechenden RFCs entsprechend. Das ist vor allem ein Studienprojekt,
um es selbst zu verstehen. Wenn man so einen Stack mal selbst
implementiert hat, kennt man viele der Probleme und kann die Erfahrung
für andere Entwicklungen nutzen.

Sollten die von Dir genannten Stacks das bereits voll unterstützen, so
ist unsere Arbeit höchstens eine weitere in diese Richtung.

von Uli (Gast)


Lesenswert?

Hallo,

Da muß ich Jon schon recht geben man muß einen TCP/IP-Stack schon
selbst programmieren um TCP/IP zu verstehen. Es gibt einige Projekte in
diese Richtung.

Mfg Ulrich

von Andreas Auer (Gast)


Lesenswert?

Auch ich möchte dem beipflichten.
Auch ich bin einer derjenigen, die TCP/IP auf nem Mega128 implemtiere!
Und ebenso läuft bei mir das Ganze unter dem Kontext
"Erfahrungssammlung" und "Wissen wollen wie das funktioniert".

mfg
Andreas

von Andreas Auer (Gast)


Lesenswert?

zu meinem vorigen Post noch eine kurze Ergänzung:
Vorallem würde mich interessieren, wie ihr das "Demultiplexing" der
Ethernet Frames handhabt.
Bei mir läuft das momentan so, dass eine Art "Scheduler" die Frames
den entsprechenden Funktionen übergibt. Beim Vorbereiten der Frames zum
Senden soll ja jede Schicht ihren Header hinzufügen. Nur ist das
teilweise nicht so einfach, da ja z.B. IP sehr viele Informationen
einfügen muss, die ich nicht unbedingt übergeben will. Und wenn ich
zuvor eine Struktur füllen muss, dann kann ich es gleich in den Header
auch schreiben... wäre da mal sehr an einem Erfahrungsaustausch
interessiert!

Die andere Frage, die ich noch habe, betrifft zwar nicht direkt TCP/IP,
könnte aber als in diesem Zusammenhang ganz interessant sein!
Und zwar hätte ich eigentlich vor, ein kleines Multithreading zu
realisieren. Und zwar so, dass z.B. HTTP, FTP und ähnliche Server als
eigene Threads laufen.
Jetzt ist eben die Frage, ob das schonmal jemand versucht hat (also
z.B. "_einfaches_" kooperatives Multithreading) zu realisieren. Von
der Performance her sollte es ja doch ein bisschen was bringen, oder??
Begründung: oftmals kommt man ja in die Lage, dass man im Laufe eines
Programms (Servers) auf etwas warten muss (Benutzereingaben u.ä.)...
und währenddessen kann man ja die Rechenleistung für einen anderen
Thread nutzen!

mfg
Andreas

von DerMax (Gast)


Lesenswert?

Naja gehen musses, ethernut macht es ja genauso (glaub ich :)

http://www.ethernut.de/de/software.html

von Andreas Auer (Gast)


Lesenswert?

Nochmal kurz ein kleiner Beitrag (der etwas Offtopic ist sorry):
Es wäre ja ganz nützlich in der Library (bzw. als Erweiterungslibrary)
des avr-gcc einfache Funktionen für einfaches Multithreading
bereitstellen zu können!
Vielleicht könnte man ja ein Gemeinschaftsprojekt auf die Beine stellen
und sowas entwickeln.

Meine Vorstellung ging da in die Richtung:
void createThread(void *function,...);

mfg
Andreas

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Ein kooperatives Multitasking lässt sich ziemlich einfach mit
setjmp/longjmp realisieren. Ich habe sowas mal für ARM geschrieben, mal
schaun ob ich den Sourcecode noch finde.

von Andreas S. (andreas) (Admin) Benutzerseite


Angehängte Dateien:

Lesenswert?

Ist im Anhang. Nur wenig getestet, hat aber soweit ganz gut funktioniert
wenn ich mich recht erinnere. Näheres zu dem Thema sollte man in Google
finden.

von Jon (Gast)


Lesenswert?

@Andreas Aur

Zum Demultiplexing: Schau einfach mal in die Source, die AndreasD
gepostet hat :-) Prinzipiell haben wir einen großen Puffer in dem das
Paket landet. Jede Schicht ist dafür zuständig ihren Teil zu
interpretieren. Die Header werden meistens angesprochen, indem ein
StructPointer auf die entsprechede Stelle im Paketpuffer zeigt. So
verschwendet man lediglich den Platz für den Pointer (2Byte), hat aber
bedeutend mehr Komfort.

von Andreas D (Gast)


Lesenswert?

@Andreas Aur

Grundsaetzlich, die Source erklaerts am besten.
Also, einen Scheduler in der Art haben wir nicht. Ein Paket loest einen
Interrupt aus, daraufhin wird der Ethernet-Header ausgelesen, geparsed
und entsprechend an arp oder ip weitergeleitet, die gucken ob ihr
Puffer gerade blockiert ist, wenn nicht wird weiter ausgelesen und in
den eigenen Puffer geschrieben. So geht das dann die Schichten hoch.
Der Puffer ist ein globales vordefiniertes Byte-Array (siehe mem.h).
Jede Schicht passt aber selber nur auf ihren Bereich darin auf.
Uebergeben werden beim senden dann Pointer auf die zu sendenden Bytes.
Die Header und Payload komplett zu uebergeben ueberfuellt dir den Stack
und ich finde es mit Pointern auch wesentlich eleganter.

Zum Multithreading:
Sehr interessant. Ich denke aber auf unserem atmega32 ohne extra ram
ist es nicht zu realisieren. Das stapelt dir ja auf den Stack wie nix
gutes ;-)

von Henning (Gast)


Lesenswert?

[X] per Email über Antworten auf diesen Beitrag informieren

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.