This patch extends the existing RTP error check test by adding support for selectively enabling/disabling SSRC and timestamp patching. The test is repeated for all combinations thereof.
Sponsored-by: On-Waves ehf --- openbsc/tests/mgcp/mgcp_test.c | 13 +++++++---- openbsc/tests/mgcp/mgcp_test.ok | 48 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 4 deletions(-)
diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c index c58f52d..4326738 100644 --- a/openbsc/tests/mgcp/mgcp_test.c +++ b/openbsc/tests/mgcp/mgcp_test.c @@ -516,7 +516,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta struct mgcp_rtp_end *rtp_end, struct sockaddr_in *addr, char *data, int len);
-static void test_packet_error_detection(void) +static void test_packet_error_detection(int patch_ssrc, int patch_ts) { int i;
@@ -527,7 +527,9 @@ static void test_packet_error_detection(void) struct sockaddr_in addr = {0}; char buffer[4096];
- printf("Testing packet error detection.\n"); + printf("Testing packet error detection%s%s.\n", + patch_ssrc ? ", patch SSRC" : "", + patch_ts ? ", patch timestamps" : "");
memset(&trunk, 0, sizeof(trunk)); memset(&endp, 0, sizeof(endp)); @@ -545,7 +547,7 @@ static void test_packet_error_detection(void) mgcp_free_endp(&endp);
rtp->payload_type = 98; - endp.allow_patch = 1; + endp.allow_patch = patch_ssrc;
for (i = 0; i < ARRAY_SIZE(test_rtp_packets1); ++i) { struct rtp_packet_info *info = test_rtp_packets1 + i; @@ -575,7 +577,10 @@ int main(int argc, char **argv) test_packet_loss_calc(); test_rqnt_cb(); test_mgcp_stats(); - test_packet_error_detection(); + test_packet_error_detection(1, 0); + test_packet_error_detection(0, 0); + test_packet_error_detection(0, 1); + test_packet_error_detection(1, 1);
printf("Done\n"); return EXIT_SUCCESS; diff --git a/openbsc/tests/mgcp/mgcp_test.ok b/openbsc/tests/mgcp/mgcp_test.ok index 3bfd78b..71293ad 100644 --- a/openbsc/tests/mgcp/mgcp_test.ok +++ b/openbsc/tests/mgcp/mgcp_test.ok @@ -42,6 +42,22 @@ Testing packet loss calculation. Testing stat parsing Parsing result: 0 Parsing result: 0 +Testing packet error detection, patch SSRC. +TS: 0, dTS: 0, TS Errs: in 0, out 0 +TS: 160, dTS: 160, TS Errs: in 0, out 0 +TS: 320, dTS: 160, TS Errs: in 0, out 0 +TS: 320, dTS: 160, TS Errs: in 1, out 1 +TS: 480, dTS: 160, TS Errs: in 1, out 1 +TS: 640, dTS: 160, TS Errs: in 1, out 1 +TS: 960, dTS: 320, TS Errs: in 2, out 2 +TS: 1120, dTS: 160, TS Errs: in 3, out 3 +TS: 1280, dTS: 160, TS Errs: in 3, out 3 +TS: 1400, dTS: 120, TS Errs: in 4, out 4 +TS: 1560, dTS: 160, TS Errs: in 5, out 5 +TS: 1720, dTS: 160, TS Errs: in 5, out 5 +TS: 1880, dTS: 160, TS Errs: in 5, out 5 +TS: 2040, dTS: 160, TS Errs: in 5, out 5 +TS: 2200, dTS: 160, TS Errs: in 5, out 5 Testing packet error detection. TS: 0, dTS: 0, TS Errs: in 0, out 0 TS: 160, dTS: 160, TS Errs: in 0, out 0 @@ -55,6 +71,38 @@ TS: 1280, dTS: 160, TS Errs: in 3, out 3 TS: 1400, dTS: 120, TS Errs: in 4, out 4 TS: 1560, dTS: 160, TS Errs: in 5, out 5 TS: 1720, dTS: 160, TS Errs: in 5, out 5 +TS: 34688, dTS: 160, TS Errs: in 5, out 5 +TS: 34848, dTS: 160, TS Errs: in 5, out 5 +TS: 35008, dTS: 160, TS Errs: in 5, out 5 +Testing packet error detection, patch timestamps. +TS: 0, dTS: 0, TS Errs: in 0, out 0 +TS: 160, dTS: 160, TS Errs: in 0, out 0 +TS: 320, dTS: 160, TS Errs: in 0, out 0 +TS: 320, dTS: 160, TS Errs: in 1, out 1 +TS: 480, dTS: 160, TS Errs: in 1, out 1 +TS: 640, dTS: 160, TS Errs: in 1, out 1 +TS: 960, dTS: 320, TS Errs: in 2, out 2 +TS: 1120, dTS: 160, TS Errs: in 3, out 3 +TS: 1280, dTS: 160, TS Errs: in 3, out 3 +TS: 1400, dTS: 120, TS Errs: in 4, out 4 +TS: 1560, dTS: 160, TS Errs: in 5, out 5 +TS: 1720, dTS: 160, TS Errs: in 5, out 5 +TS: 34688, dTS: 160, TS Errs: in 5, out 5 +TS: 34848, dTS: 160, TS Errs: in 5, out 5 +TS: 35008, dTS: 160, TS Errs: in 5, out 5 +Testing packet error detection, patch SSRC, patch timestamps. +TS: 0, dTS: 0, TS Errs: in 0, out 0 +TS: 160, dTS: 160, TS Errs: in 0, out 0 +TS: 320, dTS: 160, TS Errs: in 0, out 0 +TS: 320, dTS: 160, TS Errs: in 1, out 1 +TS: 480, dTS: 160, TS Errs: in 1, out 1 +TS: 640, dTS: 160, TS Errs: in 1, out 1 +TS: 960, dTS: 320, TS Errs: in 2, out 2 +TS: 1120, dTS: 160, TS Errs: in 3, out 3 +TS: 1280, dTS: 160, TS Errs: in 3, out 3 +TS: 1400, dTS: 120, TS Errs: in 4, out 4 +TS: 1560, dTS: 160, TS Errs: in 5, out 5 +TS: 1720, dTS: 160, TS Errs: in 5, out 5 TS: 1880, dTS: 160, TS Errs: in 5, out 5 TS: 2040, dTS: 160, TS Errs: in 5, out 5 TS: 2200, dTS: 160, TS Errs: in 5, out 5
The tsdelta computation and error detection didn't handle the intialisation phase properly.
This patches fixes this by skipping the output timing validation when the SSRCs don't match.
Sponsored-by: On-Waves ehf --- openbsc/src/libmgcp/mgcp_network.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index 75d39c1..06452a6 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -237,6 +237,15 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta state->jitter = 0; state->transit = arrival_time - timestamp; state->out_stream = state->in_stream; + state->out_stream.last_timestamp = timestamp; + state->out_stream.ssrc = rtp_hdr->ssrc - 1; /* SSRC change <=> initialisation */ + LOGP(DMGCP, LOGL_INFO, + "Initializing stream on 0x%x SSRC: %u timestamp: %u " + "from %s:%d in %d\n", + ENDPOINT_NUMBER(endp), state->in_stream.ssrc, + state->seq_offset, + inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), + endp->conn_mode); } else if (state->in_stream.ssrc != rtp_hdr->ssrc) { int32_t tsdelta = state->out_stream.last_tsdelta; if (tsdelta == 0) { @@ -286,9 +295,10 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta }
/* Check again, whether the timestamps are still valid */ - check_rtp_timestamp(endp, &state->out_stream, rtp_end, addr, - seq, timestamp, "output", - &state->out_stream.last_tsdelta); + if (state->out_stream.ssrc == rtp_hdr->ssrc) + check_rtp_timestamp(endp, &state->out_stream, rtp_end, addr, + seq, timestamp, "output", + &state->out_stream.last_tsdelta);
/* * The below takes the shape of the validation from Appendix A. Check
This adds datastructures and a VTY frontend to configure the different type of RTP header patching: SSRC and timestamp.
Note that timestamp patching is not yet implemented.
Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/mgcp.h | 4 +++ openbsc/include/openbsc/mgcp_internal.h | 10 ++++-- openbsc/src/libmgcp/mgcp_network.c | 2 +- openbsc/src/libmgcp/mgcp_protocol.c | 12 ++++++- openbsc/src/libmgcp/mgcp_vty.c | 56 ++++++++++++++++++++++++++++++- openbsc/tests/mgcp/mgcp_test.c | 6 +++- 6 files changed, 83 insertions(+), 7 deletions(-)
diff --git a/openbsc/include/openbsc/mgcp.h b/openbsc/include/openbsc/mgcp.h index 4e22e0f..8ab52ce 100644 --- a/openbsc/include/openbsc/mgcp.h +++ b/openbsc/include/openbsc/mgcp.h @@ -118,6 +118,10 @@ struct mgcp_trunk_config {
int omit_rtcp;
+ /* RTP patching */ + int force_constant_ssrc; /* 0: don't, 1: once */ + int force_constant_timing; + /* spec handling */ int force_realloc;
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h index 0b52c1c..02e193d 100644 --- a/openbsc/include/openbsc/mgcp_internal.h +++ b/openbsc/include/openbsc/mgcp_internal.h @@ -83,6 +83,10 @@ struct mgcp_rtp_end { int frames_per_packet; char *fmtp_extra;
+ /* RTP patching */ + int force_constant_ssrc; + int force_constant_timing; + /* * Each end has a socket... */ @@ -142,9 +146,6 @@ struct mgcp_endpoint { struct mgcp_rtp_state net_state; struct mgcp_rtp_state bts_state;
- /* SSRC/seq/ts patching for loop */ - int allow_patch; - /* fields for re-transmission */ char *last_trans; char *last_response; @@ -176,6 +177,9 @@ static inline int endp_back_channel(int endpoint) struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index); struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
+void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change, + struct mgcp_rtp_end *rtp); + void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *, uint32_t *expected, int *loss); uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *); diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index 06452a6..ce4e1d3 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -263,7 +263,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta state->seq_offset = (state->out_stream.last_seq + 1) - seq; state->timestamp_offset = (state->out_stream.last_timestamp + tsdelta) - timestamp; - state->patch = endp->allow_patch; + state->patch = rtp_end->force_constant_ssrc; LOGP(DMGCP, LOGL_NOTICE, "The SSRC changed on 0x%x SSRC: %u offset: %d tsdelta: %d " "from %s:%d in %d\n", diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c index f09058d..6d31ace 100644 --- a/openbsc/src/libmgcp/mgcp_protocol.c +++ b/openbsc/src/libmgcp/mgcp_protocol.c @@ -612,6 +612,15 @@ static int parse_sdp_data(struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p) return found_media; }
+void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change, + struct mgcp_rtp_end *rtp) +{ + struct mgcp_trunk_config *tcfg = endp->tcfg; + + rtp->force_constant_timing = tcfg->force_constant_timing; + rtp->force_constant_ssrc = tcfg->force_constant_ssrc; +} + static struct msgb *handle_create_con(struct mgcp_parse_data *p) { struct mgcp_trunk_config *tcfg; @@ -686,6 +695,8 @@ mgcp_header_done:
/* initialize */ endp->net_end.rtp_port = endp->net_end.rtcp_port = endp->bts_end.rtp_port = endp->bts_end.rtcp_port = 0; + mgcp_rtp_end_config(endp, 0, &endp->net_end); + mgcp_rtp_end_config(endp, 0, &endp->bts_end);
/* set to zero until we get the info */ memset(&endp->net_end.addr, 0, sizeof(endp->net_end.addr)); @@ -1119,7 +1130,6 @@ void mgcp_free_endp(struct mgcp_endpoint *endp) memset(&endp->bts_state, 0, sizeof(endp->bts_state));
endp->conn_mode = endp->orig_mode = MGCP_CONN_NONE; - endp->allow_patch = 0;
memset(&endp->taps, 0, sizeof(endp->taps)); } diff --git a/openbsc/src/libmgcp/mgcp_vty.c b/openbsc/src/libmgcp/mgcp_vty.c index 5aeb393..16b973f 100644 --- a/openbsc/src/libmgcp/mgcp_vty.c +++ b/openbsc/src/libmgcp/mgcp_vty.c @@ -31,6 +31,7 @@ #include <string.h>
#define RTCP_OMIT_STR "Drop RTCP packets in both directions\n" +#define RTP_PATCH_STR "Modify RTP packet header in both directions\n"
static struct mgcp_config *g_cfg = NULL;
@@ -511,6 +512,13 @@ static int config_write_trunk(struct vty *vty) vty_out(vty, " rtcp-omit%s", VTY_NEWLINE); else vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE); + if (trunk->force_constant_ssrc || trunk->force_constant_timing) { + vty_out(vty, " rtp-patch ssrc %d%s", + trunk->force_constant_ssrc, VTY_NEWLINE); + vty_out(vty, " rtp-patch timestamp %d%s", + trunk->force_constant_timing, VTY_NEWLINE); + } else + vty_out(vty, " no rtp-patch%s", VTY_NEWLINE); if (trunk->audio_fmtp_extra) vty_out(vty, " sdp audio fmtp-extra %s%s", trunk->audio_fmtp_extra, VTY_NEWLINE); @@ -599,6 +607,46 @@ DEFUN(cfg_trunk_no_omit_rtcp, return CMD_SUCCESS; }
+DEFUN(cfg_trunk_patch_rtp_ssrc, + cfg_trunk_patch_rtp_ssrc_cmd, + "rtp-patch ssrc (0|1)", + RTP_PATCH_STR + "Force a fixed SSRC\n" + "Disable\n" + "Enable\n" + ) +{ + struct mgcp_trunk_config *trunk = vty->index; + trunk->force_constant_ssrc = atoi(argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_trunk_patch_rtp_ts, + cfg_trunk_patch_rtp_ts_cmd, + "rtp-patch timestamp (0|1)", + RTP_PATCH_STR + "Adjust RTP timestamp\n" + "Disable\n" + "Enable\n" + ) +{ + struct mgcp_trunk_config *trunk = vty->index; + trunk->force_constant_timing = atoi(argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_trunk_no_patch_rtp, + cfg_trunk_no_patch_rtp_cmd, + "no rtp-patch", + NO_STR RTP_PATCH_STR) +{ + struct mgcp_trunk_config *trunk = vty->index; + trunk->force_constant_ssrc = 0; + trunk->force_constant_timing = 0; + return CMD_SUCCESS; +} + + DEFUN(loop_endp, loop_endp_cmd, "loop-endpoint <0-64> NAME (0|1)", @@ -636,7 +684,10 @@ DEFUN(loop_endp, endp->conn_mode = MGCP_CONN_LOOPBACK; else endp->conn_mode = endp->orig_mode; - endp->allow_patch = 1; + + /* Handle it like a MDCX, switch on SSRC patching if enabled */ + mgcp_rtp_end_config(endp, 1, &endp->bts_end); + mgcp_rtp_end_config(endp, 1, &endp->net_end);
return CMD_SUCCESS; } @@ -839,6 +890,9 @@ int mgcp_vty_init(void) install_element(TRUNK_NODE, &cfg_trunk_loop_cmd); install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd); install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd); + install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd); + install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd); + install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd); install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd);
return 0; diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c index 4326738..8c292f1 100644 --- a/openbsc/tests/mgcp/mgcp_test.c +++ b/openbsc/tests/mgcp/mgcp_test.c @@ -537,6 +537,9 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
trunk.number_endpoints = 1; trunk.endpoints = &endp; + trunk.force_constant_ssrc = patch_ssrc; + trunk.force_constant_timing = patch_ts; + endp.tcfg = &trunk;
/* This doesn't free endp but resets/frees all fields of the structure @@ -547,7 +550,6 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts) mgcp_free_endp(&endp);
rtp->payload_type = 98; - endp.allow_patch = patch_ssrc;
for (i = 0; i < ARRAY_SIZE(test_rtp_packets1); ++i) { struct rtp_packet_info *info = test_rtp_packets1 + i; @@ -556,6 +558,8 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts) OSMO_ASSERT(info->len >= 0); memmove(buffer, info->data, info->len);
+ mgcp_rtp_end_config(&endp, 1, rtp); + mgcp_patch_and_count(&endp, &state, rtp, &addr, buffer, info->len);
The ssrc has been used without respect to proper byte ordering. The timestap_offset and seq_offset variables has been set even when patching was not allowed.
This patch introduces a new variable 'ssrc' that takes the value of the SSRC in proper byte order. The offsets in the state are only updated if SSRC patching is allowed.
Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/mgcp_internal.h | 1 + openbsc/src/libmgcp/mgcp_network.c | 73 ++++++++++++++++++++----------- openbsc/src/libmgcp/mgcp_protocol.c | 3 ++ 3 files changed, 52 insertions(+), 25 deletions(-)
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h index 02e193d..b16bd49 100644 --- a/openbsc/include/openbsc/mgcp_internal.h +++ b/openbsc/include/openbsc/mgcp_internal.h @@ -59,6 +59,7 @@ struct mgcp_rtp_state { int cycles;
int32_t timestamp_offset; + uint32_t packet_duration; uint32_t jitter; int32_t transit;
diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index ce4e1d3..137ddba 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -216,7 +216,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta uint32_t arrival_time; int32_t transit, d; uint16_t seq, udelta; - uint32_t timestamp; + uint32_t timestamp, ssrc; struct rtp_hdr *rtp_hdr; int payload = rtp_end->payload_type;
@@ -227,31 +227,43 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta seq = ntohs(rtp_hdr->sequence); timestamp = ntohl(rtp_hdr->timestamp); arrival_time = get_current_ts(); + ssrc = ntohl(rtp_hdr->ssrc);
if (!state->initialized) { state->in_stream.last_seq = seq - 1; - state->in_stream.ssrc = state->orig_ssrc = rtp_hdr->ssrc; + 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 = arrival_time - timestamp; + state->packet_duration = + rtp_end->rate * rtp_end->frames_per_packet * + rtp_end->frame_duration_num / + rtp_end->frame_duration_den; state->out_stream = state->in_stream; state->out_stream.last_timestamp = timestamp; - state->out_stream.ssrc = rtp_hdr->ssrc - 1; /* SSRC change <=> initialisation */ + state->out_stream.ssrc = ssrc - 1; /* SSRC change <=> initialisation */ LOGP(DMGCP, LOGL_INFO, "Initializing stream on 0x%x SSRC: %u timestamp: %u " + "pkt-duration: %d, from %s:%d in %d\n", + ENDPOINT_NUMBER(endp), state->in_stream.ssrc, + state->seq_offset, state->packet_duration, + inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), + endp->conn_mode); + } else if (state->in_stream.ssrc != ssrc) { + int32_t tsdelta; + + LOGP(DMGCP, LOGL_NOTICE, + "The SSRC changed on 0x%x SSRC: %u " "from %s:%d in %d\n", ENDPOINT_NUMBER(endp), state->in_stream.ssrc, - state->seq_offset, inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), endp->conn_mode); - } else if (state->in_stream.ssrc != rtp_hdr->ssrc) { - int32_t tsdelta = state->out_stream.last_tsdelta; + + tsdelta = state->out_stream.last_tsdelta; if (tsdelta == 0) { - tsdelta = rtp_end->rate * rtp_end->frames_per_packet * - rtp_end->frame_duration_num / - rtp_end->frame_duration_den; + tsdelta = state->packet_duration; LOGP(DMGCP, LOGL_NOTICE, "Computed timestamp delta %d based on " "rate %d, num frames %d, frame duration %d/%d\n", @@ -259,18 +271,25 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta rtp_end->frame_duration_num, rtp_end->frame_duration_den); } - state->in_stream.ssrc = rtp_hdr->ssrc; - state->seq_offset = (state->out_stream.last_seq + 1) - seq; - state->timestamp_offset = - (state->out_stream.last_timestamp + tsdelta) - timestamp; - state->patch = rtp_end->force_constant_ssrc; - LOGP(DMGCP, LOGL_NOTICE, - "The SSRC changed on 0x%x SSRC: %u offset: %d tsdelta: %d " - "from %s:%d in %d\n", - ENDPOINT_NUMBER(endp), state->in_stream.ssrc, - state->seq_offset, tsdelta, - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), - endp->conn_mode); + state->in_stream.ssrc = ssrc; + if (rtp_end->force_constant_ssrc) { + state->seq_offset = + (state->out_stream.last_seq + 1) - seq; + state->timestamp_offset = + (state->out_stream.last_timestamp + tsdelta) - + timestamp; + state->patch = 1; + ssrc = state->orig_ssrc; + + LOGP(DMGCP, LOGL_NOTICE, + "SSRC patching enabled on 0x%x SSRC: %u " + "offset: %d tsdelta: %d " + "from %s:%d in %d\n", + ENDPOINT_NUMBER(endp), state->in_stream.ssrc, + state->seq_offset, tsdelta, + inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), + endp->conn_mode); + }
state->in_stream.last_tsdelta = 0; } else { @@ -278,6 +297,9 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta check_rtp_timestamp(endp, &state->in_stream, rtp_end, addr, seq, timestamp, "input", &state->in_stream.last_tsdelta); + + if (state->patch) + ssrc = state->orig_ssrc; }
/* Save before patching */ @@ -288,14 +310,15 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta if (state->patch) { seq += state->seq_offset; rtp_hdr->sequence = htons(seq); - rtp_hdr->ssrc = state->orig_ssrc; + rtp_hdr->ssrc = htonl(ssrc);
timestamp += state->timestamp_offset; rtp_hdr->timestamp = htonl(timestamp); - } + } else + ssrc = ntohl(rtp_hdr->ssrc);
/* Check again, whether the timestamps are still valid */ - if (state->out_stream.ssrc == rtp_hdr->ssrc) + if (state->out_stream.ssrc == ssrc) check_rtp_timestamp(endp, &state->out_stream, rtp_end, addr, seq, timestamp, "output", &state->out_stream.last_tsdelta); @@ -332,7 +355,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta /* Save output values */ state->out_stream.last_seq = seq; state->out_stream.last_timestamp = timestamp; - state->out_stream.ssrc = rtp_hdr->ssrc; + state->out_stream.ssrc = ssrc;
if (payload < 0) return; diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c index 6d31ace..8693396 100644 --- a/openbsc/src/libmgcp/mgcp_protocol.c +++ b/openbsc/src/libmgcp/mgcp_protocol.c @@ -834,6 +834,9 @@ static struct msgb *handle_modify_con(struct mgcp_parse_data *p) } }
+ mgcp_rtp_end_config(endp, 1, &endp->net_end); + mgcp_rtp_end_config(endp, 1, &endp->bts_end); + /* modify */ LOGP(DMGCP, LOGL_DEBUG, "Modified endpoint on: 0x%x Server: %s:%u\n", ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr), ntohs(endp->net_end.rtp_port));
Currently the output SSRC is always forced to be the same if SSRC patching is enabled.
This patch modifies this to optionally restrict the number of SSRC changes that will be corrected.
Note that the configuration only allows for the 'once' mode and 'off'.
Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/mgcp_internal.h | 2 +- openbsc/src/libmgcp/mgcp_network.c | 2 ++ openbsc/src/libmgcp/mgcp_protocol.c | 4 +++- openbsc/src/libmgcp/mgcp_vty.c | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h index b16bd49..255161f 100644 --- a/openbsc/include/openbsc/mgcp_internal.h +++ b/openbsc/include/openbsc/mgcp_internal.h @@ -85,7 +85,7 @@ struct mgcp_rtp_end { char *fmtp_extra;
/* RTP patching */ - int force_constant_ssrc; + int force_constant_ssrc; /* -1: always, 0: don't, 1: once */ int force_constant_timing;
/* diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index 137ddba..b9bfc5e 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -280,6 +280,8 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta timestamp; state->patch = 1; ssrc = state->orig_ssrc; + if (rtp_end->force_constant_ssrc != -1) + rtp_end->force_constant_ssrc -= 1;
LOGP(DMGCP, LOGL_NOTICE, "SSRC patching enabled on 0x%x SSRC: %u " diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c index 8693396..f29e927 100644 --- a/openbsc/src/libmgcp/mgcp_protocol.c +++ b/openbsc/src/libmgcp/mgcp_protocol.c @@ -617,8 +617,10 @@ void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change, { struct mgcp_trunk_config *tcfg = endp->tcfg;
+ int patch_ssrc = expect_ssrc_change && tcfg->force_constant_ssrc; + rtp->force_constant_timing = tcfg->force_constant_timing; - rtp->force_constant_ssrc = tcfg->force_constant_ssrc; + rtp->force_constant_ssrc = patch_ssrc ? 1 : 0; }
static struct msgb *handle_create_con(struct mgcp_parse_data *p) diff --git a/openbsc/src/libmgcp/mgcp_vty.c b/openbsc/src/libmgcp/mgcp_vty.c index 16b973f..38570cb 100644 --- a/openbsc/src/libmgcp/mgcp_vty.c +++ b/openbsc/src/libmgcp/mgcp_vty.c @@ -613,7 +613,7 @@ DEFUN(cfg_trunk_patch_rtp_ssrc, RTP_PATCH_STR "Force a fixed SSRC\n" "Disable\n" - "Enable\n" + "Enable (once per MDCX)\n" ) { struct mgcp_trunk_config *trunk = vty->index;
This forces the output timing to fulfill dTS = dSegNo * fixedPacketDuration where dSegNo = seqNo - lastSeqNo.
If timestamp patching is enabled, the output timestamp will be set to lastTimestamp + dTS. This kind of relative updating is used to handle seqNo- and timestamp-wraparounds properly.
Ticket: OW#1065 Sponsored-by: On-Waves ehf --- openbsc/src/libmgcp/mgcp_network.c | 21 ++++++++++++++++ openbsc/tests/mgcp/mgcp_test.ok | 48 ++++++++++++++++++------------------ 2 files changed, 45 insertions(+), 24 deletions(-)
diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index b9bfc5e..a68c43c 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -308,6 +308,27 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta state->in_stream.last_timestamp = timestamp; state->in_stream.last_seq = seq;
+ if (rtp_end->force_constant_timing && + state->out_stream.ssrc == ssrc && state->packet_duration) { + int delta_seq = seq + state->seq_offset - state->out_stream.last_seq; + int timestamp_offset = + state->out_stream.last_timestamp - timestamp + + delta_seq * state->packet_duration; + if (state->timestamp_offset != timestamp_offset) { + state->timestamp_offset = timestamp_offset; + state->patch = 1; + + LOGP(DMGCP, LOGL_NOTICE, + "Timestamp patching enabled on 0x%x SSRC: %u " + "SeqNo delta: %d, TS offset: %d, " + "from %s:%d in %d\n", + ENDPOINT_NUMBER(endp), state->in_stream.ssrc, + delta_seq, state->timestamp_offset, + inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), + endp->conn_mode); + } + } + /* apply the offset and store it back to the packet */ if (state->patch) { seq += state->seq_offset; diff --git a/openbsc/tests/mgcp/mgcp_test.ok b/openbsc/tests/mgcp/mgcp_test.ok index 71293ad..c018fb2 100644 --- a/openbsc/tests/mgcp/mgcp_test.ok +++ b/openbsc/tests/mgcp/mgcp_test.ok @@ -78,32 +78,32 @@ Testing packet error detection, patch timestamps. TS: 0, dTS: 0, TS Errs: in 0, out 0 TS: 160, dTS: 160, TS Errs: in 0, out 0 TS: 320, dTS: 160, TS Errs: in 0, out 0 -TS: 320, dTS: 160, TS Errs: in 1, out 1 -TS: 480, dTS: 160, TS Errs: in 1, out 1 -TS: 640, dTS: 160, TS Errs: in 1, out 1 -TS: 960, dTS: 320, TS Errs: in 2, out 2 -TS: 1120, dTS: 160, TS Errs: in 3, out 3 -TS: 1280, dTS: 160, TS Errs: in 3, out 3 -TS: 1400, dTS: 120, TS Errs: in 4, out 4 -TS: 1560, dTS: 160, TS Errs: in 5, out 5 -TS: 1720, dTS: 160, TS Errs: in 5, out 5 -TS: 34688, dTS: 160, TS Errs: in 5, out 5 -TS: 34848, dTS: 160, TS Errs: in 5, out 5 -TS: 35008, dTS: 160, TS Errs: in 5, out 5 +TS: 480, dTS: 160, TS Errs: in 1, out 0 +TS: 640, dTS: 160, TS Errs: in 1, out 0 +TS: 800, dTS: 160, TS Errs: in 1, out 0 +TS: 960, dTS: 160, TS Errs: in 2, out 0 +TS: 1120, dTS: 160, TS Errs: in 3, out 0 +TS: 1280, dTS: 160, TS Errs: in 3, out 0 +TS: 1440, dTS: 160, TS Errs: in 4, out 0 +TS: 1600, dTS: 160, TS Errs: in 5, out 0 +TS: 1760, dTS: 160, TS Errs: in 5, out 0 +TS: 34728, dTS: 160, TS Errs: in 5, out 0 +TS: 34888, dTS: 160, TS Errs: in 5, out 0 +TS: 35048, dTS: 160, TS Errs: in 5, out 0 Testing packet error detection, patch SSRC, patch timestamps. TS: 0, dTS: 0, TS Errs: in 0, out 0 TS: 160, dTS: 160, TS Errs: in 0, out 0 TS: 320, dTS: 160, TS Errs: in 0, out 0 -TS: 320, dTS: 160, TS Errs: in 1, out 1 -TS: 480, dTS: 160, TS Errs: in 1, out 1 -TS: 640, dTS: 160, TS Errs: in 1, out 1 -TS: 960, dTS: 320, TS Errs: in 2, out 2 -TS: 1120, dTS: 160, TS Errs: in 3, out 3 -TS: 1280, dTS: 160, TS Errs: in 3, out 3 -TS: 1400, dTS: 120, TS Errs: in 4, out 4 -TS: 1560, dTS: 160, TS Errs: in 5, out 5 -TS: 1720, dTS: 160, TS Errs: in 5, out 5 -TS: 1880, dTS: 160, TS Errs: in 5, out 5 -TS: 2040, dTS: 160, TS Errs: in 5, out 5 -TS: 2200, dTS: 160, TS Errs: in 5, out 5 +TS: 480, dTS: 160, TS Errs: in 1, out 0 +TS: 640, dTS: 160, TS Errs: in 1, out 0 +TS: 800, dTS: 160, TS Errs: in 1, out 0 +TS: 960, dTS: 160, TS Errs: in 2, out 0 +TS: 1120, dTS: 160, TS Errs: in 3, out 0 +TS: 1280, dTS: 160, TS Errs: in 3, out 0 +TS: 1440, dTS: 160, TS Errs: in 4, out 0 +TS: 1600, dTS: 160, TS Errs: in 5, out 0 +TS: 1760, dTS: 160, TS Errs: in 5, out 0 +TS: 1920, dTS: 160, TS Errs: in 5, out 0 +TS: 2080, dTS: 160, TS Errs: in 5, out 0 +TS: 2240, dTS: 160, TS Errs: in 5, out 0 Done
This patch extends the existing RTP error check test by adding a check for timestamp errors after SSRC changes and a check for a segno delta of 2 (with a timestamp delta of 320).
To test SSRC patching too, a corresponding line will be written on each SSRC change that has been detected in the output stream.
In addition there is now support for selectively enabling/disabling SSRC and timestamp patching. The RTP test sequence is repeated for all combinations thereof.
Sponsored-by: On-Waves ehf --- openbsc/tests/mgcp/mgcp_test.c | 40 ++++++++++++++++++-- openbsc/tests/mgcp/mgcp_test.ok | 78 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 4 deletions(-)
diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c index c58f52d..8e130bb 100644 --- a/openbsc/tests/mgcp/mgcp_test.c +++ b/openbsc/tests/mgcp/mgcp_test.c @@ -510,13 +510,33 @@ struct rtp_packet_info test_rtp_packets1[] = { /* RTP: SeqNo=14, TS=35008 */ {0.280000, 20, "\x80\x62\x00\x0E\x00\x00\x88\xC0\x10\x20\x30\x40" "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* Non 20ms RTP timestamp (delta = 120): */ + /* RTP: SeqNo=15, TS=35128 */ + {0.300000, 20, "\x80\x62\x00\x0F\x00\x00\x89\x38\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=16, TS=35288 */ + {0.320000, 20, "\x80\x62\x00\x10\x00\x00\x89\xD8\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=17, TS=35448 */ + {0.340000, 20, "\x80\x62\x00\x11\x00\x00\x8A\x78\x10\x20\x30\x40" + "\x01\x23\x45\x67\x8A\xAB\xCD\xEF"}, + /* SeqNo increment by 2, RTP timestamp delta = 320: */ + /* RTP: SeqNo=19, TS=35768 */ + {0.360000, 20, "\x80\x62\x00\x13\x00\x00\x8B\xB8\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=20, TS=35928 */ + {0.380000, 20, "\x80\x62\x00\x14\x00\x00\x8C\x58\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=21, TS=36088 */ + {0.380000, 20, "\x80\x62\x00\x14\x00\x00\x8C\xF8\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, };
void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state, struct mgcp_rtp_end *rtp_end, struct sockaddr_in *addr, char *data, int len);
-static void test_packet_error_detection(void) +static void test_packet_error_detection(int patch_ssrc, int patch_ts) { int i;
@@ -526,8 +546,11 @@ static void test_packet_error_detection(void) struct mgcp_rtp_end *rtp = &endp.net_end; struct sockaddr_in addr = {0}; char buffer[4096]; + uint32_t last_ssrc = 0;
- printf("Testing packet error detection.\n"); + printf("Testing packet error detection%s%s.\n", + patch_ssrc ? ", patch SSRC" : "", + patch_ts ? ", patch timestamps" : "");
memset(&trunk, 0, sizeof(trunk)); memset(&endp, 0, sizeof(endp)); @@ -545,7 +568,7 @@ static void test_packet_error_detection(void) mgcp_free_endp(&endp);
rtp->payload_type = 98; - endp.allow_patch = 1; + endp.allow_patch = patch_ssrc;
for (i = 0; i < ARRAY_SIZE(test_rtp_packets1); ++i) { struct rtp_packet_info *info = test_rtp_packets1 + i; @@ -557,6 +580,12 @@ static void test_packet_error_detection(void) mgcp_patch_and_count(&endp, &state, rtp, &addr, buffer, info->len);
+ if (state.out_stream.ssrc != last_ssrc) { + printf("Output SSRC changed to %08x\n", + ntohl(state.out_stream.ssrc)); + last_ssrc = state.out_stream.ssrc; + } + printf("TS: %d, dTS: %d, TS Errs: in %d, out %d\n", state.out_stream.last_timestamp, state.out_stream.last_tsdelta, @@ -575,7 +604,10 @@ int main(int argc, char **argv) test_packet_loss_calc(); test_rqnt_cb(); test_mgcp_stats(); - test_packet_error_detection(); + test_packet_error_detection(1, 0); + test_packet_error_detection(0, 0); + test_packet_error_detection(0, 1); + test_packet_error_detection(1, 1);
printf("Done\n"); return EXIT_SUCCESS; diff --git a/openbsc/tests/mgcp/mgcp_test.ok b/openbsc/tests/mgcp/mgcp_test.ok index 3bfd78b..57d3bfb 100644 --- a/openbsc/tests/mgcp/mgcp_test.ok +++ b/openbsc/tests/mgcp/mgcp_test.ok @@ -42,7 +42,79 @@ Testing packet loss calculation. Testing stat parsing Parsing result: 0 Parsing result: 0 +Testing packet error detection, patch SSRC. +Output SSRC changed to 11223344 +TS: 0, dTS: 0, TS Errs: in 0, out 0 +TS: 160, dTS: 160, TS Errs: in 0, out 0 +TS: 320, dTS: 160, TS Errs: in 0, out 0 +TS: 320, dTS: 160, TS Errs: in 1, out 1 +TS: 480, dTS: 160, TS Errs: in 1, out 1 +TS: 640, dTS: 160, TS Errs: in 1, out 1 +TS: 960, dTS: 320, TS Errs: in 2, out 2 +TS: 1120, dTS: 160, TS Errs: in 3, out 3 +TS: 1280, dTS: 160, TS Errs: in 3, out 3 +TS: 1400, dTS: 120, TS Errs: in 4, out 4 +TS: 1560, dTS: 160, TS Errs: in 5, out 5 +TS: 1720, dTS: 160, TS Errs: in 5, out 5 +TS: 1880, dTS: 160, TS Errs: in 5, out 5 +TS: 2040, dTS: 160, TS Errs: in 5, out 5 +TS: 2200, dTS: 160, TS Errs: in 5, out 5 +TS: 2320, dTS: 120, TS Errs: in 6, out 6 +TS: 2480, dTS: 160, TS Errs: in 7, out 7 +TS: 2640, dTS: 160, TS Errs: in 7, out 7 +TS: 2960, dTS: 160, TS Errs: in 7, out 7 +TS: 3120, dTS: 160, TS Errs: in 7, out 7 +TS: 3280, dTS: 160, TS Errs: in 8, out 8 Testing packet error detection. +Output SSRC changed to 11223344 +TS: 0, dTS: 0, TS Errs: in 0, out 0 +TS: 160, dTS: 160, TS Errs: in 0, out 0 +TS: 320, dTS: 160, TS Errs: in 0, out 0 +TS: 320, dTS: 160, TS Errs: in 1, out 1 +TS: 480, dTS: 160, TS Errs: in 1, out 1 +TS: 640, dTS: 160, TS Errs: in 1, out 1 +TS: 960, dTS: 320, TS Errs: in 2, out 2 +TS: 1120, dTS: 160, TS Errs: in 3, out 3 +TS: 1280, dTS: 160, TS Errs: in 3, out 3 +TS: 1400, dTS: 120, TS Errs: in 4, out 4 +TS: 1560, dTS: 160, TS Errs: in 5, out 5 +TS: 1720, dTS: 160, TS Errs: in 5, out 5 +Output SSRC changed to 10203040 +TS: 34688, dTS: 32968, TS Errs: in 5, out 6 +TS: 34848, dTS: 160, TS Errs: in 5, out 7 +TS: 35008, dTS: 160, TS Errs: in 5, out 7 +TS: 35128, dTS: 120, TS Errs: in 6, out 8 +TS: 35288, dTS: 160, TS Errs: in 7, out 9 +TS: 35448, dTS: 160, TS Errs: in 7, out 9 +TS: 35768, dTS: 160, TS Errs: in 7, out 9 +TS: 35928, dTS: 160, TS Errs: in 7, out 9 +TS: 36088, dTS: 160, TS Errs: in 8, out 10 +Testing packet error detection, patch timestamps. +Output SSRC changed to 11223344 +TS: 0, dTS: 0, TS Errs: in 0, out 0 +TS: 160, dTS: 160, TS Errs: in 0, out 0 +TS: 320, dTS: 160, TS Errs: in 0, out 0 +TS: 320, dTS: 160, TS Errs: in 1, out 1 +TS: 480, dTS: 160, TS Errs: in 1, out 1 +TS: 640, dTS: 160, TS Errs: in 1, out 1 +TS: 960, dTS: 320, TS Errs: in 2, out 2 +TS: 1120, dTS: 160, TS Errs: in 3, out 3 +TS: 1280, dTS: 160, TS Errs: in 3, out 3 +TS: 1400, dTS: 120, TS Errs: in 4, out 4 +TS: 1560, dTS: 160, TS Errs: in 5, out 5 +TS: 1720, dTS: 160, TS Errs: in 5, out 5 +Output SSRC changed to 10203040 +TS: 34688, dTS: 32968, TS Errs: in 5, out 6 +TS: 34848, dTS: 160, TS Errs: in 5, out 7 +TS: 35008, dTS: 160, TS Errs: in 5, out 7 +TS: 35128, dTS: 120, TS Errs: in 6, out 8 +TS: 35288, dTS: 160, TS Errs: in 7, out 9 +TS: 35448, dTS: 160, TS Errs: in 7, out 9 +TS: 35768, dTS: 160, TS Errs: in 7, out 9 +TS: 35928, dTS: 160, TS Errs: in 7, out 9 +TS: 36088, dTS: 160, TS Errs: in 8, out 10 +Testing packet error detection, patch SSRC, patch timestamps. +Output SSRC changed to 11223344 TS: 0, dTS: 0, TS Errs: in 0, out 0 TS: 160, dTS: 160, TS Errs: in 0, out 0 TS: 320, dTS: 160, TS Errs: in 0, out 0 @@ -58,4 +130,10 @@ TS: 1720, dTS: 160, TS Errs: in 5, out 5 TS: 1880, dTS: 160, TS Errs: in 5, out 5 TS: 2040, dTS: 160, TS Errs: in 5, out 5 TS: 2200, dTS: 160, TS Errs: in 5, out 5 +TS: 2320, dTS: 120, TS Errs: in 6, out 6 +TS: 2480, dTS: 160, TS Errs: in 7, out 7 +TS: 2640, dTS: 160, TS Errs: in 7, out 7 +TS: 2960, dTS: 160, TS Errs: in 7, out 7 +TS: 3120, dTS: 160, TS Errs: in 7, out 7 +TS: 3280, dTS: 160, TS Errs: in 8, out 8 Done
The tsdelta computation and error detection didn't handle the intialisation phase properly.
This patches fixes this by skipping the output timing validation when the SSRCs don't match.
Sponsored-by: On-Waves ehf --- openbsc/src/libmgcp/mgcp_network.c | 17 ++++++++++++++--- openbsc/tests/mgcp/mgcp_test.ok | 36 ++++++++++++++++++------------------ 2 files changed, 32 insertions(+), 21 deletions(-)
diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index 75d39c1..53f1a20 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -237,6 +237,16 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta state->jitter = 0; state->transit = arrival_time - timestamp; state->out_stream = state->in_stream; + state->out_stream.last_timestamp = timestamp; + /* force output SSRC change */ + state->out_stream.ssrc = rtp_hdr->ssrc - 1; + LOGP(DMGCP, LOGL_INFO, + "Initializing stream on 0x%x SSRC: %u timestamp: %u " + "from %s:%d in %d\n", + ENDPOINT_NUMBER(endp), state->in_stream.ssrc, + state->seq_offset, + inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), + endp->conn_mode); } else if (state->in_stream.ssrc != rtp_hdr->ssrc) { int32_t tsdelta = state->out_stream.last_tsdelta; if (tsdelta == 0) { @@ -286,9 +296,10 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta }
/* Check again, whether the timestamps are still valid */ - check_rtp_timestamp(endp, &state->out_stream, rtp_end, addr, - seq, timestamp, "output", - &state->out_stream.last_tsdelta); + if (state->out_stream.ssrc == rtp_hdr->ssrc) + check_rtp_timestamp(endp, &state->out_stream, rtp_end, addr, + seq, timestamp, "output", + &state->out_stream.last_tsdelta);
/* * The below takes the shape of the validation from Appendix A. Check diff --git a/openbsc/tests/mgcp/mgcp_test.ok b/openbsc/tests/mgcp/mgcp_test.ok index 57d3bfb..4d3caac 100644 --- a/openbsc/tests/mgcp/mgcp_test.ok +++ b/openbsc/tests/mgcp/mgcp_test.ok @@ -80,15 +80,15 @@ TS: 1400, dTS: 120, TS Errs: in 4, out 4 TS: 1560, dTS: 160, TS Errs: in 5, out 5 TS: 1720, dTS: 160, TS Errs: in 5, out 5 Output SSRC changed to 10203040 -TS: 34688, dTS: 32968, TS Errs: in 5, out 6 -TS: 34848, dTS: 160, TS Errs: in 5, out 7 -TS: 35008, dTS: 160, TS Errs: in 5, out 7 -TS: 35128, dTS: 120, TS Errs: in 6, out 8 -TS: 35288, dTS: 160, TS Errs: in 7, out 9 -TS: 35448, dTS: 160, TS Errs: in 7, out 9 -TS: 35768, dTS: 160, TS Errs: in 7, out 9 -TS: 35928, dTS: 160, TS Errs: in 7, out 9 -TS: 36088, dTS: 160, TS Errs: in 8, out 10 +TS: 34688, dTS: 160, TS Errs: in 5, out 5 +TS: 34848, dTS: 160, TS Errs: in 5, out 5 +TS: 35008, dTS: 160, TS Errs: in 5, out 5 +TS: 35128, dTS: 120, TS Errs: in 6, out 6 +TS: 35288, dTS: 160, TS Errs: in 7, out 7 +TS: 35448, dTS: 160, TS Errs: in 7, out 7 +TS: 35768, dTS: 160, TS Errs: in 7, out 7 +TS: 35928, dTS: 160, TS Errs: in 7, out 7 +TS: 36088, dTS: 160, TS Errs: in 8, out 8 Testing packet error detection, patch timestamps. Output SSRC changed to 11223344 TS: 0, dTS: 0, TS Errs: in 0, out 0 @@ -104,15 +104,15 @@ TS: 1400, dTS: 120, TS Errs: in 4, out 4 TS: 1560, dTS: 160, TS Errs: in 5, out 5 TS: 1720, dTS: 160, TS Errs: in 5, out 5 Output SSRC changed to 10203040 -TS: 34688, dTS: 32968, TS Errs: in 5, out 6 -TS: 34848, dTS: 160, TS Errs: in 5, out 7 -TS: 35008, dTS: 160, TS Errs: in 5, out 7 -TS: 35128, dTS: 120, TS Errs: in 6, out 8 -TS: 35288, dTS: 160, TS Errs: in 7, out 9 -TS: 35448, dTS: 160, TS Errs: in 7, out 9 -TS: 35768, dTS: 160, TS Errs: in 7, out 9 -TS: 35928, dTS: 160, TS Errs: in 7, out 9 -TS: 36088, dTS: 160, TS Errs: in 8, out 10 +TS: 34688, dTS: 160, TS Errs: in 5, out 5 +TS: 34848, dTS: 160, TS Errs: in 5, out 5 +TS: 35008, dTS: 160, TS Errs: in 5, out 5 +TS: 35128, dTS: 120, TS Errs: in 6, out 6 +TS: 35288, dTS: 160, TS Errs: in 7, out 7 +TS: 35448, dTS: 160, TS Errs: in 7, out 7 +TS: 35768, dTS: 160, TS Errs: in 7, out 7 +TS: 35928, dTS: 160, TS Errs: in 7, out 7 +TS: 36088, dTS: 160, TS Errs: in 8, out 8 Testing packet error detection, patch SSRC, patch timestamps. Output SSRC changed to 11223344 TS: 0, dTS: 0, TS Errs: in 0, out 0
This adds datastructures and a VTY frontend to configure the different type of RTP header patching: SSRC and timestamp.
Note that timestamp patching is not yet implemented.
Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/mgcp.h | 4 +++ openbsc/include/openbsc/mgcp_internal.h | 10 ++++-- openbsc/src/libmgcp/mgcp_network.c | 2 +- openbsc/src/libmgcp/mgcp_protocol.c | 15 ++++++++- openbsc/src/libmgcp/mgcp_vty.c | 56 ++++++++++++++++++++++++++++++- openbsc/tests/mgcp/mgcp_test.c | 6 +++- 6 files changed, 86 insertions(+), 7 deletions(-)
diff --git a/openbsc/include/openbsc/mgcp.h b/openbsc/include/openbsc/mgcp.h index 4e22e0f..8ab52ce 100644 --- a/openbsc/include/openbsc/mgcp.h +++ b/openbsc/include/openbsc/mgcp.h @@ -118,6 +118,10 @@ struct mgcp_trunk_config {
int omit_rtcp;
+ /* RTP patching */ + int force_constant_ssrc; /* 0: don't, 1: once */ + int force_constant_timing; + /* spec handling */ int force_realloc;
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h index 0b52c1c..02e193d 100644 --- a/openbsc/include/openbsc/mgcp_internal.h +++ b/openbsc/include/openbsc/mgcp_internal.h @@ -83,6 +83,10 @@ struct mgcp_rtp_end { int frames_per_packet; char *fmtp_extra;
+ /* RTP patching */ + int force_constant_ssrc; + int force_constant_timing; + /* * Each end has a socket... */ @@ -142,9 +146,6 @@ struct mgcp_endpoint { struct mgcp_rtp_state net_state; struct mgcp_rtp_state bts_state;
- /* SSRC/seq/ts patching for loop */ - int allow_patch; - /* fields for re-transmission */ char *last_trans; char *last_response; @@ -176,6 +177,9 @@ static inline int endp_back_channel(int endpoint) struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index); struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
+void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change, + struct mgcp_rtp_end *rtp); + void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *, uint32_t *expected, int *loss); uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *); diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index 53f1a20..367cebd 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -264,7 +264,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta state->seq_offset = (state->out_stream.last_seq + 1) - seq; state->timestamp_offset = (state->out_stream.last_timestamp + tsdelta) - timestamp; - state->patch = endp->allow_patch; + state->patch = rtp_end->force_constant_ssrc; LOGP(DMGCP, LOGL_NOTICE, "The SSRC changed on 0x%x SSRC: %u offset: %d tsdelta: %d " "from %s:%d in %d\n", diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c index a0b905d..d7e4745 100644 --- a/openbsc/src/libmgcp/mgcp_protocol.c +++ b/openbsc/src/libmgcp/mgcp_protocol.c @@ -614,6 +614,15 @@ static int parse_sdp_data(struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p) return found_media; }
+void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change, + struct mgcp_rtp_end *rtp) +{ + struct mgcp_trunk_config *tcfg = endp->tcfg; + + rtp->force_constant_timing = tcfg->force_constant_timing; + rtp->force_constant_ssrc = tcfg->force_constant_ssrc; +} + static struct msgb *handle_create_con(struct mgcp_parse_data *p) { struct mgcp_trunk_config *tcfg; @@ -688,6 +697,8 @@ mgcp_header_done:
/* initialize */ endp->net_end.rtp_port = endp->net_end.rtcp_port = endp->bts_end.rtp_port = endp->bts_end.rtcp_port = 0; + mgcp_rtp_end_config(endp, 0, &endp->net_end); + mgcp_rtp_end_config(endp, 0, &endp->bts_end);
/* set to zero until we get the info */ memset(&endp->net_end.addr, 0, sizeof(endp->net_end.addr)); @@ -825,6 +836,9 @@ static struct msgb *handle_modify_con(struct mgcp_parse_data *p) } }
+ mgcp_rtp_end_config(endp, 1, &endp->net_end); + mgcp_rtp_end_config(endp, 1, &endp->bts_end); + /* modify */ LOGP(DMGCP, LOGL_DEBUG, "Modified endpoint on: 0x%x Server: %s:%u\n", ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr), ntohs(endp->net_end.rtp_port)); @@ -1121,7 +1135,6 @@ void mgcp_free_endp(struct mgcp_endpoint *endp) memset(&endp->bts_state, 0, sizeof(endp->bts_state));
endp->conn_mode = endp->orig_mode = MGCP_CONN_NONE; - endp->allow_patch = 0;
memset(&endp->taps, 0, sizeof(endp->taps)); } diff --git a/openbsc/src/libmgcp/mgcp_vty.c b/openbsc/src/libmgcp/mgcp_vty.c index 5aeb393..16b973f 100644 --- a/openbsc/src/libmgcp/mgcp_vty.c +++ b/openbsc/src/libmgcp/mgcp_vty.c @@ -31,6 +31,7 @@ #include <string.h>
#define RTCP_OMIT_STR "Drop RTCP packets in both directions\n" +#define RTP_PATCH_STR "Modify RTP packet header in both directions\n"
static struct mgcp_config *g_cfg = NULL;
@@ -511,6 +512,13 @@ static int config_write_trunk(struct vty *vty) vty_out(vty, " rtcp-omit%s", VTY_NEWLINE); else vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE); + if (trunk->force_constant_ssrc || trunk->force_constant_timing) { + vty_out(vty, " rtp-patch ssrc %d%s", + trunk->force_constant_ssrc, VTY_NEWLINE); + vty_out(vty, " rtp-patch timestamp %d%s", + trunk->force_constant_timing, VTY_NEWLINE); + } else + vty_out(vty, " no rtp-patch%s", VTY_NEWLINE); if (trunk->audio_fmtp_extra) vty_out(vty, " sdp audio fmtp-extra %s%s", trunk->audio_fmtp_extra, VTY_NEWLINE); @@ -599,6 +607,46 @@ DEFUN(cfg_trunk_no_omit_rtcp, return CMD_SUCCESS; }
+DEFUN(cfg_trunk_patch_rtp_ssrc, + cfg_trunk_patch_rtp_ssrc_cmd, + "rtp-patch ssrc (0|1)", + RTP_PATCH_STR + "Force a fixed SSRC\n" + "Disable\n" + "Enable\n" + ) +{ + struct mgcp_trunk_config *trunk = vty->index; + trunk->force_constant_ssrc = atoi(argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_trunk_patch_rtp_ts, + cfg_trunk_patch_rtp_ts_cmd, + "rtp-patch timestamp (0|1)", + RTP_PATCH_STR + "Adjust RTP timestamp\n" + "Disable\n" + "Enable\n" + ) +{ + struct mgcp_trunk_config *trunk = vty->index; + trunk->force_constant_timing = atoi(argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_trunk_no_patch_rtp, + cfg_trunk_no_patch_rtp_cmd, + "no rtp-patch", + NO_STR RTP_PATCH_STR) +{ + struct mgcp_trunk_config *trunk = vty->index; + trunk->force_constant_ssrc = 0; + trunk->force_constant_timing = 0; + return CMD_SUCCESS; +} + + DEFUN(loop_endp, loop_endp_cmd, "loop-endpoint <0-64> NAME (0|1)", @@ -636,7 +684,10 @@ DEFUN(loop_endp, endp->conn_mode = MGCP_CONN_LOOPBACK; else endp->conn_mode = endp->orig_mode; - endp->allow_patch = 1; + + /* Handle it like a MDCX, switch on SSRC patching if enabled */ + mgcp_rtp_end_config(endp, 1, &endp->bts_end); + mgcp_rtp_end_config(endp, 1, &endp->net_end);
return CMD_SUCCESS; } @@ -839,6 +890,9 @@ int mgcp_vty_init(void) install_element(TRUNK_NODE, &cfg_trunk_loop_cmd); install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd); install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd); + install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd); + install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd); + install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd); install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd);
return 0; diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c index 8e130bb..908773a 100644 --- a/openbsc/tests/mgcp/mgcp_test.c +++ b/openbsc/tests/mgcp/mgcp_test.c @@ -558,6 +558,9 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
trunk.number_endpoints = 1; trunk.endpoints = &endp; + trunk.force_constant_ssrc = patch_ssrc; + trunk.force_constant_timing = patch_ts; + endp.tcfg = &trunk;
/* This doesn't free endp but resets/frees all fields of the structure @@ -568,7 +571,6 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts) mgcp_free_endp(&endp);
rtp->payload_type = 98; - endp.allow_patch = patch_ssrc;
for (i = 0; i < ARRAY_SIZE(test_rtp_packets1); ++i) { struct rtp_packet_info *info = test_rtp_packets1 + i; @@ -577,6 +579,8 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts) OSMO_ASSERT(info->len >= 0); memmove(buffer, info->data, info->len);
+ mgcp_rtp_end_config(&endp, 1, rtp); + mgcp_patch_and_count(&endp, &state, rtp, &addr, buffer, info->len);
On Thu, Dec 05, 2013 at 05:44:18PM +0100, Jacob Erlbeck wrote:
+void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
struct mgcp_rtp_end *rtp);
config sounds more like an object than an action? The patch looks fine and I intend to apply it today.
Show old and new SSRC. Move logging command upward to show the values immediately after the change has been detected and before any fixing attempt is made.
Sponsored-by: On-Waves ehf --- openbsc/src/libmgcp/mgcp_network.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index 367cebd..d19b56e 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -249,6 +249,15 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta endp->conn_mode); } else if (state->in_stream.ssrc != rtp_hdr->ssrc) { int32_t tsdelta = state->out_stream.last_tsdelta; + + LOGP(DMGCP, LOGL_NOTICE, + "The SSRC changed on 0x%x: %u -> %u " + "from %s:%d in %d\n", + ENDPOINT_NUMBER(endp), + state->in_stream.ssrc, rtp_hdr->ssrc, + inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), + endp->conn_mode); + if (tsdelta == 0) { tsdelta = rtp_end->rate * rtp_end->frames_per_packet * rtp_end->frame_duration_num / @@ -265,13 +274,6 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta state->timestamp_offset = (state->out_stream.last_timestamp + tsdelta) - timestamp; state->patch = rtp_end->force_constant_ssrc; - LOGP(DMGCP, LOGL_NOTICE, - "The SSRC changed on 0x%x SSRC: %u offset: %d tsdelta: %d " - "from %s:%d in %d\n", - ENDPOINT_NUMBER(endp), state->in_stream.ssrc, - state->seq_offset, tsdelta, - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), - endp->conn_mode);
state->in_stream.last_tsdelta = 0; } else {
Currently seq_offset and timestamp_offset are updated on each SSRC change even when SSRC patching is not allowed.
This patch fixes this by changing mgcp_patch_and_count() to only update these fields when SSRC patching is allowed.
Sponsored-by: On-Waves ehf --- openbsc/src/libmgcp/mgcp_network.c | 44 +++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 16 deletions(-)
diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index d19b56e..c14b913 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -248,8 +248,6 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), endp->conn_mode); } else if (state->in_stream.ssrc != rtp_hdr->ssrc) { - int32_t tsdelta = state->out_stream.last_tsdelta; - LOGP(DMGCP, LOGL_NOTICE, "The SSRC changed on 0x%x: %u -> %u " "from %s:%d in %d\n", @@ -258,22 +256,36 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), endp->conn_mode);
- if (tsdelta == 0) { - tsdelta = rtp_end->rate * rtp_end->frames_per_packet * - rtp_end->frame_duration_num / - rtp_end->frame_duration_den; + state->in_stream.ssrc = rtp_hdr->ssrc; + if (rtp_end->force_constant_ssrc) { + int32_t tsdelta = state->out_stream.last_tsdelta; + if (tsdelta == 0) { + tsdelta = rtp_end->rate * rtp_end->frames_per_packet * + rtp_end->frame_duration_num / + rtp_end->frame_duration_den; + LOGP(DMGCP, LOGL_NOTICE, + "Computed timestamp delta %d based on " + "rate %d, num frames %d, frame duration %d/%d\n", + tsdelta, rtp_end->rate, rtp_end->frames_per_packet, + rtp_end->frame_duration_num, + rtp_end->frame_duration_den); + } + state->seq_offset = + (state->out_stream.last_seq + 1) - seq; + state->timestamp_offset = + (state->out_stream.last_timestamp + tsdelta) - + timestamp; + state->patch = 1; + LOGP(DMGCP, LOGL_NOTICE, - "Computed timestamp delta %d based on " - "rate %d, num frames %d, frame duration %d/%d\n", - tsdelta, rtp_end->rate, rtp_end->frames_per_packet, - rtp_end->frame_duration_num, - rtp_end->frame_duration_den); + "SSRC patching enabled on 0x%x SSRC: %u " + "offset: %d tsdelta: %d " + "from %s:%d in %d\n", + ENDPOINT_NUMBER(endp), state->in_stream.ssrc, + state->seq_offset, tsdelta, + inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), + endp->conn_mode); } - state->in_stream.ssrc = rtp_hdr->ssrc; - state->seq_offset = (state->out_stream.last_seq + 1) - seq; - state->timestamp_offset = - (state->out_stream.last_timestamp + tsdelta) - timestamp; - state->patch = rtp_end->force_constant_ssrc;
state->in_stream.last_tsdelta = 0; } else {
This patch adds a packet_duration field to mgcp_rtp_state which contains the RTP packet's duration in RTP timestamp units or 0, when the duration is unknown or not fixed.
Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/mgcp_internal.h | 1 + openbsc/src/libmgcp/mgcp_network.c | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h index 02e193d..b16bd49 100644 --- a/openbsc/include/openbsc/mgcp_internal.h +++ b/openbsc/include/openbsc/mgcp_internal.h @@ -59,6 +59,7 @@ struct mgcp_rtp_state { int cycles;
int32_t timestamp_offset; + uint32_t packet_duration; uint32_t jitter; int32_t transit;
diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index c14b913..f177339 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -236,15 +236,19 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta state->initialized = 1; state->jitter = 0; state->transit = arrival_time - timestamp; + state->packet_duration = + rtp_end->rate * rtp_end->frames_per_packet * + rtp_end->frame_duration_num / + rtp_end->frame_duration_den; state->out_stream = state->in_stream; state->out_stream.last_timestamp = timestamp; /* force output SSRC change */ state->out_stream.ssrc = rtp_hdr->ssrc - 1; LOGP(DMGCP, LOGL_INFO, "Initializing stream on 0x%x SSRC: %u timestamp: %u " - "from %s:%d in %d\n", + "pkt-duration: %d, from %s:%d in %d\n", ENDPOINT_NUMBER(endp), state->in_stream.ssrc, - state->seq_offset, + state->seq_offset, state->packet_duration, inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), endp->conn_mode); } else if (state->in_stream.ssrc != rtp_hdr->ssrc) { @@ -260,15 +264,14 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta if (rtp_end->force_constant_ssrc) { int32_t tsdelta = state->out_stream.last_tsdelta; if (tsdelta == 0) { - tsdelta = rtp_end->rate * rtp_end->frames_per_packet * - rtp_end->frame_duration_num / - rtp_end->frame_duration_den; + tsdelta = state->packet_duration; LOGP(DMGCP, LOGL_NOTICE, - "Computed timestamp delta %d based on " - "rate %d, num frames %d, frame duration %d/%d\n", - tsdelta, rtp_end->rate, rtp_end->frames_per_packet, - rtp_end->frame_duration_num, - rtp_end->frame_duration_den); + "Timestamp delta is not available on 0x%x, " + "using packet duration instead: %d " + "from %s:%d in %d\n", + ENDPOINT_NUMBER(endp), tsdelta, + inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), + endp->conn_mode); } state->seq_offset = (state->out_stream.last_seq + 1) - seq;
The ssrc has been used without respect to proper byte ordering in mgcp_patch_and_count(). This only affected log messages.
This patch introduces a new variable 'ssrc' that takes the value of the SSRC in proper byte order.
Sponsored-by: On-Waves ehf --- openbsc/src/libmgcp/mgcp_network.c | 22 +++++++++++++--------- openbsc/tests/mgcp/mgcp_test.c | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index f177339..abb48f5 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -216,7 +216,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta uint32_t arrival_time; int32_t transit, d; uint16_t seq, udelta; - uint32_t timestamp; + uint32_t timestamp, ssrc; struct rtp_hdr *rtp_hdr; int payload = rtp_end->payload_type;
@@ -227,10 +227,11 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta seq = ntohs(rtp_hdr->sequence); timestamp = ntohl(rtp_hdr->timestamp); arrival_time = get_current_ts(); + ssrc = ntohl(rtp_hdr->ssrc);
if (!state->initialized) { state->in_stream.last_seq = seq - 1; - state->in_stream.ssrc = state->orig_ssrc = rtp_hdr->ssrc; + state->in_stream.ssrc = state->orig_ssrc = ssrc; state->in_stream.last_tsdelta = 0; state->base_seq = seq; state->initialized = 1; @@ -242,8 +243,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta rtp_end->frame_duration_den; state->out_stream = state->in_stream; state->out_stream.last_timestamp = timestamp; - /* force output SSRC change */ - state->out_stream.ssrc = rtp_hdr->ssrc - 1; + state->out_stream.ssrc = ssrc - 1; /* force output SSRC change */ LOGP(DMGCP, LOGL_INFO, "Initializing stream on 0x%x SSRC: %u timestamp: %u " "pkt-duration: %d, from %s:%d in %d\n", @@ -251,7 +251,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta state->seq_offset, state->packet_duration, inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), endp->conn_mode); - } else if (state->in_stream.ssrc != rtp_hdr->ssrc) { + } else if (state->in_stream.ssrc != ssrc) { LOGP(DMGCP, LOGL_NOTICE, "The SSRC changed on 0x%x: %u -> %u " "from %s:%d in %d\n", @@ -260,7 +260,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), endp->conn_mode);
- state->in_stream.ssrc = rtp_hdr->ssrc; + state->in_stream.ssrc = ssrc; if (rtp_end->force_constant_ssrc) { int32_t tsdelta = state->out_stream.last_tsdelta; if (tsdelta == 0) { @@ -279,6 +279,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta (state->out_stream.last_timestamp + tsdelta) - timestamp; state->patch = 1; + ssrc = state->orig_ssrc;
LOGP(DMGCP, LOGL_NOTICE, "SSRC patching enabled on 0x%x SSRC: %u " @@ -296,6 +297,9 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta check_rtp_timestamp(endp, &state->in_stream, rtp_end, addr, seq, timestamp, "input", &state->in_stream.last_tsdelta); + + if (state->patch) + ssrc = state->orig_ssrc; }
/* Save before patching */ @@ -306,14 +310,14 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta if (state->patch) { seq += state->seq_offset; rtp_hdr->sequence = htons(seq); - rtp_hdr->ssrc = state->orig_ssrc; + rtp_hdr->ssrc = htonl(ssrc);
timestamp += state->timestamp_offset; rtp_hdr->timestamp = htonl(timestamp); }
/* Check again, whether the timestamps are still valid */ - if (state->out_stream.ssrc == rtp_hdr->ssrc) + if (state->out_stream.ssrc == ssrc) check_rtp_timestamp(endp, &state->out_stream, rtp_end, addr, seq, timestamp, "output", &state->out_stream.last_tsdelta); @@ -350,7 +354,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta /* Save output values */ state->out_stream.last_seq = seq; state->out_stream.last_timestamp = timestamp; - state->out_stream.ssrc = rtp_hdr->ssrc; + state->out_stream.ssrc = ssrc;
if (payload < 0) return; diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c index 908773a..e5b8bbd 100644 --- a/openbsc/tests/mgcp/mgcp_test.c +++ b/openbsc/tests/mgcp/mgcp_test.c @@ -586,7 +586,7 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
if (state.out_stream.ssrc != last_ssrc) { printf("Output SSRC changed to %08x\n", - ntohl(state.out_stream.ssrc)); + state.out_stream.ssrc); last_ssrc = state.out_stream.ssrc; }
On Thu, Dec 05, 2013 at 05:44:22PM +0100, Jacob Erlbeck wrote:
Dear Jacob,
if (state.out_stream.ssrc != last_ssrc) { printf("Output SSRC changed to %08x\n",
ntohl(state.out_stream.ssrc));
state.out_stream.ssrc);
is an update of the .ok file missing or is this case not tested by our regression suite?
thanks holger
On 12/09/2013 05:01 PM, Holger Hans Peter Freyther wrote:
On Thu, Dec 05, 2013 at 05:44:22PM +0100, Jacob Erlbeck wrote:
if (state.out_stream.ssrc != last_ssrc) { printf("Output SSRC changed to %08x\n",
ntohl(state.out_stream.ssrc));
state.out_stream.ssrc);is an update of the .ok file missing or is this case not tested by our regression suite?
The ntohl() has been moved from here to where the binary data is read (mgcp_network.c), so the .ok file remains unchanged (in opposite to the log messages).
Jacob
Currently the output SSRC is always forced to be the same if SSRC patching is enabled.
This patch modifies this to optionally restrict the number of SSRC changes that will be corrected.
Note that the configuration only allows for the 'once' mode and 'off'.
Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/mgcp_internal.h | 2 +- openbsc/src/libmgcp/mgcp_network.c | 2 ++ openbsc/src/libmgcp/mgcp_protocol.c | 4 +++- openbsc/src/libmgcp/mgcp_vty.c | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h index b16bd49..255161f 100644 --- a/openbsc/include/openbsc/mgcp_internal.h +++ b/openbsc/include/openbsc/mgcp_internal.h @@ -85,7 +85,7 @@ struct mgcp_rtp_end { char *fmtp_extra;
/* RTP patching */ - int force_constant_ssrc; + int force_constant_ssrc; /* -1: always, 0: don't, 1: once */ int force_constant_timing;
/* diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index abb48f5..79c9e1a 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -280,6 +280,8 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta timestamp; state->patch = 1; ssrc = state->orig_ssrc; + if (rtp_end->force_constant_ssrc != -1) + rtp_end->force_constant_ssrc -= 1;
LOGP(DMGCP, LOGL_NOTICE, "SSRC patching enabled on 0x%x SSRC: %u " diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c index d7e4745..facbeb2 100644 --- a/openbsc/src/libmgcp/mgcp_protocol.c +++ b/openbsc/src/libmgcp/mgcp_protocol.c @@ -619,8 +619,10 @@ void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change, { struct mgcp_trunk_config *tcfg = endp->tcfg;
+ int patch_ssrc = expect_ssrc_change && tcfg->force_constant_ssrc; + rtp->force_constant_timing = tcfg->force_constant_timing; - rtp->force_constant_ssrc = tcfg->force_constant_ssrc; + rtp->force_constant_ssrc = patch_ssrc ? 1 : 0; }
static struct msgb *handle_create_con(struct mgcp_parse_data *p) diff --git a/openbsc/src/libmgcp/mgcp_vty.c b/openbsc/src/libmgcp/mgcp_vty.c index 16b973f..38570cb 100644 --- a/openbsc/src/libmgcp/mgcp_vty.c +++ b/openbsc/src/libmgcp/mgcp_vty.c @@ -613,7 +613,7 @@ DEFUN(cfg_trunk_patch_rtp_ssrc, RTP_PATCH_STR "Force a fixed SSRC\n" "Disable\n" - "Enable\n" + "Enable (once per MDCX)\n" ) { struct mgcp_trunk_config *trunk = vty->index;
This forces the output timing to fulfill dTS = dSegNo * fixedPacketDuration where dSegNo = seqNo - lastSeqNo.
If timestamp patching is enabled, the output timestamp will be set to lastTimestamp + dTS. This kind of relative updating is used to handle seqNo- and timestamp-wraparounds properly.
The updating of timestamp and SSRC has been separated and the patch field of mgcp_rtp_state has been renamed to patch_ssrc to reflect it's semantics more closely. The offset fields are now used always and will change the corresponding header field if they are != 0.
Ticket: OW#1065 Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/mgcp_internal.h | 2 +- openbsc/src/libmgcp/mgcp_network.c | 40 +++++++++++++---- openbsc/tests/mgcp/mgcp_test.ok | 72 +++++++++++++++---------------- 3 files changed, 68 insertions(+), 46 deletions(-)
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h index 255161f..b6f4a0d 100644 --- a/openbsc/include/openbsc/mgcp_internal.h +++ b/openbsc/include/openbsc/mgcp_internal.h @@ -50,7 +50,7 @@ struct mgcp_rtp_stream_state {
struct mgcp_rtp_state { int initialized; - int patch; + int patch_ssrc;
uint32_t orig_ssrc;
diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index 79c9e1a..6463ae0 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -278,7 +278,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta state->timestamp_offset = (state->out_stream.last_timestamp + tsdelta) - timestamp; - state->patch = 1; + state->patch_ssrc = 1; ssrc = state->orig_ssrc; if (rtp_end->force_constant_ssrc != -1) rtp_end->force_constant_ssrc -= 1; @@ -300,7 +300,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta seq, timestamp, "input", &state->in_stream.last_tsdelta);
- if (state->patch) + if (state->patch_ssrc) ssrc = state->orig_ssrc; }
@@ -308,16 +308,38 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta state->in_stream.last_timestamp = timestamp; state->in_stream.last_seq = seq;
- /* apply the offset and store it back to the packet */ - if (state->patch) { - seq += state->seq_offset; - rtp_hdr->sequence = htons(seq); - rtp_hdr->ssrc = htonl(ssrc); + if (rtp_end->force_constant_timing && + state->out_stream.ssrc == ssrc && state->packet_duration) { + int delta_seq = seq + state->seq_offset - state->out_stream.last_seq; + int timestamp_offset = + state->out_stream.last_timestamp - timestamp + + delta_seq * state->packet_duration; + if (state->timestamp_offset != timestamp_offset) { + state->timestamp_offset = timestamp_offset;
- timestamp += state->timestamp_offset; - rtp_hdr->timestamp = htonl(timestamp); + LOGP(DMGCP, LOGL_NOTICE, + "Timestamp patching enabled on 0x%x SSRC: %u " + "SeqNo delta: %d, TS offset: %d, " + "from %s:%d in %d\n", + ENDPOINT_NUMBER(endp), state->in_stream.ssrc, + delta_seq, state->timestamp_offset, + inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), + endp->conn_mode); + } }
+ /* Store the updated SSRC back to the packet */ + if (state->patch_ssrc) + rtp_hdr->ssrc = htonl(ssrc); + + /* Apply the offset and store it back to the packet. + * This won't change anything if the offset is 0, so the conditional is + * omitted. */ + seq += state->seq_offset; + rtp_hdr->sequence = htons(seq); + timestamp += state->timestamp_offset; + rtp_hdr->timestamp = htonl(timestamp); + /* Check again, whether the timestamps are still valid */ if (state->out_stream.ssrc == ssrc) check_rtp_timestamp(endp, &state->out_stream, rtp_end, addr, diff --git a/openbsc/tests/mgcp/mgcp_test.ok b/openbsc/tests/mgcp/mgcp_test.ok index 4d3caac..3beeb59 100644 --- a/openbsc/tests/mgcp/mgcp_test.ok +++ b/openbsc/tests/mgcp/mgcp_test.ok @@ -94,46 +94,46 @@ Output SSRC changed to 11223344 TS: 0, dTS: 0, TS Errs: in 0, out 0 TS: 160, dTS: 160, TS Errs: in 0, out 0 TS: 320, dTS: 160, TS Errs: in 0, out 0 -TS: 320, dTS: 160, TS Errs: in 1, out 1 -TS: 480, dTS: 160, TS Errs: in 1, out 1 -TS: 640, dTS: 160, TS Errs: in 1, out 1 -TS: 960, dTS: 320, TS Errs: in 2, out 2 -TS: 1120, dTS: 160, TS Errs: in 3, out 3 -TS: 1280, dTS: 160, TS Errs: in 3, out 3 -TS: 1400, dTS: 120, TS Errs: in 4, out 4 -TS: 1560, dTS: 160, TS Errs: in 5, out 5 -TS: 1720, dTS: 160, TS Errs: in 5, out 5 +TS: 480, dTS: 160, TS Errs: in 1, out 0 +TS: 640, dTS: 160, TS Errs: in 1, out 0 +TS: 800, dTS: 160, TS Errs: in 1, out 0 +TS: 960, dTS: 160, TS Errs: in 2, out 0 +TS: 1120, dTS: 160, TS Errs: in 3, out 0 +TS: 1280, dTS: 160, TS Errs: in 3, out 0 +TS: 1440, dTS: 160, TS Errs: in 4, out 0 +TS: 1600, dTS: 160, TS Errs: in 5, out 0 +TS: 1760, dTS: 160, TS Errs: in 5, out 0 Output SSRC changed to 10203040 -TS: 34688, dTS: 160, TS Errs: in 5, out 5 -TS: 34848, dTS: 160, TS Errs: in 5, out 5 -TS: 35008, dTS: 160, TS Errs: in 5, out 5 -TS: 35128, dTS: 120, TS Errs: in 6, out 6 -TS: 35288, dTS: 160, TS Errs: in 7, out 7 -TS: 35448, dTS: 160, TS Errs: in 7, out 7 -TS: 35768, dTS: 160, TS Errs: in 7, out 7 -TS: 35928, dTS: 160, TS Errs: in 7, out 7 -TS: 36088, dTS: 160, TS Errs: in 8, out 8 +TS: 34728, dTS: 160, TS Errs: in 5, out 0 +TS: 34888, dTS: 160, TS Errs: in 5, out 0 +TS: 35048, dTS: 160, TS Errs: in 5, out 0 +TS: 35208, dTS: 160, TS Errs: in 6, out 0 +TS: 35368, dTS: 160, TS Errs: in 7, out 0 +TS: 35528, dTS: 160, TS Errs: in 7, out 0 +TS: 35848, dTS: 160, TS Errs: in 7, out 0 +TS: 36008, dTS: 160, TS Errs: in 7, out 0 +TS: 36008, dTS: 160, TS Errs: in 8, out 0 Testing packet error detection, patch SSRC, patch timestamps. Output SSRC changed to 11223344 TS: 0, dTS: 0, TS Errs: in 0, out 0 TS: 160, dTS: 160, TS Errs: in 0, out 0 TS: 320, dTS: 160, TS Errs: in 0, out 0 -TS: 320, dTS: 160, TS Errs: in 1, out 1 -TS: 480, dTS: 160, TS Errs: in 1, out 1 -TS: 640, dTS: 160, TS Errs: in 1, out 1 -TS: 960, dTS: 320, TS Errs: in 2, out 2 -TS: 1120, dTS: 160, TS Errs: in 3, out 3 -TS: 1280, dTS: 160, TS Errs: in 3, out 3 -TS: 1400, dTS: 120, TS Errs: in 4, out 4 -TS: 1560, dTS: 160, TS Errs: in 5, out 5 -TS: 1720, dTS: 160, TS Errs: in 5, out 5 -TS: 1880, dTS: 160, TS Errs: in 5, out 5 -TS: 2040, dTS: 160, TS Errs: in 5, out 5 -TS: 2200, dTS: 160, TS Errs: in 5, out 5 -TS: 2320, dTS: 120, TS Errs: in 6, out 6 -TS: 2480, dTS: 160, TS Errs: in 7, out 7 -TS: 2640, dTS: 160, TS Errs: in 7, out 7 -TS: 2960, dTS: 160, TS Errs: in 7, out 7 -TS: 3120, dTS: 160, TS Errs: in 7, out 7 -TS: 3280, dTS: 160, TS Errs: in 8, out 8 +TS: 480, dTS: 160, TS Errs: in 1, out 0 +TS: 640, dTS: 160, TS Errs: in 1, out 0 +TS: 800, dTS: 160, TS Errs: in 1, out 0 +TS: 960, dTS: 160, TS Errs: in 2, out 0 +TS: 1120, dTS: 160, TS Errs: in 3, out 0 +TS: 1280, dTS: 160, TS Errs: in 3, out 0 +TS: 1440, dTS: 160, TS Errs: in 4, out 0 +TS: 1600, dTS: 160, TS Errs: in 5, out 0 +TS: 1760, dTS: 160, TS Errs: in 5, out 0 +TS: 1920, dTS: 160, TS Errs: in 5, out 0 +TS: 2080, dTS: 160, TS Errs: in 5, out 0 +TS: 2240, dTS: 160, TS Errs: in 5, out 0 +TS: 2400, dTS: 160, TS Errs: in 6, out 0 +TS: 2560, dTS: 160, TS Errs: in 7, out 0 +TS: 2720, dTS: 160, TS Errs: in 7, out 0 +TS: 3040, dTS: 160, TS Errs: in 7, out 0 +TS: 3200, dTS: 160, TS Errs: in 7, out 0 +TS: 3200, dTS: 160, TS Errs: in 8, out 0 Done
Since the packet duration is given in ms with the 'ptime' RTP media attribute and also with the 'p' MGCP local connection option, the computation is changed to use this value (if present). The computation assumes, that there are N complete frames in a packet and takes into account, that the ptime value possibly had been rounded towards the next ms value (which is never the case with a frame length of exact 20ms).
Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/mgcp_internal.h | 3 +++ openbsc/src/libmgcp/mgcp_network.c | 5 +---- openbsc/src/libmgcp/mgcp_protocol.c | 24 +++++++++++++++++++++--- 3 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h index b6f4a0d..d59c5d7 100644 --- a/openbsc/include/openbsc/mgcp_internal.h +++ b/openbsc/include/openbsc/mgcp_internal.h @@ -82,6 +82,7 @@ struct mgcp_rtp_end { uint32_t frame_duration_num; uint32_t frame_duration_den; int frames_per_packet; + uint32_t packet_duration_ms; char *fmtp_extra;
/* RTP patching */ @@ -180,6 +181,8 @@ struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change, struct mgcp_rtp_end *rtp); +uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp, + struct mgcp_rtp_end *rtp);
void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *, uint32_t *expected, int *loss); diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index 6463ae0..bf205d1 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -237,10 +237,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta state->initialized = 1; state->jitter = 0; state->transit = arrival_time - timestamp; - state->packet_duration = - rtp_end->rate * rtp_end->frames_per_packet * - rtp_end->frame_duration_num / - rtp_end->frame_duration_den; + state->packet_duration = mgcp_rtp_packet_duration(endp, rtp_end); state->out_stream = state->in_stream; state->out_stream.last_timestamp = timestamp; state->out_stream.ssrc = ssrc - 1; /* force output SSRC change */ diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c index facbeb2..3e26ad6 100644 --- a/openbsc/src/libmgcp/mgcp_protocol.c +++ b/openbsc/src/libmgcp/mgcp_protocol.c @@ -75,7 +75,7 @@ char *strline_r(char *str, char **saveptr) /* Assume audio frame length of 20ms */ #define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20 #define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000 -#define DEFAULT_RTP_AUDIO_FRAMES_PER_PACKET 1 +#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20 #define DEFAULT_RTP_AUDIO_DEFAULT_RATE 8000
static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end); @@ -625,6 +625,23 @@ void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change, rtp->force_constant_ssrc = patch_ssrc ? 1 : 0; }
+uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp, + struct mgcp_rtp_end *rtp) +{ + int f = 0; + + /* Get the number of frames per channel and packet */ + if (rtp->frames_per_packet) + f = rtp->frames_per_packet; + else if (rtp->packet_duration_ms && rtp->frame_duration_num) { + int den = 1000 * rtp->frame_duration_num; + f = (rtp->packet_duration_ms * rtp->frame_duration_den + den/2) + / den; + } + + return rtp->rate * f * rtp->frame_duration_num / rtp->frame_duration_den; +} + static struct msgb *handle_create_con(struct mgcp_parse_data *p) { struct mgcp_trunk_config *tcfg; @@ -1080,8 +1097,9 @@ static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end) /* Set default values */ end->frame_duration_num = DEFAULT_RTP_AUDIO_FRAME_DUR_NUM; end->frame_duration_den = DEFAULT_RTP_AUDIO_FRAME_DUR_DEN; - end->frames_per_packet = DEFAULT_RTP_AUDIO_FRAMES_PER_PACKET; - end->rate = DEFAULT_RTP_AUDIO_DEFAULT_RATE; + end->frames_per_packet = 0; /* unknown */ + end->packet_duration_ms = DEFAULT_RTP_AUDIO_PACKET_DURATION_MS; + end->rate = DEFAULT_RTP_AUDIO_DEFAULT_RATE; }
static void mgcp_rtp_end_init(struct mgcp_rtp_end *end)