mikrovezérlő tcp kezelés

Sziasztok,
több heti Tannembaum-könyv rágcsálás és Guglizás után sem világosak a multi-szegmenses küldéshez szükséges lépések. Egy neten megjelent pici mikrovezérlős web-server projectet szeretnék tovább bővíteni, de az eredetileg 500 byte-nyi ablakméret miatt a tcp stacket át kell alakítanom, tudjon multi-szegmens kezelést is, ha egy picivel is nagyobb html oldalt akarok küldeni.
Az alábbi kommunikáció-részlet előtt már küldtem password kérdő ablakot, ment a válasz is, addig nincs baj míg egy szegmensben el tudom küldeni, amit akarok. Itt küldeném az oldal további részeit, de az első darabra már nincs válasz. Miért?

 
16:50.364614 IP (tos 0x0, ttl 128, id 2476, offset 0, flags [DF], proto: TCP (6), length: 48) Firefox.1109 > Atmel.80: S, cksum 0x89f2 (correct), 4201085121:4201085121(0) win 65535 <mss 1460,nop,nop,sackOK>
	0x0000:  4500 0030 09ac 4000 8006 6fbd c0a8 0003  E..0..@...o.....
	0x0010:  c0a8 000b 0455 0050 fa67 78c1 0000 0000  .....U.P.gx.....
	0x0020:  7002 ffff 89f2 0000 0204 05b4 0101 0402  p...............


16:50.365948 IP (tos 0x0, ttl  64, id 2476, offset 0, flags [DF], proto: TCP (6), length: 44) Atmel.80 > Firefox.1109: S, cksum 0x751c (correct), 10752:10752(0) ack 4201085122 win 65535 <mss 1408>
	0x0000:  4500 002c 09ac 4000 4006 afc1 c0a8 000b  E..,..@.@.......
	0x0010:  c0a8 0003 0050 0455 0000 2a00 fa67 78c2  .....P.U..*..gx.
	0x0020:  6012 ffff 751c 0000 0204 0580 0000       `...u.........


16:50.366006 IP (tos 0x0, ttl 128, id 2478, offset 0, flags [DF], proto: TCP (6), length: 40) Firefox.1109 > Atmel.80: ., cksum 0x8ca5 (correct), 4201085122:4201085122(0) ack 10753 win 65535
	0x0000:  4500 0028 09ae 4000 8006 6fc3 c0a8 0003  E..(..@...o.....
	0x0010:  c0a8 000b 0455 0050 fa67 78c2 0000 2a01  .....U.P.gx...*.
	0x0020:  5010 ffff 8ca5 0000                      P.......


16:50.367120 IP (tos 0x0, ttl 128, id 2479, offset 0, flags [DF], proto: TCP (6), length: 461) Firefox.1109 > Atmel.80: P, cksum 0x1115 (correct), 4201085122:4201085543(421) ack 10753 win 65535
	0x0000:  4500 01cd 09af 4000 8006 6e1d c0a8 0003  E.....@...n.....
	0x0010:  c0a8 000b 0455 0050 fa67 78c2 0000 2a01  .....U.P.gx...*.
	0x0020:  5018 ffff 1115 0000 504f 5354 202f 2048  P.......POST./.H
	0x0030:  5454 502f 312e 310d 0a48 6f73 743a 2031  TTP/1.1..Host:.1
	0x0040:  3932 2e31 3638 2e30 2e31 310d 0a55 7365  92.168.0.11..Use
	0x0050:  722d 4167 656e 743a 204d 6f7a 696c 6c61  r-Agent:.Mozilla
	0x0060:  2f35 2e30 2028 5769 6e64 6f77 7320 4e54  /5.0.(Windows.NT
	0x0070:  2035 2e31 3b20 7276 3a31 302e 302e 3229  .5.1;.rv:10.0.2)
	0x0080:  2047 6563 6b6f 2f32 3031 3030 3130 3120  .Gecko/20100101.
	0x0090:  4669 7265 666f 782f 3130 2e30 2e32 0d0a  Firefox/10.0.2..
	0x00a0:  4163 6365 7074 3a20 7465 7874 2f68 746d  Accept:.text/htm
	0x00b0:  6c2c 6170 706c 6963 6174 696f 6e2f 7868  l,application/xh
	0x00c0:  746d 6c2b 786d 6c2c 6170 706c 6963 6174  tml+xml,applicat
	0x00d0:  696f 6e2f 786d 6c3b 713d 302e 392c 2a2f  ion/xml;q=0.9,*/
	0x00e0:  2a3b 713d 302e 380d 0a41 6363 6570 742d  *;q=0.8..Accept-
	0x00f0:  4c61 6e67 7561 6765 3a20 6875 2d68 752c  Language:.hu-hu,
	0x0100:  6875 3b71 3d30 2e38 2c65 6e2d 7573 3b71  hu;q=0.8,en-us;q
	0x0110:  3d30 2e35 2c65 6e3b 713d 302e 330d 0a41  =0.5,en;q=0.3..A
	0x0120:  6363 6570 742d 456e 636f 6469 6e67 3a20  ccept-Encoding:.
	0x0130:  677a 6970 2c20 6465 666c 6174 650d 0a43  gzip,.deflate..C
	0x0140:  6f6e 6e65 6374 696f 6e3a 206b 6565 702d  onnection:.keep-
	0x0150:  616c 6976 650d 0a52 6566 6572 6572 3a20  alive..Referer:.
	0x0160:  6874 7470 3a2f 2f31 3932 2e31 3638 2e30  http://192.168.0
	0x0170:  2e31 312f 0d0a 436f 6e74 656e 742d 5479  .11/..Content-Ty
	0x0180:  7065 3a20 6170 706c 6963 6174 696f 6e2f  pe:.application/
	0x0190:  782d 7777 772d 666f 726d 2d75 726c 656e  x-www-form-urlen
	0x01a0:  636f 6465 640d 0a43 6f6e 7465 6e74 2d4c  coded..Content-L
	0x01b0:  656e 6774 683a 2031 360d 0a0d 0a70 6173  ength:.16....pas
	0x01c0:  7377 6f72 643d 3736 3534 3332 31         sword=7654321


16:50.371079 IP (tos 0x0, ttl  64, id 2479, offset 0, flags [DF], proto: TCP (6), length: 40) Atmel.80 > Firefox.1109: ., cksum 0x8b00 (correct), 10753:10753(0) ack 4201085543 win 65535
	0x0000:  4500 0028 09af 4000 4006 afc2 c0a8 000b  E..(..@.@.......
	0x0010:  c0a8 0003 0050 0455 0000 2a01 fa67 7a67  .....P.U..*..gzg
	0x0020:  5010 ffff 8b00 0000 0000 0000 0000       P.............


16:50.372363 IP (tos 0x0, ttl  64, id 2480, offset 0, flags [+, DF], proto: TCP (6), length: 156) Atmel.80 > Firefox.1109: P 10753:10869(116) ack 4201085543 win 65535
	0x0000:  4500 009c 09b0 6000 4006 8f4d c0a8 000b  E.....`.@..M....
	0x0010:  c0a8 0003 0050 0455 0000 2a01 fa67 7a67  .....P.U..*..gzg
	0x0020:  5018 ffff a8f3 0000 4854 5450 2f31 2e30  P.......HTTP/1.0
	0x0030:  2032 3030 204f 4b0d 0a43 6f6e 7465 6e74  .200.OK..Content
	0x0040:  2d54 7970 653a 2074 6578 742f 6874 6d6c  -Type:.text/html
	0x0050:  0d0a 0d0a 3c6d 6574 6120 6368 6172 7365  ....<meta.charse
	0x0060:  743d 2275 7466 2d38 223e 3c74 723e 3c68  t="utf-8"><tr><h
	0x0070:  313e 3c63 656e 7465 723e 4e65 7465 7320  1><center>Netes.
	0x0080:  74c3 a176 6b61 7063 736f 6cc3 b33c 2f68  t..vkapcsol..</h
	0x0090:  313e 3c2f 7472 3e3c 2f74 643e            1></tr></td>

Hozzászólások

Szia! Látom nem jutottál sokkal előrébb! :(
c

Hát nem. Olyan alapvető dolgokat nem tudtam kideríteni, hogy
- a multi-packetes küldés esetén változik-e a packet ID
- minden packet esetén új kapcsolatot kell-e felépíteni vagy egy kapcsolaton belül több packet is elmehet
Mindenhol csak azt találom leírva, hogy egy packet továbbítása és nyugtázása hogyan történik.
Próbálgattam több variációt, de egy meglevő tcp implementáció átszervezése macerás dolog és nem túl lelkesítő annak a tudatában, hogy előre tudom, hogy ez is csak egy újabb találgatás részemről. Valahogy könnyebb úgy programot írni, ha tudom, mi a feladat. :(

a kapcsolat biztosan marad, a packetid meg emlékeim szerint a stream-en belüli ofsettel egyenlő, de lehet, hogy tévedek. Régen volt már a főiskola, de elég részletesen tanultuk a tcp/ip működését. Amúgy a neten le van ezer helyen írva még, egy kis keresgéléssel részletesen megtalálod a válaszokat.

vonaton ulve eleg nehez barmit is kihamozni egy halom hexa dumpbol, viszont ha hazaerek atnezem a logokat;)

még mindig nem sikerült elegendő időt keríteni arra, hogy átnézzem a dolgot;) Sajnos ez a rohangálós dolog ilyen.
Az alattam lévő threadben elég szépen ki van boncolva, hogy miért nem célszerű ethernet szinten megoldani a csomagok fragmentálását. Én ezt a részét rábíznám a tcp-re, mert így egyrészt megoldódnának az ack csomagokkal való mizériák is.
Másrészt, a kevés memória miatt nem tudod egyben letárolni a kiküldésre váró dolgokat, így ha kellően fix a kiküldött adatok szerkezete, célszerű lenne különböző state-ekre bontani a kiküldött adatokat.
Azért lenne ez célszerű, mert a szegmenseknél nem kötelező kihasználnod a max data length-et, így nyugodtan küldhetsz bármekkora packetet (az előbbinél az volt a tapasztalatom, ha fragmentációra kerül a sor és nincs kitöltve az MTU mérete (mert elvileg az ennél nagyobb csomagok esetén történne csak meg ez), akkor változatos hibákkal találkozik az ember).
Másrészt ha state-re bontod a kiküldésre váró adatokat, megismételhetőek maradnak az adott session-re vonatkozó részek, így ha valami elveszne, újragenerálható lesz az adott darab, illetve minden darabra jönnek a válasz csomagok is.
Szóval véleményem szerint dobd az MF-et és használd a TCP erre vonatkozó részét (jobban jársz több részről is).

u.i.: Bocs ha valami nem érthető, 3 óra alvás után a gondolkodásom még hagy némi kívánni valót maga után;)

0. Etesd meg a forgalmat egy wiresharkkal, az szépen szinezi a hibás csomagokat.

1. Így elsőre pl. a packet mérete a ip header szerint 009c, a valóságban meg csak 0070 byte-nyit írtál be ide...

2. MF flaget használsz. Ez azt jelenti, hogy amíg a vevő az _összes_ fragmentjét meg nem kapta annak az IP packetnek, addig nem csinál vele semmit (pláne nem küld ACK-t egy fél IP packetre), ha pedig akár egy darab is elveszik, akkor a vevő vár, vár, vár, majd újraküldeti veled az egészet (megismétli a régi ACK-t). Ez nem TCP-re való, _szerintem_ nem akarod te ezt igazán. Ne használj fragmentációt, nem kell neked ez a szopás. A TCP tudja ezt ennél okosabban is.

Mint írtam, egy avr mikrovezérlőről szól a játék, ahol van 1k memória. Ebből kell helyet bitosítani stack-nek, saját változóknak és puffereknek - ergo muszáj MF-et csináljak.

Az IP header hossz valóban hiba, erről tényleg tudok tenni, köszönöm az észrevételt.
Mivel a tanácsok ellenére csak MF-fel tudom megoldani a munkát, erre kérdezek rá a továbbiakban:
- az összevont ack-t nem nyugtáztam vissza a böngészőnek, így elvárom, hogy a minden darab után nyugtát kapjak. Jogos?
- az összeköttetést ugye nem kell bontani, majd újra felépíteni a következő fragment miatt?
- jól gondolom, hogy az összeköttetés marad ugyan, de a következő fragment ID már más lesz?

Azt nem kell mondani, hogy az utolsó fragment-ben már nem lehet benne az MF bit, erre figyelek.
-

ergo muszáj MF-et csináljak.

Ha MF-fel meg tudod csinálni, anélkül is meg tudod csinálni. Sőt, nélküle még jobban meg lehet csinálni - ha TCP-ről beszélünk. Az UDP már más tészta.

Személy szerint azt gondolom, hogy semmilyen megoldást nem fogsz tudni megcsinálni, ha a csőben levő (Ethernet vezeték), még vissza nem igazolt összes Ethernet packetet nem tudod bármikor újra elküldeni. Ha ez csak ram-ból megy (különben ugye újra kell generálnod), és csak 1KB-od van, akkor - szerintem - ennél több adat nem lehet visszaigazolatlanul a csőben. Ez a mennyiség szorozva a round-trip delay-jel korlátozza a max. elérhető sávszélességet. Ha pl. 10ms oda-vissza egy kör, és 1KB-nyi adatot tudsz beletolni a csőbe visszaigazolás nélkül, akkor 1KB/10ms = 100KB/s az elméletileg elérhető max. sebesség.

- az összevont ack-t nem nyugtáztam vissza a böngészőnek, így elvárom, hogy a minden darab után nyugtát kapjak. Jogos?

Nem érted, még mindig. IP csomag szinten kaphatsz ACK-t, akkor, amikor az egész IP csomag megjött a túloldalra. Te azt választottad, hogy egy IP csomagot több Ethernet csomagra bontasz. Ennek az lesz az "ára", hogy akkor kapsz ACK-t, amikor _mindegyik_ Ethernet csomag megjön az címzetthez, ami ahhoz az IP csomaghoz kell, mert addig neki sem tud állni összerakosgatni az IP csomagot, hiszen még a fele nincs is meg...

- jól gondolom, hogy az összeköttetés marad ugyan, de a következő fragment ID már más lesz?

Fragment ID nincs. IP csomag szinten van egy ID, aminek mindegyik fragmentben meg kell egyeznie, különben "nem találnak egymásra" a fragmentek, nem lehet tudni, hogy kik tartoznak össze.

Fragment offset van, az azt mondja meg, hogy az IP csomag elejéhez képest hova kerüljön az a fragment. Akkor jött meg az egész IP csomag, ha megvan az utolsó darab (amiben MF=0), ÉS a korábban kapott fragmentek 0x0000-tól lefedik az utolsó darab előtti teljes mezőt.

És még egyszer: ha egyetlen egy fragment is elveszik, az _egész_ IP csomag megy a kukába, te meg küldheted újra _mindet_.

- az összeköttetést ugye nem kell bontani, majd újra felépíteni a következő fragment miatt?

Mármint a TCP kapcsolatot???
Szerintem mélyvíz ez az MF neked (nem érted a fogalmakat se), tényleg használd inkább a TCP tudását, megy ez MF nélkül is.

Szerintem mélyvíz ez az MF neked (nem érted a fogalmakat se)

Hm. Ez valóban mélyvíz, ezért kérdezek itt. És azért nem tanultam meg a netes kommunikáció alapjait, mert mikor én munkába álltam, még nem volt IC sem, nem hogy processzor, pláne net. :(
Azért valahogyan mégis elbotorkáltam odáig, hogy működik az arp, icmp és - egyetlen packetre vonatkoztatva - a tcp is. Ezen alapulva mennek az olyan egyszerű, egyetlen packeten alapuló dolgok is, mint pl. jelszó lekérés, felhasználó azonosítás, stb. Most viszont kénytelen vagyok több részre bontani egy túl nagy html oldalt és ezt nem tudom, hogyan tehetem. Bizony, bizony azt hiszem, félreértem az alapokat és valamilyen perverz gondolattól vezérelve úgy hittem, a hiányosságaimból eredő kérdéseimre itt választ kapok.
Jött sok nagyon okos tanács, hogy dobjak el mindent, tervezzem újra a hw-t és álljak át valami számora ismeretlen procira, de szerencsére volt 2-3 válaszadó, akik a kérdésemet is olvasták :), ami mindössze pár flag szerepének a tisztázásáról szólt.
Ha mégis akadna valaki, aki tévesen értelmezett terminus technicusaimat helyretéve, magánban a kérdést segítene tisztázni, megköszönném...

Esetleg mikrovezérlő terén egy komolyabbra váltani.

http://www2.chipcad.hu/www/arak.aspx?group=010114 - MIPS M4K
http://goo.gl/pT6hQ - ARM Cortex M3

8 .. 128 kB RAM
64 .. 1024 kB flash.

További előny, hogy a mikrovezérlőgyártó által mellékelt TCP stack alkalmazására is van lehetőséged, ugyanakkor nem kell szívnod azon, hogy kevés az erőforrás az N+1. beleintegrálandó funkcióhoz.

Azaz egy csomó szoftverszívástól mentesülhetsz.