• Non ci sono risultati.

5.3.1

Presentazione del componente

Il modulo myStatsModule.py `e responsabile della raccolta di statistiche da ogni switch connesso al controller. Le statistiche prelevate da uno switch riguardano

1. le porte di cui esso dispone;

2. i flussi presenti all’interno della propria tabella.

La classe che implementa il componente prende il nome di StatsHandler. Come risulter`a chiaro in seguito (paragrafo 5.5), si `e interessati ad ottenere delle stime riguardanti la banda occupata da un certo flusso e la porzione di banda ancora disponibile su un certo link. D’altra parte, come `e gi`a stato osservato nel paragrafo 3.2, le statistiche messe a disposizione dal protocollo OpenFlow forniscono solamente un conteggio relativo al numero di byte (o di pacchetti) ricevuti (o trasmessi), fino all’istante d’interrogazione.

La strategia utilizzata `e dunque la seguente. Il modulo in esame provvede ad interrogare gli switch presenti all’interno della topologia ad intervalli di tempo regolari, la cui durata `e specificata dalla variabile delta, configurabile da riga di comando. In tutti gli esperimenti presentati nel capitolo 7, a tale variabile `e stato assegnato un valore pari a 5 secondi. Indipendentemente dal fatto che si tratti di statistiche di porta o statistiche di flusso, il controller sottrae dal con- tatore attuale il valore prelevato al passo precedente, ottenendo cos`ı la quantit`a di byte (o di pacchetti) ricevuti (o trasmessi) nel corso dell’ultimo intervallo d’interrogazione. Tale quantit`a viene quindi opportunamente scalata e divisa per la durata dell’intervallo, in modo da ricondursi ad un rapporto esprimibile in ‘bit/s’, ‘byte/s’ o ‘pacchetti/s’.

Un approccio di questo tipo fornisce, in realt`a, una media temporale della banda istantanea, calcolata sull’intero intervallo d’interrogazione. Fermo re- stando che metodi diversi non sarebbero comunque praticabili, ottenere uno smoothing della grandezza sotto osservazione non rappresenta necessariamente uno svantaggio. Supponendo, infatti, che alla stima di detta grandezza segua un certo tipo di azione da parte di altri moduli (paragrafo 5.5), un filtraggio passa- basso mitiga l’effetto di eventuali “picchi di traffico” che potrebbero portare a scelte e contromisure sbagliate, o quanto meno poco efficaci.

Una volta che ogni switch della rete ha fornito al componente le proprie statistiche, si passa alla generazione di due eventi: uno relativo alle porte e l’altro ai flussi. Detti eventi contengono le informazioni raccolte, organizzate in strutture dati appositamente studiate per renderle facilmente consultabili da parte dei moduli interessati.

Dimostrazione (filtraggio passa-basso del rate istantaneo) Sia N (t) la funzione cumulativa che rappresenta il numero di bit ricevuti da una porta appartenente ad uno switch, fino all’istante t. La trattazione che segue rimane

R (t) 1 Ts Z t t−Ts (·) dτ R [k]ˆ kTs ˆ R (t)

Figura 5.4: Rappresentazione grafica della relazione (5.4)

valida sostituendo le parole “ricevuti” e “porta” con “trasmessi” e “flusso”, ri- spettivamente. Tale funzione dovr`a essere necessariamente monotona crescente, almeno in senso lato. In altri termini, si avr`a

N (t + T ) ≥ N (t) , ∀ T > 0.

Come detto in precedenza, il controller ha accesso alla funzione N (t) sola- mente ad istanti multipli dell’intervallo d’interrogazione Ts. In realt`a, dunque, il segnale di cui si dispone `e la sequenza

N [k] = N (kTs) , k ∈ N. (5.1)

Si osservi come la (5.1) rappresenti, in effetti, un campionamento della funzione N (t), a passi di Tssecondi.

Definiamo con R (t) il “tasso” (rate) istantaneo con il quale i bit vengono ricevuti dalla porta in esame, ovvero

R (t) = dN (t)

dt bit/s. (5.2)

La stima di R (t) al passo k sar`a dunque pari a ˆ

R [k] = N [k] − N [k − 1] Ts

. (5.3)

Sostituendo la (5.1) nella (5.3), si ottiene ˆ

R [k] = N (kTs) − N (kTs− Ts) Ts

, da cui, grazie alla (5.2), si giunge al risultato6 (figura 5.4)

ˆ R [k] = 1 Ts Z kTs kTs−Ts R (τ ) dτ. (5.4)

Per verificare che la (5.4) rappresenta effettivamente un filtraggio passa-basso della funzione R (t), si consideri un sistema LTI avente risposta impulsiva h (t) definita come h (t) = 1 Ts rect t − Ts/2 Ts  . (5.5)

Risulta evidente, anche grazie all’ausilio fornito dalla figura 5.5, come un tale sistema costituisca un filtro passa-basso.

Applicazione di controllo 51 −Ts0 −Ts/2 0 Ts/2 Ts 3Ts/2 2Ts Ts/4 Ts/2 3Ts/4 Ts t h(t)

(a) Risposta impulsiva (5.5)

−4/Ts0 −3/Ts −2/Ts −1/Ts 0 1/Ts 2/Ts 3/Ts 4/Ts 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 f |H(f)|

(b) Modulo della risposta in frequenza: |sinc (f Ts)|

Figura 5.5: Filtraggio passa-basso (smoothing) dovuto al procedimento seguito per il calcolo della banda

Se, dunque, applicassimo in ingresso ad h (t) il segnale R (t), ci`o che otter- remmo in uscita sarebbe

ˆ R (t) = R (t) ⊗ h (t) , = Z ∞ −∞ R (τ ) h (t − τ ) dτ, = 1 Ts Z t t−Ts R (τ ) dτ,

che altro non `e se non la versione a tempo continuo della (5.4). Infatti

ˆ R [k] = ˆR (kTs) = 1 Ts Z t t−Ts R (τ ) dτ t=kTs = 1 Ts Z kTs kTs−Ts R (τ ) dτ .

5.3.2

Analisi del codice

Il codice relativo al modulo in esame pu`o essere recuperato consultando il paragrafo D.3.

Richiesta di statistiche e generazione di eventi

Come detto in precedenza, ad intervalli di tempo regolari (di durata pari a delta secondi) il modulo in esame provvede ad interrogare gli switch connessi al controller, in modo da farsi recapitare le statistiche relative a porte e flussi corrispondenti. Il metodo della classe predisposto alla richiesta di statistiche `e askForStats().

Il numero di switch per la rete in esame viene determinato osservando l’evo- luzione temporale del numero di connessioni attive tra controller e dispositivi. Ad ogni nuova connessione/disconnessione, un contatore interno – numSwitch – viene incrementato/decrementato; ci`o fa s`ı che il numero degli switch venga dichiarato “instabile”. Si attende quindi un certo lasso temporale, trascorso il quale il contatore viene esaminato nuovamente. Se il suo valore non ha subito ulteriori modifiche, il numero degli switch viene dichiarato “stabile” e posto pari al contatore stesso. In caso contrario, la condizione d’instabilit`a si protrae fino alla prossima verifica. L’instabilit`a del numero di switch connessi al controller, cos`ı come la loro assenza, causa la sospensione della richiesta di statistiche.

La conoscenza del numero di switch che compongono la rete in esame `e con- dizione necessaria al corretto funzionamento del modulo. Il metodo predisposto alla generazione degli eventi relativi al carico di porte e flussi – publish() – attende infatti di aver ricevuto le statistiche da tutti i dispositivi effettivamente presenti, prima di svolgere le azioni per le quali `e stato creato. L’unico modo per verificare di aver ottenuto tutte le informazioni disponibili `e quello di contare il numero di risposte, verificando che esso sia pari al numero di switch ritenuto (al momento) stabile.

Applicazione di controllo 53 Nrx[k] z−1

+

×

8/Ts ˆ Rrx[k] + Nrx[k − 1] − (a) Ricezione Ntx[k] z−1

+

×

8/Ts ˆ Rtx[k] + Ntx[k − 1] − (b) Trasmissione

Figura 5.6: Stima del carico sperimentato da una porta appartenente ad uno switch OpenFlow

Statistiche di porta

Le statistiche di porta cronologicamente pi`u recenti sono organizzate all’interno del dizionario lastPortLoad, che mappa ciascuno switch (ciascun identificativo di uno switch) in un ulteriore dizionario, il quale costituisce una corrispondenza tra un numero di porta ed una lista, costituita dai valori – espressi in ‘bit/s’ – relativi agli ultimi carichi di traffico misurati, sia in ricezione che in trasmissione. In breve:

s e l f. l a s t P o r t L o a d [ s w i t c h _ i d ][ s w i t c h _ p o r t ] = [ bw_rx , b w _ t x ].

Un analogo dizionario, prevPorts, `e dedicato alla memorizzazione delle stati- stiche prelevate al passo precedente. Stavolta, i valori contenuti all’interno della lista sono espressi in ‘byte’. In sintesi:

s e l f. p r e v P o r t s [ s w i t c h _ i d ][ s w i t c h _ p o r t ] = [ b y t e s _ r x , b y t e s _ t x ].

La gestione delle statistiche di porta, ricevute da uno switch OpenFlow, `

e affidata al metodo handle PortStatsReceived(). La figura 5.6 illustra le operazioni svolte per ricavare i valori di carico – espressi in ‘bit/s’ – da inserire in lastPortLoad ( ˆRrx[k] e ˆRtx[k]), conoscendo:

• il numero di byte ricevuti e trasmessi fino all’ultimo intervallo d’interro- gazione (Nrx[k] e Ntx[k]), contenuti nel messaggio ricevuto dallo switch a seguito della richiesta di statistiche;

• il numero di byte ricevuti e trasmessi fino al penultimo intervallo d’inter- rogazione (Nrx[k − 1] e Ntx[k − 1]), memorizzati in prevPorts.

Ovviamente, il tutto `e coerente con quanto `e stato detto in precedenza. Si osservi che l’evento NewPortStats contiene una copia esatta del dizionario lastPortLoad.

Statistiche di flusso

Analogamente con quanto accade per le statistiche di porta, le statistiche di flusso pi`u recenti sono organizzate in un dizionario – lastFlowLoad – che mappa ciascuno switch (ciascun identificativo di uno switch) in un ulteriore dizionario, il quale costituisce una corrispondenza tra i campi caratteristici di alcuni flussi presenti nella tabella di uno switch ed il valore – espresso in ‘bit/s’ – relativo all’ultimo carico di traffico misurato in trasmissione. In breve:

s e l f. l a s t F l o w L o a d [ s w i t c h _ i d ][ f l o w _ f i e l d s ] = bw .

Un analogo dizionario, prevFlows, `e dedicato alla memorizzazione delle stati- stiche prelevate al passo precedente. In questo caso, il valore corrispondente viene espresso in ‘byte’. Sinteticamente:

s e l f. p r e v F l o w s [ s w i t c h _ i d ][ f l o w _ f i e l d s ] = b y t e s .

Chiaramente, per statistiche di questo tipo, non esistono i valori duali, relativi cio`e alla ricezione.

`

E importante sottolineare che, nonostante si ricevano le statistiche relative a tutti i flussi presenti nella flow-table di tutti gli switch connessi al controller, sol- tanto alcuni di essi rivestono interesse ai fini del funzionamento dell’architettura (paragrafo 5.5). Tali flussi vengono identificati tramite una tupla, contenente i valori assunti da alcuni campi presenti nelle intestazioni di trame, pacchetti e segmenti, e da due attributi tipici di una regola OpenFlow: cookie e priority (paragrafo 3.2). Riassumendo:

f l o w _ f i e l d s = ( e t h e r _ t y p e , i p _ p r o t o c o l , ip_src , ip_dst , p o r t _ s r c , p o r t _ d s t , p r i o r i t y , c o o k i e ).

Il metodo cui viene affidata la gestione delle statistiche di flusso, ricevute da uno switch OpenFlow, `e handle FlowStatsReceived(). Per le modalit`a (ormai note) con cui viene effettuato il calcolo della banda, si pu`o ancora fare riferimento alla figura 5.6b.

Anche in questo caso, l’evento NewFlowStats contiene una copia esatta del dizionario lastFlowLoad.