miércoles, 25 de octubre de 2017

Otro intento para configurar QoS en Linux: Día 1

Nota: Pues que creo que he tenido problemas con las capturas de pantalla y no se corresponden del todo con el trabajo en curso. Igual lo publico, así las cosas. Excepto ese pequeño detalle, todo lo demás es funcional

La idea es que modelemos el tráfico de nuestra red aplicando la siguiente configuración en nuestro firewall linux. O en nuestro IPS inline, que no es tan mala idea como en un principio lo parece. Que incluso puede hacerse una cajita específicamente para esto: Lo importante es que la configuración de este equipo pueda modelar todo el tráfico de nuestra red, al pasar toda nuestra red mediante él.

Por defecto, nuestra configuración tiene la siguiente forma:
tc qdisc show 
qdisc noqueue 0: dev lo root refcnt 2
qdisc pfifo_fast 0: dev ens2 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc pfifo_fast 0: 10.dev ens3 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc pfifo_fast 0: dev ens4 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc pfifo_fast 0: dev ens9 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
El usuario lo vería de la siguiente manera:

Empezamos con lo que podría considerarse una configuración mínima para hacer shaping:
#!/bin/bash

## Borramos la configuración anterior. 
## Cuando se tenga la configuración por defecto, se lanza un mensaje de error "RTNETLINK answers: No such file or directory"
tc qdisc delete dev ens2 root

## Cambiamos qdisc de fast_fifo a htb. 
## Dentro del esquema de HTB, este es llamado ROOT
tc qdisc add dev ens2 root handle 1:0 htb default 10

## Agregamos la primera clase. 
## Dentro del esquema de HTB, este es llamado INNER. No hay shapping en este momento, pero es necesario configurarle para el funcionamiento de los leaf
tc class add dev ens2 parent 1:0 classid 1:1 htb rate 20480 ceil 20480

## Dentro del esquema de HTB, este es llamado LEAF. Acá ocurre el shapping por primera vez
tc class add dev ens2 parent 1:1 classid 1:10 htb rate 20480 ceil 20480

## Dentro de la última (Y única por ahora) clase LEAF, agregamos una QDISC de tipo SFQ. 
## SFQ intentará repartir el ancho de banda de forma más o menos equitivativa
tc qdisc add dev ens2 parent 1:10 handle 130: sfq perturb 5


Ahora, estamos configurados de la siguiente forma:
tc qdisc show dev ens2
qdisc htb 1: root refcnt 2 r2q 10 default 10 direct_packets_stat 0 direct_qlen 1000

tc class show dev ens2
class htb 1:10 parent 1:1 leaf 130: prio 0 rate 20480bit ceil 20480bit burst 1600b cburst 1600b
class htb 1:1 root rate 20480bit ceil 20480bit burst 1600b cburst 1600b
El resultado es que ahora nos vamos limitar: 20480bit representa un enlace de 2 MB/s. Desde el punto de vista del cliente nos vemos de la siguiente forma: Al iniciar ambas peticiones casi al mismo tiempo, el uso de ancho de banda se reparte casi igual
Conforma pasa el tiempo, el tráfico para FTP-DATA consigue un mejor rendimiento. Luego, también podría ocurrir si se inicia la descarga de FTP primero:
En general, con pfifo_fast ocurrirá que algunas conexiones irán mejor que otras. Posiblemente las más nuevas (Esto es bien común de verificar). Algunos protocolos sbbre otros. Para tener mejor idea, descargo el mismo contenido usando HTTP en ambos clientes
El cliente a la derecha descarga con todo el ancho de banda disponible en ese momento

Cuando empieza la descarga en el cliente a la izquierda, este es claramente beneficiado de un mejor ancho de banda

Una solución a este problema (Que el ancho de banda se reparta mejor entre todas las conexiones), es usar una disciplina de cola en la clase leaf. SFQ es bastante sugerido para esta trabajo en específico. Agremos lo siguiente al final del script anterior

## Dentro de la última (Y única por ahora) clase LEAF, agregamos una QDISC de tipo SFQ.
## SFQ intentará repartir el ancho de banda de forma más o menos equitivativa
tc qdisc add dev ens2 parent 1:10 handle 130: sfq perturb 5
Una vez configurado así, no importa en que momento inicia la descarga el uno o el otro: Ambas conexiones tienen casi el mismo ancho de banda disponible. El "casi" es importante. SFQ "intenta" darles el mismo ancho de banda a ambas conexiones. Con todo lo que lleva en contra, parece que hace un trabajo bastante aceptable

martes, 24 de octubre de 2017

Otro intento para configurar QoS en Linux: Segunda introducción

Sobre como configurar ancho de banda en TC

Sobre este punto, tc puede ser complicado en tanto las nociones sobre unidades de transmisión suelen ser confusas para la mayoría de administradores de sistemas. Aún más, suelen confundirse las notaciones y usarse los términos indistintamente.

Al hablar de ancho de banda, la unidad de medida a usar es bites por segundo, que debería abreviarse como bps. Esta es la unidad de medida que suelen usar los proveedores de internet: Así, al decir megas, se refieren a Megabits por segundo; así por ejemplo, 2 Mbps en su forma abreviada.

Por otra parte, la mayoría de aplicaciones suelen medir la cantidad de bytes (Entendido como unidad de almacenamiento) que recibimos en una unidad de tiempo. Esta es la que se debería escribir como bytes/s

Para entender que estamos midiendo, pues considere dos cosas: Primero, la relación entre bytes/s y bps y  es de 1 a 8: 1 bytes/s = 8bps.  Luego, que como son unidades muy pequeñas, es común que ambas se usen como el prefijo kilos: KB/s y kbps, la relación sigue siendo la misma. 
(El truco más barato para saber que unidad de medida esta usando, es que si es muy grande, posiblemente se refiera a bps)

Luego esta tc. Se supone que tc acepta ambas unidades de medidas al agregar la unidad como sufijo. Hay que prestar atención para entender la confusión:
  • kbit se refiere a kilobits por segundo (Para este no hay problema). Esta también puede escribirse como Kbit
  • kbps se refiere a kilobytes por segundo (Acá se usa la notación que se espera para la otra unidad de medida)

Si ya domina la confusión sobre unidades de transferencia, puede venir a entender a tc

tc usa bits por segundo como unidad por defecto

Sobre como clasificar tráfico para tc
Nuestra primera opción es la de usar el componente filter de tc. En este caso, se considera que el clasificador u32 es el máximo exponente. Pero dado que puede convertirse en algo complicado, tenemos la opción de seguir usando a filter con algo más sencillo: Buscar "marcas" hechas con iptables mediante MARK target. También es posible usar a TOS target (Nos limitaría un poco) y a DSCP target (Con más opciones) para buscar valores en ambas cabeceras, pero tienen el inconveniente que podría tener efectos inesperados con algunos paquetes que ya tienen marca de acuerdo a sus programas de origen.

Mi mejor apuesta es a usar el CLASSIFY target, que como se verá en las pruebas que realicemos, nos ahorra, al menos a nivel de configuración, al componente filter de tc, casi nada.

lunes, 23 de octubre de 2017

Otro intento para configurar QoS en Linux: Introducción

Aunque no tengo algo como esto en producción, quería empezar a registrar algunas ideas al respecto:

Es posible que lo que entiendas por QoS sea una especie de cajón de sastre: 

Como muchos otros conceptos en informática, dicho sea de paso.
En este caso, no ayuda que en realidad haya muchos conceptos involucrados:
  • La definición misma del Protocolo de Internet (RFC791) describe en sus cabeceras al campo TOS, que permitiría elegir la calidad de servicio, es decir, los parámetros requeridos a la red por la que el paquete va a atravesar. 
  • Para ser más preciso, quizá casi a manera de curiosidad, parece haber un RFC específico para TOS, pero esta marcado como obsoleto debido a RFC2474
  • Precisamente, una ampliación de TOS se realiza en Differentiated Services (RFC2474), que básicamente define más técnicas para mejorar la calidad de la red.
  • Dentro del campo DS (Differentiated Service), de los 8 bits que lo componen, 6 bits se corresponden con DSCP (Differentiated Service Code Point). Pues sí, DSCP es parte de DiffServ, algo que en la práctica no puede tener mayor repercusión, pero que parece confundir a muchos
En GNU/Linux, la Linux Advanced Routing & Traffic Control debe considerarse La Guía de Referencia sobre QoS en este ambiente. En realidad, trata sobre casi todas las cosas más avanzadas que es posible configurar en la red de un sistema GNU/Linux, así que después después de los primeros capítulos, introductorios, nos interesa Chapter 9. Queueing Disciplines for Bandwidth Management. Es una lectura poco extensa pero que como introducción cumple bastante bien su cometido.
Recomendable leer HTB Linux queuing discipline manual - user guide, manual sobre la disciplina de encolado que vamos a usar, y que representa el núcleo de toda la configuración. De hecho, todo lo demás que puedan ofrecer esta guía proviene de allí, así que igual podría irse a las fuentes originales

Qos no es el mesías hecho software

No va a aumentar el ancho de banda mágicamente. Su función es resolver problemas bien específicos, entre los cuales no está el acelerar la navegación web. Es decir, puede hacerse algo, pero no tanto: Parece que en general, podrían haber cambios de percepción de cara al usuario, pero al final hablamos de un par de milisegundos ganados.

Algunos conceptos a tener en cuenta

A grandes rasgos, tres cosas se realizan dentro de las reglas de QoS: Restringir ancho de banda, modelar colas y clasificar el tráfico para establecer precisamente que tipo de tráfico recibirá que reglas
  • Shaping:  Se refiere a la administración del ancho de banda. Dentro de tc, se realiza con las class
  • Queueing: Se refiere a la forma en modelamos las colas. De hecho, la mayoría de documentación se vertebran respecto a este aspecto. Dentro de tc, se realiza con qdisc (Disciplina de colas)
  • Filter: Clasificar el tráfico es realmente el paso fundamental en QoS. Por diseño, el tráfico en TCP/IP no lo está, clasificarlo es el primer paso de cara a establecer un comportamiento de parte de la red hacia ellos
Pero estos activadades no se corresponden con todos sus componentes. Debería leerse Traditional Elements of Traffic Control, que de todo lo disponible, es la lectura teórica más importante que podría hacer de todo este tema.
Aprovechando, a Components of Linux Traffic Control prácticamente debe memorizarlo

Fuentes y lecturas complementarias

jueves, 12 de octubre de 2017

Resolviendo problemas con Nvidia GLX en Fedora 26

Aunque Fedora 26 ya tenía mucho andando en mi equipo, no había resentido el problema de GLX excepto en algunas cuestiones puntuales:
  • Al intentar ejecutar glxinfo desde consola, aparecía un mensaje de error: BadWindow (invalid Window parameter). También aparecía cuando intentaba acceder a la pestaña
  • También aparecía al intentar acceder a  X Screen 0 > OpenGL/GLX Information en Nvidia X Server Settings
  • Al estar usando LXQT como entorno gráfico, SDDM, el gestor gráfico (No me había dado cuenta de como llamo a estas cosas) no se mostraba en pantalla. Básicamente, SDDM cargaba como pantalla negra (Pero cargaba: Bastaba escribir la contraseña, hacer Enter y cargaba mi sesión) . Este era precisamente lo único que se me antojaba como un error.
Al revisar los log de SDDM, encontré algo parecido a Unrecognized OpenGL Version. Supuse que GLX no cargo y decidí buscar en los log de Xorg en /var/log/Xorg.0.log:
[    35.236] (EE) NVIDIA(0): Failed to initialize the GLX module; please check in your X
[    35.236] (EE) NVIDIA(0):     log file that the GLX module has been loaded in your X
[    35.236] (EE) NVIDIA(0):     server, and that the module is the NVIDIA GLX module.  If
[    35.236] (EE) NVIDIA(0):     you continue to encounter problems, Please try
[    35.236] (EE) NVIDIA(0):     reinstalling the NVIDIA driver.
Revisé con más atención el fichero y me doy cuenta que la carga del módulo ocurre, pero lo hace con el módulo de Xorg
(II) LoadModule: "glx"
(II) Loading /usr/lib/xorg/modules/extensions/libglx.so
(II) Module glx: vendor="X.Org Foundation"
compiled for 7.1.1, module version = 1.0.0
ABI class: X.Org Server Extension, version 0.3
De todas las soluciones posibles (Borrarlo, enlace simbólico, etc), me pareció que la mejor opción era cambiar el nombre del módulo GLX de Xorg para que al no hallarlo cargara el de NVIDIA
cd /usr/lib64/xorg/modules/extensions/
mv libglx.so libglx.xorg.so
Y al reiniciarlo, todo bien, ningún problema

Fuentes: (Lo más cercano que tuve a un consejo)

Otros apuntes interesantes

Otros apuntes interesantes