TSDuck brûke om IP(TS)-streamen te kontrolearjen

Tsjintwurdich binne d'r ready-made (proprietêre) oplossingen foar it kontrolearjen fan IP(TS) streamen, bygelyks VB и iQ, se hawwe in frij rike set fan funksjes en meastentiids hawwe grutte operators dy't omgean mei TV tsjinsten hawwe sokke oplossings. Dit artikel beskriuwt in oplossing basearre op in iepen boarne projekt TSDuck, ûntworpen foar minimale kontrôle fan IP (TS) streamen troch CC (kontinuïteitsteller) teller en bitrate. In mooglike tapassing is om it ferlies fan pakketten of de hiele stream troch in ferhierd L2-kanaal te kontrolearjen (dat kin net normaal kontrolearre wurde, bygelyks troch ferliestellers yn wachtrigen te lêzen).

Hiel koart oer TSDuck

TSDuck is in iepen boarne (2-Clause BSD-lisinsje) software (in set fan konsole-helpprogramma's en in bibleteek foar it ûntwikkeljen fan oanpaste utilities as plugins) foar it manipulearjen fan TS-streamen. As in ynfier, it kin wurkje mei IP (multicast / unicast), http, hls, dvb tuners, dektec dvb-asi demodulator, der is in ynterne TS-stream generator en lêzen fan triemmen. De útfier kin skriuwe nei in triem, IP (multicast / unicast), hls, dektec dvb-asi en HiDes modulators, spilers (mplayer, vlc, xine) en drop. Ferskate ferkearsprozessors kinne wurde opnommen tusken ynput en útfier, bygelyks PID-remapping, scrambling / descrambling, CC-telleranalyse, bitrate-berekkening, en oare typyske operaasjes foar TS-streamen.

Yn dit artikel wurde IP-streamen (multicast) brûkt as ynfier, de processors bitrate_monitor (fan 'e namme is dúdlik wat it is) en kontinuïteit (analyze fan CC-tellers) wurde brûkt. Jo kinne IP-multycast maklik ferfange mei in oar ynfiertype stipe troch TSDuck.

Binne beskikber offisjele builds / pakketten TSDuck foar de measte aktuele bestjoeringssystemen. Se binne net beskikber foar Debian, mar it is ús slagge om se sûnder problemen te bouwen ûnder debian 8 en debian 10.

Folgjende wurdt ferzje TSDuck 3.19-1520 brûkt, Linux wurdt brûkt as it OS (debian 10 waard brûkt om de oplossing ta te rieden, CentOS 7 waard brûkt foar echt gebrûk)

TSDuck en OS tariede

Foardat jo echte streamen kontrolearje, moatte jo derfoar soargje dat TSDuck goed wurket en d'r gjin drippen binne op it netwurkkaart as OS (socket) nivo. Dit is nedich om letter net te rieden wêr't de drippen barde - op it netwurk of "binnen de tsjinner". Jo kinne drops kontrolearje op it netwurk card nivo mei de ethtool -S ethX kommando, tuning wurdt dien troch deselde ethtool (meastentiids, jo moatte fergrutsje de RX buffer (-G) en soms útskeakelje guon offloads (-K)). As in algemiene oanbefelling kin it wurde advisearre om in aparte haven te brûken foar it ûntfangen fan it analysearre ferkear, as it mooglik is, dit minimearret falske positives dy't ferbûn binne mei it feit dat de drip krekt barde op 'e analysatorhaven fanwege de oanwêzigens fan oar ferkear. As dit net mooglik is (in mini-kompjûter / NUC mei ien poarte wurdt brûkt), dan is it tige winsklik om de prioritearring fan it analysearre ferkear yn te stellen yn relaasje ta de rest op it apparaat wêrmei de analysator is ferbûn. Wat firtuele omjouwings oanbelanget, moatte jo hjir foarsichtich wêze en pakketdruppels kinne fine begjinnend fan in fysike poarte en einigje mei in applikaasje yn in firtuele masine.

Generaasje en ûntfangst fan in stream binnen de host

As earste stap yn it tarieden fan TSDuck, sille wy ferkear generearje en ûntfange binnen in inkele host mei netns.

It miljeu tariede:

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

De omjouwing is klear. Wy begjinne de ferkearsanalysator:

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

wêr "-p 1 -t 1" betsjut dat jo de bitrate elke sekonde moatte berekkenje en elke sekonde ynformaasje oer de bitrate werjaan
Wy begjinne de ferkearsgenerator mei in snelheid fan 10Mbps:

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

wêr "-p 7 -e" betsjut dat jo moatte pakke 7 TS pakketten yn 1 IP pakket en doch it hurd (-e), i.e. altyd wachtsje 7 TS pakketten út de lêste prosessor foar it ferstjoeren fan in IP pakket.

De analysator begjint de ferwachte berjochten út te fieren:

* 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

Foegje no wat drippen ta:

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

en berjochten lykas dit ferskine:

* 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 

wat ferwachte wurdt. Skeakelje pakketferlies út (ip netns exec P iptables -F) en besykje de generatorbitrate te ferheegjen nei 100Mbps. De analyzer rapportearret in bosk CC flaters en oer 75 Mbps ynstee fan 100. Wy besykje út te finen wa't is de skuld - de generator hat gjin tiid of it probleem is net yn it, foar dit wy begjinne te generearjen in fêst oantal pakketten (700000 TS-pakketten = 100000 IP-pakketten):

# 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

Sa't jo sjen kinne, binne krekt 100000 IP-pakketten generearre (151925460-151825460). Dus litte wy útfine wat der bart mei de analyzer, hjirfoar kontrolearje wy mei de RX-teller op veth1, it is strikt gelyk oan de TX-teller op veth0, dan sjogge wy nei wat bart op it socketnivo:

# 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 

Hjir kinne jo it oantal drippen sjen = 24355. Yn TS-pakketten is dit 170485 of 24.36% fan 700000, dus sjogge wy dat deselde 25% fan 'e ferlerne bitrate drippen binne yn' e udp-socket. Drops yn in UDP-socket komme normaal foar troch in tekoart oan buffer, sjoch nei de standert socketbuffergrutte en de maksimale socketbuffergrutte:

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

Dus, as applikaasjes net eksplisyt in buffergrutte oanfreegje, wurde sockets makke mei in buffer fan 208 KB, mar as se mear freegje, sille se noch net ûntfange wat frege is. Om't jo de buffergrutte yn tsp kinne ynstelle foar de IP-ynfier (-buffer-grutte), sille wy de standert socketgrutte net oanreitsje, mar allinich de maksimale socketbuffergrutte ynstelle en de buffergrutte eksplisyt spesifisearje fia de tsp-arguminten:

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

Mei dizze ôfstimming fan 'e socketbuffer, no is de rapporteare bitrate sawat 100Mbps, binne d'r gjin CC-flaters.

Neffens de CPU-konsumpsje fan 'e tsp-applikaasje sels. Relatyf oan ien kearn i5-4260U CPU @ 1.40GHz, 10Mbps flow analyze sil fereaskje 3-4% CPU, 100Mbps - 25%, 200Mbps - 46%. By it ynstellen fan it % Packet Loss nimt de lading op 'e CPU praktysk net ta (mar kin ôfnimme).

Op mear produktive hardware wie it mooglik om streams fan mear dan 1Gb / s sûnder problemen te generearjen en te analysearjen.

Testen op echte netwurkkaarten

Nei it testen op in veth-paar, moatte jo twa hosts of twa havens fan ien host nimme, de havens mei elkoar ferbine, de generator op ien begjinne, en de analyzer op 'e twadde. D'r wiene hjir gjin ferrassingen, mar feitlik hinget it allegear ôf fan it izer, hoe swakker, hoe nijsgjirriger it hjir sil wêze.

Gebrûk fan de ûntfongen gegevens troch it tafersjochsysteem (Zabbix)

tsp hat gjin masine-lêsbere API lykas SNMP of ferlykber. CC-berjochten moatte op syn minst 1 sekonde wurde aggregearre (mei in heech persintaazje pakketferlies kinne d'r hûnderten / tûzenen / tsientûzenen per sekonde wêze, ôfhinklik fan 'e bitrate).

Sa, om sawol ynformaasje te bewarjen as grafiken te tekenjen foar CC-flaters en bitrate en in soarte fan ûngemakken te meitsjen, kinne d'r de folgjende opsjes wêze:

  1. Parse en aggregearje (troch CC) de útfier fan tsp, d.w.s. konvertearje it nei de winske foarm.
  2. Finish tsp sels en / of prosessor plugins bitrate_monitor en kontinuïteit, sadat it resultaat wurdt jûn yn in masine-lêsbere foarm geskikt foar de monitoring systeem.
  3. Skriuw jo applikaasje boppe op 'e tsduck-bibleteek.

Fansels is opsje 1 de maklikste yn termen fan ynspanning, foaral yn betinken nommen dat tsduck sels skreaun is yn in leech-nivo (troch moderne noarmen) taal (C ++)

In ienfâldige bash-parser + aggregator-prototype liet sjen dat op in 10Mbps-stream en 50% pakketferlies (slimste gefal), it bash-proses 3-4 kear mear CPU konsumearre dan it tsp-proses sels. Dit senario is net akseptabel. Eins in stik fan dit prototype hjirûnder

Noedels op de top

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

Neist in wêzen ûnakseptabel stadich, der binne gjin normale triedden yn bash, bash banen binne aparte prosessen, en ik moast skriuwe de wearde fan missingPackets ien kear in sekonde op 'e kant effekt (by ûntfangst bitrate berjochten dy't komme elke sekonde). As resultaat waard bash allinich litten en waard besletten om in wrapper (parser + aggregator) yn golang te skriuwen. De CPU-konsumpsje fan ferlykbere golang-koade is 4-5 kear minder as it tsp-proses sels. De fersnelling fan 'e wrapper troch it ferfangen fan bash mei golang blykte sawat 16 kear te wêzen en yn' t algemien is it resultaat akseptabel (CPU-overhead mei 25% yn it slimste gefal). De golang boarne triem is te finen hjir.

Run wrapper

Om de wrapper te begjinnen, waard it ienfâldichste tsjinstsjabloan foar systemd makke (hjir). De wrapper sels moat wurde kompilearre yn in binêre triem (gean build tsduck-stat.go) leit yn /opt/tsduck-stat/. Der wurdt oannommen dat jo golang brûke mei stipe foar monotone klok (>=1.9).

Om in eksimplaar fan 'e tsjinst te meitsjen, moatte jo it kommando systemctl enable útfiere [e-post beskerme]:1234 dan rinne mei systemctl start [e-post beskerme]: 1234.

Untdekking fan Zabbix

Om zabbix rinnende tsjinsten te ûntdekken, is it dien groep list generator (discovery.sh), yn it formaat dat nedich is foar Zabbix-ûntdekking, wurdt oannommen dat it op itselde plak leit - yn /opt/tsduck-stat. Om ûntdekking út te fieren fia zabbix-agent, moatte jo tafoegje .conf triem nei de zabbix-agent-konfiguraasjemap om de brûkersparameter ta te foegjen.

Zabbix sjabloan

Sjabloan makke (tsduck_stat_template.xml) befettet de autodiscover regel, item prototypes, grafiken en triggers.

Koarte checklist (goed, wat as immen beslút it te brûken)

  1. Soargje derfoar dat tsp gjin pakketten falle ûnder "ideale" omstannichheden (generator en analysator binne direkt ferbûn), as d'r drippen binne, sjoch paragraaf 2 of de tekst fan it artikel oer dizze saak.
  2. Meitsje tuning de maksimale socket buffer (net.core.rmem_max = 8388608).
  3. Kompilearje tsduck-stat.go (gean bouwe tsduck-stat.go).
  4. Set it tsjinstsjabloan yn /lib/systemd/system.
  5. Start tsjinsten mei systemctl, kontrolearje dat tellers binne begûn te ferskinen (grep "" /dev/shm/tsduck-stat/*). It oantal tsjinsten troch it oantal multicast-streamen. Hjir kinne jo moatte meitsje in rûte nei de multicast groep, miskien útskeakelje rp_filter of meitsje in rûte nei de boarne ip.
  6. Run discovery.sh, soargje derfoar dat it json genereart.
  7. Foegje zabbix agent config ta, start zabbix agent opnij.
  8. Upload it sjabloan nei zabbix, tapasse it op de host dy't wurdt kontrolearre en de zabbix-agent is ynstalleare, wachtsje sawat 5 minuten, sjoch as d'r nije items, grafiken en triggers binne.

resultaat

TSDuck brûke om IP(TS)-streamen te kontrolearjen

Foar de taak om pakketferlies te detektearjen is it hast genôch, teminsten is it better as gjin tafersjoch.

Yndied kinne CC "ferlies" foarkomme by it fusearjen fan fideofragminten (foar safier't ik wit, dit is hoe't ynserts wurde makke by lokale tv-sintra yn 'e Russyske Federaasje, dus sûnder de CC-teller opnij te berekkenjen), dit moat wurde ûnthâlden. Proprietêre oplossings omfetsje dit probleem foar in part troch SCTE-35-labels te detektearjen (as tafoege troch de streamgenerator).

Wat it tafersjoch op transportkwaliteit oanbelanget, is der in tekoart oan jittermonitoring (IAT). TV-apparatuer (is it modulators as einapparaten) hat easken foar dizze parameter en it is net altyd mooglik om de jitbuffer oant ûneinich op te blazen. En jitter kin driuwe as apparatuer mei grutte buffers wurdt brûkt yn transit en QoS is net konfigurearre of net goed ynsteld genôch om sa'n realtime ferkear oer te stjoeren.

Boarne: www.habr.com

Add a comment