aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2012-01-16 09:29:28 +0100
committerAndreas Eversberg <jolly@eversberg.eu>2013-07-29 12:34:03 +0200
commitd1dea065295f825e91cd7f04dc60bc35f4cdbd75 (patch)
tree19ac3873f7bac430348c389ed54a50173eeba247
parent0af6a32d98640742c14cb7ea3506c3070e25b9f0 (diff)
Adding traffic forwarding via RTP to remote application
Instead of forwarding traffic through MNCC interface, traffic can now be forwarded to a given RTP destination. A special MNCC message is used for that. The traffic can still be forwarded through MNCC interface when this special MNCC message is not used. It also works with E1 based BTSs. In conjunction with LCR's "rtp-bridge" feature, the RTP traffic can be directly exchanged with a remote SIP endpoint, so that the traffic is not forwarded by LCR itself. This way the performance of handling traffic only depends on OpenBSC and the remote SIP endpoint. Also the traffic is exchanged with the SIP endpoint without transcoding, to have maximum performance.
-rw-r--r--openbsc/include/openbsc/gsm_04_08.h3
-rw-r--r--openbsc/include/openbsc/mncc.h11
-rw-r--r--openbsc/include/openbsc/rtp_proxy.h5
-rw-r--r--openbsc/include/openbsc/transaction.h2
-rw-r--r--openbsc/src/ipaccess/ipaccess-config.c6
-rw-r--r--openbsc/src/libmsc/gsm_04_08.c175
-rw-r--r--openbsc/src/libmsc/mncc_builtin.c2
-rw-r--r--openbsc/src/libmsc/mncc_sock.c21
-rw-r--r--openbsc/src/libmsc/transaction.c1
-rw-r--r--openbsc/src/libtrau/rtp_proxy.c42
-rw-r--r--openbsc/src/libtrau/trau_mux.c14
-rw-r--r--openbsc/src/utils/bs11_config.c6
-rw-r--r--openbsc/tests/abis/abis_test.c6
13 files changed, 251 insertions, 43 deletions
diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h
index 2f5aaa98c..068672059 100644
--- a/openbsc/include/openbsc/gsm_04_08.h
+++ b/openbsc/include/openbsc/gsm_04_08.h
@@ -6,6 +6,7 @@
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <openbsc/meas_rep.h>
+#include <openbsc/mncc.h>
struct msgb;
struct gsm_bts;
@@ -72,4 +73,6 @@ void gsm48_lchan2chan_desc(struct gsm48_chan_desc *cd,
void release_security_operation(struct gsm_subscriber_connection *conn);
void allocate_security_operation(struct gsm_subscriber_connection *conn);
+int tch_frame_down(struct gsm_network *net, uint32_t callref, struct gsm_data_frame *data);
+
#endif
diff --git a/openbsc/include/openbsc/mncc.h b/openbsc/include/openbsc/mncc.h
index 4a99bb11b..12a6ec833 100644
--- a/openbsc/include/openbsc/mncc.h
+++ b/openbsc/include/openbsc/mncc.h
@@ -92,9 +92,13 @@ struct gsm_call {
#define MNCC_FRAME_RECV 0x0201
#define MNCC_FRAME_DROP 0x0202
#define MNCC_LCHAN_MODIFY 0x0203
+#define MNCC_RTP_CREATE 0x0204
+#define MNCC_RTP_CONNECT 0x0205
+#define MNCC_RTP_FREE 0x0206
#define GSM_TCHF_FRAME 0x0300
#define GSM_TCHF_FRAME_EFR 0x0301
+#define GSM_TCHF_FRAME_HR 0x0302
#define MNCC_SOCKET_HELLO 0x0400
@@ -176,6 +180,13 @@ struct gsm_mncc_hello {
uint32_t lchan_type_offset;
};
+struct gsm_mncc_rtp {
+ uint32_t msg_type;
+ uint32_t callref;
+ uint32_t ip;
+ uint16_t port;
+};
+
char *get_mncc_name(int value);
void mncc_set_cause(struct gsm_mncc *data, int loc, int val);
void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg);
diff --git a/openbsc/include/openbsc/rtp_proxy.h b/openbsc/include/openbsc/rtp_proxy.h
index 26cac0df4..a7d692c56 100644
--- a/openbsc/include/openbsc/rtp_proxy.h
+++ b/openbsc/include/openbsc/rtp_proxy.h
@@ -36,8 +36,9 @@
enum rtp_rx_action {
RTP_NONE,
- RTP_PROXY,
- RTP_RECV_UPSTREAM,
+ RTP_PROXY, /* forward from BTS to BTS */
+ RTP_RECV_UPSTREAM, /* forward to L4 application */
+ RTP_RECV_L4, /* receive RTP frames from L4 application */
};
enum rtp_tx_action {
diff --git a/openbsc/include/openbsc/transaction.h b/openbsc/include/openbsc/transaction.h
index b6c859c71..6f4258d10 100644
--- a/openbsc/include/openbsc/transaction.h
+++ b/openbsc/include/openbsc/transaction.h
@@ -28,6 +28,7 @@ struct gsm_trans {
/* reference from MNCC or other application */
uint32_t callref;
+ uint32_t callref_keep; /* to remember callref, even if it is removed */
/* if traffic channel receive was requested */
int tch_recv;
@@ -46,6 +47,7 @@ struct gsm_trans {
int T308_second; /* used to send release again */
struct osmo_timer_list timer;
struct gsm_mncc msg; /* stores setup/disconnect/release message */
+ struct rtp_socket *rs; /* L4 traffic via RTP */
} cc;
struct {
struct gsm411_smc_inst smc_inst;
diff --git a/openbsc/src/ipaccess/ipaccess-config.c b/openbsc/src/ipaccess/ipaccess-config.c
index e66771a1a..c778469d4 100644
--- a/openbsc/src/ipaccess/ipaccess-config.c
+++ b/openbsc/src/ipaccess/ipaccess-config.c
@@ -87,6 +87,12 @@ static uint8_t prim_oml_attr[] = { 0x95, 0x00, 7, 0x88, 192, 168, 100, 11, 0x00,
static uint8_t unit_id_attr[] = { 0x91, 0x00, 9, '2', '3', '4', '2', '/' , '0', '/', '0', 0x00 };
*/
+/* dummy function to keep rtp_proxy.c happy */
+int tch_frame_down(struct gsm_network *net, uint32_t callref, struct gsm_data_frame *data)
+{
+ return 0;
+}
+
extern int ipaccess_fd_cb(struct osmo_fd *bfd, unsigned int what);
extern struct e1inp_line_ops ipaccess_e1inp_line_ops;
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index eea073614..649a77090 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -1323,8 +1323,15 @@ void _gsm48_cc_trans_free(struct gsm_trans *trans)
}
if (trans->cc.state != GSM_CSTATE_NULL)
new_cc_state(trans, GSM_CSTATE_NULL);
+ /* Be sure to unmap upstream traffic for our callref only. */
if (trans->conn)
- trau_mux_unmap(&trans->conn->lchan->ts->e1_link, trans->callref);
+ trau_mux_unmap(&trans->conn->lchan->ts->e1_link, trans->callref_keep);
+
+ /* free L4 RTP socket */
+ if (trans->cc.rs) {
+ rtp_socket_free(trans->cc.rs);
+ trans->cc.rs = NULL;
+ }
}
static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
@@ -1442,6 +1449,7 @@ static int switch_for_handover(struct gsm_lchan *old_lchan,
new_rs->receive = old_rs->receive;
break;
case RTP_NONE:
+ case RTP_RECV_L4:
break;
}
@@ -1648,6 +1656,129 @@ static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable)
return 0;
}
+/* handle RTP requests of L4 */
+static int mncc_rtp(struct gsm_network *net, uint32_t callref, struct gsm_mncc_rtp *mncc)
+{
+ struct rtp_socket *rs;
+ struct gsm_trans *trans;
+ int rc;
+
+ /* Find callref */
+ trans = trans_find_by_callref(net, callref);
+ if (!trans) {
+ LOGP(DCC, LOGL_ERROR, "Unknown transaction for callref=%d\n", callref);
+ return -EINVAL;
+ }
+
+ rs = trans->cc.rs;
+
+ switch (mncc->msg_type) {
+ case MNCC_RTP_CREATE:
+ /* use RTP instead of MNCC socket, for traffic
+ * open L4 RTP socket */
+ if (rs) {
+ LOGP(DCC, LOGL_ERROR, "RTP already created.\n");
+ return -EIO;
+ }
+ rs = trans->cc.rs = rtp_socket_create();
+ if (!rs) {
+ LOGP(DCC, LOGL_ERROR, "RTP socket creation failed.\n");
+ /* reply with IP/port = 0 */
+ mncc->ip = 0;
+ mncc->port = 0;
+ mncc_recvmsg(net, trans, MNCC_RTP_CREATE, (struct gsm_mncc *)mncc);
+ return -EIO;
+ }
+ rs->rx_action = RTP_RECV_L4;
+ rs->receive.net = net;
+ rs->receive.callref = callref;
+ /* reply with bound IP/port */
+ mncc->ip = ntohl(rs->rtp.sin_local.sin_addr.s_addr);
+ mncc->port = ntohs(rs->rtp.sin_local.sin_port);
+ mncc_recvmsg(net, trans, MNCC_RTP_CREATE, (struct gsm_mncc *)mncc);
+ break;
+ case MNCC_RTP_CONNECT:
+ if (!rs) {
+ LOGP(DCC, LOGL_ERROR, "RTP not created.\n");
+ return -EIO;
+ }
+ rc = rtp_socket_connect(trans->cc.rs, mncc->ip, mncc->port);
+ if (rc < 0) {
+ LOGP(DCC, LOGL_ERROR, "RTP socket connect failed.\n");
+ /* reply with IP/port = 0 */
+ mncc->ip = 0;
+ mncc->port = 0;
+ mncc_recvmsg(net, trans, MNCC_RTP_CONNECT, (struct gsm_mncc *)mncc);
+ return -EIO;
+ }
+ /* reply with local IP/port */
+ mncc->ip = ntohl(rs->rtp.sin_local.sin_addr.s_addr);
+ mncc->port = ntohs(rs->rtp.sin_local.sin_port);
+ mncc_recvmsg(net, trans, MNCC_RTP_CONNECT, (struct gsm_mncc *)mncc);
+ break;
+ case MNCC_RTP_FREE:
+ if (!rs) {
+ LOGP(DCC, LOGL_ERROR, "RTP not created.\n");
+ return -EIO;
+ }
+ rtp_socket_free(trans->cc.rs);
+ trans->cc.rs = NULL;
+ /* reply */
+ mncc_recvmsg(net, trans, MNCC_RTP_FREE, (struct gsm_mncc *)mncc);
+ break;
+ }
+
+ return 0;
+}
+
+/* handle tch frame from L4 */
+int tch_frame_down(struct gsm_network *net, uint32_t callref, struct gsm_data_frame *data)
+{
+ struct gsm_trans *trans;
+ struct gsm_bts *bts;
+
+ /* Find callref */
+ trans = trans_find_by_callref(net, data->callref);
+ if (!trans) {
+ LOGP(DMNCC, LOGL_ERROR, "TCH frame for non-existing trans\n");
+ return -EIO;
+ }
+ if (!trans->conn) {
+ LOGP(DMNCC, LOGL_NOTICE, "TCH frame for trans without conn\n");
+ return 0;
+ }
+ if (trans->conn->lchan->type != GSM_LCHAN_TCH_F) {
+ /* This should be LOGL_ERROR or NOTICE, but
+ * unfortuantely it happens for a couple of frames at
+ * the beginning of every RTP connection */
+ LOGP(DMNCC, LOGL_DEBUG, "TCH frame for lchan != TCH_F\n");
+ return 0;
+ }
+ bts = trans->conn->lchan->ts->trx->bts;
+ switch (bts->type) {
+ case GSM_BTS_TYPE_NANOBTS:
+ case GSM_BTS_TYPE_OSMO_SYSMO:
+ if (!trans->conn->lchan->abis_ip.rtp_socket) {
+ DEBUGP(DMNCC, "TCH frame to lchan without RTP connection\n");
+ return 0;
+ }
+ if (trans->conn->lchan->abis_ip.rtp_socket->receive.callref != callref) {
+ /* Drop frame, if not our callref. This happens, if
+ * the call is on hold or retrieved by another
+ * transaction. */
+ return 0;
+ }
+ return rtp_send_frame(trans->conn->lchan->abis_ip.rtp_socket, data);
+ case GSM_BTS_TYPE_BS11:
+ case GSM_BTS_TYPE_RBS2000:
+ case GSM_BTS_TYPE_NOKIA_SITE:
+ return trau_send_frame(trans->conn->lchan, data);
+ default:
+ LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type);
+ }
+ return -EINVAL;
+}
+
static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
{
DEBUGP(DCC, "-> STATUS ENQ\n");
@@ -2880,7 +3011,6 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg)
int i, rc = 0;
struct gsm_trans *trans = NULL, *transt;
struct gsm_subscriber_connection *conn = NULL;
- struct gsm_bts *bts = NULL;
struct gsm_mncc *data = arg, rel;
DEBUGP(DMNCC, "receive message %s\n", get_mncc_name(msg_type));
@@ -2893,41 +3023,14 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg)
return tch_recv_mncc(net, data->callref, 0);
case MNCC_FRAME_RECV:
return tch_recv_mncc(net, data->callref, 1);
+ case MNCC_RTP_CREATE:
+ case MNCC_RTP_CONNECT:
+ case MNCC_RTP_FREE:
+ return mncc_rtp(net, data->callref, (struct gsm_mncc_rtp *) arg);
case GSM_TCHF_FRAME:
- /* Find callref */
- trans = trans_find_by_callref(net, data->callref);
- if (!trans) {
- LOGP(DMNCC, LOGL_ERROR, "TCH frame for non-existing trans\n");
- return -EIO;
- }
- if (!trans->conn) {
- LOGP(DMNCC, LOGL_NOTICE, "TCH frame for trans without conn\n");
- return 0;
- }
- if (trans->conn->lchan->type != GSM_LCHAN_TCH_F) {
- /* This should be LOGL_ERROR or NOTICE, but
- * unfortuantely it happens for a couple of frames at
- * the beginning of every RTP connection */
- LOGP(DMNCC, LOGL_DEBUG, "TCH frame for lchan != TCH_F\n");
- return 0;
- }
- bts = trans->conn->lchan->ts->trx->bts;
- switch (bts->type) {
- case GSM_BTS_TYPE_NANOBTS:
- case GSM_BTS_TYPE_OSMO_SYSMO:
- if (!trans->conn->lchan->abis_ip.rtp_socket) {
- DEBUGP(DMNCC, "TCH frame to lchan without RTP connection\n");
- return 0;
- }
- return rtp_send_frame(trans->conn->lchan->abis_ip.rtp_socket, arg);
- case GSM_BTS_TYPE_BS11:
- case GSM_BTS_TYPE_RBS2000:
- case GSM_BTS_TYPE_NOKIA_SITE:
- return trau_send_frame(trans->conn->lchan, arg);
- default:
- LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type);
- }
- return -EINVAL;
+ case GSM_TCHF_FRAME_EFR:
+ case GSM_TCHF_FRAME_HR:
+ return tch_frame_down(net, data->callref, (struct gsm_data_frame *) arg);
}
memset(&rel, 0, sizeof(struct gsm_mncc));
diff --git a/openbsc/src/libmsc/mncc_builtin.c b/openbsc/src/libmsc/mncc_builtin.c
index 617cbf25f..5f909f739 100644
--- a/openbsc/src/libmsc/mncc_builtin.c
+++ b/openbsc/src/libmsc/mncc_builtin.c
@@ -342,6 +342,7 @@ int int_mncc_recv(struct gsm_network *net, struct msgb *msg)
switch (msg_type) {
case GSM_TCHF_FRAME:
case GSM_TCHF_FRAME_EFR:
+ case GSM_TCHF_FRAME_HR:
break;
default:
DEBUGP(DMNCC, "(call %x) Received message %s\n", call->callref,
@@ -410,6 +411,7 @@ int int_mncc_recv(struct gsm_network *net, struct msgb *msg)
break;
case GSM_TCHF_FRAME:
case GSM_TCHF_FRAME_EFR:
+ case GSM_TCHF_FRAME_HR:
rc = mncc_rcv_tchf(call, msg_type, arg);
break;
default:
diff --git a/openbsc/src/libmsc/mncc_sock.c b/openbsc/src/libmsc/mncc_sock.c
index cf4bca87a..ad0f27f63 100644
--- a/openbsc/src/libmsc/mncc_sock.c
+++ b/openbsc/src/libmsc/mncc_sock.c
@@ -37,6 +37,8 @@
#include <openbsc/debug.h>
#include <openbsc/mncc.h>
#include <openbsc/gsm_data.h>
+#include <openbsc/transaction.h>
+#include <openbsc/rtp_proxy.h>
struct mncc_sock_state {
struct gsm_network *net;
@@ -50,12 +52,27 @@ int mncc_sock_from_cc(struct gsm_network *net, struct msgb *msg)
struct gsm_mncc *mncc_in = (struct gsm_mncc *) msgb_data(msg);
int msg_type = mncc_in->msg_type;
+ /* L4 uses RTP for this transaction, we send our data via RTP,
+ * otherwise we send it through MNCC interface */
+ if (msg_type == GSM_TCHF_FRAME
+ || msg_type == GSM_TCHF_FRAME_EFR
+ || msg_type == GSM_TCHF_FRAME_HR) {
+ struct gsm_trans *trans = trans_find_by_callref(net, mncc_in->callref);
+
+ if (trans && trans->cc.rs) {
+ rtp_send_frame(trans->cc.rs, (struct gsm_data_frame *) mncc_in);
+ msgb_free(msg);
+ return 0;
+ }
+ }
+
/* Check if we currently have a MNCC handler connected */
if (net->mncc_state->conn_bfd.fd < 0) {
LOGP(DMNCC, LOGL_ERROR, "mncc_sock receives %s for external CC app "
"but socket is gone\n", get_mncc_name(msg_type));
- if (msg_type != GSM_TCHF_FRAME &&
- msg_type != GSM_TCHF_FRAME_EFR) {
+ if (msg_type != GSM_TCHF_FRAME
+ && msg_type != GSM_TCHF_FRAME_EFR
+ && msg_type != GSM_TCHF_FRAME_HR) {
/* release the request */
struct gsm_mncc mncc_out;
memset(&mncc_out, 0, sizeof(mncc_out));
diff --git a/openbsc/src/libmsc/transaction.c b/openbsc/src/libmsc/transaction.c
index c1441969d..5967d9935 100644
--- a/openbsc/src/libmsc/transaction.c
+++ b/openbsc/src/libmsc/transaction.c
@@ -78,6 +78,7 @@ struct gsm_trans *trans_alloc(struct gsm_subscriber *subscr,
trans->protocol = protocol;
trans->transaction_id = trans_id;
trans->callref = callref;
+ trans->callref_keep = callref;
llist_add_tail(&trans->entry, &subscr->net->trans_list);
diff --git a/openbsc/src/libtrau/rtp_proxy.c b/openbsc/src/libtrau/rtp_proxy.c
index 0074b4a04..8ad248843 100644
--- a/openbsc/src/libtrau/rtp_proxy.c
+++ b/openbsc/src/libtrau/rtp_proxy.c
@@ -169,13 +169,28 @@ static int rtp_decode(struct msgb *msg, uint32_t callref, struct msgb **data)
msg_type = GSM_TCHF_FRAME;
if (payload_len != 33) {
DEBUGPC(DLMUX, "received RTP full rate frame with "
- "payload length != 32 (len = %d)\n",
+ "payload length != 33 (len = %d)\n",
payload_len);
return -EINVAL;
}
break;
case RTP_PT_GSM_EFR:
msg_type = GSM_TCHF_FRAME_EFR;
+ if (payload_len != 31) {
+ DEBUGPC(DLMUX, "received RTP extended full rate frame "
+ "with payload length != 31 (len = %d)\n",
+ payload_len);
+ return -EINVAL;
+ }
+ break;
+ case RTP_PT_GSM_HALF:
+ msg_type = GSM_TCHF_FRAME_HR;
+ if (payload_len != 14) {
+ DEBUGPC(DLMUX, "received RTP half rate frame with "
+ "payload length != 14 (len = %d)\n",
+ payload_len);
+ return -EINVAL;
+ }
break;
default:
DEBUGPC(DLMUX, "received RTP frame with unknown payload "
@@ -244,6 +259,11 @@ int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
payload_len = 31;
duration = 160;
break;
+ case GSM_TCHF_FRAME_HR:
+ payload_type = RTP_PT_GSM_HALF;
+ payload_len = 14;
+ duration = 160;
+ break;
default:
DEBUGPC(DLMUX, "unsupported message type %d\n",
frame->msg_type);
@@ -426,7 +446,7 @@ static int rtp_socket_read(struct rtp_socket *rs, struct rtp_sub_socket *rss)
other_rss->bfd.when |= BSC_FD_WRITE;
break;
- case RTP_RECV_UPSTREAM:
+ case RTP_RECV_UPSTREAM: /* from BTS to application */
if (!rs->receive.callref || !rs->receive.net) {
rc = -EIO;
goto out_free;
@@ -455,6 +475,24 @@ static int rtp_socket_read(struct rtp_socket *rs, struct rtp_sub_socket *rss)
trau_tx_to_mncc(rs->receive.net, new_msg);
break;
+ case RTP_RECV_L4: /* from L4 */
+ if (!rs->receive.callref || !rs->receive.net) {
+ rc = -EIO;
+ goto out_free;
+ }
+ if (rss->bfd.priv_nr != RTP_PRIV_RTP) {
+ rc = ENOTSUP;
+ goto out_free;
+ }
+ rc = rtp_decode(msg, rs->receive.callref, &new_msg);
+ if (rc < 0)
+ goto out_free;
+ msgb_free(msg);
+ tch_frame_down(rs->receive.net, rs->receive.callref,
+ (struct gsm_data_frame *) new_msg->data);
+ msgb_free(new_msg);
+ break;
+
case RTP_NONE: /* if socket exists, but disabled by app */
msgb_free(msg);
break;
diff --git a/openbsc/src/libtrau/trau_mux.c b/openbsc/src/libtrau/trau_mux.c
index 9272ac04f..ac410c3fc 100644
--- a/openbsc/src/libtrau/trau_mux.c
+++ b/openbsc/src/libtrau/trau_mux.c
@@ -122,7 +122,9 @@ int trau_mux_unmap(const struct gsm_e1_subslot *ss, uint32_t callref)
llist_del(&ue->list);
return 0;
}
- if (ss && !memcmp(&ue->src, ss, sizeof(*ss))) {
+ /* Only release, if no callref is given. We must ensure that
+ * only the transaction's upstream is removed, if exists. */
+ if (ss && !callref && !memcmp(&ue->src, ss, sizeof(*ss))) {
llist_del(&ue->list);
return 0;
}
@@ -280,6 +282,7 @@ int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame)
uint8_t trau_bits_out[TRAU_FRAME_BITS];
struct gsm_e1_subslot *dst_e1_ss = &lchan->ts->e1_link;
struct subch_mux *mx;
+ struct upqueue_entry *ue;
int i, j, k, l, o;
unsigned char *data = frame->data;
struct decoded_trau_frame tf;
@@ -287,6 +290,15 @@ int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame)
mx = e1inp_get_mux(dst_e1_ss->e1_nr, dst_e1_ss->e1_ts);
if (!mx)
return -EINVAL;
+ if (!(ue = lookup_trau_upqueue(dst_e1_ss))) {
+ /* Call might be on hold, so we drop frames. */
+ return 0;
+ }
+ if (ue->callref != frame->callref) {
+ /* Slot has different transaction, due to
+ * another call. (Ours is on hold.) */
+ return 0;
+ }
switch (frame->msg_type) {
case GSM_TCHF_FRAME:
diff --git a/openbsc/src/utils/bs11_config.c b/openbsc/src/utils/bs11_config.c
index e8acb461a..f459744aa 100644
--- a/openbsc/src/utils/bs11_config.c
+++ b/openbsc/src/utils/bs11_config.c
@@ -83,6 +83,12 @@ struct osmo_counter *osmo_counter_alloc(const char *name)
return NULL;
}
+/* dummy function to keep rtp_proxy.c happy */
+int tch_frame_down(struct gsm_network *net, uint32_t callref, struct gsm_data_frame *data)
+{
+ return 0;
+}
+
int handle_serial_msg(struct msgb *rx_msg);
/* create all objects for an initial configuration */
diff --git a/openbsc/tests/abis/abis_test.c b/openbsc/tests/abis/abis_test.c
index e7e78d202..6bb84cca0 100644
--- a/openbsc/tests/abis/abis_test.c
+++ b/openbsc/tests/abis/abis_test.c
@@ -27,6 +27,12 @@
#include <openbsc/abis_nm.h>
#include <openbsc/debug.h>
+/* dummy function to keep rtp_proxy.c happy */
+int tch_frame_down(struct gsm_network *net, uint32_t callref, struct gsm_data_frame *data)
+{
+ return 0;
+}
+
static const uint8_t simple_config[] = {
/*0, 13, */
66, 18, 0, 3, 1, 2, 3, 19, 0, 3, 3, 4, 5,