Idag finns det fÀrdiga (proprietÀra) lösningar för övervakning av IP(TS)-strömmar, till exempel och , de har en ganska rik uppsÀttning funktioner och sÄdana lösningar finns vanligtvis hos stora operatörer som sysslar med TV-tjÀnster. Denna artikel beskriver en lösning baserad pÄ open source-projektet , utformat för minimal övervakning av IP(TS)-strömmar med hjÀlp av CC (continuity counter) och bitrates. En möjlig tillÀmpning Àr övervakning av paketförlust eller förlust av hela strömmen genom en hyrd L2-kanal (som inte kan övervakas korrekt, exempelvis genom att lÀsa förlustrÀknare i köer).
En kort introduktion till TSDuck
TSDuck Àr en open source-programvara (licens 2-Clause BSD), ett set av kommandoradsverktyg och ett bibliotek för utveckling av egna verktyg eller plugin-program för manipulation av TS-strömmar. Som ingÄng stöder den IP (multicast/unicast), http, hls, dvb-mottagare, dektec dvb-asi demodulator, har en intern TS-strömsgenerator och stöd för att lÀsa frÄn filer. För utgÄng kan den skriva till filer, IP (multicast/unicast), hls, dektec dvb-asi och HiDes modulatorer, spelare (mplayer, vlc, xine) och drop. Mellan ingÄng och utgÄng kan olika trafikprocessorer inkluderas, till exempel PID-mappning, skremblning/descremblering, analys av CC-rÀknare, berÀkning av bitrate och andra typiska operationer för TS-strömmar.
I denna artikel kommer IP-strömmar (multicast) att anvÀndas som ingÄng, med processorerna bitrate_monitor (som namnet antyder vad de gör) och continuity (analys av CC-rÀknare). Utan nÄgra större problem kan IP multicast ersÀttas med en annan typ av ingÄng som stöds av TSDuck.
Det finns TSDuck för de flesta aktuella operativsystem. För Debian finns de inte, men det har varit möjligt att utan problem kompilera för Debian 8 och Debian 10.
Den version av TSDuck som anvÀnds hÀr Àr 3.19-1520, med Linux som operativsystem (Debian 10 anvÀndes för förberedelse av lösningen och CentOS 7 för verklig anvÀndning)
Förberedelse av TSDuck och operativsystem
Innan du övervakar verkliga flöden mĂ„ste du se till att TSDuck fungerar korrekt och att det inte förekommer droppar pĂ„ nivĂ„n av nĂ€tverkskort eller operativsystem (socket). Detta krĂ€vs för att du senare inte ska behöva fundera pĂ„ var droppen intrĂ€ffade â pĂ„ nĂ€tverket eller "inuti servern". Du kan kontrollera droppar pĂ„ nĂ€tverkskortet med kommandot ethtool -S ethX, justering görs med samma ethtool (vanligtvis behöver RX-buffert (-G) ökas och ibland Ă€r det nödvĂ€ndigt att stĂ€nga av vissa offloads (-K)). Som en allmĂ€n rekommendation kan du övervĂ€ga att anvĂ€nda en separat port för att ta emot analyserad trafik, om möjligt, eftersom detta minimerar falska larm relaterade till att dropp intrĂ€ffade specifikt pĂ„ analysatorns port pĂ„ grund av annan trafik. Om en sĂ„dan möjlighet inte finns (om en mini-dator/NUC med en port anvĂ€nds) Ă€r det mycket önskvĂ€rt att konfigurera prioritering av analyserad trafik i förhĂ„llande till annan trafik pĂ„ enheten som analysatorn Ă€r ansluten till. NĂ€r det gĂ€ller virtuella miljöer mĂ„ste du vara försiktig och kunna identifiera paketdroppar som börjar vid den fysiska porten och slutar vid applikationen inuti den virtuella maskinen.
Generering och mottagning av trafik inom vÀrden
Som ett första steg i förberedelserna kommer vi att generera och ta emot trafik inom en och samma vÀrd med hjÀlp av netns.
Förbereder miljön:
ip netns add P #skapar netns P, dÀr trafikanalysen kommer att Àga rum
ip link add type veth #skapar en veth-par - veth0 lÀmnas i netns som standard (trafiken kommer att genereras pÄ detta grÀnssnitt)
ip link set dev veth1 netns P #veth1 - placeras i netns P (trafik kommer att mottas pÄ detta grÀnssnitt)
ip netns exec P ifconfig veth1 192.0.2.1/30 up #aktiverar IP pÄ veth1, det spelar ingen roll vilket
ip netns exec P ip ro add default via 192.0.2.2 #konfigurerar standardrutt inom netns P
sysctl net.ipv6.conf.veth0.disable_ipv6=1 #stÀnger av IPv6 pÄ veth0 - detta görs för att förhindra att skrÀp rÀknas i TX-rÀknaren
ifconfig veth0 up #aktiverar grÀnssnittet veth0
ip route add 239.0.0.1 dev veth0 #skapar en rutt sÄ att OS dirigerar trafik till 239.0.0.1 mot veth0Miljön Àr klar. Startar trafikanalysatorn:
ip netns exec P tsp --realtime -t
-I ip 239.0.0.1:1234
-P continuity
-P bitrate_monitor -p 1 -t 1
-O dropdÀr "-p 1 -t 1" innebÀr att bitrate ska berÀknas varje sekund och att information om bitraten ska visas varje sekund
Startar trafikgeneratorn med en hastighet av 10 Mbit/s:
tsp -I craft
-P regulate -b 10000000
-O ip -p 7 -e --local-port 6000 239.0.0.1:1234dÀr "-p 7 -e" betyder att man ska paketera 7 TS-paket i 1 IP-paket och göra det strÀngt (-e), dvs alltid vÀnta pÄ 7 TS-paket frÄn den senaste processorn innan man skickar IP-paketet.
Analysatorn börjar producera de förvÀntade meddelandena:
* 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/sNu lÀgger vi till lite droppar:
ip netns exec P iptables -I INPUT -d 239.0.0.1 -m statistic --mode random --probability 0.001 -j DROPoch meddelandena av den hÀr typen dyker upp:
* 2020/01/03 14:57:11 - continuity: paketindex: 80,745, PID: 0x0000, saknas 7 paket
* 2020/01/03 14:57:11 - continuity: paketindex: 83,342, PID: 0x0000, saknas 7 paket vilket Ă€r förvĂ€ntat. Vi inaktiverar paketförlust (ip netns exec P iptables -F) och försöker öka bitrate-genereringen till 100Mbit/s. Analysatorn rapporterar massor av CC-fel och cirka 75 Mbit/s istĂ€llet för 100. Vi försöker ta reda pĂ„ vem som Ă€r skyldig â hinner inte generatorn eller Ă€r problemet inte dĂ€r, för att ta reda pĂ„ detta startar vi genereringen av ett fast antal paket (700000 TS-paket = 100000 IP-paket):
# 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 0Som kan ses har exakt 100000 IP-paket genererats (151925460-151825460). LÄt oss undersöka vad som hÀnder med analysatorn, för detta jÀmför vi med RX-rÀknaren pÄ veth1, vilket strikt matchar TX-rÀknaren pÄ veth0, och ser sedan vad som hÀnder pÄ socket-nivÄ:
# 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 HÀr syns antalet droppar = 24355. I TS-paketen Àr det 170485 eller 24.36% av 700000, sÄ vi ser att dessa 25% av den förlorade bitraten Àr droppar i UDP-socketen. Droppar i UDP-socketen uppstÄr vanligtvis pÄ grund av brist pÄ buffert, lÄt oss se vad standardstorleken pÄ socketbufferten och den maximala storleken Àr:
# sysctl net.core.rmem_default
net.core.rmem_default = 212992
# sysctl net.core.rmem_max
net.core.rmem_max = 212992SĂ„ledes, om applikationerna inte uttryckligen begĂ€r storleken pĂ„ bufferten, skapas sockets med en buffert pĂ„ 208 kB, men om de begĂ€r mer kommer de Ă€ndĂ„ inte att fĂ„ det begĂ€rda. Eftersom man i tsp för IP-ingĂ„ng kan ange storleken pĂ„ bufferten (âbuffer-size), kommer vi inte att röra standardstorleken pĂ„ socket, utan bara sĂ€tta den maximala storleken pĂ„ socket buffert och ange buffertstorleken explicit genom tsp-argumenten:
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 dropMed denna buffertjustering rapporterar nu bitraten cirka 100Mbit/s, och inga CC-fel.
CPU-anvĂ€ndning av applikationen tsp. För en i5-4260U CPU @ 1.40GHz kommer analys av en 10 Mbit/s ström att krĂ€va 3-4% CPU, 100 Mbit/s â 25%, 200 Mbit/s â 46%. Vid angivande av % paketförlust ökar belastningen pĂ„ CPU:n praktiskt taget inte (men kan minska).
PÄ mer kraftfull hÄrdvara har vi utan problem kunnat generera och analysera strömmar över 1 Gbit/s.
Testning pÄ verkliga nÀtverkskort
Efter testning pÄ en veth-par behöver man ta tvÄ vÀrdar eller tvÄ portar frÄn en vÀrd, koppla dem ihop, köra generatorn pÄ den ena och analysatorn pÄ den andra. HÀr intrÀffade inga överraskningar, men det beror faktiskt helt pÄ hÄrdvaran; ju svagare, desto intressantare blir det.
AnvÀndning av de erhÄllna uppgifterna av övervakningssystemet (Zabbix)
Tsp har inget maskinlÀsbart API som SNMP eller liknande. CC-meddelanden mÄste aggregeras Ätminstone per sekund (vid hög paketförlust kan det bli hundratals/tusentals/tior av tusentals per sekund beroende pÄ bitrate).
SÄledes, för att spara information och rita diagram av CC-fel och bitrate och göra vissa incidenter kan följande alternativ finnas:
- Parsa och aggregera (per CC) utdata frÄn tsp, det vill sÀga omvandla den till önskad form.
- FörbÀttra sjÀlva tsp och/eller processorplugins bitrate_monitor och continuity sÄ att resultatet ges i maskinlÀsbar form, lÀmplig för övervakningssystem.
- Skriva en egen applikation ovanpÄ biblioteket tsduck.
Det Àr uppenbart att alternativ 1 Àr det enklaste nÀr det gÀller arbetsinsats, sÀrskilt med tanke pÄ att tsduck Àr skrivet i ett lÄgnivÄsprÄk (enligt moderna mÄtt) (C++).
En enkel prototyp av parser + aggregator pÄ bash visade att vid en ström pÄ 10 Mbit/s och 50% paketförlust (det sÀmsta scenariot), konsumerade bash-processen 3-4 gÄnger mer CPU Àn sjÀlva tsp-processen. Denna utvecklingsvÀg Àr oacceptabel. HÀr Àr en del av prototypen nedan.
Nudel pÄ 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
doneFörutom att det fungerar oacceptabelt lÄngsamt, saknar bash normala trÄdar, bash-jobb Àr fristÄende processer och jag var tvungen att registrera vÀrdet av missingPackets en gÄng i sekunden som en bieffekt (vid mottagande av bitrate-meddelanden som kommer varje sekund). Slutresultatet blev att bash lÀmnades ifred och det beslutades att skriva en wrapper (parser + aggregator) i golang. CPU-förbrukningen för motsvarande kod i golang Àr 4-5 gÄnger mindre Àn sjÀlva tsp-processen. Genom att byta ut bash mot golang fick vi en hastighetsökning pÄ cirka 16 gÄnger och i allmÀnhet ett acceptabelt resultat (CPU-överhuvud pÄ 25% i det sÀmsta fallet). KÀllfilen i golang finns .
Köra wrappern
För att köra wrappern har en enklaste service-mall för systemd skapats (). Det förutsÀtts att sjÀlva wrappern har kompilerats till en binÀrfil (go build tsduck-stat.go) och placerats i /opt/tsduck-stat/. Det förutsÀtts att golang med stöd för monotonic clock (>=1.9) anvÀnds.
För att skapa en serviceinstans behöver du köra kommandot systemctl enable tsduck-stat@239.0.0.1:1234, och sedan starta den med systemctl start tsduck-stat@239.0.0.1:1234.
Discovery frÄn Zabbix
För att Zabbix ska kunna göra discovery av körande tjĂ€nster har en (discovery.sh) skapats, i det format som krĂ€vs för Zabbix discovery, det förutsĂ€tts att den Ă€r placerad dĂ€r samma â i /opt/tsduck-stat. För att köra discovery via zabbix-agenten, behöver du lĂ€gga till i katalogen för konfigurationer av zabbix-agenten för att lĂ€gga till en user-parameter.
Zabbix-mall
(tsduck_stat_template.xml) innehÄller en regel för autodiscovery, prototyper av datapunkter, diagram och triggar.
Kort checklista (ifall nÄgon vill anvÀnda den)
- SÀkra att tsp inte tappar paket under "idealiska" förhÄllanden (generatorn och analysatorn Àr direkt anslutna), om det finns tapp, se punkt 2 eller texten i artikeln om detta.
- Gör en justering av den maximala socket-bufferten (net.core.rmem_max=8388608).
- Kompilera tsduck-stat.go (go build tsduck-stat.go).
- LÀgg mallen för tjÀnsten i /lib/systemd/system.
- Starta tjÀnsterna med systemctl, kontrollera att rÀknarna börjar dyka upp (grep "" /dev/shm/tsduck-stat/*). Antalet tjÀnster ska motsvara antalet multicast-strömmar. HÀr kan det krÀvas att skapa en vÀg till multicast-gruppen, eventuellt stÀnga av rp_filter eller skapa en vÀg till kÀll-IP.
- Kör discovery.sh, kontrollera att den genererar json.
- LÀgg till konfigurationen för zabbix-agenten, starta om zabbix-agenten.
- Ladda ner mallen i Zabbix, anvÀnd den pÄ vÀrden dÀr övervakning pÄgÄr och Zabbix-agenten Àr installerad, vÀnta i ungefÀr 5 minuter, och se att nya datakategorier, diagram och utlösare har dykt upp.
Resultat

För att identifiera paketförlust Àr nÀstan tillrÀckligt, men det Àr bÀttre Àn ingen övervakning alls.
I sjÀlva verket kan CC-"förluster" uppstÄ vid klippning av videosekvenser (sÄvitt jag vet, sÄ görs insÀttningarna vid lokala tv-centraler i Ryssland, d.v.s. utan omrÀkning av CC-nummerskalan), detta Àr viktigt att komma ihÄg. I proprietÀra lösningar delvis löses detta genom att detektera SCTE-35-taggar (om de lÀggs till av strömgenereringen).
Ur perspektivet av kvalitet övervakning av transport saknas övervakning av jitter (IAT), eftersom tv-utrustning (oavsett om det Àr modulatorer eller slutliga enheter) har krav pÄ den hÀr parametern och det Àr inte alltid möjligt att blÄsa upp jitbuffer till oÀndligheten. Jitter kan pÄverkas nÀr utrustning med stora buffertar anvÀnds pÄ transit och QoS för överföring av sÄdan realtidsdata inte Àr korrekt instÀllt eller inte tillrÀckligt bra konfigurerat.
KĂ€lla: habr.com
