Vamos a describir en esta receta algunos de los comandos útiles para lo que se ha venido a denominar traffic shaping, en cristiano, control de nuestro ancho de banda. Aviso a navegantes, este tema es un poco lioso y yo no soy ni mucho menos un experto por lo que, primero, espero comentarios, correcciones, mejoras, etc. y segundo, ojo con lo que haces!!

Enviando paquetes a la red

Bueno vamos con algunos comandos y de paso vamos introduciendo algunos conceptos:

# ip link show
1: lo: <LOOPBACK,UP,10000> mtu 16436 qdisc noqueue
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:e0:4c:00:84:bb brd ff:ff:ff:ff:ff:ff

Este comando muestra los “enlaces” presentes en un computador, en esta información va incluida alguna información muy útil, dejando aparte la interfaz loopback, nos centramos en el enlace número dos, es decir la eth0 que es una interfaz ethernet. Despues de la información relativa a la mtu (Maximum transmission unit) que en una ethernet es 1500 tenemos la disciplina de colas (qdisc). Para que nos entendamos, todos los paquetes que se envían son almacenados en un sistema de colas hasta la entrega a la red.

Ahora bien, cómo se gestionan las colas y qué algoritmo se utiliza para decidir qué paquete desencolamos es un mundo un poco complejo que trataremos de introducir en esta receta.

Antes de continuar hay que indicar que, aparte de las colas, están las clases de tráfico y los filtros. Generalmente (esto depende mucho del tipo de colas que estamos usando) se definen clases de tráfico y los filtros clasifican el tráfico en esas clases atendiendo al protocolo, ip, etc..

Tipos de Colas

El algoritmo por defecto es “pfifo_fast”, que es el más sencillo, el primer paquete que llega es el primero que sale y lo más rápido posible, esto no tiene ningún misterio. Con esta política todo el mundo es feliz y todos los paquetes son tratados exactamente igual buscando las máximas prestaciones. No obstante estaremos de acuerdo en que no todas las aplicaciones y ordenadores son de igual importancia por lo que asignar un recurso tan escaso como el ancho de banda, puede ser una buena idea y muy útil.

Hay mas disciplinas de colas, entre las cuales podemos enumerar:

  • FIFO – simple FIFO (packet (p-FIFO) or byte (b-FIFO) ): la que hemos visto, tambien hay ha nivel de byte.
  • PRIO – n-band strict priority scheduler: En esta disciplina tenemos un sistemas de encolado basado en clases de tráfico a las cuales se les asigna una prioridad, Las clases de tráfico son desencoladas en funcíon de la prioridad (el 0 es la mayor prioridad y cuanto mayor es el número menor prioridad).
  • TBF – token bucket filter: Esta es una disciplina para establecer límites en el ratio de entrega de paquetes para las distintas colas. Si quieres limitar el ancho de banda de una interfaz, esto es lo que necesitas.
  • CBQ – class based queue: Otro sistema basado en colas un poco mas complejo que el PRIO, aquí puedes establecer jerarquías de clases y prioridades. Hay que resaltar que dentro de cada una de las clases hay una qdisc que, por defecto es una pfifo pero que puede ser configurada por lo que la cantidad de combinaciones es enorme.
  • CSZ – Clark-Scott-Zhang: Para que nos entendamos garantiza el ancho de banda de los servicios garantizados y el resto lo deja para los paquetes que no se clasifican (best-effort traffic), la teoría de esto es compleja.
  • SFQ – stochastic fair queue: Tienes diferentes colas asociadas a flujos y vas sacando de cada cola un paquete a la vez (round robin) para que todas los flujos tengan el mismo ancho de banda, el tema es que si una aplicación establece muchos flujos obtiene mas ancho de banda.
  • RED – random early detection: Esto esta diseñado para backbones, el tema es que trata de aprovechar las características de control de flujo del protocolo TCP para ajustar los parámetros de entrega de los paquetes y evitar la congestión antes de que se produzca. Lo que hace es eliminar aleatoriamente paquetes cuando las colas empiezan a llenarse, cuanto mas llena esta la cola, va aumentando la probabilidad de eliminar un paquete de forma aleatoria. TCP cuando pierde paquetes reduce su tasa de envío por lo que reduce la posibilidad de congestiones, hay que ajustar muy bien los valores para que no perdamos mas paquetes de los que perderíamos en congestión (vamos eliminando paquetes por que la red no da mas de si). Esto plantea un problema ya que UDP no implementa un mecanismo similar con lo que los flujos UDP no se ajustan.
  • GRED – generalized random early detection: El tema es que RED descarta aleatoriamente paquetes cuando hay una posible congestión y de forma aleatoria tratando todos los flujos igual, como en el campo del señor no todos somos iguales, GRED crea una serie de colas virtuales y establece políticas RED distintas (como por ejemplo la probabilidad de eliminar un paquete cuando se empieza a llenar la cola) a cada una de ellas.
  • TEQL – traffic equalizer: Esta se usa cuando entre dos redes distintas tenemos dos enlaces directos, para balancear la carga entre ellos. Aquí hay un ejemplo sencillo: http://www.roseindia.net/linux/tutorial/linux-howto/Adv-Routing-HOWTO/lartc.loadshare.html
  • ATM – asynchronous transfer mode: Esto es para que emules el comportamiento de una red ATM transmitiendo unidades de información en celdas.
  • DSMARKDSCP (Diff-Serv Code Point)marker/remarker: Esto mas que una disciplina es una política de marcado de paquetes en función de reglas específicas.
  • Hierarchical Token Bucket (HTB): Podemos dividir el ancho de banda especificando el mínimo y el máximo, si alguien no esta usando su ancho de banda, se asigna al resto de clases. Este se considera mas sencillo que el CBQ y bastante flexible por lo que lo usaremos para los ejemplitos.

La herramienta tc: comándos básicos

Vamos con algunos comandos, de aqui en adelante si queremos ver como van nuestras colas:

 $ tc -s qdisc ls dev eth0
qdisc pfifo_fast 0: root bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
 Sent 287345331 bytes 846853 pkt (dropped 0, overlimits 0 requeues 0)
 rate 0bit 0pps backlog 0b 0p requeues 0

Un comandito muy útil para eliminar todo y dejarlo con la configuración por defecto:

 $ tc qdisc del dev eth0 root

Vamos con un ejemplo, si queremos limitar el tráfico ip de salida a 5 kbps debemos realizar los siguientes pasos:

Primero añadimos la gestión de colas htb a la raíz de nuestro dispositivo (en este caso eth0):

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

Este primer comando define una cola que se añade a la raiz (root) con un manejador handle 1: y que
por defecto manda el tráfico a la clase de tráfico 1.

Ahora creamos la clase de tráfico:

 $ tc class add dev eth0 parent 1: classid 1:1 htb rate 1kbps ceil 5kbps

Para esta clase de tráfico, el padre es la qdisc que acabamos de crear (parent 1:) y cuyo identificador es 1 (classid 1:1). Por último, la parte de comando que delimita el ancho de banda que pueden consumir viene determinado por la parte del comando “rate 1kbps ceil 5 kbps” que le dice al kernel, que, asegure una tasa de 1kbps en caso de congestión y que como mucho esa clase puede llegar a 5 kbps. Si no ponemos la parte ceil, la clase consumirá todo el ancho de banda sobrante que quede (esto es así por que estamos usando HTB).

En teoría ya esta todo, al indicarle al crear la cola que la clase por defecto es la 1, todo el tráfico es dirigido a esa clase que ya esta limitada. Ahora bien, si queremos indicarle explícitamente que mande todo el tráfico ip a esa clase debemos crear un filtro:

 $ tc filter add dev eth0 protocol ip parent 1: handle 1 fw classid 1:1

De nuevo le indicamos que el parent es la qdisc htb root (parent 1:), el manejador de este filtro es el 1 y la acción es forwardear todo el protocolo ip (protocol ip) a la clase 1:1 (fw classid 1:1).

Varios temas, primero sólo podemos controlar el tráfico que sale por eth0, para controlar el tráfico de entrada hay que trabajar con la cola de entrada (ingress). A menos que estes probando cosas, es recomendable meter tu configuración (lista de comandos) en un script ya que es frecuente cometer errores, y aunque se pueden cambiar las especificaciones, muchas veces puede ser lioso.

Viendo como va nuestra configuración

Si queremos ver como va nuestra configuración de filtros:

 # tc filter show dev eth0
filter parent 1: protocol ip pref 49152 fw
filter parent 1: protocol ip pref 49152 fw handle 0x1 classid 1:1

Nuestras clases:

 # tc class show dev eth0
class htb 1:1 root prio 0 rate 8000bit ceil 40000bit burst 1603b cburst 1619b

El rate es en bit, le pusimos 1kb es decir 1000*8 bits (lo coge en bytes).

Y las colas:

 # tc qdisc show dev eth0
qdisc htb 1: r2q 10 default 1 direct_packets_stat 294

Cada sistema de colas diferentes tiene comandos y parámetros específicos , en algunos casos puedes añadirle a las clases de tráfico qdisc propias que tienen nuevas clases (en forma de árbol) por lo que las combinaciones son múltiples.

Algunas referencias:



blog comments powered by Disqus