ADSL Bandwidth Management HOWTO

Dan Singletary

   <dvsing@sonicspike.net>
   Diario delle Revisioni
   Revisione 1.3 2003-04-07 Revisionato da: ds
   Aggiunta la sezione Link correlati.
   Revisione 1.2 2002-09-26 Revisionato da: ds
   Aggiunto il link alla nuova lista di discussione via email. Aggiunta
   un'informazione nella sezione riguardante il nuovo e migliore QoS per
   Linux, creato specificamente per l'ADSL e disponibile a breve.
   Revisione 1.1 2002-08-26 Revisionato da: ds
   Alcune correzioni (grazie alle molte persone che le hanno fatte
   notare!). Aggiunta un'informazione alla sezione sull'implementazione.
   Revisione 1.0 2002-08-21 Revisionato da: ds
   Miglior controllo sulla banda, pi teoria, aggiornato per i kernel
   2.4.
   Revisione 0.1 2001-08-06 Revisionato da: ds
   Pubblicazione iniziale

   Questo documento descrive come configurare un router Linux per
   controllare piu efficacemente il traffico in uscita di un modem ADSL o
   altro dispositivo con stesse propriet di larghezza di banda (cable
   modem, ISDN ecc.). Viene messa l'enfasi sull'abbassamento della
   latenza per il traffico interattivo anche quando la larghezza di banda
   in upstream e/o in downstream  completamente satura. Traduzione a
   cura di Michele Ferritto, ferritto@toglimi.libero.it, e revisione a
   cura di Sandro Cardelli.
     _________________________________________________________________

   Sommario
   1. Introduzione

        1.1. Nuove versioni di questo documento
        1.2. Liste di discussione
        1.3. Liberatoria
        1.4. Copyright and License
        1.5. Copyright e Licenza d'uso
        1.6. Feedback e correzioni

   2. Background

        2.1. Prerequisiti
        2.2. Schema
        2.3. Le Code Pacchetto(Packet Queues)

   3. Come Funziona

        3.1. Limitare il traffico uscente con Linux HTB
        3.2. Priorit di messa in coda con HTB
        3.3. Classificare i pacchetti uscenti con iptables
        3.4. Qualche piccola miglioria...
        3.5. Provare a limitare il traffico in arrivo

   4. Implementazione

        4.1. Avvertimenti
        4.2. Script: myshaper

   5. Test della nuova coda
   6. OK Funziona!! E adesso?
   7. Link correlati

1. Introduzione

   Lo scopo di questo documento  suggerire un modo per controllare il
   traffico in uscita su una connessione ADSL (o cable modem) a Internet.
   Il problema  che molte linee ADSL sono limitate nelle vicinanze dei
   128kbps per i trasferimenti upstream. Ad aggravare questo c' la coda
   dei pacchetti nel modem ADSL, la quale pu impiegare da 2 a 3 secondi
   per svuotarsi quando  piena. Ci significa che quando la larghezza di
   banda in upstream  completamente satura possono passare fino a 3
   secondi prima che qualsiasi altro nuovo pacchetto di dati possa uscire
   verso Internet, mettendo in crisi applicazioni interattive quali
   telnet e giochi in modalit multi-player.
     _________________________________________________________________

1.1. Nuove versioni di questo documento

   Si veda, per l'ultima versione di questo documento, sul World Wide Web
   presso l'URL: http://www.tldp.org.

   Nuove versioni di questo documento saranno trasferite ai vari siti
   Linux WWW e FTP, inclusa l'home page di LDP presso
   http://www.tldp.org.
     _________________________________________________________________

1.2. Liste di discussione

   Per domande e informazioni a proposito dell'ADSL Bandwidth Management
   per favore iscrivetevi all'ADSL Bandwidth Management mailing list
   presso http://jared.sonicspike.net/mailman/listinfo/adsl-qos.
     _________________________________________________________________

1.3. Liberatoria

   Ne l'autore ne i distributori o alcuno dei contributori di questo
   HOWTO sono in nessun modo responsabili per danni fisici, finanziari,
   morali o di altro tipo che dovessero occorrere seguendo i suggerimenti
   di questo testo.
     _________________________________________________________________

1.4. Copyright and License

   This document is copyright 2002 by Dan Singletary, and is released
   under the terms of the GNU Free Documentation License, which is hereby
   incorporated by reference.
     _________________________________________________________________

1.5. Copyright e Licenza d'uso

   Questo documento  copyright 2002 by Dan Singletary, ed  rilasciato
   sotto i termini della GNU Free Documentation License, la quale  di
   conseguenza incorporata per riferimento.
     _________________________________________________________________

1.6. Feedback e correzioni

   Se avete domande o commenti da fare su questo documento, sentitevi
   liberi di contattare l'autore presso dvsing@sonicspike.net.
     _________________________________________________________________

2. Background

2.1. Prerequisiti

   Il metodo descritto in questo documento dovrebbe funzionare anche in
   altri scenari in ogni caso rimane non testato in tutte le
   configurazioni eccettuata la seguente:

     * Red Hat Linux 7.3
     * Kernel 2.4.18-5 con il supporto QoS fully enabled (moduli OK) con
       incluse le seguenti patch (le quali potrebbero essere incluse in
       kernel pi recenti):
          + HTB queue - http://luxik.cdi.cz/~devik/qos/htb/
            Nota:  stato segnalato che i kernel dalla versione 2.4.18-3
            distibuiti con Mandrake (8.1, 8.2) sono gi patchati per
            l'HTB.
          + IMQ device - http://luxik.cdi.cz/~patrick/imq/
     * iptables 1.2.6a o superiore (la versione di iptables distribuita
       con Red Hat 7.3 manca del length module)

   Nota: Precedenti versioni di questo documento specificano un metodo di
   controllo di banda che richiede di patchare l'esistente queue
   sch_prio.  stato scoperto successivamente che questa patch non era
   necessaria. A parte ci il nuovo metodo descritto in questo documento
   vi dar migliori risultati (sebbene durante la stesura di questo
   documento siano necessarie 2 patch del kernel. :) Buon patching.)
     _________________________________________________________________

2.2. Schema

   Per facilitare le cose, tutti i riferimenti ai dispositivi di rete e
   le configurazioni in questo documento si riferiranno al seguente
   schema:
               <-- 128kbit/s      --------------     <-- 10Mbit -->
  Internet <--------------------> | ADSL Modem | <--------------------
                1.5Mbit/s -->     --------------                     |
                                                                     | eth0
                                                                     V
                                                         -----------------
                                                         |               |
                                                         | Linux Router  |
                                                         |               |
                                                         -----------------
                                                          | .. | eth1..ethN
                                                          |    |
                                                          V    V

                                                       Rete Locale
     _________________________________________________________________

2.3. Le Code Pacchetto(Packet Queues)

   Le Code Pacchetto sono contenitori che mantengono i dati per un
   dispositivo di rete quando essi non possono essere immediatamente
   inviati. La maggior parte delle Code Pacchetto utilizzano una
   disciplina FIFO (first in, first out)a meno che non siano state
   configurate per fare altrimenti. Questo significa che quando la Coda
   Pacchetto di un particolare device  completamente piena, il pacchetto
   pi recente posto in essa sar inviato al dispositivo solo dopo che
   tutti gli altri pacchetti nella coda in quel momento saranno stati
   inviati.
     _________________________________________________________________

2.3.1. L'Upstream

   Con un modem ADSL, la larghezza di banda  asimmetrica con 1.5Mbit/s
   di downstream e 128kbit/sec di upstream tipici. Bench questa sia la
   velocit della linea, l'interfaccia tra il Router Linux e il modem
   ADSL  tipicamente prossima ai 10Mbit/s. Se l'interfaccia con la rete
   locale  lo stesso a 10Mbit/s, ci sar tipicamente un NO QUEUING sul
   router quando i pacchetti vanno dalla Rete Locale a Internet. I
   pacchetti sono inviati fuori da eth0 alla stessa velocit a cui sono
   stati ricevuti dalla Rete Locale. Diversamente sul modem ADSL, i
   pacchetti vengono messi in coda, dato che essi arrivano a 10Mbit/s e
   possono essere inviati solo a 128kbit/s. Nell'eventualit la Coda
   Pacchetto sul modem ADSL diventa piena e ogni pacchetto in pi
   inviatogli verr silenziosamente scartato. Il TCP  progettato per
   ovviare a questo problema e provveder ad aggiustare la dimensione
   della finestra di trasmissione per ottenere il massimo vantaggio dalla
   banda disponibile.

   Mentre le Code Pacchetto combinate con il TCP danno come risultato un
   pi efficiente uso della larghezza di banda, grandi code FIFO possono
   aumentare la latenza per il traffico di tipo interattivo.

   Un altro tipo di coda con una disciplina alquanto simile a FIFO viene
   detta coda di priorit n-band (n-band priority queue). In questo caso,
   invece di avere una sola coda dove mettere i dati, la coda di priorit
   n-band ha n code FIFO nelle quali i pacchetti sono messi a seconda
   della loro classificazione. Ogni coda ha una priorit e i pacchetti
   sono sempre inviati a partire dalla coda con priorit pi alta che ne
   contiene. Utilizzando questa disciplina i pacchetti FTP possono essere
   messi in una coda con priorit pi bassa rispetto a pacchetti telnet
   cosi che durante un FTP upload, un singolo pacchetto telnet pu
   saltare la coda ed essere inviato immediatamente.

   Questo documento  stato rivisto per utilizzare una nuova coda di
   linux chiamata Hierarchical Token Bucket (HTB). La coda HTB  qualcosa
   in pi rispetto alla coda n-band descritta sopra, e ha la capacit di
   limitare il tasso di traffico in ciascuna classe. In aggiunta, ha
   anche la possibilit di creare classi di traffico al di sotto di altre
   classi creando una gerarchia. La descrizione completa di HTB va oltre
   lo scopo di questo documento, maggiori informazioni si trovano presso
   http://www.lartc.org
     _________________________________________________________________

2.3.2. Il Downstream

   Il traffico entrante sul vostro modem ADSL viene messo in coda
   all'incirca come il traffico uscente , in questo caso la coda sta dal
   vostro ISP. A causa di ci, probabilmente non avete il controllo
   diretto di come i pacchetti vengono messi in coda o quale tipo di
   traffico richiede trattamento preferenziale. L'unico modo di mantenere
   la latenza bassa  essere sicuri che gli utenti non inviino dati
   troppo velocemente. Sfortunatamente, non c' modo di controllare
   direttamente la velocit a cui i pacchetti arrivano, tuttavia da
   quando la gran parte del traffico sulle vostre reti  costituita dal
   TCP, ci sono alcuni modi di rallentare chi invia i dati:

     * Scartare intenzionalmente pacchetti entranti - il TCP  progettato
       per ottenere il massimo vantaggio dalla banda disponibile e allo
       stesso tempo evitare la congestione del link. Questo significa che
       durante un trasferimento , TCP invia una sempre maggiore quantit
       di dati fino a che eventualmente un pacchetto viene scartato. TCP
       riesce a rilevare questo e di conseguenza riduce la sua finestra
       di trasmissione. Questo ciclo continua durante tutto il processo e
       assicura che i dati vengano spostati il pi velocemente possibile.
     * Manipolare gli avvisi di ricezione finestra - Durante un
       trasferimento TCP , il ricevente invia indietro un flusso continuo
       di pacchetti di acknowledgment (ACK). Inclusi in questi pacchetti
       ACK c' un avviso di dimensione finestra il quale dichiara il
       totale massimo di dati non riconosciuti che il ricevente dovrebbe
       inviare. Manipolando la dimensione finestra dei pacchetti ACK
       uscenti possiamo intenzionalmente rallentare chi invia i dati.
       Attualmente non c' nessuna (libera) implementazione per questo
       tipo di controllo di flusso su Linux (Comunque potrei lavorarci
       su!).
     _________________________________________________________________

3. Come Funziona

   Ci sono due passi fondamentali per ottimizzare la larghezza di banda
   upstream. Per primo dobbiamo trovare un modo per prevenire che il
   modem ADSL metta in coda pacchetti fino a che non abbiamo il controllo
   su come esso la tratti. Per fare questo dovremo limitare la quantit
   di dati che il router invia su eth0 per rimanere leggermente sotto
   rispetto alla larghezza di banda totale dell'upstream del modem ADSL.
   Questo risulter nell'avere il router che mette in coda pacchetti che
   arrivano dalla Rete Locale pi velocemente di quanto esso possa
   inviarne.

   Il secondo passo consiste nell'inserire una priorit di disciplina di
   coda sul router. Studieremo una coda che pu essere configurata per
   dare priorit al traffico interattivo come il telnet o i giochi in
   modalit multi-player.

   Utilizzando la coda HTB possiamo realizzare lo shaping della larghezza
   di banda e la priorit di messa in coda allo stesso tempo assicurando
   anche nel mentre che nessuna priorit di classe rimanga senza banda.
   Evitare questo fenomeno non era possibile utilizzando il metodo
   evidenziato nella revisione 0.1 di questo documento.

   Il passo finale  di configurare il firewall per assegnare la priorit
   ai pacchetti utilizzando il campo fwmark.
     _________________________________________________________________

3.1. Limitare il traffico uscente con Linux HTB

   Sebbene la connessione tra il router e il modem  a 10Mbit/s, il modem
    capace di inviare dati solo a 128kbit/s. Ogni dato che ecceda questa
   quota verr messo in coda sul modem. In questo modo, un pacchetto ping
   inviato dal router pu andare al modem immediatamente, ma pu
   impiegare qualche secondo per essere inviato effettivamente a Internet
   se la coda del modem ha qualche pacchetto al suo interno.
   Sfortunatamente molti modem ADSL non hanno nessun meccanismo per
   specificare come i pacchetti sono levati dalla coda o quanto sia larga
   questa, cos il nostro primo obbiettivo  spostare il luogo dove i
   pacchetti in uscita sono messi in coda da qualche parte dove possiamo
   avere maggior controllo su di essa.

   Possiamo realizzare questo utilizzando la coda HTB per limitare il
   tasso al quale inviamo i pacchetti al modem ADSL. Anche se la nostra
   larghezza di banda upstream pu essere 128kbit/s dovremo limitare il
   valore al quale inviamo i pacchetti per fare in modo che sia
   leggermente inferiore a questo. Se vogliamo abbassare la latenza
   dobbiamo essere SICURI che neanche un singolo pacchetto sia messo in
   coda sul modem. Tramite prove ho scoperto che limitare il traffico
   uscente a circa 90kbit/s mi da quasi il 95% della larghezza di banda
   che posso ottenere senza il controllo di tasso HTB. Con HTB abilitato
   a questo valore, preveniamo la messa in coda dei pacchetti da parte
   del modem ADSL.
     _________________________________________________________________

3.2. Priorit di messa in coda con HTB

   Nota: precedenti asserzioni in questa sezione (originariamente
   chiamata Priorit di messa in coda con N-band) sono state scoperte
   essere non corrette. ERA possibile classificare i pacchetti nelle
   bande individuali della priorit di coda usando solo il campo fwmark,
   comunque era una cosa poco documentata durante la stesura della
   versione 0.1 di questo documento.

   A questo punto non abbiamo ancora realizzato nessun cambiamento nella
   performance. Abbiamo semplicemente spostato la coda FIFO dal modem
   ADSL al router. In effetti, con Linux configurato con una coda di
   default di 100 pacchetti abbiamo probabilmente peggiorato il nostro
   problema! Ma non per molto...

   Ad ogni classe adiacente in una coda HTB pu essere assegnata una
   priorit. Mettendo differenti tipi di traffico in differenti classi e
   assegnando a queste classi differenti priorit, possiamo controllare
   l'ordine con il quale i pacchetti sono levati dalla coda e inviati.
   HTB rende ci possibile, evitando contemporaneamente il prosciugamento
   delle altre classi, poich c' la possibilit di specificare un valore
   minimo garantito per ogni classe. In aggiunta, HTB ci permette di dire
   ad una particolare classe che pu utilizzare qualsiasi larghezza di
   banda non utilizzata da altre classi fino ad una certa soglia.

   Una volta che abbiamo le nostre classi pronte, dobbiamo creare dei
   filtri per distribuire il traffico nelle suddette. Ci sono diversi
   modi per farlo, ma il metodo descritto in questo documento utilizza i
   pi noti comandi iptables/ipchains per marcare i pacchetti con un
   valore fwmark. I filtri mettono il traffico nelle classi della coda
   HTB basandosi sul loro fwmark. In questo modo, abbiamo la possibilit
   di creare delle matching rules con iptables per inviare certi tipi di
   traffico a determinate classi.
     _________________________________________________________________

3.3. Classificare i pacchetti uscenti con iptables

   Nota: originariamente questo documento utilizzava ipchains per
   classificare i pacchetti. Ora  utilizzato il pi recente iptables.

   Il passo finale nella configurazione del vostro router per dare
   priorit al traffico interattivo  creare il firewall per definire
   come il traffico deve essere classificato. Questo viene ottenuto
   settando il campo fwmark del pacchetto.

   Senza entrare in dettagli, di seguito c' una descrizione semplificata
   di come i pacchetti uscenti possono essere classificati in 4 categorie
   con la 0x00 avente la priorit pi alta:

    1. Marcare TUTTI i pacchetti come 0x03. Questo li posiziona, per
       default, dentro la coda con priorit piu basssa.
    2. Marcare i pacchetti ICMP come 0x00. Vogliamo pingare e mostrare la
       latenza per i pacchetti ad alta priorit.
    3. Marcare tutti i pacchetti destinati alla porta 1024 o inferiore
       come 0x01. Questo da priorit ai servizi di sistema quali Telnet e
       SSH. Anche la porta di controllo FTP ricade in questo range
       comunque i dati di trasferimento FTP stanno su porte alte e
       rimangono nella banda 0x03.
    4. Marcare tutti i pacchetti destinati alla porta 25 (SMTP) come
       0x03. Se qualcuno invia e-mail con grandi allegati non vogliamo
       che affoghi il traffico interattivo.
    5. Marcare tutti i pacchetti destinati a game server multiplayer come
       0x02. Questo da ai giocatori bassa latenza ma evita loro di
       impantanare le applicazioni di sistema che la richiedono.
       Marcare ogni pacchetto "piccolo" come 0x02. Pacchetti ACK uscenti
       generati da download entranti devono essere inviati prontamente
       per assicurare scaricamenti efficienti. Questo  possibile con
       l'utilizzo dell'iptables length module.

   Ovviamente, tutto ci pu essere aggiustato secondo le vostre
   esigenze.
     _________________________________________________________________

3.4. Qualche piccola miglioria...

   Ci sono altre due cose che potete fare per migliorare la vostra
   latenza. Primo, potete settare la Maximum Transmittable Unit (mtu) ad
   un valore pi basso del default di 1500 bytes. Abbassando questo
   numero si abbasser anche il tempo medio che dovrete aspettare per
   inviare un pacchetto prioritario se c' gi un pacchetto a bassa
   priorit full-sized che viene inviato. Abbassando questo numero
   decrescer leggermente anche il vostro throughput perch ogni
   pacchetto contiene almeno 40 byte di valore di IP e TCP header
   information.

   L'altra cosa che potete fare per migliorare la latenza anche sul
   vostro traffico a bassa priorit  di diminuire la lunghezza della
   coda dal valore di default di 100, la quale pu impiegare anche 10
   secondi per svuotarsi con una mtu di 1500 byte.
     _________________________________________________________________

3.5. Provare a limitare il traffico in arrivo

   Usando l'Intermediate Queuing Device (IMQ), possiamo elaborare tutti i
   pacchetti entranti attraverso una coda nello stesso modo in cui lo
   facciamo con gli uscenti. La priorit dei pacchetti  piu semplice in
   questo caso. Potendo solo (provare a) controllare il traffico TCP in
   arrivo, potremmo mettere tutto il traffico non TCP nella classe 0x00,
   e tutto il traffico TCP nella classe 0x01. Potremmo anche mettere i
   pacchetti TCP "piccoli" nella 0x00 dato che questi sono per la maggior
   parte pacchetti ACK per dati in uscita che sono gia stati inviati.
   Creiamo una coda standard FIFO nella classe 0x00, e una coda Random
   Early Drop (RED) nella classe 0x01. La coda RED  migliore della FIFO
   (tail-drop) per controllare il TCP perch scarta i pacchetti prima di
   andare in overflow nel tentativo di rallentare trasferimenti che
   potrebbero andare fuori controllo. Possiamo limitare entrambe le
   classi ad un valore massimo inferiore all'effettivo valore in ingresso
   sul modem ADSL.
     _________________________________________________________________

3.5.1. Perch limitare il Traffico in arrivo non  cos giusto

   Vogliamo limitare il nostro traffico in ingresso per evitare di
   riempire la coda presso l'ISP,il quale pu a volte bufferizzare fino a
   un valore di 5 secondi dei dati. Il problema  che attualmente l'unico
   modo per limitare il traffico TCP in ingresso  quello di scartare
   pacchetti perfettamente validi. Questi pacchetti hanno gi preso una
   certa parte di banda sul modem ADSL solo per essere scartati dalla
   Linux Box nello sforzo di rallentare i futuri pacchetti. Essi saranno
   eventualmente ritrasmessi consumando ancora pi banda. Quando
   limitiamo il traffico, limitiamo il rate dei pacchetti che saranno
   accettati nella nostra rete. Poich l' attuale data rate in ingresso 
   leggermente superiore a causa dei pacchetti che scartiamo, dobbiamo
   limitare il downstream ad un valore molto pi basso rispetto
   all'attuale valore del modem ADSL per assicurare una latenza bassa. In
   pratica devo limitare il mio downstream di 1.5 Mbit/s a 700kbit/sec
   per avere una latenza accettabile con 5 download concorrenti. Pi
   sessioni TCP si hanno, pi larghezza di banda si spreca con i
   pacchetti scartati, e pi basso sar il valore massimo da configurare.

   Un miglior modo di controllare il traffico in arrivo potrebbe essere
   la manipolazione della larghezza della finestra del TCP, ma al momento
   di questa stesura non ci sono (libere) implementazioni di ci per
   Linux (per quanto ne so...).
     _________________________________________________________________

4. Implementazione

   Dopo tutte le spiegazioni  giunto il momento di implementare il
   bandwidth management con Linux.
     _________________________________________________________________

4.1. Avvertimenti

   Limitare il rate dei dati inviati al modem DSL non  semplice come pu
   sembrare. La maggior parte di questi modem sono in realt solo dei
   bridge ethernet che mandano i dati avanti e indietro tra la vostra
   linux box e il gateway dal vostro ISP. Molti modem DSL utilizzano ATM
   come strato di collegamento per inviare dati. ATM invia dati in celle
   che hanno una lunghezza fissa di 53 byte. 5 di questi byte sono
   informazioni di intestazione, e i rimanenti 48 byte sono disponibili
   per i dati. Anche se mandate 1 byte di dati, vengono consumati 53 byte
   di larghezza di banda poich le celle ATM sono sempre lunghe 53 byte.
   Questo significa che se voi state inviando un tipico pacchetto TCP di
   ACK esso consiste di 0 byte di dati + 20 byte di header TCP + 20 byte
   di header IP + 18 byte di header Ethernet . Attualmente, anche se il
   pacchetto ethernet che inviate ha solo 40 byte di payload (TCP e IP
   header), il payload minimo per un pacchetto Ethernet  di 46 byte di
   dati, cos i rimanenti 6 byte sono riempiti con dati nulli. Questo
   significa che l'attuale lunghezza del pacchetto Ethernet pi
   l'intestazione  di 18 + 46 = 64 byte. Per inviare 64 byte su ATM,
   dovete inviare due celle ATM che consumano 106 byte di larghezza di
   banda. Quindi per ogni pacchetto TCP di ACK, state sprecando 42 byte.
   Questo potrebbe essere okay se Linux tenesse conto della
   incapsulazione che usa il modem DSL, invece, Linux tiene solo conto di
   TCP header, IP header e dei 14 byte dell'indirizzo MAC (Linux non
   tiene conto dei 4 byte di CRC poich questo viene fatto a livello
   hardware). Linux non tiene conto inoltre n della grandezza minima del
   pacchetto Ethernet di 46 byte, n della grandezza fissa della cella
   ATM.

   Tutto ci sta a significare che dovete limitare la vostra larghezza di
   banda in uscita ad un valore inferiore rispetto all'effettiva capacit
   (fintanto che si possa calcolare uno schedulatore di pacchetti che
   possa tener conto dei vari tipi di incapsulazioni che vengono
   utilizzate). Potreste scoprire di aver calcolato un buon valore a cui
   limitare la vostra larghezza di banda, ma poi scaricate un grosso file
   e la latenza inizia a schizzare verso l'alto dopo 3 secondi. Ci di
   solito avviene perch la larghezza di banda che questi piccoli
   pacchetti ACK consumano viene calcolata male da Linux.

   Ho lavorato a questo problema per qualche mese e ho quasi aggiustato
   una soluzione che presto rilascer al pubblico per ulteriori test. La
   soluzione implica l'utilizzo di una coda user-space invece della QoS
   di Linux per limitare il rate dei pacchetti. Ho fondamentalmente
   implementato una semplice coda HTB usando una coda linux user-space.
   Questa soluzione (per quanto ne so) riesce a regolare il traffico in
   uscita MOLTO BENE anche durante un massiccio download (diversi flussi)
   e pesante upload (gnutella, diversi flussi) la latenza ha un picco di
   400ms oltre la mia latenza senza traffico di circa 15ms. Per maggiori
   informazioni su questo metodo QoS, iscrivetevi alla mailing list per
   le novit o controllate gli aggiornamenti a questo HOWTO.
     _________________________________________________________________

4.2. Script: myshaper

   Il seguente  il listato dello script che utilizzo per controllare la
   larghezza di banda sul mio router Linux. Esso utilizza molti dei
   concetti trattati nel documento. Il traffico in uscita viene messo in
   una delle 7 code a seconda del tipo. Il traffico in entrata 
   posizionato in due code con i pacchetti TCP che vengono scartati prima
   (priorit pi bassa) se i dati in entrata vanno oltre il rate fissato.
   I valori dati in questo script sembrano essere OK per il mio setup ma
   i vostri risultati potrebbero variare.

   Questo script era basato in origine sul WonderShaper ADSL come visto
   presso il sito web LARTC.

#!/bin/bash
#
# myshaper - DSL/Cable modem outbound traffic shaper and prioritizer.
#            Based on the ADSL/Cable wondershaper (www.lartc.org)
#
# Written by Dan Singletary (8/7/02)
#
# NOTE!! - This script assumes your kernel has been patched with the
#          appropriate HTB queue and IMQ patches available here:
#          (subnote: future kernels may not require patching)
#
#       http://luxik.cdi.cz/~devik/qos/htb/
#       http://luxik.cdi.cz/~patrick/imq/
#
# Configuration options for myshaper:
#  DEV    - set to ethX that connects to DSL/Cable Modem
#  RATEUP - set this to slightly lower than your
#           outbound bandwidth on the DSL/Cable Modem.
#           I have a 1500/128 DSL line and setting
#           RATEUP=90 works well for my 128kbps upstream.
#           However, your mileage may vary.
#  RATEDN - set this to slightly lower than your
#           inbound bandwidth on the DSL/Cable Modem.
#
#
#  Theory on using imq to "shape" inbound traffic:
#
#     It's impossible to directly limit the rate of data that will
#  be sent to you by other hosts on the internet.  In order to shape
#  the inbound traffic rate, we have to rely on the congestion avoidance
#  algorithms in TCP.  Because of this, WE CAN ONLY ATTEMPT TO SHAPE
#  INBOUND TRAFFIC ON TCP CONNECTIONS.  This means that any traffic that
#  is not tcp should be placed in the high-prio class, since dropping
#  a non-tcp packet will most likely result in a retransmit which will
#  do nothing but unnecessarily consume bandwidth.
#     We attempt to shape inbound TCP traffic by dropping tcp packets
#  when they overflow the HTB queue which will only pass them on at
#  a certain rate (RATEDN) which is slightly lower than the actual
#  capability of the inbound device.  By dropping TCP packets that
#  are over-rate, we are simulating the same packets getting dropped
#  due to a queue-overflow on our ISP's side.  The advantage of this
#  is that our ISP's queue will never fill because TCP will slow it's
#  transmission rate in response to the dropped packets in the assumption
#  that it has filled the ISP's queue, when in reality it has not.
#     The advantage of using a priority-based queuing discipline is
#  that we can specifically choose NOT to drop certain types of packets
#  that we place in the higher priority buckets (ssh, telnet, etc).  This
#  is because packets will always be dequeued from the lowest priority class
#  with the stipulation that packets will still be dequeued from every
#  class fairly at a minimum rate (in this script, each bucket will deliver
#  at least it's fair share of 1/7 of the bandwidth).
#
#  Reiterating main points:
#   * Dropping a tcp packet on a connection will lead to a slower rate
#     of reception for that connection due to the congestion avoidance algorith
m.
#   * We gain nothing from dropping non-TCP packets.  In fact, if they
#     were important they would probably be retransmitted anyways so we want to
#     try to never drop these packets.  This means that saturated TCP connectio
ns
#     will not negatively effect protocols that don't have a built-in retransmi
t like TCP.
#   * Slowing down incoming TCP connections such that the total inbound rate is
 less
#     than the true capability of the device (ADSL/Cable Modem) SHOULD result i
n little
#     to no packets being queued on the ISP's side (DSLAM, cable concentrator,
etc).  Since
#     these ISP queues have been observed to queue 4 seconds of data at 1500Kbp
s or 6 megabits
#     of data, having no packets queued there will mean lower latency.
#
#  Caveats (questions posed before testing):
#   * Will limiting inbound traffic in this fashion result in poor bulk TCP per
formance?
#     - Preliminary answer is no!  Seems that by prioritizing ACK packets (smal
l <64b)
#       we maximize throughput by not wasting bandwidth on retransmitted packet
s
#       that we already have.
#

# NOTE: The following configuration works well for my
# setup: 1.5M/128K ADSL via Pacific Bell Internet (SBC Global Services)

DEV=eth0
RATEUP=90
RATEDN=700  # Note that this is significantly lower than the capacity of 1500.
            # Because of this, you may not want to bother limiting inbound traf
fic
            # until a better implementation such as TCP window manipulation can
 be used.

#
# End Configuration Options
#

if [ "$1" = "status" ]
then
        echo "[qdisc]"
        tc -s qdisc show dev $DEV
        tc -s qdisc show dev imq0
        echo "[class]"
        tc -s class show dev $DEV
        tc -s class show dev imq0
        echo "[filter]"
        tc -s filter show dev $DEV
        tc -s filter show dev imq0
        echo "[iptables]"
        iptables -t mangle -L MYSHAPER-OUT -v -x 2> /dev/null
        iptables -t mangle -L MYSHAPER-IN -v -x 2> /dev/null
        exit
fi

# Reset everything to a known state (cleared)
tc qdisc del dev $DEV root    2> /dev/null > /dev/null
tc qdisc del dev imq0 root 2> /dev/null > /dev/null
iptables -t mangle -D POSTROUTING -o $DEV -j MYSHAPER-OUT 2> /dev/null > /dev/n
ull
iptables -t mangle -F MYSHAPER-OUT 2> /dev/null > /dev/null
iptables -t mangle -X MYSHAPER-OUT 2> /dev/null > /dev/null
iptables -t mangle -D PREROUTING -i $DEV -j MYSHAPER-IN 2> /dev/null > /dev/nul
l
iptables -t mangle -F MYSHAPER-IN 2> /dev/null > /dev/null
iptables -t mangle -X MYSHAPER-IN 2> /dev/null > /dev/null
ip link set imq0 down 2> /dev/null > /dev/null
rmmod imq 2> /dev/null > /dev/null

if [ "$1" = "stop" ]
then
        echo "Shaping removed on $DEV."
        exit
fi

###########################################################
#
# Outbound Shaping (limits total bandwidth to RATEUP)

# set queue size to give latency of about 2 seconds on low-prio packets
ip link set dev $DEV qlen 30

# changes mtu on the outbound device.  Lowering the mtu will result
# in lower latency but will also cause slightly lower throughput due
# to IP and TCP protocol overhead.
ip link set dev $DEV mtu 1000

# add HTB root qdisc
tc qdisc add dev $DEV root handle 1: htb default 26

# add main rate limit classes
tc class add dev $DEV parent 1: classid 1:1 htb rate ${RATEUP}kbit

# add leaf classes - We grant each class at LEAST it's "fair share" of bandwidt
h.
#                    this way no class will ever be starved by another class.
Each
#                    class is also permitted to consume all of the available ba
ndwidth
#                    if no other classes are in use.
tc class add dev $DEV parent 1:1 classid 1:20 htb rate $[$RATEUP/7]kbit ceil ${
RATEUP}kbit prio 0
tc class add dev $DEV parent 1:1 classid 1:21 htb rate $[$RATEUP/7]kbit ceil ${
RATEUP}kbit prio 1
tc class add dev $DEV parent 1:1 classid 1:22 htb rate $[$RATEUP/7]kbit ceil ${
RATEUP}kbit prio 2
tc class add dev $DEV parent 1:1 classid 1:23 htb rate $[$RATEUP/7]kbit ceil ${
RATEUP}kbit prio 3
tc class add dev $DEV parent 1:1 classid 1:24 htb rate $[$RATEUP/7]kbit ceil ${
RATEUP}kbit prio 4
tc class add dev $DEV parent 1:1 classid 1:25 htb rate $[$RATEUP/7]kbit ceil ${
RATEUP}kbit prio 5
tc class add dev $DEV parent 1:1 classid 1:26 htb rate $[$RATEUP/7]kbit ceil ${
RATEUP}kbit prio 6

# attach qdisc to leaf classes - here we at SFQ to each priority class.  SFQ in
sures that
#                                within each class connections will be treated
(almost) fairly.
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev $DEV parent 1:21 handle 21: sfq perturb 10
tc qdisc add dev $DEV parent 1:22 handle 22: sfq perturb 10
tc qdisc add dev $DEV parent 1:23 handle 23: sfq perturb 10
tc qdisc add dev $DEV parent 1:24 handle 24: sfq perturb 10
tc qdisc add dev $DEV parent 1:25 handle 25: sfq perturb 10
tc qdisc add dev $DEV parent 1:26 handle 26: sfq perturb 10

# filter traffic into classes by fwmark - here we direct traffic into priority
class according to
#                                         the fwmark set on the packet (we set
fwmark with iptables
#                                         later).  Note that above we've set th
e default priority
#                                         class to 1:26 so unmarked packets (or
 packets marked with
#                                         unfamiliar IDs) will be defaulted to
the lowest priority
#                                         class.
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:20
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:21
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 22 fw flowid 1:22
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 23 fw flowid 1:23
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 24 fw flowid 1:24
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 25 fw flowid 1:25
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 26 fw flowid 1:26

# add MYSHAPER-OUT chain to the mangle table in iptables - this sets up the tab
le we'll use
#                                                      to filter and mark packe
ts.
iptables -t mangle -N MYSHAPER-OUT
iptables -t mangle -I POSTROUTING -o $DEV -j MYSHAPER-OUT

# add fwmark entries to classify different types of traffic - Set fwmark from 2
0-26 according to
#                                                             desired class. 20
 is highest prio.
iptables -t mangle -A MYSHAPER-OUT -p tcp --sport 0:1024 -j MARK --set-mark 23
# Default for low port traffic
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport 0:1024 -j MARK --set-mark 23
# ""
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport 20 -j MARK --set-mark 26
# ftp-data port, low prio
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport 5190 -j MARK --set-mark 23
# aol instant messenger
iptables -t mangle -A MYSHAPER-OUT -p icmp -j MARK --set-mark 20
# ICMP (ping) - high prio, impress friends
iptables -t mangle -A MYSHAPER-OUT -p udp -j MARK --set-mark 21
# DNS name resolution (small packets)
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport ssh -j MARK --set-mark 22
# secure shell
iptables -t mangle -A MYSHAPER-OUT -p tcp --sport ssh -j MARK --set-mark 22
# secure shell
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport telnet -j MARK --set-mark 22
# telnet (ew...)
iptables -t mangle -A MYSHAPER-OUT -p tcp --sport telnet -j MARK --set-mark 22
# telnet (ew...)
iptables -t mangle -A MYSHAPER-OUT -p ipv6-crypt -j MARK --set-mark 24
# IPSec - we don't know what the payload is though...
iptables -t mangle -A MYSHAPER-OUT -p tcp --sport http -j MARK --set-mark 25
# Local web server
iptables -t mangle -A MYSHAPER-OUT -p tcp -m length --length :64 -j MARK --set-
mark 21 # small packets (probably just ACKs)
iptables -t mangle -A MYSHAPER-OUT -m mark --mark 0 -j MARK --set-mark 26
# redundant- mark any unmarked packets as 26 (low prio)

# Done with outbound shaping
#
####################################################

echo "Outbound shaping added to $DEV.  Rate: ${RATEUP}Kbit/sec."

# uncomment following line if you only want upstream shaping.
# exit

####################################################
#
# Inbound Shaping (limits total bandwidth to RATEDN)

# make sure imq module is loaded

modprobe imq numdevs=1

ip link set imq0 up

# add qdisc - default low-prio class 1:21

tc qdisc add dev imq0 handle 1: root htb default 21

# add main rate limit classes
tc class add dev imq0 parent 1: classid 1:1 htb rate ${RATEDN}kbit

# add leaf classes - TCP traffic in 21, non TCP traffic in 20
#
tc class add dev imq0 parent 1:1 classid 1:20 htb rate $[$RATEDN/2]kbit ceil ${
RATEDN}kbit prio 0
tc class add dev imq0 parent 1:1 classid 1:21 htb rate $[$RATEDN/2]kbit ceil ${
RATEDN}kbit prio 1

# attach qdisc to leaf classes - here we at SFQ to each priority class.  SFQ in
sures that
#                                within each class connections will be treated
(almost) fairly.
tc qdisc add dev imq0 parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev imq0 parent 1:21 handle 21: red limit 1000000 min 5000 max 100
000 avpkt 1000 burst 50

# filter traffic into classes by fwmark - here we direct traffic into priority
class according to
#                                         the fwmark set on the packet (we set
fwmark with iptables
#                                         later).  Note that above we've set th
e default priority
#                                         class to 1:26 so unmarked packets (or
 packets marked with
#                                         unfamiliar IDs) will be defaulted to
the lowest priority
#                                         class.
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:20
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:21

# add MYSHAPER-IN chain to the mangle table in iptables - this sets up the tabl
e we'll use
#                                                         to filter and mark pa
ckets.
iptables -t mangle -N MYSHAPER-IN
iptables -t mangle -I PREROUTING -i $DEV -j MYSHAPER-IN

# add fwmark entries to classify different types of traffic - Set fwmark from 2
0-26 according to
#                                                             desired class. 20
 is highest prio.
iptables -t mangle -A MYSHAPER-IN -p ! tcp -j MARK --set-mark 20              #
 Set non-tcp packets to highest priority
iptables -t mangle -A MYSHAPER-IN -p tcp -m length --length :64 -j MARK --set-m
ark 20 # short TCP packets are probably ACKs
iptables -t mangle -A MYSHAPER-IN -p tcp --dport ssh -j MARK --set-mark 20    #
 secure shell
iptables -t mangle -A MYSHAPER-IN -p tcp --sport ssh -j MARK --set-mark 20    #
 secure shell
iptables -t mangle -A MYSHAPER-IN -p tcp --dport telnet -j MARK --set-mark 20 #
 telnet (ew...)
iptables -t mangle -A MYSHAPER-IN -p tcp --sport telnet -j MARK --set-mark 20 #
 telnet (ew...)
iptables -t mangle -A MYSHAPER-IN -m mark --mark 0 -j MARK --set-mark 21
       # redundant- mark any unmarked packets as 26 (low prio)

# finally, instruct these packets to go through the imq0 we set up above
iptables -t mangle -A MYSHAPER-IN -j IMQ

# Done with inbound shaping
#
####################################################

echo "Inbound shaping added to $DEV.  Rate: ${RATEDN}Kbit/sec."
     _________________________________________________________________

5. Test della nuova coda

   Il modo pi semplice per testare la vostra nuova configurazione 
   saturare l'upstream con traffico a bassa priorit. Questo dipende da
   come avete settato le priorit. Per beneficio di esempio, diciamo che
   avete messo il traffico telnet e il traffico ping alla priorit pi
   alta (fwmark basso) rispetto ad altre porte alte (che sono utilizzate
   per trasferimenti FTP, ecc.). Se iniziate un upload FTP per saturare
   la larghezza di banda, dovreste solo notare che il vostro tempo di
   ping al gateway (dall'altro lato della linea DSL) incrementa di un
   piccolo valore rispetto all'aumento che si avrebbe senza priorit di
   coda. Tempi di risposta del ping inferiori a 100ms sono tipici a
   seconda di come avete configurato il tutto. Tempi di Ping superiori a
   uno o due secondi indicano probabilmente che le cose non stanno
   funzionando bene.
     _________________________________________________________________

6. OK Funziona!! E adesso?

   Ora che avete iniziato con successo il managing della vostra larghezza
   di banda, cominciate a pensare ad un modo per usarla. Dopo tutto,
   probabilmente la state pagando!

     * Usate un client Gnutella e CONDIVIDETE I VOSTRI FILE senza effetti
       negativi sulla performance della vostra rete
     * Fate girare un server web senza che gli "hits" alle pagine vi
       rallentino a Quake
     _________________________________________________________________

7. Link correlati

     * Bandwidth Controller per Windows -
       http://www.bandwidthcontroller.com
     * dsl_qos_queue - (beta) per Linux. Nessuna patch al kernel e
       migliore performance -
