Korištenje TSDucka za nadzor IP(TS) tokova

Danas postoje gotova (vlastita) rješenja za praćenje IP(TS) tokova, npr. VB и iQ, imaju prilično bogat skup funkcija i obično veliki operateri koji se bave TV uslugama imaju takva rješenja. Ovaj članak opisuje rješenje temeljeno na projektu otvorenog koda TSDak, dizajniran za minimalnu kontrolu IP(TS) tokova pomoću CC (brojača kontinuiteta) brojača i brzine prijenosa. Moguća primjena je kontrola gubitka paketa ili cijelog protoka kroz iznajmljeni L2 kanal (što se ne može normalno pratiti, npr. čitanjem brojača gubitaka u redovima).

Vrlo kratko o TSDucku

TSDuck je softver otvorenog koda (2-klauzula BSD licence) (skup konzolnih uslužnih programa i biblioteka za razvoj prilagođenih uslužnih programa ili dodataka) za manipuliranje TS streamovima. Kao ulaz može raditi s IP (multicast/unicast), http, hls, dvb tunerima, dektec dvb-asi demodulatorom, postoji interni TS-stream generator i čitanje iz datoteka. Izlaz može biti pisanje u datoteku, IP (multicast/unicast), hls, dektec dvb-asi i HiDes modulatori, playeri (mplayer, vlc, xine) i drop. Između ulaza i izlaza mogu se uključiti različiti procesori prometa, na primjer, remapiranje PID-a, kodiranje/dekodiranje, analiza CC brojača, izračun brzine prijenosa i druge tipične operacije za TS tokove.

U ovom članku će se kao ulaz koristiti IP streamovi (multicast), korišteni su procesori bitrate_monitor (iz naziva je jasno o čemu se radi) i kontinuitet (analiza CC brojača). IP multicast možete jednostavno zamijeniti drugom vrstom unosa koju podržava TSDuck.

Postoje službene verzije/paketi TSDuck za većinu aktualnih operativnih sustava. Nisu dostupni za Debian, ali uspjeli smo ih izgraditi pod debian 8 i debian 10 bez ikakvih problema.

Zatim se koristi verzija TSDuck 3.19-1520, kao OS se koristi Linux (za pripremu rješenja korišten je debian 10, za stvarnu upotrebu CentOS 7)

Priprema TSDuck i OS

Prije praćenja stvarnih protoka, morate se uvjeriti da TSDuck radi ispravno i da nema padova na razini mrežne kartice ili OS-a (socket). Ovo je potrebno kako se kasnije ne bi nagađalo gdje su se padovi dogodili - na mreži ili "unutar poslužitelja". Možete provjeriti padove na razini mrežne kartice pomoću naredbe ethtool -S ethX, podešavanje se vrši istim ethtool-om (obično trebate povećati RX međuspremnik (-G) i ponekad onemogućiti neka opterećenja (-K)). Kao opću preporuku, može se savjetovati korištenje zasebnog priključka za primanje analiziranog prometa, ako je moguće, ovo minimizira lažne pozitivne rezultate povezane s činjenicom da se pad dogodio točno na priključku analizatora zbog prisutnosti drugog prometa. Ukoliko to nije moguće (koristi se mini-računalo/NUC s jednim portom), tada je vrlo poželjno postaviti prioritet analiziranog prometa u odnosu na ostatak na uređaju na koji je analizator spojen. Što se tiče virtualnih okruženja, ovdje morate biti oprezni i moći pronaći ispuštanje paketa počevši od fizičkog priključka do aplikacije unutar virtualnog stroja.

Generiranje i prijem toka unutar hosta

Kao prvi korak u pripremi TSDucka, mi ćemo generirati i primati promet unutar jednog hosta koristeći netns.

Priprema okoline:

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

Okolina je spremna. Pokrećemo 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

gdje "-p 1 -t 1" znači da trebate izračunati brzinu prijenosa svake sekunde i prikazati informacije o brzini prijenosa svake sekunde
Pokrećemo generator prometa brzinom od 10Mbps:

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

gdje "-p 7 -e" znači da morate spakirati 7 TS paketa u 1 IP paket i to učiniti teško (-e), tj. uvijek pričekajte 7 TS paketa od zadnjeg procesora prije slanja IP paketa.

Analizator počinje ispisivati ​​očekivane poruke:

* 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

Sada dodajte nekoliko kapi:

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

i pojavljuju se poruke poput ove:

* 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 

što se očekuje. Onemogućite gubitak paketa (ip netns exec P iptables -F) i pokušajte povećati bitrate generatora na 100 Mbps. Analizator javlja hrpu CC grešaka i oko 75 Mbps umjesto 100. Pokušavamo otkriti tko je kriv - generator nema vremena ili problem nije u njemu, za ovo počinjemo generirati fiksni broj paketi (700000 TS paketa = 100000 IP paketa):

# 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

Kao što vidite, generirano je točno 100000 IP paketa (151925460-151825460). Dakle, shvatimo što se događa s analizatorom, za ovo provjeravamo s RX brojačem na veth1, on je strogo jednak TX brojaču na veth0, zatim gledamo što se događa na razini utič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 

Ovdje možete vidjeti broj dropova = 24355. U TS paketima to je 170485 ili 24.36% od 700000, tako da vidimo da su tih istih 25% izgubljenog bitratea dropovi u udp socketu. Do pada u UDP utičnici obično dolazi zbog nedostatka međuspremnika, pogledajte zadanu veličinu međuspremnika utičnice i maksimalnu veličinu međuspremnika utičnice:

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

Stoga, ako aplikacije izričito ne zahtijevaju veličinu međuspremnika, utičnice se stvaraju s međuspremnikom od 208 KB, ali ako zatraže više, još uvijek neće dobiti traženo. Budući da možete postaviti veličinu međuspremnika u tsp za IP ulaz (-buffer-size), nećemo dirati zadanu veličinu utičnice, već samo postaviti maksimalnu veličinu međuspremnika i odrediti veličinu međuspremnika eksplicitno kroz tsp argumente:

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 ovim podešavanjem međuspremnika utičnice, sada je prijavljena brzina prijenosa oko 100 Mbps, nema CC pogrešaka.

Prema CPU potrošnji same tsp aplikacije. U odnosu na jedan jezgreni i5-4260U CPU na 1.40 GHz, analiza protoka od 10 Mbps zahtijevat će 3-4% CPU-a, 100 Mbps - 25%, 200 Mbps - 46%. Prilikom postavljanja % gubitka paketa, opterećenje CPU-a praktički se ne povećava (ali se može smanjiti).

Na produktivnijem hardveru bilo je moguće generirati i analizirati tokove veće od 1Gb/s bez ikakvih problema.

Testiranje na pravim mrežnim karticama

Nakon testiranja na veth paru, trebate uzeti dva hosta ili dva porta jednog hosta, spojiti portove jedan s drugim, pokrenuti generator na jednom, a analizator na drugom. Tu nije bilo iznenađenja, ali zapravo sve ovisi o željezu, što je slabije, to će ovdje biti zanimljivije.

Korištenje primljenih podataka od strane sustava za nadzor (Zabbix)

tsp nema nikakav strojno čitljiv API poput SNMP-a ili sličnog. CC poruke moraju biti agregirane najmanje 1 sekundu (s visokim postotkom gubitka paketa, može ih biti na stotine/tisuće/desetke tisuća u sekundi, ovisno o brzini prijenosa).

Stoga, kako biste spremili informacije i nacrtali grafikone za CC pogreške i bitrate i napravili neku vrstu nezgoda, mogu postojati sljedeće opcije:

  1. Raščlanite i agregirajte (pomoću CC) izlaz tsp, tj. pretvoriti u željeni oblik.
  2. Dovršite sam tsp i/ili procesorske dodatke bitrate_monitor i kontinuitet tako da se rezultat daje u strojno čitljivom obliku prikladnom za sustav nadzora.
  3. Napišite svoju aplikaciju na vrhu tsduck biblioteke.

Očito je da je opcija 1 najlakša u smislu napora, posebno imajući u vidu da je sam tsduck napisan na jeziku niske razine (po modernim standardima) (C ++)

Jednostavan prototip bash parser+agregatora pokazao je da na streamu od 10 Mbps i 50% gubitka paketa (u najgorem slučaju), bash proces troši 3-4 puta više CPU-a nego sam tsp proces. Ovaj scenarij je neprihvatljiv. Zapravo dio ovog prototipa ispod

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

Osim što je neprihvatljivo spor, u bashu nema normalnih niti, bash poslovi su odvojeni procesi, a ja sam morao pisati vrijednost missingPackets jednom u sekundi zbog nuspojave (prilikom primanja bitrate poruka koje dolaze svake sekunde). Kao rezultat toga, bash je ostao sam i odlučeno je da se omot (parser + agregator) napiše u golangu. CPU potrošnja sličnog golang koda je 4-5 puta manja od samog tsp procesa. Ubrzanje omotača zbog zamjene basha golangom pokazalo se oko 16 puta i općenito je rezultat prihvatljiv (preopterećenje CPU-a za 25% u najgorem slučaju). Golang izvorna datoteka je locirana здесь.

Pokreni omot

Za pokretanje wrappera napravljen je najjednostavniji servisni predložak za systemd (здесь). Sam omotač trebao bi se kompajlirati u binarnu datoteku (idi izgraditi tsduck-stat.go) koja se nalazi u /opt/tsduck-stat/. Pretpostavlja se da koristite golang s podrškom za monotoni sat (>=1.9).

Da biste kreirali instancu usluge, morate pokrenuti naredbu systemctl enable [e-pošta zaštićena]:1234 zatim pokrenite s systemctl start [e-pošta zaštićena]: 1234.

Otkriće Zabbixa

Da bi zabbix mogao otkriti pokrenute usluge, to je učinjeno generator popisa grupa (discovery.sh), u formatu potrebnom za otkrivanje Zabbixa, pretpostavlja se da se nalazi na istom mjestu - u /opt/tsduck-stat. Da biste pokrenuli otkrivanje putem zabbix-agenta, trebate dodati .conf datoteka u konfiguracijski direktorij zabbix-agenta za dodavanje korisničkog parametra.

Zabbix predložak

Izrađen predložak (tsduck_stat_template.xml) sadrži pravilo automatskog otkrivanja, prototipove stavki, grafikone i okidače.

Kratki kontrolni popis (dobro, što ako ga netko odluči koristiti)

  1. Provjerite da tsp ne ispušta pakete pod "idealnim" uvjetima (generator i analizator su povezani izravno), ako ima ispuštanja, pogledajte paragraf 2 ili tekst članka o ovom pitanju.
  2. Izvršite podešavanje maksimalnog međuspremnika utičnice (net.core.rmem_max=8388608).
  3. Prevedi tsduck-stat.go (idi izgradi tsduck-stat.go).
  4. Stavite predložak usluge u /lib/systemd/system.
  5. Pokrenite usluge s systemctl, provjerite jesu li se počeli pojavljivati ​​brojači (grep "" /dev/shm/tsduck-stat/*). Broj usluga prema broju multicast tokova. Ovdje ćete možda morati stvoriti rutu do multicast grupe, možda onemogućiti rp_filter ili stvoriti rutu do izvorne ip adrese.
  6. Pokrenite discovery.sh, provjerite generira li json.
  7. Dodajte konfiguraciju zabbix agenta, ponovno pokrenite zabbix agenta.
  8. Učitajte predložak na zabbix, primijenite ga na host koji se prati i zabbix-agent je instaliran, pričekajte oko 5 minuta, pogledajte ima li novih stavki, grafikona i okidača.

Rezultirati

Korištenje TSDucka za nadzor IP(TS) tokova

Za zadatak otkrivanja gubitka paketa, to je gotovo dovoljno, barem je bolje od nikakvog praćenja.

Doista, kod spajanja video fragmenata može doći do "gubitaka" CC-a (koliko ja znam, tako se rade umetci u lokalnim TV centrima u Ruskoj Federaciji, tj. bez ponovnog izračunavanja CC brojača), to se mora zapamtiti. Vlasnička rješenja djelomično zaobilaze ovaj problem otkrivanjem SCTE-35 oznaka (ako ih je dodao generator toka).

Što se tiče praćenja kvalitete prijevoza, nedostaje praćenje podrhtavanja (IAT). TV oprema (bilo da se radi o modulatorima ili krajnjim uređajima) ima zahtjeve za ovaj parametar i nije uvijek moguće napuhati jitbuffer do beskonačnosti. I podrhtavanje može plutati kada se oprema s velikim međuspremnicima koristi u prijenosu, a QoS nije konfiguriran ili nije dovoljno dobro konfiguriran za prijenos takvog prometa u stvarnom vremenu.

Izvor: www.habr.com

Dodajte komentar