Uporaba TSDuck za spremljanje tokov IP(TS).

Danes obstajajo že pripravljene (lastniške) rešitve za spremljanje tokov IP(TS), na primer VB и iQ, imajo dokaj bogat nabor funkcij in običajno imajo takšne rešitve veliki operaterji, ki se ukvarjajo s TV storitvami. Ta članek opisuje rešitev, ki temelji na odprtokodnem projektu TSDuck, zasnovan za minimalen nadzor IP(TS) tokov s števcem CC (continuity counter) in bitno hitrostjo. Možna aplikacija je nadzor izgube paketov ali celotnega toka po zakupljenem kanalu L2 (česar ni mogoče normalno spremljati, npr. z branjem števcev izgub v čakalnih vrstah).

Zelo na kratko o TSDucku

TSDuck je odprtokodna (licenca BSD z dvema členoma) programska oprema (nabor pripomočkov za konzolo in knjižnica za razvoj pripomočkov ali vtičnikov po meri) za manipulacijo tokov TS. Kot vhod lahko deluje z IP (multicast/unicast), http, hls, dvb tunerji, dektec dvb-asi demodulator, na voljo je notranji TS stream generator in branje iz datotek. Izhod je lahko snemanje v datoteko, IP (multicast/unicast), hls, modulatorji dektec dvb-asi in HiDes, predvajalniki (mplayer, vlc, xine) in drop. Med vhodom in izhodom lahko omogočite različne prometne procesorje, na primer ponovno preslikavo PID-jev, izvajanje kodiranja/dešifriranja, analiziranje števcev CC, izračun bitne hitrosti in druge operacije, značilne za tokove TS.

V tem članku bodo kot vhod uporabljeni tokovi IP (multicast), uporabljeni so procesorji bitrate_monitor (iz imena je jasno, kaj je) in kontinuiteta (analiza števcev CC). IP multicast lahko enostavno zamenjate z drugo vrsto vnosa, ki jo podpira TSDuck.

Obstajajo uradne zgradbe/paketi TSDuck za najnovejši OS. Za Debian jih ni, smo pa jih brez težav uspeli prevesti za Debian 8 in Debian 10.

Nato je uporabljena različica TSDuck 3.19-1520, kot OS je uporabljen Linux (za pripravo rešitve je bil uporabljen debian 10, za dejansko uporabo pa CentOS 7)

Priprava TSDuck in OS

Pred spremljanjem resničnih tokov se morate prepričati, da TSDuck deluje pravilno in da do padcev ne prihaja na ravni omrežne kartice ali OS (socket). To je potrebno, da vam kasneje ne bo treba ugibati, kje je prišlo do padcev - v omrežju ali "znotraj strežnika". Padce na ravni omrežne kartice lahko preverite z ukazom ethtool -S ethX, nastavitev izvede isti ethtool (ponavadi morate povečati medpomnilnik RX (-G) in včasih onemogočiti nekatere razbremenitve (-K)). Kot splošno priporočilo je priporočljivo, da uporabite ločena vrata za sprejem analiziranega prometa, če je mogoče, bo to zmanjšalo lažne pozitivne rezultate zaradi dejstva, da je do padca prišlo istočasno na vratih analizatorja zaradi prisotnosti drugega prometa. Če to ni mogoče (uporabljate mini računalnik/NUC z enim priključkom), je zelo priporočljivo konfigurirati prioriteto analiziranega prometa glede na preostali na napravi, v katero je priključen analizator. Kar zadeva virtualna okolja, tukaj morate biti previdni in biti sposobni najti padce paketov, začenši s fizičnimi vrati in konča z aplikacijo znotraj virtualnega računalnika.

Generiranje in sprejem toka znotraj gostitelja

Kot prvi korak pri pripravi TSDuck bomo ustvarili in prejeli promet znotraj enega gostitelja z uporabo netns.

Priprava okolja:

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

Okolje je pripravljeno. Zaženite analizator prometa:

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

kjer "-p 1 -t 1" pomeni, da morate vsako sekundo izračunati bitno hitrost in prikazati informacije o bitni hitrosti vsako sekundo
Zaženemo generator prometa s hitrostjo 10 Mbit/s:

tsp -I craft 
 -P regulate -b 10000000 
 -O ip -p 7 -e --local-port 6000 239.0.0.1:1234

kjer "-p 7 -e" pomeni, da morate zapakirati 7 paketov TS v 1 paket IP in to narediti težko (-e), tj. vedno počakajte 7 TS paketov od zadnjega procesorja preden pošljete IP paket.

Analizator začne oddajati pričakovana sporočila:

* 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

Zdaj dodajte nekaj kapljic:

ip netns exec P iptables -I INPUT -d 239.0.0.1 -m statistic --mode random --probability 0.001 -j DROP

in prikažejo se sporočila, kot je to:

* 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 

kar se pričakuje. Onemogočimo izgubo paketov (ip netns exec P iptables -F) in poskusimo povečati bitno hitrost generatorja na 100 Mbit/s. Analizator sporoči kup napak CC in okoli 75 Mbit/s namesto 100. Poskušamo ugotoviti, kdo je kriv - generator ne dohaja ali pa težava ni v njem, za to začnemo generirati fiksno število paketov (700000 TS paketov = 100000 IP paketov):

# 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

Kot lahko vidite, je bilo ustvarjenih točno 100000 paketov IP (151925460-151825460). Torej ugotovimo, kaj se dogaja z analizatorjem, za to preverimo s števcem RX na veth1, ki je strogo enak števcu TX na veth0, nato pa pogledamo, kaj se dogaja na ravni vtičnice:

# 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 

Tukaj lahko vidite število padcev = 24355. V paketih TS je to 170485 ali 24.36 % od 700000, tako da vidimo, da je teh istih 25 % izgubljene bitne hitrosti padcev v vtičnici udp. Do padcev na vtičnici UDP običajno pride zaradi pomanjkanja medpomnilnika, poglejmo, kakšna sta privzeta velikost medpomnilnika vtičnice in največja velikost medpomnilnika vtičnice:

# sysctl net.core.rmem_default
net.core.rmem_default = 212992
# sysctl net.core.rmem_max
net.core.rmem_max = 212992

Če torej aplikacije izrecno ne zahtevajo velikosti medpomnilnika, se vtičnice ustvarijo z medpomnilnikom 208 KB, če pa zahtevajo več, še vedno ne bodo prejele zahtevanega. Ker lahko v tsp nastavite velikost vmesnega pomnilnika za vnos IP (--buffer-size), se ne bomo dotaknili privzete velikosti vtičnice, ampak bomo samo nastavili največjo velikost medpomnilnika vtičnice in izrecno določili velikost vmesnega pomnilnika z argumenti 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 to nastavitvijo vmesnega pomnilnika vtičnic je prijavljena bitna hitrost zdaj približno 100 Mb/s, napak CC ni.

Glede na porabo procesorja same aplikacije tsp. Kar zadeva en jedrni CPE i5-4260U pri 1.40 GHz, bo za analizo pretoka 10 Mbit/s potrebnih 3-4 % CPU, 100 Mbit/s - 25 %, 200 Mbit/s - 46 %. Pri nastavitvi % izgube paketov se obremenitev procesorja praktično ne poveča (lahko pa se zmanjša).

Na bolj produktivni strojni opremi je bilo mogoče brez težav generirati in analizirati tokove s hitrostjo več kot 1Gb/s.

Testiranje na pravih omrežnih karticah

Po testiranju na veth paru morate vzeti dva gostitelja ali dve vrati enega gostitelja, povezati vrata med seboj, zagnati generator na enem in analizator na drugem. Tukaj ni bilo presenečenj, je pa pravzaprav vse odvisno od strojne opreme, šibkejša kot je, bolj zanimivo bo tukaj.

Uporaba prejetih podatkov s sistemom za spremljanje (Zabbix)

tsp nima nobenega strojno berljivega API-ja, kot je SNMP ali podobno. Sporočila CC morajo biti združena vsaj 1 sekundo naenkrat (pri visokem odstotku izgube paketov jih je lahko na stotine/tisoč/desettisoč na sekundo, odvisno od bitne hitrosti).

Tako lahko obstajajo naslednje možnosti, če želite shraniti informacije in risati grafe za napake CC in bitno hitrost ter povzročiti še kakšno nesrečo:

  1. Razčlenite in združite (s CC) izhod tsp, tj. spremenite v želeno obliko.
  2. Dokončajte sam tsp in/ali vtičnike procesorja bitrate_monitor in continuity, tako da je rezultat podan v strojno berljivi obliki, primerni za nadzorni sistem.
  3. Svojo aplikacijo napišite na vrh knjižnice tsduck.

Očitno je z vidika stroškov dela možnost 1 najpreprostejša, zlasti glede na to, da je sam tsduck napisan v nizkem (po sodobnih standardih) jeziku (C++)

Preprost prototip razčlenjevalnika + agregatorja v bashu je pokazal, da je pri pretoku 10 Mbit/s in 50-odstotni izgubi paketov (v najslabšem primeru) proces bash porabil 3-4-krat več CPE kot sam proces tsp. Ta scenarij je nesprejemljiv. Pravzaprav delček tega prototipa spodaj

Rezanci na vrhu

#!/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

Poleg tega, da je nesprejemljivo počasen, v bashu ni običajnih niti, opravila bash so ločeni procesi in sem moral enkrat na sekundo zapisati vrednost missingPackets na stranski učinek (ko prejemam sporočila o bitni hitrosti, ki prihajajo vsako sekundo). Posledično je bash ostal pri miru in bilo je odločeno, da se ovoj (parser + agregator) napiše v golangu. Poraba procesorja podobne kode golang je 4-5-krat manjša od samega procesa tsp. Pospešitev ovoja zaradi zamenjave bash z golangom se je izkazala za približno 16-krat in na splošno je rezultat sprejemljiv (obremenitve procesorja za 25% v najslabšem primeru). Izvorna datoteka golang se nahaja tukaj.

Zagon ovoja

Za zagon ovoja je bila izdelana najpreprostejša servisna predloga za systemd (tukaj). Sam ovoj naj bi bil preveden v binarno datoteko (pojdite zgraditi tsduck-stat.go), ki se nahaja v /opt/tsduck-stat/. Predpostavlja se, da se golang uporablja s podporo za monotono uro (>=1.9).

Če želite ustvariti primerek storitve, morate zagnati ukaz systemctl enable [e-pošta zaščitena]:1234, nato zaženite s systemctl start [e-pošta zaščitena]: 1234.

Odkritje Zabbixa

Da lahko zabbix odkrije delujoče storitve, generator seznama skupin (discovery.sh), v formatu, ki je potreben za odkrivanje Zabbixa, predpostavlja se, da se nahaja na istem mestu - v /opt/tsduck-stat. Če želite zagnati odkrivanje prek zabbix-agenta, morate dodati .conf datoteko v imenik s konfiguracijami agenta zabbix, da dodate uporabniški parameter.

Predloga Zabbix

Ustvarjena predloga (tsduck_stat_template.xml) vsebuje pravilo samodejnega odkrivanja, element, graf in prototipe sprožilcev.

Kratek kontrolni seznam (kaj če se kdo odloči za uporabo)

  1. Prepričajte se, da tsp ne spusti paketov pod "idealnimi" pogoji (generator in analizator sta povezana neposredno), če pride do padcev, glejte 2. odstavek ali besedilo članka o tej zadevi.
  2. Nastavite največji medpomnilnik vtičnic (net.core.rmem_max=8388608).
  3. Prevedite tsduck-stat.go (zgradite tsduck-stat.go).
  4. Storitveno predlogo postavite v /lib/systemd/system.
  5. Zaženite storitve s systemctl, preverite, ali so se začeli prikazovati števci (grep "" /dev/shm/tsduck-stat/*). Število storitev glede na število multicast tokov. Tukaj boste morda morali ustvariti pot do multicast skupine, morda onemogočiti rp_filter ali ustvariti pot do izvornega ip-ja.
  6. Zaženite discovery.sh in se prepričajte, da ustvari json.
  7. Namestite konfiguracijo agenta zabbix, znova zaženite agenta zabbix.
  8. Naložite predlogo v zabbix, jo uporabite za gostitelja, ki ga nadzirate in zabbix-agent je nameščen, počakajte približno 5 minut, poglejte, ali so novi elementi, grafi in sprožilci.

Rezultat

Uporaba TSDuck za spremljanje tokov IP(TS).

Za nalogo prepoznavanja izgube paketov je skoraj dovolj, vsaj bolje kot brez spremljanja.

Pravzaprav lahko pride do "izgub" CC pri spajanju video fragmentov (kolikor vem, se tako vložki izdelujejo v lokalnih televizijskih centrih v Ruski federaciji, tj. brez ponovnega izračuna števca CC), to je treba zapomniti. V lastniških rešitvah se ta težava delno izogne ​​z zaznavanjem oznak SCTE-35 (če jih doda generator toka).

Z vidika spremljanja kakovosti transporta spremljanje tresenja (IAT) ni dovolj, saj TV oprema (modulatorji ali končne naprave) ima zahteve za ta parameter in ni vedno mogoče napihniti jitbufferja do neskončnosti. In tresenje lahko plava, ko se med prenosom uporablja oprema z velikimi medpomnilniki in QoS ni konfiguriran ali ni dovolj dobro konfiguriran za prenos takšnega prometa v realnem času.

Vir: www.habr.com

Dodaj komentar