Paggamit ng TSDuck upang subaybayan ang mga daloy ng IP(TS).

Ngayon, may mga handa na (proprietary) na solusyon para sa pagsubaybay sa mga daloy ng IP(TS), halimbawa VB ΠΈ iQ, mayroon silang medyo mayamang hanay ng mga function at kadalasan ang malalaking operator na nakikitungo sa mga serbisyo sa TV ay may mga katulad na solusyon. Inilalarawan ng artikulong ito ang isang solusyon batay sa isang open source na proyekto TSDuck, na idinisenyo para sa minimal na kontrol ng mga daloy ng IP(TS) gamit ang CC (continuity counter) counter at bitrate. Ang isang posibleng aplikasyon ay sinusubaybayan ang pagkawala ng mga packet o ang buong daloy sa pamamagitan ng isang naupahang L2 channel (na hindi masusubaybayan nang normal, halimbawa, sa pamamagitan ng pagbabasa ng mga loss counter sa mga pila).

Napakaikling tungkol sa TSDuck

Ang TSDuck ay open source (2-Clause BSD license) software (isang set ng console utilities at library para sa pagbuo ng sarili mong mga utility o plugin) para sa pagmamanipula ng TS stream. Bilang isang input, maaari itong gumana sa IP (multicast/unicast), http, hls, dvb tuners, dektec dvb-asi demodulator, mayroong panloob na TS stream generator at pagbabasa mula sa mga file. Ang output ay maaaring i-record sa isang file, IP (multicast/unicast), hls, dektec dvb-asi at HiDes modulators, mga manlalaro (mplayer, vlc, xine) at drop. Sa pagitan ng input at output, maaari mong paganahin ang iba't ibang mga processor ng trapiko, halimbawa, muling pagmamapa ng mga PID, paggawa ng scrambling/descrambling, pagsusuri ng mga CC counter, pagkalkula ng bitrate at iba pang mga operasyong tipikal para sa mga stream ng TS.

Sa artikulong ito, ang mga IP stream (multicast) ay gagamitin bilang input, bitrate_monitor processors (mula sa pangalan ay malinaw kung ano ito) at continuity (CC counter analysis) na mga processor ang gagamitin. Nang walang anumang mga problema, maaari mong palitan ang IP multicast ng isa pang uri ng input na sinusuportahan ng TSDuck.

Mayroong opisyal na mga build/package TSDuck para sa pinakabagong OS. Walang para sa Debian, ngunit nagawa naming i-compile ang mga ito para sa Debian 8 at Debian 10 nang walang anumang problema.

Susunod, ang bersyon ng TSDuck 3.19-1520 ay ginagamit, ang Linux ay ginagamit bilang OS (ginamit ang debian 10 upang ihanda ang solusyon, ang CentOS 7 ay ginamit para sa aktwal na paggamit)

Inihahanda ang TSDuck at OS

Bago subaybayan ang mga totoong daloy, kailangan mong tiyakin na gumagana nang tama ang TSDuck at ang mga pagbagsak ay hindi mangyayari sa antas ng network card o OS (socket). Ito ay kinakailangan upang hindi mo na kailangang hulaan sa ibang pagkakataon kung saan naganap ang mga patak - sa network o "sa loob ng server." Maaari mong suriin ang mga patak sa antas ng network card gamit ang command na ethtool -S ethX, ang pag-tune ay ginagawa ng parehong ethtool (karaniwan ay kailangan mong dagdagan ang RX buffer (-G) at kung minsan ay hindi paganahin ang ilang mga offload (-K)). Bilang pangkalahatang rekomendasyon, ipinapayong gumamit ng hiwalay na port upang matanggap ang nasuri na trapiko, kung maaari, mababawasan nito ang mga maling positibo dahil sa katotohanan na ang pagbaba ay nangyari nang sabay-sabay sa port ng analyzer dahil sa pagkakaroon ng iba pang trapiko. Kung hindi ito posible (gumagamit ka ng isang mini-computer/NUC na may isang port), kung gayon ito ay lubos na ipinapayong i-configure ang priyoridad ng nasuri na trapiko na may kaugnayan sa iba pa sa device kung saan nakakonekta ang analyzer. Tungkol sa mga virtual na kapaligiran, dito kailangan mong mag-ingat at makahanap ng mga packet drop simula sa pisikal na port at nagtatapos sa application sa loob ng virtual machine.

Pagbuo at pagtanggap ng stream sa loob ng host

Bilang unang hakbang sa paghahanda ng TSDuck, bubuo at tatanggap kami ng trapiko sa loob ng isang host gamit ang netns.

Paghahanda ng kapaligiran:

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

Handa na ang kapaligiran. Ilunsad ang traffic analyzer:

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

kung saan ang "-p 1 -t 1" ay nangangahulugan na kailangan mong kalkulahin ang bitrate bawat segundo at ipakita ang impormasyon tungkol sa bitrate bawat segundo
Naglulunsad kami ng generator ng trapiko na may bilis na 10 Mbit/s:

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

kung saan ang "-p 7 -e" ay nangangahulugan na kailangan mong mag-pack ng 7 TS packet sa 1 IP packet at gawin itong mahirap (-e), i.e. palaging maghintay para sa 7 TS packet mula sa huling processor bago ipadala ang pagbuo ng isang IP packet.

Nagsisimulang ipakita ng analyzer ang mga inaasahang mensahe:

* 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

Ngayon magdagdag tayo ng ilang patak:

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

at lumalabas ang mga mensaheng tulad nito:

* 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 

na inaasahan. Hindi namin pinapagana ang pagkawala ng packet (ip netns exec P iptables -F) at sinusubukang taasan ang bitrate ng generator sa 100 Mbit/s. Ang analyzer ay nag-uulat ng isang bungkos ng mga error sa CC at humigit-kumulang 75 Mbit/s sa halip na 100. Sinusubukan naming malaman kung sino ang dapat sisihin - ang generator ay hindi nakakasunod o ang problema ay wala sa loob nito, upang gawin ito nagsisimula kaming bumuo ng isang nakapirming bilang ng mga packet (700000 TS packet = 100000 IP packets):

# 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

Tulad ng nakikita mo, eksaktong 100000 IP packet ang nabuo (151925460-151825460). Kaya't nalaman namin kung ano ang nangyayari sa analyzer, upang gawin ito, sinusuri namin ang RX counter sa veth1, ito ay mahigpit na katumbas ng TX counter sa veth0, pagkatapos ay tinitingnan namin kung ano ang nangyayari sa antas ng 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 

Dito makikita mo ang bilang ng mga patak = 24355. Sa mga TS packet ito ay 170485 o 24.36% ng 700000, kaya nakikita natin na ang parehong 25% ng nawalang bitrate ay mga patak sa UDP socket. Ang mga pagbagsak sa isang UDP socket ay kadalasang nangyayari dahil sa kakulangan ng buffer, tingnan natin kung ano ang default na laki ng buffer ng socket at ang maximum na laki ng buffer ng socket:

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

Kaya, kung ang mga application ay hindi tahasang humiling ng laki ng buffer, ang mga socket ay nilikha na may 208 KB na buffer, ngunit kung humiling sila ng higit pa, hindi pa rin nila matatanggap ang kanilang hiniling. Dahil sa tsp maaari mong itakda ang laki ng buffer para sa IP input (--buffer-size), hindi namin hawakan ang default na laki ng socket, ngunit itatakda lamang ang maximum na laki ng buffer ng socket at tahasang tukuyin ang laki ng buffer sa pamamagitan ng mga argumento ng 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

Sa ganitong pag-tune ng socket buffer, ang naiulat na bitrate ay tinatayang 100Mbps na ngayon, walang mga CC error.

Batay sa pagkonsumo ng CPU ng tsp application mismo. Tungkol sa isang core i5-4260U CPU @ 1.40GHz, para pag-aralan ang 10Mbit/s na daloy, 3-4% ng CPU ang kakailanganin, 100Mbit/s - 25%, 200Mbit/s - 46%. Kapag nagtatakda ng % packet loss, halos hindi tumataas ang CPU load (ngunit maaaring bumaba).

Sa mas produktibong hardware, posible na bumuo at magsuri ng mga stream na higit sa 1Gb/s nang walang anumang problema.

Pagsubok sa mga totoong network card

Pagkatapos ng pagsubok sa isang pares ng veth, kailangan mong kumuha ng dalawang host o dalawang port ng isang host, ikonekta ang mga port sa isa't isa, patakbuhin ang generator sa isa, at ang analyzer sa pangalawa. Walang mga sorpresa dito, ngunit sa katunayan ang lahat ay nakasalalay sa hardware, mas mahina ito, mas kawili-wili ito dito.

Gamit ang natanggap na data ng monitoring system (Zabbix)

tsp ay walang anumang machine-readable na API tulad ng SNMP o katulad. Ang mga mensahe ng CC ay kailangang pinagsama-sama ng hindi bababa sa 1 segundo sa isang pagkakataon (na may mataas na porsyento ng pagkawala ng packet, maaaring magkaroon ng daan-daang/libo/sampu-sampung libo bawat segundo, depende sa bitrate).

Kaya, upang makatipid ng impormasyon at gumuhit ng mga graph para sa mga error sa CC at bitrate at gumawa ng ilang uri ng mga aksidente, maaaring mayroong mga sumusunod na opsyon:

  1. I-parse at pagsama-samahin (sa pamamagitan ng CC) ang tsp output, i.e. ibahin ito sa nais na anyo.
  2. Idagdag ang tsp mismo at/o ang bitrate_monitor at continuity processor na mga plugin upang ang resulta ay output sa isang form na nababasa ng makina na angkop para sa monitoring system.
  3. Isulat ang iyong aplikasyon sa ibabaw ng tsduck library.

Malinaw, sa mga tuntunin ng mga gastos sa paggawa, ang opsyon 1 ay ang pinakasimpleng, lalo na kung isasaalang-alang na ang tsduck mismo ay nakasulat sa isang mababang antas (ayon sa modernong mga pamantayan) na wika (C++)

Ang isang simpleng prototype ng isang parser + aggregator sa bash ay nagpakita na sa daloy ng 10 Mbit/s at 50% packet loss (pinakamasamang kaso), ang proseso ng bash ay kumonsumo ng 3-4 na beses na mas maraming CPU kaysa sa mismong proseso ng tsp. Ang senaryo na ito ay hindi katanggap-tanggap. Sa totoo lang ay nasa ibaba ang isang piraso ng prototype na ito

Noodles sa basha

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

Bilang karagdagan sa katotohanan na ito ay gumagana nang hindi katanggap-tanggap na mabagal, walang mga normal na thread sa bash, ang mga trabaho sa bash ay mga independiyenteng proseso at kinailangan kong isulat ang nawawalangPackets na halaga isang beses sa isang segundo sa side effect (kapag tumatanggap ng mga bitrate na mensahe na dumarating bawat segundo). Bilang isang resulta, ang bash ay naiwang mag-isa at napagpasyahan na magsulat ng isang wrapper (parser + aggregator) sa golang. Ang pagkonsumo ng CPU ng katulad na code sa golang ay 4-5 beses na mas mababa kaysa sa mismong proseso ng tsp. Ang acceleration ng wrapper sa pamamagitan ng pagpapalit ng bash ng golang ay humigit-kumulang 16 na beses at sa pangkalahatan ay katanggap-tanggap ang resulta (CPU overhead ng 25% sa pinakamasamang kaso). Ang golang source file ay matatagpuan dito.

Paglulunsad ng wrapper

Upang ilunsad ang wrapper, isang simpleng template ng serbisyo para sa systemd ang ginawa (dito). Ipinapalagay na ang wrapper mismo ay pinagsama-sama sa isang binary file (go build tsduck-stat.go), na matatagpuan sa /opt/tsduck-stat/. Ipinapalagay na ang golang ay ginagamit na may suporta sa monotonic na orasan (>=1.9).

Upang lumikha ng isang halimbawa ng serbisyo kailangan mong patakbuhin ang systemctl enable command [protektado ng email]:1234, pagkatapos ay tumakbo gamit ang systemctl start [protektado ng email]: 1234.

Pagtuklas mula sa Zabbix

Upang ang zabbix ay makatuklas ng mga tumatakbong serbisyo, generator ng listahan ng grupo (discovery.sh), sa format na kinakailangan para sa pagtuklas ng Zabbix, ipinapalagay na ito ay matatagpuan sa parehong lugar - sa /opt/tsduck-stat. Upang patakbuhin ang pagtuklas sa pamamagitan ng zabbix-agent, kailangan mong magdagdag .conf file sa direktoryo na may mga pagsasaayos ng zabbix-agent upang magdagdag ng parameter ng user.

Template ng Zabbix

Nagawa ang template (tsduck_stat_template.xml) ay naglalaman ng autodiscovery na panuntunan, elemento, graph, at trigger na mga prototype.

Isang maikling checklist (paano kung may magpasya na gamitin ito)

  1. Siguraduhin na ang tsp ay hindi nag-drop ng mga packet sa ilalim ng "ideal" na mga kondisyon (ang generator at analyzer ay direktang konektado), kung may mga patak, tingnan ang punto 2 o ang teksto ng artikulo sa paksang ito.
  2. Gumawa ng pag-tune ng maximum na socket buffer (net.core.rmem_max=8388608).
  3. I-compile ang tsduck-stat.go (bumuo ng tsduck-stat.go).
  4. Ilagay ang template ng serbisyo sa /lib/systemd/system.
  5. Simulan ang mga serbisyo gamit ang systemctl, tingnan kung nagsimula nang lumitaw ang mga counter (grep "" /dev/shm/tsduck-stat/*). Bilang ng mga serbisyo ayon sa bilang ng mga multicast stream. Dito maaaring kailanganin mong lumikha ng ruta patungo sa multicast group, marahil ay huwag paganahin ang rp_filter o lumikha ng ruta patungo sa source ip.
  6. Patakbuhin ang discovery.sh, tiyaking bumubuo ito ng json.
  7. Ilagay ang zabbix agent config, i-restart ang zabbix agent.
  8. I-upload ang template sa zabbix, ilapat ito sa host kung saan isinasagawa ang pagsubaybay at naka-install ang zabbix-agent, maghintay ng mga 5 minuto, tingnan na lumitaw ang mga bagong elemento ng data, graph at trigger.

Resulta

Paggamit ng TSDuck upang subaybayan ang mga daloy ng IP(TS).

Para sa gawain ng pagtukoy ng pagkawala ng packet, ito ay halos sapat, hindi bababa sa ito ay mas mahusay kaysa sa walang pagsubaybay.

Sa katunayan, ang "pagkalugi" ng CC ay maaaring mangyari kapag nag-splice ng mga fragment ng video (sa pagkakaalam ko, ito ay kung paano ginawa ang mga pagsingit sa mga lokal na sentro ng telebisyon sa Russian Federation, i.e. nang hindi muling kinakalkula ang CC counter), dapat itong alalahanin. Sa pagmamay-ari na mga solusyon, ang problemang ito ay bahagyang naiiwasan sa pamamagitan ng pag-detect ng mga tag ng SCTE-35 (kung idinagdag sila ng stream generator).

Mula sa punto ng view ng pagsubaybay sa kalidad ng transportasyon, ang jitter monitoring (IAT) ay hindi sapat, dahil Ang mga kagamitan sa TV (modulators man o end device) ay may mga kinakailangan para sa parameter na ito at hindi laging posible na palakihin ang jitbuffer nang walang katapusan. At ang jitter ay maaaring lumutang kapag ang transit ay gumagamit ng kagamitan na may malalaking buffer at ang QoS ay hindi na-configure o hindi sapat na na-configure upang maihatid ang naturang realtime na trapiko.

Pinagmulan: www.habr.com

Magdagdag ng komento