9.2. Disciplinas de cola simples, sin clases

Como dije, con las disciplinas de cola, cambiamos el modo en que se envían los datos. Las disciplinas de cola sin clases son aquellas que, mayormente, aceptan datos y se limitan a reordenarlos, retrasarlos, o descartarlos.

Esto se puede usar para ajustar el tráfico de una interfaz entera, sin subdivisiones. ¡Es vital que comprenda esta parte del encolado antes de que pasemos a los qdisc-contenedores-de-qdiscs con clases!

La disciplina más usada, con mucho, es la qdisc pfifo_fast (se usa por defecto). Esto también explica por qué estas características avanzadas son tan robustas. No son más que «simplemente otra cola».

Cada una de estas colas tiene puntos fuertes y debilidades específicos. Puede que no todas estén bien probadas.

9.2.1. pfifo_fast

Esta cola es, como su nombre indica, First In, First Out (el primero que entra es el primero que sale), lo que significa que ningún paquete recibe un tratamiento especial. Al menos, no mucho. Esta cola tiene 3 de lo que llamamos «bandas». Dentro de cada banda, se aplican las reglas FIFO. Sin embargo, no se procesará la banda 1 mientras haya paquetes esperando en la banda 0. Lo mismo se aplica para las bandas 1 y 2.

El núcleo obedece la marca llamada Type of Service que hay en los paquetes, y tiene cuidado de insertar los paquetes de «mínimo retraso» en la banda 0.

¡No confunda esta qdisc sencilla y sin clases con la PRIO con clases! Aunque se comportan de manera similar, la pfifo_fast no tiene clases y no puede añadir otras qdisc a ella con la orden tc.

9.2.1.1. Parámetros y forma de uso

No puede configurar la qdisc pfifo_fast ya que es el la cola por defecto fija. Así es como va configurada de serie:

priomap

Determina cómo se corresponden las prioridades de los paquetes, tal como las asigna el núcleo, a las bandas. La correspondencia se basa en el octeto TOS del paquete, que es así:

   0     1     2     3     4     5     6     7
+-----+-----+-----+-----+-----+-----+-----+-----+
|                 |                       |     |
|   PRECEDENCE    |          TOS          | MBZ |
|                 |                       |     |
+-----+-----+-----+-----+-----+-----+-----+-----+

Los cuatro bits TOS (el «campo TOS») se define como:

Binary Decimcal  Meaning
-----------------------------------------
1000   8         Minimizar retraso (md)
0100   4         Maximizar transferencia (mt)
0010   2         Maximizar fiabilidad (mr)
0001   1         Minimizar el coste monetario (mmc)
0000   0         Servicio normal

Como hay 1 bit a la derecha de estos cuatro, el valor real del campo TOS es el doble del valor de sus bits. Tcpdump -v -v muestra el valor del campo TOS completo, no sólo sus cuatro bits. Este es el valor que ve en la primera columna de esta tabla:

TOS     Bits  Significa                Prioridad Linux   Banda
--------------------------------------------------------------
0x0     0     Servicio normal          0 Mejor esfuerzo  1
0x2     1     Minimizar coste monet.   1 Relleno         2
0x4     2     Maximizar fiabilidad     0 Mejor esfuerzo  1
0x6     3     mmc+mr                   0 Mejor esfuerzo  1
0x8     4     Mazimizar transferencia  2 En masa         2
0xa     5     mmc+mt                   2 En masa         2
0xc     6     mr+mt                    2 En masa         2
0xe     7     mmc+mr+mt                2 En masa         2
0x10    8     Minimizar retrasos       6 Interactivo     0
0x12    9     mmc+md                   6 Interactivo     0
0x14    10    mr+md                    6 Interactivo     0
0x16    11    mmc+mr+md                6 Interactivo     0
0x18    12    mt+md                    4 Int. en masa    1
0x1a    13    mmc+mt+md                4 Int. en masa    1
0x1c    14    mr+mt+md                 4 Int. en masa    1
0x1e    15    mmc+mr+mt+md             4 Int. en masa    1

Muchos números. La segunda columna contiene el valor de los cuatro bits TOS relevantes, seguidos por su significado traducido. Por ejemplo, el 15 significa que un paquete espera un Mínimo coste monetario, la Máxima fiabilidad, la Máxima transferencia Y un Retraso mínimo. Yo llamaría a esto un «paquete holandés» (N. del T: el autor es holandés, y supongo que se reirá mucho con este chiste).

La cuarta columna indica la manera en que el núcleo Linux interpreta los bits del TOS, mostrando qué prioridad les asigna.

La última columna indica el resultado del priomap por defecto. En la línea de órdenes el priomap por defecto se parece a:

1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1

Esto significa que a la prioridad 4, por ejemplo, se asigna la banda número 1. El priomap también le permite listar prioridades mayores (> 7) que no se corresponden a asignaciones del TOS, sino que se configuran por otros medios.

Esta tabla del RFC 1349 (léalo para obtener más detalles) le dice cómo deberían activar las aplicaciones los bits del TOS:

TELNET                   1000           (minimizar retraso)
FTP
	Control          1000           (minimizar retraso)
        Datos            0100           (maximizar transferencia)

TFTP                     1000           (minimizar retraso)

SMTP 
	Fase de órdenes  1000           (minimizar retraso)
        Fase de datos    0100           (maximizar transferencia)

Domain Name Service
	Consulta UDP     1000           (minimizar retraso)
	Consulta TCP     0000
	Transf. de zona  0100           (maximizar transferencia)

NNTP                     0001           (minimizar coste monetario)

ICMP
	Errores          0000
	Peticiones       0000 (la mayoría)
	Respuestas       <igual que las peticiones> (la mayoría)

txqueuelen

La longitud de esta cola se obtiene de la configuración de la interfaz, que puede ver y modificar con ifconfig o ip. Para establecer la longitud de la cola a 10, ejecute: ifconfig eth0 txqueuelen 10

¡No puede establecer este parámetro con tc!

9.2.2. Token Bucket Filter

El Token Bucket Filter (TBF) es un qdisc sencillo que se limita a dejar pasar paquetes que lleguen a una tasa que no exceda una impuesta administrativamente, pero con la posibilidad de permitir ráfagas cortas que excedan esta tasa.

TBF es muy preciso, amigable para la red y el procesador. ¡Debería ser su primera elección si sólo quiere ralentizar una interfaz!

La implementación de TBF consiste en un búfer (el bucket o balde), que se llena constatemente con piezas virtuales de información denominadas tokens, a una tasa específica (token rate). El parámetro más importante del bucket es su tamaño, que es el número de tokens que puede almacenar.

Cada token que llega toma un paquete de datos entrante de la cola de datos y se elimina del bucket. Asociar este algoritmo con los dos flujos (tokens y datos), nos da tres posibles situaciones:

Esta última situación es muy importante, porque permite ajustar administrativamente al ancho de banda disponible a los datos que están pasando por el filtro.

La acumulación de tokens permite ráfagas cortas de datos extralimitados para que pasen sin pérdidas, pero cualquier sobrecarga restante causará que los paquetes se vayan retrasando constantemente, y al final sean descartados.

Tenga en cuenta que en la implementación actual, los tokens se corresponden a bytes, no a paquetes.

9.2.2.1. Parámetros y uso

Incluso aunque probablemente no necesite hacerle cambios, tbf tiene algunos controles ajustables. Primero, los parámetros que estarán disponibles siempre:

limit o latency

Limit es el número de bytes que pueden ser encolados a la espera de que haya tokens disponibles. También puede especificar esto estableciendo el parámetro latency, que indica el periodo máximo de tiempo que puede pasar un paquete en el TBF. Este último cálculo tiene en cuenta el tamaño del bucket, la tasa y posiblemente el peakrate (la tasa de picos, si es que la ha configurado).

burst/buffer/maxburst

Tamaño del bucket, en bytes. Esta es la máxima cantidad de bytes para los que pueden haber tokens disponibles instantáneamente. En general, grandes tasas precisan grandes búferes. Para 10mbit/s sobre Intel, ¡necesitará al menos un búfer de 10kbyte si desea alcanzar la tasa que ha configurado!

Si el búfer es demasiado pequeño, se descartarán paquetes debido a que llegan más tokens por tick del temporizador de los que caben en el bucket.

mpu

Un paquete de tamaño cero no usa un ancho de banda cero. En ethernet, ningún paquete usa menos de 64 bytes. La Minimum Packet Unit determina el uso mínimo de tokens por paquete.

rate

El ajuste de la velocidad. ¡Vea las indicaciones hechas anteriormente sobre la velocidad!

Si el paquete contiene tokens y se le permite estar vacío, por defecto tendrá velocidad infinita. Si esto no es aceptable, use los siguientes parámetros:

peakrate

Si hay tokens disponibles, y llegan paquetes, por defecto se envían inmediatamente, a «la velocidad de la luz» por decirlo de alguna manera. Puede que esto no sea lo que usted quiere, especialmente si tiene un bucket grande.

La tasa de picos se puede usar para especificar cuán rápido se le permite al bucket vaciarse. Si está haciendo todo según el libro, esto se consigue enviando un paquete, y esperando después lo suficiente antes de enviar el siguiente. Hemos calculado nuestras esperas de manera que se envíen justo a la tasa de picos (peakrate).

Sin embargo, debido a la resolución por defecto de 10ms del temporizador de Unix, con paquetes de 10.000 bits de media, ¡estaremos limitados a una tasa de picos de 1mbit/s!

mtu/minburst

La peakrate de 1mbit/s no es muy útil si la tasa normal es mayor que ésa. Es posible tener una tasa de picos mayor enviando más paquetes por fracción del temporizador, ¡lo que significa de forma efectiva que hemos creado un segundo bucket!

Este segundo bucket contiene por defecto un único paquete, por lo que no es un bucket realmente.

Para calcular la peakrate máxima posible, multiplique la mtu configurada por 100 (o más correctamente, HZ, que es 100 en Intel, y 1024 en Alpha).

9.2.2.2. Configuración de ejemplo

Esta es una configuración sencilla pero *muy* útil:

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

Ok, ¿por qué es esto útil? Si tiene un dispositivo de red con una cola grande, como un módem para DSL o un cable módem, y quiere comunicarse con él mediante un dispositivo rápido, como una interfaz ethernet, se encontrará conque enviar cualquier cosa destruye completamente la interactividad.

Esto se debe a que enviar datos llena la cola del módem, que probablamente es *enorme* porque realmente ayuda a conseguir una buena transferencia de datos al enviar. Pero esto no es lo que usted quiere; lo que quiere es tener una cola no tan grande de manera que la interactividad se mantenga de manera que aún pueda hacer otras cosas mientras envía los datos.

La línea anterior reduce los envíos a una tasa que no lleve formar colas en el módem (la cola estará en Linux, donde podemos ajustarla a un tamaño limitado).

Cambie 220kbit por su velocidad *real* de envío, menos un pequeño porcentaje. Si tiene un módem realmente rápido, suba «burst» un poco.

9.2.3. Stochastic Fairness Queueing

Stochastic Fairness Queueing (SFQ) es una implementación sencilla de la familia de algoritmos de colas justas (fair queueing). Es menos preciso que los otros, pero también necesita menos cálculos mientras que resulta ser casi perfectamente justo.

La palabra clave en SFQ es conversación (o flujo), que se corresponde en su mayoría a una sesión TCP o a un flujo UDP. El tráfico se divide en un número bastante grande de colas FIFO, una por cada conversación. Entonces se envía el tráfico de una manera parecida a round robin, dando a cada sesión por turnos la oportunidad de enviar datos.

Esto lleva a un comportamiento bastante equitativo y evita que una única conversación ahogue a las demás. SFQ se llama «estocástica» porque realmente no crea una cola para cada sesión, sino que tiene un algoritmo que divide el tráfico en un número limitado de colas usando un algoritmo de hash (troceo).

Debido al hash, varias sesiones pueden acabar en el mismo bucket, lo que dividirá por dos las posibilidades de cada sesión de enviar un paquete, reduciendo a la mitad de esta forma la velocidad efectiva disponible. Para evitar que esta situación acabe siendo detectable, SFQ cambia a menudo su algoritmo hash de manera que dos sesiones sólo colisionen durante unos pocos segundos.

¡Es importante tener en cuenta que SFQ sólo es útil en caso de que la interfaz real de salida esté realmente llena! Si no lo está, entonces la máquina Linux no encolará paquetes y no se producirá efecto alguno. Más tarde describiremos cómo combinar SFQ con otros qdisc para obtener lo mejor de ambos mundos.

Específicamente, configurar SFQ sobre una interfaz ethernet que esté apuntando al cable módem o a un router DSL, ¡no tiene sentido si no se hace algún ajuste más!

9.2.3.1. Parámetros y uso

SFQ es mayormente autoajustable:

perturb

Reconfigurar el hash una vez cada estos segundos. Si no se indica, el hash no se reconfigurará nunca. No es recomendable. 10 segundos es probablemente un buen valor.

quantum

Cantidad de bytes de un flujo que se permiten sacar de la cola antes de que le toque el turno a la siguiente cola. Por defecto es 1 paquete de tamaño máximo (tamaño MTU). ¡No lo ponga por debajo del MTU!

9.2.3.2. Configuración de ejemplo

Si tiene un dispositivo que tenga velocidad de enlace y tasa actual disponible idénticas, como una línea telefónica, esta configuración ayudará a mejorar la equitatividad:

# tc qdisc add dev ppp0 root sfq perturb 10
# tc -s -d qdisc ls
qdisc sfq 800c: dev ppp0 quantum 1514b limit 128p flows 128/1024 perturb 10sec 
 Sent 4812 bytes 62 pkts (dropped 0, overlimits 0) 

El número 800c: es el número de manejador asignado de forma automática, limit indica que pueden esperar 128 paquetes en esta cola. Hay 1024 hashbuckets disponibles para la contabilidad, de los cuales puede haber 128 activos al mismo tiempo (¡no caben más paquetes en la cola!) Los hash se reconfiguran una vez cada 10 segundos.