From a5a59c9a05982efdcf2a87337d9dc763beb5c3bd Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 6 Oct 2014 20:04:42 +0200 Subject: mgcp: Move Annex A counting out of patch/count method mgcp_patch_and_count has grown due supporting linearizing timestamps, ssrc and other things for equipment like the ip.access nanoBTS. Fight back and move the Annex A code into a dedicated method. The result is updated as we now count after all the patching and for the Annex A code no change in SSRC can be detected. --- openbsc/include/openbsc/mgcp_internal.h | 13 ++-- openbsc/src/libmgcp/mgcp_network.c | 104 +++++++++++++++++++------------- openbsc/tests/mgcp/mgcp_test.c | 10 +-- openbsc/tests/mgcp/mgcp_test.ok | 72 +++++++++++----------- 4 files changed, 113 insertions(+), 86 deletions(-) diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h index 3bccb39df..0ec18cd5b 100644 --- a/openbsc/include/openbsc/mgcp_internal.h +++ b/openbsc/include/openbsc/mgcp_internal.h @@ -54,17 +54,22 @@ struct mgcp_rtp_state { uint32_t orig_ssrc; - uint16_t base_seq; int seq_offset; - int cycles; int32_t timestamp_offset; uint32_t packet_duration; - uint32_t jitter; - int32_t transit; struct mgcp_rtp_stream_state in_stream; struct mgcp_rtp_stream_state out_stream; + + /* jitter and packet loss calculation */ + int stats_initialized; + uint16_t stats_base_seq; + uint16_t stats_max_seq; + uint32_t stats_ssrc; + uint32_t stats_jitter; + int32_t stats_transit; + int stats_cycles; }; struct mgcp_rtp_codec { diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index be8ba1bf0..888ec6eb7 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -331,6 +331,60 @@ void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp, *fmtp_extra = endp->bts_end.fmtp_extra; } + +void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state, + const uint16_t seq, const int32_t transit, + const uint32_t ssrc) +{ + uint16_t udelta; + int32_t d; + + /* initialize or re-initialize */ + if (!state->stats_initialized || state->stats_ssrc != ssrc) { + state->stats_initialized = 1; + state->stats_base_seq = seq; + state->stats_max_seq = seq - 1; + state->stats_ssrc = ssrc; + state->stats_jitter = 0; + state->stats_transit = transit; + state->stats_cycles = 0; + } + + /* + * The below takes the shape of the validation of + * Appendix A. Check if there is something weird with + * the sequence number, otherwise check for a wrap + * around in the sequence number. + * It can't wrap during the initialization so let's + * skip it here. The Appendix A probably doesn't have + * this issue because of the probation. + */ + udelta = seq - state->stats_max_seq; + if (udelta < RTP_MAX_DROPOUT) { + if (seq < state->stats_max_seq) + state->stats_cycles += RTP_SEQ_MOD; + } else if (udelta <= RTP_SEQ_MOD - RTP_MAX_MISORDER) { + LOGP(DMGCP, LOGL_NOTICE, + "RTP seqno made a very large jump on 0x%x delta: %u\n", + ENDPOINT_NUMBER(endp), udelta); + } + + /* + * Calculate the jitter between the two packages. The TS should be + * taken closer to the read function. This was taken from the + * Appendix A of RFC 3550. Timestamp and arrival_time have a 1/rate + * resolution. + */ + d = transit - state->stats_transit; + state->stats_transit = transit; + if (d < 0) + d = -d; + state->stats_jitter += d - ((state->stats_jitter + 8) >> 4); + state->stats_max_seq = seq; +} + + + /** * The RFC 3550 Appendix A assumes there are multiple sources but * some of the supported endpoints (e.g. the nanoBTS) can only handle @@ -344,8 +398,8 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta char *data, int len) { uint32_t arrival_time; - int32_t transit, d; - uint16_t seq, udelta; + int32_t transit; + uint16_t seq; uint32_t timestamp, ssrc; struct rtp_hdr *rtp_hdr; int payload = rtp_end->codec.payload_type; @@ -361,13 +415,10 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta transit = arrival_time - timestamp; if (!state->initialized) { + state->initialized = 1; state->in_stream.last_seq = seq - 1; state->in_stream.ssrc = state->orig_ssrc = ssrc; state->in_stream.last_tsdelta = 0; - state->base_seq = seq; - state->initialized = 1; - state->jitter = 0; - state->transit = transit; state->packet_duration = mgcp_rtp_packet_duration(endp, rtp_end); state->out_stream = state->in_stream; state->out_stream.last_timestamp = timestamp; @@ -398,8 +449,6 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta endp->conn_mode); state->in_stream.ssrc = ssrc; - state->jitter = 0; - state->transit = transit; if (rtp_end->force_constant_ssrc) { int16_t delta_seq; @@ -470,34 +519,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta addr, seq, timestamp, "output", &state->out_stream.last_tsdelta); - /* - * The below takes the shape of the validation from Appendix A. Check - * if there is something weird with the sequence number, otherwise check - * for a wrap around in the sequence number. - * - * Note that last_seq is used where the appendix mentions max_seq. - */ - udelta = seq - state->out_stream.last_seq; - if (udelta < RTP_MAX_DROPOUT) { - if (seq < state->out_stream.last_seq) - state->cycles += RTP_SEQ_MOD; - } else if (udelta <= RTP_SEQ_MOD - RTP_MAX_MISORDER) { - LOGP(DMGCP, LOGL_NOTICE, - "RTP seqno made a very large jump on 0x%x delta: %u\n", - ENDPOINT_NUMBER(endp), udelta); - } - - /* - * Calculate the jitter between the two packages. The TS should be - * taken closer to the read function. This was taken from the - * Appendix A of RFC 3550. Timestamp and arrival_time have a 1/rate - * resolution. - */ - d = transit - state->transit; - state->transit = transit; - if (d < 0) - d = -d; - state->jitter += d - ((state->jitter + 8) >> 4); + mgcp_rtp_annex_count(endp, state, seq, transit, ssrc); /* Save output values */ state->out_stream.last_seq = seq; @@ -998,10 +1020,10 @@ void mgcp_state_calc_loss(struct mgcp_rtp_state *state, struct mgcp_rtp_end *end, uint32_t *expected, int *loss) { - *expected = state->cycles + state->out_stream.last_seq; - *expected = *expected - state->base_seq + 1; + *expected = state->stats_cycles + state->stats_max_seq; + *expected = *expected - state->stats_base_seq + 1; - if (!state->initialized) { + if (!state->stats_initialized) { *expected = 0; *loss = 0; return; @@ -1023,7 +1045,7 @@ void mgcp_state_calc_loss(struct mgcp_rtp_state *state, uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *state) { - if (!state->initialized) + if (!state->stats_initialized) return 0; - return state->jitter >> 4; + return state->stats_jitter >> 4; } diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c index a0575032c..e145c6ab9 100644 --- a/openbsc/tests/mgcp/mgcp_test.c +++ b/openbsc/tests/mgcp/mgcp_test.c @@ -699,10 +699,10 @@ static void test_packet_loss_calc(void) memset(&state, 0, sizeof(state)); memset(&rtp, 0, sizeof(rtp)); - state.initialized = 1; - state.base_seq = pl_test_dat[i].base_seq; - state.out_stream.last_seq = pl_test_dat[i].max_seq; - state.cycles = pl_test_dat[i].cycles; + state.stats_initialized = 1; + state.stats_base_seq = pl_test_dat[i].base_seq; + state.stats_max_seq = pl_test_dat[i].max_seq; + state.stats_cycles = pl_test_dat[i].cycles; rtp.packets = pl_test_dat[i].packets; mgcp_state_calc_loss(&state, &rtp, &expected, &loss); @@ -921,7 +921,7 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts) state.out_stream.err_ts_counter - last_out_ts_err_cnt); printf("Stats: Jitter = %u, Transit = %d\n", - mgcp_state_calc_jitter(&state), state.transit); + mgcp_state_calc_jitter(&state), state.stats_transit); last_in_ts_err_cnt = state.in_stream.err_ts_counter; last_out_ts_err_cnt = state.out_stream.err_ts_counter; diff --git a/openbsc/tests/mgcp/mgcp_test.ok b/openbsc/tests/mgcp/mgcp_test.ok index a56a3fd1b..a25bed4d3 100644 --- a/openbsc/tests/mgcp/mgcp_test.ok +++ b/openbsc/tests/mgcp/mgcp_test.ok @@ -142,58 +142,58 @@ Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 Stats: Jitter = 15, Transit = 40 In TS: 34688, dTS: 0, Seq: 12 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 +Stats: Jitter = 2065, Transit = -32768 In TS: 34848, dTS: 160, Seq: 13 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 +Stats: Jitter = 1935, Transit = -32768 In TS: 35008, dTS: 160, Seq: 14 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 +Stats: Jitter = 1814, Transit = -32768 In TS: 35128, dTS: 120, Seq: 15 Out TS change: 120, dTS: 120, Seq change: 1, TS Err change: in +1, out +1 -Stats: Jitter = 2, Transit = -32728 +Stats: Jitter = 1704, Transit = -32728 In TS: 35288, dTS: 160, Seq: 16 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 2, Transit = -32728 +Stats: Jitter = 1597, Transit = -32728 In TS: 35448, dTS: 160, Seq: 17 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 2, Transit = -32728 +Stats: Jitter = 1497, Transit = -32728 In TS: 35768, dTS: 160, Seq: 19 Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0 -Stats: Jitter = 12, Transit = -32888 +Stats: Jitter = 1414, Transit = -32888 In TS: 35928, dTS: 160, Seq: 20 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 11, Transit = -32888 +Stats: Jitter = 1325, Transit = -32888 In TS: 36088, dTS: 160, Seq: 21 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 20, Transit = -33048 +Stats: Jitter = 1252, Transit = -33048 In TS: 36088, dTS: 160, Seq: 21 Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0 -Stats: Jitter = 29, Transit = -32888 +Stats: Jitter = 1184, Transit = -32888 In TS: 36248, dTS: 160, Seq: 22 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 27, Transit = -32888 +Stats: Jitter = 1110, Transit = -32888 In TS: 36408, dTS: 160, Seq: 23 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 25, Transit = -32888 +Stats: Jitter = 1041, Transit = -32888 In TS: 36568, dTS: 160, Seq: 23 Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1 -Stats: Jitter = 24, Transit = -32888 +Stats: Jitter = 976, Transit = -32888 In TS: 36728, dTS: 160, Seq: 24 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 22, Transit = -32888 +Stats: Jitter = 915, Transit = -32888 In TS: 36888, dTS: 160, Seq: 25 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 21, Transit = -32888 +Stats: Jitter = 857, Transit = -32888 In TS: 160000, dTS: 0, Seq: 1000 Out TS change: 12000, dTS: 12000, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 +Stats: Jitter = 7748, Transit = -144000 In TS: 160160, dTS: 160, Seq: 1001 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 +Stats: Jitter = 7264, Transit = -144000 In TS: 160320, dTS: 160, Seq: 1002 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 +Stats: Jitter = 6810, Transit = -144000 Testing packet error detection. Output SSRC changed to 11223344 In TS: 0, dTS: 0, Seq: 0 @@ -422,57 +422,57 @@ Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 Stats: Jitter = 15, Transit = 40 In TS: 34688, dTS: 0, Seq: 12 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 +Stats: Jitter = 2065, Transit = -32768 In TS: 34848, dTS: 160, Seq: 13 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 +Stats: Jitter = 1935, Transit = -32768 In TS: 35008, dTS: 160, Seq: 14 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -32768 +Stats: Jitter = 1814, Transit = -32768 In TS: 35128, dTS: 120, Seq: 15 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +1, out +0 -Stats: Jitter = 2, Transit = -32728 +Stats: Jitter = 1704, Transit = -32728 In TS: 35288, dTS: 160, Seq: 16 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 2, Transit = -32728 +Stats: Jitter = 1597, Transit = -32728 In TS: 35448, dTS: 160, Seq: 17 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 2, Transit = -32728 +Stats: Jitter = 1497, Transit = -32728 In TS: 35768, dTS: 160, Seq: 19 Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0 -Stats: Jitter = 12, Transit = -32888 +Stats: Jitter = 1414, Transit = -32888 In TS: 35928, dTS: 160, Seq: 20 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 11, Transit = -32888 +Stats: Jitter = 1325, Transit = -32888 In TS: 36088, dTS: 160, Seq: 21 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 20, Transit = -33048 +Stats: Jitter = 1252, Transit = -33048 In TS: 36088, dTS: 160, Seq: 21 Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0 -Stats: Jitter = 29, Transit = -32888 +Stats: Jitter = 1184, Transit = -32888 In TS: 36248, dTS: 160, Seq: 22 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 27, Transit = -32888 +Stats: Jitter = 1110, Transit = -32888 In TS: 36408, dTS: 160, Seq: 23 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 25, Transit = -32888 +Stats: Jitter = 1041, Transit = -32888 In TS: 36568, dTS: 160, Seq: 23 Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1 -Stats: Jitter = 24, Transit = -32888 +Stats: Jitter = 976, Transit = -32888 In TS: 36728, dTS: 160, Seq: 24 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 22, Transit = -32888 +Stats: Jitter = 915, Transit = -32888 In TS: 36888, dTS: 160, Seq: 25 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 21, Transit = -32888 +Stats: Jitter = 857, Transit = -32888 In TS: 160000, dTS: 0, Seq: 1000 Out TS change: 12000, dTS: 12000, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 +Stats: Jitter = 7748, Transit = -144000 In TS: 160160, dTS: 160, Seq: 1001 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 +Stats: Jitter = 7264, Transit = -144000 In TS: 160320, dTS: 160, Seq: 1002 Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 -Stats: Jitter = 0, Transit = -144000 +Stats: Jitter = 6810, Transit = -144000 Testing multiple payload types Done -- cgit v1.2.3