Modulo Neighborhood - Requisiti / Dipendenze

INeighborhoodIPRouteManager

Tramite l'oggetto che implementa questa interfaccia dovrà essere possibile apportare delle modifiche al sistema. Per un sistema Linux ad esempio, dotato del software iproute, questo si traduce nell'esecuzione di questi comandi:

Metodi

Comandi

i_neighborhood_add_address

 ip address add 169.254.1.1 dev wlan0  

i_neighborhood_add_neighbor

 ip route add 169.254.22.33 dev wlan0 src 169.254.1.1  

i_neighborhood_remove_neighbor

 ip route del 169.254.22.33 dev wlan0 src 169.254.1.1  

i_neighborhood_remove_address

 ip address del 169.254.1.1/32 dev wlan0  

INeighborhoodNetworkInterface

Tramite l'oggetto che implementa questa interfaccia dovrà essere possibile misurare il RTT tra l'interfaccia di rete dev_a del nodo a e l'interfaccia di rete dev_b del nodo b. Se il nodo a è quello che inizia la procedura, il modulo Neighborhood in esso comunica (preferibilmente via TCP che è reliable) un numero random guid al modulo nel nodo b. Immediatamente il modulo nel nodo b richiama su questo oggetto il metodo  i_neighborhood_prepare_ping(guid) . Dopo circa un secondo il modulo Neighborhood nel nodo a richiama su questo oggetto il metodo  i_neighborhood_get_usec_rtt(guid)  ed ottiene la misura del RTT. Tutto il resto dell'implementazione è a carico dell'oggetto passato al modulo.

L'istanza di questo oggetto passato al modulo è legata alla specifica interfaccia di rete (dev_a nel nodo a, dev_b nel nodo b del nostro esempio). Essa ha un riferimento all'istanza di UDPServer (libreria ZCD) che è associata a quel device, sia in scrittura che in ascolto. E' tramite l'uso delle API di questa libreria che l'oggetto svolge il suo compito.

Modifiche alla libreria ZCD

L'oggetto nel nodo b, associato al device dev_b, richiama un metodo sul relativo UDPServer con il quale lo informa che sta per ricevere un messaggio PING_XXX dove XXX è il numero guid. L'UDPServer inserisce il messaggio indicato in una collezione.

Dopo circa 1 secondo l'oggetto nel nodo a, associato al device dev_a, richiama un metodo sul relativo UDPServer che inizia la procedura di 'ping' descritta di seguito con il valore guid. L'UDPServer in questo metodo inserisce il messaggio PONG_XXX in una collezione. Poi invia sul device interessato il messaggio PING_XXX in broadcast UDP. Inoltre registra un Channel che sarà messaggiato alla ricezione del PONG, e si mette in attesa su quel channel. Quando il nodo b riceve il messaggio PING, il metodo handle_request del suo UDPServer verificherà per prima cosa che il messaggio sia un PING atteso. Se lo è invia sul device interessato il messaggio PONG_XXX in broadcast UDP e rimuove dalla lista degli attesi il PING_XXX. Quando il nodo a riceve il messaggio PONG, il metodo handle_request del suo UDPServer verificherà per prima cosa che il messaggio sia un PONG atteso. Se lo è messaggia il Channel precedentemente registrato. A questo punto il metodo che era stato inizialmente chiamato sul UDPServer del nodo a va a terminare, misurando il RTT.

Questo giro consente di evitare gran parte dell'overhead introdotto dalla libreria 'ZCD' nelle chiamate a metodi remoti, ottenendo quindi un RTT più accurato.

Nota: se la misurazione del RTT va in timeout il metodo di UDPServer restituisce un'eccezione ChannelError. L'oggetto che implementa INeighborhoodNetworkInterface la traduce in un'eccezione NeighborhoodGetRttError, che è prevista dalla firma del metodo i_neighborhood_get_usec_rtt. Il modulo Neighborhood non elabora questa misurazione fallita, senza per questo rimuovere l'arco, in quanto l'UDP è di natura un protocollo non reliable.

INeighborhoodStubFactory - metodo i_neighborhood_get_broadcast

Usando questo metodo sull'oggetto che implementa questa interfaccia il modulo potrà indicare una istanza dell'interfaccia IAcknowledgementsCommunicator per ricevere dopo il timeout la lista dei MAC address che hanno segnalato con un ACK la ricezione del messaggio.

Modifiche alla libreria ZCD

La libreria 'ZCD', quando usata per l'invio di messaggi in broadcast, offre la possibilità di ricevere un acknowledgement dai nodi che ricevono correttamente il messaggio. Infatti l'invio del messaggio in UDP non garantisce la sua ricezione. Va detto che anche il messaggio di ACK potrebbe perdersi, ma in generale avere la certezza della ricezione o in caso contrario il dubbio è sufficiente.

Gran parte delle operazioni necessarie per questa feature sono svolte dalla libreria ZCD.

Per tutti i messaggi in broadcast viene inviato un pacchetto ACK dai nodi che lo ricevono.

Il nodo che invia il messaggio crea un'istanza dell'oggetto UDPMessage. L'istanza genera un identificativo di 10 cifre con  Random.int_range(1000000000, 1999999999)  di modo che entri in un int32 e abbia una rappresentazione a stringa di sempre 10 cifre.

Il nodo che riceve il messaggio, quando ha ricomposto l'oggetto UDPMessage, compone il messaggio  ACK_1234567890_CC:AF:78:2E:C8:B6 . I caratteri da 4 a 13 sono l'identificativo della UDPMessage ricevuta. I caratteri da 15 a 31 sono il MAC dell'interfaccia su cui la UDPMessage è stata ricevuta, in maiuscolo e con il separatore ':'. Quindi invia il messaggio in broadcast UDP sulla stessa interfaccia di rete.

Un generico BroadcastClient (o uno specifico, per esempio AddressManagerBroadcastClient) nel costruttore può ricevere e memorizzare una istanza della interfaccia IAcknowledgementsCommunicator. Questa specifica il metodo 'prepare()' che restituisce un oggetto 'Tasklets.Channel'.

Chi vuole inviare un messaggio quindi può istanziare una sua classe che implementi questo metodo. Esso viene chiamato quando sul BroadcastClient viene invocato un metodo remoto; il chiamante fa in modo che questo metodo prepari un Channel. Poi l'invio del messaggio avviene e 'ZCD' si occupa di stare attento a quali MAC segnalino entro un certo tempo con un ACK la ricezione del messaggio. Al termine di questo tempo 'ZCD' segnala questo elenco di MAC inviando la lista in un unico messaggio attraverso il Channel suddetto.