Brug af TSDuck til at overvåge IP(TS)-streams

I dag findes der færdige (proprietære) løsninger til f.eks. overvågning af IP(TS)-strømme VB и iQ, de har et ret rigt sæt funktioner, og normalt har store operatører, der beskæftiger sig med tv-tjenester, sådanne løsninger. Denne artikel beskriver en løsning baseret på et open source-projekt TSDuck, designet til minimal kontrol af IP(TS)-streams ved hjælp af CC(continuity counter)-tæller og bitrate. En mulig anvendelse er at kontrollere tabet af pakker eller hele flowet gennem en lejet L2-kanal (som ikke kan overvåges normalt, f.eks. ved at aflæse tabstællere i køer).

Meget kort om TSDuck

TSDuck er en open source-software (2-klausul BSD-licens) (et sæt konsolværktøjer og et bibliotek til udvikling af brugerdefinerede hjælpeprogrammer eller plugins) til at manipulere TS-streams. Som input kan den arbejde med IP (multicast/unicast), http, hls, dvb tunere, dektec dvb-asi demodulator, der er intern TS-stream generator og læsning fra filer. Outputtet kan være skrivning til en fil, IP (multicast/unicast), hls, dektec dvb-asi og HiDes modulatorer, afspillere (mplayer, vlc, xine) og drop. Forskellige trafikprocessorer kan inkluderes mellem input og output, for eksempel PID remapping, scrambling / descrambling, CC-tælleranalyse, bitrateberegning og andre typiske operationer for TS-streams.

I denne artikel vil IP-streams (multicast) blive brugt som input, processorerne bitrate_monitor (fra navnet er det tydeligt, hvad det er) og kontinuitet (analyse af CC-tællere). Du kan nemt erstatte IP multicast med en anden inputtype understøttet af TSDuck.

Der er officielle builds/pakker TSDuck til de fleste nuværende operativsystemer. De er ikke tilgængelige for Debian, men vi formåede at bygge dem under debian 8 og debian 10 uden problemer.

Dernæst bruges version TSDuck 3.19-1520, Linux bruges som OS (debian 10 blev brugt til at forberede løsningen, CentOS 7 blev brugt til rigtig brug)

Forberedelse af TSDuck og OS

Før du overvåger reelle strømme, skal du sikre dig, at TSDuck fungerer korrekt, og at der ikke er nogen fald på netværkskortet eller OS (socket) niveau. Dette er nødvendigt for ikke at gætte senere, hvor faldene skete - på netværket eller "inde i serveren". Du kan tjekke drops på netværkskortniveauet med ethtool -S ethX kommandoen, tuning udføres af det samme ethtool (normalt skal du øge RX bufferen (-G) og nogle gange deaktivere nogle offloads (-K)). Som en generel anbefaling kan det anbefales at bruge en separat port til at modtage den analyserede trafik, hvis det er muligt, dette minimerer falske positiver forbundet med det faktum, at faldet skete nøjagtigt på analysatorporten på grund af tilstedeværelsen af ​​anden trafik. Hvis dette ikke er muligt (der anvendes en minicomputer/NUC med én port), så er det yderst ønskeligt at opsætte prioriteringen af ​​den analyserede trafik i forhold til resten på den enhed, som analysatoren er tilsluttet. Med hensyn til virtuelle miljøer, her skal du være forsigtig og være i stand til at finde pakkedråber, der starter fra en fysisk port og slutter med en applikation inde i en virtuel maskine.

Generering og modtagelse af en strøm inde i værten

Som et første trin i at forberede TSDuck vil vi generere og modtage trafik inden for en enkelt vært ved hjælp af netns.

Forberedelse af miljøet:

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

Miljøet er klar. Vi starter trafikanalysatoren:

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

hvor "-p 1 -t 1" betyder, at du skal beregne bithastigheden hvert sekund og vise information om bithastigheden hvert sekund
Vi starter trafikgeneratoren med en hastighed på 10 Mbps:

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

hvor "-p 7 -e" betyder, at du skal pakke 7 TS-pakker i 1 IP-pakke og gøre det hårdt (-e), dvs. vent altid 7 TS-pakker fra den sidste processor, før du sender en IP-pakke.

Analysatoren begynder at udsende de forventede meddelelser:

* 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

Tilføj nu nogle dråber:

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

og meddelelser som denne vises:

* 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 

som forventes. Deaktiver pakketab (ip netns exec P iptables -F) og prøv at øge generatorens bitrate til 100 Mbps. Analysatoren rapporterer en masse CC-fejl og omkring 75 Mbps i stedet for 100. Vi forsøger at finde ud af, hvem der har skylden - generatoren har ikke tid eller problemet er ikke i den, til dette begynder vi at generere et fast antal pakker (700000 TS-pakker = 100000 IP-pakker):

# 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

Som du kan se, blev der genereret præcis 100000 IP-pakker (151925460-151825460). Så lad os finde ud af, hvad der sker med analysatoren, for dette kontrollerer vi med RX-tælleren på veth1, den er strengt taget lig med TX-tælleren på veth0, så ser vi på, hvad der sker på socket-niveau:

# 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 

Her kan du se antallet af drops = 24355. I TS-pakker er dette 170485 eller 24.36% af 700000, så vi ser, at de samme 25% af den tabte bitrate er fald i udp-socket. Fald i en UDP-socket opstår normalt på grund af mangel på buffer, se på standard socketbufferstørrelsen og den maksimale socketbufferstørrelse:

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

Således, hvis applikationer ikke eksplicit anmoder om en bufferstørrelse, oprettes sockets med en buffer på 208 KB, men hvis de anmoder om mere, vil de stadig ikke modtage det, der blev anmodet om. Da du kan indstille bufferstørrelsen i tsp for IP-inputtet (-buffer-størrelse), vil vi ikke røre standard socket-størrelsen, men kun indstille den maksimale socket-bufferstørrelse og specificere bufferstørrelsen eksplicit gennem tsp-argumenterne:

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

Med denne tuning af socketbufferen, nu den rapporterede bitrate er omkring 100 Mbps, er der ingen CC-fejl.

Ifølge CPU-forbruget af selve tsp-applikationen. I forhold til én kerne i5-4260U CPU ved 1.40 GHz vil 10 Mbps flowanalyse kræve 3-4 % CPU, 100 Mbps – 25 %, 200 Mbps – 46 %. Når du indstiller % Packet Loss, øges belastningen på CPU'en praktisk talt ikke (men kan falde).

På mere produktiv hardware var det muligt at generere og analysere streams på mere end 1 Gb/s uden problemer.

Test på rigtige netværkskort

Efter at have testet på et veth-par, skal du tage to værter eller to porte på en vært, forbinde portene til hinanden, starte generatoren på den ene og analysatoren på den anden. Der var ingen overraskelser her, men faktisk afhænger det hele af jernet, jo svagere, jo mere interessant vil det være her.

Brug af de modtagne data af overvågningssystemet (Zabbix)

tsp har ikke nogen maskinlæsbar API som SNMP eller lignende. CC-beskeder skal aggregeres i mindst 1 sekund (med en høj procentdel af pakketab kan der være hundreder/tusinder/titusinder pr. sekund, afhængigt af bithastigheden).

For at gemme både information og tegne grafer for CC-fejl og bitrate og lave en eller anden form for ulykker, kan der således være følgende muligheder:

  1. Parse og aggreger (ved CC) outputtet af tsp, dvs. konverter den til den ønskede form.
  2. Afslut tsp selv og/eller processor plugins bitrate_monitor og kontinuitet, så resultatet er givet i en maskinlæsbar form, der passer til overvågningssystemet.
  3. Skriv din ansøgning oven på tsduck-biblioteket.

Mulighed 1 er naturligvis den nemmeste med hensyn til lønomkostninger, især i betragtning af, at tsduck selv er skrevet på et lavt niveau (efter moderne standarder) sprog (C ++)

En simpel bash parser+aggregator prototype viste, at på en 10Mbps stream og 50% pakketab (worst case), forbrugte bash processen 3-4 gange mere CPU end selve tsp processen. Dette scenarie er uacceptabelt. Faktisk et stykke af denne prototype nedenfor

Nudler på toppen

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

Ud over at være uacceptabelt langsom, er der ingen normale tråde i bash, bash-jobs er separate processer, og jeg var nødt til at skrive værdien af ​​missingPackets en gang i sekundet på bivirkningen (når jeg modtager bitrate-beskeder, der kommer hvert sekund). Som et resultat blev bash efterladt alene, og det blev besluttet at skrive en wrapper (parser + aggregator) i golang. CPU-forbruget af lignende golang-kode er 4-5 gange mindre end selve tsp-processen. Fremskyndelsen af ​​indpakningen på grund af udskiftningen af ​​bash med golang viste sig at være omkring 16 gange, og generelt er resultatet acceptabelt (CPU-overhead med 25% i værste fald). Golang-kildefilen er placeret her.

Kør indpakning

For at starte indpakningen blev den enkleste serviceskabelon til systemd lavet (her). Selve indpakningen formodes at være kompileret til en binær fil (go build tsduck-stat.go) placeret i /opt/tsduck-stat/. Det antages, at du bruger golang med understøttelse af monotont ur (>=1.9).

For at oprette en forekomst af tjenesten skal du køre kommandoen systemctl enable [e-mail beskyttet]:1234 kør derefter med systemctl start [e-mail beskyttet]: 1234.

Opdagelse fra Zabbix

For at zabbix skal kunne opdage kørende tjenester, er det gjort gruppelistegenerator (discovery.sh), i det format, der kræves til Zabbix-opdagelse, antages det, at det er placeret på samme sted - i /opt/tsduck-stat. For at køre opdagelse via zabbix-agent skal du tilføje .conf-fil til zabbix-agent-konfigurationsbiblioteket for at tilføje brugerparameteren.

Zabbix skabelon

Oprettet skabelon (tsduck_stat_template.xml) indeholder autodiscover-reglen, vareprototyper, grafer og triggere.

Kort tjekliste (tja, hvad hvis nogen beslutter sig for at bruge det)

  1. Sørg for, at tsp ikke taber pakker under "ideelle" forhold (generator og analysator er forbundet direkte), hvis der er fald, se afsnit 2 eller teksten i artiklen om denne sag.
  2. Foretag indstilling af den maksimale socketbuffer (net.core.rmem_max=8388608).
  3. Kompiler tsduck-stat.go (gå til build tsduck-stat.go).
  4. Sæt tjenesteskabelonen i /lib/systemd/system.
  5. Start tjenester ved hjælp af systemctl, tjek at tællere er begyndt at dukke op (grep "" /dev/shm/tsduck-stat/*). Antallet af tjenester efter antallet af multicast-streams. Her skal du muligvis oprette en rute til multicast-gruppen, måske deaktivere rp_filter eller oprette en rute til kilde-ip.
  6. Kør discovery.sh, sørg for at det genererer json.
  7. Tilføj zabbix agent config, genstart zabbix agent.
  8. Upload skabelonen til zabbix, anvend den på værten, der overvåges, og zabbix-agenten er installeret, vent ca. 5 minutter, se om der er nye elementer, grafer og triggere.

Outcome

Brug af TSDuck til at overvåge IP(TS)-streams

Til opgaven med at opdage pakketab er det næsten nok, i det mindste er det bedre end ingen overvågning.

Faktisk kan CC-"tab" opstå ved sammenlægning af videofragmenter (så vidt jeg ved, er det sådan, indsætninger laves på lokale tv-centre i Den Russiske Føderation, dvs. uden at genberegne CC-tælleren), dette skal huskes. Proprietære løsninger omgår delvist dette problem ved at detektere SCTE-35-etiketter (hvis tilføjet af stream-generatoren).

Med hensyn til overvågning af transportkvalitet er der mangel på jitter-overvågning (IAT). Tv-udstyr (det være sig modulatorer eller slutenheder) har krav til denne parameter, og det er ikke altid muligt at puste jitbufferen op i det uendelige. Og jitter kan flyde, når udstyr med store buffere bruges i transit, og QoS ikke er konfigureret eller ikke godt konfigureret nok til at transmittere sådan realtidstrafik.

Kilde: www.habr.com

Tilføj en kommentar