Avanti Indietro Indice

8. Queue

8.1 Introduzione

Come abbiamo visto le qdisc sono un elemento fondamentale e ne sono disponibili diverse con proprie caratteristiche e obiettivi. Alcune sono 'classful' ossia possono essere "suddivise" in sotto-classi (es. CBQ) altre invece 'classless'.

La differenza consiste nel fatto che le qdisc 'classful' sono utilizzate per generare le classi, mentre le qdisc 'classless' (RED, SFQ, ...) hanno la funzione di coda e quindi di gestione dei pacchetti che arrivano alla classe.

Per creare, modificare, cancellare una disciplina è necessario utilizzare il comando tc qdisc:

# tc qdisc help

Usage: tc qdisc [ add | del | replace | change | get ] dev STRING
       [ handle QHANDLE ] [ root | ingress | parent CLASSID ]
       [ estimator INTERVAL TIME_CONSTANT ]
       [ [ QDISC_KIND ] [ help | OPTIONS ] ]

       tc qdisc show [ dev STRING ] [ingress]
Where:
QDISC_KIND := { [p|b]fifo | tbf | prio | cbq | red | etc. }
OPTIONS := ... try tc qdisc add <desired QDISC_KIND> help

add|del|replace|change|get: è necessario sempre indicare l'operazione che si desidera 
                            effettuare: add (aggiungi), del (rimuovi), replace (sostituisci), 
                            change (cambia), get (ottiene l'ID interno utilizzato).
 
dev:       si deve specificare l'interfaccia/dispositivo su cui si desidera controllare 
           il traffico (es. dev eth0).

handle:    è l'identificatore numerico utilizzato per distinguere le varie classi (es. 10:0).

[root | ingress | parent]: root si utilizza quando si imposta una classe radice, ingress quando 
                           si desidera limitare il traffico in ingresso, parent per specificare 
                           la classe/nodo "padre". 

estimator: utilizzato per stabilire se i requesiti della coda sono soddisfatti.
           Usage: ... estimator INTERVAL TIME-CONST
            INTERVAL:   intervallo tra i misuramenti
            TIME-CONST: costante media tempo
            Esempio: ... est 1sec 8sec

8.2 qdisc

Le qdisc che possono essere utilizzare sono le seguenti:

CBQ

CBQ (class-based queueing) è la 'queue discipline' più importante. E' basata su classi ossia è possibile creare diverse classi, che a loro volta possono essere suddivise in ulteriori classi, a cui assegnare caratteristiche differenti (bandwidth, priorità, coda, ...). Ciò permette, se si ha a disposizione ad esempio una banda pari a 10Mbit, di suddividerla in due classi, una con bandwidth di 3Mbit e una di 7Mbit. Potremmo così inviare il traffico più importante verso la banda più "larga" e quello meno importante sull'altra. I parametri richiesti da questa coda sono i seguenti:

# tc qdisc add cbq help
Usage: ... cbq bandwidth BPS avpkt BYTES [ mpu BYTES ]
               [ cell BYTES ] [ ewma LOG ]

bandwidth: bandwidth totale disponibile espressa in bytes o altra misura (es. 1Mbit, 10Mbit, 128kbps ...)
avpkt:     dimensione media dei pacchetti, nel caso di pacchetti ethernet corrisponde a 1000 byte
mpu:       dimensione minima che può avere un pacchetto, nel caso ethernet corrisponde a 64 byte
cell:      impostata in genere a 8 byte
ewma:      exponential weighted moving average

NOTA: i parametri compresi tra [ parentesi quadre ] sono opzionali. 

Es.: tc qdisc add dev eth0 root handle 1: cbq bandwidth 10Mbit avpkt 1000
FIFO

L'algoritmo FIFO (First In, First Out) è l'algoritmo di default e probabilmente il più semplice. I pacchetti che arrivano prima sono i primi ad essere serviti e quindi ad essere inviati. Se un pacchetto arriva mentre è in corso l'invio di alcuni pacchetti presenti nella coda, questo è accodato. Se la coda però è completamente occupata, la "policy" determinerà se questo pacchetto deve essere scartato oppure se un pacchetto presente nella coda deve essere rimosso per fargli posto.


          +---------+
--- o --->| | |o|o|o|---->
          +---------+
           coda FIFO


# tc qdisc add pfifo help
Usage: ... [p|b]fifo [ limit NUMBER ]
limit: dimensione della coda.
       Se si sceglie pfifo questo valore deve essere espresso in numero di pacchetti.
       Se si sceglie bfifo può essere indicato in byte.

Es.:   tc qdisc add dev eth0 parent 1:10 pfifo 

CSZ

CSZ utilizza sia WFQ (Weighted Fair Queueing) sia priority. Priority è ideale per i servizi real-time, mentre WFQ supporta e gestisce guaranteed service e link sharing. Al momento CSZ è inutilizzabile e probabilmente sarà sostituito con h-pfq.

PRIO

Questo algoritmo permette di suddividere i pacchetti in diverse code (bande) ciascuna con diversa priorità. In base a questa priorità viene selezionata la coda da cui prelevare il pacchetto da inviare in output. Se la coda con priorità maggiore ha dei pacchetti saranno quest'ultimi ad essere inviati, se è vuota saranno inviati (se presenti) i pacchetti della seconda coda in ordine di priorità.


        +-----+
        |o| | |------+
        +-----+      |
          P1         |
        +-----+      |
- o -+  |o|o| |      +----->
     |  +-----+
     |    P2
     |  +-----+
     +->|o| | |
        +-----+
          P3

# tc qdisc add prio help
Usage: ... prio bands NUMBER priomap P1 P2..

bands:   numero di bande che si vogliono creare (default 3)
priomap: priorità delle bande. Da aggiornare se si indicano più bande 
         del valore di default, ossia 3.
         Questa è la priomap di default: 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1.
        
Es.:     tc qdisc add dev eth0 parent 1:10 prio
RED

RED è utilizzata per controllare la congestione della rete ed è usata in particolare con le backbone. Questo algoritmo si basa sui protocolli TCP/IP, ed il suo scopo è quello di simulare una situazione di congestione della rete prima che essa avvenga realmente. Questa simulazione permette di tenere sotto controllo la latenza, la coda e di evitare diversi inconvenienti noti. Il TCP/IP infatti prevede inizialmente un invio contenuto di pacchetti che tende ad aumentare progressivamente fino al completo esaurimento della banda a disposizione con conseguenti pacchetti scartati, richieste di ritrasmissione, ...

# tc qdisc add red help
Usage: ... red limit BYTES min BYTES max BYTES avpkt BYTES burst PACKETS
               probability PROBABILITY bandwidth KBPS

limit: dimensione della coda in byte
min:   soglia minima della coda prima di cominciare a scartare i pacchetti
       Per una linea ISDN 64kbit/s si dovrebbe aggirare sui 1600 bytes, considerando 
       una latenza di 200 ms. (min = bandwidth*latenza). 
       E' importante scegliere un valore min che non sia troppo basso o eccessivo altrimenti
       si potrebbero ottenere rispettivamente un degrado del throughput o della latenza.
max:   soglia massima della coda che l'algoritmo deve rispettare.
       Dovrebbe essere il doppio del parametro min.
avpkt: dimensione media dei pacchetti
burst: numero massimo di pacchetti che possono essere inviati in un certo istante (burst).
probability: probabilità che i pacchetti siano scartati in caso di raggiungimento
             del limite
bandwidth: bandwidth a disposizione
SFQ

SFQ (Stochastic Fairness Queueing) [RFC1254] prevede che i pacchetti siano distinti in base ai parametri delle loro intestazioni. Nel caso di pacchetti IP in base a indirizzo sorgente, destinazione. Questo permette di distinguere i flussi, le connessioni stabilite. SFQ prevede l'allocazione e l'utilizzo di una nuova coda FIFO per ogni flusso di pacchetti. I pacchetti poi saranno prelevati dalle code e inviati nella rete utilizzando una disciplina round-robin, che consiste nel prelevare in ordine un pacchetto da ogni coda (se presente) e nell'inviarlo in rete. Le code FIFO sono quindi trattate in modo equo, imparziale (Fairness). In caso di congestione è prevista la rimozione di pacchetti dalla coda FIFO che ne contiene il maggior numero. Per tenere traccia dei vari flussi è utilizzata una tabella hash che come noto è soggetta a collisioni, ciò può degradare l'imparzialità di trattamento, quindi è previsto un meccanismo di "perturbamento" periodico della hash function in modo da limitare le collisioni. I benefici che si traggono da questo tipo di implementazione sono un consumo minimo di risorse CPU e di memoria.

         +-------------------+
         |    +-----+  .<..  |
              |o| | |--.---+ |
         |    +-----+  .  .| |
         |     FIFO    .  ^| |
         |    +-----+  .  .| |
- o -+        |o|o| |  .  .+----->>
     |   |    +-----+  .  .  |
     |   |     FIFO    .  .  |
     |   |    +-----+  v  .  |
     +------> |o| | |  .  .  |
         |    +-----+  ..>.  |
         |     FIFO          |
         +-------------------+




# tc qdisc add sfq help
Usage: ... sfq [ perturb SECS ] [ quantum BYTES ]

perturb: intervallo di tempo prima di effettuare un'operazione di "perturbamento"
quantum: corrisponde in genere a MTU (caso ethernet si utilizza 1514b).

Es.:     tc qdisc add dev eth0 parent 1:10 sfq quantum 1514b perturb 15
TEQL

...

...
TBF

TBF (Token Bucket Filter) è un algoritmo diverso dai precedenti in quanto l'invio dei pacchetti nella rete dipende da una seconda struttura (bucket) in cui sono memorizzati dei token. I token sono aggiunti nel bucket a cadenza regolare (es. 1 ogni secondo), e sono utilizzati per determinare se un pacchetto può essere inviato nella rete, se deve attendere oppure se deve essere scartato. Se un pacchetto arriva e il bucket non contiene almeno un token allora dovrà attenderne l'arrivo di uno (l'implementazione in Linux prevede che questi pacchetti siano scartati) prima di essere inviato nella rete, altrimenti può essere inviato immediatamente e un token è rimosso dal bucket. Se il bucket è completamente occupato i nuovi token sono scartati.

   
                            +---- O  r token/secondo
                            | 
                            V
                           | |
                           |O|
                           |O|
                           +-+
                            |
                            V
                           ---
  pacchetti  ----- o ----->| | -------> rete
                           ---

# tc qdisc add tbf help
Usage: ... tbf limit BYTES burst BYTES[/BYTES] rate KBPS [ mtu BYTES[/BYTES] ]
               [ peakrate KBPS ] [ latency TIME ]

limit: numero massimo di byte che possono essere accodati
burst: numero massimo di byte che possono essere inviati in un certo istante (burst).
rate:  velocità trasmissione dati (KBPS) 
mtu:   maximum transfer unit 
peakrate: limite massimo di pacchetti che possono essere inviati.
latency:  latenza

Es.:  tc qdisc add dev eth0 parent 1:10 tbf rate 64Kbit buffer 5Kb/8 limit 10Kb
GRED

Generalized RED.

Usage: ... gred DP drop-probability limit BYTES min BYTES max BYTES
                avpkt BYTES burst PACKETS probability PROBABILITY bandwidth KBPS
                [prio value]
           OR ...
           gred setup DPs <num of DPs> default <default DP> [grio]
Diffserv field marker

Questa qdisc permette di realizzare i "Differentiated Services" sfruttando differenti per-hop behaviour (PHB). I pacchetti sono distinti attraverso il campo DS presente nell'intestazione IP. Nel caso del protocollo IPv4 il campo DS corrisponde al campo TOS (Type Of Service) che è riutilizzato ed esteso. Tutti i pacchetti con lo stesso valore DS sono trattati come un singolo flusso.

Usage: dsmark indices INDICES [ default_index DEFAULT_INDEX ] [ set_tc_index ]

Es.:   tc qdisc add dev eth0 handle 1:0 root dsmark indices 64

Ingress Qdisc

Questa disciplina speciale è utilizzata per limitare il traffico in ingresso ad una interfaccia. Gli eventuali pacchetti che eccedono il limite sono scartati. Un utilizzo per questa qdisc pùò essere ad esempio quello di limitare attacchi TCP SYN flooding.

Usage: ... ingress

Es.:   tc qdisc add dev eth0 handle ffff: ingress 

8.3 Creare una qdisc root

Per creare una qdisc root, supponendo di avere a disposizione una banda da 10Mbit, che permetta di utilizzare più classi dove indirizzare i pacchetti è possibile utilizzare la qdisc CBQ:


              +------------ QDISC CBQ -----------+
              |                                  |
              |                                  |
              |                                  |
Pacchetto --> |                                  |
              |                                  |
              |                                  |
              |                                  = ---> 
              |                                  |   eth0
              |                                  |
              |                                  |
              |                                  |
              |                                  |
              |                                  |
              +----------------------------------+
                                                              
# -----------------------------------------------------------------------------
# Crea e associa all'interfaccia eth0 una qdisc root cbq e identificala con 10:
# bandwidth totale a disposizione 10Mbit avpkt 1000 byte. 
# -----------------------------------------------------------------------------
tc qdisc add dev eth0 root handle 10: cbq bandwidth 10Mbit avpkt 1000

Avanti Indietro Indice