分析RTP数据丢包与乱序

发布时间 2023-03-23 11:12:59作者: wefjack

背景

问题描述:

某客户使用华为TE视频终端开会,会议偶发出现马赛克问题(每次马赛克持续2-4秒)。

设备通信:

TE:视频终端,物理位置在A市 。MCU:类似视频服务器,物理位置在B市。开会时TE需要和MCU进行实时通信,中间经过运营商的专线。

初步分析:

视频有马赛克的话说明TE侧收到MCU发出的数据包有问题(网络丢包、乱序 )或TE设备解析有问题,在TE侧和MCU侧进行抓包分析,经华为分析MCU发出的数据包都是正常的(无丢包和数据包乱序情况),但是TE收到的数据包有乱序和丢包的情况。华为:丢包和乱序都会导致视频会议的马赛克问题。

[^Tips]: TE侧抓到的数据包是未经TE解析的数据包,保证了数据包无污染性。

通过网络抓包抓到1.2G的数据包,数据包的数量大约在138万个,通过wireshark可以打开,但是速度比较慢,使用wireshark分析起来更慢,另外丢包数量可以通过wireshark分析出来,但是有多少数据包乱序 wireshark就无能为力了,所以分析乱序和丢包主要借助linux下的tshark、grep、awk、wc等工具进行分析。

[root@rhel ~]# ll -h
total 1.2G
-rw-r--r--. 1 root root 1.2G Mar 22 08:24 te50-rx.pcap

[root@rhel ~]# tshark -r te50-rx.pcap | wc -l
Running as user "root" and group "root". This could be dangerous.
1380386

分析目的:

分析出TE收到的MCU发送的数据包丢包与乱序的数量。

分析前提:

通过wireshark打开后看到都是udp流量,需要对数据包进行解码,根据源端口或目的端口 进行decode as(解码)成应用层协议RTP,另外下面举了数据包丢包和数据包乱序的例子。seq最大是65535,超过65535再从0开始计数。

wireshark打开数据包后看到都是udp流量
1.1.1.1	2.2.2.2	UDP	1077	49202 → 10004 Len=1035
1.1.1.1	2.2.2.2	UDP	1077	49202 → 10004 Len=1035
1.1.1.1	2.2.2.2	UDP	1076	49202 → 10004 Len=1034

解码后
根据seq判断是否有丢包的情况
下面举例为丢包:
1.1.1.1 → 2.2.2.2 	RTP 1165 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=17901, Time=161734770
1.1.1.1 → 2.2.2.2 	RTP 911 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=17902, Time=161734770
1.1.1.1 → 2.2.2.2 	RTP 1100 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=17905, Time=161734770
1.1.1.1 → 2.2.2.2 	RTP 1072 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=17906, Time=161734770
中间数据包17903,17904数据包丢失。

下面举例为数据包乱序:
1.1.1.1 → 2.2.2.2 	RTP 1007 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=16504, Time=161734770
1.1.1.1 → 2.2.2.2 	RTP 1160 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=16502, Time=161734770
1.1.1.1 → 2.2.2.2 	RTP 1145 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=16503, Time=161734770
1.1.1.1 → 2.2.2.2 	RTP 1145 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=16505, Time=161734770
数据包Seq=16504 乱序

seq最大是65535,超过65535再从0开始计数
1.1.1.1	2.2.2.2	RTP	546		PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=65534, Time=151356330
1.1.1.1	2.2.2.2	RTP	1165	PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=65535, Time=151358130
1.1.1.1	2.2.2.2	RTP	1166	PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=0, Time=151358130
1.1.1.1	2.2.2.2	RTP	1166	PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=1, Time=151358130

思路

通过数据包中的seq(序列)字段是否缺失 或乱序 来判断TE收到的数据包丢了多少包,乱序了多少包。

1.查找视频流源目IP地址

2.解码与过滤,得到seq-te序列

3.判断循环次数(判断收到数据包中的seq 0-65535,循环了几次(grep+wc))

4.for循环(制作一个正确的序列,得到seq-for序列)

5.seq-for序列与seq-te序列对比(diff+grep + wc分析得出数据包丢失和乱序的数量)

分析

查找视频流源目IP地址

  1. 使用wireshark打开数据包,通过统计-会话功能 根据源目IP地址和数据包的字节数来判断哪个一个是视频流(视频流通常数据量比较大)
image-20230323084807016

我们发现源是1.1.1.1 (MCU IP地址),源端口49202,目的是2.2.2.2,目的端口1004,数据量大小为278M,而数据包1.2G大小包含了在开会之前抓到的另一个会议的数据包(另一个会议MCU地址不是1.1.1.1),所以要剔除这部分数据包。

解码与过滤

1.举例:

下面举了一个tshark 解码和过滤的例子

-d udp.port==49202,rtp 将udp源端口号为49202的数据包解析为RTP协议,ip.src==1.1.1.1 and udp.srcport==49202过滤源数据包为1.1.1.1,源udp端口为49202的数据包。

[root@rhel ~]# tshark -r te50-rx.pcap -d udp.port==49202,rtp ip.src==1.1.1.1 and udp.srcport==49202 | tail
Running as user "root" and group "root". This could be dangerous.
1.1.1.1 → 2.2.2.2 RTP 1166 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=17893, Time=161729370
1.1.1.1 → 2.2.2.2 RTP 990 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=17894, Time=161729370, Mark
1.1.1.1 → 2.2.2.2 RTP 1165 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=17895, Time=161731170
1.1.1.1 → 2.2.2.2 RTP 986 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=17896, Time=161731170, Mark
1.1.1.1 → 2.2.2.2 RTP 1165 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=17897, Time=161733060
1.1.1.1 → 2.2.2.2 RTP 1166 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=17898, Time=161733060
1.1.1.1 → 2.2.2.2 RTP 1166 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=17899, Time=161733060
1.1.1.1 → 2.2.2.2 RTP 147 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=17900, Time=161733060, Mark
1.1.1.1 → 2.2.2.2 RTP 1165 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=17901, Time=161734770
1.1.1.1 → 2.2.2.2 RTP 911 PT=DynamicRTP-Type-110, SSRC=0xEE2AD303, Seq=17902, Time=161734770, 

2.一条命令得到视频流中的seq-te序列

[root@rhel ~]# tshark -r te50-rx.pcap -d udp.port==49202,rtp ip.src==93.0.12.26 and udp.srcport==49202 | grep Seq | awk '{print $10}'| cut -d = -f 2 | cut -d , -f 1 >seq-te

[root@rhel ~]# ll -h
-rw-r--r--. 1 root root 1.6M Mar 22 10:22 seq-te

[root@rhel ~]# head seq-te
0
1
2
3
4
5
6
7
8
9
[root@rhel ~]# tail seq-te
17893
17894
17895
17896
17897
17898
17899
17900
17901
17902

判断循环次数

使用grep+wc,判断收到数据包中的seq 0-65535 ,循环了几次

[root@rhel ~]# cat seq-te | grep -E ^0 | wc -l
5

可以看到以0开始的数字循环了5次,然后再看一下 最后一次循环的seq是多少
[root@rhel ~]# tail seq-te
17893
17894
17895
17896
17897
17898
17899
17900
17901
17902

可以看到最后1次是0-17902,前四次是0-65535

for循环

for i in {0..65535};do echo $i >>seq-for;done
for i in {0..65535};do echo $i >>seq-for;done
for i in {0..65535};do echo $i >>seq-for;done
for i in {0..65535};do echo $i >>seq-for;done	//0-65535循环四次
for i in {0..17902};do echo $i >>seq-for;done	//0-17902循环一次
得到seq-for文件

[root@rhel ~]# ll -h
-rw-r--r--. 1 root root 1.6M Mar 22 10:56 seq-for

seq-for序列与seq-te序列对比

[root@rhel ~]# diff seq-te seq-for| grep ' '| grep '< '| wc -l
1464	//乱序

[root@rhel ~]# diff seq-te seq-for | grep ' '| grep '> '| wc -l
2228		//2228-1464 =764 丢包

结论

  1. TE收到MCU发送的数据包 经过网络传输后 乱序数据包有1464个,丢包764个
  2. 基本排除TE硬件解析的问题,至于为什么丢包还需要继续排查网络,网络流量多路径负载导致数据包乱序。