[PATCH] openbsc[master]: mgcp: Add jitter buffer on the uplink receiver

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/gerrit-log@lists.osmocom.org/.

Pau Espin Pedrol gerrit-no-reply at lists.osmocom.org
Fri Apr 13 14:25:37 UTC 2018


Review at  https://gerrit.osmocom.org/7793

mgcp: Add jitter buffer on the uplink receiver

Default usage values are defined in mgcp node, and can be per-BSC
overriden on each bsc node.

Change-Id: Ibf3932adc07442fb5e9c7a06404853f9d0a20959
---
M openbsc/include/openbsc/bsc_nat.h
M openbsc/include/openbsc/mgcp.h
M openbsc/include/openbsc/mgcp_internal.h
M openbsc/src/libmgcp/mgcp_network.c
M openbsc/src/libmgcp/mgcp_protocol.c
M openbsc/src/libmgcp/mgcp_vty.c
M openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c
M openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
8 files changed, 253 insertions(+), 3 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/openbsc refs/changes/93/7793/1

diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index fad3804..48cd034 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -175,6 +175,16 @@
 
 	/* Osmux is enabled/disabled per BSC */
 	int osmux;
+
+	/* Use a jitterbuffer on the bts-side receiver */
+	bool bts_use_jibuf;
+	/* Minimum and maximum buffer size for the jitter buffer */
+	uint32_t bts_jitter_delay_min;
+	uint32_t bts_jitter_delay_max;
+	/* Enabled if explicitly configured through VTY: */
+	bool bts_use_jibuf_override;
+	bool bts_jitter_delay_min_override;
+	bool bts_jitter_delay_max_override;
 };
 
 struct bsc_lac_entry {
diff --git a/openbsc/include/openbsc/mgcp.h b/openbsc/include/openbsc/mgcp.h
index b2262bc..8dc3e76 100644
--- a/openbsc/include/openbsc/mgcp.h
+++ b/openbsc/include/openbsc/mgcp.h
@@ -236,6 +236,12 @@
 	 * message.
 	 */
 	uint16_t osmux_dummy;
+
+	/* Use a jitterbuffer on the bts-side receiver */
+	bool bts_use_jibuf;
+	/* Minimum and maximum buffer size for the jitter buffer */
+	uint32_t bts_jitter_delay_min;
+	uint32_t bts_jitter_delay_max;
 };
 
 /* config management */
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h
index 7c89d10..4bc4f43 100644
--- a/openbsc/include/openbsc/mgcp_internal.h
+++ b/openbsc/include/openbsc/mgcp_internal.h
@@ -25,6 +25,7 @@
 #include <string.h>
 
 #include <osmocom/core/select.h>
+#include <osmocom/netif/jibuf.h>
 
 #define CI_UNUSED 0
 
@@ -205,6 +206,14 @@
 			uint32_t octets;
 		} stats;
 	} osmux;
+
+	/* Jitter buffer */
+	struct osmo_jibuf* bts_jb;
+	/* Use a jitterbuffer on the bts-side receiver */
+	bool bts_use_jibuf;
+	/* Minimum and maximum buffer size for the jitter buffer */
+	uint32_t bts_jitter_delay_min;
+	uint32_t bts_jitter_delay_max;
 };
 
 #define for_each_line(line, save)			\
@@ -340,3 +349,8 @@
 		return endp->cfg->bts_ports.bind_addr;
 	return endp->cfg->source_addr;
 }
+
+/**
+ * Internal jitter buffer related
+ */
+void mgcp_dejitter_udp_send(struct msgb *msg, void *data);
diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c
index abce6e4..799d998 100644
--- a/openbsc/src/libmgcp/mgcp_network.c
+++ b/openbsc/src/libmgcp/mgcp_network.c
@@ -580,6 +580,36 @@
 	return rc;
 }
 
+void mgcp_dejitter_udp_send(struct msgb *msg, void *data)
+{
+	struct mgcp_rtp_end *rtp_end = (struct mgcp_rtp_end *) data;
+
+	int rc = mgcp_udp_send(rtp_end->rtp.fd, &rtp_end->addr,
+			   rtp_end->rtp_port, (char*) msg->data, msg->len);
+	if (rc != msg->len)
+		LOGP(DMGCP, LOGL_ERROR,
+			"Failed to send data after jitter buffer: %d\n", rc);
+	msgb_free(msg);
+}
+
+static int enqueue_dejitter(struct osmo_jibuf *jb, struct mgcp_rtp_end *rtp_end, char *buf, int len)
+{
+	struct msgb *msg;
+	msg = msgb_alloc(len, "mgcp-jibuf");
+	if (!msg)
+		return -1;
+
+	memcpy(msg->data, buf, len);
+	msgb_put(msg, len);
+
+	if (osmo_jibuf_enqueue(jb, msg) < 0) {
+		rtp_end->dropped_packets += 1;
+		msgb_free(msg);
+	}
+
+	return len;
+}
+
 int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp,
 	      struct sockaddr_in *addr, char *buf, int rc)
 {
@@ -587,6 +617,7 @@
 	struct mgcp_rtp_end *rtp_end;
 	struct mgcp_rtp_state *rtp_state;
 	int tap_idx;
+	struct osmo_jibuf *jb;
 
 	/* For loop toggle the destination and then dispatch. */
 	if (tcfg->audio_loop)
@@ -600,10 +631,12 @@
 		rtp_end = &endp->net_end;
 		rtp_state = &endp->bts_state;
 		tap_idx = MGCP_TAP_NET_OUT;
+		jb = endp->bts_jb;
 	} else {
 		rtp_end = &endp->bts_end;
 		rtp_state = &endp->net_state;
 		tap_idx = MGCP_TAP_BTS_OUT;
+		jb = NULL;
 	}
 
 	if (!rtp_end->output_enabled)
@@ -621,9 +654,12 @@
 			mgcp_patch_and_count(endp, rtp_state, rtp_end, addr, buf, len);
 			forward_data(rtp_end->rtp.fd, &endp->taps[tap_idx],
 				     buf, len);
-			rc = mgcp_udp_send(rtp_end->rtp.fd,
-					   &rtp_end->addr,
-					   rtp_end->rtp_port, buf, len);
+			if (jb)
+				rc = enqueue_dejitter(jb, rtp_end, buf, len);
+			else
+				rc = mgcp_udp_send(rtp_end->rtp.fd,
+						   &rtp_end->addr,
+						   rtp_end->rtp_port, buf, len);
 
 			if (rc <= 0)
 				return rc;
diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c
index ae5c90b..0cdc07b 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -827,6 +827,12 @@
 		goto error2;
 	}
 
+	/* Apply Jiter buffer settings for this endpoint, they can be overriden by CRCX policy later */
+	endp->bts_use_jibuf = endp->cfg->bts_use_jibuf;
+	endp->bts_jitter_delay_min = endp->cfg->bts_jitter_delay_min;
+	endp->bts_jitter_delay_max = endp->cfg->bts_jitter_delay_max;
+
+
 	endp->allocated = 1;
 
 	/* set up RTP media parameters */
@@ -862,12 +868,27 @@
 		case MGCP_POLICY_DEFER:
 			/* stop processing */
 			create_transcoder(endp);
+			/* Set up jitter buffer if required after policy has updated jibuf endp values */
+			if(endp->bts_use_jibuf) {
+				endp->bts_jb = osmo_jibuf_alloc(tcfg->endpoints);
+				osmo_jibuf_set_min_delay(endp->bts_jb, endp->bts_jitter_delay_min);
+				osmo_jibuf_set_max_delay(endp->bts_jb, endp->bts_jitter_delay_max);
+				osmo_jibuf_set_dequeue_cb(endp->bts_jb, mgcp_dejitter_udp_send, &endp->net_end);
+			}
 			return NULL;
 			break;
 		case MGCP_POLICY_CONT:
 			/* just continue */
 			break;
 		}
+	}
+
+	/* Set up jitter buffer if required after policy has updated jibuf endp values */
+	if(endp->bts_use_jibuf) {
+		endp->bts_jb = osmo_jibuf_alloc(tcfg->endpoints);
+		osmo_jibuf_set_min_delay(endp->bts_jb, endp->bts_jitter_delay_min);
+		osmo_jibuf_set_max_delay(endp->bts_jb, endp->bts_jitter_delay_max);
+		osmo_jibuf_set_dequeue_cb(endp->bts_jb, mgcp_dejitter_udp_send, &endp->net_end);
 	}
 
 	LOGP(DMGCP, LOGL_DEBUG, "Creating endpoint on: 0x%x CI: %u port: %u/%u\n",
@@ -1333,6 +1354,9 @@
 void mgcp_release_endp(struct mgcp_endpoint *endp)
 {
 	LOGP(DMGCP, LOGL_DEBUG, "Releasing endpoint on: 0x%x\n", ENDPOINT_NUMBER(endp));
+	if(endp->bts_jb)
+		osmo_jibuf_delete(endp->bts_jb);
+	endp->bts_jb = NULL;
 	endp->ci = CI_UNUSED;
 	endp->allocated = 0;
 
diff --git a/openbsc/src/libmgcp/mgcp_vty.c b/openbsc/src/libmgcp/mgcp_vty.c
index b97d7f8..7f56c9e 100644
--- a/openbsc/src/libmgcp/mgcp_vty.c
+++ b/openbsc/src/libmgcp/mgcp_vty.c
@@ -29,6 +29,7 @@
 #include <openbsc/vty.h>
 
 #include <string.h>
+#include <inttypes.h>
 
 #define RTCP_OMIT_STR "Drop RTCP packets in both directions\n"
 #define RTP_PATCH_STR "Modify RTP packet header in both directions\n"
@@ -164,6 +165,13 @@
 		vty_out(vty, "  osmux dummy %s%s",
 			g_cfg->osmux_dummy ? "on" : "off", VTY_NEWLINE);
 	}
+	if (g_cfg->bts_use_jibuf)
+		vty_out(vty, "  bts-jitter-buffer%s", VTY_NEWLINE);
+	if (g_cfg->bts_jitter_delay_min)
+		vty_out(vty, "  bts-jitter-delay-min %"PRIu32"%s", g_cfg->bts_jitter_delay_min, VTY_NEWLINE);
+	if (g_cfg->bts_jitter_delay_max)
+		vty_out(vty, "  bts-jitter-delay-max %"PRIu32"%s", g_cfg->bts_jitter_delay_max, VTY_NEWLINE);
+
 	return CMD_SUCCESS;
 }
 
@@ -241,6 +249,11 @@
 
 	if (g_cfg->osmux)
 		vty_out(vty, "Osmux used CID: %d%s", osmux_used_cid(), VTY_NEWLINE);
+	vty_out(vty, "Jitter Buffer by default on Uplink : %s%s",
+		g_cfg->bts_use_jibuf ? "on" : "off", VTY_NEWLINE);
+	if (g_cfg->bts_use_jibuf)
+		vty_out(vty, "Jitter Buffer delays: min=%"PRIu32" max=%"PRIu32"%s",
+		g_cfg->bts_jitter_delay_min, g_cfg->bts_jitter_delay_max, VTY_NEWLINE);
 
 	return CMD_SUCCESS;
 }
@@ -1333,6 +1346,63 @@
 	return CMD_SUCCESS;
 }
 
+#define DEJITTER_STR "Uplink Jitter Buffer"
+DEFUN(cfg_mgcp_bts_use_jibuf,
+      cfg_mgcp_bts_use_jibuf_cmd,
+      "bts-jitter-buffer",
+      DEJITTER_STR "\n")
+{
+	g_cfg->bts_use_jibuf = true;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_no_bts_use_jibuf,
+      cfg_mgcp_no_bts_use_jibuf_cmd,
+      "no bts-jitter-buffer",
+      NO_STR DEJITTER_STR "\n")
+{
+	g_cfg->bts_use_jibuf = false;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_bts_jitter_delay_min,
+      cfg_mgcp_bts_jitter_delay_min_cmd,
+      "bts-jitter-buffer-delay-min <1-65535>",
+      DEJITTER_STR " Minimum Delay\n" "Minimum Delay\n")
+{
+	g_cfg->bts_jitter_delay_min = atoi(argv[0]);
+	if (!g_cfg->bts_jitter_delay_min) {
+		vty_out(vty, "bts-jitter-buffer-delay-min cannot be zero.%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	if (g_cfg->bts_jitter_delay_min && g_cfg->bts_jitter_delay_max &&
+	    g_cfg->bts_jitter_delay_min > g_cfg->bts_jitter_delay_max) {
+		vty_out(vty, "bts-jitter-buffer-delay-min cannot be bigger than " \
+			"bts-jitter-buffer-delay-max.%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_bts_jitter_delay_max,
+      cfg_mgcp_bts_jitter_delay_max_cmd,
+      "bts-jitter-buffer-delay-max <1-65535>",
+      DEJITTER_STR " Maximum Delay\n" "Maximum Delay\n")
+{
+	g_cfg->bts_jitter_delay_max = atoi(argv[0]);
+	if (!g_cfg->bts_jitter_delay_max) {
+		vty_out(vty, "bts-jitter-buffer-delay-max cannot be zero.%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	if (g_cfg->bts_jitter_delay_min && g_cfg->bts_jitter_delay_max &&
+	    g_cfg->bts_jitter_delay_min > g_cfg->bts_jitter_delay_max) {
+		vty_out(vty, "bts-jitter-buffer-delay-max cannot be smaller than " \
+			"bts-jitter-buffer-delay-min.%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	return CMD_SUCCESS;
+}
+
 int mgcp_vty_init(void)
 {
 	install_element_ve(&show_mgcp_cmd);
@@ -1399,6 +1469,10 @@
 	install_element(MGCP_NODE, &cfg_mgcp_osmux_dummy_cmd);
 	install_element(MGCP_NODE, &cfg_mgcp_allow_transcoding_cmd);
 	install_element(MGCP_NODE, &cfg_mgcp_no_allow_transcoding_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_bts_use_jibuf_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_no_bts_use_jibuf_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_bts_jitter_delay_min_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_bts_jitter_delay_max_cmd);
 
 
 	install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
diff --git a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c
index 48847865..80a8a7a 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c
@@ -585,6 +585,16 @@
 	if (state == MGCP_ENDP_CRCX) {
 		struct sockaddr_in sock;
 
+		/* set up jitter buffer parameters */
+		if(bsc_endp->bsc->cfg->bts_use_jibuf_override)
+			mgcp_endp->bts_use_jibuf = bsc_endp->bsc->cfg->bts_use_jibuf;
+
+		if(bsc_endp->bsc->cfg->bts_jitter_delay_min_override)
+			mgcp_endp->bts_jitter_delay_min = bsc_endp->bsc->cfg->bts_jitter_delay_min;
+
+		if(bsc_endp->bsc->cfg->bts_jitter_delay_max_override)
+			mgcp_endp->bts_jitter_delay_max = bsc_endp->bsc->cfg->bts_jitter_delay_max;
+
 		/* Annotate the allocated Osmux CID until the bsc confirms that
 		 * it agrees to use Osmux for this voice flow.
 		 */
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
index d4cef5d..001780e 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
@@ -40,6 +40,7 @@
 
 #include <stdlib.h>
 #include <stdbool.h>
+#include <inttypes.h>
 
 static struct bsc_nat *_nat;
 
@@ -173,6 +174,12 @@
 		vty_out(vty, "  osmux only%s", VTY_NEWLINE);
 		break;
 	}
+	if (bsc->bts_use_jibuf_override)
+		vty_out(vty, "  %sbts-jitter-buffer%s", bsc->bts_use_jibuf? "" : "no ", VTY_NEWLINE);
+	if (bsc->bts_jitter_delay_min_override)
+		vty_out(vty, "  bts-jitter-delay-min %"PRIu32"%s", bsc->bts_jitter_delay_min, VTY_NEWLINE);
+	if (bsc->bts_jitter_delay_max_override)
+		vty_out(vty, "  bts-jitter-delay-max %"PRIu32"%s", bsc->bts_jitter_delay_max, VTY_NEWLINE);
 }
 
 static int config_write_bsc(struct vty *vty)
@@ -1231,6 +1238,71 @@
 	return CMD_SUCCESS;
 }
 
+#define DEJITTER_STR "Uplink Jitter Buffer"
+DEFUN(cfg_bsc_bts_use_jibuf,
+      cfg_bsc_bts_use_jibuf_cmd,
+      "bts-jitter-buffer",
+      DEJITTER_STR "\n")
+{
+	struct bsc_config *conf = vty->index;
+	conf->bts_use_jibuf = true;
+	conf->bts_use_jibuf_override = true;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bsc_no_bts_use_jibuf,
+      cfg_bsc_no_bts_use_jibuf_cmd,
+      "no bts-jitter-buffer",
+      NO_STR DEJITTER_STR "\n")
+{
+	struct bsc_config *conf = vty->index;
+	conf->bts_use_jibuf = false;
+	conf->bts_use_jibuf_override = true;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bsc_bts_jitter_delay_min,
+      cfg_bsc_bts_jitter_delay_min_cmd,
+      "bts-jitter-buffer-delay-min <1-65535>",
+      DEJITTER_STR " Minimum Delay\n" "Minimum Delay\n")
+{
+	struct bsc_config *conf = vty->index;
+	conf->bts_jitter_delay_min = atoi(argv[0]);
+	if (!conf->bts_jitter_delay_min) {
+		vty_out(vty, "bts-jitter-buffer-delay-min cannot be zero.%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	if (conf->bts_jitter_delay_min && conf->bts_jitter_delay_max &&
+	    conf->bts_jitter_delay_min > conf->bts_jitter_delay_max) {
+		vty_out(vty, "bts-jitter-buffer-delay-min cannot be bigger than " \
+			"bts-jitter-buffer-delay-max.%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	conf->bts_jitter_delay_min_override = true;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bsc_bts_jitter_delay_max,
+      cfg_bsc_bts_jitter_delay_max_cmd,
+      "bts-jitter-buffer-delay-max <1-65535>",
+      DEJITTER_STR " Maximum Delay\n" "Maximum Delay\n")
+{
+	struct bsc_config *conf = vty->index;
+	conf->bts_jitter_delay_max = atoi(argv[0]);
+	if (!conf->bts_jitter_delay_max) {
+		vty_out(vty, "bts-jitter-buffer-delay-max cannot be zero.%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	if (conf->bts_jitter_delay_min && conf->bts_jitter_delay_max &&
+	    conf->bts_jitter_delay_min > conf->bts_jitter_delay_max) {
+		vty_out(vty, "bts-jitter-buffer-delay-max cannot be smaller than " \
+			"bts-jitter-buffer-delay-min.%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	conf->bts_jitter_delay_max_override = true;
+	return CMD_SUCCESS;
+}
+
 int bsc_nat_vty_init(struct bsc_nat *nat)
 {
 	_nat = nat;
@@ -1318,6 +1390,10 @@
 	install_element(NAT_BSC_NODE, &cfg_bsc_paging_grp_cmd);
 	install_element(NAT_BSC_NODE, &cfg_bsc_no_paging_grp_cmd);
 	install_element(NAT_BSC_NODE, &cfg_bsc_osmux_cmd);
+	install_element(NAT_BSC_NODE, &cfg_bsc_bts_use_jibuf_cmd);
+	install_element(NAT_BSC_NODE, &cfg_bsc_no_bts_use_jibuf_cmd);
+	install_element(NAT_BSC_NODE, &cfg_bsc_bts_jitter_delay_min_cmd);
+	install_element(NAT_BSC_NODE, &cfg_bsc_bts_jitter_delay_max_cmd);
 
 	mgcp_vty_init();
 

-- 
To view, visit https://gerrit.osmocom.org/7793
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibf3932adc07442fb5e9c7a06404853f9d0a20959
Gerrit-PatchSet: 1
Gerrit-Project: openbsc
Gerrit-Branch: master
Gerrit-Owner: Pau Espin Pedrol <pespin at sysmocom.de>



More information about the gerrit-log mailing list