Χρήση του TSDuck για την παρακολούθηση ροών IP(TS).

Σήμερα, υπάρχουν έτοιμες (ιδιόκτητες) λύσεις για την παρακολούθηση ροών IP(TS), για παράδειγμα VB и iQ, έχουν ένα αρκετά πλούσιο σύνολο λειτουργιών και συνήθως μεγάλες εταιρείες που ασχολούνται με τηλεοπτικές υπηρεσίες έχουν τέτοιες λύσεις. Αυτό το άρθρο περιγράφει μια λύση που βασίζεται σε έργο ανοιχτού κώδικα TSDuck, σχεδιασμένο για ελάχιστο έλεγχο των ροών IP(TS) από μετρητή CC (μετρητή συνέχειας) και ρυθμό μετάδοσης bit. Μια πιθανή εφαρμογή είναι ο έλεγχος της απώλειας πακέτων ή ολόκληρης της ροής μέσω ενός μισθωμένου καναλιού L2 (το οποίο δεν μπορεί να παρακολουθηθεί κανονικά, για παράδειγμα, με την ανάγνωση μετρητών απώλειας σε ουρές).

Πολύ σύντομα για το TSDuck

Το TSDuck είναι ένα λογισμικό ανοιχτού κώδικα (άδεια BSD 2 ρητρών) (ένα σύνολο βοηθητικών προγραμμάτων κονσόλας και μια βιβλιοθήκη για την ανάπτυξη προσαρμοσμένων βοηθητικών προγραμμάτων ή προσθηκών) για τον χειρισμό ροών TS. Ως είσοδος, μπορεί να λειτουργήσει με IP (multicast/unicast), http, hls, dvb tuners, dektec dvb-asi demoulator, υπάρχει μια εσωτερική γεννήτρια TS-stream και ανάγνωση από αρχεία. Η έξοδος μπορεί να είναι εγγραφή σε αρχείο, IP (multicast/unicast), hls, διαμορφωτές dektec dvb-asi και HiDes, προγράμματα αναπαραγωγής (mplayer, vlc, xine) και απόθεση. Μπορούν να συμπεριληφθούν διάφοροι επεξεργαστές κυκλοφορίας μεταξύ εισόδου και εξόδου, για παράδειγμα, επαναχαρτογράφηση PID, κρυπτογράφηση / αποκωδικοποίηση, ανάλυση μετρητή CC, υπολογισμός ρυθμού bit και άλλες τυπικές λειτουργίες για ροές TS.

Σε αυτό το άρθρο, οι ροές IP (multicast) θα χρησιμοποιηθούν ως είσοδος, οι επεξεργαστές bitrate_monitor (από το όνομα είναι ξεκάθαρο τι είναι) και η συνέχεια (ανάλυση μετρητών CC). Μπορείτε εύκολα να αντικαταστήσετε το IP multicast με έναν άλλο τύπο εισόδου που υποστηρίζεται από το TSDuck.

Υπάρχουν επίσημες κατασκευές/πακέτα TSDuck για τα περισσότερα τρέχοντα λειτουργικά συστήματα. Δεν είναι διαθέσιμα για το Debian, αλλά καταφέραμε να τα δημιουργήσουμε κάτω από το debian 8 και το debian 10 χωρίς κανένα πρόβλημα.

Στη συνέχεια, χρησιμοποιείται η έκδοση TSDuck 3.19-1520, το Linux χρησιμοποιείται ως λειτουργικό σύστημα (το debian 10 χρησιμοποιήθηκε για την προετοιμασία της λύσης, το CentOS 7 χρησιμοποιήθηκε για πραγματική χρήση)

Προετοιμασία TSDuck και OS

Πριν παρακολουθήσετε πραγματικές ροές, πρέπει να βεβαιωθείτε ότι το TSDuck λειτουργεί σωστά και ότι δεν υπάρχουν πτώσεις στο επίπεδο της κάρτας δικτύου ή του λειτουργικού συστήματος (πρίζα). Αυτό απαιτείται για να μην μαντέψετε αργότερα πού συνέβησαν οι πτώσεις - στο δίκτυο ή "μέσα στον διακομιστή". Μπορείτε να ελέγξετε τις πτώσεις σε επίπεδο κάρτας δικτύου με την εντολή 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" σημαίνει ότι πρέπει να υπολογίζετε το bitrate κάθε δευτερόλεπτο και να εμφανίζετε πληροφορίες σχετικά με το bitrate κάθε δευτερόλεπτο
Ξεκινάμε τη γεννήτρια κυκλοφορίας με ταχύτητα 10 Mbps:

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) και προσπαθήστε να αυξήσετε τον ρυθμό μετάδοσης bit της γεννήτριας στα 100 Mbps. Ο αναλυτής αναφέρει μια δέσμη σφαλμάτων CC και περίπου 75 Mbps αντί για 100. Προσπαθούμε να καταλάβουμε ποιος φταίει - η γεννήτρια δεν έχει χρόνο ή το πρόβλημα δεν βρίσκεται σε αυτήν, για αυτό ξεκινάμε να δημιουργούμε έναν σταθερό αριθμό πακέτα (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). Ας καταλάβουμε λοιπόν τι συμβαίνει με τον αναλυτή, γι' αυτό ελέγχουμε με τον μετρητή RX στο veth1, είναι αυστηρά ίσος με τον μετρητή TX στο veth0 και, στη συνέχεια, εξετάζουμε τι συμβαίνει στο επίπεδο υποδοχής:

# 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% του χαμένου bitrate είναι σταγόνες στην υποδοχή udp. Οι πτώσεις σε μια υποδοχή UDP συνήθως συμβαίνουν λόγω έλλειψης buffer, δείτε το προεπιλεγμένο μέγεθος buffer υποδοχής και το μέγιστο μέγεθος buffer υποδοχής:

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

Έτσι, εάν οι εφαρμογές δεν ζητούν ρητά μέγεθος buffer, δημιουργούνται υποδοχές με buffer 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

Με αυτόν τον συντονισμό του buffer της υποδοχής, τώρα ο αναφερόμενος ρυθμός μετάδοσης bit είναι περίπου 100 Mbps, δεν υπάρχουν σφάλματα CC.

Σύμφωνα με την κατανάλωση CPU της ίδιας της εφαρμογής tsp. Σε σχέση με έναν πυρήνα CPU i5-4260U @ 1.40GHz, η ανάλυση ροής 10Mbps θα απαιτεί 3-4% CPU, 100Mbps - 25%, 200Mbps - 46%. Όταν ρυθμίζετε το % Packet Loss, το φορτίο στη CPU πρακτικά δεν αυξάνεται (αλλά μπορεί να μειωθεί).

Σε πιο παραγωγικό υλικό, ήταν δυνατή η δημιουργία και ανάλυση ροών άνω του 1 Gb / s χωρίς προβλήματα.

Δοκιμή σε πραγματικές κάρτες δικτύου

Μετά τη δοκιμή σε ένα ζεύγος veth, πρέπει να πάρετε δύο κεντρικούς υπολογιστές ή δύο θύρες ενός κεντρικού υπολογιστή, να συνδέσετε τις θύρες μεταξύ τους, να ξεκινήσετε τη γεννήτρια στη μία και τον αναλυτή στη δεύτερη. Δεν υπήρχαν εκπλήξεις εδώ, αλλά στην πραγματικότητα όλα εξαρτώνται από το σίδερο, όσο πιο αδύναμο, τόσο πιο ενδιαφέρον θα είναι εδώ.

Χρήση των δεδομένων που λαμβάνονται από το σύστημα παρακολούθησης (Zabbix)

Το tsp δεν διαθέτει μηχανικά αναγνώσιμο API όπως το SNMP ή παρόμοιο. Τα μηνύματα CC πρέπει να συγκεντρώνονται για τουλάχιστον 1 δευτερόλεπτο (με υψηλό ποσοστό απώλειας πακέτων, μπορεί να υπάρχουν εκατοντάδες/χιλιάδες/δεκάδες χιλιάδες ανά δευτερόλεπτο, ανάλογα με το bitrate).

Έτσι, για να αποθηκεύσετε πληροφορίες και να σχεδιάσετε γραφήματα για σφάλματα CC και bitrate και να κάνετε κάποιο είδος ατυχημάτων, ενδέχεται να υπάρχουν οι ακόλουθες επιλογές:

  1. Αναλύστε και συγκεντρώστε (κατά CC) την έξοδο του tsp, δηλ. μετατρέψτε το στην επιθυμητή μορφή.
  2. Ολοκληρώστε το ίδιο το tsp ή/και τα πρόσθετα επεξεργαστή bitrate_monitor και continuity έτσι ώστε το αποτέλεσμα να δίνεται σε αναγνώσιμη από μηχανή μορφή κατάλληλη για το σύστημα παρακολούθησης.
  3. Γράψτε την αίτησή σας πάνω από τη βιβλιοθήκη tsduck.

Προφανώς, η επιλογή 1 είναι η πιο εύκολη από άποψη προσπάθειας, ειδικά αν σκεφτεί κανείς ότι το ίδιο το tsduck είναι γραμμένο σε γλώσσα χαμηλού επιπέδου (σύμφωνα με τα σύγχρονα πρότυπα) (C ++)

Ένα απλό πρωτότυπο bash parser+aggregator έδειξε ότι σε μια ροή 10Mbps και απώλεια πακέτων 50% (τη χειρότερη περίπτωση), η διαδικασία bash κατανάλωνε 3-4 φορές περισσότερη CPU από την ίδια τη διαδικασία tsp. Αυτό το σενάριο είναι απαράδεκτο. Στην πραγματικότητα, ένα κομμάτι αυτού του πρωτοτύπου παρακάτω

Noodles στην κορυφή

#!/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 μία φορά το δευτερόλεπτο στην παρενέργεια (όταν λαμβάνω μηνύματα bitrate που έρχονται κάθε δευτερόλεπτο). Ως αποτέλεσμα, ο bash έμεινε μόνος του και αποφασίστηκε να γραφτεί ένα περιτύλιγμα (αναλυτής + αθροιστής) σε golang. Η κατανάλωση CPU παρόμοιου κώδικα golang είναι 4-5 φορές μικρότερη από την ίδια τη διαδικασία tsp. Η επιτάχυνση του περιτυλίγματος λόγω της αντικατάστασης του bash με golang αποδείχθηκε περίπου 16 φορές και σε γενικές γραμμές το αποτέλεσμα είναι αποδεκτό (επιβάρυνση CPU κατά 25% στη χειρότερη περίπτωση). Το αρχείο προέλευσης golang βρίσκεται εδώ.

Run περιτύλιγμα

Για να ξεκινήσετε το περιτύλιγμα, δημιουργήθηκε το απλούστερο πρότυπο υπηρεσίας για το systemd (εδώ). Το ίδιο το περιτύλιγμα υποτίθεται ότι έχει μεταγλωττιστεί σε ένα δυαδικό αρχείο (go build tsduck-stat.go) που βρίσκεται στο /opt/tsduck-stat/. Υποτίθεται ότι χρησιμοποιείτε golang με υποστήριξη για μονοτονικό ρολόι (>=1.9).

Για να δημιουργήσετε μια παρουσία της υπηρεσίας, πρέπει να εκτελέσετε την εντολή systemctl enable [προστασία μέσω email]:1234 και μετά εκτελέστε με systemctl start [προστασία μέσω email]: 1234.

Ανακάλυψη από το Zabbix

Για να μπορέσει το zabbix να ανακαλύψει τις τρέχουσες υπηρεσίες, έχει γίνει δημιουργός λίστας ομάδων (discovery.sh), στη μορφή που απαιτείται για την ανακάλυψη Zabbix, θεωρείται ότι βρίσκεται στο ίδιο μέρος - στο /opt/tsduck-stat. Για να εκτελέσετε το Discovery μέσω zabbix-agent, πρέπει να προσθέσετε αρχείο .conf στον κατάλογο διαμόρφωσης zabbix-agent για να προσθέσετε την παράμετρο χρήστη.

Πρότυπο Zabbix

Δημιουργήθηκε πρότυπο (tsduck_stat_template.xml) περιέχει τον κανόνα αυτόματης ανακάλυψης, πρωτότυπα αντικειμένων, γραφήματα και κανόνες ετικέτας.

Σύντομη λίστα ελέγχου (καλά, τι γίνεται αν κάποιος αποφασίσει να τη χρησιμοποιήσει)

  1. Βεβαιωθείτε ότι το tsp δεν ρίχνει πακέτα υπό "ιδανικές" συνθήκες (η γεννήτρια και ο αναλυτής συνδέονται απευθείας), εάν υπάρχουν πτώσεις, δείτε την παράγραφο 2 ή το κείμενο του άρθρου σχετικά με αυτό το θέμα.
  2. Κάντε συντονισμό του μέγιστου buffer υποδοχής (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 agent config, επανεκκίνηση του zabbix agent.
  8. Μεταφορτώστε το πρότυπο στο zabbix, εφαρμόστε το στον κεντρικό υπολογιστή που παρακολουθείται και είναι εγκατεστημένο το zabbix-agent, περιμένετε περίπου 5 λεπτά, δείτε εάν υπάρχουν νέα στοιχεία, γραφήματα και κανόνες ενεργοποίησης.

Αποτέλεσμα

Χρήση του TSDuck για την παρακολούθηση ροών IP(TS).

Για την ανίχνευση απώλειας πακέτων, είναι σχεδόν αρκετό, τουλάχιστον είναι καλύτερο από την απουσία παρακολούθησης.

Πράγματι, μπορεί να προκύψουν "απώλειες" CC κατά τη συγχώνευση θραυσμάτων βίντεο (εξ όσων γνωρίζω, έτσι γίνονται τα ένθετα σε τοπικά τηλεοπτικά κέντρα στη Ρωσική Ομοσπονδία, δηλ. χωρίς επανυπολογισμό του μετρητή CC), αυτό πρέπει να το θυμόμαστε. Οι ιδιόκτητες λύσεις παρακάμπτουν εν μέρει αυτό το πρόβλημα ανιχνεύοντας ετικέτες SCTE-35 (εάν προστεθούν από τη γεννήτρια ροής).

Όσον αφορά την παρακολούθηση της ποιότητας των μεταφορών, υπάρχει έλλειψη παρακολούθησης jitter (IAT). Ο εξοπλισμός τηλεόρασης (είτε είναι διαμορφωτές είτε τελικές συσκευές) έχει απαιτήσεις για αυτήν την παράμετρο και δεν είναι πάντα δυνατό να φουσκώσει το jitbuffer στο άπειρο. Και το jitter μπορεί να επιπλέει όταν χρησιμοποιείται εξοπλισμός με μεγάλα buffer κατά τη μεταφορά και το QoS δεν έχει ρυθμιστεί ή δεν έχει ρυθμιστεί αρκετά καλά για να μεταδίδει τέτοια κίνηση σε πραγματικό χρόνο.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο