-
Notifications
You must be signed in to change notification settings - Fork 19
Work with MPEG 2 TS Multicasts
IGMP is a common practice to prevent the flooding of switch's ports with multicast traffic. In this case, in order to receive the multicast traffic, you need to join the multicast group. You can do that using smcroute
. You can install it by executing:
sudo apt install smcroute
And this is the command to join the multicast:
sudo smcroutectl join <IFNAME> <MULTICAST-GROUP>
where:
<IFNAME>
is the interface name which can receive the multicast traffic.
<MULTICAST-GROUP>
is the multicast address without the port.
For example, the following command will join 224.0.0.0 multicast on eno1
interface:
sudo smcroutectl join eno1 224.0.0.0
You can check the joined multicast groups executing:
sudo smcroutectl show groups
GROUP (S,G) INBOUND
(*, 224.0.0.0) eno1
You can also leave the joined groups by:
sudo smcroutectl leave <IFNAME> <MULTICAST-GROUP>
SSM is another common practice to limit the flooding of the switch's ports. In this case, you need to define the IP address of the multicast source in order to receive the multicast traffic. You can do this as well with smcroute
by placing the source IP in front of the <MULTICAST-GROUP>
:
sudo smcroutectl join <IFNAME> <SOURCE-IP> <MULTICAST-GROUP>
The leave command is exactly the same as above but in this case, you also need to define the <SOURCE-IP>
:
sudo smcroutectl leave <IFNAME> <SOURCE-IP> <MULTICAST-GROUP>
Afterward, you can confirm that you have left this group by executing:
sudo smcroutectl show groups
You can use smcroute
for forwarding the multicast traffic from one interface to another. This is really easy and similar to the join/add commands but in this case, you need to use:
sudo smcroutectl add <INPUT-IFNAME> <SOURCE-IP> <MULTICAST-GROUP> <OUTPUT-IFNAME-1> <OUTPUT-IFNAME-2> ...
where:
<INPUT-IFNAME>
is the network interface receiving the multicast traffic.
<SOURCE-IP>
is an optional argument in case you have SSM traffic.
<MULTICAST-GROUP>
is the multicast group you want to join.
<OUTPUT-IFNAME-1>
is the output network interface on which the input multicast traffic will be forwarded.
<OUTPUT-IFNAME-2>
is also an optional argument and should be used only if you want to forward the multicast group to more than one interface.
You can learn more about the usage of smcroute
at the official Github page or you can also execute smcroute help
.
You can check for existing multicast traffic on a particular network interface using the tcpdump
command.
sudo tcpdump -nn -v -q -i <IFNAME> -c 1000 multicast and udp and greater 1344 | sort | uniq | grep '>'
where:
-nn
option is telling tcpdump
not to resolve port numbers.
-v
- forces the output to be more verbose.
-c 1000
tells tcpdump
to capture only 1000 packets.
-i <IFNAME>
defines which network interface to be used. This has to be the network interface receiving the multicast traffic.
udp
- forces tcpdump
to analyze only UDP traffic.
multicast
- additionally says to filter only for multicast traffic.
greater 1344
is filtering the results additionally by packet length and only capturing packets with a length greater than 1344 bytes.
| sort
is sorting the output.
| uniq
is showing only the unique entries.
| grep '>'
is suppressing the tcpdump
output and showing only the entries having the >
sign.
In the above example, we are setting the packet length to be greater than 1344 because this filter by default is filtering by total UDP packet size and not by the UDP payload size. By default, UDP doesn't have a length field, but its header size is always 8, and you can usually assume that the IPv4 header size will always be 20 (IPv4 options are very rare, although they do get used in IGMP). So the total UDP packet length is:
IP.TotalLength = IP.Header[20] + UDP.Header[8] + UDP.Payload[1316] = 1344
More information can be found at this link
For example:
sudo tcpdump -c 1000 -q -nn -v -i eno1 udp and multicast and greater 1346 | sort | uniq | grep '>'
tcpdump: listening on eno1, link-type EN10MB (Ethernet), capture size 262144 bytes
1000 packets captured
1089 packets received by filter
0 packets dropped by kernel
10.0.0.1.4000 > 224.0.0.1.1234: UDP, length 1316
10.0.0.2.4000 > 224.0.0.2.1234: UDP, length 1316
10.0.0.3.4000 > 224.0.0.3.1234: UDP, length 1316
The above command is showing me that there are three multicasts present on my eno1
network interface: 224.0.0.1:1234
, 224.0.0.2:1234
, 224.0.0.3:1234
and the source IP addresses sending those multicasts in the network are: 10.0.0.1
, 10.0.0.2
, 10.0.0.3
all using source port 4000.
If you want to suppress the tcpdump
statistics output, you can redirect the STDERR
to /dev/null
and this will leave only information about the present multicasts:
sudo tcpdump -c 1000 -q -nn -v -i eno1 udp and multicast and greater 1346 2>/dev/null | sort | uniq | grep '>'
10.0.0.1.4000 > 224.0.0.1.1234: UDP, length 1316
10.0.0.2.4000 > 224.0.0.2.1234: UDP, length 1316
10.0.0.3.4000 > 224.0.0.3.1234: UDP, length 1316
You can use check the live MPEG-2 TS stream using ffprobe
, which is part of ffmpeg
ffprobe udp://<MULTICAST-IP>:<PORT> 2>&1 | egrep -e "Program" -e "Stream" -e "service_name" -e "service_provider"
where:
<MULTICAST-IP>
is the multicast IP address.
<PORT>
is the multicast port.
2>&1
- redirects the STDERR
to the STDOUT
.
| egrep -e "Program" -e "Stream" -e "service_name" -e "service_provider"
- prints only the lines containing Program
, Stream
, service_name
and service_provider
to the STDOUT
.
You can also use tsduck to analyze the stream but first, you need to install it either by installing the provided binaries or compile it from source. After that you can try to execute the following command:
timeout -s SIGINT 30 tsp -I ip <MULTICAST-IP>:<PORT> -P analyze -O drop
where:
timeout 30
- waits for 30 seconds.
-s SIGINT
- sends SIGINT
signal at the end of the 30 seconds, which is replicating a pressing of CTRL-C by the user.
tsp
is the TSProcessor
, one of the main programs contained in the tsduck
package.
-I ip
- sets the input to IP.
<MULTICAST-IP>:<PORT>
is the multicast IP address and port.
-P analyze
is setting the used TSProcessor
plugin to analyze.
-O drop
is telling to the TSProcessor
to drop the output and not save or forward it.
The above command will analyze the provided multicast address for 30 seconds and will output information about all services and PIDs in the stream. It will also show you if there are any errors in the stream. If you want to save this information in a file you can just add redirection of the output of the command to a specified file.
timeout -s SIGINT 30 tsp -I ip <MULTICAST-IP>:<PORT> -P analyze -O drop > analysis.txt
This will analyze the multicast stream for 30 seconds and record the output to analysis.txt
file in the same directory.
You can also use tsp
to display the errors in the stream:
timeout -s SIGINT 30 tsp -I ip <MULTICAST-IP>:<PORT> -P analyze --error-analysis -O drop
As you can see TSDuck
is a very powerful tool and I strongly recommend you to check its documentation to get to know its full capabilities.
You can use different programs to record the MPEG-2 TS streams like: ffmpeg
, tsudpreceive
, part of the OpenCaster software, tsp
, part of TSDuck
, socat
and multicat
.
An example using tsp
program to make a recording of the MPEG-2 TS:
timeout -s SIGINT 30 tsp -ron --buffer-size-mb 50 -I ip <MULTICAST-IP>:<PORT> -O file recording.ts
where:
-ron
forces the recording to be realtime.
-buffer-size-mb
sets the buffer to 50Mb.
-O file
sets the output to a file and saves the stream in this file (recording.ts
).
An example of the ffmpeg recording:
ffmpeg -hide_banner -re -i "udp://<MULTICAST-IP>:<PORT>?overrun_nonfatal=1&fifo_size=50000000" \
-map 0 -ignore_unknown -c copy -t 30 -f mpegts ffmpeg.ts
where:
-hide_banner
hides the initial banner which contains information about the ffmpeg's version and its configuration.
-re
forces tsp
to work real-time.
-i udp://<MULTICAST-IP>:<PORT>
- defines the input for ffmpeg
.
overrun_nonfatal=1
- tells ffmpeg
to recover if it accidentally crashes due to some problem in the input stream.
fifo_size=50000000
defines the FIFO size to 50Mb, by default it is 5Mb.
-map 0
- (optional) use this argument only if you have more than one video and audio streams. It tells ffmpeg
to grab all streams present in the input. It is very important to use this option in case you want to record an MPTS (multiple programs transport stream). By default ffmpeg
is grabbing the first Video and audio stream. and forwards them to the output.
-ignore_unknown
forces ffmpeg
to ignore the unknown descriptors and to just copy them to the output.
-c copy
- tells ffmpeg
to copy everything from the input to the output.
-t 30
- sets the recording duration to 30 seconds.
-f mpegts
- forces the output format to be MPEG-2 TS.
The above command will save the input UDP multicast stream to the recording.ts
file. Please note that ffmpeg
by default is erasing all the null stuffing in the stream and it is also adding service name and service providers in the metadata of the stream so perhaps this is not the best utility to save the stream.
Another option is to use tsudpreceive
which is part of the OpenCaster software:
timeout 30 tsudpreceive <MULTICAST-IP> <PORT> > recording.ts
Here we use the Linux tool timeout
to limit the duration of the recording to 30 seconds since tsudpreceive
is a very basic utility and it doesn't have such an option. Please note that in the tsudpreceive
syntax you need to separate the and the by space and not by double points.
Another option is to use the socat
Linux tool:
socat -u UDP4-RECV:<PORT>,ip-add-membership=<MULTICAST-IP>:<IFNAME> CREATE:recording.ts
Here you need to define also the name of the interface in order to make the recording.
Multicat is another interesting tool, developed by Videolan. You can use it to make a recording on the live TS:
multicat -u -U @<MULTICAST-IP>:<PORT> -d 810000000 recording.ts
where:
-d 810000000
is defining the duration of the recording to 30 seconds. Multicat by default is accepting the duration in 27MHz units, so 27E+6 * 30 = 81E+7.