aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2013-11-25 12:53:29 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-11-25 18:13:35 +0100
commitd62419b574f7002b1c857d9e2df72a95daca36f1 (patch)
tree1971b7a0aceaa7fa92f86fff235a64eb09b8f1a1
parent50079a18434836fc6193f7d8ee30aeda6adbf872 (diff)
mgcp/rtp: Add test case for RTP timestamp patching and stats
This patch adds a test case to check, whether RTP timestamps are generated properly after SSRC changes and whether the error counters work properly. Sponsored-by: On-Waves ehf
-rw-r--r--openbsc/src/libmgcp/mgcp_network.c18
-rw-r--r--openbsc/tests/mgcp/mgcp_test.c106
-rw-r--r--openbsc/tests/mgcp/mgcp_test.ok16
3 files changed, 131 insertions, 9 deletions
diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c
index 6966be64..72d0a5c3 100644
--- a/openbsc/src/libmgcp/mgcp_network.c
+++ b/openbsc/src/libmgcp/mgcp_network.c
@@ -209,9 +209,9 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
* There is also no probation period for new sources. Every package
* we receive will be seen as a switch in streams.
*/
-static void 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)
+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)
{
uint32_t arrival_time;
int32_t transit, d;
@@ -369,9 +369,9 @@ static int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp,
if (dest == MGCP_DEST_NET) {
if (is_rtp) {
- patch_and_count(endp, &endp->bts_state,
- &endp->net_end,
- addr, buf, rc);
+ mgcp_patch_and_count(endp, &endp->bts_state,
+ &endp->net_end,
+ addr, buf, rc);
forward_data(endp->net_end.rtp.fd,
&endp->taps[MGCP_TAP_NET_OUT], buf, rc);
return mgcp_udp_send(endp->net_end.rtp.fd,
@@ -384,9 +384,9 @@ static int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp,
}
} else {
if (is_rtp) {
- patch_and_count(endp, &endp->net_state,
- &endp->bts_end,
- addr, buf, rc);
+ mgcp_patch_and_count(endp, &endp->net_state,
+ &endp->bts_end,
+ addr, buf, rc);
forward_data(endp->bts_end.rtp.fd,
&endp->taps[MGCP_TAP_BTS_OUT], buf, rc);
return mgcp_udp_send(endp->bts_end.rtp.fd,
diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c
index 46eb9844..b2d20b45 100644
--- a/openbsc/tests/mgcp/mgcp_test.c
+++ b/openbsc/tests/mgcp/mgcp_test.c
@@ -348,6 +348,111 @@ static void test_mgcp_stats(void)
msgb_free(msg);
}
+struct rtp_packet_info {
+ float txtime;
+ int len;
+ char *data;
+};
+
+struct rtp_packet_info test_rtp_packets1[] = {
+ /* RTP: SeqNo=0, TS=0 */
+ {0.000000, 20, "\x80\x62\x00\x00\x00\x00\x00\x00\x11\x22\x33\x44"
+ "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+ /* RTP: SeqNo=1, TS=160 */
+ {0.020000, 20, "\x80\x62\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
+ "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+ /* RTP: SeqNo=2, TS=320 */
+ {0.040000, 20, "\x80\x62\x00\x02\x00\x00\x01\x40\x11\x22\x33\x44"
+ "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+ /* Repeat RTP timestamp: */
+ /* RTP: SeqNo=3, TS=320 */
+ {0.060000, 20, "\x80\x62\x00\x03\x00\x00\x01\x40\x11\x22\x33\x44"
+ "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+ /* RTP: SeqNo=4, TS=480 */
+ {0.080000, 20, "\x80\x62\x00\x04\x00\x00\x01\xE0\x11\x22\x33\x44"
+ "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+ /* RTP: SeqNo=5, TS=640 */
+ {0.100000, 20, "\x80\x62\x00\x05\x00\x00\x02\x80\x11\x22\x33\x44"
+ "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+ /* Double skip RTP timestamp (delta = 2*160): */
+ /* RTP: SeqNo=6, TS=960 */
+ {0.120000, 20, "\x80\x62\x00\x06\x00\x00\x03\xC0\x11\x22\x33\x44"
+ "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+ /* RTP: SeqNo=7, TS=1120 */
+ {0.140000, 20, "\x80\x62\x00\x07\x00\x00\x04\x60\x11\x22\x33\x44"
+ "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+ /* RTP: SeqNo=8, TS=1280 */
+ {0.160000, 20, "\x80\x62\x00\x08\x00\x00\x05\x00\x11\x22\x33\x44"
+ "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+ /* Non 20ms RTP timestamp (delta = 120): */
+ /* RTP: SeqNo=9, TS=1400 */
+ {0.180000, 20, "\x80\x62\x00\x09\x00\x00\x05\x78\x11\x22\x33\x44"
+ "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+ /* RTP: SeqNo=10, TS=1560 */
+ {0.200000, 20, "\x80\x62\x00\x0A\x00\x00\x06\x18\x11\x22\x33\x44"
+ "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+ /* RTP: SeqNo=11, TS=1720 */
+ {0.220000, 20, "\x80\x62\x00\x0B\x00\x00\x06\xB8\x11\x22\x33\x44"
+ "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+ /* SSRC changed to 0x10203040, RTP timestamp jump */
+ /* RTP: SeqNo=12, TS=34688 */
+ {0.240000, 20, "\x80\x62\x00\x0C\x00\x00\x87\x80\x10\x20\x30\x40"
+ "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+ /* RTP: SeqNo=13, TS=34848 */
+ {0.260000, 20, "\x80\x62\x00\x0D\x00\x00\x88\x20\x10\x20\x30\x40"
+ "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+ /* 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"},
+};
+
+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)
+{
+ int i;
+
+ struct mgcp_trunk_config trunk;
+ struct mgcp_endpoint endp;
+ struct mgcp_rtp_state state;
+ struct mgcp_rtp_end rtp;
+ struct sockaddr_in addr = {0};
+ char buffer[4096];
+
+ printf("Testing packet error detection.\n");
+
+ memset(&trunk, 0, sizeof(trunk));
+ memset(&endp, 0, sizeof(endp));
+ memset(&state, 0, sizeof(state));
+ memset(&rtp, 0, sizeof(rtp));
+
+ trunk.number_endpoints = 1;
+ trunk.endpoints = &endp;
+
+ rtp.payload_type = 98;
+ endp.allow_patch = 1;
+ endp.tcfg = &trunk;
+
+ for (i = 0; i < ARRAY_SIZE(test_rtp_packets1); ++i) {
+ struct rtp_packet_info *info = test_rtp_packets1 + i;
+
+ OSMO_ASSERT(info->len <= sizeof(buffer));
+ OSMO_ASSERT(info->len >= 0);
+ memmove(buffer, info->data, info->len);
+
+ mgcp_patch_and_count(&endp, &state, &rtp, &addr,
+ buffer, info->len);
+
+ printf("TS: %d, dTS: %d, TS Errs: in %d, out %d\n",
+ state.out_stream.last_timestamp,
+ state.out_stream.last_tsdelta,
+ state.in_stream.err_ts_counter,
+ state.out_stream.err_ts_counter);
+ }
+}
+
int main(int argc, char **argv)
{
osmo_init_logging(&log_info);
@@ -357,6 +462,7 @@ int main(int argc, char **argv)
test_packet_loss_calc();
test_rqnt_cb();
test_mgcp_stats();
+ test_packet_error_detection();
printf("Done\n");
return EXIT_SUCCESS;
diff --git a/openbsc/tests/mgcp/mgcp_test.ok b/openbsc/tests/mgcp/mgcp_test.ok
index 8711e38f..8c3fa266 100644
--- a/openbsc/tests/mgcp/mgcp_test.ok
+++ b/openbsc/tests/mgcp/mgcp_test.ok
@@ -28,4 +28,20 @@ Testing packet loss calculation.
Testing stat parsing
Parsing result: 0
Parsing result: 0
+Testing packet error detection.
+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: 1720, dTS: 160, TS Errs: in 5, out 6
+TS: 1880, dTS: 160, TS Errs: in 5, out 6
+TS: 2040, dTS: 160, TS Errs: in 5, out 6
Done