= Il modulo qspn =
Nel modulo qspn.py viene definita la '''classe Etp'''.
<
>
Questa viene istanziata nel costruttore della [[../ClasseNtkNode|classe NtkNode]]. Si mette in ascolto degli eventi prodotti dalla classe Neighbour (vedi il [[../ModuloRadar|modulo Radar]]).
In particolare è interessata agli eventi {{{NEIGH_NEW}}}, {{{NEIGH_REM_CHGED}}} e {{{NEIGH_DELETED}}}, che sono emessi quando viene rilevato un nuovo vicino, oppure cambia l'efficienza del link ad un vicino, oppure un vicino abbandona la rete.
<
>
In risposta a questi eventi:
* Aggiorna la mappa delle routes note chiamando i metodi {{{routeneigh_xxx}}} della [[../ClasseMapRoute|classe MapRoute]];
* Genera gli [[../StrutturaETP|ETP]];
* Tramite i TCPClient li invia ai vicini interessati.
Inoltre fornisce il [[../ElencoRemotableFunctions|remotable method]] {{{etp_exec}}}, nel quale processa gli [[../StrutturaETP|ETP]] ricevuti dai suoi vicini.
Infine emette i segnali {{{ETP_EXECUTED}}} e {{{NET_COLLISION}}}. Entrambi sono gestiti dalla [[../ClasseHook|classe Hook]], entrambi con funzioni [[../ModuloMicro|microfunc]] di tipo "''con dispatcher''".
== Caso "vicino con REM modificata" ==
In questo evento la classe intraprende le seguenti azioni:
. Aggiorna la mappa con la nuova REM del vicino.
. Se il nodo è nella fase di avvio termina qui l'algoritmo, perché non ha ancora conoscenza della topologia della rete e non può dunque inviare ETP.
. Avvalendosi del metodo {{{bestroutes_get}}} della [[../ClasseMapRoute|classe MapRoute]], crea la lista {{{M}}}^|^; è una lista di 4 liste, una per ogni livello; ogni lista contiene le migliori routes per ogni destinazione, tra tutte quelle conosciute.
. Filtra questa lista {{{M}}}^|^ '''eliminando''' quelle che hanno come gateway il vicino stesso; ottiene così la lista {{{R}}}.
. Se la lista {{{R}}} risulta vuota l'algoritmo si ferma.
. La lista {{{R}}} è composta da routes espresse come tupla {{{(dst, rem)}}}
. Crea un ETP composto da:
1. La lista di routes {{{R}}}.
2. Il suo ID. Inizia una lista di blocchi con un primo blocco di livello 0. In esso inizia una lista di nodi (di livello 0) con un primo nodo che rappresenta se stesso. Per questo mette il suo ID di livello 0 e una {{{NullRem}}}. <
> Quando un nodo crea inizialmente un ETP, mette sempre insieme al suo ID una {{{NullRem}}} perché non deve indicare l'efficienza di nessun link. Spetta al nodo che '''riceve''' l'ETP indicare, in base ai dati della sua mappa, la Rem del link tra lui e il nodo che glielo ha inviato. <
> '''''TODO''': secondo il documento qspn.pdf il rem è impostato dal nodo che invia l'ETP, correggere il documento.''
3. Un flag di interesse posto a 1. <
> In pratica questo flag non è più usato e andrebbe rimosso. Vedi commento sulla pagina di struttura degli [[../StrutturaETP|ETP]].
. Invia l'ETP prodotto al "vicino con REM modificata".
== Caso "vicino nuovo" ==
In questo caso la classe si comporta allo stesso modo del caso "vicino con REM modificata".
== Caso "vicino non più rilevato" ==
In questo evento la classe intraprende le seguenti azioni:
. Avvalendosi del metodo {{{bestroutes_get}}} della [[../ClasseMapRoute|classe MapRoute]], crea la lista {{{M}}}^|^ (vedi sopra).
. Filtra questa lista {{{M}}}^|^ '''trattenendo solo''' quelle che hanno come gateway il vicino stesso; ottiene così la lista {{{R}}}.
. Aggiorna la mappa eliminando le routes che passano per il vicino.
. Se il nodo è nella fase di avvio termina qui l'algoritmo, perché non ha ancora conoscenza della topologia della rete e non può dunque inviare ETP.
. Se la lista {{{R}}} risulta vuota l'algoritmo si ferma.
. --(Avvalendosi del metodo {{{bestroutes_get}}} della [[../ClasseMapRoute|classe MapRoute]], crea la lista {{{M}}}^|^, '''aggiornata'''.)--
. --(Filtra questa lista {{{M}}}^|^ '''trattenendo solo''' quelle che hanno come destinazione le destinazioni delle routes appena eliminate; ottiene così la lista {{{R}}}^|^.)--
. Calcola la lista {{{R}}}^|^ con le ''nuove'' migliori routes (ottenute con il metodo {{{best_route}}} delle istanze di [[../ClasseRouteNode|RouteNode]] contenute nella [[../ClasseMapRoute|classe MapRoute]]) verso le stesse destinazioni presenti nella precedente lista {{{R}}}.
. Crea un ETP composto da:
1. La lista di routes {{{R}}}^|^.
2. Il suo ID. Inizia una lista di blocchi con un primo blocco di livello 0. In esso inizia una lista di nodi (di livello 0) con un primo nodo che rappresenta se stesso. Per questo mette il suo ID di livello 0 e una {{{NullRem}}}. <
> Vedi commento sopra.
3. Un flag di interesse posto a 1. <
> Vedi commento sopra.
. Invia l'ETP prodotto a tutti i suoi vicini tranne il "vicino non più rilevato".
== Processazione degli ETP ricevuti dai vicini (metodo etp_exec) ==
Alla ricezione di un ETP la classe intraprende le seguenti azioni:
. Controlla se si è verificata una collisione di 2 reti nate separatamente. Vedi la microfunc [[../NetworkCollision|collision_check]]. <
> Se è avvenuta una collisione viene emesso il segnale {{{NET_COLLISION}}} e la processazione del ETP termina.
. Se il nodo era ancora nella fase di avvio, ora che ha ricevuto un ETP è a tutti gli effetti entrato nella rete. Processando l'ETP viene a conoscenza della topologia della rete e potrà inoltrare l'ETP.
. Il TPL contenuto nell'ETP ricevuto ha queste proprietà:
. a) non ha mai più di 4 (settings.LEVELS) blocchi;
. b) ogni blocco è preceduto da blocchi di livello più alto e seguito da blocchi di livello più basso;
. Il TPL e l'insieme di routes {{{R}}} contenuti nell'ETP ricevuto hanno significato in quanto riferiti al nodo che ha inviato l'ETP.
. Verifica quale livello comune di appartenenza ha il nodo corrente con il nodo mittente. Cioè si memorizza il primo livello (il più alto) in cui gli ID differiscono. Chiamiamolo {{{comm_lvl}}}. Appartengo allo stesso gnodo? Livello 0. Allo stesso ggnodo? Livello 1. ...
. Si scorre i blocchi del TPL ricevuto (vedi la struttura dell'[[../StrutturaETP|ETP]]). Di ogni blocco con un livello più basso di {{{comm_lvl}}}, i vari {{{pairs}}} vengono "accorpati" in un unico {{{pair}}} all'interno del blocco e il blocco diventa di livello {{{comm_lvl}}}. Questo unico {{{pair}}} ha come ID l'ID di livello {{{comm_lvl}}} del nodo mittente e come {{{Rem}}} la somma delle {{{Rem}}} dei {{{pairs}}} che sostituisce.
. Si scorre di nuovo i blocchi del TPL e accorpa i blocchi contigui di paro livello.
. Si scorre di nuovo i blocchi del TPL e per ogni blocco si scorre i {{{pairs}}} ivi contenuti e accorpa i {{{pairs}}} contigui di uguale ID.
. Questi passi fanno si che il TPL ricevuto diventi di significato riferito al nodo corrente. Inoltre sono mantenute le sue proprietà a) e b) di cui sopra.
. Poi inizia la procedura come delineata nel documento qspn.pdf.
. Verifica che il proprio ID non sia già presente nella lista percorsa dall'ETP (Acyclic rule). Se è presente ignora il pacchetto e termina la processazione. '''Non''' viene emesso il segnale {{{ETP_EXECUTED}}}, infatti l'ETP ricevuto non è stato processato perché per la Acyclic rule esso è non interessante
. Aggiorna la propria mappa in base alle info ottenute dalla TPL. <
> Nel farlo, si calcola un flag {{{TPL_is_interesting}}} dal quale dipende la propagazione o meno del ETP. ('''''Nota''': non è la stessa cosa del {{{flag_of_interest}}} nella struttura del ETP'')
. Aggiorna la propria mappa in base alle info contenute nella porzione di mappa in {{{R}}}.
. Calcola la lista {{{S}}} con le routes verso le destinazioni presenti nella lista {{{R}}} di cui il nodo corrente conosce routes migliori che non passano per il nodo che ha inviato l'ETP.
. Calcola la lista {{{R}}}^|^ con tutte le routes della lista {{{R}}} le cui destinazioni non compaiono nella lista {{{S}}}.
. Se la lista {{{R}}}^|^ non è vuota oppure se il TPL è interessante (vedi flag {{{TPL_is_interesting}}} sopra) allora l'ETP viene propagato:
. Aggiunge il nodo corrente in coda al TPL. <
> Deve essere in un blocco di livello 0; se nel TPL non c'è più il blocco 0 (cioè il nodo mittente è di un'altro g-nodo) lo crea. <
> Il {{{pair}}} che aggiunge ha come ID l'ID di livello 0 del nodo corrente e come {{{Rem}}} l'efficienza del link verso il nodo mittente.
. Crea un nuovo ETP che contiene l'insieme di routes {{{R}}}^|^. Come TPL usa quello ricevuto e fin qui processato.
. Invia l'ETP prodotto a tutti i suoi vicini tranne il "vicino mittente".
. Viene emesso il segnale {{{ETP_EXECUTED}}}, sia che l'ETP venga propagato oppure no.