# [Howto] Limitare la banda

## egolf

Tradotto da "Bandwidth limiting howto  di abali".

0. Chi ha bisogno di questo howto?

 Gente che usa programmi p2p e vuole poter navigare a velocità normale limitando l' up/download del programma p2p;

 Gente che ha un server WEB/FTP/ecc.. e considerate la sua importanza piu bassa rispetto a quella del vostro lavoro normale al pc; 

 Persone che hanno una connessione DSL e hanno rallentamenti di download se stanno uploadando;

 Persone che sono curiose e vogliono controllare la banda in uscita dai propri pc;

1. Introduzione

Sul meccanismo di controllo della banda di Linux c' è molto da dire, cmq in questo howto non dirò tutto, visto che voglio scrivere una guida semplice per utenti che vogliono soluzioni semplici e pratiche a problemi che occorrono abbastanza spesso.

Prima di partire ecco le cose che questo howto non tratta:

 Primo non vi spiegerà come limitare la velocità di download, (Sezione 7 per più info).

 Secondo, non vi spiegherà come limitare la velocità totale di uno specifico client.

 Terzo, non vi spiegherà i concetti base del lavoro con reti, ne andrà troppo nei dettagli. Insomma è una guida per un utente medio con basilari conoscenze del funzionamento di TCP/IP.

2. Prerequisiti

Pet tutti gli esempi in questa guida avete bisogno di due pacchetti:

```
$ emerge sys-apps/iproute2

$ emerge net-firewall/iptables
```

Iptables non è richiesto se non usate i metodi avvanzati per classificare il traffico della rete. Cmq è un programma che ogni pc con accesso alla rete dovrebbe avere.

Nel vostro kernel dovreste avere come minimo questi moduli

```
Kernel 2.6.x

------------

Device Drivers --> Networking Support --> Networking options

[*] Network packet filtering (replaces ipchains)

QoS and/or fair queueing -->

<M> HTB packet scheduler

<M> SFQ queue

<M> U32 Classifier

[*] Traffic policing

Kernel 2.4.x

------------

Networking options --> IP: Netfilter Configuration

<*> IP tables support

Networking options --> QoS and/or fair queueing

<M> HTB packet scheduler

<M> SFQ queue

[*] Packet classifier API

<M>  U32 classifier
```

Raccomando di selezionare tutto sotto QoS e iptables, e compliarli come moduli (visto che non si sa mai di cosa di ha bisogno).

Il HTB packet schedulerè incluso dal kernel 2.4.20 in avanti; se avete un kernel piu vecchio uscire dalla tana e installatene uno piu recente.  :Smile: 

3. Come funziona la limitazione

La limitazione della banda (queueing) determina il modo in cui i dati vengono mandati dal vostro pc. Con iproute2 potete creare dell cosidette  classi per il traffico in uscita dal vostro pc e attaccare a ogniuna di queste classi un comportamento d'accodamento (qdisc),

La vostra coda in uscita  (egress) di default non ha classi e il comportamento d' accodamento è di tipo FIFO (First In, First Out, o meglio pacchetto che prima arriva prima va in rete).

Si puo dividere il traffico in uscita in tutte le classi che volete con un comportamento d' accodamento come volete.

Quando avtemo preparato le classi per il traffico, dovremo ancora classificare i singoli pachetti per metterli nella classe giusta. Questo sarà fatto tramite regole specifiche che usano le caratteristiche dei pachetti, quali porta di provenienza o IP di destinazione.

4. Creare le classi

L' unico comportamento d'accodamento che useremo in questa guida è il HTB (Hierarchical Token Bucket) qdisc (un piu veloce e intuitivo rimpiazzamento del  CBQ qdisc), perchè è piuttosto facile da imparare e si può usare anche per soluzioni piu complesse

In questo esempio creeremo 3 classi per il traffico in uscita, dove ogni classe ha un limite di velocità d' uscita diverso:

Se l' intefaccia dalla quale passa il vostro traffico d' uscita non è eth0, dovrete cambiare i comandi seguienti usando l' interfaccia apropriata (per esempio: ppp0, wlan0).

```
$ tc qdisc add dev eth0 root handle 1: htb default 10

$ tc class add dev eth0 parent 1: classid 1:1 htb rate 120kbit burst 6k

$ tc class add dev eth0 parent 1:1 classid 1:10 htb rate 120kbit burst 6k prio 1

$ tc class add dev eth0 parent 1:1 classid 1:20 htb rate  60kbit burst 6k prio 2

$ tc class add dev eth0 parent 1:1 classid 1:30 htb rate  30kbit burst 6k prio 3

$ tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10

$ tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10

$ tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10 
```

Ecco le spiegazioni:

```
$ tc qdisc add dev eth0 root handle 1: htb default 10
```

Questa linea aggiunge l' HTB qdisc al trattamento di base, e li da il "nome" 1:, che useremo piu tardi per riferici a questa coda.

default 10 il default vuole semplicemente dire che se non si danno altre indicazioni esplicite i pacchetti saranno messi nella classe  1:10.

```
$ tc class add dev eth0 parent 1: classid 1:1 htb rate 120kbit burst 6k
```

Questo comando aggiunge una sottoclasse 1:1 alla classe definita sopra.

rate 120kbit specifica che i questa classe non puo usare piu di 120kbit/s della banda.

burst 6k controlla la quantità di dati che possono uscire nello stesso momento a velocità massima.

Senza andare troppo nei dettagli il concetto di bust deriva dal fatto che la velocità della rete non è misurata istantaneamente, ma calcolata. Quindi se usate un boost troppo piccolo avrete velocità di trasmissione più basse rispetto al comportamento desiderato; se invece questa variabile è troppo grande la limitazione della banda diventa molto imprecisa o adirittura inutile.

Se non siete sicuri semplicemente non specificate questa variabile nel comando, iproute2 userà il valore più piccolo possibile.

Normalmente è una buona idea settare il root upload a un valore leggermente piu basso della vostra reale velocità d' uscita, cosi l' accodamento dei pacchetti non viene eseguito dal modem (probabilmente piu lento del pc), ma dal vostro sistema linux.

```
$ tc class add dev eth0 parent 1:1 classid 1:10 htb rate 120kbit burst 6k prio 1

$ tc class add dev eth0 parent 1:1 classid 1:20 htb rate  60kbit burst 6k prio 2

$ tc class add dev eth0 parent 1:1 classid 1:30 htb rate  30kbit burst 6k prio 3
```

Questi comandi sono sotto-classi, derivanti dalla classe specificata sopra.

Queste classi hanno il nome 1:10, 1:20 e 1:30.

1:10 (come magari ricordate è la classe di default), e ha gli stessi parametri come la classe sovrastante in quanto in questa classe faremo passare il traffico che non vogliamo limitare.

1:20è limitata a 60kbit/s, mentre 1:30 è limitata a 30kbit/s. 

Dando la priorità specifichiamo che per esempuo la classe 1:20 puo usare 60kbit/s di banda ma solo se la classe 1:10 lascia almeno 60kbit/s di banda non usati. Quindi se la nostro connessione è di 120kbit/s e la classe 1:10 ne ha bisongo 80, alla classe 1:20 rimangono 40k/s, e cosi via. La classe 1:30 è puo usare banda solo se le altre due classe ne lasciano un po' libera.

Se può servire eccovi  un alberello simpatico per chiarire un po':

```
                1:1

            120kbit/s

  1:10            1:20            1:30

120kbit/s   60kbit/s    30kbit/s

(prio 1)         (prio 2)      (prio 3)

```

HTB offre un infinità di possibilità grazie alla sua struttura hirarchica, queste possibilità sono ben documentate nella guida dell' utente, quindi non scendo in maggiori dettagli.

```
$ tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10

$ tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10

$ tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10

```

In fine queste line aggiungono un qdisc alle classi che abbiamo definito, Il SFQ (Stochastic Fairness Queueing) qdisc è un algoritmo piuttosto semplice che assicura che la banda a disposizione di ogni singola classe sia sfruttata da tutti gli appartententi della classe in modo equo.

Si raccomanda di usare sempre un qdisc visto che la velocità è maggiore rispetto all' accodamento FIFO, se i pacchetti non hanno un ToS (Type of Service) flag corretto settato (cosa che non capita spesso).

5. Classificare il singoli flussi

I flussi in uscita si possono assegnare alle classi usando il comando: tc filter. Se avete un albero di classi piuttosto semplice come quello sopra potete "attaccare" le vostre regole alla classe root, 1: nel nostro caso. Se invece avete un sistema piu complesso potete "attaccarle" a qualunque altra classe, nel vostro albero.

Esempi:

 Mettiamo che avete un amico/a che ha l' indirizzo IP  1.2.3.4 e scarica molto da voi, probabilmente volete mettere il traffico che va a lui/lei nella classe 1:30 cosi non vi usa piu di 30kbit/s di banda (magari aggiungete un netmask  /24 al numero IP):

```
$ tc filter add dev eth0 parent 1: protocol ip u32 match ip dst 1.2.3.4 flowid 1:30

```

 Un' altra situazione potrebbe ssere che state usando un server web sulla porta 80 e non volete che prenda tutta la vostra banda, quindi per sempio volete metterlo nella classe 1:20:

```
$ tc filter add dev eth0 parent 1: protocol ip u32 match ip sport 80 0xffff flowid 1:20

```

Potete anche usare i cosidetti marks che fate sui pacchetti usando iptables, che abilitano l' uso di regole avvanzate di iptables, non sopportate dal classificatore u32. Ma non essendo questo documento concepito come una guida a iptables faccio solo un esempio:

 Mettiamo che sto usando DC++ in wine, e voglio limitarne la banda in upload.  Iptables ha un estensione ingeniosa chiamata  owner (proprietario), che crea la possibilità di controllare un pacchetto uscente generato localmente da un processo un un dato UID, GID, PID, SID, o nome di comando.

Quindi cerco  "wineserver"  ("ps -A" per i nomi dei processi), e assegno un mark "2" a tutti i pachetti che vengono da quel processo, poi uso tc e assegno i pacchetti col mark 2 alla classe 1:30:

```
$ iptables -t mangle -A OUTPUT -m owner --cmd-owner wineserver -j MARK --set-mark 2

$ tc filter add dev eth0 protocol ip parent 1:0 handle 2 fw flowid 1:30

```

U32 e iptables hanno molte piu opzioni che magari vi possono risultare utili, quindi leggete la documentazione se vi serve qualcosa di più avanti.

In ogni caso non fate regole che si contraddicono a vicenda, e assegnate a ogni classe una priorità.

6. Comandi utili

Per vedere la lista di classi:

```
$ tc class show dev eth0

class htb 1:1 root rate 120Kbit ceil 120Kbit burst 6Kb cburst 1752b 

class htb 1:10 parent 1:1 leaf 10: prio 1 rate 120Kbit ceil 120Kbit burst 6Kb cburst 1752b 

class htb 1:20 parent 1:1 leaf 20: prio 2 rate 60Kbit ceil 60Kbit burst 6Kb cburst 1675b 

class htb 1:30 parent 1:1 leaf 30: prio 3 rate 30Kbit ceil 30Kbit burst 6Kb cburst 1637b 

```

Per vedere le statistiche relative alle classi:

```
$ tc -s class show dev eth0

class htb 1:1 root rate 120Kbit ceil 120Kbit burst 6Kb cburst 1752b 

 Sent 440085220 bytes 2961615 pkts (dropped 0, overlimits 0) 

 rate 5170bps 23pps 

 lended: 0 borrowed: 0 giants: 0

 tokens: 291200 ctokens: -1534

class htb 1:10 parent 1:1 leaf 10: prio 1 rate 120Kbit ceil 120Kbit burst 6Kb cburst 1752b 

 Sent 157506822 bytes 2213767 pkts (dropped 0, overlimits 0) 

 rate 1306bps 18pps 

 lended: 2213767 borrowed: 0 giants: 0

 tokens: 402094 ctokens: 109360

class htb 1:20 parent 1:1 leaf 20: prio 2 rate 60Kbit ceil 60Kbit burst 6Kb cburst 1675b 

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

 lended: 0 borrowed: 0 giants: 0

 tokens: 819200 ctokens: 223466

class htb 1:30 parent 1:1 leaf 30: prio 3 rate 30Kbit ceil 30Kbit burst 6Kb cburst 1637b 

 Sent 275743173 bytes 747867 pkts (dropped 34476, overlimits 0) 

 rate 3826bps 4pps backlog 19p 

 lended: 747848 borrowed: 0 giants: 0

 tokens: 728678 ctokens: -472923
```

Cancellare una classe:

```
$ tc qdisc del dev eth0 root
```

7. Limitare la banda in download

Come detto sopra questa guida vuole spiegare come limitare il traffico in uscita e non quello in ingresso, visto che è una cosa piu complicata dal momento che non potete controllare cosa la gente manda al vostro pc. Comunque l' internet odierno è basato sopratutto su TCP/IP, quindi avete basilarmente 3 modi come limitare il download:

Se i dati che arrivano sono piu grandi di quello che volete, potete iniziare a buttare (drop) i pacchetti che vi arrivano, a questo punto il pc da qui arrivano i dati dovrebbe riconoscere la perdita di pacchetti e abbassare la velocità con qui vi mandando i pacchetti, ma nella maggior parte dei casi non abbasseranno questa velocità.

Se conoscete il protocollo TCP/IP probabilmente avete notato che bisogna notificare al mittente il fatto di aver ricevuto un pacchetto. Questa risposta è chiamata ACK packet, se si facessero partire queste risposte con un po' di ritardo la velocità dovrebbe diminuire, ma cmq questa è teoria, e non l' ho mai visto in pratica.

TCP window manipulation (manipulazione delle finestre TCP) è il metodo migliore per influenzare velocità di flussi sulla rete, purtroppo non ci sono applicazioni open source che permettono questo.

8. Risorse

Per piu info eccovi alcuni link utili:

Linux Advanced Routing & Traffic Control, casa dell' howto

Homepage of HTB, un eccellente guida per l'utente

Traffic Shaping with Linux, una buona introduzione a iproute2

----------

## egolf

Ho cercato di tradurre il meglio possibile, se avete critiche o vedete qualche errore fatemelo sapere.  :Smile: 

Spero che possa servire a qualcuno questo howto.

----------

## xchris

OTTIMO HOWTO!!!

----------

## fedeliallalinea

Messo nei post utilissimi

----------

## egolf

Grazie  :Smile:  a tutti due

----------

## mouser

Veramente ottimo howto!!!

Complimenti

----------

## RedNeckCracker

per semplificare la vita:

http://sourceforge.net/projects/cbqinit

----------

## Truzzone

 *egolf wrote:*   

> ...
> 
> Spero che possa servire a qualcuno questo howto.

 

Proprio nel momento giusto, ieri avevo 'scoperto' la versione in Inglese, ora mi stampo subito questa in Italiano.

Grazie 1000   :Very Happy: 

Ciao by Truzzone   :Wink: 

----------

## gutter

I miei complimenti per l'ottimo articolo   :Very Happy: 

----------

## croot

Bellissimo!! grazie, veramente ottimo!!

----------

## motaboy

powerfull!

----------

## irontux

Ho seguito questa guida e devo dire che funziona bene. Solo non ho pensato ad una cosa: Io uso anche la scheda di rete per trasferire file attraverso la rete locale.

Come devo fare per far sì che ignori queste classi quando uso connessioni verso igli IP 10.0.0.x ?

----------

## Apetrini

Dio benedica egolf...

edit:

Per fare quel tipo di operazioni secondo me conviene usare il mark di iptables e poi fare shaping in base ai vari mark.

----------

