Използване на TSDuck за наблюдение на IP(TS) потоци

Днес има готови (собствени) решения за наблюдение на IP(TS) потоци, напр. VB и iQ, те имат доста богат набор от функции и обикновено големите оператори, занимаващи се с телевизионни услуги, имат такива решения. Тази статия описва решение, базирано на проект с отворен код TSDuck, проектиран за минимален контрол на IP(TS) потоци чрез CC (брояч на непрекъснатост) брояч и битрейт. Възможно приложение е да се контролира загубата на пакети или целия поток през нает L2 канал (който не може да се наблюдава нормално, например чрез четене на броячи на загуби в опашки).

Много накратко за TSDuck

TSDuck е софтуер с отворен код (2-Clause BSD лиценз) (набор от конзолни помощни програми и библиотека за разработване на персонализирани помощни програми или добавки) за манипулиране на TS потоци. Като вход може да работи с IP (multicast/unicast), http, hls, dvb тунери, dektec dvb-asi демодулатор, има вътрешен TS-stream генератор и четене от файлове. Изходът може да бъде запис във файл, IP (multicast/unicast), модулатори hls, dektec dvb-asi и HiDes, плейъри (mplayer, vlc, xine) и drop. Различни процесори за трафик могат да бъдат включени между входа и изхода, например, пренасочване на PID, разбъркване / декодиране, анализ на CC брояч, изчисляване на битрейт и други типични операции за TS потоци.

В тази статия като вход ще се използват IP потоци (мултикаст), процесорите bitrate_monitor (от името е ясно какво е) и непрекъснатост (анализ на CC броячи). Можете лесно да замените IP мултикаст с друг тип вход, поддържан от TSDuck.

Има официални компилации/пакети TSDuck за повечето текущи операционни системи. Те не са налични за Debian, но успяхме да ги изградим под debian 8 и debian 10 без никакви проблеми.

След това се използва версия TSDuck 3.19-1520, Linux се използва като ОС (debian 10 е използван за подготовка на решението, CentOS 7 е използван за реална употреба)

Подготовка на TSDuck и OS

Преди да наблюдавате реални потоци, трябва да се уверите, че TSDuck работи правилно и няма спадове на ниво мрежова карта или OS (сокет). Това е необходимо, за да не гадаете по-късно къде са настъпили капките - в мрежата или „вътре в сървъра“. Можете да проверите паданията на ниво мрежова карта с командата ethtool -S ethX, настройката се извършва от същия ethtool (обикновено трябва да увеличите RX буфера (-G) и понякога да деактивирате някои разтоварвания (-K)). Като обща препоръка може да се препоръча използването на отделен порт за получаване на анализирания трафик, ако е възможно, това минимизира фалшивите положителни резултати, свързани с факта, че спадът се е случил точно на порта на анализатора поради наличието на друг трафик. Ако това не е възможно (използва се миникомпютър/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), т.е. винаги изчаквайте 7 TS пакета от последния процесор, преди да изпратите IP пакет.

Анализаторът започва да извежда очакваните съобщения:

* 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. Опитваме се да разберем кой е виновен - генераторът няма време или проблемът не е в него, за това започваме да генерираме фиксиран брой пакети (700000 100000 TS пакета = XNUMX XNUMX 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 151925460 IP пакета (151825460-1). Така че нека да разберем какво се случва с анализатора, за това проверяваме с RX брояча на veth0, той е строго равен на TX брояча на vethXNUMX, след което гледаме какво се случва на ниво сокет:

# 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, така че виждаме, че същите тези XNUMX% от загубения битрейт са спадове в udp сокета. Пропадания в UDP сокет обикновено се случват поради липса на буфер, погледнете размера на буфера на сокета по подразбиране и максималния размер на буфера на сокета:

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

По този начин, ако приложенията не поискат изрично размер на буфера, сокетите се създават с буфер от 208 KB, но ако поискат повече, пак няма да получат това, което е поискано. Тъй като можете да зададете размера на буфера в tsp за IP вход (-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 приложение. В сравнение с един ядрен процесор i5-4260U @ 1.40 GHz, анализът на потока от 10 Mbps ще изисква 3-4% CPU, 100 Mbps - 25%, 200 Mbps - 46%. Когато зададете % загуба на пакети, натоварването на процесора практически не се увеличава (но може да намалее).

На по-продуктивен хардуер беше възможно да се генерират и анализират потоци от повече от 1Gb / s без никакви проблеми.

Тестване на реални мрежови карти

След тестване на двойка veth, трябва да вземете два хоста или два порта на един хост, да свържете портовете един към друг, да стартирате генератора на единия и анализатора на втория. Тук нямаше изненади, но всъщност всичко зависи от желязото, колкото по-слабо, толкова по-интересно ще бъде тук.

Използване на получените данни от системата за мониторинг (Zabbix)

tsp няма машинно четим API като SNMP или подобен. CC съобщенията трябва да се агрегират за поне 1 секунда (при висок процент на загуба на пакети може да има стотици/хиляди/десетки хиляди в секунда, в зависимост от битрейта).

По този начин, за да се запази както информацията, така и да се начертаят графики за CC грешки и битрейт и да се направят някакви инциденти, може да има следните опции:

  1. Анализирайте и обобщете (чрез CC) изхода на tsp, т.е. преобразувайте го в желаната форма.
  2. Завършете самия tsp и/или процесорните добавки bitrate_monitor и continuity, така че резултатът да бъде даден в машинно четима форма, подходяща за системата за наблюдение.
  3. Напишете вашето приложение върху библиотеката tsduck.

Очевидно вариант 1 е най-лесният по отношение на усилията, особено като се има предвид, че самият tsduck е написан на език от ниско ниво (по съвременните стандарти) (C ++)

Прост прототип на парсер + агрегатор на bash показа, че при поток от 10 Mbps и 50% загуба на пакети (в най-лошия случай), процесът bash консумира 3-4 пъти повече CPU от самия процес tsp. Този сценарий е неприемлив. Всъщност част от този прототип по-долу

Юфка отгоре

#!/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 заданията са отделни процеси и трябваше да пиша стойността на missingPackets веднъж в секунда при страничния ефект (когато получавам съобщения за битрейт, които идват всяка секунда). В резултат на това bash беше оставен сам и беше решено да се напише обвивка (парсер + агрегатор) в golang. Потреблението на процесора на подобен golang код е 4-5 пъти по-малко от самия tsp процес. Ускоряването на обвивката поради замяната на bash с golang се оказа около 16 пъти и като цяло резултатът е приемлив (зареждане на процесора с 25% в най-лошия случай). Изходният файл на golang се намира тук.

Изпълнение на обвивка

За да стартирате обвивката, беше направен най-простият шаблон за услуга за systemd (тук). Самата обвивка трябва да бъде компилирана в двоичен файл (отидете на компилация tsduck-stat.go), разположен в /opt/tsduck-stat/. Предполага се, че използвате golang с поддръжка за монотонен часовник (>=1.9).

За да създадете екземпляр на услугата, трябва да изпълните командата systemctl enable [имейл защитен]:1234 след това стартирайте със systemctl start [имейл защитен]: 1234.

Откритие от Zabbix

За да може zabbix да открие работещи услуги, това е направено генератор на групови списъци (discovery.sh), във формата, необходим за откриване на Zabbix, предполага се, че се намира на същото място - в /opt/tsduck-stat. За да стартирате откриване чрез zabbix-агент, трябва да добавите .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-агентът е инсталиран, изчакайте около 5 минути, вижте дали има нови елементи, графики и задействания.

Резултат

Използване на TSDuck за наблюдение на IP(TS) потоци

За задачата за откриване на загуба на пакети е почти достатъчно, поне е по-добре от липса на мониторинг.

Всъщност „загубите“ на CC могат да възникнат при обединяване на видео фрагменти (доколкото знам, така се правят вложки в местните телевизионни центрове в Руската федерация, т.е. без преизчисляване на брояча на CC), това трябва да се помни. Патентованите решения частично заобикалят този проблем чрез откриване на етикети SCTE-35 (ако са добавени от генератора на потоци).

По отношение на мониторинга на качеството на транспорта липсва мониторинг на трептене (IAT). Телевизионното оборудване (било то модулатори или крайни устройства) има изисквания за този параметър и не винаги е възможно да се раздуе jitbuffer до безкрайност. И трептенето може да се появи, когато оборудване с големи буфери се използва при преминаване и QoS не е конфигуриран или не е достатъчно добре конфигуриран, за да предава такъв трафик в реално време.

Източник: www.habr.com

Добавяне на нов коментар