Forum: Mikrocontroller und Digitale Elektronik Der Ethernet Thread


von Nik Bamert (Gast)


Lesenswert?

Hi!

Ich dachte mir, da ich sicherlich nicht ganz der einzige da draussen
bin, der gerade an einer udp/tcp etc unterstützung schreibt, starte ich
diesen Thread. Er soll dazu dienen allgemein Fragen zu dem Thema zu
sammeln, um denen, die sich später um die Suche bemühen, die Arbeit zu
erleichtern. - Ethernet auf dem uC scheint ja immer mehr im kommen zu
sein, mca25 webcam, uli's webserver etc :-)

Vielleicht gibts sonst ja auch niemanden der eine Frage hat, was ich
aber bezweifle...
Also starte ich mal:

Bis anhin habe ich ARP und udp empfang erfolgreich implementiert,
klappt wunderbar, nur; bei den Replies habe ich Probleme, um genau zu
sein mit den CRC16 Checksummen beispielsweise für ICMP.(Meine Ping
Antworten kommen zwar an, allerdings sind sie ungültig, wegen einer
falschen Checksum.) Irgendwie finde ich es sinnlos ein buch über die
Materie zu kaufen, da ich mir das restliche Wissen mit einigen
Ausnahmen eigentlich gut über Ethereal aneignen kann. Die Frage
bezüglich CRC ist nun eigentlich eher - was für einen Initial wert
brauche ich jeweils..(?) und für welchen Bereich des Packets muss man
z.B. gerade bei ICMP die CRC anwenden, nur die Daten oder für den
ganzen icmp-'Abschnitt'...Fragen über Fragen ich weiss, aber am Ende
möchte ich von der Sache eigentlich eine Ahnung haben und nicht nur
Codes von anderen Leuten kopieren, dabei lernt man schliesslich nicht
so viel...

Mfg, Nik

von Ssss S. (sssssss)


Lesenswert?

Hi!

Zum Thema IP/TCP/UDP gibts bei wikipedia einiges. Sonst google & co.

Zum Thema ICMP checksum mal ein auszug aus meinem avrETH1 projekt:
1
    //"calculate" checksum:
2
    //use quick & dirty hack, we change only the icmp type
3
    //so we cant calculate the new checksum like this:
4
    if (buffer[ICMP_POS_CHECKSUM+0] > 0xFF-0x08)
5
      buffer[ICMP_POS_CHECKSUM+1] = buffer[ICMP_POS_CHECKSUM+1] + 1;
6
7
    buffer[ICMP_POS_CHECKSUM+0] = buffer[ICMP_POS_CHECKSUM+0] + 0x08;

Ich nehme dazu einfach das Alte Paket und änder nur den Typ von
ICMP_TYPE_ECHO_REQUEST nach ICMP_TYPE_ECHO_REPLY.
Und das verändert die checksum nur minimal (siehe oben) 8)
Ist schön schnell und braucht wenig program space 8)

Bei udp/tcp mache ich es aber anders, da baue ich alle Pakete komplett
selber zusammen
(ohne die alten zu recyclen)

Bye, Simon

von Nik Bamert (Gast)


Lesenswert?

Ohe danke :-) Ich habe eben grundsätzlich noch Problem mit dem
Verständniss von CRC, was sich ändern wenn ich dieses und jenes Byte
ändere(wie z.B. das Type byte..)

Ich versuche das gerne mal einzubaun, Udp replies brauche ich im Moment
sowiso noch nicht.. :-P

Nik


P.S. müsste es in deinem Kommentar nicht can heissen? :-X

von Daniel N. (bip)


Lesenswert?

Hi Nik, schaumal in die RFC 792:
http://www.faqs.org/rfcs/rfc792.html
Dort ist das ganze Protokoll definiert.
Unter Checksum findet man folgendes:

"The checksum is the 16-bit ones's complement of the one's
complement sum of the ICMP message starting with the ICMP Type.
For computing the checksum , the checksum field should be zero."

Vielleicht hiflt dir das ja weiter. Ich verstehs leider nicht so
wirklich :(
Kann das hier vielleicht jemand anhand eines Beispiels erläutern? Wäre
nett :)

Gruß,
Daniel

von Nik Bamert (Gast)


Lesenswert?

Es läuft!! Danke Simon ;-) laut etheral 1.3ms ping über einen Switch
:-)))


@Daniel Danke für den Link, ich werd mich dort dann auch mal nach TCP
umschauen, scheint ja ziemlich viel zu geben dort :P
Den Satz über die Checksum checke ich auch nicht wirklich irgendwie
braucht man alle 16 bit des Headers um die Start Crc zu berechnen.
Allerdings gibts im icmp header ja nur 2 Were die 16bit lang sind..(?)

von André K. (freakazoid)


Lesenswert?

> Den Satz über die Checksum checke ich auch nicht wirklich irgendwie
> braucht man alle 16 bit des Headers um die Start Crc zu berechnen.
> Allerdings gibts im icmp header ja nur 2 Were die 16bit lang
sind..(?)
Vergiß die Organisation der Datenfelder. Nimm einfach 16Bit-Blöcke,
addier die und bilde das Einerkomplement. Sollte die Bytezahl ungerade
sein, nimm das letzte Byte als HIGH und 0x00 als LOW vom letzten Wort
(16-Bit-Wert).

Grüße,
André

P.S.:
Das ist CRC16? Glaub ich nicht. Da is weder XOR, noch sonstwas drin.
Nach meiner Kenne nimmt man aber einfache Addition um die Neuberechnung
 der Checksumme in den Nodes (Switch, Router, ...) einfach zu halten.
Neuberechnung ist nötig, da TTL dekrementiert wird.

von André K. (freakazoid)


Lesenswert?

BTW: Wenn ich permanent Pakete (z.B. Ping-Replys) vom ENC28J60 sende,
kommen die zwar am Switch an (LED blinkt), aber ein Rechner weiter
fällt  ca. jedes 5.-8. Paket weg.
Das Abort-Flag im ENC ist NICHT gesetzt,
TX-Logik wird gemäß Errata resettet,
Fullduplex/Halfduplex macht keinen Unterschied.

Kann das jemand nachvollziehen, oder ist meine Schirmung nur Mist?

Grüße, Freakazoid

von Ssss S. (sssssss)


Lesenswert?

crc:
nee das is kein crc, wird einfach nur aufaddiert und dann nochmal
invertiert glaub ich.

Hmm sowas hatte ich nie. Auch aufm Steckbrett nicht. Selbst nen
floodping geht ohne Probleme ;)

Oder was meinst du mit permanent senden ? Nur raushauen ohne ein
eingehendes Paket ? Das hab ich noch nie getestet.

Alle Cs dran ? (der dicke elko + alle 100nF ?)

Bye, Simon

von André K. (freakazoid)


Lesenswert?

@Simon:

>Alle Cs dran ? (der dicke elko + alle 100nF ?)
Ja. Ich bin ja lernfähig ;-)

Ich hab als Test mal nur Replys zurückgesendet. Ohne Requests ;-)
Haben zwar keinen Sinn, tauchen aber in TCPdump/Packetyzer auf.

ping -f -c 1000 192.168.0.234
PING 192.168.0.234 (192.168.0.234) 56(84) bytes of data.
........................................................................ 
.............................
--- 192.168.0.234 ping statistics ---
1000 packets transmitted, 899 received, 10% packet loss, time 3474ms
rtt min/avg/max/mdev = 1.464/1.545/5.265/0.145 ms, ipg/ewma 3.477/1.550
ms

Komisch ist aber, daß die Flags im ENc alle auf 'OK' stehen.

Ws hast Du aus dem Errata umgesetzt?

Grüße, Freakazoid

von Nik Bamert (Gast)


Lesenswert?

okay ja ich bin einfach mal davon ausgegangen dass es crc ist...werds
dann mal versuchen(btw:bezieht sich das nun nur auf ICMP oder allgemein
auch auf tcp udp usw?)


@freak
das es an der Hardware liegt glaube ich weniger, ich hab hier auch mal
nen floodping ausprobiert, klappt tadellos 100 mal ohne ein verlorenes
Packet ... schau dir mal meine "Schirmung" an .. ;)

http://sharespace.nikbamert.com/files/DSCN5130_small.jpg

Evt. liegts am Switch, ich hab hier mit meinem Teilweise auch
Probleme,
vorallem wenn ich mein avr system einschalte, dauerts ein weilchen, bis
der Switch wirklich 'begriffen' hat, dass da was dran ist(ich meine
nicht die Link led!), denn teilweise kann ich bis eine Minute warten,
bis ich dann Packete senden kann, manchmal gehts aber auch ganz
schnell..

Nik

von André K. (freakazoid)


Lesenswert?

Thanx.

@Simon: Hast Du den Kleinen direkt am Rechner, oder über einen Switch?
Wenn ich aber ein Floodping im Heim-Netzwerk an einen anderen Rechner
über diesen Switch mache kommt alles an. Naja. Vielleicht liegt es doch
an der einzigsten 10MBit-Node im Netz. Die ist halt einsam ;-)

von Ssss S. (sssssss)


Lesenswert?

>das es an der Hardware liegt glaube ich weniger, ich hab hier auch mal
>nen floodping ausprobiert, klappt tadellos 100 mal ohne ein
verlorenes
>Packet ... schau dir mal meine "Schirmung" an .. ;)
Meine Schirmung:
http://www.mikrocontroller.net/attachment.php/329781/avrETH_steckbrett_p4023794.jpg
;D ;D ;D

>dauerts ein weilchen, bis der Switch wirklich 'begriffen' hat, dass
da was dran ist
Manchmal erkennt mein switch den enc beim einschalten auch nciht bei
mir.
Ca alle 50x starten empfängt der enc keine Pakete vom switch.
Kurz power weg und dran und schon gehts wieder.

Erratas:
Ich glaub da hab ich fast keine implementiert...
- reset mache ich per reset pin und 10ms warten (min 1ms)
- vorm paket senden resette ich die tx logic (set&clear
ENC28J60_BIT_TXRST)
- neue pakete erkenne ich an PKTIF, das im errata vorgeschlagene lesen
von ENC28J60_REG_EPKTCNT funzt irgendwie nicht
- pakete hole ich per polling ab (nutze die interrupts nciht)
- ungerade/gerade prüfen des lese(?) pointers mache ich auch nicht

Bye, SImon

von Ssss S. (sssssss)


Lesenswert?

geht über nen switch. sonst sind auch nur 100mbit kisten dran.

von André K. (freakazoid)


Lesenswert?

> neue pakete erkenne ich an PKTIF, das im errata vorgeschlagene lesen
> von ENC28J60_REG_EPKTCNT funzt irgendwie nicht
Bei mir funzt beides. ENC28J60_REG_EPKTCNT hat halt den Vorteil das man
die Anzahl kennt. Dauert aber auch länger (Bankswitch vorher). Rev2 und
Rev4 verhalten sich übrigens gleich.

Das Resetten der Logik wirkt sich bei mir nich aus. Aber weils drin
steht, mach ich es halt.

Die 1ms warte ich nicht nach dem Reset. der Fehler tritt aber auch
nicht direkt danach aus, sondern mitten im Betrieb. Allerdings hab ich
festgestellt, daß weniger Pakete wegfallen je schneller das
'drumherum' ist (ASM, kein Debug, ...). Egal ich krieg den noch
klein.

von Ssss S. (sssssss)


Lesenswert?

EPKTCNT liefert bei mir manchmal "neues paket" obwohl nix neues da
ist.
PKTIF funktioniert bestens (bei rev2 und rev4 :-\)

Bye, Simon

von A.K. (Gast)


Lesenswert?

Addition im Einerkomplement ist heute einigermassen ungebräuchlich,
eigentlich nur dank TCP/IP nicht gänzlich ausgestorben. Das war aber
früher garnicht so selten, nicht zuletzt weil Seymour Cray einen Narren
daran gefressen hatte.

Es bedeutet, dass ein oben rauslaufender Übertrag unten gleich wieder
reingerechnet wird.

In diesem Fall bedeutet es, dass der Block 16bit-weise mit Übertrag
addiert wird, also ungefähr so:
     clear carry
     clear accu
     add-with-carry accu, word0
     add-with-carry accu, word1
     add-with-carry accu, word2
     ...
     add-with-carry accu, wordN
Das hat ein paar hübsche Eigenschaften, die auch die Implementierung
erleichtern/beschleunigen. Dazu kann ich das entsprechende RFC-Dokument
von TCP/IP empfehlen.

von Nik Bamert (Gast)


Lesenswert?

Ich hab noch etwas neues festgestellt. Teilweise 'erkennt' mein Switch
ja das Teil nicht - dachte ich. Nun liegts aber denke ich trozdem am
avr. Wenn ich zB bei jedem ICMP packet noch aufm Display ausgebe, dass
eines angekommen ist, dann klappt es anstandslos, jedesmal wenn ich die
schaltung am switch einschalte. Lasse ich diese 'debugausgabe' weg,
dann gehts teilweise, aber nicht immer...sehr merkwürdig - die spi
geschwindigkeit bleibt ja dieselbe..

von Robert W. (rweber)


Lesenswert?

- Schon mal die ARP-Table auf beiden Seiten überprüft?
- Nimmt Du immer die selbe MAC adresse?

von Gironymo (Gast)


Lesenswert?

Hallo Leute,

find ich ja sehr interessant was ihr da so schreibt. Mir gehts
eigentlich genau so wie Nik, nur mit dem Unterschied, dass ich noch
keine Schaltung hab. Hat von euch vielleicht jemand einen Schaltplan
für mich, vielleicht sogar mit einer kurzen Doku (ich möcht dabei auch
was über Elektronik lernen ;o)?

Besten Dank

von Jan (Gast)


Lesenswert?

habt ihr euch schon mal mit FreeRTOS.org auseinander gesetzt?
Dort gibt es mehrere Ports mit Webserver die ethernet drin haben.
Ursprünglich wurde dieses von einem Rowley Mitarbeiter geschrieben.
Ist auf ROwley.co.uk zu finden. vll einfach als Anschauungsmaterial

von Nik Bamert (Gast)


Lesenswert?

So, also ich bins wieder einmal :-)

@Robert Weber

Ja, ich hab immer dieselbe Mac Adresse, wenns dann nicht klappt sieht
das etwa so aus...Mein Pc schickt ein Broadcast Packet, welches nach
meiner mac fragt, allerdings gibt's keine Antwort von meinem Server.
Die Software ist allerdings wasserdicht, bzw. wenns dann einmal läuft,
dann läufts stundenlang durch, ich glaube nicht das es an meiner
Software liegt..:( Aber mittlerweile klappts auch öfter, weshalb weiss
ich allerdings nicht.

@ChecksumExperten
So ich hab nun mal versucht mit Hilfe von Ulrich's Stack und dessen
Checksum Funktion das Ganze zu verstehen. Verstanden habe ich's soweit
einmal..denke ich. Nur klappts nicht wirklich.

Also ich sende ein UDP Packet mit folgenden Daten:
Sourceport 85  (0x0055)
Dest. port 1113(0x0459)
Länge      13  (0x000D)
Data       Atest (0x4174,0x6573,0x74) (schon in die besagten 16 bit
Blöcke aufgeteilt)

Dann addiere ich das ganze und bekomme 0xac16, einmal ~ drüber und dann
habe ich 0x48f6. Dies ist laut Ethereal aber falsch, rauskommen sollte
0x5c11. Die Variable in der ich das alles aufaddiere ist vom typ
uint16_t. Einen Übertrag gibts bei den paar wenigen bytes soweit ich
sehe noch gar nicht, deshalb sehe ich nicht ganz, was ich denn falsch
mache..Ich hab auch schon zig Varianten versucht(ohne ports, ohne
lenght field etc...) Vielleicht kann mir jemand sagen was ich da noch
nicht ganz verstanden habe :-)...

Grüsse & ein Frohes Osterfest,

Nik

von Nik Bamert (Gast)


Lesenswert?

Aha..Tcp und Udp scheinen einen 'Pseudoheader' zu haben, wohl eine
Erfindung um die Programmierer zu nerven :P

von Nik Bamert (Gast)


Lesenswert?

Ich mach mich dann mal an die Arbeit, juhuuu :P, gefunden hab ich das
übrigens hier : http://www.netfor2.com/contents.htm

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.