aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2017-04-27 15:59:19 +0200
committerHarald Welte <laforge@gnumonks.org>2018-04-16 16:18:40 +0000
commit093cc765665cae83ce17b0eb452ff3f7b8bfdb14 (patch)
tree07b097ad20df712c37fa0ea64c06e628f84bc296
parentdc09470c40ae595806f6b52d60e815cfb2fb9434 (diff)
nat: 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
-rw-r--r--openbsc/include/openbsc/bsc_nat.h10
-rw-r--r--openbsc/include/openbsc/mgcp.h6
-rw-r--r--openbsc/include/openbsc/mgcp_internal.h14
-rw-r--r--openbsc/src/libmgcp/mgcp_network.c42
-rw-r--r--openbsc/src/libmgcp/mgcp_protocol.c24
-rw-r--r--openbsc/src/libmgcp/mgcp_vty.c74
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c10
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat_vty.c76
8 files changed, 253 insertions, 3 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index fad380438..5171c3e0c 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -175,6 +175,16 @@ struct bsc_config {
/* 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, in ms */
+ 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 b2262bc8d..4d1c5ef47 100644
--- a/openbsc/include/openbsc/mgcp.h
+++ b/openbsc/include/openbsc/mgcp.h
@@ -236,6 +236,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 */
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h
index 7c89d1021..cd6365f98 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 @@ 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) \
@@ -340,3 +349,8 @@ static inline const char *mgcp_bts_src_addr(struct mgcp_endpoint *endp)
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 abce6e49d..799d99838 100644
--- a/openbsc/src/libmgcp/mgcp_network.c
+++ b/openbsc/src/libmgcp/mgcp_network.c
@@ -580,6 +580,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(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 @@ 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;
/* For loop toggle the destination and then dispatch. */
if (tcfg->audio_loop)
@@ -600,10 +631,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;
}
if (!rtp_end->output_enabled)
@@ -621,9 +654,12 @@ int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp,
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 ae5c90bcc..84dbc1f52 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -827,6 +827,12 @@ 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 */
@@ -862,6 +868,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:
@@ -870,6 +883,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(DMGCP, 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);
@@ -1333,6 +1354,9 @@ int mgcp_endpoints_allocate(struct mgcp_trunk_config *tcfg)
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 b97d7f835..6d1a7acc7 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 @@ 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;
}
@@ -1333,6 +1346,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);
@@ -1399,6 +1469,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);
diff --git a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c
index 48847865c..8cf4e9427 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 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int
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 d4cef5dbe..e51de537a 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 @@ static void config_write_bsc_single(struct vty *vty, struct bsc_config *bsc)
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 @@ DEFUN(cfg_bsc_osmux,
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 in ms\n" "Minimum Delay in ms\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 in ms\n" "Maximum Delay in ms\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 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
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();