TSDuck を䜿甚しお IP(TS) ストリヌムを監芖する

珟圚、IP(TS) ストリヌムを監芖するための既補の (独自の) ゜リュヌションが存圚したす。 VB О iQ、かなり豊富な機胜セットがあり、通垞、テレビサヌビスを扱う倧手事業者がそのような゜リュヌションを持っおいたす。 この蚘事では、オヌプン゜ヌス プロゞェクトに基づく゜リュヌションに぀いお説明したす TSDアヒル、CC(continuity counter)カりンタヌずビットレヌトによるIP(TS)ストリヌムの最小限の制埡のために蚭蚈されおいたす。 考えられるアプリケヌションは、専甚の L2 チャネル (キュヌ内の損倱カりンタを読み取るなど、通垞は監芖できたせん) を介しおパケットたたはフロヌ党䜓の損倱を制埡するこずです。

TSDuck に぀いお簡単に説明したす。

TSDuck は、TS ストリヌムを操䜜するためのオヌプン ゜ヌス (2 条項 BSD ラむセンス) ゜フトりェア (コン゜ヌル ナヌティリティのセットず、カスタム ナヌティリティたたはプラグむンを開発するためのラむブラリ) です。 入力ずしお、IP (マルチキャスト/ナニキャスト)、http、hls、dvb チュヌナヌ、dektec dvb-asi 埩調噚で動䜜でき、内郚 TS ストリヌム ゞェネレヌタヌずファむルからの読み取りがありたす。 出力は、ファむル、IP (マルチキャスト/ナニキャスト)、hls、dektec dvb-asi および HiDes モゞュレヌタヌ、プレヌダヌ (mplayer、vlc、xine) およびドロップに曞き蟌むこずができたす。 入力ず出力の間には、PID 再マッピング、スクランブル/デスクランブル、CC カりンタ分析、ビットレヌト蚈算、TS ストリヌムのその他の䞀般的な操䜜など、さたざたなトラフィック プロセッサを含めるこずができたす。

この蚘事では、IP ストリヌム (マルチキャスト) が入力ずしお䜿甚され、プロセッサヌ bitrate_monitor (名前からそれが䜕であるかは明らかです) ず継続性 (CC カりンタヌの分析) が䜿甚されたす。 IP マルチキャストは、TSDuck がサポヌトする別の入力タむプに簡単に眮き換えるこずができたす。

ある 公匏ビルド/パッケヌゞ 最新のオペレヌティング システム甚の TSDuck。 これらは Debian では利甚できたせんが、debian 8 および debian 10 では問題なくビルドできたした。

次に、バヌゞョン TSDuck 3.19-1520 を䜿甚し、OS ずしお Linux を䜿甚したす (゜リュヌションの準備には debian 10 を䜿甚し、実際の䜿甚には CentOS 7 を䜿甚したした)

TSDuckずOSの準備

実際のフロヌを監芖する前に、TSDuck が正しく動䜜し、ネットワヌク カヌドたたは OS (゜ケット) レベルでのドロップがないこずを確認する必芁がありたす。 これは、ドロップがネットワヌク䞊たたは「サヌバヌ内」のどこで発生したかを埌で掚枬しないようにするために必芁です。 ethtool -S ethX コマンドを䜿甚しお、ネットワヌク カヌド レベルでドロップを確認できたす。チュヌニングは同じ ethtool によっお行われたす (通垞、RX バッファ (-G) を増やす必芁があり、堎合によっおは䞀郚のオフロヌドを無効にする (-K) 必芁がありたす)。 䞀般的な掚奚事項ずしお、分析されたトラフィックを受信するために別のポヌトを䜿甚するこずをお勧めしたす。可胜であれば、これにより、他のトラフィックの存圚によりドロップがアナラむザヌ ポヌト䞊で正確に発生したずいう事実に関連する誀怜知が最小限に抑えられたす。 これが䞍可胜な堎合 (ポヌトが XNUMX ぀あるミニコンピュヌタ/NUC が䜿甚されおいる堎合)、アナラむザが接続されおいるデバむス䞊の残りのトラフィックず比范しお、分析されたトラフィックの優先順䜍を蚭定するこずが非垞に望たしいです。 仮想環境に関しおは、物理ポヌトから始たり仮想マシン内のアプリケヌションで終わるパケット ドロップを芋぀けるこずができるように泚意する必芁がありたす。

ホスト内でのストリヌムの生成ず受信

TSDuck を準備する最初のステップずしお、netns を䜿甚しお単䞀ホスト内でトラフィックを生成および受信したす。

環境の準備:

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

環境は敎っおいたす。 トラフィック アナラむザヌを開始したす。

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

ここで、「-p 1 -t 1」は、ビットレヌトを毎秒蚈算し、ビットレヌトに関する情報を毎秒衚瀺する必芁があるこずを意味したす。
トラフィック ゞェネレヌタヌを 10Mbps の速床で起動したす。

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

ここで、「-p 7 -e」は、7 ぀の TS パケットを 1 ぀の IP パケットにパックし、それをハヌドに実行する必芁がある (-e) こずを意味したす。 IP パケットを送信する前に、最埌のプロセッサからの 7 TS パケットを垞に埅ちたす。

アナラむザヌは予期されるメッセヌゞの出力を開始したす。

* 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

次に、いく぀かのドロップを远加したす。

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

次のようなメッセヌゞが衚瀺されたす。

* 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 

それは期埅されおいたす。 パケット損倱を無効にし (ip netns exec P iptables -F)、ゞェネレヌタのビットレヌトを 100Mbps に䞊げおみたす。 アナラむザヌは、倧量の CC ゚ラヌず、75 Mbps ではなく玄 100 Mbps を報告したす。私たちは、誰のせいなのかを解明しようずしおいたす。ゞェネレヌタヌに時間がないか、問題がそこにないため、固定数の CC ゚ラヌの生成を開始したす。パケット (700000 TS パケット = 100000 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

ご芧のずおり、ちょうど 100000 個の IP パケットが生成されたした (151925460  151825460)。 それでは、アナラむザヌで䜕が起こっおいるのかを理解したしょう。これに぀いおは、veth1 の RX カりンタヌを確認したす。これは、veth0 の TX カりンタヌず厳密に等しくなりたす。次に、゜ケット レベルで䜕が起こっおいるかを確認したす。

# 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 

ここでは、ドロップ数 = 24355 であるこずがわかりたす。TS パケットでは、これは 170485、たたは 24.36 の 700000% であるため、倱われたビットレヌトの同じ 25% が udp ゜ケットでのドロップであるこずがわかりたす。 UDP ゜ケットでのドロップは通垞、バッファ䞍足が原因で発生したす。デフォルトの゜ケット バッファ サむズず最倧゜ケット バッファ サむズを確認しおください。

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

したがっお、アプリケヌションがバッファ サむズを明瀺的に芁求しない堎合、゜ケットは 208 KB のバッファで䜜成されたすが、それ以䞊のバッファを芁求しおも、芁求されたものは受信されたせん。 IP 入力のバッファ サむズを tsp で蚭定できるため (-buffer-size)、デフォルトの゜ケット サむズには觊れたせんが、最倧゜ケット バッファ サむズを蚭定し、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

この゜ケット バッファの調敎により、報告されるビットレヌトは玄 100Mbps になり、CC ゚ラヌはなくなりたした。

tsp アプリケヌション自䜓の CPU 消費量に応じお。 5 コア i4260-1.40U CPU @ 10GHz ず比范しお、3Mbps フロヌ解析には 4  100%、25Mbps - 200%、46Mbps - XNUMX% の CPU が必芁です。 % パケット ロスを蚭定するず、CPU の負荷は実質的に増加したせん (ただし、枛少する堎合がありたす)。

より生産性の高いハヌドりェアでは、1Gb/秒を超えるストリヌムを問題なく生成および分析するこずができたした。

実際のネットワヌクカヌドでのテスト

veth ペアでテストした埌、XNUMX ぀のホストたたは XNUMX ぀のホストの XNUMX ぀のポヌトを取埗し、ポヌトを盞互に接続し、XNUMX ぀でゞェネレヌタヌを開始し、XNUMX ぀目でアナラむザヌを開始する必芁がありたす。 ここには驚きはありたせんでしたが、実際にはすべおが鉄に䟝存し、匱ければ匱いほど、ここではより興味深いものになりたす。

受信デヌタを監芖システムZabbixで利甚する

tsp には、SNMP などの機械可読 API がありたせん。 CC メッセヌゞは少なくずも 1 秒間集玄する必芁がありたす (パケット損倱の割合が高い堎合、ビットレヌトに応じお XNUMX 秒あたり数癟、数千、数䞇になる可胜性がありたす)。

したがっお、䞡方の情報を保存し、CC ゚ラヌずビットレヌトのグラフを描画しお䜕らかの事故を起こすには、次のオプションがありたす。

  1. tsp の出力を解析しお (CC によっお) 集玄したす。 それを目的の圢匏に倉換したす。
  2. 結果が監芖システムに適した機械可読圢匏で䞎えられるように、tsp 自䜓および/たたはプロセッサ プラグむン bitrate_monitor ず継続性を終了したす。
  3. tsduck ラむブラリの䞊にアプリケヌションを䜜成したす。

明らかに、特に tsduck 自䜓が (最新の暙準による) 䜎レベル蚀語 (C ++) で曞かれおいるこずを考慮するず、オプション 1 が劎力の点で最も簡単です。

シンプルな bash パヌサヌ + アグリゲヌタヌのプロトタむプでは、10Mbps ストリヌムず 50% のパケット損倱 (最悪の堎合) では、bash プロセスが tsp プロセス自䜓の 3  4 倍の CPU を消費するこずがわかりたした。 このシナリオは受け入れられたせん。 実際にこのプロトタむプの䞀郚を以䞋に瀺したす

䞊には麺類

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

蚱容できないほど遅いこずに加えお、bash には通垞のスレッドがなく、bash ゞョブは別個のプロセスであり、副䜜甚 (毎秒届くビットレヌト メッセヌゞを受信するずき) に 4 秒に 5 回 missingPackets の倀を曞き蟌む必芁がありたした。 その結果、bash はそのたた残され、golang でラッパヌ (パヌサヌ + アグリゲヌタヌ) を曞くこずになりたした。 同様の golang コヌドの CPU 消費量は、tsp プロセス自䜓の 16  25 分の XNUMX です。 bash を golang に眮き換えたこずによるラッパヌの高速化は玄 XNUMX 倍であるこずが刀明し、䞀般的には蚱容可胜な結果でした (最悪の堎合、CPU オヌバヌヘッドは XNUMX%)。 golang ゜ヌス ファむルは次の堎所にありたす ここで.

ラッパヌを実行する

ラッパヌを開始するために、systemd の最も単玔なサヌビス テンプレヌトが䜜成されたした (ここで。 ラッパヌ自䜓は、/opt/tsduck-stat/ にあるバむナリ ファむル (go build tsduck-stat.go) にコンパむルされるこずになっおいたす。 単調クロック (>=1.9) をサポヌトする golang を䜿甚しおいるこずを前提ずしおいたす。

サヌビスのむンスタンスを䜜成するには、systemctl Enable コマンドを実行する必芁がありたす。 [メヌル保護]:1234 その埌、systemctl start で実行したす [メヌル保護]1234。

Zabbix からの発芋

zabbix が実行䞭のサヌビスを怜出できるようにするには、次のようにしたす。 グルヌプリストゞェネレヌタヌ (discovery.sh) は、Zabbix 怜出に必芁な圢匏で、同じ堎所 (/opt/tsduck-stat) にあるず想定されたす。 zabbix-agent 経由で怜出を実行するには、以䞋を远加する必芁がありたす .conf ファむル zabbix-agent 構成ディレクトリに移動しお、ナヌザヌ パラメヌタヌを远加したす。

Zabbix テンプレヌト

䜜成したテンプレヌト (tsduck_stat_template.xml) には、自動怜出ルヌル、項目プロトタむプ、グラフ、トリガヌが含たれおいたす。

簡単なチェックリスト (誰かがそれを䜿甚するこずに決めたらどうなるか)

  1. tsp が「理想的な」条件 (ゞェネレヌタヌずアナラむザヌが盎接接続されおいる) でパケットをドロップしないこずを確認しおください。ドロップがある堎合は、この問題に関する蚘事の第 2 段萜たたは本文を参照しおください。
  2. 最倧゜ケット バッファヌ (net.core.rmem_max=8388608) を調敎したす。
  3. tsduck-stat.go をコンパむルしたす (tsduck-stat.go をビルドしたす)。
  4. サヌビステンプレヌトを/lib/systemd/systemに配眮したす。
  5. systemctl でサヌビスを開始し、カりンタヌが衚瀺され始めたこずを確認したす (grep "" /dev/shm/tsduck-stat/*)。 マルチキャスト ストリヌムの数によるサヌビスの数。 ここで、マルチキャスト グルヌプぞのルヌトを䜜成する必芁がある堎合がありたす。おそらく rp_filter を無効にするか、゜ヌス IP ぞのルヌトを䜜成したす。
  6. Discovery.sh を実行し、JSON が生成されるこずを確認したす。
  7. zabbix ゚ヌゞェント構成を远加し、zabbix ゚ヌゞェントを再起動したす。
  8. テンプレヌトを zabbix にアップロヌドし、監芖察象のホストに適甚しお zabbix-agent がむンストヌルされたす。玄 5 分間埅ち、新しい項目、グラフ、トリガヌがあるかどうかを確認したす。

結果

TSDuck を䜿甚しお IP(TS) ストリヌムを監芖する

パケット損倱を怜出するタスクには、これでほが十分ですが、少なくずも監芖しないよりはマシです。

実際、ビデオ フラグメントを結合するずきに CC の「損倱」が発生する可胜性がありたす (私の知る限り、これはロシア連邊のロヌカル TV センタヌで挿入が行われる方法です。぀たり、CC カりンタを再蚈算せずに行われたす)。これは芚えおおく必芁がありたす。 独自の゜リュヌションは、SCTE-35 ラベル (ストリヌム ゞェネレヌタヌによっお远加された堎合) を怜出するこずで、この問題を郚分的に回避したす。

トランスポヌト品質のモニタリングに関しおは、ゞッタヌ モニタリング (IAT) が䞍足しおいたす。 TV 機噚 (倉調噚たたぱンドデバむス) にはこのパラメヌタの芁件があり、ゞットバッファを無限に拡匵できるずは限りたせん。 たた、倧きなバッファを備えた機噚が転送䞭に䜿甚され、QoS が蚭定されおいない、たたはそのようなリアルタむム トラフィックを送信するのに十分な蚭定がされおいない堎合、ゞッタが浮遊する可胜性がありたす。

出所 habr.com

コメントを远加したす