Forum: Mikrocontroller und Digitale Elektronik UDP Prüfsumme bilden


von SPI (Gast)


Lesenswert?

Hallo zusammen!

Ich versuche zwischen einem PIC (16F877) an welchem ein ENC28j60 
angeschlossen ist, Daten an einen Computer zu senden. Soweit 
funktioniert auch alles, jedoch habe ich Probleme mit der Bildung der 
Prüfsumme.

Im Programm Wireshark entnehme ich eine Prüfsumme von 0xaef6.
Folgende Einstellungen stehen dabei im Internet Protocol:
    Version:4
    Header length: 20 bytes
    Differentiates services Field: (DSCP 0x00: Default; ECN: 0x00)
    Total Lenght: 94
    Identification: 0x0800 (2048)
    Fragment offset: 0
    Time to live: 128
    Protocol: UDP (17)
    Header checksum: 0xaef6
    Source: 192.168.1.31
    Destination: 192.168.1.41

Kann mir bitte jemand an diesem Beispiel erklären, welche Daten alles 
für die Prüfsumme benötigt werden und wie diese zusammengezählt werden, 
damit eine Prüfsumme von 0xaef6 herauskommt.


Herzlichen Dank
SPI

von g457 (Gast)


Lesenswert?


von SPI (Gast)


Lesenswert?

Diesen Artikel habe ich auch schon gesehen, jedoch hat er nicht wirklich 
zur Lösung meines Problems beigeholfen.

Mfg

von g457 (Gast)


Lesenswert?

Da steht doch ganz genau drin, was alles verwurstet wird (und wie). Was 
ist denn noch unklar?

von SPI (Gast)


Lesenswert?

Mir ist nicht ganz bewusst welche Bytes zu einem Wort zusammengefügt 
werden.

Währen dies in meinem Beispiel:

             2 Bytes
Quelle:      192 168
               1 41
Ziel:        192 168
               1 31
Protokoll:   0x00 17
Länge UDP:   0x00 94


Wird demfall Time to live, Identification und Header length nicht für 
die Prüfsumme verwendet?

Danke für deine Hilfe!!!
Mfg

von Andreas F. (aferber)


Lesenswert?

Die Prüfsumme in deinem Wireshark-Beispiel ist die IP-Header-Checksum, 
nicht die UDP-Prüfsumme. In der englischen Wikipedia ist eigentlich 
ausreichend genau beschrieben, wie die berechnet wird, inklusive 
Beispiel (bei der Beschreibung zum Feld "Header Checksum"):

http://en.wikipedia.org/wiki/IPv4#Header

Die UDP-Prüfsumme beinhaltet auch den Payload, ist (bei IPv4) aber 
optional, muss also nicht unbedingt berechnet werden, sondern kann 
auch einfach auf 0 gesetzt werden.

Bei beiden Prüfsummen gilt, dass einfach die Bytes so wie sie über's 
Netzwerk gesendet werden in Zweiergruppen zu Words zusammengefasst 
werden (High-Byte zuerst).

Andreas

von g457 (Gast)


Lesenswert?

Zuallererst musst Du noch entscheiden - das hab ich vorhin vergessen.. - 
ob du die Prüfsumme im IP-Header berechnen willst (das scheint die zu 
sein, die Du oben zitiert hast) oder ob Du die Prüfsumme im UDP-Header 
(so stehts in der Überschrift und darauf bezieht sie auch obiger link) 
berechnen willst.

Für ersteres möchte ich hier ggf. noch [1] zur Lektüre nachliefern.

Die Berechnung als solches geschieht bei beiden weitgehend analog (der 
Teufel liegt wie immer im Detail..): Es werden immer 2 Bytes zu 
vorzeichenlosen 16-bit-Werten zusammengefasst und diese dann aufaddiert.
Welche Daten an welchen Stellen stehen steht in der 
Protokollspezifikation (z.B. in den genannten Links - am 
übersichtlichsten in den Bildern). Einfach immer hübsch Byte1/2 +Byte3/4 
+Byte5/6 usw. bis zum Ende.

HTH

[1] http://en.wikipedia.org/wiki/IPv4#Header

von Tobi (Gast)


Lesenswert?

Übrigens ist der ENC28J60 in der Lage, die Berechnung der 
IP-Header-Prüfsumme selbst durchzuführen. Du musst ihm nur verraten, von 
wo bis wo sich in seinem RAM der IP-Header befindet. Dann hättest Du das 
schonmal aus dem Kopf.

1
void
2
enc28j60_calcChecksum(uint16_t startAddr, uint16_t endAddr, uint16_t checksumAddr)
3
{
4
  uint16_t checksum;
5
6
  /* Set previous checksum to 0 */
7
  enc28j60_regWriteWord(EWRPT, TXBUFST + 1 + checksumAddr);
8
  enc28j60_bufWriteByte(0);
9
  enc28j60_bufWriteByte(0);
10
11
  /* Let ENC28J60 calculate the checksum for the specified range. */
12
  enc28j60_regWriteWord(EDMAST, TXBUFST + 1 + startAddr);
13
  enc28j60_regWriteWord(EDMAND, TXBUFST + 1 + endAddr);
14
  enc28j60_regSetBits(ECON1, DMAST | CSUMEN);
15
  while (enc28j60_regReadByte(ECON1) & DMAST);
16
  checksum = enc28j60_regReadWord(EDMACS);
17
18
  /* Store calculated checksum at "checksumAdr". */
19
  enc28j60_regWriteWord(EWRPT, TXBUFST + 1 + checksumAddr);
20
  enc28j60_bufWriteByte(checksum >> 8);
21
  enc28j60_bufWriteByte(checksum >> 0);
22
}

von Andreas F. (aferber)


Lesenswert?

Tobi schrieb:
> Übrigens ist der ENC28J60 in der Lage, die Berechnung der
> IP-Header-Prüfsumme selbst durchzuführen. Du musst ihm nur verraten, von
> wo bis wo sich in seinem RAM der IP-Header befindet. Dann hättest Du das
> schonmal aus dem Kopf.

Errata gelesen? Leider hat das Teil einen bösen Bug (unter DMA in den 
Errata), der Hardware-Checksumming mit dem Chip ziemlich unbenutzbar 
macht, zumindest dann wenn man nicht nur senden, sondern auch empfangen 
will.

Andreas

von Tobi (Gast)


Lesenswert?

> Errata gelesen?

Um der Wahrheit die Ehre zu geben: Nein. Allerdings ist mir der Bug bis 
heute nicht aufgefallen. Den höheren Protokollschichten sei Dank :)

von SPI (Gast)


Lesenswert?

Ich habe es nun endlich geschafft und die Checksummenbildung 
funktioniert sogar. Super!!

Herzlichen Dank für eure Hilfe.

Mfg SPI

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.