12.5. Pouzdanost – sekvence, ACK-ovi, ponovni prijenosi¶
Sloj za uokvirivanje otkriva oštećenja pomoću svojih CRC-ova. Sloj pouzdanosti pretvara „otkriveno oštećenje” u „aplikacija nikada ne vidi neispravne podatke” tako da pregovara o ponovnom prijenosu kad god paket ne stigne netaknut.
12.5.1. Sekvencijski brojevi¶
Svako zaglavlje paketa nosi jednobajtni sekvencijski broj, zaseban za svaki smjer kretanja. Pošiljatelj povećava brojač prije prijenosa; primatelj provjerava je li sekvenca svakog primljenog paketa za jedan veća od prethodne (modulo 256).
Tri stvari mogu se pojaviti na primatelju umjesto čistog paketa u ispravnom redoslijedu:
Očekivani sekvencijski broj, s valjanim CRC-om. Paket se predaje sljedećem sloju.
Očekivani sekvencijski broj, s neispravnim CRC-om. Primatelj odbacuje paket i (ako su ACK-ovi dogovoreni) šalje NAK kojim traži ponovni prijenos.
Sekvencijski broj koji je za jedan veći od očekivanog, s valjanim CRC-om. Primatelj zna da je prethodni paket izgubljen; šalje NAK koji upućuje na propuštenu sekvencu i pohranjuje novi paket.
Slučaj duplikata (ponovni prijenos koji stigne nakon što je izvornik konačno prošao) obrađuje se provjerom u odnosu na očekivani brojač: ako je sekvenca iza očekivane, paket je duplikat i primatelj ga odbacuje nakon što pošalje ACK koji pošiljatelj očito nije primio prvi put.
12.5.2. ACK i NAK¶
Dva zastavična bita u zaglavlju paketa nose sam promet pouzdanosti:
ACK_REQpostavljen na odlaznom paketu znači „želim potvrdu natrag.” Podatkovni paketi obično ga postavljaju; statusni ping-ovi i jednokratni događaji možda neće.ACKpostavljen na paketu znači „ovaj paket je potvrda za sekvencijski broj u zaglavlju.” Ne nosi vlastiti korisni teret.NAKpostavljen znači „ovaj paket odbija prethodni” – obično zbog neispravnog CRC-a ili praznine u sekvencijskim brojevima. Zaglavlje usmjerava pošiljatelja na to koju sekvencu treba ponovno prenijeti.
Pošiljatelj izvodi petlju zaustavi-i-čekaj: prenosi jedan paket koji zahtijeva potvrdu, zatim čeka odgovarajući ACK (ili NAK) prije slanja sljedećeg. Model s jednim paketom u letu ograničava stanje pošiljatelja – nekoliko stotina bajtova na najmanjim kamerama – i odgovara ulozi protokola kao upravljačkog kanala između dviju krajnjih točaka, a ne cjevovoda optimiranog za propusnost. Na NAK pošiljatelj ponovno prenosi isti paket s postavljenom zastavicom RTX kako bi primatelj znao da se radi o ponovnom pokušaju.
12.5.3. Vrijeme ponovnog prijenosa¶
Ako ni ACK ni NAK ne stignu unutar vremena za ponovni prijenos, pošiljatelj sam ponovno prenosi paket u letu. Zadano vrijeme čekanja iznosi 500 ms i udvostručuje se pri svakom uzastopnom pokušaju (1 s, 2 s, …). Nakon konfiguriranog broja pokušaja – zadano tri – pošiljatelj odustaje i prijavljuje pogrešku prijenosa aplikaciji.
Udvostručavanje vremena čekanja standardni je obrazac eksponencijalnog odustajanja (exponential backoff). Kratko prvo vrijeme čekanja brzo hvata izgubljene pakete; udvostručavanje znači da računalo koje je zauzeto nekoliko stotina milisekundi ne pokreće oluju duplikata koji dodatno opterećuju sustav.
12.5.4. Konfiguriranje pouzdanosti¶
Oba kraja mogu, dogovorno, isključiti dijelove sloja pouzdanosti kada si aplikacija može priuštiti gubitak podataka:
protocol.init(ack=False)onemogućuje ACK-ove po paketu. Pošiljatelj pošalje i zaboravi; primatelj predaje što god stigne. Dobro za strujanje podataka senzora gdje je zastarjeli uzorak prihvatljiv.protocol.init(seq=False)isključuje praćenje sekvencijskih brojeva, što podrazumijeva i isključene ACK-ove. Korisno samo na savršeno pouzdanim prijenosima.protocol.init(crc=False)isključuje provjeru CRC-a, ali ostavlja ostatak uokvirivanja netaknutim. Vrijedi učiniti samo kada je sam prijenos dovoljno robustan da se CRC pogreške ne događaju.
Zadane postavke – sve uključeno – prava su polazna točka za svaku sesiju otklanjanja pogrešaka između računala i kamere. Kada je aplikacija u proizvodnji, kompromisi postaju specifični za njezine podatke i prijenos.
12.5.5. Statusni kodovi¶
Kada se pogreška prijenosa propagira gore do aplikacijskog koda, stiže kao statusni kod. Biblioteka protokola definira njih deset:
SUCCESS– operacija je dovršena.FAILED– naredba nije uspjela iz nespecificiranog razloga.INVALID– primatelj je odbio naredbu ili jedan od njezinih argumenata.TIMEOUT– isteklo je vrijeme mjerača ponovnih pokušaja.BUSY– kamera je zauzeta (obično zaključan kanal).CHECKSUM– CRC zaglavlja ili korisnog tereta nije se podudarao.SEQUENCE– sekvencijski broj bio je izvan redoslijeda više nego što se sloj može oporaviti.OVERFLOW– korisni teret premašio je dogovoreni maksimum.FRAGMENT– višefragmentna poruka stigla je s nedostajućim dijelovima.UNKNOWN– obrambena sveobuhvatna kategorija za istinski neočekivane uvjete.
Kod na računalu koji poziva channel_read() vidi ih kao Python iznimke; aplikacijski kod na kameri koji se opredijelio za prilagođeno rukovanje pogreškama vidi ih kao povratne vrijednosti iz povratnih poziva pozadinskog dijela. Većini aplikacija na kameri uopće ne treba gledati statusne kodove – biblioteka obrađuje ponovni pokušaj, a samo istinski nepopravljivi kvarovi (npr. sam prijenos je nestao) dosežu aplikaciju.
S uokvirivanjem koje otkriva oštećenja i pouzdanošću koja se od njih oporavlja, rad na razini žice je gotov. Aplikacijski kod vidi uokvirene, poredane, netaknute pakete; bajtovi unutar njih slobodno znače što god kanal iznad želi da znače.