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