1. Scuola Politecnica e delle Scienze di Base
Corso di Laurea in Ingegneria Informatica
Elaborato di Computer Networks Design and Management:
Realizzazione controllore SDN tramite
Ryu, in configurazione di rete emulata con
Mininet-Wifi
Anno Accademico 2021-22
Proff.
Alessio Botta
Giorgio Ventre
Candidati
Carmine Pio D’Antuono M63001224 (carm.dantuono@studenti.unina.it)
Marco Vaiano M63001186 (marc.vaiano@studenti.unina.it)
2. Sommario
Realizzazione controllore SDN tramite Ryu, in configurazione di rete emulata con Mininet-Wifi.....I
Parte 1: Riduzione del packet loss in scenario handover.................................................................3
1.1 Soluzione................................................................................................................................4
1.2 Risultato .................................................................................................................................6
Parte 2: Gestione della ridondanza tramite Spanning Tree..............................................................7
2.1 Domande................................................................................................................................7
2.2 Soluzione................................................................................................................................8
2.3 Risultato ...............................................................................................................................11
3. 3
Parte 1: Riduzione del packet loss in scenario handover
In seguito allo studio del codice sub-ottimo ricevuto, abbiamo deciso di analizzare il
traffico relativo ai pacchetti inviati dalla stazione 1 denominata “sta1” per raggiungere
la stazione 2 “sta2” che effettua un movimento casuale collegandosi, in base alla
propria posizione, ad uno tra l’access point “ap1” e l’access point “ap2”.
L’analisi è stata effettuata dapprima con il comando shell tcpdump, ma poi si è optato
per l’utilizzo di un’interfaccia grafica per favorire la visualizzazione di tali pacchetti,
per tale scopo è stato utilizzato il software Wireshark.
Grazie all’ausilio di wireshark abbiamo notato due dinamiche di interesse.
La prima che abbiamo osservato è legata ai pacchetti ICMP di request e reply in
seguito alla richiesta dei messaggi di ping dalla sta1 verso la sta 2: quando la sta2 è
collegata a uno dei due access point la ricezione dei pacchetti avviene con precisione e
di conseguenza anche l’invio dei pacchetti ICMP, ma non appena la sta2 si stacca da
uno dei due access point e si trova fuori dal raggio di copertura di uno dei due oppure
mentre si sta riconnettendo ad un altro (in seguito alla disassociazione dal precedente),
i pacchetti ICMP non giungeranno a destinazione riscontrando la perdita del pacchetto
di reply il quale viene segnalato come “risposta non trovata” dal software Wireshark.
4. 4
La seconda dinamica osservata è legata al meccanismo di connessione della sta2 verso
gli access point 1 e 2. Tale condizione si può riscontrare anche senza lanciare il
comando “ping” tra le due stazioni. È possibile in questo caso visualizzare dei
messaggi in broadcast di tipo LLC (logical link control) che sono riferiti a quando la
sta2 si disassocia da un access point ed è in procinto di connettersi verso l’altro access
point (o lo stesso, entrando e uscendo dal range di copertura). Tali messaggi sono LLC
di tipo 1 ovvero, un frame che permette soltanto di effettuare la spedizione del traffico
verso il destinatario, ma senza alcun tipo di garanzia né di risposta.
1.1 Soluzione
Abbiamo, dunque, deciso di ottimizzare il codice del controllore ricevuto sfruttando la
seconda dinamica esaminata.
Quando la stazione 2 si associa a uno dei due access point viene creata nell’access
point 3 (generatore) una flow table contenente le varie entries che permettono l’inoltro
del pacchetto a destinazione. In seguito allo spostamento randomico, la stazione si
disconnette da un access point causando, sia la perdita dell’eventuale pacchetto ICMP
che il disaccoppiamento, il quale quest’ultimo provoca l’invio di messaggi LLC in
broadcast (ff:ff:ff:ff:ff:ff) da parte dell’AP3 (sorgente 00:00:00:00:00:00:03). Di
conseguenza, abbiamo provato a cancellare la regola di inoltro verso la stazione 2,
precedentemente utilizzata, per inviare una nuova richiesta in broadcast e far sì che
l’access point 3 potesse apprendere la nuova rotta come nel caso di setup iniziale. In
questo caso il messaggio mandato in broadcast viene inviato solo quando necessario in
5. 5
modo tale da poter sia ridurre la perdita dei pacchetti, ma anche di non sovraccaricare
la rete con continui messaggi di broadcast generando ulteriore overhead.
L’implementazione risulta abbastanza semplice: si effettua l’analisi dei pacchetti e
quando viene rilevato un pacchetto LLC, il controller rileva se si tratta di un frame di
formato XID1
. Tale frame è utilizzato dai nodi finali per scambiarsi degli identificatori,
dunque, quando la stazione 2 si connette a uno dei due access point questa diventa una
situazione di rilievo e tale si può verificare attraverso un costrutto condizionale (“if”)
in cui si fa un controllo per i campi DSAP e SSAP2
del protocollo LLC per verificare
se si tratta di pacchetti del protocollo XID oppure di un differente approccio. Se tale
condizione è verificata vengono resettate le entries nella flow table dell’AP che ha
generato il pacchetto.
Sub Protocol DSAP SSAP CF OC PID
XID 0x00 0x01 0xAF null null
CDP 0xaa 0xaa 0x03 0x00000c 0x2000
DTP 0xaa 0xaa 0x03 0x00000c 0x2004
STP 0x42 0x42 0x03 null null
In base a tale condizione si può notare che per il protocollo XID si necessita di:
DSAP=0x00 e SSAP=0x01.
Tale condizione è verificabile via codice:
1
eXchange ID
2
Fonte: https://github-wiki-see.page/m/luongnv89/blog/wiki/logical-link-control
if pkt_llc: #dst in questo caso e' broadcast
self.logger.info("Frame LLC rilevato")
if pkt_llc.dsap_addr==0x00 and pkt_llc.ssap_addr==0x01:
self.logger.info("Elimino tutti i flussi")
datapath.send_delete_all_flows()
out_port = ofproto.OFPP_FLOOD
out_port = ofproto.OFPP_FLOOD
6. 6
1.2 Risultato
Grazie a tale modifica del codice siamo riusciti ad ottenere dei risultati soddisfacenti.
In seguito a diverse prove (sia brevi che lunghe), ovvero rispettando le specifiche
richieste, i risultati della packet loss si sono assestati al di sotto del 15%.
In particolare, nel caso richiesto in cui la stazione 1 invia dei messaggi di ping ICMP
verso la stazione 2 in una comunicazione di durata complessiva di 15 minuti, si può
notare che la packet loss è del 11% a fronte di 2988 pacchetti trasmessi.
7. 7
Parte 2: Gestione della ridondanza tramite Spanning Tree
Per assicurarsi che la rete in questione sia robusta ad eventuali guasti su
link/interfacce, si è deciso di migliorare la reliability della stessa aggiungendo un
grado di ridondanza, ovvero aggiungendo un link anche tra l’AP1 e l’AP2
2.1 Domande
1. Perché adesso la rete è più robusta?
Introducendo il grado di ridondanza, si ottiene una topologia ad anello della rete grazie
a cui viene risolto il problema di un’eventuale caduta di un link. Grazie alla ridondanza
risulta pertanto possibile inoltrare il messaggio non più sul link diretto, ma attraverso
l’altro percorso disponibile permettendo comunque di arrivare a destinazione,
nonostante eventuali ritardi.
2. Il controller progettato per l’esercizio precedente funziona lo stesso? Se sì,
perché? Se no, perché?
Il controller progettato per l’esercizio precedente non funziona per la nuova topologia
di rete. In questa, infatti, l’access point 3 genera e invia pacchetti in flooding verso
tutti gli access point che sarà poi inoltrato a sua volta da tutti gli altri access point
generando una situazione di loop.
8. 8
3. Cosa succede se ad un certo punto il link tra ap2 e ap3 va down?
Se a un certo punto il link tra ap2 e ap3 va down, si potrebbe dire che la topologia
cambi logicamente riportando l’ap1 in una situazione centrale e consentendo quindi
anche il collegamento tra l’ap3 e l’ap2 tramite un percorso indiretto. Di conseguenza,
l’access point permetterebbe di inoltrare i pacchetti provenienti dall’ap2 con
destinazione ap3, passando per ap1.
2.2 Soluzione
Per risolvere la problematica proposta abbiamo deciso di utilizzare il protocollo di
Spanning Tree (802.1D).
Lo spanning tree prevede la costruzione di un albero utilizzando i nodi della rete
circolare, in modo da evitare che il costante invio di pacchetti broadcast causino
l’invasione dei pacchetti inviati in loop tra gli switch.
L’implementazione logica di uno spanning tree avviene in tre fasi fondamentali:
1. Bisogna selezionare il root bridge. Ogni bridge (switch) è identificato da un id di 8
byte di cui i primi due indicano un livello di priorità e gli altri sono identificativi
dell’indirizzo MAC. Viene, dunque, selezionato come root bridge il nodo radice a
cui viene impostato l’id più basso. Grazie a tale selezione l’unico bridge capace di
generare pacchetti sarà quello con la priorità inferiore, mentre gli altri potranno
solo effettuare l’operazione di inoltro.
2. Ciascuna interfaccia su ogni bridge deve avere un ruolo per la definizione dello
spanning tree in base ai costi con cui si raggiunge il root bridge:
• Root port: il porto con il minor costo tra le varie interfacce per raggiungere il
root bridge. Tale porto riceve direttamente i pacchetti generati dal root
bridge;
• Designated ports: i porti con costo basso utilizzati per raggiungere il nodo
radice e utilizzati per inviare i pacchetti ricevuti dal root bridge (tutti i porti
del root bridge sono di questa tipologia);
• Non-designated ports: altri porti che sopprimono la ricezione e l’invio dei
9. 9
pacchetti.
Un tipico scenario è riportato nella seguente immagine:
3. Scelti i diversi ruoli per i porti, è completata la configurazione dello spanning tree.
L’algoritmo procede quindi a definire lo stato dei diversi porti. Tutti i porti si
troveranno inizialmente nello stato LISTEN, dopodiché cambieranno ruolo in base
al seguente diagramma degli stati:
Grazie a cui è possibile definire i diversi stati:
• DISABLE − porto disabilitato sia in ingresso che in uscita
• BLOCK − riceve solo pacchetti BPDU
• LISTEN − trasmette e riceve pacchetti BPDU
• LEARN − trasmette e riceve pacchetti BPDU, apprende MAC
• FORWARD − trasmette e riceve pacchetti BPDU, apprende MAC e trasferisce
frame
10. 10
Abbiamo tradotto in codice Python le informazioni relative alla configurazione dello
spanning tree descritte in precedenza, apportando le modifiche adeguate che ci
permettessero di farlo funzionare con il controller Ryu attraverso l’utilizzo della
libreria stplib.
Il primo passo è stato quello di dare le diverse priorità ai bridge, designando il root
bridge all’ap3 con priorità minore: 0x800 e configurando gli altri due AP con priorità
maggiore. Inoltre, in tale configurazione si sono settati i valori dell’attributo fwd_delay
a 1 secondo in modo da velocizzare la transizione tra stati di LISTEN e LEARN
relativi alle porte dei bridge. In questo modo siamo riusciti a ridurre il tempo di setup
dello spanning tree.
In seguito alla configurazione degli AP, abbiamo utilizzato ugualmente la soluzione di
instradamento ottima dei pacchetti implementata per la parte 1 dell’elaborato
(pacchetti LLC per rilevare il passaggio della STA2 tra i diversi AP).
Abbiamo inoltre usufruito di una struttura dati di tipo dizionario map in cui si inserisce
lo stato di ciascuna porta in base alla descrizione vista nello schema precedente.
Quindi, alla modifica dello stato di una porta, questo viene salvato nella struttura map
denominata “stato_porte” insieme all’identificativo del bridge, in modo tale da poter
successivamente gestire l’inoltro dei pacchetti solo se la porta è nello stato
FORWARD riducendo quindi le entries nell’array delle associazioni mac-porta e
permettendo così il filtraggio delle diverse porte sulle varie interfacce.
config = {dpid_lib.str_to_dpid('1000000000000003'):
{'bridge': {'priority': 0x8000,'fwd_delay': 1}},
dpid_lib.str_to_dpid('1000000000000001'):
{'bridge': {'priority': 0xa000,'fwd_delay': 1}},
dpid_lib.str_to_dpid('1000000000000002'):
{'bridge': {'priority': 0x9000, 'fwd_delay': 1}}}
self.stp.set_config(config)
11. 11
if self.stato_porte[dpid][msg.in_port] == stplib.PORT_STATE_FORWARD:
self.mac_to_port[dpid][src] = msg.in_port
…………
@set_ev_cls(stplib.EventPortStateChange, MAIN_DISPATCHER)
def _port_state_change_handler(self, ev):
# Memorizzo lo stato della porta in una struttura map
self.stato_porte.setdefault(ev.dp.id, {})
self.stato_porte[ev.dp.id][ev.port_no] = ev.port_state
dpid_str = dpid_lib.dpid_to_str(ev.dp.id)
of_state = {stplib.PORT_STATE_DISABLE: 'DISABLE',
stplib.PORT_STATE_BLOCK: 'BLOCK',
stplib.PORT_STATE_LISTEN: 'LISTEN',
stplib.PORT_STATE_LEARN: 'LEARN',
stplib.PORT_STATE_FORWARD: 'FORWARD'}
self.logger.debug("[dpid=%s][port=%d] state=%s",
dpid_str, ev.port_no,of_state[ev.port_state])
Grazie a tale modifica, inizialmente, i pacchetti circoleranno non tenendo conto del
link presente tra ap2 e ap3 in quanto aventi porte in stato BLOCK, ma nel caso ci
fossero problemi di connettività in uno degli altri link, le porte su quell’interfaccia
diventerebbero “designated” in modo tale da salvaguardare l’inoltro dei pacchetti e
facendoli pertanto fluire sul percorso alternativo a quello originario.
2.3 Risultato
Tale codice è stato testato su intervalli di varia durata fornendoci risultati sempre
positivi in termini di riduzione della packet loss. In particolare, abbiamo esaminato il
caso in cui l’invio dei pacchetti inizialmente avveniva su topologia base, ovvero con i
3 link “up”, dopo 8 minuti e successivamente il link tra ap2 e ap3 diventa down, ne
consegue che entra in gioco l’algoritmo di spanning tree in modo da ripristinare la
situazione e abilitare logicamente il link tra ap2 e ap1.
Il risultato ottenuto in questo caso è stato del 12% di packet loss a fronte di 2965
pacchetti ICMP inviati in 15 minuti secondo la modalità descritta poc’anzi.