TSDucki kasutamine IP(TS) voogude jälgimiseks

Praeguseks on olemas valmis (patenteeritud) lahendused IP(TS) voogude jälgimiseks, näiteks VB ja iQ, neil on piisavalt lai funktsioonide komplekt ning tavaliselt on sarnased lahendused suurte operaatorite käsutuses, kes tegelevad TV teenustega. Käesolevas artiklis kirjeldatakse open source projektil põhinevat lahendust TSDuck, mis on mõeldud IP(TS) voogude minimaalseks jälgimiseks CC (continuity counter) ja bitrate'i järgi. Võimalik rakendamine — pakettide või kogu voolu kaotuse jälgimine renditud L2-kanali kaudu (mida ei ole võimalik korralikult jälgida, näiteks kaotuste arvu lugemise kaudu järjekordades).

TSDuckist lühidalt

TSDuck on open source (2-Clause BSD litsentsiga) tarkvara (konsol-utiliitide komplekt ja teek oma utiliitide või pluginite arendamiseks) TS voogudega manipuleerimiseks. Sisendina suudab töötada IP (multicast/unicast), http, hls, dvb-tuuneritega, dektec dvb-asi demodulaatoriga, omab sisemist TS voogude generaatorit ja failidest lugemist. Väljundina võib genereerida faili salvestamist, IP (multicast/unicast), hls, dektec dvb-asi ja HiDes modulaatorite, mängijate (mplayer, vlc, xine) ja drop. Sisendi ja väljundi vahel võivad olla erinevad liiklusprotsessorid, näiteks PIDide ümberkaardistamine, skremlinamine/ deskremlinamine, CC loenduri analüüs, bititeenuse arvestamine ja muud tüüpilised TS voogude toimingud.

Käesolevas artiklis kasutatakse sisendina IP vooge (multicast), kasutades protsessoreid bitrate_monitor (nagu nimest aru saada) ja continuity (CC loenduri analüüs). Probleemideta võib IP multicast'i asendada muu sisendiga, mida TSDuck toetab.

On olemas ametlikud kogud/paketid TSDuck enamikule praegustele operatsioonisüsteemidele. Debianile ei ole neid, kuid suudeti probleemideta koguda debiani 8 ja debiani 10 jaoks.

Edasi kasutatakse TSDuck versiooni 3.19-1520, operatsioonisüsteemina Linux (lahenduse ettevalmistamiseks kasutati debiani 10, reaalsetes tingimustes — CentOS 7)

TSDuck'i ja operatsioonisüsteemi ettevalmistamine

Enne kui jälgite reaalseid vooge, tuleb veenduda, et TSDuck töötab õigesti ning võrgu või OS (socketi) tasemel ei esine kaotusi. See on vajalik, et hiljem ei peaks spekuleerima, kus kaotused toimusid - kas võrgus või «serveri sees». Võrgu tasemel kaotuste kontrollimiseks saab kasutada käsku ethtool -S ethX, häälestamine toimub sama ethtooliga (tavaliselt tuleb suurendada RX-puhvri (-G) suurust ja mõnikord keelata teatud offload-d (-K)). Üldise soovitusena võiks soovitada kasutada eraldi porti analüüsitava liikluse vastuvõtmise jaoks, kui see on võimalik, see minimeerib valehäireid, mis on seotud kaotustega, mis toimusid analüsaatori pordil, kuna seal on ka muud liiklust. Kui sellist võimalust pole (kasutatakse mini-arvutit / NUC-i ühe pordiga), siis on väga soovitatav seadistada analüüsitava liikluse prioriteet seadmes, kuhu analüsaator on ühendatud, võrreldes muu liiklusega. Virtuaalsete keskkondade osas tuleb olla ettevaatlik ja osata leida kaotusi alates füüsilisest pordist kuni rakenduseni virtuaalmasinas.

Liikme genereerimine ja vastuvõtt hostis

Esimese sammuna TSDucki ettevalmistamiseks genereerime ja vastu võtame liiklust ühes ja samas hostis kasutades netns-i.

Valmistame keskkonna ette:

ip netns add P # loome netns P, kus toimub liikluse analüüs
ip link add type veth # loome veth-paari - veth0 jääb vaikimisi netns-i (sellele liidesesse genereeritakse liiklus)
ip link set dev veth1 netns P # veth1 - paigutame netns-i P (sellel liidesel toimub liikluse vastuvõtt)
ip netns exec P ifconfig veth1 192.0.2.1/30 up # tõstame IP üles veth1, ei oma tähtsust, mis see on
ip netns exec P ip ro add default via 192.0.2.2 # seadistame vaikimisi marsruudi netns P sees
sysctl net.ipv6.conf.veth0.disable_ipv6=1 # keelame IPv6 veth0-l - see tehakse selleks, et TX-loendisse ei satuks võõrad andmed
ifconfig veth0 up # tõstame veth0 liidese üles
ip route add 239.0.0.1 dev veth0 # loome marsruudi, et OS suunaks liikluse 239.0.0.1 suunas veth0-le

Keskkond on valmis. Käivitame liikluse analüsaatori:

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

kus «-p 1 -t 1» tähendab, et bitrate arvutatakse iga sekundi tagant ja bitrathi teave väljastatakse iga sekundi tagant
Käivitame liikme generaatori kiirusel 10 Mbit/s:

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

kus «-p 7 -e» tähendab, et tuleb pakendada 7 TS-paketti 1 IP-paketti ja teha seda rangelt (-e), st alati oodata 7 TS-paketti viimase protsessorilt enne IP-paketi saatmist.

Analüsaator hakkab välja andma oodatud sõnumeid:

* 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

Nüüd lisame natuke droppe:

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

ja ilmuvad sõnumid nagu need:

* 2020/01/03 14:57:11 - continuity: paketide indeks: 80,745, PID: 0x0000, puuduvad 7 paketti
* 2020/01/03 14:57:11 - continuity: paketide indeks: 83,342, PID: 0x0000, puuduvad 7 paketti 

mis on oodatud. Lülitame pakettide kadumise välja (ip netns exec P iptables -F) ja proovime suurendada generaatori bitreami 100Mbit/s. Analüsaator teatab hulgast CC-eksimistest ja umbes 75 Mbit/s asemel 100. Püüame välja selgitada, kes on süüdi — kas generaator ei suuda või pole probleem temas, selleks käivitame fikseeritud arvu pakettide genereerimise (700000 TS-paketti = 100000 IP-paketti):

# 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

Nagu näha, genereeriti täpselt 100000 IP-paketti (151925460-151825460). Järelikult uurime, mis toimub analüsaatoriga, selleks võrreldame RX arvesti veth1-l, see on rangelt võrdne TX arvestiga veth0-l, seejärel vaatame, mis toimub soketi tasemel:

# 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 

Siin on näha kadude arv = 24355. TS-pakettides on see 170485 või 24.36% 700000-st, seega näeme, et need 25% kadunud bitreamist on UDP-soketi dropid. UDP-soketi dropid tekivad tavaliselt mälupuhvri puudumise tõttu, vaatame, kui suur on soketi vaikimisi mälu ja maksimaalne soketi suurus:

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

Seega, kui rakendused ei küsi selgelt mälu suurust, luuakse soketid 208 Kb mälupuhvriga, kuid kui nad küsivad rohkem, ei saa nad ikkagi soovitud. Kuna tsp jaoks IP-sisendi puhul saab määrata mälupuhvri suuruse (—buffer-size), siis ei puutu vaikimisi soketi suurust, vaid määrame ainult maksimaalse soketi suuruse ja anname mälupuhvri suuruse selgelt tsp argumentide kaudu:

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

Selle soketi mälupuhvri häälestusega on nüüd teatatud bitream umbes 100Mbit/s, CC-eksimisi pole.

CPU tarbimise osas rakenduse tsp. Ühe i5-4260U CPU @ 1,40 GHz tuuma kohta nõuab 10 Mbit/s voogude analüüs 3-4% CPU, 100 Mbit/s — 25%, 200 Mbit/s — 46%. Kaotatud pakettide % määramisel ei suurene CPU koormus praktiliselt (aga võib väheneda).

Tõhusamal riistvaral õnnestus muretult genereerida ja analüüsida vooge üle 1 Gbit/s.

Testimine reaalsetel võrgukaartidel

Pärast testimist veth-paariga tuleb võtta kaks hosti või kahe portaali ühendamine ühe hosti peale, ühendada portid omavahel, käivitada ühel generaator ja teisel analüsaator. Siin üllatusi ei juhtunud, kuid tegelikult sõltub kõik riistvarast, mida nõrgem on, seda huvitavam see siin on.

Saadud andmete kasutamine jälgimisüsteemis (Zabbix)

Tsp-l ei ole mingisugust masinaga loetavat API-t nagu SNMP või sarnast. CC sõnumeid tuleb koguda vähemalt 1 sekundi kaupa (kui kaotatud pakettide protsent on kõrge, võib neid olla sadu/tuhandeid/kümneid tuhandeid sekundis, sõltub bitikiirusest).

Seega, et salvestada nii informatsiooni kui joonistada graafikud CC-tionide ja bitikiiruse kohta ning teha edasised avariid, võivad olla järgmised variandid:

  1. Parsida ja agreggeerida (CC järgi) tsp-i väljund, st muuta see vajalikku vormi.
  2. Töötada välja tsp ja/või protsessoripluginid bitrate_monitor ja continuity, et tulemus esitataks masinaga loetavas vormis, mis sobib jälgimissüsteemile.
  3. Kirjutada oma rakendus tsduck raamatukogu peal.

On ilmne, et tööjõukulude osas on variant 1 kõige lihtsam, eriti arvestades, et tsduck on kirjutatud madala taseme (kaasaegsete standardite kohaselt) keeles (C++)

Lihtne parseri + agreggeerija prototüüp bashis näitas, et 10 Mbit/s voogude ja 50% kaotatud pakettide (halvim variant) korral tarbis bash protsess 3-4 korda rohkem CPU-d kui ise tsp protsess. See stsenaarium on vastuvõetamatu. Tegelikult on allpool osa sellest prototüübist.

Nuudel bashis

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

Kuigi see töötab vastuvõetamatult aeglaselt, puuduvad bashis normaalsed lõngad, bashi tööd on iseseisvad protsessid ja tuli teha sekundis ühe korra väärtuse missingPackets salvestamine kõrvalmõjus (bitikiiruseteate saamisel, mis saabuvad iga sekundi tagant). Lõppkokkuvõttes jäi bash rahule ja otsustati kirjutada wrapper (parser + agregaat) golangis. CPU tarbimine sarnasel golangi koodil on 4-5 korda väiksem kui tsp protsessil. Wrapperi kiirus golangi vahetamisega bashist paranes umbes 16 korda ja üldine tulemus on vastuvõetav (CPU ülekoormus halvas stsenaariumis 25%). Algfail golangis asub siin.

Wrapperi käivitamine

Wrapperi käivitamiseks on loodud kõige lihtsam teenusemall systemd jaoks (siin). Eeldatakse, et ise wrapper on kompileeritud binaarfailiks (go build tsduck-stat.go), mis asub /opt/tsduck-stat/. Eeldatakse, et kasutatakse golangi, mis toetab monotoonset kella (>=1.9).

Teenuse eksemplari loomiseks tuleb käivitada käsk systemctl enable tsduck-stat@239.0.0.1:1234, seejärel käivitada käsuga systemctl start tsduck-stat@239.0.0.1:1234.

Zabbixist avastamine

Kuna zabbix peab suutma avastada aktiivseid teenuseid, on loodud rühma loendi generaator (discovery.sh), Zabbixi avastamiseks vajalikus formaadis, eeldatakse, et see asub seal samas — /opt/tsduck-stat. Zabbixi agendi abil discovery käivitamiseks tuleb lisada .conf-fail zabbix-agendi konfiguratsioonide kausta, et lisada user-parameeter.

Zabbixi mall

Loodud mall (tsduck_stat_template.xml) sisaldab automaatse avastamise reeglit, andmeelementide prototüüpe, graafikuid ja trigger'ite seadistusi.

Lühike kontrolldokument (äkki mõni otsustab kasutada)

  1. Veenduge, et tsp ei viska pakette «ideaalses» olukorras (generaator ja analüsaator on otse ühendatud), kui on pakettide kaotus, vaata p.2 või selle kohta artiklit.
  2. Teha soketi maksimaalse puhvri häälestus (net.core.rmem_max=8388608).
  3. Kompileerida tsduck-stat.go (go build tsduck-stat.go).
  4. Paigutada teenusemall /lib/systemd/system.
  5. Käivitada teenused kasutades systemctl, kontrollida, et loendurid hakkavad ilmuma (grep «» /dev/shm/tsduck-stat/*). Teenuste arv peaks vastama multicast-voogude arvule. Siin võib osutuda vajalikuks luua marsruut multicast-gruppi, võib-olla väljendada rp_filter või luua marsruut source ip suunas.
  6. Käivitada discovery.sh, veenduda, et see genereerib json.
  7. Paigutada zabbix-agendi konfigureerimine, taaskäivitada zabbix-agent.
  8. Lae mall template Zabbix, rakenda see hostile, kus toimub jälgimine ja on installitud Zabbix-agent, oota umbes 5 minutit, vaata, et ilmusid uued andmed, graafikud ja triggereid.

Tulemus

TSDucki kasutamine IP(TS) voogude jälgimiseks

Pakettide kaotuse tuvastamiseks on peaaegu piisav, vähemalt on see parem kui jälgimise puudumine.

Tõepoolest, CC-"kaotused" võivad tekkida video fragmentide liitmisel (nii palju kui mina tean, nii tehakse lisandeid kohalikes telesentralides Venemaal, st CC-loendurit ei ümber arvutata), seda tuleb meeles pidada. Propietaarsetes lahendustes on see probleem osaliselt lahendatud SCTE-35 silte tuvastamisega (kui need lisatakse voogedastuse generaatori poolt).

Transportkvaliteedi jälgimise seisukohalt puudub jitteri (IAT) jälgimine, kuna TV-seadmetel (olgu need modulaatorid või lõpp-seadmed) on selle parameetri suhtes nõuded ning jitbufferit ei saa alati ääretult suurendada. Ja jitter võib häirida, kui ülekande ajal kasutatakse seadmeid, millel on suured puhvri suurused ja QoS-i seadistus ei ole korralikult häälestatud sellise reaalajas edastamise jaoks.

Allikas: habr.com

Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster