Probablemente muchos de vosotros tengáis equipos con varias tarjetas de red, esto puede usarse para muchas cosas, una de ellas (a mi entender muy interesante) es el port trunking o también conocido como port bonding.

¿Qué es el port bonding?

Es una técnica que permite agregar varios interfaces de red físicos en uno único virtual. A cada interfaz físico se le denominará slave (esclavo). Con esto podemos realizar un balanceo de carga entre las dos interfaces y conseguir un ancho de banda final igual a la suma de los anchos de banda de cada slave. Además de una ventaja adicional inmediata: redundancia de la conexión. Tenemos varios enlaces físicos a la red, perder alguno de ellos implica una degradación de servicio pero no la pérdida completa de conexión.

Ingredientes

Es necesario un módulo que viene de serie incluído en los linux 2.4 y 2.6. Además también hace falta el programa que gestiona las interfaces: ifenslave, que viene empaquetado en Debian para disfrute de todos nosotros:
# aptitude install ifenslave-2.6

El módulo bonding

Para crear la interfaz virtual debemos cargar un módulo que la gestione aplicando alguna política o algoritmo para ello. Este módulo tiene muchos parámetros, aunque creo que antes de listarlos todos explicaremos un poco el funcionamiento teórico para entender mejor los parámetros.

Slaves y colas

Toda interfaz de red tiene asignada automáticamente una cola de envío y otra de recepción. Cada slave tiene también sus propias colas. El esquema es más o menos el siguiente (supondremos dos slaves):
RED ----> ETH0(RX) --->\
                        BOND0(RX) ----> S.O.
RED ----> ETH1(RX) --->/

                    /----> ETH0(TX) ----> RED
S.O. ----> BOND0(TX)
                    \----> ETH1(TX) ----> RED
(Ole ese ASCII ART!) En cuanto a la recepción hay poco que decir, cuando llega un paquete a algún slave se pasa a la cola de recepción de la interfaz virtual. Si un enlace físico falla, hay poco que podamos hacer: símplemente se degradará el servicio. Pero para el envío hay un poco más de historia, puesto que si detectamos que un enlace se ha perdido, deberemos pasar todos los paquetes de la cola de esa interfaz a la esclava que sigue funcionando para después congelar esa cola de envío degradando así el rendimiento de la interfaz. Por tanto debemos poder detectar cuando un enlace se ha caído, a este respecto existen dos posibilidades: detección por ARP o mediante MII (Media Indepent Interface).
  • Detección ARP: consiste en enviar periódicamente peticiones ARP por un slave, si estas peticiones fallan el enlace se considera caído.
  • Detección MII: si el módulo de la NIC (Network Interface Card) implementa ciertas llamadas, se puede detectar cuando un enlace está físicamente caído, en cuyo caso, se deshabilita el slave.
Evidentemente, los esclavos deshabilitados se seguirán probando hasta que vuelvan a estar operativos, momento en el cual se volverán a habilitar dentro de la interfaz virtual.

Balanceos de carga

Probablemente este sea el aspecto más importante del bonding: cómo balancear la carga entre todos los esclavos. En este sentido el módulo tiene un parámetro que permite indicar qué algoritmo se debe usar, los algoritmos implementados son:
  • balance-rr (modo 0): se emplea un algoritmo round robin entre la cola virtual y las de los esclavos. Es algo así como: un paquetillo para un esclavo, otro para otro esclavo, un paquetillo para un esclavo, otro para el otro... etc. Es el algoritmo que se usa por defecto.
  • active-backup (modo 1): realmente no balancea la carga, usa sólo un esclavo y en caso de fallar, usa el siguiente disponible.
  • balance-xor (modo 2): emplea una formulita para decidir por qué interfaz sale: (source-MAC xor dest-MAC) mod n-slaves.
  • broadcast (modo 3): se transmite todo por todas las interfaces. Este método no balancea tampoco, pero provee tolerancia a fallos.
  • 802.3ad (modo 4): emplea algoritmos definidos en el estándar IEEE 802.3ad.
  • balance-tlb (modo 5): balancea la carga de transmisión entre los esclavos dependiendo de la velocidad de estos y de la carga total. El tráfico es recibido por un esclavo, en caso de fallar otro esclavo toma su MAC y continúa recibiendo tráfico.
  • balance-alb (modo 6): realiza el balanceo anterior además de un balanceo también en la recepción. Este método debe modificar las MAC de los esclavos estando las tarjetas activas, esto debe estar soportado por el driver para poder usar este método.
Aunque todo esto parezca muy bonito, hay que tener en cuenta una cosa: algunos métodos necesitan ciertas configuraciones/capacidades en el switch al que estés conectados los esclavos. Ah! se me olvidaba: si el switch tiene un único link de salida a la red y va a la misma velocidad que nuestros esclavos, el balanceo se hace inútil ya que se produce un cuello de botella en el link de salida del switch.

Ahora si: carga y configuración del módulo bonding

Cargaremos el módulo como de costumbre:
# modprobe bonding [parámetros]
Y los parámetros los tenemos a continuación:
  • arp_interval: si se especifica (por defecto es 0, desactivado) indica cada cuántos milisegundos se enviará un ARP reply. Este tipo de detección es compatible con las políticas 0 y 2.
  • arp_ip_target: indica cuál será la IP destino. Se pueden especificar varias separadas por comas (como máximo 16).
  • downdelay: especifica cuántos milisegundos se tardará en desactivar un esclavo cuando se detecte un error en el enlace. Por defecto es 0 (inmediatamente) y sólo se emplea en la detección mediante MII.
  • lacp_rate: en el modo 802.3ad especifica cada cuánto se va a envíar un mensaje LACDPU. Estos paquetes se encargan de controlar el protocolo de agregación de enlaces. Este parámetro tiene dos posibles valores: slow o 0 (por defecto) y fast o 1.
  • max_bonds: indica cuántas interfaces virtuales creará como máximo esta instancia del módulo. Por defecto vale 1 (sólo bond0).
  • miimon: si especificamos un valor distinto de 0 (por defecto) activa la detección por MII, indica cada cuántos milisegundos se va a comprobar el estado del enlace. Un buen valor puede ser 100.
  • mode: indica que algoritmo de balanceo se va a usar, sus posibles valores se indicaron en el apartado anterior.
  • primary: este parámetro sólo se usa si se activa el modo 1, y se usa para indicar cuál esclavo es el primario.
  • updelay: especifica cuánto tiempo en milisegundos se tardará en activar un esclavo cuando se detecta un enlace repuesto. Por defecto vale 0.
  • use_carrier: por defecto vale 1, lo cual indica que se usará una llamada a netif_carrier_ok() del módulo de la NIC para la detección por MII. Si vale 0 se usarán llamadas ETHTOOL ioctl's, lo cual está deprecated.
  • xmit_hash_policy: especifica la política de transmisión para los modos 2 y 4. Los posibles valores son:
    • layer2: se usa la fórmula que se indicó en el modo 2 (apartado anterior). Este algoritmo hace que el tráfico con un mismo destino "salga" siempre por la misma interfaz. Es la política usada por defecto.
    • layer3+4: con esta política se usará información de niveles superiores al de enlace (realiza XOR's también con las IP's) y no tiene el mismo comportamiento según la clase de tráfico transportado. Es un buen algoritmo pero no es 100% compatible con IEEE 802.3ad.
  • Con tantos parámetros podremos probar muchas opciones, yo actualmente uso:
    # modprobe bonding miimon=100 mode=balance-tlb
    Con esto ya tenemos el módulo cargado, sólo nos falta configurar la interfaz y añadir esclavos.

    Configurar interfaz bond

    Si véis how-to's por internet veréis que montan un "pitoste" de parámetros en ficheros, etc. Pero es porque usan SuSE y cosas de esas raras, encima para tener IP estática. Pues en Debian abrimos /etc/networking/interfaces y añadimos:
    iface bond0 inet dhcp
        slaves eth0 eth1
    Tened en cuenta que eth0 y eth1 no deben estar activos en ese momento (deben estar down). Y finalmente para activar la interfaz:
    # ifup bond0
    Y ale... a disfrutar... ;)

    Apéndice A: Configuración del switch

    Los modos active-backup, balance-tlb y balance-alb no requiere ninguna configuración especial en el switch, ideales si no tenemos acceso a la configuración del equipamiento de red ;-). El modo 802.3ad requiere que el switch tenga los puertos donde conectamos los esclavos en modo 802.3ad aggregation. Esto depende de cada switch, por ejemplo, en los switch's de Cisco esta capacidad se llama EtherChannel y debe estar en modo lacp. Por último, los modos balance-rr, balance-xor y broadcast generalmente requiere poder agrupar puertos. Las nomenclaturas de estos grupos dependen del fabricante del switch, como hemos dicho antes, Cisco llama a estas agrupaciones EtherChannel, también se usa trunk group, etc.

    Enlaces de interés

    Pues hay mucho por internet, pero lo mejor es la documentación del propio módulo: Linux Ethernet Bondign Driver HOW-TO. Si probáis la receta, podéis envíar vuestras configuraciones (tanto del switch si la conocéis y de vuestro bond para hacer comparativas de rendimientos y todo eso. :-)


blog comments powered by Disqus