Ă ce jour, il existe des solutions prĂȘtes Ă l'emploi (propriĂ©taires) pour le suivi des flux IP(TS), par exemple et , elles offrent un ensemble de fonctionnalitĂ©s assez riche et de telles solutions sont gĂ©nĂ©ralement disponibles chez les grands opĂ©rateurs Ćuvrant dans les services de tĂ©lĂ©vision. Cet article dĂ©crit une solution basĂ©e sur le projet open source , destinĂ© Ă un contrĂŽle minimal des flux IP(TS) via le compteur de continuitĂ© (CC) et le dĂ©bit binaire. Une application possible serait le contrĂŽle de la perte de paquets ou de flux entier via un canal L2 louĂ© (qui ne peut pas ĂȘtre surveillĂ© normalement, par exemple en lisant les compteurs de perte dans les files d'attente).
Ă propos de TSDuck
TSDuck est un logiciel open source (licence 2-Clause BSD) qui consiste en un ensemble d'outils en ligne de commande et une bibliothĂšque pour dĂ©velopper ses propres utilitaires ou plugins, permettant de manipuler les flux TS. Il peut traiter des entrĂ©es IP (multicast/unicast), http, hls, tuners DVB, dĂ©modulateurs dektec dvb-asi, comprend un gĂ©nĂ©rateur interne de flux TS et la lecture Ă partir de fichiers. En sortie, il peut Ă©crire dans un fichier, sur IP (multicast/unicast), hls, dĂ©modulateurs dektec dvb-asi et HiDes, ainsi que des lecteurs (mplayer, vlc, xine) et drop. Entre l'entrĂ©e et la sortie, divers processeurs de trafic peuvent ĂȘtre insĂ©rĂ©s, par exemple, le remappage des PID, le scrambling/dĂ©scrambling, l'analyse des compteurs CC, le comptage des dĂ©bits binaires et d'autres opĂ©rations typiques pour les flux TS.
Dans cet article, les flux IP (multicast) seront utilisés en entrée, avec les processeurs bitrate_monitor (comme l'indique le nom) et continuity (analyse des compteurs CC). Il est possible de remplacer facilement l'IP multicast par un autre type d'entrée pris en charge par TSDuck.
Il existe officiels de TSDuck pour la plupart des systĂšmes d'exploitation actuels. Pour Debian, il n'en existe pas, mais nous avons pu le compiler sans problĂšme sous debian 8 et debian 10.
Nous utiliserons la version TSDuck 3.19-1520, avec Linux comme systĂšme d'exploitation (pour la prĂ©paration de la solution, debian 10 a Ă©tĂ© utilisĂ©, et pour l'utilisation rĂ©elle â CentOS 7).
Préparation de TSDuck et du systÚme d'exploitation
Avant de surveiller les flux rĂ©els, il est nĂ©cessaire de s'assurer que TSDuck fonctionne correctement et qu'il n'y a pas de pertes au niveau de la carte rĂ©seau ou du systĂšme d'exploitation (socket). Cela est requis afin d'Ă©viter de se poser des questions sur l'origine des pertes â Ă©taient-elles dues au rĂ©seau ou « Ă l'intĂ©rieur du serveur ». On peut vĂ©rifier les pertes au niveau de la carte rĂ©seau avec la commande ethtool -S ethX, le rĂ©glage se fait avec le mĂȘme ethtool (en gĂ©nĂ©ral, il faut augmenter le buffer RX (-G) et parfois dĂ©sactiver certains offloads (-K)). En rĂšgle gĂ©nĂ©rale, il est conseillĂ© d'utiliser un port sĂ©parĂ© pour recevoir le trafic analysĂ©, si cela est possible, cela minimise les fausses alertes liĂ©es au fait que la perte s'est produite prĂ©cisĂ©ment sur le port de l'analyseur en raison de la prĂ©sence d'un autre trafic. Si cette possibilitĂ© n'existe pas (si un mini-ordinateur/NUC avec un seul port est utilisĂ©), il est trĂšs souhaitable de configurer une priorisation du trafic analysĂ© par rapport au reste sur le dispositif auquel l'analyseur est connectĂ©. En ce qui concerne les environnements virtuels, il faut ĂȘtre prudent et savoir dĂ©tecter les pertes de paquets depuis le port physique jusqu'Ă l'application Ă l'intĂ©rieur de la machine virtuelle.
Génération et réception de flux à l'intérieur de l'hÎte
Comme premiĂšre Ă©tape de prĂ©paration de TSDuck, nous allons gĂ©nĂ©rer et recevoir du trafic Ă l'intĂ©rieur d'un mĂȘme hĂŽte en utilisant netns.
Préparation de l'environnement :
ip netns add P #crĂ©ation de netns P, oĂč l'analyse de trafic aura lieu
ip link add type veth #création d'une paire veth - veth0 reste dans le netns par défaut (le trafic sera généré sur cette interface)
ip link set dev veth1 netns P #veth1 - placement dans netns P (le trafic sera reçu sur cette interface)
ip netns exec P ifconfig veth1 192.0.2.1/30 up #activation de l'IP sur veth1, peu importe laquelle
ip netns exec P ip ro add default via 192.0.2.2 #configuration de la route par défaut à l'intérieur de netns P
sysctl net.ipv6.conf.veth0.disable_ipv6=1 #désactivation de l'IPv6 sur veth0 - ceci est fait pour éviter que des déchets externes ne tombent dans le compteur TX
ifconfig veth0 up #activation de l'interface veth0
ip route add 239.0.0.1 dev veth0 #crĂ©ation d'une route pour que le systĂšme d'exploitation dirige le trafic vers 239.0.0.1 via veth0L'environnement est prĂȘt. Lançons l'analyseur de trafic :
ip netns exec P tsp --realtime -t
-I ip 239.0.0.1:1234
-P continuity
-P bitrate_monitor -p 1 -t 1
-O dropoĂč « -p 1 -t 1 » signifie qu'il faut calculer le bitrate chaque seconde et afficher les informations sur le bitrate chaque seconde
Lançons le générateur de trafic à une vitesse de 10 Mbit/s :
tsp -I craft
-P regulate -b 10000000
-O ip -p 7 -e --local-port 6000 239.0.0.1:1234oĂč «-p 7 -e» signifie que nous devons emballer 7 paquets TS dans 1 paquet IP et le faire de maniĂšre stricte (-e), c'est-Ă -dire toujours attendre 7 paquets TS du dernier processeur avant d'envoyer la formation du paquet IP.
L'analyseur commence Ă afficher les messages attendus :
* 2020/01/03 14:55:44 - bitrate_monitor : 2020/01/03 14:55:44, débit TS : 9 970 016 bits/s
* 2020/01/03 14:55:45 - bitrate_monitor : 2020/01/03 14:55:45, débit TS : 10 022 656 bits/s
* 2020/01/03 14:55:46 - bitrate_monitor : 2020/01/03 14:55:46, débit TS : 9 980 544 bits/sNous ajoutons maintenant un peu de pertes :
ip netns exec P iptables -I INPUT -d 239.0.0.1 -m statistic --mode random --probability 0.001 -j DROPet apparaissent des messages de ce type :
* 2020/01/03 14:57:11 - continuity : index du paquet : 80,745, PID : 0x0000, 7 paquets manquants
* 2020/01/03 14:57:11 - continuity : index du paquet : 83,342, PID : 0x0000, 7 paquets manquants ce qui est attendu. Nous dĂ©sactivons la perte de paquets (ip netns exec P iptables -F) et essayons d'augmenter le dĂ©bit du gĂ©nĂ©rateur Ă 100 Mbit/s. L'analyseur rapporte de nombreuses erreurs CC et environ 75 Mbit/s au lieu de 100. Nous essayons de comprendre qui est en faute â le gĂ©nĂ©rateur ne suit pas ou le problĂšme vient d'ailleurs, pour cela nous lançons la gĂ©nĂ©ration d'un nombre fixe de paquets (700000 paquets TS = 100000 paquets 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 0Comme on peut le voir, exactement 100000 paquets IP ont été générés (151925460-151825460). Nous examinons donc ce qui se passe avec l'analyseur, en vérifiant le compteur RX sur veth1, il est strictement égal au compteur TX sur veth0, puis nous regardons ce qui se passe au niveau du 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 Ici, on voit le nombre de pertes = 24355. En paquets TS, cela représente 170485 ou 24,36 % des 700000, nous voyons donc que ces 25 % de perte de débit proviennent des pertes dans le socket UDP. Les pertes dans le socket UDP surviennent généralement en raison d'un manque de mémoire tampon, voyons quelle est la taille de la mémoire tampon du socket par défaut et la taille de mémoire tampon maximale du socket :
# sysctl net.core.rmem_default
net.core.rmem_default = 212992
# sysctl net.core.rmem_max
net.core.rmem_max = 212992Ainsi, si les applications ne demandent pas explicitement la taille de la mĂ©moire tampon, les sockets sont créés avec une mĂ©moire tampon de 208 Ko, mais si elles demandent plus, elles ne l'obtiennent pas. Puisque dans tsp pour l'entrĂ©e IP, nous pouvons dĂ©finir la taille de la mĂ©moire tampon (âbuffer-size), nous ne toucherons pas la taille de la mĂ©moire tampon par dĂ©faut du socket, mais dĂ©finirons uniquement la taille de mĂ©moire tampon maximale du socket et spĂ©cifierons la taille de la mĂ©moire tampon explicitement via les arguments 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 dropAvec ce réglage de la mémoire tampon du socket, le débit rapporté est maintenant d'environ 100 Mbit/s, sans erreurs CC.
En ce qui concerne la consommation de CPU par l'application tsp, pour un cĆur i5-4260U CPU @ 1.40GHz, l'analyse d'un flux de 10 Mbit/s nĂ©cessitera 3-4 % de CPU, 100 Mbit/s â 25 %, 200 Mbit/s â 46 %. Avec un certain pourcentage de perte de paquets, la charge du CPU n'augmente pratiquement pas (mais peut diminuer).
Sur du matériel plus performant, il était possible de générer et d'analyser sans problÚme des flux de plus de 1 Gb/s.
Test sur des cartes réseau réelles
AprĂšs les tests sur une paire veth, il faut prendre deux hĂŽtes ou deux ports d'un mĂȘme hĂŽte, relier les ports entre eux, exĂ©cuter le gĂ©nĂ©rateur sur l'un et l'analyseur sur l'autre. Aucune surprise ne s'est produite ici, mais en rĂ©alitĂ©, tout dĂ©pend du matĂ©riel ; plus il est faible, plus la situation devient intĂ©ressante.
Utilisation des données obtenues par le systÚme de surveillance (Zabbix)
Le tsp n'a pas de API machine-readable comme SNMP ou similaire. Les messages CC doivent ĂȘtre agrĂ©gĂ©s au moins par seconde (avec un taux Ă©levĂ© de perte de paquets, il peut y avoir des centaines, des milliers, voire des dizaines de milliers par seconde, selon le dĂ©bit).
Ainsi, pour conserver les informations et dessiner des graphiques sur les erreurs CC et le dĂ©bit, les options suivantes peuvent ĂȘtre envisagĂ©es :
- Parser et agréger (par CC) la sortie de tsp, c'est-à -dire la transformer au format requis.
- Améliorer le logiciel tsp et/ou les plugins processeurs bitrate_monitor et continuity, afin que le résultat soit fourni sous une forme machine-readable, adaptée pour le systÚme de surveillance.
- Ăcrire votre propre application au-dessus de la bibliothĂšque tsduck.
Il est Ă©vident que du point de vue des efforts nĂ©cessaires, l'option 1 est la plus simple, surtout compte tenu du fait que le tsduck lui-mĂȘme est Ă©crit dans un langage bas niveau (selon les normes modernes) (C++).
Un prototype simple de parseur+agrĂ©gateur en bash a montrĂ© qu'avec un flux de 10 Mbit/s et 50 % de perte de paquets (le pire des scĂ©narios), le processus bash consommait 3-4 fois plus de CPU que le processus tsp lui-mĂȘme. Ce type de scĂ©nario n'est pas acceptable. Voici d'ailleurs une partie de ce prototype ci-dessous.
PĂątes Ă la sauce bash.
#!/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
doneEn plus de fonctionner de maniÚre inadmissiblement lente, bash n'a pas de véritables threads, les jobs bash étant des processus autonomes, il a fallu enregistrer une fois par seconde la valeur missingPackets sur l'effet secondaire (lors de la réception des messages de débit, qui arrivent chaque seconde). Au final, bash a été laissé de cÎté et il a été décidé d'écrire une couche (parser + agrégateur) en golang. La consommation CPU d'un code équivalent en golang est de 4 à 5 fois inférieure à celle du processus tsp. L'accélération de la couche grùce à la substitution de bash par golang a obtenu un gain d'environ 16 fois et dans l'ensemble, le résultat est acceptable (surcharge CPU de 25% dans le pire des cas). Le fichier source en golang se trouve .
Lancement de la couche
Pour lancer la couche, un modĂšle de service trĂšs simple pour systemd a Ă©tĂ© créé (). Il est prĂ©vu que la couche elle-mĂȘme soit compilĂ©e en un fichier binaire (go build tsduck-stat.go), placĂ© dans /opt/tsduck-stat/. Il est supposĂ© que golang avec support de l'horloge monotone (>=1.9) est utilisĂ©.
Pour créer une instance de service, il faut exécuter la commande systemctl enable tsduck-stat@239.0.0.1:1234, puis la démarrer avec systemctl start tsduck-stat@239.0.0.1:1234.
Découverte depuis Zabbix
Afin que Zabbix puisse effectuer la dĂ©couverte des services en cours d'exĂ©cution, un (discovery.sh) a Ă©tĂ© créé, dans le format requis pour la dĂ©couverte Zabbix, il est prĂ©sumĂ© qu'il est placĂ© lĂ aussi â dans /opt/tsduck-stat. Pour exĂ©cuter la dĂ©couverte via zabbix-agent, il faut ajouter dans le rĂ©pertoire des configurations de zabbix-agent pour ajouter un paramĂštre utilisateur.
ModĂšle Zabbix
(tsduck_stat_template.xml) contient une rÚgle d'auto-découverte, des prototypes d'éléments de données, de graphiques et de déclencheurs.
Liste de contrĂŽle rapide (au cas oĂč quelqu'un dĂ©ciderait de l'utiliser)
- S'assurer que tsp ne perd pas de paquets dans des conditions « idéales » (le générateur et l'analyseur étant connectés directement), s'il y a des pertes, voir p.2 ou le texte de l'article à ce sujet.
- Faire un réglage du tampon maximal du socket (net.core.rmem_max=8388608).
- Compiler tsduck-stat.go (go build tsduck-stat.go).
- Placer le modĂšle de service dans /lib/systemd/system.
- Lancer les services avec systemctl, vĂ©rifier qu'ils commencent Ă apparaĂźtre dans les compteurs (grep « » /dev/shm/tsduck-stat/*). Le nombre de services est Ă©gal au nombre de flux multicast. Il peut ĂȘtre nĂ©cessaire de crĂ©er une route vers le groupe multicast, Ă©ventuellement de dĂ©sactiver rp_filter ou de crĂ©er une route vers l'ip source.
- Lancer discovery.sh, s'assurer qu'il génÚre du json.
- Fournir la configuration de zabbix-agent, redémarrer zabbix-agent.
- TĂ©lĂ©chargez le modĂšle dans Zabbix, appliquez-le Ă l'hĂŽte sur lequel la surveillance est effectuĂ©e et oĂč l'agent Zabbix est installĂ©, attendez environ 5 minutes, puis vĂ©rifiez que de nouveaux Ă©lĂ©ments de donnĂ©es, graphiques et dĂ©clencheurs sont apparus.
Résultat

Pour la tùche de détection de perte de paquets, cela est presque suffisant, et c'est mieux que de ne pas avoir de surveillance.
En réalité, les CC de « pertes » peuvent se produire lors du montage de fragments vidéo (autant que je sache, c'est ainsi que les insertions sont réalisées dans les centres de télévision locaux en Russie, c'est-à -dire sans recalculer le compteur CC), il faut en tenir compte. Dans les solutions propriétaires, ce problÚme est partiellement contourné par la détection des étiquettes SCTE-35 (si elles sont ajoutées par le générateur de flux).
Du point de vue de la surveillance de la qualité du transport, il manque une surveillance du jitter (IAT), car l'équipement TV (qu'il s'agisse de modulateurs ou de dispositifs finaux) a des exigences pour ce paramÚtre et il n'est pas toujours possible de gonfler le jitbuffer indéfiniment. De plus, le jitter peut varier lorsque du matériel avec de grands buffers est utilisé en transit et que le QoS pour le transfert de ce type de trafic en temps réel n'est pas configuré ou pas suffisamment bien configuré.
Source : habr.com
