Korištenje TSDuck-a za praćenje IP(TS) tokova

Danas postoje gotova (vlasnička) 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 zasnovano na projektu otvorenog koda TSDuck, dizajniran za minimalnu kontrolu IP(TS) tokova pomoću CC (kontinuitet brojača) brojača i bitrate. Moguća primena je kontrola gubitka paketa ili celog toka kroz zakupljeni L2 kanal (koji se ne može normalno nadgledati, na primer, čitanjem brojača gubitaka u redovima).

Vrlo kratko o TSDucku

TSDuck je softver otvorenog koda (2-Clause BSD licenca) (skup konzolnih uslužnih programa i biblioteka za razvoj prilagođenih uslužnih programa ili dodataka) za manipulaciju TS streamovima. Kao ulaz može raditi sa IP (multicast/unicast), http, hls, dvb tjunerima, dektec dvb-asi demodulatorom, postoji interni TS-stream generator i čitanje iz fajlova. Izlaz može biti pisanje u fajl, IP (multicast/unicast), hls, dektec dvb-asi i HiDes modulatori, plejeri (mplayer, vlc, xine) i drop. Različiti prometni procesori mogu biti uključeni između ulaza i izlaza, na primjer, PID remapping, šifriranje / dekodiranje, analiza CC brojača, izračunavanje bitrate-a i druge tipične operacije za TS streamove.

U ovom članku će se kao ulaz koristiti IP streamovi (multicast), koriste se procesori bitrate_monitor (iz naziva je jasno o čemu se radi) i kontinuitet (analiza CC brojača). Možete jednostavno zamijeniti IP multicast drugim tipom ulaza koji podržava TSDuck.

Postoje službene verzije/pakete TSDuck za najsavremenije operativne sisteme. Nisu dostupni za Debian, ali uspjeli smo ih napraviti pod debianom 8 i debianom 10 bez ikakvih problema.

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

Priprema TSDuck i OS

Prije praćenja stvarnih tokova, morate biti sigurni da TSDuck radi ispravno i da nema padova na nivou mrežne kartice ili OS (socket). Ovo je potrebno kako se kasnije ne bi pogodili gdje je došlo do pada - na mreži ili "unutar servera". Možete provjeriti padove na nivou mrežne kartice pomoću ethtool -S ethX komande, podešavanje se vrši od strane istog ethtool-a (obično, trebate povećati RX bafer (-G) i ponekad onemogućiti neke offloads (-K)). Kao opšta preporuka, može se savjetovati korištenje posebnog porta za prijem analiziranog prometa, ako je moguće, to minimizira lažne pozitivne rezultate povezane sa činjenicom da se pad dogodio upravo na portu analizatora zbog prisustva drugog saobraćaja. Ako to nije moguće (koristi se mini-računalo/NUC sa jednim portom), onda je vrlo poželjno postaviti prioritet analiziranog prometa u odnosu na ostatak na uređaju na koji je analizator povezan. Što se tiče virtuelnih okruženja, ovdje morate biti oprezni i biti u mogućnosti pronaći ispadanje paketa počevši od fizičkog porta pa do aplikacije unutar virtuelne mašine.

Generisanje i prijem toka unutar hosta

Kao prvi korak u pripremi TSDuck-a, generisaćemo i primati saobraćaj 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

Okruženje je spremno. Pokrećemo analizator saobraćaja:

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 bitrate-u svake sekunde
Pokrećemo generator saobraćaja 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 trebate spakovati 7 TS paketa u 1 IP paket i to učiniti teško (-e), tj. uvijek sačekajte 7 TS paketa od posljednjeg procesora prije slanja IP paketa.

Analizator počinje da emituje 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 brzinu prijenosa generatora na 100 Mbps. Analizator javlja gomilu CC grešaka i oko 75 Mbps umjesto 100. Pokušavamo otkriti ko je kriv - generator nema vremena ili problem nije u njemu, za to 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, generisano je tačno 100000 IP paketa (151925460-151825460). Dakle, hajde da shvatimo šta se dešava sa analizatorom, za ovo proveravamo sa RX brojačem na veth1, on je striktno jednak TX brojaču na veth0, zatim gledamo šta se dešava na nivou 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 padova = 24355. U TS paketima to je 170485 ili 24.36% od 700000, tako da vidimo da su tih istih 25% izgubljenog bitrate-a padovi u udp socketu. Padovi u UDP soketu obično se javljaju zbog nedostatka bafera, pogledajte zadanu veličinu bafera utičnice i maksimalnu veličinu bafera utičnice:

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

Dakle, ako aplikacije ne traže eksplicitno veličinu bafera, kreiraju se utičnice sa baferom od 208 KB, ali ako zatraže više, i dalje neće dobiti ono što je traženo. Budući da možete postaviti veličinu bafera u tsp za IP ulaz (-buffer-size), nećemo dirati zadanu veličinu utičnice, već samo postaviti maksimalnu veličinu bafera utičnice i eksplicitno specificirati veličinu bafera 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

Sa ovim podešavanjem bafera socketa, sada je prijavljeni bitrate oko 100Mbps, nema CC grešaka.

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

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

Testiranje na stvarnim mrežnim karticama

Nakon testiranja na veth paru, potrebno je 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 zavisi od gvožđa, što slabije, to će ovde biti zanimljivije.

Korištenje primljenih podataka od strane nadzornog sistema (Zabbix)

tsp nema nikakav strojno čitljiv API kao što je SNMP ili slično. CC poruke moraju biti agregirane najmanje 1 sekundu (sa visokim procentom gubitka paketa, može biti stotine/hiljade/desetine hiljada u sekundi, u zavisnosti od brzine prenosa).

Dakle, kako bi se sačuvale i informacije i nacrtali grafikoni za CC greške i bitrate i napravili neku vrstu nezgoda, mogu postojati sljedeće opcije:

  1. Parsirajte i agregirajte (po CC) izlaz tsp, tj. pretvoriti u željeni oblik.
  2. Završite sam tsp i/ili procesorske dodatke bitrate_monitor i kontinuitet tako da se rezultat daje u mašinski čitljivom obliku pogodnom za sistem za nadzor.
  3. Napišite svoju aplikaciju na vrhu tsduck biblioteke.

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

Jednostavan bash parser+agregator prototip je pokazao da na 10Mbps streamu i 50% gubitka paketa (u najgorem slučaju), bash proces troši 3-4 puta više CPU-a od samog tsp procesa. Ovaj scenario 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, nema normalnih niti u bash-u, bash poslovi su odvojeni procesi i morao sam jednom u sekundi da upišem vrijednost missingPackets na nuspojavu (kada primam poruke brzine prijenosa koje dolaze svake sekunde). Kao rezultat toga, bash je ostao sam i odlučeno je da se napiše omot (parser + agregator) u golang. Potrošnja CPU-a sličnog golang koda je 4-5 puta manja od samog tsp procesa. Pokazalo se da je ubrzanje omotača zbog zamjene bash-a golangom oko 16 puta i općenito je rezultat prihvatljiv (CPU overhead za 25% u najgorem slučaju). Golang izvorni fajl se nalazi ovdje.

Pokreni omotač

Za pokretanje omota napravljen je najjednostavniji servisni šablon za systemd (ovdje). Sam omotač bi trebao biti preveden u binarni fajl (idi build tsduck-stat.go) koji se nalazi u /opt/tsduck-stat/. Pretpostavlja se da koristite golang sa podrškom za monotoni sat (>=1.9).

Da biste kreirali instancu usluge, morate pokrenuti naredbu systemctl enable [email zaštićen]:1234 zatim pokrenite sa systemctl start [email zaštićen]: 1234.

Otkriće iz Zabbixa

Da bi zabbix mogao otkriti pokrenute servise, to je učinjeno generator grupnih lista (discovery.sh), u formatu potrebnom za Zabbix otkriće, pretpostavlja se da se nalazi na istom mjestu - u /opt/tsduck-stat. Da biste pokrenuli otkrivanje putem zabbix-agenta, trebate dodati .conf fajl u konfiguracijski direktorij zabbix-agenta da dodate korisnički parametar.

Zabbix Template

Kreiran šablon (tsduck_stat_template.xml) sadrži pravilo automatskog otkrivanja, prototipove stavki, grafikone i pokretače.

Kratka kontrolna lista (pa, šta ako neko odluči da je koristi)

  1. Pazite da tsp ne ispušta pakete pod "idealnim" uslovima (generator i analizator su direktno povezani), ako ima ispadanja, pogledajte paragraf 2 ili tekst članka o ovom pitanju.
  2. Napravite podešavanje maksimalnog bafera utičnice (net.core.rmem_max=8388608).
  3. Kompajlirajte tsduck-stat.go (idite izgradite tsduck-stat.go).
  4. Stavite predložak usluge u /lib/systemd/system.
  5. Pokrenite servise sa systemctl, provjerite da li su brojači počeli da se pojavljuju (grep "" /dev/shm/tsduck-stat/*). Broj usluga prema broju multicast tokova. Ovdje ćete možda trebati kreirati rutu do višestruke grupe, možda onemogućiti rp_filter ili kreirati rutu do izvornog IP-a.
  6. Pokrenite discovery.sh, provjerite da li generiše json.
  7. Dodajte konfiguraciju zabbix agenta, ponovo pokrenite zabbix agent.
  8. Učitajte šablon na zabbix, primijenite ga na host koji se nadgleda i zabbix-agent je instaliran, pričekajte oko 5 minuta, pogledajte da li ima novih stavki, grafikona i okidača.

rezultat

Korištenje TSDuck-a za praćenje IP(TS) tokova

Za zadatak otkrivanja gubitka paketa, to je skoro dovoljno, barem je bolje nego bez nadzora.

Zaista, CC "gubici" mogu nastati prilikom spajanja video fragmenata (koliko ja znam, ovako se umetanja prave u lokalnim TV centrima u Ruskoj Federaciji, tj. bez ponovnog izračunavanja CC brojača), to se mora zapamtiti. Vlasnička rješenja djelimično zaobilaze ovaj problem otkrivanjem SCTE-35 oznaka (ako ih doda generator toka).

Što se tiče praćenja kvaliteta transporta, postoji nedostatak praćenja podrhtavanja (IAT). TV oprema (bilo da se radi o modulatorima ili krajnjim uređajima) ima zahtjeve za ovaj parametar i nije uvijek moguće naduvati jitbuffer do beskonačnosti. I podrhtavanje može plutati kada se oprema sa velikim baferima koristi u tranzitu, a QoS nije konfiguriran ili nije dovoljno dobro konfiguriran za prijenos takvog prometa u realnom vremenu.

izvor: www.habr.com

Dodajte komentar