Capítulo 10. Compartir la carga sobre varias interfaces

Hay varias maneras de hacer esto. Una de las más sencillas y directas es «TEQL» ("True" - o "trivial" - link equalizer). Como la mayoría de las cosas que tienen que ver con las colas, la división de cargas va en ambos sentidos. Puede que ambos extremos del enlace deban participar para conseguir un efecto completo.

Imagine esta situación:

                 +-------+   eth1   +-------+
                 |       |==========|       |
     'red 1' ----|   A   |          |   B   |---- 'red 2'
                 |       |==========|       |
                 +-------+   eth2   +-------+

A y B son routers, y por el momento asumiremos que ambos funcionan con Linux. Si el tráfico va de la red 1 a la red 2, el router A necesita distribuir los paquetes sobre ambos enlaces hacia B. Se necesita configurar el router B para que acepte esto. Lo mismo sucede en la otra dirección: cuando los paquetes van desde la red 2 a la red 1, el router B necesita enviar paquetes tanto sobre eth1 como eth2.

La parte de distribución la hace un dispositivo «TEQL», así (no podría ser más sencillo):

# tc qdisc add dev eth1 root teql0
# tc qdisc add dev eth2 root teql0
# ip link set dev teql0 up

¡No olvide la orden «ip link set up»!

Esto debe hacerse en ambas máquinas. El dispositivo teql0 básicamente es un distribuidor roundrobin sobre eth1 y eth2, para enviar paquetes. Nunca aparecerán datos viniendo por un dispositivo teql, sino que simplemente aparecen en las eth1 y eth2 "básicas".

Pero ahora sólo tenemos dispositivos, de manera que necesitamos hacer un rutado adecuado. Una manera de hacerlo es asignar una red /31 para ambos enlaces, y también al dispositivo teql0.

FIXME: ¿necesita esto algo como «nobroadcast»? Una /31 es demasiado pequeña para contener una dirección de red y una de difusión (si no funciona como debe, pruebe con /30 y ajuste las direcciones IP de acuerdo). ¡Incluso podría intentar que eth1 y eth2 vayan sin dirección IP!

En el router A:

# ip addr add dev eth1 10.0.0.0/31
# ip addr add dev eth2 10.0.0.2/31
# ip addr add dev teql0 10.0.0.4/31

En el router B:

# ip addr add dev eth1 10.0.0.1/31
# ip addr add dev eth2 10.0.0.3/31
# ip addr add dev teql0 10.0.0.5/31

El router A debería ser capaz ahora de hacer ping a 10.0.0.1, 10.0.0.3 y 10.0.0.5 sobre los dos enlaces reales y el ecualizado. El router B debería ser capaz de hacer ping a 10.0.0.0, 10.0.0.2 y 10.0.0.4 sobre los enlaces.

Si esto funciona, el router A debería hacer que 10.0.0.5 sea su ruta para alcanzar la red 2, y el router B debería hacer de 10.0.0.4 su ruta para alcanzar la red 1. Para el caso especial en que la red 1 sea su red casera y la red 2 Internet, el router A debería hacer de 10.0.0.5 su ruta por defecto.

10.1. Problemas

Nada es tan fácil como parece. Se necesita desactivar el filtrado de ruta de vuelta (return path filtering) en eth1 y eth2 de ambos router, porque en caso contrario descartarán los paquetes destinados direcciones IP que no sean las suyas:

# echo 0 > /proc/net/ipv4/conf/eth1/rp_filter
# echo 0 > /proc/net/ipv4/conf/eth2/rp_filter

Entonces nos encontramos con el desagradable problema de la reordenación de paquetes. Digamos que A envía 6 paquetes a B (eth1 podría llevar los 1, 3 y 5. eth2 llevaría entonces los 2, 4 y 6). En un mundo ideal, el router B los recibiría en este orden, 1, 2, 3, 4, 5, 6. Pero hay una posibilidad muy cierta de que el núcleo haga esto: 2, 1, 4, 3, 6, 5. El problema es que esto confunde a TCP/IP. Mientras que esto no es un problema para enlaces que llevan sesiones TCP/IP diferentes, no será capaz de juntar varios enlaces y conseguir enviar un único fichero por ftp mucho más rápido, a menos que el SO emisor o receptor sea Linux, que no se asusta fácilmente por un reordenado sencillo.

Sin embargo, para muchas aplicaciones, el equilibrio de carga sobre enlaces es una gran idea.