Me gustaría agregar algún tipo de gestión de tráfico a nuestra línea de Internet. Después de leer mucha documentación, creo que HFSC es demasiado complicado para mí (no entiendo todas las curvas, me temo que nunca lo haré bien), CBQ no es recomendable, y básicamente HTB es la forma de ir para la mayoría de las personas.
Nuestra red interna tiene tres "segmentos" y me gustaría compartir el ancho de banda más o menos equitativamente entre ellos (al menos al principio). Además, debo priorizar el tráfico de acuerdo con al menos tres tipos de tráfico (tráfico en tiempo real, tráfico estándar y tráfico masivo). El uso compartido del ancho de banda no es tan importante como el hecho de que el tráfico en tiempo real siempre debe tratarse como tráfico premium siempre que sea posible, pero, por supuesto, ninguna otra clase de tráfico puede morir de hambre.
La pregunta es, qué tiene más sentido y también garantiza un mejor rendimiento en tiempo real:
Crear una clase por segmento, cada una con la misma tasa (la prioridad no importa para las clases que no tienen hojas según el desarrollador de HTB) y cada una de estas clases tiene tres subclases (hojas) para los 3 niveles de prioridad (con diferentes prioridades y diferentes tarifas).
Tener una clase por nivel de prioridad en la parte superior, cada una con una tasa diferente (una vez más, la prioridad no importará) y cada una con 3 subclases, una por segmento, mientras que las 3 en la clase en tiempo real tienen el prio más alto, el prio más bajo en la mayoría clase, y así sucesivamente.
Trataré de aclarar esto con la siguiente imagen de arte ASCII:
Case 1:
root --+--> Segment A
| +--> High Prio
| +--> Normal Prio
| +--> Low Prio
|
+--> Segment B
| +--> High Prio
| +--> Normal Prio
| +--> Low Prio
|
+--> Segment C
+--> High Prio
+--> Normal Prio
+--> Low Prio
Case 2:
root --+--> High Prio
| +--> Segment A
| +--> Segment B
| +--> Segment C
|
+--> Normal Prio
| +--> Segment A
| +--> Segment B
| +--> Segment C
|
+--> Low Prio
+--> Segment A
+--> Segment B
+--> Segment C
El caso 1 parece la forma en que la mayoría de la gente lo haría, pero a menos que no lea los detalles de implementación de HTB correctamente, el caso 2 puede ofrecer una mejor priorización.
El manual de HTB dice que si una clase ha alcanzado su tasa, puede pedir prestado a su padre y, al pedir prestado, las clases con mayor prioridad siempre reciben primero el ancho de banda. Sin embargo, también dice que las clases que tienen ancho de banda disponible en un nivel de árbol inferior siempre se prefieren a las de un nivel de árbol superior, independientemente de la prioridad .
Supongamos la siguiente situación: el segmento C no envía tráfico. El segmento A solo envía tráfico en tiempo real, tan rápido como puede (suficiente para saturar solo el enlace) y el segmento B solo envía tráfico masivo, tan rápido como puede (nuevamente, lo suficiente como para saturar solo el enlace completo). ¿Lo que sucederá?
Caso 1:
El segmento A-> High Prio y el segmento B-> Low Prio tienen paquetes para enviar, ya que A-> High Prio tiene la prioridad más alta, siempre se programará primero, hasta que alcance su velocidad. Ahora intenta tomar prestado del Segmento A, pero dado que el Segmento A está en un nivel superior y el Segmento B-> Prio bajo aún no ha alcanzado su tasa, esta clase ahora se sirve primero, hasta que también alcanza la tasa y quiere pedir prestado Segmento B. Una vez que ambos hayan alcanzado sus tasas, ambos volverán a estar en el mismo nivel y ahora el Segmento A-> Prio alto volverá a ganar, hasta que alcance la tasa del Segmento A. Ahora intenta tomar prestado de la raíz (que tiene un montón de tráfico sobrante, ya que el Segmento C no está utilizando ninguno de su tráfico garantizado), pero nuevamente, tiene que esperar a que el Segmento B-> Prio bajo también alcance el nivel raíz. Una vez que eso suceda,
Caso 2:
High Prio-> Segment A y Low Prio-> Segment B tienen paquetes para enviar, de nuevo High Prio-> Segment A va a ganar ya que tiene la mayor prioridad. Una vez que alcanza su tasa, intenta pedir prestado a High Prio, que tiene ancho de banda libre, pero al estar en un nivel superior, tiene que esperar a que Low Prio-> Segmento B vuelva a alcanzar su tasa. Una vez que ambos hayan alcanzado su tasa y ambos tengan que pedir prestado, High Prio-> Segment A volverá a ganar hasta que alcance la tasa de la clase High Prio. Una vez que eso sucede, intenta tomar prestado de la raíz, que nuevamente le queda mucho ancho de banda (todo el ancho de banda de Normal Prio no está en uso en este momento), pero tiene que esperar nuevamente hasta que Low Prio-> Segmento B alcance el límite de velocidad del Baja clase Prio y también trata de tomar prestado de la raíz. Finalmente, ambas clases intentan tomar prestado de la raíz, se tiene en cuenta la prioridad y High Prio->
Ambos casos parecen subóptimos, ya que de cualquier manera el tráfico en tiempo real a veces tiene que esperar el tráfico masivo, aunque queda mucho ancho de banda que podría tomar prestado. Sin embargo, en el caso 2 parece que el tráfico en tiempo real tiene que esperar menos que en el caso 1, ya que solo tiene que esperar hasta que se alcance la tasa de tráfico masiva, que probablemente sea menor que la tasa de un segmento completo (y en caso 1 esa es la tasa que tiene que esperar). ¿O estoy totalmente equivocado aquí?
Pensé en configuraciones aún más simples, usando un qdisc prioritario. Pero las colas prioritarias tienen el gran problema de que causan inanición si no están limitadas de alguna manera. El hambre no es aceptable. Por supuesto, uno puede poner un TBF (Token Bucket Filter) en cada clase de prioridad para limitar la velocidad y así evitar el hambre, pero al hacerlo, una sola clase de prioridad no puede saturar el enlace por sí solo, incluso si todas las demás clases de prioridad están vacías, el TBF evitará que eso suceda. Y esto también es subóptimo, ya que ¿por qué una clase no obtendría el 100% del ancho de banda de la línea si ninguna otra clase lo necesita en este momento?
¿Algún comentario o idea con respecto a esta configuración? Parece muy difícil hacerlo usando tc qdiscs estándar. Como programador, era una tarea tan fácil si simplemente podía escribir mi propio planificador (que no se me permite hacer).