Modulo Identities - Dettagli Tecnici

Requisiti

L'utilizzatore del modulo Identities per prima cosa inizializza il modulo richiamando il costruttore di IdentityManager.

Nel costruttore viene passata l'istanza di ITasklet per fornire l'implementazione del sistema di tasklet.

Inoltre vengono passati:

Durante il tempo l'utilizzatore potrà fornire al modulo altre informazioni con questi metodi:

Deliverable

La prima identità del nodo (che è all'inizio la principale) viene creata dal modulo nel costruttore di IdentityManager. Quando il costruttore ha finito, l'utilizzatore del modulo può da subito invocare il metodo get_main_id di IdentityManager per ottenere il NodeID relativo a tale identità.

L'utilizzatore del modulo chiede alla istanza di IdentityManager di associare ad una sua identità (individuata con il NodeID) un oggetto con un dato nome. La classe IdentityManager è provvista dei seguenti metodi:

La classe IdentityManager è provvista dei seguenti metodi per fornire all'utilizzatore del modulo informazioni sul suo stato attuale. Si vedano sotto i dettagli sulle associazioni mantenute in memoria nel modulo.

La classe IdentityManager è provvista dei seguenti metodi per svolgere delle operazioni su richiesta dell'utilizzatore del modulo:

La classe IdentityManager è provvista dei seguenti segnali per notificare degli eventi all'utilizzatore del modulo:

Dettagli

Associazioni

L'elenco dev_list dei nomi delle interfacce di rete reali attualmente gestite dal nodo è tenuto in una lista (ArrayList) di stringhe.

L'elenco arc_list degli archi attualmente realizzati dal nodo con i suoi vicini è tenuto in una lista (ArrayList) di oggetti che implementano l'interfaccia IIdmgmtArc.

Ogni volta che un arco gli viene comunicato, il modulo produce una stringa con la quale può univocamente identificarlo. Ad esempio un contatore. Quindi realiziamo un metodo arc_to_string che restituisce per una istanza di IIdmgmtArc una stringa univoca, sebbene la classe che rappresenta un arco non è nota al modulo.

L'elenco id_list delle identità attualmente presenti è tenuto in una lista (ArrayList) di oggetti Identity.

Ogni istanza di Identity può essere espressa come una stringa univoca. Cioè ha un metodo to_string che produce una stringa che può essere usata per identificare l'istanza.


L'associazione namespaces tra una identità id0 e il suo namespace è realizzata con un dizionario (HashMap) che ha per chiave la stringa prodotta dal to_string della identità id0.


Per ogni identità, per ogni interfaccia di rete reale gestita dal nodo, il modulo mantiene alcune informazioni (dev, mac, linklocal) in una struttura chiamata HandledNic. Sono i dati della pseudo-interfaccia costruita su quella interfaccia di rete reale (oppure i dati di quella vera) gestita da quella particolare identità del nodo.

L'associazione handled_nics tra una coppia id0-devi (una identità e una interfaccia di rete reale) e la relativa istanza di HandledNic è realizzata con un dizionario (HashMap) che ha per chiave la stringa prodotta dal to_string della identità id0 seguita da "-" e dal nome dell'interfaccia di rete reale.


Per ogni identità, per ogni arco realizzato dal nodo, il modulo mantiene un contenitore di istanze di IdentityArc. Ogni IdentityArc è una struttura dati con alcune informazioni (peer_nodeid, peer_mac, peer_linklocal). Sono i dati della interfaccia di rete (che può essere vera o pseudo) gestita da una particolare identità del nodo vicino raggiunto con quello specifico arco. Se esiste nel contenitore una istanza di IdentityArc significa che esiste un arco-identità tra i due nodi.

L'associazione identity_arcs tra una coppia id0-arc0 (una identità e un arco) e il relativo contenitore di istanze di IdentityArc è realizzata con un dizionario (HashMap) che ha per chiave la stringa prodotta dal to_string della identità id0 seguita da "-" e dalla stringa prodotta dal metodo arc_to_string applicato all'arco arc0.

Duplicazione di una identità

Quando sul manager viene chiamato il metodo prepare_add_identity(migration_id, old_id), esso crea una istanza non completamente valorizzata della classe MigrationData. Tale classe ha un flag booleano ready che viene impostato a False per indicare appunto che non è stata valorizzata. Ma subito sono valorizzati i campi migration_id e old_id, proprio per riconoscere di quale migrazione si sta tenendo traccia con questo oggetto.

Questa struttura dati viene messa in una variabile che può essere acceduta da altre tasklet, come quelle che risponderanno ai metodi remoti del manager. Dopo di ciò il metodo prepare_add_identity, che restituisce void, fa ritorno.

L'istanza di MigrationData deve rimanere in memoria per un tempo limitato, sufficiente a garantire che tutti i nodi diretti vicini hanno completato la migrazione in oggetto. Possiamo dire, ad esempio, che dopo 10 minuti dalla chiamata prepare_add_identity può essere rimossa in sicurezza.

Quando sul manager viene chiamato il metodo add_identity(migration_id, old_id), il manager avvia un dialogo nel modulo Identities fra il nodo e i suoi vicini. Illustriamo ora tale dialogo nel dettaglio.

Indichiamo con idj il vecchio identificativo passato a parametro old_id. A fronte di tale richiesta, il manager genera un nuovo identificativo idi per la nuova identità. Aggiunge la nuova identità a id_list. Poi crea un nuovo network namespace ntemp. Assegna alla vecchia identità idj il nuovo network namespace e alla nuova identità idi il namespace nold che prima era assegnato a idj. Concretamente, questo scambio di assegnazioni avviene modificando i valori dell'associazione namespaces mantenuta dal modulo.

Questo significa anche che se idj era la precedente identità principale, ora non lo è più e lo è diventata l'identità idi. Quindi può essere necessario modificare anche il valore di main_id.

Poi il manager, per ogni interfaccia di rete reale r che il nodo gestisce, tramite il netns-manager costruisce una nuova pseudo-interfaccia p(r) sopra r e la sposta nel network namespace ntemp. Inoltre il modulo assegna a p(r) un nuovo indirizzo IP link-local scelto a caso. Avviene anche qui uno scambio. Il manager assegna alla vecchia identità idj le nuove pseudo-interfacce di rete e alla nuova identità idi le interfacce (reali o pseudo) che prima erano assegnate a idj. Concretamente, questo scambio di assegnazioni avviene modificando i valori dell'associazione handled_nics mantenuta dal modulo.

Il manager adesso può popolare del tutto l'istanza di MigrationData e raccoglie in essa le seguenti informazioni:

Qui termina una prima fase delle operazioni di add_identity nel nodo corrente. Indichiamola con il termine fase di raccolta dati. Il nodo può vedere che è terminata (ad esempio da un'altra tasklet) proprio esaminando il membro ready dell'oggetto MigrationData.

Ora il manager prende in esame ad uno ad uno tutti gli archi-identità che partono dalla identità idj e compie alcune operazioni. Ci sono due parti: una prima parte in cui le operazioni coinvolgono solo il nodo corrente. Una seconda parte in cui ci sono da fare delle comunicazioni coi diretti vicini, quindi occorre che il nodo sia preparato a gestire comportamenti imprevisti e/o scorretti da parte dei vicini.

Raggruppiamo i vari archi-identità in base all'arco su cui sono formati. Questo perché se riscontriamo un problema nelle comunicazioni attraverso un arco quell'arco va rimosso e con lui tutti gli archi-identità collegati. Quindi non ha senso proseguire le operazioni su altri eventuali archi-identità formati sullo stesso arco.

Per ogni arco arc in arc_list:

Al termine delle operazioni, il metodo add_identity restituisce l'identificativo della nuova identità.

Aggiunta o rimozione di una interfaccia di rete reale gestita dal nodo

Il metodo add_handled_nic(dev, mac, linklocal) viene richiamato dall'utilizzatore del modulo per segnalare che d'ora in poi una nuova interfaccia di rete reale sarà gestita dal nodo. Sono passati il nome, il MAC address e l'indirizzo link-local di questa interfaccia reale.

Il manager crea con questi dati una istanza di HandledNic e la aggiunge alla associazione handled_nics ma solo per l'identità principale main_id e dev.


Il metodo remove_handled_nic(dev) viene richiamato dall'utilizzatore del modulo per segnalare che d'ora in poi una certa interfaccia di rete reale, che prima era stata segnalata come gestita, non sarà più gestita dal nodo. Viene passato solo il nome di questa interfaccia reale.

Il modulo assume che l'utilizzatore, prima di chiamare questo metodo, aveva rimosso tutti gli archi che erano formati su questa interfaccia, con il metodo remove_arc. Tale metodo, come è descritto nel relativo paragrafo, scatena la rimozione di tutti gli archi-identità.

Il manager, per ogni identità id in id_list tranne la principale main_id:

Poi il manager rimuove l'interfaccia dall'associazione handled_nics dell'identità principale.

Infine rimuove l'interfaccia dalla lista devs_list.

Il manager può ritrovarsi anche senza alcuna interfaccia di rete reale gestita. Non prende iniziative a tal riguardo.

Aggiunta o rimozione di un arco

Il metodo add_arc(arc) viene richiamato dall'utilizzatore del modulo per segnalare la presenza di un arco formato dal nodo con un suo diretto vicino. Viene passata una istanza di IIdmgmtArc arc.

Il manager memorizza l'arco in arc_list.

Il manager, per ogni sua identità id, mette una lista vuota di IdentityArc in identity_arcs associato alla coppia id-arc.

In seguito il manager può usare l'arco per ottenere uno stub e comunicare con il diretto vicino. Inoltre tramite l'oggetto arco può anche vedere la propria interfaccia di rete reale su cui esso è costruito e l'indirizzo link-local del nodo vicino sull'interfaccia di rete reale in cui è raggiunto tramite questo arco. Attraverso queste informazioni il modulo in autonomia forma sopra questo arco il primo arco-identità principale.

Il modulo fa questa operazione in questo modo:


Il metodo remove_arc(arc) viene richiamato dall'utilizzatore del modulo per segnalare che un arco non è più valido. Viene passata una istanza di IIdmgmtArc arc.

Compito di questo metodo è rimuovere tutti gli archi-identità che esistono su questo arco. Vanno rimossi dalle associazioni che il modulo mantiene gli archi-identità formati su questo arco. Per ogni arco-identità tranne l'arco-identità principale di arc, si deve usare il netns-manager per rimuovere il collegamento diretto nel relativo network namespace.

La rimozione del collegamento diretto per l'arco-identità principale nel network namespace default non è compito del modulo Identities.

Il manager fa queste operazioni:

Infine, il manager rimuove l'arco da arc_list.

Aggiunta o rimozione di un arco-identità su richiesta dell'utilizzatore

Il metodo add_identity_arc(arc, id, peer_id, peer_mac, peer_linklocal) aggiunge un arco-identità sopra un arco. La prima chiamata a questo metodo relativamente all'arco arc avviene in modo automatico quando il nodo segnala la presenza di arc con il metodo add_arc. In questa chiamata viene richiesta la realizzazione dell'arco-identità principale dell'arco arc.

Il modulo in questo metodo deve saper riconoscere che l'arco-identità richiesto è l'arco-identità principale di arc. Perché in questo caso l'aggiunta del nuovo arco-identità non deve comportare la realizzazione con il netns-manager di un nuovo collegamento diretto. Infatti il modulo assume che il collegamento diretto tra i relativi indirizzi link-local che concretizza l'arco-identità principale di un arco arc è stato realizzato (sul network namespace default) senza il suo intervento.

Ovviamente il modulo sa verificare se l'identità id nel suo nodo è quella principale. Per verificare se l'identità peer_id nel nodo vicino è quella principale il modulo usa il metodo get_peer_linklocal dell'oggetto arc e lo confronta con l'argomento passato peer_linklocal e se coincidono allora assume che peer_id nel nodo vicino è la principale. Se entrambe le identità risultano essere la principale del nodo, allora l'arco-identità richiesto è l'arco-identità principale di arc.

Di norma l'utilizzatore del modulo non chiama mai esplicitamente questo metodo. Infatti l'arco-identità principale viene aggiunto automaticamente. Gli altri archi-identità vengono realizzati in autonomia dal modulo a seguito di una migrazione.

Tuttavia il modulo non vieta al suo utilizzatore di richiedere esplicitamente la realizzazione sopra un arco arc di un arco-identità diverso da quello che collega le due identità principali.

Riguardo gli archi-identità aggiunti in autonomia dal modulo, nel dettaglio possono esserci due casi:

Fatta questa premessa, il manager in questo metodo aggiunge il nuovo arco-identità alle sue associazioni. Se necessario, cioè se non si tratta dell'arco-identità principale di arc, usa il netns-manager per realizzare un nuovo collegamento diretto.


Il metodo remove_identity_arc(arc, id, peer_id) rimuove un certo arco-identità.

Di norma, se è l'utilizzatore del modulo a fare questa esplicita richiesta, la richiesta non riguarda l'arco-identità principale di arc.

Ci sono altre situazioni in cui questo metodo può venire chiamato:

Fatta questa premessa, il manager in questo metodo rimuove l'arco-identità dalle sue associazioni. Usa se necessario, cioè se non si tratta dell'arco-identità principale di arc, il netns-manager per eliminare un collegamento diretto.

Il manager fa queste operazioni:

Rimozione di una identità di connettività

Il metodo remove_identity(id) può essere chiamato dall'utilizzatore del modulo per rimuovere una certa identità di connettività.

Questo non può essere fatto per l'identità principale. Il modulo lo controlla: se riceve questa richiesta abortisce il programma.

Il manager in questo metodo: