Capitolo 3




Networking in Linux : routing e gestione delle risorse di rete







3.1 Intoduzione


Buona parte dei router e dei server mondiali su cui si basa la rete lavorano supportando il sistema operativo Linux. Questo offre un ricco insieme di funzioni per la gestione di reti in tutti i loro aspetti. Ciò è dovuto in gran parte alla natura open source di questo sistema operativo che ha permesso a chiunque di sviluppare liberamente delle parti del codice sorgente allo scopo di risolvere un problema pratico. Sebbene sia difficile in un ambiente così strutturato definire precisamente i meriti da assegnare a ciascuno, una menzione particolare va sicuramente a Alexey N. Kuznetsov dell' Istituto per la Ricerca Nucleare di Mosca il quale è il cretore della struttura del kernel, attualmente fornita standard con le varie distribuzioni di Linux, per il networking.

Nella prima parete di questo capitolo cercherò di dare una descrizione chiara di questa architettura interna passando altresì in rassegna gli strumenti disponibili da me individuati come utili al fine del raggiungimento del nostro scopo.

Infine vedremo come è stato raggiunto l'obiettivo del controllo dell'utilizzo della banda nel corso di una sessione H.323 compatibilmente con inderogabili esigenze di qualità del servizio.


3.2 La struttura del kernel e i comandi per il controllo del traffico.


Linux offre un ricco set di funzioni per il controllo del traffico come i comandi tc , iptables , iproute e così via i quali si appoggiano su una struttura definita nel kernel del sistema operativo. Cerchiamo di definire in che modo vengono elaborati ipacchetti all'interno delle macchine linux. A livello più alto possibile possiamo immaginare una situazione come quella di figura:



Fig 3.1


La figura mostra come il kernel processi i dati ricevuti dalla rete e come esso possa generare nuovi dati che dovranno essere spediti sulla rete : i pacchetti entranti possono sia essere reindirizzati immediatamente sulla rete ( magari su diverese interfacce nel caso di un router ), sia essere passati al livello superiore della pila protocollare ( come ad esempio un protocollo di trasporto ) per essere processati.

Il Forwarding include la selezione dell'interfaccia di uscita , la selezione del prossimo salto, l'incapsulamento e così via. Una volta fatto questo i pacchetti sono accodati sulle rispettive interfacce dove vigeranno le discipline di accodamento per la gestione del traffico.



3.2.1 Iproute2

Volendo esplorare più in profondità il problema cominciamo con l'analizzare il blocco denominato input de-multiplexing. Al suo interno possiamo immaginare la routing table relativa ai pacchetti provenienti dall' esterno e che devono essere reindirizzati . Il pacchetto per la gestione dell' indirizzamento è iproute2.

Questo risulta essre uno strumento molto flessibile e completo in quanto è possibile definire più tavole di routing da consultare a seconda della sorgente del pacchetto, della destinazione o semplicemente dell'utente che richiede l'utilizzazione della risorsa. Tra la miriade di comandi disponibili quelli di cui ha più senso parlare in questa sede sono:



Per rendere più chiaro quanto detto vediamo come sono le impostazioni su genni:


IMPOSTAZIONI DI ROUTING DI GENNI


#ip link list

[alec@genni alec]$ ip link list

1: lo: <LOOPBACK,UP> mtu 16436 qdisc noqueue

link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

2: eth0: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc p_fifo_fast

qlen 100

link/ether 00:01:02:15:8b:e5 brd ff:ff:ff:ff:ff:ff





Come possiamo veder su genni sono definite 2 interfacce tramite le quali fluisce il traffico:

[alec@genni alec]$ ip address

1: lo: <LOOPBACK,UP> mtu 16436 qdisc noqueue

link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

inet 127.0.0.1/8 brd 127.255.255.255 scope host lo

2: eth0: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc p_fifo_fast

qlen 100

link/ether 00:01:02:15:8b:e5 brd ff:ff:ff:ff:ff:ff

inet 151.100.11.28/24 brd 151.100.11.255 scope global eth0



Il dispositivo locale è noto con l'indirizzo 127.0.0.1/8. Il /8 finale indica che sono libero di assegnare gli ultimi 32 - 8 = 24 bit come più mi piace, così come indicato dalla netmask.

L'indirizzo associato alla scheda di rete è quello ip della macchina 127.100.11.28 e il /24 indica che la nella sottorete a cui appartengo sono libero di sfruttare per l'indirizzamento gli ulyimi 8 bit.

Passando a ip rule vediamo che come standard sono definite 3 routing table .


#ip rule list

[alec@genni alec]$ ip rule list

0: from all lookup local

32766: from all lookup main

32767: from all lookup 253


Quella che conosciamo di solito e la main che definisce l'instradamento dei pacchetti in funzione della loro destinazione.

#ip route show (route -n)

[alec@genni alec]$ route -n

Kernel IP routing table

Destination Gateway Genmask Flags Metric Ref Use Iface

151.100.11.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0

151.100.8.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0

151.100.9.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0

127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo

        1. 151.100.11.1 0.0.0.0 UG 0 0 0 eth0


In questo caso ,non essendo genni un router ,la situazione è molto semplice. Devo solo specificare che, a meno che il pacchetto non sia per me ,qualunque pacchetto lo giro al Gateway di facoltà 151.100.11.1. In raltà per velocizzare la rete e non appesantire di carico inutile il Gateway ho anche specificato che qualunque host del tipo 151.100.11.0/32 , 151.100.8.0/32 e 151.100.9.0/32 è direttamente raggiungibili.

La local table serve solo a specificare cose ovvie relative al traffico interno alla macchina

che però da qualche parte vanno pure specificate. L'ultima routing table 253 e quella di defoult , ultima ad essere guardata, che interviene se un pacchetto si perde non essendo selezionato da alcuna tavola.


[alec@genni alec]$ ip route list table local

local 151.100.11.28 dev eth0 proto kernel scope host src 151.100.11.28

broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1

broadcast 151.100.11.255 dev eth0 proto kernel scope link src 151.100.11.28

broadcast 151.100.11.0 dev eth0 proto kernel scope link src 151.100.11.28

broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1

local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1

local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1


La cosa interessante è che io posso specificare, tramite il comando ip rule, altre routing table che non dipendano solo dall'indirizzo di destinazione ma magari dalla sorgente del traffico. Per fare un esempio pratico se io ho più utenti collegati ad un router e voglio ad esempio che solo alcuni possano usufruire di alcune interfacce di uscita del router particolarmente veloci posso definire delle routing table personalizzate per gli utenti. Nelle routing table degi utenti meno pregiati non compariranno come possibili interfacce di ucita quelle più veloci.

Visto che la modifica della routing table non è utile al nostro scopo rimandiamo per maggiori approfondimenti al manuale di iproute2[].



3.2.2 Traffic controller


Vediamo di analizzare ora la parte e di gestione della coda di uscita. Volendo comprendere più in profondità il controllo di traffico cominciamo ad introdurre i concetti chiave tramite i quali il kernel di Linux ragiona:


  1. Queuing discipline

    A ogni dispositivo di rete può essere associata una disciplina di accodamento che effettua uno scheduling dei pacchetti in ingresso . Di default questa disciplina è una semplice FIFO.

  2. Classes

    Le classi servono a definire le varie tipologie di traffico.Ogni classe e padrona di una coda la quale di default è una FIFO. Quando la disciplina di accodamento è chiamata questa applica i filtri per determinare la classe alla quale il pacchetto appartiene .

  3. Filters

    I filtri si occupano di smistare il traffico nelle diverse classi . Il concetto di filtro è molto più libero di quella di classe , infatti più filtri possono essere associati alla stessa classe e quindi alla stessa coda.



Fig 3.2


Ora spiegato a grandi linee qual' è la struttura con la quale abbiamo a che fare andiamo a vedere i comandi con cui realizzarla e le funzionalità a cui possiamo attingere.

ELEMENTO

COMANDI

Queuing discipline

tc qdisc ...(OPTIONS)

Class

tc class ...(OPTIONS)

Filter

tc filter ... (OPTIONS)

La fonte più precisa di informazione sul traffic control sono proprio gli help in linea , usiamoli quindi come punto di partenza per capire i comandi e le possibili opzioni.


3.2.2.1 tc qdisc

[alec@genni alec]$ 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


E' possibile creare, cancellare, rimpiazzare o semplicemente cambiare qualche parametro a una disciplina di accodamento ( qdisc ). Subito dopo devo specificare a quale device di uscita andarà applicata questa disiplina . Prima di spiegare le altre opzioni precisiamo che non è obbligatorio lavorare con le classi. Le classi sono un arnese molto potente e flessibile ma anche piuttosto complicato. Il più delle volte è possibile utilizzando filtri e qdisc riuscire comunque a raggiungere il nostro scopo.

Poniamo di voler semplicemente limitare la banda in uscita da eth0 , dirò semplicemente :


#tc qdisc add dev eth0 root tbf rate 220kbit latency 50ms burst 1540


questo comando applica una disciplina token buckets a eth0 con certi parametri di banda.

Le più importanti qdisc classless ( che funzionano senza dover definire delle classi) sono:



0 1 2 3 4 5 6 7

+-----+-----+-----+-----+-----+-----+-----+-----+

| PRECEDENCE | TOS | MBZ |

+-----+-----+-----+-----+-----+-----+-----+-----+



Ad ogni tipo di servizio è associata una delle tre bande. Questa asociazione definisce la priomap( tabella di priorità).


Questa qdisc è da usare solo se l'interfaccia di uscita è veramente satura altrimenti non darà alcun effetto.



3.2.2.2 tc class

Anche per l'elemento classe facciamo uso dell'help in linea :

[alec@genni alec]$ 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

Il comando ha una struttura simile a quella di tc qdisc. Possiamo creare, cancellare o cambiare i parametri ad una clase esistente; dobbiamo specificare il device a cui associamo la classe; quindi dobbiamo definire l'albero gerarchico delle classi . Infatti ogni qual volta lavoriamo con le classi definiamo un albero che ad ogni ramo associa un flusso di traffico. I rami vanno denominati tramite una dicitura x:y del tipo:



Fig. 3.5


Le classi definibili sono:


Prima di fare un esempio sull'uso delle classi vediamo anche i filtri.


3.2.2.3 tc filter

[alec@genni alec]$ tc filter help

Usage: tc filter [ add | del | change | get ] dev STRING

[ pref PRIO ] [ protocol PROTO ]

[ estimator INTERVAL TIME_CONSTANT ]

[ root | classid CLASSID ] [ handle FILTERID ]

[ [ FILTER_TYPE ] [ help | OPTIONS ] ]


tc filter show [ dev STRING ] [ root | parent CLASSID ]

Where:

FILTER_TYPE := { rsvp | u32 | fw | route | etc. }

FILTERID := ... format depends on classifier, see there

OPTIONS := ... try tc filter add <desired FILTER_KIND> help

I filtri sono gli oggetti che effettivamente smistano il traffico. Sono in grado di guardare dentro il pacchetto il campo dell'header che contiene le informazioni discriminatorie e di associare al pacchetto la classe corrispondente o semplicemente il ramo corrispondente x:y di un albero.

I più importanti criteri discriminanti sono:


Usage: ... fw [ classid CLASSID ] [ police POLICE_SPEC ]

POLICE_SPEC := ... look at TBF

Usage: ... u32 [ match SELECTOR ... ] [ link HTID ] [ classid CLASSID ]

[ police POLICE_SPEC ] [ offset OFFSET_SPEC ]

[ ht HTID ] [ hashkey HASHKEY_SPEC ]

[ sample SAMPLE ]

Where: SELECTOR := SAMPLE SAMPLE ...

SAMPLE := { ip | ip6 | udp | tcp | icmp | u{32|16|8} } SAMPLE_ARGS

Usage: ... route [ from REALM | fromif TAG ] [ to REALM ]

[ flowid CLASSID ] [ police POLICE_SPEC ]

POLICE_SPEC := ... look at TBF

Usage: ... rsvp ipproto PROTOCOL session DST[/PORT | GPI ]

[ sender SRC[/PORT | GPI ]

[ classid CLASSID ] [ police POLICE_SPEC ]

[ tunnelid ID ] [ tunnel ID skip NUMBER ]

Where: GPI := { flowlabel NUMBER | spi/ah SPI | spi/esp SPI |

u{8|16|32} NUMBER mask MASK at OFFSET}

POLICE_SPEC := ... look at TBF

FILTERID := X:Y

      1. Esempio di tc

Poniamo di voler suddividere la banda a disposizione (10Mbit) della mia macchina (che poniamo funga anche da router ) come schematizzato:



Aggiungiamo lo acheduler delle classi CBQ all'interfacia eth0:


# tc qdisc add dev eth0 root handle1: cbq bandwhidth 10Mbit avpkt 1000

quindi creiamo l'albero delle classi .Prima la classe radice:


# tc class add dev eth0 parent 1:0 classid 1:10 cbq bandwidth 10Mbit rate 10Mbit allot 1514 weight 1Mbit prio 8 maxburst 20 avpkt 1000


Quindi le sottoclassi:


# tc class add dev eth0 parent 1:10 classid 1:11 cbq bandwidth 10Mbit rate 1Mbit allot 1514 weight 100kbit prio 5 maxburst 2o avpkt 1000

# tc class add dev eth0 parent 1:10 classid 1:12 cbq bandwidth 10Mbit rate 3Mbit allot 1514 weight 100kbit prio 5 maxburst 2o avpkt 1000

# tc class add dev eth0 parent 1:10 classid 1:13 cbq bandwidth 10Mbit rate 6Mbit allot 1514 weight 100kbit prio 5 maxburst 2o avpkt 1000




Fig. 3.7

Ora dobbiamo associare le tre tipologie di traffico alle tre classi create. Dobbiamo quindi dichiarare tre filtri , uno per ogni flusso, che catturino i pacchetti che gli competono. I filtri come abbiamo visto guardano alcuni campi dell'header settati opportunamente . Se per esempio poniamo che sia stato settato il campo fw a 1 per il traffico http ,a 2 per il telnet e 3 per il resto i filtri dovranno così essere dichiarati:


# tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 1 fw classid 1:11

# tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 2 fw classid 1:12

# tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 3 fw classid 1:13


La prima istruzione ad esmpio ci dice che i pacchetti marchiati 1 fw vengono associati alla classe 1:11.

Ora la questione aperta è capire come possiamo intervenire per marchiare i pacchetti o come intervenire sui campi dell'header per essere parte attiva nella definizione della QoS. Con questo scopo andiamo a conoscere il comando iptables.



      1. Iptables


Iptables è usato per settare, gestire, e ispezionare le tavole delle regole dei filtri per i pacchetti IP nel Kernel di Linux. Possono essre definite diverse tavole. Ogni tavola contiene una serie di regole detta catena in quanto le regole vengono controllate una ad una seguendo un certo ordine e la prima che combacia col pacchetto viene selezionata.




Fig . 3.8



Gli obiettivi a cui raggiungere una volta selezionato il pacchetto possono essere ad esempio l'accettazione del pacchetto (ACCEPT), la sua distruzione (DROP) o anche il marchiare il pacchetto (MARK) o la ridefinizione del campo TOS nell'header.

Iptables ha 4 catene predefinite che possono essere settate a nostro piacimento ma mai essere cancellate del tutto. Queste sono le catene di INPUT, di OUTPUT, di PREROUTING edi FORWARD. Cerchiamo di definire la loro posizione capendo in che ordine vengano consultate dal Kernel.



Fig. 3.9

La catena di PREROUTING interviene sul pacchetto prima che questo venga analizzato dalla routing table . Altrimenti i pacchetti vengono normalmente analizzati prima di essere reindirizzati sulla queuing discipline o prima di entrare negli strati superiori in locale.

Ora vista la struttura generale vediamo a grandi linee i possibili comandi definibili .

Comandi iptables

Oltre ai target predefiniti come ACCEPT o DROP con iptables sono definibili degli altri obiettivi da specificare con la sintassi : ...-j TARGET-EXTENSIONS options :

MARK --set-mark value : marchia i pacchetti

REJECT --reject-with type : rispedisce indietro i pacchetti co un certo tipo di errore come

icmp-net(host,port)-unreachable(prohibided)

TOS --set-tos value : setta gli otto bit del capo TOS



      1. Esempio con iptables

        Possiamo ora concludere l'esempio precedente facendo in modo che i pacchetti appartenenti ai tre tipo di traffico (web,telnet,altro) vengano marchiati con tre valori differenti in modo tale da essere riconosciuti dal tc filter fw definito.

# iptable -A FORWARD -p tcp -d 10.0.1.0 destination-port 23 -j ACCEPT MARK

--set-mark 1

# iptable -A FORWARD -p tcp -d 10.0.1.0 destination-port 80 -j ACCEPT MARK

--set-mark 1

# iptable -A FORWARD -p tcp -d 10.0.1.0 -j ACCEPT MARK --set-mark 1


In questo modo i pacchetti che transitano dall'esterno verso la routing table vengono reindirizzati. Quelli in transito a seconda del tipo vengono marchiati nella catena di FORWARD da iptables che funge da firewall. La queuing discipline seguente riconosce i tre marchi e tramite questi identifica i tre tipi di traffico trattandoli nei modi dovuti ad ognuno.



Fig. 3.10

    1. Soluzioni implementate e relativi test


A seguito dello studio delle potenzialità del Networking messe a disposizione dal kernel di Linux cerchiamo di definire quali siano le nostre necessità in modo da progettare ed in seguito testare un controllo del traffico appropriato.


Come primo parametro implementativo abbiamo le tipologie di traffico che dovremo trattare.

L'host genni oltre a fornire i servizi H.323 dovrà anche continuare a offrire tutte le funzionalità di un normale PC. Dovrà quindi continuare ad interfacciarsi alla rete di ateneo essendo in grado di mandare e ricevere e-mail (protocollo smtp) o procedere ad un download ftp, oltre ovviamente al normale traffico TCP/IP. Consideriamo che per queste tipologie di traffico il comportamento dell'host genni non debba risentire in alcun modo dello shaping del traffico in uscita che noi andremo ad imporre. Ho deciso quindi dividere il traffico in due flussi separati, uno dei quali individui in qualche modo ( TOS, porte , protocollo) il traffico di videoconferenza, mentre l'altro individui tutto il resto del traffico che dovrà essere trattato con le stesse priorità individuate solitamente tramite il campo TOS (Type Of Service).


Come secondo fondamentale parametro dovremo definire la banda massima da assegnare ai servizi H.323 ed eventualmente se ci interessa anche quella da assegnare al restante traffico. Questo parametro dovrà essere definito a seguito di test sulla qualità del servizio di videoconferenza risultante da diverse limitazioni di banda.


Molti altri parametri occorre definire al momento della dichiarazione del comando. Come abbiamo visto ci sono parametri legati alla tipologia dello shaper . Ad esempio nella definizione di una qdisc TBF dobbiamo definire, oltre al rate con cui vengono rilasciati i gettoni, anche la dimensione del secchio e il tempo di latenza massimo all'interno della coda.


Le architetture di gestione del traffico che ho considerato come più opportune per la realizzazione del nostro scopo prevedono sia qdisc classless che qdisc classbased. La prima è costutuita da uno scheduler PRIO con a valle due TBF, mentre la seconda prevede la definizione di due classi distinte caratterizzate al meglio grazie ai molto parametri previsti dalle qdisc CBQ.

3.3.1 La qdisc classless: PRIO + TBF


Lo scheduler PRIO, come visto nei paragrafi precedenti di questo capitolo, di default si comporta in pratica come una semplice FIFO. Divide il traffico in tre bande 0,1,2 che vengono servite in ordine crescente. La 1 viene servita solo quando la coda 0 e vuota e la 2 a sua volta viene servita solo quando la 2 è vuota. Questa priorita è definita dalla priomap che si basa sul campo TOS definito all'interno dell'header IP di ogni pacchetto. La differenza è che nel caso della qdisc PRIO noi possiamo modificare queta priomap o semplicemente trascurarla indirizzando il traffico sulle bande attrverso la definizione di filtri associati alle bande. Nel nostro caso possiamo associare i due flussi di traffico a due bande della disciplina PRIO. In questo modo però il traffico non è ancora limitato ma solo smistato.

Per limitarlo occorre definire due code d'uscita associate alle due bande. Tramite una TBF fissiamo quindi una rate massimo per ogni banda.


Andiamo a vedere passo passo le istruzioni da assegnare per la definizione dello shaper.

Per prima cosa dobbiamo essere sicuri che non siano definiti altre qdisc o filtri:


[root@genni alec]# iptables -L -t mangle

Chain PREROUTING (policy ACCEPT)

target prot opt source destination


Chain OUTPUT (policy ACCEPT)

target prot opt source destination

così ci accertiamo che non sia settato alcun firewall in uscita da genni.

Vediamo se è presente qualche qdisc:


[root@genni alec]#tc -d qdisc show dev eth0

[root@genni alec]#

abbiamo specificato di accertarci dell'assenza di qdisc sull'interfaccia di rete eth0 che è l'unica presente in genni, altrimenti avremo dovuto controllare anche le altre.

Effuttuiamo lo stesso controllo anche su classi e filtri :


[alec@genni alec]$ tc -d class show dev eth0

[alec@genni alec]$

[alec@genni alec]$ tc -d filter show dev eth0

[alec@genni alec]$

In realtà questo controllo è superfluo in quanto non possono esistere classi e filtri appesi nel nulla. Questi devono essere sempre associati ad uno scheduler e se questo viene cancellato vengono cancellati anche i filtri e le classi ad esso collegate.


Come primo passo definiamo i due flussi colorandoli tramite un marchio che il firewal appone sui paccchetti e che ha senso solo all'interno dell'host. Usiamo iptables:


[root@genni alec]# iptables -A OUTPUT -t mangle -s 151.100.11.28 -j MARK --set-mark 2

[root@genni alec]# iptables -A OUTPUT -t mangle -p udp -s 151.100.11.28 -m tos --tos 0x10 -j MARK --set-mark 1


Abbiamo deciso di individuare il traffico tramite il protocollo UDP e il campo TOS che nel caso dell'H.323 è il classico delle comunicazioni in tempo reale: Minimize Delay (0x10). Mentre tutto il resto del traffico viene definito genericamente come tutto il traffico proveniente dall'host 151.100.11.28 cioè genni. Per specificare meglio il traffico si potrebbe anche imporre la condizione sulle porte usate dall'openmcu e dai client H.323 in genere, cioè le porte 5000-5003. Si è ottenuto un medesimo risultato ma è più sensibile a eventuali richieste sballate o volutamente modificate in fase di instaurazione della chiamata da parte di un utente. La soluzione da me scelta risulta essere più conservativa anche se meno chirurgica.

Particolare attenzione va messa nell'ordine in cui si danno le regole che vanno apposte dalle più generali a quelle più particolari. Quindi va prima quella che seleziona tutto il traffico e poi quella che colora il traffico UDP con campo TOS 0x10. Questo perchè le regole del firewall non funzionano come dei filtri deviatori di traffico ma come dei veri e propri ostacoli al passaggio dei pacchetti. Nelle due regole definite è sottintesa la politica ACCEPT che fa passare oltre i pacchetti con la condizione di marchiarli. Se vessi usato L'opzione DROP i pacchetti sarebbero sati scartati. Il pacchetto arrivando incontra da principio la prima regola che colora indifferentemente ogni pacchetto marchiandolo 1 quindi arriva al secondo muro che marchia il traffico UDP con TOS 0x10 con 2, mentre lascia invariato il marchio degli altri. Se avessi invertito l'ordine comunque tutti i pacchetti sarebbero stati marchiati 2.

Chiusa questa parentesi, che mi ha fatto perdere a suo tempo due giorni di lavoro, controlliamo se le modifiche da noi apportate sono andate a buon fine:


[root@genni alec]# iptables -L -t mangle

Chain PREROUTING (policy ACCEPT)

target prot opt source destination


Chain OUTPUT (policy ACCEPT)

target prot opt source destination

MARK all -- genni.ing.uniroma1.it anywhere MARK set 0x2

MARK udp -- genni.ing.uniroma1.it anywhere TOS match Minimize-Delay MARK set 0x1


Ora andiamo a definire la qdisc. Per prima cosa lo scheduler PRIO :


[root@genni alec]# tc qdisc add dev eth0 root handle 1: prio


[root@genni alec]# tc -d qdisc show dev eth0

qdisc prio 1: bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1


Di default la PRIO definisce una radice 1: e tre bande con priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1 che definisce la prorità delle 16 configurazioni possibili del campo TOS.

Io ho aggirato la priomap definendo due filtri:


[root@genni alec]# tc filter add dev eth0 protocol ip parent 1: handle 1 fw classid 1:1

[root@genni alec]# tc filter add dev eth0 protocol ip parent 1: handle 2 fw classid 1:2


[root@genni alec]# tc -d filter show dev eth0

filter parent 1: protocol ip pref 49151 fw

filter parent 1: protocol ip pref 49151 fw handle 0x1 classid 1:1

filter parent 1: protocol ip pref 49152 fw

filter parent 1: protocol ip pref 49152 fw handle 0x1 classid 1:1


A questo punto come detto prima associo alle due bande delle TBF per limitare il rate delle bande:


[root@genni alec]# tc qdisc add dev eth0 parent 1:1 handle 10: tbf rate $RATE_A burst 500kb latency 140ms peakrate 1mbit minburst 1540


[root@genni alec]# tc qdisc add dev eth0 parent 1:2 handle 20: tbf rate $RATE_B burst 500kb latency 140ms peakrate 1mbit minburst 1540


Il valori di rate è inespresso perche sarà quello che varieremo nel corso dei test, mentre nel corso di prove precedenti si sono definiti i valori ottimali per le altre variabili.Ponendo ad esempio RATE_A = 0.3mbit e RATE_B = 0.7mbit otteniamo:


[root@genni alec]# tc -d qdisc show dev eth0

qdisc tbf 20: rate 91750bps burst 500Kb/8 mpu 0b peakrate 1Mbit mtu 1539b/8 mpu 0b

lat 170.9ms

qdisc tbf 10: rate 39321bps burst 500Kb/8 mpu 0b peakrate 1Mbit mtu 1539b/8 mpu 0b

lat 170.9ms

qdisc prio 1: bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1


quello che otteniamo è un'architettura del tipo:


Fig. 3.11



3.3.2La qdisc CBQ


Nella CBQ definiamo due tipi di classi associati ai due flussi di traffico che vogliamo siano gestiti. Dopo aver controllato come in precedenza l'eventuale esistenza di elementi per il controllo del traffico attivi già attivi, procediamo alla colorazione del traffico in uscita tramite iptables. L'operazione è identica al caso di qdisc PRIO quindi non ripeteremo quanto detto.

Per prima cosa allora definiamo lo scheduler CBQ:


[root@genni alec]# tc qdisc add dev eth0 root handle 10: cbq bandwidth 4Mbit avpkt 1000


La banda qui definita non è un limite ma solo un'informazione che serve allo scheduler per parametrizzare la media mobile che è alla base dello shaper CBQ.

Definiamo quindi la radice dell'albero delle classi:


[root@genni alec]# tc class add dev eth0 parent 10: classid 10:1 cbq bandwidth 4Mbit rate 1Mbit allot 1514 prio 8 maxburst 20 avpkt 1000 bounded


Particolare attenzione va posta al rate e alla specifica baunded. Il rate specificato qui e il rate totale di tutta la radice e i suoi rami e la parola baunded significa che non può in alcun modo in caso di necessità prendere in prestito banda da altre qdisc.

Definiamo ora le due clasii vere e proprie:

[root@genni alec]# tc class add dev eth0 parent 10:1 classid 10:2 cbq bandwidth 4Mbit rate $RATE_A allot 1514 prio 5 maxburst 20 avpkt 1000 bounded


[root@genni alec]# tc class add dev eth0 parent 10:1 classid 10:3 cbq bandwidth 4Mbit rate $RATE_B allot 1514 prio 5 maxburst 20 avpkt 1000


Anche qui è lasciato in forma di varianibe il rate che sarà variato nel corso dei test. E' importante notare che solo la classe 10:2 è baunded mentre la 10:3 se satura può chiedere in prestito alla 10:2 della banda se questa non è attualmente interamente utilizzata. Assoceremo il traffico marchiato con 1 proprio alla classe 10:2. In pratica vogliamo che comenque il traffico H.323 non superi un rate massimo, mentre per il traffico ordinario vogliamo siano possibili picchi fino al massimo della banda consentita dalla rete a genni, così come sarebbe ordinariamente .

Definiamo quindi i filtri:


[root@genni alec]# tc filter add dev eth0 parent 10:1 protocol ip prio 10 handle 1 fw

flowid 10:2

[root@genni alec]# tc filter add dev eth0 parent 10:1 protocol ip prio 10 handle 2 fw

flowid 10:3


Con questi comandi le impostazioni risultano:

qdisc:

qdisc cbq 10: rate 4Mbit cell 8b (bounded,isolated) prio no-transmit/8 weight 4Mbit allot 1514b

level 2 ewma 5 avpkt 1000b maxidle 58us


classi:

class cbq 10: root rate 4Mbit cell 8b (bounded,isolated) prio no-transmit/8 weight 4Mbit allot 1514b

level 2 ewma 5 avpkt 1000b maxidle 58us

class cbq 10:1 parent 10: rate 1Mbit cell 8b (bounded) prio no-transmit/8 allot 1514b

level 1 ewma 10 avpkt 1000b maxidle 112us

class cbq 10:2 parent 10:1 rate 19660bps cell 8b (bounded) prio 5/5 weight 19660bps allot 1514b

level 0 ewma 5 avpkt 1000b maxidle 43422us

class cbq 10:3 parent 10:1 rate 1Mbit cell 8b prio 5/5 weight 1Mbit allot 1514b

level 0 ewma 5 avpkt 1000b maxidle 5074us


filtri:

filter parent 10: protocol ip pref 10 fw

filter parent 10: protocol ip pref 10 fw handle 0x1 classid 10:2

filter parent 10: protocol ip pref 10 fw handle 0x2 classid 10:3


firewall:

Chain PREROUTING (policy ACCEPT)

target prot opt source destination


Chain OUTPUT (policy ACCEPT)

target prot opt source destination

MARK all -- genni.ing.uniroma1.it anywhere MARK set 0x2

MARK udp -- genni.ing.uniroma1.it anywhere TOS match Minimize-Delay MARK set 0x1

l'architettura risultante è simile alla precedente:


Fig. 3.12


3.3.3 Test di funzionamento degli shaper


Controlliamo ora, prima dei test di qualità, l'effettivo funzionamento degli shaper. Per fare ciò usiamo il programma nload che controlla il traffico in ingresso e uscita dall'interfaccia di rete eth0.




Fig. 3.13


Facciamo partire ohphone sia su genni che su comel tramite il comando:

[alec@genni alec]$ ohphone -ln --videotransmit --videoreceive x11

Una volta connessi ossserviamo che facendo scorrere immagini prese da scheda TV presente su genni, questo host ha un traffico medio di uscita che si assesta oltre i 500kbit/s con una oscillazione costante da cirac 280kbit/s a 850kbit/s.


Mettiamo in funzione ora lo shaper PRIO con una limitazione del rate in uscita di 300 kbit/s.

Osserviamo che dopo 4-5 secondi di assestamento lo shaper incomincia a non pernetere rate superiori ai 300kbit/s imponendo così una media di circa 220kbit/s.

Guardiamo le statistiche :

[root@genni alec]# tc -s qdisc show dev eth0

qdisc tbf 20: rate 91750bps burst 500Kb peakrate 1Mbit minburst 1539b lat 170.9ms

Sent 153789 bytes 2302 pkts (dropped 0, overlimits 0)


qdisc tbf 10: rate 39321bps burst 500Kb peakrate 1Mbit minburst 1539b lat 170.9ms

Sent 3433524 bytes 3772 pkts (dropped 3856, overlimits 17232)

backlog 19851b 21p


qdisc prio 1: bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1

Sent 3588292 bytes 6075 pkts (dropped 3856, overlimits 0)

backlog 21p



Eliminiamo ora la qdisc PRIO e inseriamo le istruzioni per la qdisc CBQ con la stesa limitazione sul rate massimo. Anche qui lo shaper ha un tempo di atenza anche se molto più breve intorno ai 2 secondi, quindi anche in questo caso il rate si assesta su massimi intorno ai 300kbit/s e la media sui 220. Guardiamo le statistiche:

[root@genni alec]# tc -s class show dev eth0

class cbq 10: root rate 4Mbit (bounded,isolated) prio no-transmit

Sent 7816759 bytes 8262 pkts (dropped 0, overlimits 0)

borrowed 0 overactions 0 avgidle 1562 undertime 0

class cbq 10:1 parent 10: rate 1Mbit (bounded) prio no-transmit

Sent 7814554 bytes 8254 pkts (dropped 0, overlimits 0)

borrowed 0 overactions 0 avgidle 94717 undertime 0

class cbq 10:2 parent 10:1 rate 39321bps (bounded) prio 5

Sent 7806605 bytes 8168 pkts (dropped 0, overlimits 16582)

backlog 53p

borrowed 0 overactions 6168 avgidle -5741 undertime 18809

class cbq 10:3 parent 10:1 rate 1Mbit prio 5

Sent 7949 bytes 86 pkts (dropped 0, overlimits 0)

borrowed 0 overactions 0 avgidle 133045 undertime 0

La classe 10:2 ha spedito 8168 pacchetti mentre ce ne sono stati 16582 andati oltre il limite.

Gli shaper quindi sono stati implementati correttamente , ora bisogna analizzare l'impatto della limitazione di banda sulla qualità dell'immagine trasmessa sotto l'azione delle due tecniche di controllo del traffico.



3.4.1 Test QoS

Provato l'effettivo funzionamento dei limitatori di banda, vediamo che effetto questi hanno sulla trasmissione di filmati tramite software di comunicazione H.323. Come sequenze di test si sono prese in considerazione due tipologie di trasmissione. La prima dovrebbe simulare il tipo di sequenze video generate durante una videoconferenza con l'utente che parla inquadrato in primo piano, o al massimo in mezzo busto, con uno sfondo generalmente fisso. La seconda invece che simula una normale trasmissione televisiva tipo una sit-com.

I due filmati scelti sono stati presi rispettivamente da una lezione del consorzio nettuno su Rai Sat Nettuno e dalla sit-com Friends su Rai Sat Fiction, ed hanno la durata di un minuto.

Le due sequenze hanno in origine due bit rate molto diversi. Infatti la sequenza della videodidattica, che d'ora in poi denomineremo semplicemente Nettuno, presenta un rate medio di 190Kbit/s con oscillazioni dai 100 ai 300Kbit/s, mentre la sequenza della sit-com, che d'ora in poi chiameremo Friends, presenta un bit rate ben più alto. Il valore medio si attesta sui 500Kbit/sec con oscillazioni dai 250 agli 850Kbit/s. Per capire quindi quale dei due shaper utilizzare e come settare la banda disponibile nel nostro controllore del traffico abbiamo previsto una serie di test variando via via shaper, banda e sequenza video.







schema prove

Rate (Kbit/s)

Shaper

Sequenza

150

PRIO + TBF

Netuno, Friends

150

CBQ

Netuno, Friends

250

PRIO + TBF

Netuno, Friends

250

CBQ

Netuno, Friends

500

PRIO + TBF

Friends

500

CBQ

Friends

750

PRIO + TBF

Friends

750

CBQ

Friends

.Fig. 3.14

Per il giudizio ci siamo avvalsi della metodologia Doppio Stimolo a Scala di Degrado (DSIS - Double-Stimolus Impairment Scale) la quale prevede che ogni presentazione è costituita da una coppia di stimoli: Il primo è la sequenza di riferimento, il seondo quella di test. L' insoddisfazione dei valutatori è quantificata apponendo una croce su uno dei cinque livelli di degrado presenti nella scala:


Ho usato questa scala perchè tenere memoria dei test all'interno del PC ho dovuto comunque usare un codifica che di per se aggiunge deterioramento sia all'originale che alle sequenza di test. Apriamo una piccola parentesi su quali mezzi si sono usati per questa memorizzazione dei test. Nell'ohphone si è sfruttata l'opzione --videoreceive ppm la quale, invece di aprire una finestra contenente le immagini ricevute , memorizza una serie di immagini campionate della sequenza ricevuta. Cosa importante da mettere in evidenza è che il periodo di campionamento non è fisso ma dipende da vari fattori come il rate della sequenza video e il refresh dei quadri dell'immagine. Ottenuti i frames si è proceduto ad una codifica degli stessi in un filmato mpeg tramite il software mpeg-2 del MPEG Software Simulation Group.

Incominciamo a parlare dei risultati delle prove.

Impostiamo lo shaper PRIO su un rate trasmissivo di 150Kbit/s ed andiamo a lanciare ohphone sia sull'host genni che su comel. Quindi iniziamo una sessione H.323. Comel non ha alcuna sorgente video quindi trasmette l'immagine di default, mentre genni trasmette cio che proviene da un videregistratore che ho sistemato in ingresso alla scheda TV.



Passiamo la sequenza Nettuno. Le immagini non risultano molto deteriorate sulla scala

Fig. 3.15. Frames 271 e 288 di nettuno.150.tbf


DSIS, poteremo definirlo come un peggioramento Percettibile ma non fastidioso. La percezione è visibile soprattutto da effetti sulla mano che è l'unico elemento molto monile del quadro ma l'immagine è comunque abbastanza fluida.


Le cose sono ben diverse per la sequenza Friends. In questo caso la scena è addirittura incomprensibile e risultando una somma scomposta di quadri. Qui dare un giudizio è praticamente inutile comunque nella nostra scala sarebbe decisamente un Molto fastidioso.



Fig.3.16. Frame 156 di friends.150.tbf


Interessante è passare ora alla disciplina CBQ. Innanzi tutto il frame 156 di friends.150.tbf corrisponde al frame 33 di friends.150.cbq. Questo vuol dire che comel riceve molti meno quadri da genni. Infatti le immagini sotto disciplina CBQ arrivano a scatti ed il refresh totale del quadro avviene con una frequenza di 2-3 frame al secondo. Il numero totale di frame acquisiti dall'ohphone di comel e di soli 134 contro i 493 della TBF.

Questi pochi frame sono però senza deterioramento dell'immagine. Il deterioramento è comunque Fatidioso per la lentezza dell'aggiornamento.



Fig.3.17. Frame 33 di friends.150.cbq



Tornando ora alla sequenza Nettuno in questo caso la lentezza dell'aggiornamento è meno fastidiosa ma comunque classificabile Leggermente fastidiosa in quanto si nota il movimento a scatti della mano e della bocca.


Impostiamo ora la limitazione dello shaper PRIO ad un rate di 250 Kbit/s. Con queste impostazioni la sequenza Nettuno non presenta alcun effetto visbile di peggioramento. Questo è coerente col suo rate caratteristico di 290Kbit/s. Altrettanto non si può dire dello shaper CBQ. L'ohphone su comel resce a catturare in un minuto poco più di 800 frames contro i 1068 catturati sotto disciplina PRIO. L'immagine continua a risultare legermente a scatti, quindi il peggioramento risulta percettibile anche se non fastidioso.

I giudizi cambiano radicalmente se si va ad analizzare la sequenza Friends. Con la disciplina





Fig. 3.18. Frame 269 di friends.250.tbf



PRIO + TBF l'immagine continua ad aggiornarsi a quadri risultando Fastidiosa mentre sotto disciplina CBQ la situazione è migliore in quanto sebbene a scatti l'evoluzione della storia è più chiara e come sempre le immagini sono senza difetti. I frames raccoti in un minuto risultano 252, quindi circa 4 al secondo, contro i circa 130 della CBQ a 150Kbit/s. La sequenza risulta comunque leggermente Fastidisa.

Il deterioramento finisce di esssere fastidioso quando impostiamo lo shaper CBQ sui 500Kbit/s . In questa situazione l'immagine comincia anche ad essere fluida. I frames raccolti sono 754 quindi si ottiene una frequenza di quadro di 12-13 fps che sono una frequenza buona per applicazioni di questo tipo. Per veder questo possiamo notare la vicinanza di tre frames successivi comparandoli con tre frames successivi realativi alla stessa scena nel caso CBQ a 250Kbit/s.






Fig. 3.19 Frames 316-317-318 di Friends.500.CBQ




Fig. 3.20. Fames 128-129 di Friends.250.CBQ


Se passiamo ora alla TBF questa sopporta spostamenti lenti sia del campo che degli attori. Il deterioramneto è ancora visibile, non mina la conprensione della scena ma è definibile ancora Fastidioso. Sebbene lo shaper sia settato sul suo rate medio il taglio dei picchi trasmissivi, che nel caso di friends raggiungevano gli 850Kbit/s, si fa sentire sensibilmente. A questi rate è netta la superiorità della CBQ.



Fig. 3.21. Frames 304 di friends.500.tbf


Impostando infine il rate trasmissivo a 750Kbit/s nel caso CBQ si ha un deterioramento impercettibile della qualità trasmissiva mentre con lo shaper PRIO + TBF compare ogni tanto ancora qualche quadratino fouri fase.

Chiudiamo dicendo che i test sulla sequenza Nettuna oltre i 250Kbit/s hanno dato ovviamente come risultato un peggioramento impercettibile della qualità del servizio.

Riassumiami i risultati dei test e i dati più significativi in una tabella .


Rate(Kbit/s)

Shaper

Nettuno

Friends

Frames

DSIS

Frames

DSIS

150

PRIO + TBF

830

P

493

M

150

CBQ

444

L

134

F

250

PRIO + TBF

1068

I

611

M

250

CBQ

893

P

252

L

500

PRIO + TBF

-


577

F

500

CBQ

-


749

P

750

PRIO + TBF

-


852

L

750

CBQ

-


874

I

Fig. 3.22




      1. Considerazioni sui risultati ottenuti.


I risultati dei test hanno dato una grande diversità di risultati a seconda della tecnica di controllo del traffico adottata. A dir la verità non ci aspettavamo una così netta superiorità dello shaper CBQ. Cerchiamo quindi di dare una spiegazione dei risultati ottenuti.

Per comprendere appieno cosa sia successo bisogna approfondire il discorso legato alla codifica H.261 utilizzata nell'H.323. In questa codifica ogni frame viene diviso in Macro Blocks (MB) che codificano quadri da 16x16 pixel. Nel nostro caso l'immagine è in formato QCIF quindi 144x176 pixel, quindi ogni frame è formato da 99 MB.

Sebbene ogni MB porti con se informazioni come l'indicazione del picture start code e il temporal reference per la codifica appropriata dei quadri, sopra ai macroblocchi si è voluta creare una struttura di controllo in tempo reale delle operazioni di codifica. Questo ha portato alla aggiunta degli elementi denominati Group Of Blocks (GOB). Ogni GOB costituisce un frame della sequenza video codificata e porta con se una serie di informazioni di controllo come uno start code differente per ogni GOB, in modo tale che risulti più facile la rilevazione di eventuali errori, o un group number che metta in evidenza la perdita di un frame. Nel nostro caso utilizzando il formato video QCIF abbiamo 3 GOB ognuno formato da 33 MB.





Oltre a questo i pacchetti prima di essere rilasciati vengono accodati con disciplina FIFO all'uscita del codificatore. Con lo scopo di ottenere un rate trasmissivo il più possibile costante, lo stato di riempimento della coda influenza la determinazione della soglia di quantizzazione del codificatore. Se la coda risulta piena viene alzata questa soglia. Vengono definite quindi la low trshold e la high treshold sulla coda.





Chiudiamo la parentesi sulla codifica H.261 e ritorniamo al nostro quesito: perché i due shaper hanno avuto comportamenti così diversi?

Abbiamo visto che la codifica H.261 prevede meccanismi di controllo sia sulla codifica che sulla decodifica. Quando noi limitiamo il traffico il codificatore se ne accorge?

Per testare questo aspetto andiamo a vedere il traffico RTP scambiato tra i due host. Possiamo fare ciò avviando ohphone con opzione -tt che visualizza tutti i messaggi di controllo scambiati durante una connessione H.323.

///////////////////// INIZIA LA TRASMISSIONE DATI\\\\\\\\\\\\\\\


1:08.414 RTP Transmit statistics: packets=1990 octets=1787693 avgTime=9 maxTime=16 minTime=5

1:08.414 RTP SentSenderReport: ssrc=439861623 ntp=3230540219.1049273252 rtp=0 psent=1990 osent=1787693

1:09.414 RTP Transmit statistics: packets=2095 octets=1881131 avgTime=9 maxTime=12 minTime=5

1:09.414 RTP SentSenderReport: ssrc=439861623 ntp=3230540220.1049316192 rtp=0 psent=2095 osent=1881131

1:09.993 H323RTP Receiver written timestamp 167200

1:10.414 RTP Transmit statistics: packets=2201 octets=1977235 avgTime=9 maxTime=13 minTime=4

1:10.414 RTP SentSenderReport: ssrc=439861623 ntp=3230540221.1051493250 rtp=0 psent=2201 osent=1977235

1:11.414 RTP Transmit statistics: packets=2307 octets=2073576 avgTime=9 maxTime=12 minTime=4

1:11.414 RTP SentSenderReport: ssrc=439861623 ntp=3230540222.1050046172 rtp=0 psent=2307 osent=2073576

1:12.281 H323RTP Receiver written timestamp 183840

1:12.434 RTP Transmit statistics: packets=2412 octets=2168238 avgTime=9 maxTime=14 minTime=5

1:12.434 RTP SentSenderReport: ssrc=439861623 ntp=3230540223.1135050196 rtp=0 psent=2412 osent=2168238

1:13.290 RTP OnRxSenderReport: ssrc=2562893555 ntp=2002/5/16-14:14:12.889361 rtp=192160 psent=301 osent=39732

1:13.290 RTP Receive statistics: packets=301 octets=39732 lost=0 tooLate=76 order=0 avgTime=81 maxTime=251 minTime=0 jitter=152

1:13.290 RTP SentReceiverReport: ssrc=2562893555 fraction=0 lost=0 last_seq=44272 jitter=1217 lsr=0 dlsr=0

1:13.454 RTP Transmit statistics: packets=2517 octets=2264552 avgTime=9 maxTime=14 minTime=5

1:13.454 RTP SentSenderReport: ssrc=439861623 ntp=3230540224.1221299480 rtp=0 psent=2517 osent=2264552


Inizialmente non è inserito alcuno shaper. Sono visibili le statistiche di trasmissione dei pacchetti. Il valore interessante di cui osservare l'evoluzione è avgTime il quale indica il tempo medio di spedizione dei pacchetti da aprte della coda del codificatore. Inseriamo lo shaper CBQ.


/////////////// INIZIA AD OPERARE LA CBQ \\\\\\\\\\\\\\\\\\\\\\


1:14.321 H323RTP Receiver written timestamp 200480

1:16.385 H323RTP Receiver written timestamp 217120

1:18.564 RTP Transmit statistics: packets=2621 octets=2356677 avgTime=50 maxTime=1410 minTime=6

1:18.564 RTP SentSenderReport: ssrc=439861623 ntp=3230540229.1693356076 rtp=0 psent=2621 osent=2356677

1:23.504 RTP Transmit statistics: packets=2725 octets=2446566 avgTime=49 maxTime=1350 minTime=6

1:23.504 RTP SentSenderReport: ssrc=439861623 ntp=3230540234.1435926482 rtp=0 psent=2725 osent=2446566

1:28.574 RTP Transmit statistics: packets=2830 octets=2540072 avgTime=50 maxTime=1386 minTime=5

1:28.574 RTP SentSenderReport: ssrc=439861623 ntp=3230540239.1736270312 rtp=0 psent=2830 osent=2540072

1:31.558 H225 Received PDU: empty

1:31.558 H225 Handling PDU: Facility callRef=29648

1:31.558 H245 Received PDU: command miscellaneousCommand

1:31.558 H261Codec lost partial picture message ignored, not implemented

1:31.558 Codec OnMiscellaneousCommand: lostPartialPicture

1:31.558 H323 InternalEstablishedConnectionCheck: connectionState=EstablishedConnection fastStartState=FastStartDisabled

1:31.559 H323 InternalEstablishedConnectionCheck: connectionState=EstablishedConnection fastStartState=FastStartDisabled


Come possiamo vedre il codificatore si accorge instantaneamente delle difficoltà incontrate nell'invio dei pacchetti e reagisce rallentando il rate di spedizione dei pacchetti da 9 a 50ms. Non appena stacco la CBQ il parametro avgTime si riporta al valore di 9ms.


//////////////// STACCO LA CBQ \\\\\\\\\\\\\\\\\\\\\\\\\\\


1:31.884 RTP Transmit statistics: packets=2936 octets=2637029 avgTime=32 maxTime=1300 minTime=4

1:31.884 RTP SentSenderReport: ssrc=439861623 ntp=3230540242.3067590660 rtp=0 psent=2936 osent=2637029

1:32.884 RTP Transmit statistics: packets=3042 octets=2735415 avgTime=9 maxTime=13 minTime=5

1:32.884 RTP SentSenderReport: ssrc=439861623 ntp=3230540243.3067302962 rtp=0 psent=3042 osent=2735415

1:33.884 RTP Transmit statistics: packets=3147 octets=2829292 avgTime=9 maxTime=12 minTime=5


.........................


1:42.914 RTP Transmit statistics: packets=4116 octets=3705996 avgTime=9 maxTime=12 minTime=5

1:42.914 RTP SentSenderReport: ssrc=439861623 ntp=3230540253.3196268958 rtp=0 psent=4116 osent=3705996


Inseriamo ora lo shaper PRIO +TBF.


////////////////// ATTACCO LA PRIO + LA TBF\\\\\\\\\\\\\\\\


1:43.385 H225 Received PDU: empty

1:43.385 H225 Handling PDU: Facility callRef=29648

1:43.386 H245 Received PDU: command miscellaneousCommand

1:43.386 H261Codec lost partial picture message ignored, not implemented

1:43.386 Codec OnMiscellaneousCommand: lostPartialPicture

1:43.386 H323 InternalEstablishedConnectionCheck: connectionState=EstablishedConnection fastStartState=FastStartDisabled

1:43.386 H323 InternalEstablishedConnectionCheck: connectionState=EstablishedConnection fastStartState=FastStartDisabled

1:43.531 H225 Received PDU: empty

1:43.531 H225 Handling PDU: Facility callRef=29648

1:43.532 H245 Received PDU: command miscellaneousCommand

1:43.532 H261Codec lost partial picture message ignored, not implemented

1:43.532 Codec OnMiscellaneousCommand: lostPartialPicture

1:43.532 H323 InternalEstablishedConnectionCheck: connectionState=EstablishedConnection fastStartState=FastStartDisabled

1:43.532 H323 InternalEstablishedConnectionCheck: connectionState=EstablishedConnection fastStartState=FastStartDisabled

1:43.914 RTP Transmit statistics: packets=4222 octets=3801811 avgTime=9 maxTime=11 minTime=5

1:43.914 RTP SentSenderReport: ssrc=439861623 ntp=3230540254.3196247488 rtp=0 psent=4222 osent=3801811

1:44.111 H225 Received PDU: empty

1:44.111 H225 Handling PDU: Facility callRef=29648

1:44.111 H245 Received PDU: command miscellaneousCommand

1:44.111 H261Codec lost partial picture message ignored, not implemented

1:44.111 Codec OnMiscellaneousCommand: lostPartialPicture

1:44.111 H323 InternalEstablishedConnectionCheck: connectionState=EstablishedConnection fastStartState=FastStartDisabled

1:44.111 H323 InternalEstablishedConnectionCheck: connectionState=EstablishedConnection fastStartState=FastStartDisabled

1:44.301 H225 Received PDU: empty

1:44.301 H225 Handling PDU: Facility callRef=29648

1:44.301 H245 Received PDU: command miscellaneousCommand

1:44.301 H261Codec lost partial picture message ignored, not implemented

1:44.302 Codec OnMiscellaneousCommand: lostPartialPicture



Osserviamo come inizi un frequente scambio di messaggi ( anche 7-8 messaggi ogni millesimo di secondo!) . Questi indicano problemi di decodifica come continue perdite di parti di frame ma la codifica non reagisce in alcun modo inputando ciò a problemi di rete.

Alla luce di quanto osservato risulta chiaro come dal punto di vista del codificatore i pacchetti scartati dovuti al riempimento del secchio della TBF sono a tutti gli effetti inviati. La CBQ invece non scarta i pacchetti ma ne rinvia la trasmissione. Questo causa un riempimento della coda d'uscita del decodificatore il quale reagisce variando il rate di codifica.





























Page hosted at Laboratorio Telematico at Info-Com
Last Update ven gen 31 18:03:32 CET 2003