Reserva de ancho de banda

Una de las grandes ventajas de Linux es que va mucho más allá de lo que existe en materia de sistema de gestión de ancho de banda de tipo propietario, que cuestan cientos de miles de pesetas.

Para el controlo de tráfico, se usan dos conceptos: filtros y colas. Los filtros ponen los paquetes en las colas y las colas deciden qué paquetes mandar antes que otros. Luego veremos más en detalle la relación entre colas y ancho de banda.

Hay muchos tipos de filtros distintos, los más comunes son 'fwmark' y 'u32'. El primero nos deja usar el código de netfilter (iptables) para seleccionar tráfico, mientras que el segundo nos permite seleccionar el tráfico basándose en cualquier cabecera de paquete.

Vamos a demostrarlo con un ejemplo ficticio de ISP que necesita hacer reparto de ancho de banda entre sus clientes.

Qué son colas ?

Las colas determinan el orden en que se mandan los paquetes. Qué tiene que ver con nuestro ancho de banda ?

Imaginamos una caja de supermercado donde la gente hace cola para pagar sus compras. La ultima persona llegada se pone al final de la cola y espera su turno: es una cola FIFO (First In, First Out). Ahora si dejamos ciertas personas siempre ponerse en medio de la cola, serán atendidas antes y podrán comprar más rápidamente.

Internet esta basado principalmente en TCP/IP y TCP/IP no sabe nada de ancho de banda. Lo que hace una máquina es mandar datos cada vez más rápido hasta que se detecte que algunos paquetes se están perdiendo, luego ralentiza el proceso.

Es el equivalente de no leer la mitad de los emails recibidos, esperando que la gente deje de mandar correo. La diferencia es que con Internet sí funciona.

Nuestro ISP

Nuestro router Linux tiene 2 interfaces eth0 y eth1. eth0 esta conectado a nuestra red de clientes y eth1 es nuestra conexión al backbone Internet.

Sólo podemos limitar lo que mandamos así que necesitamos dos tablas de reglas. Modificaremos la cola de eth0 para decidir la velocidad a la que se mandan los datos a nuestros clientes, su ancho de banda o su 'download speed'.

Luego modificamos eth1 para especificar la velocidad de envío de datos a Internet. Es lo que se denomina 'upload speed' para nuestros clientes.

Usando CBQ

Con CBQ podemos usar clases de usuarios (así como subclases). Vamos a crear dos: 'ISP' para nuestros clientes y 'Office' para la red corporativa. Disponemos de 10 Mbit de ancho de banda, vamos a dar 8 a ISP y 2 a Office.

La herramienta que usamos es 'tc'

Definimos la regla de cola (qdisc: queueing discipline) para eth0. Con 'root' indicamos cuál es la disciplina raíz. El 'handle' es el identificador de la regla. Luego indicamos al núcleo que tiene 10Mbit disponibles y que el tamaño medio de los paquetes es más o menos 1000 octetos:

# tc qdisc add dev eth0 root handle 10: cbq bandwidth \
     10Mbit avpkt 10
	

Ahora generamos nuestra clase raíz de la que cuelgan las demás. 'parent 10:0' indica que desciende del 'handle' '10:'. Le asignamos el identificador '10:1'. Se especifica también el MTU (1514). Para información, el MTU (Maximum Transmission Unit) es el tamaño máximo posible de datos transportados por un 'frame' (por ejemplo un datagramo IP). En el caso de una conexion ethernet, el MTU es de 1500:

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

Generamos luego nuestra clase ISP: le dedicamos 8 Mbit e indicamos que no se puede superar, con 'bounded', si no, iría restando ancho de banda de otras clases:

# tc class add dev eth0 parent 10:1 classid 10:100 cbq \
bandwidth 10Mb 8Mbit allot 1514 weight 800Kbit prio 5 \
maxburst 20 avpkt 1000 bounded
	

Este es el comando que genera la clase Office:

# tc class add dev eth0 parent 10:1 classid 10:200 cbq \
bandwidth 10Mb 2Mbit allot 1514 weight 200Kbit prio 5 \
maxburst 20 avpkt 1000 bounded
	

Hasta ahora hemos indicado al núcleo cuáles son nuestras clases pero no cómo gestionar las colas. El procedimiento es el siguiente:

# tc qdisc add dev eth0 parent 10:100 sfq quantum 1514b \
  perturb 15   
# tc qdisc add dev eth0 parent 10:200 sfq quantum 1514b \
  perturb 15   
	

En este caso, usamos la regla 'Stochastic Fairness Queueing' (sfq), que no es totalmente imparcial, pero que funciona bien para un ancho de banda bastante elevado, sin cargar demasiado el núcleo.

Hay otras reglas como 'Token Bucket Filter' pero consumen mas ciclos de CPU.

Sólo nos queda hacer una cosa: indicar al núcleo qué paquetes pertenecen a qué clase:

# tc filter add dev eth0 parent 10:0 protocol ip prio 100 \
  u32 match ip \
150.151.23.24 flowid 10:200
# tc filter add dev eth0 parent 10:0 protocol ip prio 25 \
  u32 match ip \
150.151.0.0/16 flowid 10:10
	

Aquí consideramos que Office solo tiene 1 dirección IP para todo el tráfico y que las demás son de ISP.

Esta parte servía para dividir el tráfico 'downstream'. Hay que hacer lo mismo con el tráfico saliente:

# tc qdisc add dev eth1 root handle 20: cbq bandwidth \
  10Mbit avpkt 10
# tc class add dev eth1 parent 20:0 classid 20:1 cbq \
bandwidth 10Mbit 10Mbit allot 1514 weight 1Mbit prio 8 \
maxburst 20 avpkt 1000       
# tc class add dev eth1 parent 20:1 classid 20:100 cbq \
bandwidth 10Mb 8Mbit allot 1514 weight 800Kbit prio 5 \
maxburst 20 avpkt 1000 bounded                                                            
# tc class add dev eth1 parent 20:1 classid 20:200 cbq \
bandwidth 10Mb 2Mbit allot 1514 weight 200Kbit prio 5 \
maxburst 20 avpkt 1000 bounded                                                            
# tc qdisc add dev eth1 parent 20:100 sfq quantum 1514b \
  perturb 15
# tc qdisc add dev eth1 parent 20:200 sfq quantum 1514b \
  perturb 15
# tc filter add dev eth1 parent 20:0 protocol ip prio 100 \
  u32 match ip 150.151.23.24 flowid 20:200
# tc filter add dev eth1 parent 20:0 protocol ip prio 25 \
u32 match ip 150.151.0.0/16 flowid 20:100
	

Pues muy bien, tenemos nuestro sistema de ancho de banda funcionando !

Más disciplinas de cola

Hay muchas disciplinas de cola bajo Linux. Cada una tiene sus ventajas y inconvenientes.

pfifo_fast

Desde luego es la cola más usada. Como indica su nombre, es una cola FIFO y entonces los paquetes no reciben tratamiento especial.

Stochastic Fairness Queue (sfq)

Es el tipo de cola que hemos visto antes. No es muy determinista pero trabaja bastante bien. Su principal ventaja es que consume poco ciclos de CPU y poca memoria. Para tener un sistema de cola totalmente imparcial, habría que grabar todos los paquetes que pasan por la máquina.

Existen varios algoritmos 'imparciales' (fair). SFQ es uno de ellos, y se basa en lo que llamaremos conversaciones. Una conversación es una secuencia de paquetes de datos que tienen suficientes parámetros como para distinguirlos de las otras conversaciones. En este caso, los parámetros usados son la dirección de origen y de destino de los paquetes, así cómo el protocolo usado.

Se otorgan colas FIFO dinámicamente a las conversaciones que surgen, una cola por conversación. La disciplina de envío es de tipo round-robin, es decir se envía un paquete de cada cola secuencialmente. Un inconveniente de SFQ es que no puede distinguir tráfico interactivo de tráfico de masa. Por esta razón se suele usar CBQ antes de SFQ

Token Bucket Filter

TBF es un buffer (bucket/cubo) rellenado constantemente por trozos virtuales de información (tokens) a velocidad especifica (token rate). El parámetro realmente importante es el tamaño del cubo.

Cada token que llega permite a un paquete llegando a la cola ser enviado y luego se destruye. Tenemos dos flujos que pueden dar lugar a tres posibilidades:

  • Si los datos llegan al TBF a la misma velocidad que los tokens, cada paquete empareja un token y pasa la cola sin demorar.

  • Si los paquetes de datos llegan menos rápido que los tokens, los tokens se van acumulando hasta rellenar el cubo. Si llegan todavía más tokens, se pierden. Los tokens que se han ido acumulando pueden ser usado luego para amortiguar picos de tráfico.

  • Si los paquetes de datos llegan más rápido que los tokens, cuando no hay más tokens, se tiran los paquetes que desbordan

La última posibilidad es importante, en el sentido que permite definir el ancho de banda disponible para los datos. La acumulación de tokens permite amortiguar unos picos de tráfico pero no una sobrecarga continúa.

Random Early Detect

RED es un gestor de cola 'inteligente'. Cuando se inicia una sesión TCP/IP, ninguno de los dos hosts sabe cual es el ancho de banda disponible. Así que TCP/IP empieza a transmitir paquetes cada vez más rápido. Cuando se esta ocupando todo el ancho de banda, se desechan los paquetes (ver arriba).

Lo que hace RED es que finge una congestión antes de que el ancho de banda sea realmente enteramente ocupado. Es una técnica muy útil para tráfico de ancho de banda muy grande. RED se usa principalmente en los routers de Backbone, es decir donde el ancho de banda supera 100 Mbits/s. En este caso no se puede hacer un reparto de ancho de banda 'imparcial'. Más bien se hace un reparto de tipo estadística.

Ingress policer qdisc

Este tipo de cola es interesante si se necesita limitar el ancho de banda de una máquina sin ayuda de una caja externa. Se puede determinar el ancho de banda internamente y decidir tirar paquetes cuando se desborda.

En breve, es un sistema práctico cuando uno quiere limitar su velocidad de baja de ficheros, para dejar un poco de ancho de banda a sus colegas.

DSMARK

Para acabar este serie, hay que mencionar Dsmark también. Es probablemente el gestor de cola más complicado que existe. Su explicación sola necesitaría seguramente una buena así que no vamos a entrar en los detalles.

Dsmark es una disciplina de cola que permite ofrecer Servicios Diferenciados (Differentiated Services, o DiffServ o DS). Hoy en día conocemos dos arquitecturas de QoS (Quality of Service, Calidad de Servicio).

Una de los primeros intentos para ofrecer QoS en IP fue de usar el campo TOS (Type of Service) en las cabeceras IP. Cambiando su valor, podíamos elegir un nivel de débito o de fiabilidad. Pero este método no daba suficiente flexibilidad. Una de la nuevas arquitecturas que apareció fue DiffServ que usa el campo DS de las cabeceras IP.

Para más informaciones os aconsejo dirigiros a la página http://www.ietf.org/html.carters/diffserv-charter.html

Para concluir

Esperamos que esta breve introducción fue interesante y os presento un poco todas las posibilidades del núcleo Linux a nivel de gestión avanzada de tráfico. Hay muchos campos que no hemos podido mencionar debido a la complejidad del asunto.

También hay que destacar que es un dominio en pleno desarrollo y evolución. Habría que mencionar los clasificadores de cola, todos los parámetros de configuración del núcleo a nivel TCP/IP, el bridging y el proxy-arp, el routing dinámico, limitación del tráfico ICMP, etc, etc.