mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
				synced 2025-11-04 05:53:26 +00:00 
			
		
		
		
	legacy-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 This commit is a forward-port of openbsc.git Change-Id Ibf3932adc07442fb5e9c7a06404853f9d0a20959. Change-Id: Ie19a64ac09f9d51f2434ad0d7925610fc919a90e
This commit is contained in:
		@@ -243,6 +243,12 @@ struct mgcp_config {
 | 
			
		||||
	 * 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, in ms */
 | 
			
		||||
	uint32_t bts_jitter_delay_min;
 | 
			
		||||
	uint32_t bts_jitter_delay_max;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* config management */
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/select.h>
 | 
			
		||||
#include <osmocom/netif/jibuf.h>
 | 
			
		||||
 | 
			
		||||
#define CI_UNUSED 0
 | 
			
		||||
 | 
			
		||||
@@ -198,6 +199,14 @@ struct mgcp_endpoint {
 | 
			
		||||
			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, in ms */
 | 
			
		||||
	uint32_t bts_jitter_delay_min;
 | 
			
		||||
	uint32_t bts_jitter_delay_max;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define for_each_line(line, save)			\
 | 
			
		||||
@@ -335,3 +344,8 @@ static inline const char *mgcp_bts_src_addr(struct mgcp_endpoint *endp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mgcp_msg_terminate_nul(struct msgb *msg);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Internal jitter buffer related
 | 
			
		||||
 */
 | 
			
		||||
void mgcp_dejitter_udp_send(struct msgb *msg, void *data);
 | 
			
		||||
 
 | 
			
		||||
@@ -584,6 +584,36 @@ static int mgcp_send_transcoder(struct mgcp_rtp_end *end,
 | 
			
		||||
	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(DLMGCP, 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)
 | 
			
		||||
{
 | 
			
		||||
@@ -591,6 +621,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp,
 | 
			
		||||
	struct mgcp_rtp_end *rtp_end;
 | 
			
		||||
	struct mgcp_rtp_state *rtp_state;
 | 
			
		||||
	int tap_idx;
 | 
			
		||||
	struct osmo_jibuf *jb;
 | 
			
		||||
 | 
			
		||||
	LOGP(DLMGCP, LOGL_DEBUG,
 | 
			
		||||
	     "endpoint %x dest %s tcfg->audio_loop %d endp->conn_mode %d (== loopback: %d)\n",
 | 
			
		||||
@@ -612,10 +643,12 @@ int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp,
 | 
			
		||||
		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;
 | 
			
		||||
	}
 | 
			
		||||
	LOGP(DLMGCP, LOGL_DEBUG,
 | 
			
		||||
	     "endpoint %x dest %s net_end %s %d %d bts_end %s %d %d rtp_end %s %d %d\n",
 | 
			
		||||
@@ -680,6 +713,9 @@ int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp,
 | 
			
		||||
				rtp_state->patched_first_rtp_payload = true;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			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);
 | 
			
		||||
 
 | 
			
		||||
@@ -863,6 +863,11 @@ mgcp_header_done:
 | 
			
		||||
		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 */
 | 
			
		||||
@@ -898,6 +903,13 @@ mgcp_header_done:
 | 
			
		||||
		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:
 | 
			
		||||
@@ -906,6 +918,14 @@ mgcp_header_done:
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* 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(DLMGCP, LOGL_DEBUG, "Creating endpoint on: 0x%x CI: %u port: %u/%u\n",
 | 
			
		||||
		ENDPOINT_NUMBER(endp), endp->ci,
 | 
			
		||||
		endp->net_end.local_port, endp->bts_end.local_port);
 | 
			
		||||
@@ -1373,6 +1393,9 @@ int mgcp_endpoints_allocate(struct mgcp_trunk_config *tcfg)
 | 
			
		||||
void mgcp_release_endp(struct mgcp_endpoint *endp)
 | 
			
		||||
{
 | 
			
		||||
	LOGP(DLMGCP, 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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,7 @@
 | 
			
		||||
#include <osmocom/legacy_mgcp/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 @@ static int config_write_mgcp(struct vty *vty)
 | 
			
		||||
		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 @@ DEFUN(show_mcgp, show_mgcp_cmd,
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
}
 | 
			
		||||
@@ -1344,6 +1357,63 @@ DEFUN(cfg_mgcp_osmux_dummy,
 | 
			
		||||
	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 in ms\n" "Minimum Delay in ms\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 in ms\n" "Maximum Delay in ms\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);
 | 
			
		||||
@@ -1411,6 +1481,10 @@ int mgcp_vty_init(void)
 | 
			
		||||
	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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user