Utilizà TSDuck per Monitorà IP (TS) Streams

Oghje, ci sò suluzioni pronti (proprietarii) per surviglià i flussi IP (TS), per esempiu VB и iQ, anu un inseme abbastanza riccu di funzioni è di solitu grandi operatori chì trattanu di servizii TV anu tali suluzioni. Questu articulu descrive una suluzione basatu annantu à un prughjettu open source TSDuck, cuncepitu per un cuntrollu minimu di flussi IP (TS) da CC (contatore di continuità) contatore è bitrate. Una applicazione pussibule hè di cuntrullà a perdita di pacchetti o u flussu sanu attraversu un canali L2 affittu (chì ùn pò micca esse monitoratu nurmale, per esempiu, leghjendu i contatori di perdita in fila).

Moltu brevemente nantu à TSduck

TSDuck hè un software open source (licenza BSD 2-Clause) (un inseme di utilità di cunsola è una biblioteca per sviluppà utilità o plugins persunalizati) per manipulà i flussi TS. Cum'è un input, pò travaglià cù IP (multicast/unicast), http, hls, dvb tuners, dektec dvb-asi demodulator, ci hè un generatore TS-stream internu è leghje da i schedari. L'output pò esse scrittu à un schedariu, IP (multicast/unicast), hls, dektec dvb-asi è modulatori HiDes, players (mplayer, vlc, xine) è drop. Diversi processori di trafficu ponu esse inclusi trà l'input è l'output, per esempiu, remapping PID, scrambling / descrambling, analisi di contatore CC, calculu di bitrate, è altre operazioni tipiche per i flussi TS.

In questu articulu, i flussi IP (multicast) seranu utilizati com'è input, i prucessori bitrate_monitor (da u nome hè chjaru ciò chì hè) è a continuità (analisi di i contatori CC) sò usati. Pudete facilmente rimpiazzà IP multicast cù un altru tipu di input supportatu da TSduck.

Disponibile builds / pacchetti ufficiali TSduck per a maiò parte di i sistemi operativi attuali. Ùn sò micca dispunibuli per Debian, ma avemu riesciutu à custruisce elli sottu Debian 8 è Debian 10 senza prublemi.

In seguitu, a versione TSDuck 3.19-1520 hè aduprata, Linux hè utilizatu cum'è OS (debian 10 hè stata utilizata per preparà a suluzione, CentOS 7 hè stata utilizata per un usu veru)

Preparazione di TSduck è OS

Prima di monitorà i flussi reali, avete bisognu di assicurà chì TSDuck funziona bè è ùn ci sò micca gocce à u livellu di a carta di rete o di u SO (socket). Questu hè necessariu per ùn guessà più tardi induve e gocce sò accadute - in a reta o "dentro u servitore". Pudete cuntrollà i gocce à u nivellu di a carta di rete cù u cumandimu ethtool -S ethX, a sintonizazione hè fatta da u listessu ethtool (di solitu, avete bisognu di aumentà u buffer RX (-G) è qualchì volta disattiveghjanu qualchi offloads (-K)). Cum'è una ricunniscenza generale, pò esse cunsigliatu di utilizà un portu separatu per riceve u trafficu analizatu, se pussibule, questu minimize falsi pusitivi assuciati cù u fattu chì a goccia hè accaduta esattamente nantu à u portu di l'analizzatore per a presenza di un altru trafficu. Se questu ùn hè micca pussibule (un mini-computer / NUC cù un portu hè utilizatu), allora hè assai desideratu di stabilisce a priorità di u trafficu analizatu in relazione à u restu nantu à u dispusitivu à quale l'analizzatore hè cunnessu. In quantu à l'ambienti virtuali, quì ci vole à esse attentu è esse capace di truvà gocce di pacchetti partendu da un portu fisicu è finiscinu cù una applicazione in una macchina virtuale.

Generazione è ricezione di un flussu in l'ospite

Cum'è un primu passu in a preparazione di TSduck, genereremu è riceverà trafficu in un unicu host utilizendu netns.

Preparazione di l'ambiente:

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

L'ambiente hè prontu. Cuminciamu l'analizzatore di trafficu:

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

induve "-p 1 -t 1" significa chì avete bisognu di calculà u bitrate ogni secondu è visualizà infurmazioni nantu à u bitrate ogni secondu
Cuminciamu u generatore di trafficu cù una velocità di 10 Mbps:

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

induve "-p 7 -e" significa chì avete bisognu di imballà 7 pacchetti TS in 1 pacchettu IP è fate dura (-e), i.e. aspetta sempre 7 pacchetti TS da l'ultimu processatore prima di mandà un pacchettu IP.

L'analizzatore cumencia à emette i missaghji previsti:

* 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

Avà aghjunghje alcune gocce:

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

è missaghji cum'è questu appariscenu:

* 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 

chì hè aspittatu. Disattivate a perdita di pacchetti (ip netns exec P iptables -F) è pruvate d'aumentà u bitrate di u generatore à 100 Mbps. L'analizzatore informa una mansa di errori CC è circa 75 Mbps invece di 100. Avemu pruvatu à capisce quale hè a culpa - u generatore ùn hà micca tempu o u prublema ùn hè micca in questu, per questu avemu principiatu à generà un numeru fissu di pacchetti (700000 pacchetti TS = 100000 pacchetti IP):

# 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

Comu pudete vede, esattamente 100000 pacchetti IP sò stati generati (151925460-151825460). Allora scopremu ciò chì succede cù l'analizzatore, per questu cuntrollemu cù u contatore RX in veth1, hè strettamente uguale à u contatore TX in veth0, allora guardemu ciò chì succede à u nivellu di socket:

# 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 

Quì pudete vede u numeru di gocce = 24355. In i pacchetti TS, questu hè 170485 o 24.36% di 700000, cusì vedemu chì quelli stessi 25% di u bitrate persu sò gocce in u socket udp. Gocce in un socket UDP sò generalmente per una mancanza di buffer, fighjate à a dimensione di buffer di socket predeterminata è a dimensione massima di buffer di socket:

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

Cusì, se l'applicazioni ùn dumandanu micca esplicitamente una dimensione di buffer, i sockets sò creati cù un buffer di 208 KB, ma se dumandanu più, ùn riceveranu micca ciò chì era dumandatu. Siccomu pudete stabilisce a dimensione di u buffer in tsp per l'input IP (-buffer-size), ùn avemu micca toccu a dimensione di u socket predeterminatu, ma solu stabilisce a dimensione massima di u buffer di u socket è specificà a dimensione di u buffer esplicitamente attraversu l'argumenti tsp:

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

Cù sta sintonizazione di u buffer di socket, avà u bitrate rappurtatu hè di circa 100Mbps, ùn ci sò micca errori CC.

Sicondu u cunsumu CPU di l'applicazione tsp stessu. Relativamente à un core i5-4260U CPU @ 1.40GHz, l'analisi di flussu 10Mbps necessitarà 3-4% CPU, 100Mbps - 25%, 200Mbps - 46%. Quandu stabilisce u % Packet Loss, a carica nantu à u CPU praticamente ùn aumenta (ma pò diminuite).

Nantu à un hardware più produtivu, era pussibule generà è analizà flussi di più di 1 Gb / s senza prublemi.

Pruvate nantu à e carte di rete reale

Dopu à pruvà à un paru veth, vi tocca à piglià dui ospiti o dui porti di un òspite, cunnette i porti à l'altri, principià u generatore nantu à unu, è l'analizzatore nantu à u sicondu. Ùn ci era micca sorprese quì, ma in fatti tuttu dipende di u ferru, u più debule, u più interessante serà quì.

Utilizà i dati ricevuti da u sistema di monitoraghju (Zabbix)

tsp ùn hà micca alcuna API leggibile da a macchina cum'è SNMP o simili. I missaghji CC devenu esse aggregati per almenu 1 segundu (cù un altu percentualità di perdita di pacchetti, pò esse centinaie / millaie / decine di millai per seconda, secondu u bitrate).

Cusì, per salvà l'infurmazioni è disegnà grafici per errori CC è bitrate è fà qualchì tipu d'accidenti, ponu esse l'opzioni seguenti:

  1. Parse è aggregate (da CC) l'output di tsp, i.e. cunvertisce à a forma desiderata.
  2. Finisci tsp stessu è / o plugins di prucessori bitrate_monitor è continuità per chì u risultatu hè datu in una forma leggibile in macchina adattata per u sistema di surviglianza.
  3. Scrivite a vostra applicazione nantu à a biblioteca tsduck.

Ovviamente, l'opzione 1 hè a più faciule in termini di sforzu, soprattuttu cunsiderendu chì tsduck stessu hè scrittu in una lingua di livellu bassu (da i standard muderni) (C ++)

Un prototipu bash parser + aggregator simplice hà dimustratu chì in un flussu di 10Mbps è 50% di perdita di pacchetti (u peghju casu), u prucessu bash hà cunsumatu 3-4 volte più CPU cà u prucessu tsp stessu. Stu scenariu hè inacceptable. In realtà un pezzu di stu prototipu quì sottu

Noodles nantu à a cima

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

In più di esse inaccettabilmente lentu, ùn ci sò micca fili nurmali in bash, i travaglii di bash sò prucessi separati è aghju avutu à scrive u valore di missingPackets una volta à seconda nantu à l'effettu side (quandu riceve missaghji di bitrate chì venenu ogni secondu). In u risultatu, bash hè stata lasciata sola è hè statu decisu di scrive un wrapper (parser + aggregator) in golang. U cunsumu di CPU di codice golang simili hè 4-5 volte menu di u prucessu tsp stessu. L'accelerazione di u wrapper per via di a sustituzione di bash cù golang hè stata circa 16 volte è in generale u risultatu hè accettabile (CPU overhead da 25% in u peghju casu). U schedariu fonte golang hè situatu ccà.

Run wrapper

Per inizià u wrapper, u mudellu di serviziu più simplice per systemd hè statu fattu (ccà). U wrapper stessu hè suppostu esse cumpilatu in un schedariu binariu (andate à custruisce tsduck-stat.go) situatu in /opt/tsduck-stat/. Si assume chì avete aduprà golang cù supportu per u clock monotonicu (>=1.9).

Per creà una istanza di u serviziu, avete bisognu di eseguisce u cumandimu systemctl enable [email prutettu]: 1234 poi eseguite cù systemctl start [email prutettu]: 1234.

Scoperta da Zabbix

Per fà chì zabbix possa scopre i servizii in esecuzione, hè fattu generatore di lista di gruppi (discovery.sh), in u formatu necessariu per a scuperta Zabbix, si assume chì si trova in u stessu locu - in /opt/tsduck-stat. Per eseguisce a scuperta via zabbix-agent, avete bisognu di aghjunghje schedariu .conf à u repertoriu di cunfigurazione zabbix-agent per aghjunghje u paràmetru d'utilizatore.

U mudellu Zabbix

U mudellu creatu (tsduck_stat_template.xml) cuntene a regula di autodiscover, prototipi di l'articuli, grafici è triggers.

Breve lista di cuntrollu (bene, chì se qualchissia decide di usà)

  1. Assicuratevi chì tsp ùn sguassate micca pacchetti in cundizioni "ideali" (generatore è analizatore sò cunnessi direttamente), se ci sò gocce, vede u paràgrafu 2 o u testu di l'articulu nantu à sta materia.
  2. Fate tuning u buffer di socket massimu (net.core.rmem_max=8388608).
  3. Cumpilà tsduck-stat.go (andà à custruisce tsduck-stat.go).
  4. Mettite u mudellu di serviziu in /lib/systemd/system.
  5. Cumincià i servizii cù systemctl, verificate chì i cuntatori anu cuminciatu à apparisce (grep "" /dev/shm/tsduck-stat/*). U numeru di servizii da u numeru di flussi multicast. Quì pudete bisognu di creà una strada à u gruppu multicast, forsi disattivà rp_filter o crea una strada à l'ip di fonte.
  6. Eseguite discovery.sh, assicuratevi chì genera json.
  7. Aghjunghjite a cunfigurazione di l'agente zabbix, riavvia l'agente zabbix.
  8. Caricate u mudellu à zabbix, appricà à l'ospite chì hè monitoratu è u zabbix-agent hè stallatu, aspettate circa 5 minuti, vede s'ellu ci sò novi elementi, grafici è triggers.

risultatu

Utilizà TSDuck per Monitorà IP (TS) Streams

Per u compitu di detectà a perdita di pacchettu, hè quasi abbastanza, almenu hè megliu cà senza surviglianza.

Infatti, "perdite" di CC pò accade quandu si fusione frammenti di video (finu à ciò chì sò, hè cusì chì l'inserzioni sò fatti in i centri TV lucali in a Federazione Russa, vale à dì senza ricalculare u cuntatore CC), questu deve esse ricurdatu. Soluzioni prupietarie parzialmente circundanu stu prublema detectendu etichette SCTE-35 (se aghjunte da u generatore di flussu).

In quantu à u monitoraghju di a qualità di trasportu, ci hè una mancanza di monitorizazione di jitter (IAT). L'equipaggiu di TV (sia modulatori o dispositi finali) hà esigenze per questu paràmetru è ùn hè micca sempre pussibule di gonfià u jitbuffer à l'infinitu. È u jitter pò flutterà quandu l'equipaggiu cù grande buffer hè utilizatu in transitu è ​​QoS ùn hè micca cunfiguratu o micca bè cunfiguratu abbastanza per trasmette stu trafficu in tempu reale.

Source: www.habr.com

Add a comment