aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gsm_04_08.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2009-07-28 18:25:29 +0200
committerHarald Welte <laforge@gnumonks.org>2009-07-28 18:25:29 +0200
commit805f64486b490d8c7042235e69565755074b768e (patch)
treed9e4fd82232b2dd80a19ecba40a1509a8fac2501 /openbsc/src/gsm_04_08.c
parentaea9a98dc2dfbbad0daf434c97bc6d2a4d3384f2 (diff)
add RTP proxy mode for ip.access
Up until now, we only supported direct RTP streams between ip.access BTS. With this commit, the user can specify '-P' to the command line to enable a RTP/RTCP proxy inside OpenBSC. The nanoBTS will then send all their voice data to OpenBSC, which will relay it to the respective destination BTS (which can be the same BTS). The default behaviour remains unchanged. Without '-P' on the command line, RTP/RTCP is exchanged directly.
Diffstat (limited to 'openbsc/src/gsm_04_08.c')
-rw-r--r--openbsc/src/gsm_04_08.c132
1 files changed, 110 insertions, 22 deletions
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index a9f2ebd8e..2d3a634e1 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -44,6 +44,7 @@
#include <openbsc/signal.h>
#include <openbsc/trau_frame.h>
#include <openbsc/trau_mux.h>
+#include <openbsc/rtp_proxy.h>
#include <openbsc/talloc.h>
#include <openbsc/transaction.h>
@@ -56,6 +57,10 @@
static void *tall_locop_ctx;
+/* should ip.access BTS use direct RTP streams between each other (1),
+ * or should OpenBSC always act as RTP relay/proxy in between (0) ? */
+int ipacc_rtp_direct = 1;
+
static const struct tlv_definition rsl_att_tlvdef = {
.def = {
[GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV },
@@ -399,17 +404,6 @@ static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
return 0;
}
-/*
- * This will be ran by the linker when loading the DSO. We use it to
- * do system initialization, e.g. registration of signal handlers.
- */
-static __attribute__((constructor)) void on_dso_load_0408(void)
-{
- tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
- "loc_updating_oper");
- register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
-}
-
static void to_bcd(u_int8_t *bcd, u_int16_t val)
{
bcd[2] = val % 10;
@@ -1973,12 +1967,80 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
return 0;
}
+/* some other part of the code sends us a signal */
+static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data)
+{
+ struct gsm_lchan *lchan = signal_data;
+ struct gsm_bts_trx_ts *ts;
+ int rc;
+
+ if (subsys != SS_ABISIP)
+ return 0;
+
+ /* in case we use direct BTS-to-BTS RTP */
+ if (ipacc_rtp_direct)
+ return 0;
+
+ ts = lchan->ts;
+
+ switch (signal) {
+ case S_ABISIP_BIND_ACK:
+ /* the BTS has successfully bound a TCH to a local ip/port,
+ * which means we can connect our UDP socket to it */
+ if (ts->abis_ip.rtp_socket) {
+ rtp_socket_free(ts->abis_ip.rtp_socket);
+ ts->abis_ip.rtp_socket = NULL;
+ }
+
+ ts->abis_ip.rtp_socket = rtp_socket_create();
+ if (!ts->abis_ip.rtp_socket)
+ goto out_err;
+
+ rc = rtp_socket_connect(ts->abis_ip.rtp_socket,
+ ts->abis_ip.bound_ip,
+ ts->abis_ip.bound_port);
+ if (rc < 0)
+ goto out_err;
+ break;
+ case S_ABISIP_DISC_IND:
+ /* the BTS tells us a RTP stream has been disconnected */
+ if (ts->abis_ip.rtp_socket) {
+ rtp_socket_free(ts->abis_ip.rtp_socket);
+ ts->abis_ip.rtp_socket = NULL;
+ }
+ break;
+ }
+
+ return 0;
+out_err:
+ /* FIXME: do something */
+ return 0;
+}
+
+/* bind rtp proxy to local IP/port and tell BTS to connect to it */
+static int ipacc_connect_proxy_bind(struct gsm_lchan *lchan)
+{
+ struct gsm_bts_trx_ts *ts = lchan->ts;
+ struct rtp_socket *rs = ts->abis_ip.rtp_socket;
+ int rc;
+
+ rc = rsl_ipacc_connect(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
+ ntohs(rs->rtp.sin_local.sin_port),
+ ts->abis_ip.conn_id,
+ /* FIXME: use RTP payload of bound socket, not BTS*/
+ ts->abis_ip.rtp_payload2);
+
+ return rc;
+}
+
/* map two ipaccess RTP streams onto each other */
static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
{
struct gsm_bts *bts = lchan->ts->trx->bts;
struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
struct gsm_bts_trx_ts *ts;
+ int rc;
DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
@@ -1992,23 +2054,38 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
switch (bts->type) {
case GSM_BTS_TYPE_NANOBTS_900:
case GSM_BTS_TYPE_NANOBTS_1800:
- ts = remote_lchan->ts;
- rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
- ts->abis_ip.bound_port,
- lchan->ts->abis_ip.conn_id,
- ts->abis_ip.rtp_payload2);
-
- ts = lchan->ts;
- rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
- ts->abis_ip.bound_port,
- remote_lchan->ts->abis_ip.conn_id,
- ts->abis_ip.rtp_payload2);
+ if (!ipacc_rtp_direct) {
+ /* connect the TCH's to our RTP proxy */
+ rc = ipacc_connect_proxy_bind(lchan);
+ if (rc < 0)
+ return rc;
+ rc = ipacc_connect_proxy_bind(remote_lchan);
+
+ /* connect them with each other */
+ rtp_socket_proxy(lchan->ts->abis_ip.rtp_socket,
+ remote_lchan->ts->abis_ip.rtp_socket);
+ } else {
+ /* directly connect TCH RTP streams to each other */
+ ts = remote_lchan->ts;
+ rc = rsl_ipacc_connect(lchan, ts->abis_ip.bound_ip,
+ ts->abis_ip.bound_port,
+ lchan->ts->abis_ip.conn_id,
+ ts->abis_ip.rtp_payload2);
+ if (rc < 0)
+ return rc;
+ ts = lchan->ts;
+ rc = rsl_ipacc_connect(remote_lchan, ts->abis_ip.bound_ip,
+ ts->abis_ip.bound_port,
+ remote_lchan->ts->abis_ip.conn_id,
+ ts->abis_ip.rtp_payload2);
+ }
break;
case GSM_BTS_TYPE_BS11:
trau_mux_map_lchan(lchan, remote_lchan);
break;
default:
DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
+ rc = -EINVAL;
break;
}
@@ -3732,3 +3809,14 @@ int bsc_upqueue(struct gsm_network *net)
return work;
}
+/*
+ * This will be ran by the linker when loading the DSO. We use it to
+ * do system initialization, e.g. registration of signal handlers.
+ */
+static __attribute__((constructor)) void on_dso_load_0408(void)
+{
+ tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
+ "loc_updating_oper");
+ register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
+ register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
+}