Dnes už existují hotová (proprietární) řešení například pro monitorování IP(TS) streamů
Velmi stručně o TSDuck
TSDuck je open source (licence 2-Clause BSD) software (sada konzolových utilit a knihovna pro vývoj vlastních utilit nebo pluginů) pro manipulaci s TS streamy. Jako vstup umí pracovat s IP (multicast/unicast), http, hls, dvb tunery, demodulátorem dektec dvb-asi, nechybí interní generátor TS-streamu a čtení ze souborů. Výstupem může být zápis do souboru, IP (multicast/unicast), hls, modulátory dektec dvb-asi a HiDes, přehrávače (mplayer, vlc, xine) a drop. Mezi vstup a výstup mohou být zahrnuty různé provozní procesory, například přemapování PID, kódování / dekódování, analýza čítače CC, výpočet bitové rychlosti a další typické operace pro toky TS.
V tomto článku budou jako vstup použity IP streamy (multicast), procesory bitrate_monitor (z názvu je jasné, co to je) a kontinuita (analýza CC čítačů). IP multicast můžete snadno nahradit jiným typem vstupu podporovaným TSDuck.
Tam jsou
Dále je použita verze TSDuck 3.19-1520, jako OS Linux (pro přípravu řešení byl použit debian 10, pro reálné použití CentOS 7)
Příprava TSDuck a OS
Před sledováním skutečných toků se musíte ujistit, že TSDuck funguje správně a nedochází k žádným poklesům na úrovni síťové karty nebo OS (socket). To je nutné, aby se později nehádalo, kde došlo k poklesu - v síti nebo „uvnitř serveru“. Poklesy na úrovni síťové karty můžete zkontrolovat pomocí příkazu ethtool -S ethX, ladění se provádí stejným nástrojem ethtool (obvykle je třeba zvýšit vyrovnávací paměť RX (-G) a někdy zakázat některá snížení zátěže (-K)). Jako obecné doporučení lze doporučit použití samostatného portu pro příjem analyzovaného provozu, pokud je to možné, minimalizuje se tím falešná pozitivita spojená se skutečností, že k poklesu došlo právě na portu analyzátoru kvůli přítomnosti jiného provozu. Pokud to není možné (používá se minipočítač/NUC s jedním portem), je velmi žádoucí nastavit prioritu analyzovaného provozu ve vztahu ke zbytku na zařízení, ke kterému je analyzátor připojen. Pokud jde o virtuální prostředí, zde musíte být opatrní a být schopni najít dropety počínaje fyzickým portem a konče aplikací uvnitř virtuálního stroje.
Generování a příjem streamu uvnitř hostitele
Jako první krok v přípravě TSDuck budeme generovat a přijímat provoz v rámci jednoho hostitele pomocí netns.
Příprava prostředí:
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
Prostředí je připraveno. Spustíme analyzátor provozu:
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
kde "-p 1 -t 1" znamená, že musíte vypočítat bitrate každou sekundu a každou sekundu zobrazit informace o bitrate
Spustíme generátor provozu s rychlostí 10 Mbps:
tsp -I craft
-P regulate -b 10000000
-O ip -p 7 -e --local-port 6000 239.0.0.1:1234
kde "-p 7 -e" znamená, že je potřeba zabalit 7 TS paketů do 1 IP paketu a udělat to natvrdo (-e), tzn. před odesláním IP paketu vždy počkejte 7 TS paketů od posledního procesoru.
Analyzátor začne vydávat očekávané zprávy:
* 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
Nyní přidejte pár kapek:
ip netns exec P iptables -I INPUT -d 239.0.0.1 -m statistic --mode random --probability 0.001 -j DROP
a objeví se tyto zprávy:
* 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
což se očekává. Zakažte ztrátu paketů (ip netns exec P iptables -F) a zkuste zvýšit bitovou rychlost generátoru na 100 Mbps. Analyzátor hlásí spoustu chyb CC a asi 75 Mbps místo 100. Snažíme se přijít na to, kdo za to může - generátor nemá čas nebo problém není v něm, proto začneme generovat pevný počet pakety (700000 100000 paketů TS = XNUMX XNUMX paketů 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
Jak vidíte, bylo vygenerováno přesně 100000 151925460 IP paketů (151825460-1). Pojďme tedy zjistit, co se děje s analyzátorem, zkontrolujeme to pomocí počítadla RX na veth0, je to přesně stejné jako počítadlo TX na vethXNUMX, pak se podíváme na to, co se stane na úrovni zásuvky:
# 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
Zde vidíte počet poklesů = 24355. V TS paketech je to 170485 nebo 24.36 % ze 700000 25, takže vidíme, že stejných XNUMX % ztraceného bitrate jsou poklesy v udp socketu. K výpadkům v soketu UDP obvykle dochází kvůli nedostatku vyrovnávací paměti, podívejte se na výchozí velikost vyrovnávací paměti soketu a maximální velikost vyrovnávací paměti soketu:
# sysctl net.core.rmem_default
net.core.rmem_default = 212992
# sysctl net.core.rmem_max
net.core.rmem_max = 212992
Pokud tedy aplikace explicitně nepožadují velikost vyrovnávací paměti, jsou vytvořeny sokety s vyrovnávací pamětí 208 kB, ale pokud požadují více, stále nedostanou to, co bylo požadováno. Protože můžete nastavit velikost vyrovnávací paměti v tsp pro vstup IP (-buffer-size), nedotkneme se výchozí velikosti soketu, ale pouze nastavíme maximální velikost vyrovnávací paměti soketu a explicitně určíme velikost vyrovnávací paměti pomocí argumentů 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
S tímto vyladěním soketové vyrovnávací paměti je nyní hlášená přenosová rychlost asi 100 Mbps, nejsou žádné chyby CC.
Podle spotřeby CPU samotné aplikace tsp. V porovnání s jedním jádrem i5-4260U CPU @ 1.40 GHz bude analýza toku 10 Mb/s vyžadovat 3–4 % CPU, 100 Mb/s – 25 %, 200 Mb/s – 46 %. Při nastavení % Packet Loss se zátěž CPU prakticky nezvyšuje (ale může klesat).
Na produktivnějším hardwaru bylo možné bez problémů generovat a analyzovat streamy nad 1Gb/s.
Testování na skutečných síťových kartách
Po testování na páru veth musíte vzít dva hostitele nebo dva porty jednoho hostitele, propojit porty navzájem, spustit generátor na jednom a analyzátor na druhém. Tady se žádné překvapení nekonalo, ale vlastně všechno záleží na železe, čím slabší, tím to tady bude zajímavější.
Použití přijatých dat monitorovacím systémem (Zabbix)
tsp nemá žádné strojově čitelné API, jako je SNMP nebo podobné. Zprávy CC musí být agregovány po dobu alespoň 1 sekundy (při vysokém procentu ztráty paketů to mohou být stovky/tisíce/desetitisíce za sekundu, v závislosti na bitrate).
Aby bylo možné uložit jak informace, tak vykreslit grafy pro chyby CC a datový tok a způsobit nějaké nehody, mohou existovat následující možnosti:
- Analyzujte a agregujte (pomocí CC) výstup tsp, tj. převést do požadované podoby.
- Dokončete samotný tsp a/nebo moduly procesoru bitrate_monitor a kontinuitu tak, aby byl výsledek uveden ve strojově čitelné podobě vhodné pro monitorovací systém.
- Napište svou aplikaci nad knihovnu tsduck.
Je zřejmé, že možnost 1 je z hlediska úsilí nejjednodušší, zvláště vezmeme-li v úvahu, že samotný tsduck je napsán v jazyce nízké úrovně (podle moderních standardů) (C ++)
Jednoduchý prototyp bash analyzátoru + agregátoru ukázal, že při 10Mbps streamu a 50% ztrátě paketů (nejhorší případ) bash proces spotřeboval 3-4krát více CPU než samotný tsp proces. Tento scénář je nepřijatelný. Vlastně kousek tohoto prototypu níže
Nahoře nudle
#!/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
Kromě toho, že je to nepřijatelně pomalé, v bash nejsou žádná normální vlákna, bash joby jsou samostatné procesy a hodnotu missingPackets jsem musel napsat jednou za sekundu na vedlejší efekt (při příjmu zpráv s bitratem, které přicházejí každou sekundu). Výsledkem bylo, že bash zůstal sám a bylo rozhodnuto napsat obal (parser + agregátor) v golangu. Spotřeba CPU podobného golang kódu je 4-5krát menší než samotný proces tsp. Zrychlení wrapperu díky nahrazení bashe golangem dopadlo asi 16x a celkově je výsledek přijatelný (režie CPU o 25% v nejhorším případě). Zdrojový soubor golang je umístěn
Spustit obal
Pro spuštění wrapperu byla vytvořena nejjednodušší šablona služby pro systemd (
Chcete-li vytvořit instanci služby, musíte spustit příkaz systemctl enable [chráněno e-mailem]:1234 pak spusťte se startem systemctl [chráněno e-mailem]: 1234.
Objev ze Zabbix
Aby zabbix mohl objevit běžící služby, je hotovo
Šablona Zabbix
Stručný kontrolní seznam (no, co když se ho někdo rozhodne použít)
- Ujistěte se, že tsp nezahazuje pakety za "ideálních" podmínek (generátor a analyzátor jsou připojeny přímo), pokud k poklesu dochází, viz odstavec 2 nebo text článku na toto téma.
- Proveďte ladění maximální vyrovnávací paměti soketu (net.core.rmem_max=8388608).
- Zkompilujte tsduck-stat.go (přejděte na sestavení tsduck-stat.go).
- Vložte šablonu služby do /lib/systemd/system.
- Spusťte služby pomocí systemctl, zkontrolujte, zda se začaly objevovat čítače (grep "" /dev/shm/tsduck-stat/*). Počet služeb podle počtu toků multicast. Zde možná budete muset vytvořit cestu ke skupině multicast, možná zakázat rp_filter nebo vytvořit cestu ke zdrojové ip.
- Spusťte discovery.sh a ujistěte se, že generuje json.
- Přidejte konfiguraci agenta zabbix, restartujte agenta zabbix.
- Nahrajte šablonu na zabbix, aplikujte ji na hostitele, který je monitorován a zabbix-agent je nainstalován, počkejte asi 5 minut a podívejte se, zda jsou nové položky, grafy a spouštěče.
Výsledek
Pro úlohu detekce ztráty paketů to téměř stačí, alespoň je to lepší než žádný monitoring.
Při slučování fragmentů videa skutečně může dojít ke „ztrátám“ CC (pokud vím, takto se vkládání provádí v místních televizních centrech v Ruské federaci, tj. bez přepočítávání počítadla CC), na to je třeba pamatovat. Patentovaná řešení tento problém částečně obcházejí detekcí značek SCTE-35 (pokud jsou přidány generátorem proudu).
Z hlediska sledování kvality přepravy chybí sledování jitteru (IAT). Televizní zařízení (ať už se jedná o modulátory nebo koncová zařízení) má na tento parametr požadavky a ne vždy je možné jitbuffer nafouknout do nekonečna. A jitter může plavat, když se při přenosu používá zařízení s velkými vyrovnávací paměti a QoS není nakonfigurováno nebo není dostatečně dobře nakonfigurováno pro přenos takového provozu v reálném čase.
Zdroj: www.habr.com