Il modulo qspn
Nel modulo qspn.py viene definita la classe Etp.
Questa viene istanziata nel costruttore della classe NtkNode. Si mette in ascolto degli eventi prodotti dalla classe Neighbour (vedi il 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 classe MapRoute;
Genera gli ETP;
- Tramite i TCPClient li invia ai vicini interessati.
Inoltre fornisce il remotable method etp_exec, nel quale processa gli ETP ricevuti dai suoi vicini.
Infine emette i segnali ETP_EXECUTED e NET_COLLISION. Entrambi sono gestiti dalla classe Hook, entrambi con funzioni 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 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:
La lista di routes R.
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.Un flag di interesse posto a 1.
In pratica questo flag non è più usato e andrebbe rimosso. Vedi commento sulla pagina di struttura degli 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 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 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 RouteNode contenute nella classe MapRoute) verso le stesse destinazioni presenti nella precedente lista R.
- Crea un ETP composto da:
La lista di routes R|.
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.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 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'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.