Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 30 mar 2026, o 08:13


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 7 ] 
Autor Wiadomość
PostNapisane: 5 gru 2015, o 22:19 
Offline
Nowy

Dołączył(a): 05 gru 2015
Posty: 11
Pomógł: 0

Dobry wieczór!
Nazywam się Piotrek, jestem tutaj nowy, dlatego proszę o wyrozumiałość.

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.

Losowo, w różnych segmentach, czasami pojawia się nieprawidłowa suma kontrolna. Co ciekawe, zawsze o wartość 0x100 (HEX), czyli 256 dziesiętnie.

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ę.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Z góry dziękuję za wszelkie sugestie! :)

Pozdrawiam



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 gru 2015, o 23:25 
Offline
Użytkownik

Dołączył(a): 04 paź 2011
Posty: 8631
Pomógł: 338

Witaj

w zasadzie nie widzę w samej funkcji problemu , wydaje mi się że kłopot nie leży po stronie liczenia, a gdzieś głębiej
trzeba by szerzej zerknąć na problem, np spróbować złapać debugerem moment "złego wyliczenia" .



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 7 gru 2015, o 19:54 
Offline
Nowy

Dołączył(a): 05 gru 2015
Posty: 11
Pomógł: 0

Ewidetnie przydałby się AVR Dragon, no, ale niestety go nie mam i muszę radzić sobie "na piechotę" :(
Analizuję od dłuższego czasu kod i tak: suma kontrolna jest liczona w Big Endian, natomiast w Wiresharku pokazuje mi w Little Endian. Przykład:
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).

Oznacza to jedno. Skąd się bierze 0x0001 podczas liczenia sumy kontrolnej ?

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. :(

Nie pokazałem jeszcze, że to nie jest za dużo w sumie kontrolnej, tylko za mało o 1.
Suma kontrolna to dopełnienie do FFFF, więc brakuje 0x0001. Tylko skąd ją wziąć? :|



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 7 gru 2015, o 23:47 
Offline
Użytkownik

Dołączył(a): 27 lis 2015
Posty: 36
Zbananowany użytkownik

Pomógł: 5

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 "skok o 0x0100").

Czy w międzyczasie (gdy wykonujesz funkcję tcpChecksum), nikt nie odwołuje się do struct netPseudoIpHeader może gdzieś w ipGetConfig()->ip ? Bo tylko to w tym małym fragmencie może sugerować ew. problem.

Ogólnie za mało kodu podałeś by mieć pewność.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 gru 2015, o 00:21 
Offline
Nowy

Dołączył(a): 05 gru 2015
Posty: 11
Pomógł: 0

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:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


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.

florekSi napisał(a):
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 "skok o 0x0100").

Mógłbyś mi to bardziej wyjaśnić/przybliżyć?

BTW. czasami gubię segmenty - tutaj też pytanie, dlaczego?

Pozdrawiam



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 gru 2015, o 00:40 
Offline
Użytkownik

Dołączył(a): 27 lis 2015
Posty: 36
Zbananowany użytkownik

Pomógł: 5

Najkrócej jak się da i na przykładzie i dla AVR:

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).

I teraz:
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.
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.

Pomyśl teraz że każdy taki dostęp to co najmniej 2 instrukcje które mogą się "przeplatać" w dowolnej kolejności. Jeśli tak to potencjalnym wynikiem w zależności od kolejności instrukcji asemblerowych będą:
0x0100
0x01FF
0x01FE
0x00FE
0x01FE

Oczywiście nie wszystkie przypadki wystąpią bo w obydwu "wątkach" kolejność dostępu będzie taka sama, ale sam problem wystąpi zawsze "na granicy" dostępów do 2 bajtów licznika. Będzie więc występował z prawdopodobieństwem: 1 / 65536 :-)

Mam nadzieję że teraz jasne :-) A jak uniknąć problemu ? Najłatwiej nie współdzielić danych. A jak (niestety) trzeba, to wykonać operację atomowo czyli niepodzielnie czyli... zablokować jeden z "wątków" np. przerwanie :-) (ATOMIC_BLOCK podpowiem).



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 gru 2015, o 00:45 
Offline
Nowy

Dołączył(a): 05 gru 2015
Posty: 11
Pomógł: 0

OK, dzięki za odpowiedź i łopatologiczne tłumaczenie :) Nie współdzielę pamięci. Wszystko związane z TCP/IP wykonuje się sekwencyjnie.

Pytanie - dlaczego pomijając checksum czasami gubię segmenty 1000-bajtowe?

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.

Natomiast jak wyłącze optymalizację to gubię segmenty i nawet ponowienie transmisji i 3-way handshake'a nie załatwia sprawy.

Gubię dane?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 7 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Google [Bot] i 2 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO