2 * RTP stream handler functions used by tshark and wireshark
4 * Copyright 2008, Ericsson AB
5 * By Balint Reczey <balint.reczey@ericsson.com>
7 * most functions are copied from ui/gtk/rtp_stream.c and ui/gtk/rtp_analysis.c
8 * Copyright 2003, Alcatel Business Systems
9 * By Lars Ruoff <lars.ruoff@gmx.net>
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 1998 Gerald Combs
15 * SPDX-License-Identifier: GPL-2.0-or-later
26 #include <epan/rtp_pt.h>
27 #include <epan/addr_resolv.h>
28 #include <epan/proto_data.h>
29 #include <epan/dissectors/packet-rtp.h>
30 #include <wsutil/pint.h>
31 #include "rtp_stream.h"
32 #include "tap-rtp-common.h"
33 #include "tap-rtp-analysis.h"
35 typedef struct _key_value {
41 /* RTP sampling clock rates for fixed payload types as defined in
42 http://www.iana.org/assignments/rtp-parameters */
43 static const key_value clock_map[] = {
50 {PT_DVI4_16000, 16000},
54 {PT_L16_STEREO, 44100},
61 {PT_DVI4_11025, 11025},
62 {PT_DVI4_22050, 22050},
74 #define NUM_CLOCK_VALUES (sizeof clock_map / sizeof clock_map[0])
77 get_clock_rate(guint32 key)
81 for (i = 0; i < NUM_CLOCK_VALUES; i++) {
82 if (clock_map[i].key == key)
83 return clock_map[i].value;
88 typedef struct _mimetype_and_clock {
89 const gchar *pt_mime_name_str;
92 /* RTP sampling clock rates for
93 "In addition to the RTP payload formats (encodings) listed in the RTP
94 Payload Types table, there are additional payload formats that do not
95 have static RTP payload types assigned but instead use dynamic payload
96 type number assignment. Each payload format is named by a registered
98 http://www.iana.org/assignments/rtp-parameters.
100 NOTE: Please keep the mimetypes in case insensitive alphabetical order.
102 static const mimetype_and_clock mimetype_and_clock_map[] = {
103 {"AMR", 8000}, /* [RFC4867][RFC3267] */
104 {"AMR-WB", 16000}, /* [RFC4867][RFC3267] */
105 {"BMPEG", 90000}, /* [RFC2343],[RFC3555] */
106 {"BT656", 90000}, /* [RFC2431],[RFC3555] */
107 {"DV", 90000}, /* [RFC3189] */
108 {"EVRC", 8000}, /* [RFC3558] */
109 {"EVRC0", 8000}, /* [RFC4788] */
110 {"EVRC1", 8000}, /* [RFC4788] */
111 {"EVRCB", 8000}, /* [RFC4788] */
112 {"EVRCB0", 8000}, /* [RFC4788] */
113 {"EVRCB1", 8000}, /* [RFC4788] */
114 {"EVRCWB", 16000}, /* [RFC5188] */
115 {"EVRCWB0", 16000}, /* [RFC5188] */
116 {"EVRCWB1", 16000}, /* [RFC5188] */
117 {"EVS", 16000}, /* [3GPP TS 26.445] */
118 {"G7221", 16000}, /* [RFC3047] */
119 {"G726-16", 8000}, /* [RFC3551][RFC4856] */
120 {"G726-24", 8000}, /* [RFC3551][RFC4856] */
121 {"G726-32", 8000}, /* [RFC3551][RFC4856] */
122 {"G726-40", 8000}, /* [RFC3551][RFC4856] */
123 {"G729D", 8000}, /* [RFC3551][RFC4856] */
124 {"G729E", 8000}, /* [RFC3551][RFC4856] */
125 {"GSM-EFR", 8000}, /* [RFC3551] */
126 {"H263-1998", 90000}, /* [RFC2429],[RFC3555] */
127 {"H263-2000", 90000}, /* [RFC2429],[RFC3555] */
128 {"H264", 90000}, /* [RFC3984] */
129 {"MP1S", 90000}, /* [RFC2250],[RFC3555] */
130 {"MP2P", 90000}, /* [RFC2250],[RFC3555] */
131 {"MP4V-ES", 90000}, /* [RFC3016] */
132 {"mpa-robust", 90000}, /* [RFC3119] */
133 {"pointer", 90000}, /* [RFC2862] */
134 {"raw", 90000}, /* [RFC4175] */
135 {"red", 1000}, /* [RFC4102] */
136 {"SMV", 8000}, /* [RFC3558] */
137 {"SMV0", 8000}, /* [RFC3558] */
138 {"t140", 1000}, /* [RFC4103] */
139 {"telephone-event", 8000}, /* [RFC4733] */
142 #define NUM_DYN_CLOCK_VALUES (sizeof mimetype_and_clock_map / sizeof mimetype_and_clock_map[0])
145 get_dyn_pt_clock_rate(const gchar *payload_type_str)
149 /* Search for matching mimetype in reverse order to avoid false matches
150 * when pt_mime_name_str is the prefix of payload_type_str */
151 for (i = NUM_DYN_CLOCK_VALUES - 1; i > -1 ; i--) {
152 if (g_ascii_strncasecmp(mimetype_and_clock_map[i].pt_mime_name_str,payload_type_str,(strlen(mimetype_and_clock_map[i].pt_mime_name_str))) == 0)
153 return mimetype_and_clock_map[i].value;
159 /****************************************************************************/
161 rtppacket_analyse(tap_rtp_stat_t *statinfo,
163 const struct _rtp_info *rtpinfo)
166 double current_jitter;
167 double current_diff = 0;
169 double arrivaltime; /* Time relative to start_time */
170 double expected_time;
174 /* Store the current time */
175 current_time = nstime_to_msec(&pinfo->rel_ts);
177 /* Is this the first packet we got in this direction? */
178 if (statinfo->first_packet) {
179 /* Save the MAC address of the first RTP frame */
180 if( pinfo->dl_src.type == AT_ETHER){
181 copy_address(&(statinfo->first_packet_mac_addr), &(pinfo->dl_src));
183 statinfo->start_seq_nr = rtpinfo->info_seq_num;
184 statinfo->stop_seq_nr = rtpinfo->info_seq_num;
185 statinfo->seq_num = rtpinfo->info_seq_num;
186 statinfo->start_time = current_time;
187 statinfo->timestamp = rtpinfo->info_timestamp;
188 statinfo->first_timestamp = rtpinfo->info_timestamp;
189 statinfo->time = current_time;
190 statinfo->lastnominaltime = 0;
191 statinfo->pt = rtpinfo->info_payload_type;
192 statinfo->reg_pt = rtpinfo->info_payload_type;
193 if (pinfo->net_src.type == AT_IPv6) {
194 statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 48;
196 statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 28;
198 statinfo->bw_history[statinfo->bw_index].time = current_time;
199 statinfo->bw_index++;
200 if (pinfo->net_src.type == AT_IPv6) {
201 statinfo->total_bytes += rtpinfo->info_data_len + 48;
203 statinfo->total_bytes += rtpinfo->info_data_len + 28;
205 statinfo->bandwidth = (double)(statinfo->total_bytes*8)/1000;
206 /* Not needed ? initialised to zero? */
208 statinfo->jitter = 0;
211 statinfo->total_nr++;
212 statinfo->flags |= STAT_FLAG_FIRST;
213 if (rtpinfo->info_marker_set) {
214 statinfo->flags |= STAT_FLAG_MARKER;
216 statinfo->first_packet_num = pinfo->num;
217 statinfo->first_packet = FALSE;
224 /*According to bug https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=11478
225 * this code causes problems. A better solution is needed if there is need for the functionality */
226 /* Try to detect duplicated packets due to mirroring/span ports by comparing src MAC addresses.
227 * Check for duplicates (src mac differs from first_packet_mac_addr) */
229 if( pinfo->dl_src.type == AT_ETHER){
230 if(!addresses_equal(&(statinfo->first_packet_mac_addr), &(pinfo->dl_src))){
231 statinfo->flags |= STAT_FLAG_DUP_PKT;
232 statinfo->delta = current_time-(statinfo->time);
237 /* When calculating expected rtp packets the seq number can wrap around
238 * so we have to count the number of cycles
239 * Variable cycles counts the wraps around in forwarding connection and
240 * under is flag that indicates where we are
242 * XXX How to determine number of cycles with all possible lost, late
243 * and duplicated packets without any doubt? It seems to me, that
244 * because of all possible combination of late, duplicated or lost
245 * packets, this can only be more or less good approximation
247 * There are some combinations (rare but theoretically possible),
248 * where below code won't work correctly - statistic may be wrong then.
251 /* So if the current sequence number is less than the start one
252 * we assume, that there is another cycle running
254 if ((rtpinfo->info_seq_num < statinfo->start_seq_nr) && (statinfo->under == FALSE)){
256 statinfo->under = TRUE;
258 /* what if the start seq nr was 0? Then the above condition will never
259 * be true, so we add another condition. XXX The problem would arise
260 * if one of the packets with seq nr 0 or 65535 would be lost or late
262 else if ((rtpinfo->info_seq_num == 0) && (statinfo->stop_seq_nr == 65535) &&
263 (statinfo->under == FALSE)) {
265 statinfo->under = TRUE;
267 /* the whole round is over, so reset the flag */
268 else if ((rtpinfo->info_seq_num > statinfo->start_seq_nr) && (statinfo->under != FALSE)) {
269 statinfo->under = FALSE;
272 /* Since it is difficult to count lost, duplicate or late packets separately,
273 * we would like to know at least how many times the sequence number was not ok
276 /* If the current seq number equals the last one or if we are here for
277 * the first time, then it is ok, we just store the current one as the last one
279 if ( (statinfo->seq_num+1 == rtpinfo->info_seq_num) || (statinfo->flags & STAT_FLAG_FIRST) )
280 statinfo->seq_num = rtpinfo->info_seq_num;
281 /* If the first one is 65535 we wrap */
282 else if ( (statinfo->seq_num == 65535) && (rtpinfo->info_seq_num == 0) )
283 statinfo->seq_num = rtpinfo->info_seq_num;
284 /* Lost packets. If the prev seq is enormously larger than the cur seq
285 * we assume that instead of being massively late we lost the packet(s)
286 * that would have indicated the sequence number wrapping. An imprecise
287 * heuristic at best, but it seems to work well enough.
288 * https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5958 */
289 else if (statinfo->seq_num+1 < rtpinfo->info_seq_num || statinfo->seq_num - rtpinfo->info_seq_num > 0xFF00) {
290 statinfo->seq_num = rtpinfo->info_seq_num;
291 statinfo->sequence++;
292 statinfo->flags |= STAT_FLAG_WRONG_SEQ;
294 /* Late or duplicated */
295 else if (statinfo->seq_num+1 > rtpinfo->info_seq_num) {
296 statinfo->sequence++;
297 statinfo->flags |= STAT_FLAG_WRONG_SEQ;
300 /* Check payload type */
301 if (rtpinfo->info_payload_type == PT_CN
302 || rtpinfo->info_payload_type == PT_CN_OLD)
303 statinfo->flags |= STAT_FLAG_PT_CN;
304 if (statinfo->pt == PT_CN
305 || statinfo->pt == PT_CN_OLD)
306 statinfo->flags |= STAT_FLAG_FOLLOW_PT_CN;
307 if (rtpinfo->info_payload_type != statinfo->pt)
308 statinfo->flags |= STAT_FLAG_PT_CHANGE;
309 statinfo->pt = rtpinfo->info_payload_type;
312 * Return for unknown payload types
313 * Ignore jitter calculation for clockrate = 0
315 if (statinfo->pt < 96 ){
316 clock_rate = get_clock_rate(statinfo->pt);
317 } else { /* Dynamic PT */
318 if ( rtpinfo->info_payload_type_str != NULL ) {
319 /* Is it a "telephone-event" ?
320 * Timestamp is not increased for telepone-event packets impacting
321 * calculation of Jitter Skew and clock drift.
322 * see 2.2.1 of RFC 4733
324 if (g_ascii_strncasecmp("telephone-event",rtpinfo->info_payload_type_str,(strlen("telephone-event")))==0) {
326 statinfo->flags |= STAT_FLAG_PT_T_EVENT;
328 if(rtpinfo->info_payload_rate !=0) {
329 clock_rate = rtpinfo->info_payload_rate;
331 clock_rate = get_dyn_pt_clock_rate(rtpinfo->info_payload_type_str);
339 /* Handle wraparound ? */
340 arrivaltime = current_time - statinfo->start_time;
342 nominaltime = (double)(guint32_wraparound_diff(rtpinfo->info_timestamp, statinfo->first_timestamp));
344 /* Can only analyze defined sampling rates */
345 if (clock_rate != 0) {
346 statinfo->clock_rate = clock_rate;
347 /* Convert from sampling clock to ms */
348 nominaltime = nominaltime /(clock_rate/1000);
350 /* Calculate the current jitter(in ms) */
351 if (!statinfo->first_packet) {
352 expected_time = statinfo->time + (nominaltime - statinfo->lastnominaltime);
353 current_diff = fabs(current_time - expected_time);
354 current_jitter = (15 * statinfo->jitter + current_diff) / 16;
356 statinfo->delta = current_time-(statinfo->time);
357 statinfo->jitter = current_jitter;
358 statinfo->diff = current_diff;
360 statinfo->lastnominaltime = nominaltime;
361 /* Calculate skew, i.e. absolute jitter that also catches clock drift
362 * Skew is positive if TS (nominal) is too fast
364 statinfo->skew = nominaltime - arrivaltime;
365 absskew = fabs(statinfo->skew);
366 if(absskew > fabs(statinfo->max_skew)) {
367 statinfo->max_skew = statinfo->skew;
369 /* Gather data for calculation of average, minimum and maximum framerate based on timestamp */
371 if (numPackets > 0 && (!hardPayloadType || !alternatePayloadType)) {
372 /* Skip first packet and possibly alternate payload type packets */
374 dt = nominaltime - statinfo->lastnominaltime;
376 numdt += (dt != 0 ? 1 : 0);
377 mindt = (dt < mindt ? dt : mindt);
378 maxdt = (dt > maxdt ? dt : maxdt);
381 /* Gather data for calculation of skew least square */
382 statinfo->sumt += 1.0 * current_time;
383 statinfo->sumTS += 1.0 * nominaltime;
384 statinfo->sumt2 += 1.0 * current_time * current_time;
385 statinfo->sumtTS += 1.0 * current_time * nominaltime;
387 if (!statinfo->first_packet) {
388 statinfo->delta = current_time-(statinfo->time);
392 /* Calculate the BW in Kbps adding the IP+UDP header to the RTP -> 20bytes(IP) + 8bytes(UDP) */
393 if (pinfo->net_src.type == AT_IPv6) {
394 statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 48;
396 statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 28;
398 statinfo->bw_history[statinfo->bw_index].time = current_time;
400 /* Check if there are more than 1sec in the history buffer to calculate BW in bps. If so, remove those for the calculation */
401 while ((statinfo->bw_history[statinfo->bw_start_index].time+1000/* ms */)<current_time){
402 statinfo->total_bytes -= statinfo->bw_history[statinfo->bw_start_index].bytes;
403 statinfo->bw_start_index++;
404 if (statinfo->bw_start_index == BUFF_BW) statinfo->bw_start_index=0;
406 /* IP hdr + UDP + RTP */
407 if (pinfo->net_src.type == AT_IPv6){
408 statinfo->total_bytes += rtpinfo->info_data_len + 48;
410 statinfo->total_bytes += rtpinfo->info_data_len + 28;
412 statinfo->bandwidth = (double)(statinfo->total_bytes*8)/1000;
413 statinfo->bw_index++;
414 if (statinfo->bw_index == BUFF_BW) statinfo->bw_index = 0;
417 /* Used by GTK code only */
418 statinfo->delta_timestamp = guint32_wraparound_diff(rtpinfo->info_timestamp, statinfo->timestamp);
420 /* Is it a packet with the mark bit set? */
421 if (rtpinfo->info_marker_set) {
422 statinfo->flags |= STAT_FLAG_MARKER;
425 /* Difference can be negative. We don't expect difference bigger than 31 bits. Difference don't care about wrap around. */
426 gint32 tsdelta=rtpinfo->info_timestamp - statinfo->timestamp;
428 statinfo->flags |= STAT_FLAG_WRONG_TIMESTAMP;
430 /* Is it a regular packet? */
431 if (!(statinfo->flags & STAT_FLAG_FIRST)
432 && !(statinfo->flags & STAT_FLAG_MARKER)
433 && !(statinfo->flags & STAT_FLAG_PT_CN)
434 && !(statinfo->flags & STAT_FLAG_WRONG_TIMESTAMP)
435 && !(statinfo->flags & STAT_FLAG_FOLLOW_PT_CN)) {
436 /* Include it in maximum delta calculation */
437 if (statinfo->delta > statinfo->max_delta) {
438 statinfo->max_delta = statinfo->delta;
439 statinfo->max_nr = pinfo->num;
441 if (clock_rate != 0) {
442 /* Maximum and mean jitter calculation */
443 if (statinfo->jitter > statinfo->max_jitter) {
444 statinfo->max_jitter = statinfo->jitter;
446 statinfo->mean_jitter = (statinfo->mean_jitter*statinfo->total_nr + current_diff) / (statinfo->total_nr+1);
449 /* Regular payload change? (CN ignored) */
450 if (!(statinfo->flags & STAT_FLAG_FIRST)
451 && !(statinfo->flags & STAT_FLAG_PT_CN)) {
452 if ((statinfo->pt != statinfo->reg_pt)
453 && (statinfo->reg_pt != PT_UNDEFINED)) {
454 statinfo->flags |= STAT_FLAG_REG_PT_CHANGE;
458 /* Set regular payload*/
459 if (!(statinfo->flags & STAT_FLAG_PT_CN)) {
460 statinfo->reg_pt = statinfo->pt;
463 statinfo->time = current_time;
464 statinfo->timestamp = rtpinfo->info_timestamp;
465 statinfo->stop_seq_nr = rtpinfo->info_seq_num;
466 statinfo->total_nr++;
467 statinfo->last_payload_len = rtpinfo->info_payload_len - rtpinfo->info_padding_count;
473 * Editor modelines - https://www.wireshark.org/tools/modelines.html
478 * indent-tabs-mode: nil
481 * ex: set shiftwidth=4 tabstop=8 expandtab:
482 * :indentSize=4:tabSize=8:noTabs=true: