Oggi
mi trovo con piacere ad essere ospite di questa isola felice di condivisione, messa in piedi e portata avanti dal mio esimio collega Tiziano Tofoni (alias, l’Ammiraglio Tofonoto),
per ampliare un po’ il discorso sul protocollo OpenFlow, iniziato con questo post sul ruolo del BGP e MPLS nell'era SDN.
UN PO’ DI STORIA
Come ogni cosa, è bene partire
dall’inizio (o come dicono gli inglesi “first
things first”). L’idea del protocollo OpenFlow nasce dalle fucine
dell’università di Stanford nel non troppo lontano 2008, portandosi
all’attenzione del grande pubblico con un whitepaper carico di sogni e speranze
dal titolo: “OpenFlow: Enabling Innovation in Campus Networks” (openflow-wp-latest.pdf).
Obiettivo di questo articolo era di proporre ai produttori di apparati di rete, un modo per influenzare i meccanismi di forwarding di uno switch Ethernet, tramite la manipolazione di regole personalizzate di instradamento. Questo procedimento avrebbe aiutato i ricercatori nello studio e nel testing di nuovi protocolli, in una rete reale e di produzione. Il tutto senza la necessità di aprire le implementazioni proprietarie del piano di controllo degli apparati in commercio, ma semplicemente implementando un nuovo protocollo: OpenFlow appunto.
Obiettivo di questo articolo era di proporre ai produttori di apparati di rete, un modo per influenzare i meccanismi di forwarding di uno switch Ethernet, tramite la manipolazione di regole personalizzate di instradamento. Questo procedimento avrebbe aiutato i ricercatori nello studio e nel testing di nuovi protocolli, in una rete reale e di produzione. Il tutto senza la necessità di aprire le implementazioni proprietarie del piano di controllo degli apparati in commercio, ma semplicemente implementando un nuovo protocollo: OpenFlow appunto.
L’idea era di poter accedere alle tabelle di
gestione dei flussi (flow table) già
presenti nella maggior parte dei prodotti commerciali di diversi vendor, tramite
un’interfaccia standard e open source. Così facendo, si sarebbe potuto avere un
controllo sul traffico tale da poter maneggiare separatamente dei flussi
sperimentali, lasciando inalterato il traffico di produzione. Già da questo
primo articolo troviamo la presenza di un controllore esterno alla macchina ed
una prima architettura di uno switch OpenFlow, come mostrato nella figura seguente.
Venne quindi costituito l’OpenFlow Consortium (poi confluito nel Open Networking Foundation, ONF) a cui venne demandato il compito di mantenere e supportare lo sviluppo di OpenFlow. A distanza di un anno da questo primo articolo, nel dicembre del 2009, venne infine rilasciata la prima versione stabile, di OpenFlow, la 1.0 (openflow-spec-v1.0.0.pdf).
(Figura tratta da OpenFlow® Switch Specification 1.0.0)
|
Venne quindi costituito l’OpenFlow Consortium (poi confluito nel Open Networking Foundation, ONF) a cui venne demandato il compito di mantenere e supportare lo sviluppo di OpenFlow. A distanza di un anno da questo primo articolo, nel dicembre del 2009, venne infine rilasciata la prima versione stabile, di OpenFlow, la 1.0 (openflow-spec-v1.0.0.pdf).
OPENFLOW SWITCH
L’attuale “standard” dello switch OpenFlow è
la versione 1.5.1, uscita giusto un anno fa, nel marzo del 2015 (openflow-switch-v1.5.1.pdf).
Prenderò a riferimento questa versione nelle successive descrizioni del
protocollo.
Tirando le somme, cerchiamo di dare una definizione di OpenFlow. L’ONF lo definisce (cito traducendo) come:
“…la prima interfaccia di comunicazione standard tra il
piano di controllo e il piano dati di una architettura SDN. Permette l’accesso
diretto e la manipolazione del piano dati di un dispositivo di rete…”
Questo sposta nettamente il focus lontano dal
testing di nuovi protocolli, e ci fa approdare direttamente nel campo per noi di
maggiore interesse: il Software Defined Networking (SDN) ! Iniziamo quindi a distinguere nel protocollo
OpenFlow due attori:
- Il controller OpenFlow.
- Lo switch OpenFlow.
Il secondo è uno switch logico, costituito delle risorse gestite da OpenFlow. Si distingue ad alto livello in due tipologie: OpenFlow-only e OpenFlow-hybrid. La differenza sta nel fatto che le risorse del primo vengono gestite dal protocollo OpenFlow (completamente!), mentre l’altro ha risorse compatibili con il protocollo OpenFlow, ma è capace di lavorare autonomamente come uno switch comune. Quest’ultimo si avvicina maggiormente all’idea iniziale di quello che si ipotizzava essere uno switch OpenFlow nel whitepaper originale del 2008.
Analizziamo più nel dettaglio la struttura di
queste risorse.
CONTROL CHANNEL
Iniziamo
da qualcosa che conosciamo: il Control Channel. Abbiamo già visto che
l’OpenFlow Channel è il canale attraverso cui il controller e lo switch
OpenFlow riescono a comunicare. Il Control Channel è semplicemente l’insieme
degli OpenFlow Channel (può essere uno, o più di uno, o ... anche nessuno!), e dei
rispettivi controller connessi ad essi. Questa comunicazione tra il controller
e lo switch avviene secondo tre diverse metodologie:
- Controller-to-switch
La comunicazione parte dal
controller e può richiedere o meno una risposta. Di questa categoria fanno
parte quei messaggi che sondano le funzionalità (FEATURES), le configurazioni
(CONFIGURATION) o lo stato (READ-STATE) dello switch. Ma soprattutto fa parte
il messaggio di inoltro di un pacchetto, dal controller verso lo switch
(PACKET-OUT), per permetterne l’instradamento.
- Asynchronous
La comunicazione parte dallo
switch, senza sollecitazioni da parte del controller. Di questa categoria fanno
parte quei messaggi che mantengono aggiornato il controller sullo stato delle
porte (PORT-STATUS) o lo stato dei flussi (FLOW-MONITOR o FLOW-REMOVED). Anche
l’invio di un pacchetto al controller, fa parte di questa categoria (PACKET-IN).
- Symmetric
Questo genere di comunicazioni sono
inoltrate da entrambe le parti senza sollecitazione. Di questa categoria fanno
parte i messaggi di controllo come i ping (ECHO), i keepalive
(HELLO) e i messaggi di errore (ERROR).
PORTE STANDARD
Un’altra
forma di comunicazione che avviene tra lo switch OpenFlow e il mondo esterno è
rappresentata dal traffico circolante tra le OpenFlow Port. Queste sono anche
dette Standard Port e sono l’insieme di tutte le interfacce gestite dallo
switch OpenFlow in ingresso o in uscita. Vengono distinte in tre tipologie:
porte fisiche, porte logiche e porte riservate.
Le
porte fisiche sono interfacce dello switch, con una corrispondenza uno-a-uno con
una interfaccia hardware della macchina. Questo permette, ad esempio, di mettere
in comunicazione diretta lo switch logico con un’interfaccia verso il mondo
esterno. È anche possibile virtualizzare un’interfaccia fisica, riuscendo così a
dedicare una porzione della stessa interfaccia a più porte fisiche
dello switch OpenFlow.
Le
porte logiche sono interfacce, utilizzate dallo switch, completamente astratte.
Non hanno alcuna corrispondenza con una parte dell’hardware. Una porta logica
può implementare una funzionalità di rete come un’interfaccia di loopback, un
tunnel, così come può essere un multiplexer per diverse porte fisiche. La
funzionalità principale è che il loro attraversamento sia totalmente
trasparente al funzionamento dello switch, che deve semplicemente utilizzarle per instradarvi il
traffico.
Infine, le porte riservate sono porte che nascondono una specifica funzionalità di
forwarding. Nella specifica vengono definite alcune porte come Required, cioè da
implementare obbligatoriamente, e alcune come Optional, appunto di carattere
opzionale. La scelta di implementare o meno queste porte, dipende dal
tipo di switch che vogliamo implementare. Nello specifico, implementando o meno
le porte Optional, andiamo a creare uno switch OpenFlow del tipo OpenFlow-hybrid. Ci sono circa 9
tipologie di instradamento previste da queste porte logiche. tra le quali possiamo
annoverare nelle obbligatorie:
- ALL: rappresenta la via verso tutte le interfacce disponibili. Utilizzabile solo in uscita.
- CONTROLLER: rappresenta il canale di comunicazione con il controller in ingresso e in uscita.
e
tra le opzionali:
- NORMAL: rappresenta il canale verso le tabelle di inoltro legacy. In parole povere è la strada da percorrere se si vuole fare gestire questo traffico come su un normale switch.
PIPELINE
Dopo
tutte queste trattazioni architetturali andiamo finalmente a confrontarci con i
meccanismi che ci permetto di lavorare davvero sul traffico. Ovviamente, anche
qui non ci troveremo nessun vecchio amico tra i piedi (vedi spanning tree,
protocolli di routing o chicchessia), ma troveremo altri validi alleati.
Il
traffico che arriva ad uno switch OpenFlow viene veicolato in due canali, o pipeline, attraverso i quali viene
elaborato. Queste due pipeline rappresentano un canale per il traffico entrante, e uno per il traffico uscente, chiamate rispettivamente Ingress processing e Egress
processing.
La pipeline in uscita è stata introdotta proprio con la versione 1.5.1 di OpenFlow, ed è considerata opzionale. L’elaborazione viene gestita da una serie di tabelle chiamate Flow Table. All’interno di queste tabelle vi sono delle regole, chiamate Flow Entry, a cui viene legato un Instruction Set, ossia un insieme di azioni che dovranno essere effettuate al matching con la specifica Flow Entry. Queste istruzioni possono andare a costruire e modificare un insieme di azioni, chiamato appunto Action Set, Il quale, a conclusione della pipeline, viene eseguito applicando le elaborazioni sul traffico.
La pipeline in uscita è stata introdotta proprio con la versione 1.5.1 di OpenFlow, ed è considerata opzionale. L’elaborazione viene gestita da una serie di tabelle chiamate Flow Table. All’interno di queste tabelle vi sono delle regole, chiamate Flow Entry, a cui viene legato un Instruction Set, ossia un insieme di azioni che dovranno essere effettuate al matching con la specifica Flow Entry. Queste istruzioni possono andare a costruire e modificare un insieme di azioni, chiamato appunto Action Set, Il quale, a conclusione della pipeline, viene eseguito applicando le elaborazioni sul traffico.
Ma
andiamo a vedere esattamente cosa succede. Appena un pacchetto arriva nello
switch da una qualsiasi porta di ingresso, viene inserito nella pipeline di ingresso (Ingress processing). In questa pipeline si possono costituire una o più Flow Table. Il traffico
entrerà sempre nella prima tabella, che viene denominata come "0". La Flow Table è
fondamentalmente un contenitore astratto, in cui raggruppare diverse Flow Entry.
Si può dire che il lavoro effettivo di elaborazione dei pacchetti venga fatto
dalle Flow Entry.
Alla fine di ogni Flow Table, è possibile definire anche una Flow Entry speciale chiamata Table-miss, che ha lo scopo di gestire i pacchetti che non hanno avuto alcun matching. La struttura di queste Flow Entry è riportata nella figura seguente.
Alla fine di ogni Flow Table, è possibile definire anche una Flow Entry speciale chiamata Table-miss, che ha lo scopo di gestire i pacchetti che non hanno avuto alcun matching. La struttura di queste Flow Entry è riportata nella figura seguente.
Ogni Flow Entry è costituita da un insieme di 7 elementi:
- Match Fields: la parte dell'insieme in cui si specificano le caratteristiche che deve avere il pacchetto.
- Priority: stabilisce una precedenza tra le Flow Entry.
- Counters: un contatore per le hit sulla Flow Entry.
- Instructions: stabiliscono l’elaborazione da eseguire sul pacchetto.
- Timeouts: il tempo massimo di vita della specifica riga.
- Cookie: può essere usato per elaborazioni statistiche interne al protocollo OpenFlow.
- Flags: possono modificare la gestione di una Flow Entry.
Una Flow Entry è identificata in maniera univoca dai primi due campi: Match Fields e Priority. Andiamo a vedere più nel dettaglio alcuni di questi elementi.
- Uno dei campi più importanti è sicuramente il Match Fields. Qui vengono definiti i parametri per cui un pacchetto appartiene o no ad una determinata Flow Entry. Questi parametri sono importanti poiché ci permettono di determinare cosa filtrare, come e con che granularità. In questo campo possono essere determinati fino a 44 diversi parametri, con i loro rispettivi valori. Un pacchetto viene considerato appartenente ad una Flow Entry se e solo soddisfa tutte le condizioni specificate nel campo Match Fields, (NOTA: questo non significa che le condizioni riguardino tutti i 44 parametri, ma possono essere solo su alcuni di questi). Vediamo alcuni di questi parametri:
Porta
di input dello switch
Indirizzo Ethernet destinazione
Indirizzo Ethernet sorgente
VLAN ID
Indirizzo IPv4 sorgente/ destinazione
Indirizzo IPv6 sorgente/ destinazione
Porta
UDP sorgente/ destinazione
ARP sorgente/destinazione IPv4
ARP sorgente/destinazione IPv6
ARP sorgente/destinazione MAC
MPLS
label
TCP
flag
Code
ICMP
Type
ICMPv6
...
- In caso di matching sovrapposti su due Flow Entry distinte, viene presa in esame la Priority. Come è facile immaginare, con questo valore si stabilisce una priorità in valore assoluto di quale Flow Entry abbia la precedenza su un'altra. Viene rappresentata da un valore numerico di 2 byte (da 0 a 65.535). Al valore maggiore corrisponde una maggiore priorità.
- Determinata a quale Flow Entry appartiene un pacchetto, viene incrementato il valore del campo Counter della Flow Entry.
- A questo punto si eseguono le Instruction contenute nel rispettivo campo. Qui è possibile operare in diversi modi: è possibile ad esempio effettuare modifiche al pacchetto, inoltrarlo verso un'altra Flow Table, modificare il suo Action Set o lavorare su dei metadati. Alcune di queste non devono necessariamente essere implementate sul switch OpenFlow (la modifica al pacchetto, ai metadati e altre). Per quanto riguarda l'invio ad altre Flow Table, è necessario specificare un paio di regole importanti: non è mai possibile far tornare un pacchetto in una Flow Table precedente e, come conseguenza, le Flow Entry dell'ultima tabella non potranno mai inviare il pacchetto ad un'altra tabella. La gestione dell'Action Set è fondamentale in questa fase, in quanto all'interno di questo insieme vengono accumulate tutte le elaborazioni da effettuare sul pacchetto, prima di concludere il suo percorso all'interno della pipeline.
- copy TTL inwards
- pop
- push-MPLS
- push-PBB
- push-VLAN
- copy TTL outwards
- decrement TTL
- set
- qos
- group
- output
CONCLUSIONI
Siamo quindi arrivati in fondo a questa volata sul protocollo e sullo switch OpenFlow. Abbiamo familiarizzato un po' con i concetti e con l'ultima specifica disponibile. Già da questa breve trattazione tecnica, è possibile capire quelli che sono i principi e gli obiettivi che guidano lo sviluppo di OpenFlow.
Lo sviluppo procede, ma le implementazioni languono. Vedremo se OpenFlow riuscirà a far breccia nei nostri cuori o rimarrà quel lontano cugino con cui giocavamo a calcetto da piccoli, ma che non abbiamo mai più visto.
Altri approfondimenti ed altre analisi potrebbero ancora essere fatte, ma le lasciamo ad eventuali futuri post.
Se OpenFlow può leggere/modificare campi quali Mac Address, IP e TTL, è possibile utilizzare uno switch OpenFlow come router?
RispondiEliminaAssolutamente si. In effetti il nome OpenFlow Switch fuorvia un po'. In realtà il termine "switch" andrebbe inteso, non come sinonimo di layer 2, ma nel senso più largo, ovvero smistare. Tecnicamente può smistare dati di qualsiasi tipo. I limiti che ci vengono imposti riguardano solo la tipologia di campi su cui fare match (determinata ferreamente dal protocollo) e le elaborazioni che vi si possono effettuare direttamente, senza cioè passare dal controller esterno.
Elimina