<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl-pl">
<link rel="self" type="application/atom+xml" href="https://forum.atnel.pl/feed.php?f=4&amp;t=13778&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2015-12-08T00:45:47+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=13778&amp;mode</id>
<entry>
<author><name><![CDATA[PioDer]]></name></author>
<updated>2015-12-08T00:45:47+01:00</updated>
<published>2015-12-08T00:45:47+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147383#p147383</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147383#p147383"/>
<title type="html"><![CDATA[Re: [Atmega+ENC28J60] - losowo nieprawidłowy TCP checksum]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147383#p147383"><![CDATA[
OK, dzięki za odpowiedź i łopatologiczne tłumaczenie <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /> Nie współdzielę pamięci. Wszystko związane z TCP/IP wykonuje się sekwencyjnie.<br /><br />Pytanie - dlaczego pomijając checksum czasami gubię segmenty 1000-bajtowe?<br /><br />Zauważyłem jeszcze jedną ciekawą właściwość: przy włączonej opytamlizacji (-O2), wywala niewłaściwą sumę kontrolną, jeżeli trzymam F5 na klawiaturze.<br /><br />Natomiast jak wyłącze optymalizację to gubię segmenty i nawet ponowienie transmisji i 3-way handshake'a nie załatwia sprawy.<br /><br />Gubię dane?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=12054">PioDer</a> — 8 gru 2015, o 00:45</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[florekSi]]></name></author>
<updated>2015-12-08T00:40:07+01:00</updated>
<published>2015-12-08T00:40:07+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147380#p147380</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147380#p147380"/>
<title type="html"><![CDATA[Re: [Atmega+ENC28J60] - losowo nieprawidłowy TCP checksum]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147380#p147380"><![CDATA[
Najkrócej jak się da i na przykładzie i dla AVR:<br /><br />Załóżmy że 2 wątki (np. przerwanie i program główny) mają dostęp do 16-bitowego licznika. Jeden go inkrementuje a drugi dekrementuje. Każdy dostęp do licznika to kilka instrukcji (co najmniej 2 lub więcej tu przyjmę dla jasności że 2). Zakładam dla przykładu że w liczniku jest teraz 0x00FF (czyli 256). <br /><br />I teraz:<br />Jeden z wątków zwiększa licznik więc w młodszym bajcie będzie chciał umieścić 0x00 a w starszym 0x01 czyli wynik wg. niego wynikiem to będzie 0x0100.<br />Drugi wątek będzie chciał licznik zmniejszyć czyli w młodszym bajcie będzie chciał umieścić 0xFE a w starszym 0x00. Wynik dla niego to będzie 0x00FE.<br /><br />Pomyśl teraz że każdy taki dostęp to co najmniej 2 instrukcje które mogą się &quot;przeplatać&quot; w dowolnej kolejności. Jeśli tak to potencjalnym wynikiem w zależności od kolejności instrukcji asemblerowych będą:<br />0x0100 <br />0x01FF<br />0x01FE<br />0x00FE<br />0x01FE<br /><br />Oczywiście nie wszystkie przypadki wystąpią bo w obydwu &quot;wątkach&quot; kolejność dostępu będzie taka sama, ale sam problem wystąpi zawsze &quot;na granicy&quot; dostępów do 2 bajtów licznika. Będzie więc występował z prawdopodobieństwem: 1 / 65536 <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":-)" title="Szczęśliwy" /><br /><br />Mam nadzieję że teraz jasne <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":-)" title="Szczęśliwy" /> A jak uniknąć problemu ? Najłatwiej nie współdzielić danych. A jak (niestety) trzeba, to wykonać operację atomowo czyli niepodzielnie czyli... zablokować jeden z &quot;wątków&quot; np. przerwanie <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":-)" title="Szczęśliwy" /> (ATOMIC_BLOCK podpowiem).<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=11956">florekSi</a> — 8 gru 2015, o 00:40</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[PioDer]]></name></author>
<updated>2015-12-08T00:21:09+01:00</updated>
<published>2015-12-08T00:21:09+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147379#p147379</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147379#p147379"/>
<title type="html"><![CDATA[Re: [Atmega+ENC28J60] - losowo nieprawidłowy TCP checksum]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147379#p147379"><![CDATA[
Fakt, możecie mnie zjechać teraz, że mam obsługę stosu w przerwaniu. Chociaż jeżeli wrzucę netstackService(); do pętli głównej to też potrafi namieszać i psuć sumę kontrolną. Natomiast podaję jeszcze obsługę dzielenia danych i wysyłania segmentów:<br />[syntax=c]void tcpSendData(tcpip_hdr* packet, uint8_t* data, unsigned int data_len, uint32_t ackno_offset, uint32_t seqno_offset)<br />{<br />uint8_t *segment;<br />uint32_t segment_size;<br />uint16_t part_len=0;<br />uint32_t offset=0;<br />//ograniczam wielkość danych segmentu do TCP_MAX_DATA_LEN<br /><br />//zastosuję też technikę alokacji pamięci dla nagłówków IP i Ethernet, żeby potem<br />//ich już nie kopiować i niepotrzebnie alokować kolejną strukturę<br />if (data_len &gt; TCP_MAX_DATA_LEN)<br />segment_size = sizeof(struct netTcpHeader) + sizeof(struct netEthIpHeader) +TCP_MAX_DATA_LEN;<br />else<br />segment_size = sizeof(struct netTcpHeader) + sizeof(struct netEthIpHeader) + data_len;<br /><br />segment = malloc(segment_size);<br />segment += sizeof(struct netEthIpHeader); //przesuwam wskaźnik za nagłówki Ethernet i IP<br /><br />struct netTcpHeader *hdr = (struct netTcpHeader *)segment;<br /><br />//wypełnienie nowego nagłówka TCP<br />hdr-&gt;srcport = packet-&gt;tcp.destport;<br />hdr-&gt;destport = packet-&gt;tcp.srcport;<br />hdr-&gt;seqno = htonl(htonl(packet-&gt;tcp.ackno)+seqno_offset);<br />hdr-&gt;len_offset = 5&lt;&lt;4;<br />hdr-&gt;flags = TCP_FLAGS_PSH|TCP_FLAGS_ACK;<br />hdr-&gt;wnd = packet-&gt;tcp.wnd;<br />hdr-&gt;ackno = htonl(htonl(packet-&gt;tcp.seqno) + ackno_offset);<br />hdr-&gt;urgp = 0x00;<br /><br />do<br />{<br />hdr-&gt;tcpchksum = 0x00;<br />//jeżeli transmitujemy kolejny pakiet, ACKnew=ACK+part_len+1 (za ACK klienta)<br />if (part_len&gt;0)<br />hdr-&gt;seqno = htonl(htonl(hdr-&gt;seqno) + part_len);<br /><br />part_len = (data_len-offset&gt;TCP_MAX_DATA_LEN) ? TCP_MAX_DATA_LEN : data_len-offset; // długość partu (może być tylko jeden)<br />offset += part_len;<br /><br />segment += sizeof(struct netTcpHeader); //przesuwamy wskaźnik dla danych<br />memcpy(segment, data, part_len);<br />segment -= sizeof(struct netTcpHeader); //wracamy!<br /><br />hdr-&gt;tcpchksum = tcpChecksum(&amp;packet-&gt;ip.srcipaddr, segment, part_len+TCP_HEADER_LEN);<br /><br />data += part_len;// przesuwam wskaźnik troszkę dalej...<br /><br />ipSend(HTONL(packet-&gt;ip.srcipaddr), IP_PROTO_TCP, part_len+sizeof(struct netTcpHeader), segment - sizeof(struct netEthIpHeader), 1);<br />}<br />while(offset&lt;data_len);<br /><br />segment -= sizeof(struct netEthIpHeader);<br />free(segment);<br />}[/syntax]<br /><br />Nikt się nie odwołuje do ipGetConfig, jeżeli nawet (ARP) to bez zmiany wartości. Zmienna strukturalna netPseudoIpHeader jest niedostępna z zewnątrz procedury liczenia sumy kontrolnej.<br /><br /><div class="quotetitle">florekSi napisał(a):</div><div class="quotecontent"><br />Dane w AVR są 8-bitowe i 8-bitowe dostępy są atomowe czyli niepodzielne. Jeśli ktoś/coś odwołuje się do 16-bitów, to masz poprawkę w starszym bajcie i jej brak (albo nieprawidłową) w młodszym (stąd &quot;skok o 0x0100&quot;).<br /></div><br />Mógłbyś mi to bardziej wyjaśnić/przybliżyć?<br /><br />BTW. czasami gubię segmenty - tutaj też pytanie, dlaczego?<br /><br />Pozdrawiam<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=12054">PioDer</a> — 8 gru 2015, o 00:21</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[florekSi]]></name></author>
<updated>2015-12-07T23:47:15+01:00</updated>
<published>2015-12-07T23:47:15+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147378#p147378</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147378#p147378"/>
<title type="html"><![CDATA[Re: [Atmega+ENC28J60] - losowo nieprawidłowy TCP checksum]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147378#p147378"><![CDATA[
Błąd sugeruje że masz dostęp do danych z co najmniej 2 miejsc lub co najmniej z 2 wątków (wątkiem może być przerwanie). Dane w AVR są 8-bitowe i 8-bitowe dostępy są atomowe czyli niepodzielne. Jeśli ktoś/coś odwołuje się do 16-bitów, to masz poprawkę w starszym bajcie i jej brak (albo nieprawidłową) w młodszym (stąd &quot;skok o 0x0100&quot;).<br /><br />Czy w międzyczasie (gdy wykonujesz funkcję tcpChecksum), nikt nie odwołuje się do struct netPseudoIpHeader może gdzieś w ipGetConfig()-&gt;ip ? Bo tylko to w tym małym fragmencie może sugerować ew. problem.<br /><br />Ogólnie za mało kodu podałeś by mieć pewność.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=11956">florekSi</a> — 7 gru 2015, o 23:47</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[PioDer]]></name></author>
<updated>2015-12-07T19:54:30+01:00</updated>
<published>2015-12-07T19:54:30+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147332#p147332</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147332#p147332"/>
<title type="html"><![CDATA[Re: [Atmega+ENC28J60] - losowo nieprawidłowy TCP checksum]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147332#p147332"><![CDATA[
Ewidetnie przydałby się AVR Dragon, no, ale niestety go nie mam i muszę radzić sobie &quot;na piechotę&quot; <img src="https://forum.atnel.pl/images/smilies/icon_e_sad.gif" alt=":(" title="Smutny" /><br />Analizuję od dłuższego czasu kod i tak: suma kontrolna jest liczona w Big Endian, natomiast w Wiresharku pokazuje mi w <span style="text-decoration: underline">Little Endian</span>. Przykład:<br />jeżeli w Wiresharku suma kontrolna 0xF8FF (poprawna 0xF7FF) w Little Endian to w Big Endian (podczas liczenia) suma kontrolna to 0xFFF8 (a powinna być 0xFFF7).<br /><br />Oznacza to jedno. Skąd się bierze 0x0001 podczas liczenia sumy kontrolnej ?<br /><br />Myślałem, że podczas wysyłania PSH ACK coś się chrzani, ale jak robię SYN ACK na strukturze bufora danych wejściowych to też potrafi zawyżyć mi checksum o właśnie 0x0001. <img src="https://forum.atnel.pl/images/smilies/icon_e_sad.gif" alt=":(" title="Smutny" /><br /><br />Nie pokazałem jeszcze, że to nie jest za dużo w sumie kontrolnej, tylko za mało o 1.<br />Suma kontrolna to dopełnienie do FFFF, więc brakuje 0x0001. Tylko skąd ją wziąć? <img src="https://forum.atnel.pl/images/smilies/icon_neutral.gif" alt=":|" title="Średnio zadowolony" /><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=12054">PioDer</a> — 7 gru 2015, o 19:54</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[SunRiver]]></name></author>
<updated>2015-12-05T23:25:52+01:00</updated>
<published>2015-12-05T23:25:52+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147152#p147152</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147152#p147152"/>
<title type="html"><![CDATA[Re: [Atmega+ENC28J60] - losowo nieprawidłowy TCP checksum]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147152#p147152"><![CDATA[
Witaj <br /><br />w zasadzie nie widzę w samej funkcji problemu , wydaje mi się że kłopot nie leży po stronie liczenia, a gdzieś głębiej <br />trzeba by szerzej zerknąć na problem, np spróbować złapać debugerem moment &quot;złego wyliczenia&quot; .<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=58">SunRiver</a> — 5 gru 2015, o 23:25</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[PioDer]]></name></author>
<updated>2015-12-05T22:19:15+01:00</updated>
<published>2015-12-05T22:19:15+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147146#p147146</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147146#p147146"/>
<title type="html"><![CDATA[[Atmega+ENC28J60] - losowo nieprawidłowy TCP checksum]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=13778&amp;p=147146#p147146"><![CDATA[
Dobry wieczór!<br />Nazywam się Piotrek, jestem tutaj nowy, dlatego proszę o wyrozumiałość.<br /><br />Chciałbym opisać swój problem. Buduje serwer HTTP na stacku z Procyon AVRLib. Po odpowiednich modyfikacjach, poprawkach i autorskich zmianach nie mam większych problemów z nim, dodatkowo zaimplementowałem prostą obsługę TCP wraz z dzieleniem bufora na mniejsze segmenty danych.<br /><br />Losowo, w różnych segmentach, czasami pojawia się nieprawidłowa suma kontrolna. Co ciekawe, zawsze o wartość 0x100 (HEX), czyli 256 dziesiętnie.<br /><br />Szukam już trochę czasu, jednak to trochę jak szukanie igły w stogu siana. Poniżej przedstawiam listing funkcji liczącej sumę kontrolną TCP (jest to moja modyfikacja funkcji netChecksum uwzględniająca pseudonagłówek). Osobiście mam przeczucie, że funkcja jest dobra, bo w 99% przypadków liczy dobrze, a problem leży gdzie indziej, ale może się mylę.<br />[syntax=c]uint16_t tcpChecksum(uint32_t dstIp, void *data, uint16_t len)<br />{<br />register uint32_t sum = 0;<br /><br />struct netPseudoIpHeader *hdr = malloc(sizeof(struct netPseudoIpHeader));<br /><br />uint16_t *x=(uint16_t*) hdr;<br />uint16_t len2 = IP_PSEUDO_HEADER_LEN;<br /><br />hdr-&gt;srcipaddr = htonl(ipGetConfig()-&gt;ip);<br />hdr-&gt;destipaddr = dstIp;<br />hdr-&gt;proto = IP_PROTO_TCP;<br />hdr-&gt;reserved = 0x00;//dla pewności<br />hdr-&gt;len = htons(len);<br /><br />for (;;) {<br />if (len2 &lt; 2)<br />break;<br /><br />sum += *x++;<br />len2 -= 2;<br />}<br />free(hdr);<br /><br />for (;;) {<br />if (len &lt; 2)<br />break;<br /><br />sum += *((uint16_t *)data);<br />data+=2;<br />len -= 2;<br />}<br />if (len)<br />sum += *(uint8_t *) data;<br /><br />while ((len = (uint16_t) (sum &gt;&gt; 16)) != 0)<br />sum = (uint16_t) sum + len;<br />return (uint16_t) sum ^ 0xFFFF;<br />}[/syntax]<br /><br />Z góry dziękuję za wszelkie sugestie! <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br /><br />Pozdrawiam<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=12054">PioDer</a> — 5 gru 2015, o 22:19</p><hr />
]]></content>
</entry>
</feed>