aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJirka Novak <j.novak@netsystem.cz>2021-01-03 08:03:46 +0100
committerAndersBroman <a.broman58@gmail.com>2021-01-03 16:53:21 +0000
commit7928f81b10eae1133da1cb313eb53ffd82178f23 (patch)
treed998015ca76e2b3be1c7241df4e50871ff2404aa
parent85deb99637672f2be1f64ab4b07676b91613b6e0 (diff)
downloadwireshark-7928f81b10eae1133da1cb313eb53ffd82178f23.tar.gz
wireshark-7928f81b10eae1133da1cb313eb53ffd82178f23.tar.bz2
wireshark-7928f81b10eae1133da1cb313eb53ffd82178f23.zip
RTP processing: Modified RTP sequence verification
The patch changes: - Removed first_packet_mac_addr staff. It was commented out many years ago... - Removed delta_timestamp item. Not used. - Sequence verification takes into account timestamp therefore it is able to detect delayed packets more clearly. As consequence of it, #16330 is solved. - If packet is delayed, it is not used in calculation of diff/jitter/skew. It just mess output. As consequence of it, #16330 is solved. I checked output with many RTP streams and looks well. But I have no sample with wrapped timestamp and I have just a few samples with missing/reordered packets. Nevertheless all are calculated same way as before and #16330 is solved too.
-rw-r--r--ui/tap-rtp-analysis.c182
-rw-r--r--ui/tap-rtp-analysis.h4
-rw-r--r--ui/tap-rtp-common.c2
3 files changed, 103 insertions, 85 deletions
diff --git a/ui/tap-rtp-analysis.c b/ui/tap-rtp-analysis.c
index ee7158eb9e..f1e2c3a4f9 100644
--- a/ui/tap-rtp-analysis.c
+++ b/ui/tap-rtp-analysis.c
@@ -156,6 +156,8 @@ get_dyn_pt_clock_rate(const gchar *payload_type_str)
return 0;
}
+#define TIMESTAMP_DIFFERENCE(v1,v2) ((gint64)v2-(gint64)v1)
+
/****************************************************************************/
void
rtppacket_analyse(tap_rtp_stat_t *statinfo,
@@ -170,6 +172,7 @@ rtppacket_analyse(tap_rtp_stat_t *statinfo,
double expected_time;
double absskew;
guint32 clock_rate;
+ gboolean in_time_sequence;
/* Store the current time */
current_time = nstime_to_msec(&pinfo->rel_ts);
@@ -177,9 +180,6 @@ rtppacket_analyse(tap_rtp_stat_t *statinfo,
/* Is this the first packet we got in this direction? */
if (statinfo->first_packet) {
/* Save the MAC address of the first RTP frame */
- if( pinfo->dl_src.type == AT_ETHER){
- copy_address(&(statinfo->first_packet_mac_addr), &(pinfo->dl_src));
- }
statinfo->start_seq_nr = rtpinfo->info_seq_num;
statinfo->stop_seq_nr = rtpinfo->info_seq_num;
statinfo->seq_num = rtpinfo->info_seq_num;
@@ -220,23 +220,10 @@ rtppacket_analyse(tap_rtp_stat_t *statinfo,
/* Reset flags */
statinfo->flags = 0;
-#if 0
- /*According to bug https://gitlab.com/wireshark/wireshark/-/issues/11478
- * this code causes problems. A better solution is needed if there is need for the functionality */
- /* Try to detect duplicated packets due to mirroring/span ports by comparing src MAC addresses.
- * Check for duplicates (src mac differs from first_packet_mac_addr) */
- */
- if( pinfo->dl_src.type == AT_ETHER){
- if(!addresses_equal(&(statinfo->first_packet_mac_addr), &(pinfo->dl_src))){
- statinfo->flags |= STAT_FLAG_DUP_PKT;
- statinfo->delta = current_time-(statinfo->time);
- return;
- }
- }
-#endif
+
/* When calculating expected rtp packets the seq number can wrap around
* so we have to count the number of cycles
- * Variable cycles counts the wraps around in forwarding connection and
+ * Variable seq_cycles counts the wraps around in forwarding connection and
* under is flag that indicates where we are
*
* XXX How to determine number of cycles with all possible lost, late
@@ -248,11 +235,32 @@ rtppacket_analyse(tap_rtp_stat_t *statinfo,
* where below code won't work correctly - statistic may be wrong then.
*/
+ /* Check if time sequence of packets is in order. We check whether
+ * timestamp difference is below 1/2 of timestamp range (hours or days).
+ * Packets can be in pure sequence or sequence can be wrapped arround
+ * 0xFFFFFFFF.
+ */
+ if ((statinfo->first_timestamp <= rtpinfo->info_timestamp) &&
+ TIMESTAMP_DIFFERENCE(statinfo->first_timestamp, rtpinfo->info_timestamp) < 0x80000000) {
+ // Normal timestamp sequence
+ in_time_sequence = TRUE;
+ } else if ((statinfo->first_timestamp > rtpinfo->info_timestamp) &&
+ (TIMESTAMP_DIFFERENCE(0x00000000,statinfo->first_timestamp) + TIMESTAMP_DIFFERENCE(rtpinfo->info_timestamp, 0xFFFFFFFF)) < 0x80000000) {
+ // Normal timestamp sequence with wraparound
+ in_time_sequence = TRUE;
+ } else {
+ // New packet is not in sequence (is in past)
+ in_time_sequence = FALSE;
+ statinfo->flags |= STAT_FLAG_WRONG_TIMESTAMP;
+ }
+
/* So if the current sequence number is less than the start one
* we assume, that there is another cycle running
*/
- if ((rtpinfo->info_seq_num < statinfo->start_seq_nr) && (statinfo->under == FALSE)){
- statinfo->cycles++;
+ if ((rtpinfo->info_seq_num < statinfo->start_seq_nr) &&
+ in_time_sequence &&
+ (statinfo->under == FALSE)) {
+ statinfo->seq_cycles++;
statinfo->under = TRUE;
}
/* what if the start seq nr was 0? Then the above condition will never
@@ -260,12 +268,15 @@ rtppacket_analyse(tap_rtp_stat_t *statinfo,
* if one of the packets with seq nr 0 or 65535 would be lost or late
*/
else if ((rtpinfo->info_seq_num == 0) && (statinfo->stop_seq_nr == 65535) &&
- (statinfo->under == FALSE)) {
- statinfo->cycles++;
+ in_time_sequence &&
+ (statinfo->under == FALSE)) {
+ statinfo->seq_cycles++;
statinfo->under = TRUE;
}
/* the whole round is over, so reset the flag */
- else if ((rtpinfo->info_seq_num > statinfo->start_seq_nr) && (statinfo->under != FALSE)) {
+ else if ((rtpinfo->info_seq_num > statinfo->start_seq_nr) &&
+ in_time_sequence &&
+ (statinfo->under != FALSE)) {
statinfo->under = FALSE;
}
@@ -276,17 +287,25 @@ rtppacket_analyse(tap_rtp_stat_t *statinfo,
/* If the current seq number equals the last one or if we are here for
* the first time, then it is ok, we just store the current one as the last one
*/
- if ( (statinfo->seq_num+1 == rtpinfo->info_seq_num) || (statinfo->flags & STAT_FLAG_FIRST) )
+ if ( in_time_sequence &&
+ ( (statinfo->seq_num+1 == rtpinfo->info_seq_num) || (statinfo->flags & STAT_FLAG_FIRST) )
+ ) {
statinfo->seq_num = rtpinfo->info_seq_num;
+ }
/* If the first one is 65535 we wrap */
- else if ( (statinfo->seq_num == 65535) && (rtpinfo->info_seq_num == 0) )
+ else if ( in_time_sequence &&
+ ( (statinfo->seq_num == 65535) && (rtpinfo->info_seq_num == 0) )
+ ) {
statinfo->seq_num = rtpinfo->info_seq_num;
+ }
/* Lost packets. If the prev seq is enormously larger than the cur seq
* we assume that instead of being massively late we lost the packet(s)
* that would have indicated the sequence number wrapping. An imprecise
* heuristic at best, but it seems to work well enough.
* https://gitlab.com/wireshark/wireshark/-/issues/5958 */
- else if (statinfo->seq_num+1 < rtpinfo->info_seq_num || statinfo->seq_num - rtpinfo->info_seq_num > 0xFF00) {
+ else if ( in_time_sequence &&
+ (statinfo->seq_num+1 < rtpinfo->info_seq_num || statinfo->seq_num - rtpinfo->info_seq_num > 0xFF00)
+ ) {
statinfo->seq_num = rtpinfo->info_seq_num;
statinfo->sequence++;
statinfo->flags |= STAT_FLAG_WRONG_SEQ;
@@ -336,56 +355,60 @@ rtppacket_analyse(tap_rtp_stat_t *statinfo,
}
}
- /* Handle wraparound ? */
- arrivaltime = current_time - statinfo->start_time;
+ /* diff/jitter/skew calculations are done just for in sequence packets */
+ if ( in_time_sequence ) {
- nominaltime = (double)(guint32_wraparound_diff(rtpinfo->info_timestamp, statinfo->first_timestamp));
+ /* Handle wraparound ? */
+ arrivaltime = current_time - statinfo->start_time;
- /* Can only analyze defined sampling rates */
- if (clock_rate != 0) {
- statinfo->clock_rate = clock_rate;
- /* Convert from sampling clock to ms */
- nominaltime = nominaltime /(clock_rate/1000);
+ nominaltime = (double)(guint32_wraparound_diff(rtpinfo->info_timestamp, statinfo->first_timestamp));
- /* Calculate the current jitter(in ms) */
- if (!statinfo->first_packet) {
- expected_time = statinfo->time + (nominaltime - statinfo->lastnominaltime);
- current_diff = fabs(current_time - expected_time);
- current_jitter = (15 * statinfo->jitter + current_diff) / 16;
+ /* Can only analyze defined sampling rates */
+ if (clock_rate != 0) {
+ statinfo->clock_rate = clock_rate;
+ /* Convert from sampling clock to ms */
+ nominaltime = nominaltime /(clock_rate/1000);
- statinfo->delta = current_time-(statinfo->time);
- statinfo->jitter = current_jitter;
- statinfo->diff = current_diff;
- }
- statinfo->lastnominaltime = nominaltime;
- /* Calculate skew, i.e. absolute jitter that also catches clock drift
- * Skew is positive if TS (nominal) is too fast
- */
- statinfo->skew = nominaltime - arrivaltime;
- absskew = fabs(statinfo->skew);
- if(absskew > fabs(statinfo->max_skew)) {
- statinfo->max_skew = statinfo->skew;
- }
- /* Gather data for calculation of average, minimum and maximum framerate based on timestamp */
-#if 0
- if (numPackets > 0 && (!hardPayloadType || !alternatePayloadType)) {
- /* Skip first packet and possibly alternate payload type packets */
- double dt;
- dt = nominaltime - statinfo->lastnominaltime;
- sumdt += 1.0 * dt;
- numdt += (dt != 0 ? 1 : 0);
- mindt = (dt < mindt ? dt : mindt);
- maxdt = (dt > maxdt ? dt : maxdt);
- }
-#endif
- /* Gather data for calculation of skew least square */
- statinfo->sumt += 1.0 * arrivaltime;
- statinfo->sumTS += 1.0 * nominaltime;
- statinfo->sumt2 += 1.0 * arrivaltime * arrivaltime;
- statinfo->sumtTS += 1.0 * arrivaltime * nominaltime;
- } else {
- if (!statinfo->first_packet) {
- statinfo->delta = current_time-(statinfo->time);
+ /* Calculate the current jitter(in ms) */
+ if (!statinfo->first_packet) {
+ expected_time = statinfo->time + (nominaltime - statinfo->lastnominaltime);
+ current_diff = fabs(current_time - expected_time);
+ current_jitter = (15 * statinfo->jitter + current_diff) / 16;
+
+ statinfo->delta = current_time-(statinfo->time);
+ statinfo->jitter = current_jitter;
+ statinfo->diff = current_diff;
+ }
+ statinfo->lastnominaltime = nominaltime;
+ /* Calculate skew, i.e. absolute jitter that also catches clock drift
+ * Skew is positive if TS (nominal) is too fast
+ */
+ statinfo->skew = nominaltime - arrivaltime;
+ absskew = fabs(statinfo->skew);
+ if (absskew > fabs(statinfo->max_skew)) {
+ statinfo->max_skew = statinfo->skew;
+ }
+ /* Gather data for calculation of average, minimum and maximum framerate based on timestamp */
+ #if 0
+ if (numPackets > 0 && (!hardPayloadType || !alternatePayloadType)) {
+ /* Skip first packet and possibly alternate payload type packets */
+ double dt;
+ dt = nominaltime - statinfo->lastnominaltime;
+ sumdt += 1.0 * dt;
+ numdt += (dt != 0 ? 1 : 0);
+ mindt = (dt < mindt ? dt : mindt);
+ maxdt = (dt > maxdt ? dt : maxdt);
+ }
+ #endif
+ /* Gather data for calculation of skew least square */
+ statinfo->sumt += 1.0 * arrivaltime;
+ statinfo->sumTS += 1.0 * nominaltime;
+ statinfo->sumt2 += 1.0 * arrivaltime * arrivaltime;
+ statinfo->sumtTS += 1.0 * arrivaltime * nominaltime;
+ } else {
+ if (!statinfo->first_packet) {
+ statinfo->delta = current_time-(statinfo->time);
+ }
}
}
@@ -414,19 +437,11 @@ rtppacket_analyse(tap_rtp_stat_t *statinfo,
if (statinfo->bw_index == BUFF_BW) statinfo->bw_index = 0;
- /* Used by GTK code only */
- statinfo->delta_timestamp = guint32_wraparound_diff(rtpinfo->info_timestamp, statinfo->timestamp);
-
/* Is it a packet with the mark bit set? */
if (rtpinfo->info_marker_set) {
statinfo->flags |= STAT_FLAG_MARKER;
}
- /* Difference can be negative. We don't expect difference bigger than 31 bits. Difference don't care about wrap around. */
- gint32 tsdelta=rtpinfo->info_timestamp - statinfo->timestamp;
- if (tsdelta < 0) {
- statinfo->flags |= STAT_FLAG_WRONG_TIMESTAMP;
- }
/* Is it a regular packet? */
if (!(statinfo->flags & STAT_FLAG_FIRST)
&& !(statinfo->flags & STAT_FLAG_MARKER)
@@ -460,7 +475,12 @@ rtppacket_analyse(tap_rtp_stat_t *statinfo,
statinfo->reg_pt = statinfo->pt;
}
- statinfo->time = current_time;
+ if (in_time_sequence) {
+ /* We remember last time just for in_time sequence packets
+ * therefore diff calculations are correct for it
+ */
+ statinfo->time = current_time;
+ }
statinfo->timestamp = rtpinfo->info_timestamp;
statinfo->stop_seq_nr = rtpinfo->info_seq_num;
statinfo->total_nr++;
diff --git a/ui/tap-rtp-analysis.h b/ui/tap-rtp-analysis.h
index 7ed83b980f..99ebb72d15 100644
--- a/ui/tap-rtp-analysis.h
+++ b/ui/tap-rtp-analysis.h
@@ -45,12 +45,10 @@ typedef struct _tap_rtp_stat_t {
/* all of the following fields will be initialized after
* rtppacket_analyse has been called
*/
- address first_packet_mac_addr; /**< MAC address of first packet, used to determine duplicates due to mirroring */
guint32 flags; /* see STAT_FLAG-defines below */
guint16 seq_num;
guint32 timestamp;
guint32 first_timestamp;
- guint32 delta_timestamp;
double bandwidth;
bw_history_item bw_history[BUFF_BW];
guint16 bw_start_index;
@@ -78,7 +76,7 @@ typedef struct _tap_rtp_stat_t {
guint32 total_nr;
guint32 sequence;
gboolean under;
- gint cycles;
+ gint seq_cycles;
guint16 pt;
int reg_pt;
guint32 first_packet_num;
diff --git a/ui/tap-rtp-common.c b/ui/tap-rtp-common.c
index 2efa2dcaa2..baa3a6c9cc 100644
--- a/ui/tap-rtp-common.c
+++ b/ui/tap-rtp-common.c
@@ -487,7 +487,7 @@ void rtpstream_info_calculate(const rtpstream_info_t *strinfo, rtpstream_info_ca
calc->packet_count = strinfo->packet_count;
/* packet count, lost packets */
- calc->packet_expected = (strinfo->rtp_stats.stop_seq_nr + strinfo->rtp_stats.cycles*65536)
+ calc->packet_expected = (strinfo->rtp_stats.stop_seq_nr + strinfo->rtp_stats.seq_cycles*0x10000)
- strinfo->rtp_stats.start_seq_nr + 1;
calc->total_nr = strinfo->rtp_stats.total_nr;
calc->lost_num = calc->packet_expected - strinfo->rtp_stats.total_nr;