[PATCH 3/4] mgcp/rtp: Add test case for RTP timestamp patching and stats

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.

Jacob Erlbeck jerlbeck at sysmocom.de
Thu Nov 21 18:05:44 UTC 2013


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
---
 openbsc/src/libmgcp/mgcp_network.c |   18 +++---
 openbsc/tests/mgcp/mgcp_test.c     |  106 ++++++++++++++++++++++++++++++++++++
 openbsc/tests/mgcp/mgcp_test.ok    |   16 ++++++
 3 files changed, 131 insertions(+), 9 deletions(-)

diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c
index 14bc024..17e3d87 100644
--- a/openbsc/src/libmgcp/mgcp_network.c
+++ b/openbsc/src/libmgcp/mgcp_network.c
@@ -142,9 +142,9 @@ int mgcp_send_dummy(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;
@@ -346,9 +346,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,
@@ -361,9 +361,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 3499ee3..705db80 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.last_timestamp,
+		       state.last_tsdelta,
+		       state.err_ts_in_counter,
+		       state.err_ts_out_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 8711e38..8c3fa26 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
-- 
1.7.9.5





More information about the OpenBSC mailing list