La disciplina CBQ (Class-based queueing) permette di creare più classi, a loro volta ulteriormente suddividibili, ognuna con le proprie caratteristiche (rate, priorità, identificatore, ...). Inoltre è sempre associata una delle qdisc viste precedentemente (SFQ, FIFO, ...) che servono a stabilire come devono essere gestiti i pacchetti che arrivano. Se non si specifica una coda allora è utilizzata per default la FIFO.
Le qdisc che supportano le classi (classful) sono: CBQ, DS_MARK, CSZ e p-FIFO. Le altre non le supportano e sono dette classless (RED, TBF, ...).
Graficamente si possono rappresentare in questo modo:
+------------------- QDISC CBQ -------------------+
|+--------------- CLASSE CBQ ROOT ---------------+| ______
|| || / \
|| +-CLASSE A 8Mbit prio 3 ---+ || | ROOT |
|| | +----------------+ | || \______/
Pacchetto -->== = -> | SFQ |--> = ---+ || /10:1\
|| | +----------------+ | | || 8Mbit / \ 2Mbit
|| +--------------------------+ | || ______ ______
|| +--> ==---> / \ / \
|| +-CLASSE B 2Mbit prio 2 ---+ | || |CLASSE A| |CLASSE B|
|| | +--------------+ | | || \______/ \______/
|| = -> | FIFO | ---> = ---+ || 10:100 10:200
|| | +--------------+ | ||
|| +--------------------------+ ||
|+-----------------------------------------------+|
+-------------------------------------------------+
Per creare una classe è necessario utilizzare il comando tc class e quindi impostare correttamente i parametri:
# tc class help
Usage: tc class [ add | del | change | get ] dev STRING
[ classid CLASSID ] [ root | parent CLASSID ]
[ [ QDISC_KIND ] [ help | OPTIONS ] ]
tc class show [ dev STRING ] [ root | parent CLASSID ]
Where:
QDISC_KIND := { prio | cbq | etc. }
OPTIONS := ... try tc class add <desired QDISC_KIND> help
dev: device, interfaccia
classid: identificatore della classe. Es. 10:100 il primo numero (10) indica in genere la
classe root contenitore, il secondo numero (100) è l'identificatore della classe.
Attraverso questo identificatore possiamo indicare univocamente la classe e ad
esempio utilizzarla per associarle una qdisc.
root | parent: la struttura delle classi è ad albero, in genere si ha un nodo root
(classe "contenitore") e diverse classi. Per ciascuna di queste classi è necessario
specificare da quale classe/nodo derivano utilizzando il parametro parent.
QDISC_KIND: qdisc da utilizzare.
Per creare una classe con qdisc CBQ è necessario specificare diversi parametri:
# tc class add cbq help
Usage: ... cbq bandwidth BPS rate BPS maxburst PKTS [ avpkt BYTES ]
[ minburst PKTS ] [ bounded ] [ isolated ]
[ allot BYTES ] [ mpu BYTES ] [ weight RATE ]
[ prio NUMBER ] [ cell BYTES ] [ ewma LOG ]
[ estimator INTERVAL TIME_CONSTANT ]
[ split CLASSID ] [ defmap MASK/CHANGE ]
bandwidth: larghezza di banda totale a disposizione
rate: bandwidth assegnata a questa classe
maxburst: numero massimo di pacchetti che possono essere inviati nel burst
avpkt: dimensione media di un pacchetto
minburst: numero minimo di pacchetti
bounded: da specificare se non si desidera che la classe possa utilizzare la
banda a disposizione della classe "parent" da cui deriva.
isolated: da specificare se non si desidera che la classe condivida la propria bandwidth con
nessuna classe che non sia discendente.
allot: MTU + intestazione MAC. Nel caso ethernet è da impostare a 1500+14=1514 byte
mpu: numero minimo di bytes che possono essere inviati in un pacchetto
weight: parametro da scegliere in modo che sia proporzionale al parametro 'rate'
Es. 1/10 di rate
prio: priorità da associare alla classe
cell: impostata in genere a 8 byte
ewma: vedi sopra
estimator: vedi sopra
split: utilizzato per accessi rapidi
defmap: si utilizza per assegnare alla classe i pacchetti con i bit TOS
(caso pacchetti in arrivo) o priorità (caso pacchetti generati localmente)
specificati e che non sono classificabili in nessun'altra classe.
Ad esempio per creare le classi del grafo precedente, supponendo di aver già creato la qdisc root 10:, è necessario utilizzare i seguenti comandi:
# -------------------------------------------------------------------------
# Creazione della prima classe ROOT.
# bandwidth assegnata 10Mbit, priorità della classe 8.
# allot nel caso ethernet è da impostare a 1514 (allot=MTU+MAC)
# weight è da scegliere proporzionale a rate, in genere 1/10 di rate.
# -------------------------------------------------------------------------
tc class add dev eth0 parent 10:0 classid 10:1 cbq bandwidth 10Mbit rate 10Mbit \
allot 1514 cell 8 weight 1Mbit prio 8 maxburst 20 avpkt 1000
# ----------------------------------------------------------------------------------------------
# Crea e associa una classe all'interfaccia eth0, la classe parent è root 10:1 già creata.
# La classe è di tipo cbq, la bandwidth totale è di 10Mbit, alla classe sono assegnati 8Mbit,
# la priorità assegnata è 3 e inoltre non si desidera che la banda possa essere condivisa
# (bounded). Gli altri parametri (allot 1514, avpkt 1000, ...) sono sempre gli stessi.
# ----------------------------------------------------------------------------------------------
tc class add dev eth0 parent 10:1 classid 10:100 cbq bandwidth 10Mbit rate 8Mbit allot 1514
weight 800kbit prio 3 maxburst 20 avpkt 1000 bounded
# ----------------------------------------------------------------------------------------------
# Crea e associa una classe all'interfaccia eth0, la classe parent è root 10:1 già creata.
# La classe è di tipo cbq, la bandwidth totale è di 10Mbit, alla classe sono assegnati 2Mbit, la
# priorità assegnata è 2 e inoltre non si desidera che la banda possa essere condivisa (bounded).
# ----------------------------------------------------------------------------------------------
tc class add dev eth0 parent 10:1 classid 10:200 cbq bandwidth 10Mbit rate 2Mbit allot 1514
weight 200kbit prio 2 maxburst 20 avpkt 1000 bounded
A questo punto è possibile associare alle classi create una qdisc (SFQ, RED, FIFO, TBF, ...) utilizzando il classid assegnato.
# ---------------------------------------------------------------------------------------------- # Associamo alla classe 10:100 una qdisc SFQ #----------------------------------------------------------------------------------------------- tc qdisc add dev eth0 parent 10:100 sfq quantum 1514b perturb 15 #----------------------------------------------------------------------------------------------- # Associamo alla classe 10:200 una qdisc FIFO bfifo #----------------------------------------------------------------------------------------------- tc qdisc add dev eth0 parent 10:200 bfifo
Conclusa questa fase le classi sono completate. Non resta che utilizzare i classificatori/filtri per smistare i pacchetti in arrivo nelle classi create.
Per creare una class dsmark è necessario utilizzare il comando tc class e quindi impostare i parametri della classe:
Usage: ... dsmark [ mask MASK ] [ value VALUE ] Es.: tc class change dev eth0 classid 1:1 dsmark 0x3 value 0xb8