Hoy en día, existen soluciones listas para usar (propietarias) para monitorear flujos de IP (TS), por ejemplo
Muy brevemente sobre TSDuck
TSDuck es un software de código abierto (licencia BSD de 2 cláusulas) (un conjunto de utilidades de consola y una biblioteca para desarrollar utilidades o complementos personalizados) para manipular flujos de TS. Como entrada, puede funcionar con IP (multidifusión/unidifusión), http, hls, sintonizadores dvb, demodulador dektec dvb-asi, hay un generador de flujo de TS interno y lectura de archivos. La salida se puede escribir en un archivo, moduladores IP (multicast/unicast), hls, dektec dvb-asi y HiDes, reproductores (mplayer, vlc, xine) y drop. Se pueden incluir varios procesadores de tráfico entre la entrada y la salida, por ejemplo, reasignación de PID, codificación/descodificación, análisis de contador CC, cálculo de tasa de bits y otras operaciones típicas para transmisiones TS.
En este artículo, los flujos de IP (multidifusión) se utilizarán como entrada, se utilizarán los procesadores bitrate_monitor (por el nombre, está claro de qué se trata) y la continuidad (análisis de los contadores CC). Puede reemplazar fácilmente la multidifusión IP con otro tipo de entrada compatible con TSDuck.
Hay
A continuación, se usa la versión TSDuck 3.19-1520, se usa Linux como sistema operativo (se usó debian 10 para preparar la solución, CentOS 7 se usó para uso real)
Preparando TSDuck y OS
Antes de monitorear los flujos reales, debe asegurarse de que TSDuck funcione correctamente y que no haya caídas en la tarjeta de red o en el nivel del sistema operativo (socket). Esto es necesario para no adivinar más tarde dónde ocurrieron las caídas: en la red o "dentro del servidor". Puede verificar las caídas en el nivel de la tarjeta de red con el comando ethtool -S ethX, el ajuste se realiza con el mismo ethtool (generalmente, necesita aumentar el búfer RX (-G) y, a veces, deshabilitar algunas descargas (-K)). Como recomendación general, se puede recomendar utilizar un puerto separado para recibir el tráfico analizado, si es posible, esto minimiza los falsos positivos asociados con el hecho de que la caída ocurrió exactamente en el puerto del analizador debido a la presencia de otro tráfico. Si esto no es posible (se utiliza una minicomputadora/NUC con un puerto), entonces es muy recomendable configurar la priorización del tráfico analizado en relación con el resto en el dispositivo al que está conectado el analizador. Con respecto a los entornos virtuales, aquí debe tener cuidado y poder encontrar caídas de paquetes que comiencen desde un puerto físico y terminen con una aplicación dentro de una máquina virtual.
Generación y recepción de un stream dentro del host
Como primer paso para preparar TSDuck, generaremos y recibiremos tráfico dentro de un solo host usando netns.
Preparando el ambiente:
ip netns add P #создаём netns P, в нём будет происходить анализ трафика
ip link add type veth #создаём veth-пару - veth0 оставляем в netns по умолчанию (в этот интерфейс будет генерироваться трафик)
ip link set dev veth1 netns P #veth1 - помещаем в netns P (на этом интерфейсе будет приём трафика)
ip netns exec P ifconfig veth1 192.0.2.1/30 up #поднимаем IP на veth1, не имеет значения какой именно
ip netns exec P ip ro add default via 192.0.2.2 #настраиваем маршрут по умолчанию внутри nents P
sysctl net.ipv6.conf.veth0.disable_ipv6=1 #отключаем IPv6 на veth0 - это делается для того, чтобы в счётчик TX не попадал посторонний мусор
ifconfig veth0 up #поднимаем интерфейс veth0
ip route add 239.0.0.1 dev veth0 #создаём маршрут, чтобы ОС направляла трафик к 239.0.0.1 в сторону veth0
El ambiente está listo. Iniciamos el analizador de tráfico:
ip netns exec P tsp --realtime -t
-I ip 239.0.0.1:1234
-P continuity
-P bitrate_monitor -p 1 -t 1
-O drop
donde "-p 1 -t 1" significa que necesita calcular la tasa de bits cada segundo y mostrar información sobre la tasa de bits cada segundo
Arrancamos el generador de tráfico con una velocidad de 10Mbps:
tsp -I craft
-P regulate -b 10000000
-O ip -p 7 -e --local-port 6000 239.0.0.1:1234
donde "-p 7 -e" significa que necesita empaquetar 7 paquetes TS en 1 paquete IP y hacerlo duro (-e), es decir siempre espere 7 paquetes TS desde el último procesador antes de enviar un paquete IP.
El analizador comienza a generar los mensajes esperados:
* 2020/01/03 14:55:44 - bitrate_monitor: 2020/01/03 14:55:44, TS bitrate: 9,970,016 bits/s
* 2020/01/03 14:55:45 - bitrate_monitor: 2020/01/03 14:55:45, TS bitrate: 10,022,656 bits/s
* 2020/01/03 14:55:46 - bitrate_monitor: 2020/01/03 14:55:46, TS bitrate: 9,980,544 bits/s
Ahora añade unas gotas:
ip netns exec P iptables -I INPUT -d 239.0.0.1 -m statistic --mode random --probability 0.001 -j DROP
y aparecen mensajes como este:
* 2020/01/03 14:57:11 - continuity: packet index: 80,745, PID: 0x0000, missing 7 packets
* 2020/01/03 14:57:11 - continuity: packet index: 83,342, PID: 0x0000, missing 7 packets
que se espera. Deshabilite la pérdida de paquetes (ip netns exec P iptables -F) e intente aumentar la tasa de bits del generador a 100 Mbps. El analizador informa un montón de errores de CC y alrededor de 75 Mbps en lugar de 100. Estamos tratando de averiguar quién tiene la culpa: el generador no tiene tiempo o el problema no está en él, para esto comenzamos a generar un número fijo de paquetes (700000 paquetes TS = 100000 paquetes IP):
# ifconfig veth0 | grep TX
TX packets 151825460 bytes 205725459268 (191.5 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
# tsp -I craft -c 700000 -P regulate -b 100000000 -P count -O ip -p 7 -e --local-port 6000 239.0.0.1:1234
* count: PID 0 (0x0000): 700,000 packets
# ifconfig veth0 | grep TX
TX packets 151925460 bytes 205861259268 (191.7 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Como puede ver, se generaron exactamente 100000 paquetes IP (151925460-151825460). Entonces, averigüemos qué está sucediendo con el analizador, para esto verificamos con el contador RX en veth1, es estrictamente igual al contador TX en veth0, luego observamos lo que sucede a nivel de socket:
# ip netns exec P cat /proc/net/udp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops
133: 010000EF:04D2 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 72338 2 00000000e0a441df 24355
Aquí puede ver el número de caídas = 24355. En paquetes TS, esto es 170485 o 24.36 % de 700000, por lo que vemos que ese mismo 25 % de la tasa de bits perdida son caídas en el socket udp. Las caídas en un socket UDP generalmente ocurren debido a la falta de búfer, observe el tamaño de búfer de socket predeterminado y el tamaño máximo de búfer de socket:
# sysctl net.core.rmem_default
net.core.rmem_default = 212992
# sysctl net.core.rmem_max
net.core.rmem_max = 212992
Por lo tanto, si las aplicaciones no solicitan explícitamente un tamaño de búfer, los sockets se crean con un búfer de 208 KB, pero si solicitan más, aún no recibirán lo solicitado. Dado que puede establecer el tamaño del búfer en tsp para la entrada de IP (-buffer-size), no tocaremos el tamaño del zócalo predeterminado, sino que solo estableceremos el tamaño máximo del búfer del zócalo y especificaremos el tamaño del búfer explícitamente a través de los argumentos tsp:
sysctl net.core.rmem_max=8388608
ip netns exec P tsp --realtime -t -I ip 239.0.0.1:1234 -b 8388608 -P continuity -P bitrate_monitor -p 1 -t 1 -O drop
Con este ajuste del búfer de socket, ahora la tasa de bits informada es de aproximadamente 100 Mbps, no hay errores de CC.
Según el consumo de CPU de la propia aplicación tsp. En relación con un CPU i5-4260U de un núcleo a 1.40 GHz, el análisis de flujo de 10 Mbps requerirá un 3-4 % de CPU, 100 Mbps - 25 %, 200 Mbps - 46 %. Al configurar el % de pérdida de paquetes, la carga en la CPU prácticamente no aumenta (pero puede disminuir).
En hardware más productivo, fue posible generar y analizar flujos de más de 1 Gb/s sin ningún problema.
Pruebas en tarjetas de red reales
Después de probar en un par veth, debe tomar dos hosts o dos puertos de un host, conectar los puertos entre sí, iniciar el generador en uno y el analizador en el segundo. Aquí no hubo sorpresas, pero de hecho todo depende del hierro, cuanto más débil, más interesante será aquí.
Usando los datos recibidos por el sistema de monitoreo (Zabbix)
tsp no tiene ninguna API legible por máquina como SNMP o similar. Los mensajes CC deben agregarse durante al menos 1 segundo (con un alto porcentaje de pérdida de paquetes, puede haber cientos/miles/decenas de miles por segundo, según la tasa de bits).
Así, para guardar tanto la información como dibujar gráficas de errores de CC y bitrate y cometer algún tipo de accidente, pueden existir las siguientes opciones:
- Analizar y agregar (por CC) la salida de tsp, es decir convertirlo a la forma deseada.
- Finalice el propio tsp y/o los complementos del procesador bitrate_monitor y la continuidad para que el resultado se brinde en una forma legible por máquina adecuada para el sistema de monitoreo.
- Escriba su aplicación encima de la biblioteca tsduck.
Obviamente, la opción 1 es la más fácil en términos de esfuerzo, especialmente considerando que tsduck en sí está escrito en un lenguaje de bajo nivel (según los estándares modernos) (C ++)
Un prototipo simple de analizador bash+agregador mostró que en un flujo de 10 Mbps y una pérdida de paquetes del 50 % (en el peor de los casos), el proceso bash consumía de 3 a 4 veces más CPU que el propio proceso tsp. Este escenario es inaceptable. En realidad, una parte de este prototipo a continuación.
fideos en la parte superior
#!/usr/bin/env bash
missingPackets=0
ccErrorSeconds=0
regexMissPackets='^* (.+) - continuity:.*missing ([0-9]+) packets$'
missingPacketsTime=""
ip netns exec P tsp --realtime -t -I ip -b 8388608 "239.0.0.1:1234" -O drop -P bitrate_monitor -p 1 -t 1 -P continuity 2>&1 |
while read i
do
#line example:* 2019/12/28 23:41:14 - continuity: packet index: 6,078, PID: 0x0100, missing 5 packets
#line example 2: * 2019/12/28 23:55:11 - bitrate_monitor: 2019/12/28 23:55:11, TS bitrate: 4,272,864 bits/s
if [[ "$i" == *continuity:* ]]
then
if [[ "$i" =~ $regexMissPackets ]]
then
missingPacketsTimeNew="${BASH_REMATCH[1]}" #timestamp (seconds)
if [[ "$missingPacketsTime" != "$missingPacketsTimeNew" ]] #new second with CC error
then
((ccErrorSeconds += 1))
fi
missingPacketsTime=$missingPacketsTimeNew
packets=${BASH_REMATCH[2]} #TS missing packets
((missingPackets += packets))
fi
elif [[ "$i" == *bitrate_monitor:* ]]
then
: #...
fi
done
Además de ser inaceptablemente lento, no hay subprocesos normales en bash, los trabajos de bash son procesos separados y tuve que escribir el valor de los paquetes perdidos una vez por segundo en el efecto secundario (al recibir mensajes de tasa de bits que vienen cada segundo). Como resultado, bash se quedó solo y se decidió escribir un contenedor (analizador + agregador) en golang. El consumo de CPU de un código golang similar es 4-5 veces menor que el propio proceso tsp. La aceleración del envoltorio debido a la sustitución de bash por golang resultó ser unas 16 veces y, en general, el resultado es aceptable (sobrecarga de la CPU en un 25 % en el peor de los casos). El archivo fuente de golang se encuentra
Ejecutar contenedor
Para iniciar el contenedor, se creó la plantilla de servicio más simple para systemd (
Para crear una instancia del servicio, debe ejecutar el comando systemctl enable [email protected]:1234 luego ejecutar con systemctl start [email protected]: 1234.
Descubrimiento de Zabbix
Para que zabbix pueda descubrir servicios en ejecución, se hace
Plantilla Zabbix
Breve lista de verificación (bueno, ¿y si alguien decide usarla?)
- Asegúrese de que tsp no deje caer paquetes en condiciones "ideales" (el generador y el analizador están conectados directamente), si hay caídas, consulte el párrafo 2 o el texto del artículo sobre este tema.
- Ajuste el búfer de socket máximo (net.core.rmem_max=8388608).
- Compile tsduck-stat.go (vaya a compilar tsduck-stat.go).
- Coloque la plantilla de servicio en /lib/systemd/system.
- Inicie los servicios con systemctl, verifique que hayan comenzado a aparecer los contadores (grep "" /dev/shm/tsduck-stat/*). El número de servicios por el número de flujos de multidifusión. Aquí es posible que deba crear una ruta al grupo de multidifusión, tal vez deshabilitar rp_filter o crear una ruta a la IP de origen.
- Ejecute discovery.sh, asegúrese de que genere json.
- Agregue la configuración del agente zabbix, reinicie el agente zabbix.
- Cargue la plantilla en zabbix, aplíquela al host que se está monitoreando y el zabbix-agent está instalado, espere unos 5 minutos, vea si hay nuevos elementos, gráficos y disparadores.
resultado
Para la tarea de detectar la pérdida de paquetes, es casi suficiente, al menos es mejor que no monitorear.
De hecho, las "pérdidas" de CC pueden ocurrir al fusionar fragmentos de video (que yo sepa, así es como se hacen las inserciones en los centros de televisión locales en la Federación Rusa, es decir, sin volver a calcular el contador de CC), esto debe recordarse. Las soluciones patentadas evitan parcialmente este problema al detectar etiquetas SCTE-35 (si las agrega el generador de flujo).
En términos de monitoreo de la calidad del transporte, hay una falta de monitoreo de jitter (IAT). Los equipos de TV (ya sean moduladores o dispositivos finales) tienen requisitos para este parámetro y no siempre es posible inflar el jitbuffer hasta el infinito. Y la fluctuación puede flotar cuando se utilizan equipos con grandes búferes en tránsito y la QoS no está configurada o no está lo suficientemente bien configurada para transmitir dicho tráfico en tiempo real.
Fuente: habr.com