From 6c4c08ecc8f6d3855d97ca0efbac71caf3f66f8b Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Wed, 7 Sep 2016 13:39:07 +0200 Subject: IuCS: implement msc_call_assignment() for IuCS Send IuCS RAB Activation upon MNCC_CALL_PROC_REQ. Implement function msc_call_assignment(): decide between sending A-iface BSSMAP Assignment Request or IuCS RAB Assignment Request. Implement iu_rab_act_cs() to send the IuCS RAB Assignment Request. The IP address and port of the MGCPGW sent in the RAB Assignment are still hardcoded. The A-interface extension is not implemented yet. Declare ranap_new_msg_rab_assign_voice() to avoid including ranap_msg_factory.h, which would require adding ASN1 CFLAGS to Makefile.am. The mgcpgw_client as well as some more osmo-iuh functions are now linked from libmsc, hence add some dummy stubs to libiudummy and db_test.c. Change-Id: Iaae51d1fbbfc28fad1c0b85e161d53d80a420a19 --- openbsc/include/openbsc/gsm_data.h | 3 ++ openbsc/src/libmsc/msc_ifaces.c | 82 +++++++++++++++++++++++++++++++++++++- openbsc/tests/db/db_test.c | 11 +++++ openbsc/tests/libiudummy/iudummy.c | 15 +++++++ 4 files changed, 110 insertions(+), 1 deletion(-) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index a0aa1f920..6dda176f0 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -170,6 +170,9 @@ struct gsm_subscriber_connection { struct { struct ue_conn_ctx *ue_ctx; int integrity_protection; + unsigned int mgcp_rtp_endpoint; + uint16_t mgcp_rtp_port_ue; + uint16_t mgcp_rtp_port_cn; } iu; }; diff --git a/openbsc/src/libmsc/msc_ifaces.c b/openbsc/src/libmsc/msc_ifaces.c index f837ad968..2937b54f6 100644 --- a/openbsc/src/libmsc/msc_ifaces.c +++ b/openbsc/src/libmsc/msc_ifaces.c @@ -26,9 +26,16 @@ #include #include #include +#include +#include #include "../../bscconfig.h" +extern struct msgb *ranap_new_msg_rab_assign_voice(uint8_t rab_id, + uint32_t rtp_ip, + uint16_t rtp_port, + bool use_x213_nsap); + static int msc_tx(struct gsm_subscriber_connection *conn, struct msgb *msg) { switch (conn->via_iface) { @@ -102,7 +109,80 @@ int msc_tx_common_id(struct gsm_subscriber_connection *conn) #endif } +#ifdef BUILD_IU +static int iu_rab_act_cs(struct ue_conn_ctx *uectx, uint8_t rab_id, + uint32_t rtp_ip, uint16_t rtp_port, + bool use_x213_nsap) +{ + struct msgb *msg; + + LOGP(DIUCS, LOGL_DEBUG, "Assigning RAB: rab_id=%d, rtp=%x:%u," + " use_x213_nsap=%d\n", rab_id, rtp_ip, rtp_port, use_x213_nsap); + + msg = ranap_new_msg_rab_assign_voice(rab_id, rtp_ip, rtp_port, + use_x213_nsap); + msg->l2h = msg->data; + + return iu_rab_act(uectx, msg); +} + +static int conn_iu_rab_act_cs(struct gsm_trans *trans) +{ + struct gsm_subscriber_connection *conn = trans->conn; + struct ue_conn_ctx *uectx = conn->iu.ue_ctx; + + /* HACK. where to scope the RAB Id? At the conn / subscriber / + * ue_conn_ctx? */ + static uint8_t next_rab_id = 1; + + conn->iu.mgcp_rtp_endpoint = + mgcpgw_client_next_endpoint(conn->network->mgcpgw.client); + /* HACK: the addresses should be known from CRCX response + * and config. */ + conn->iu.mgcp_rtp_port_ue = 4000 + 2 * conn->iu.mgcp_rtp_endpoint; + conn->iu.mgcp_rtp_port_cn = 16000 + 2 * conn->iu.mgcp_rtp_endpoint; + + /* Establish the RTP stream first as looping back to the originator. + * The MDCX will patch through to the counterpart. TODO: play a ring + * tone instead. */ + mgcpgw_client_tx_crcx(conn->network->mgcpgw.client, + conn->iu.mgcp_rtp_endpoint, trans->callref, + MGCP_CONN_LOOPBACK); + + uint32_t rtp_ip = + mgcpgw_client_remote_addr_n(conn->network->mgcpgw.client); + + return iu_rab_act_cs(uectx, next_rab_id++, rtp_ip, conn->iu.mgcp_rtp_port_ue, 1); + /* use_x213_nsap == 0 for ip.access nano3G */ + /* TODO: store the RAB Id? At the conn / subscriber / ue_conn_ctx? */ +} +#endif + int msc_call_assignment(struct gsm_trans *trans) { - return 0; + struct gsm_subscriber_connection *conn = trans->conn; + + switch (conn->via_iface) { + case IFACE_A: + LOGP(DMSC, LOGL_ERROR, + "msc_call_assignment(): A-interface BSSMAP Assignment" + " Request not yet implemented\n"); + return -ENOTSUP; + + case IFACE_IU: +#ifdef BUILD_IU + return conn_iu_rab_act_cs(trans); +#else + LOGP(DMSC, LOGL_ERROR, + "msc_call_assignment(): IuCS RAB Activation not supported" + " in this build\n"); + return -ENOTSUP; +#endif + + default: + LOGP(DMSC, LOGL_ERROR, + "msc_tx(): conn->via_iface invalid (%d)\n", + conn->via_iface); + return -EINVAL; + } } diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c index 755a6e9eb..372806e7b 100644 --- a/openbsc/tests/db/db_test.c +++ b/openbsc/tests/db/db_test.c @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -254,3 +255,13 @@ int main() /* stubs */ void vty_out() {} +unsigned int mgcpgw_client_next_endpoint(struct mgcpgw_client *client) +{ return 0; } +int mgcpgw_client_tx_crcx(struct mgcpgw_client *client, + uint16_t rtp_endpoint, unsigned int call_id, + enum mgcp_connection_mode mode) +{ return -ENOTSUP; } +const char *mgcpgw_client_remote_addr_str(struct mgcpgw_client *mgcp) +{ return "0.0.0.0"; } +uint32_t mgcpgw_client_remote_addr_n(struct mgcpgw_client *mgcp) +{ return 0; } diff --git a/openbsc/tests/libiudummy/iudummy.c b/openbsc/tests/libiudummy/iudummy.c index 32ffaa172..d2d0d5930 100644 --- a/openbsc/tests/libiudummy/iudummy.c +++ b/openbsc/tests/libiudummy/iudummy.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -34,6 +35,20 @@ int iu_page_ps(const char *imsi, const uint32_t *ptmsi, uint16_t lac, uint8_t ra return 0; } +struct msgb *ranap_new_msg_rab_assign_voice(uint8_t rab_id, uint32_t rtp_ip, + uint16_t rtp_port, + bool use_x213_nsap) +{ + LOGP(DLGLOBAL, LOGL_INFO, "ranap_new_msg_rab_assign_voice() dummy called, NOT composing RAB Assignment\n"); + return NULL; +} + +int iu_rab_act(struct ue_conn_ctx *ue_ctx, struct msgb *msg) +{ + LOGP(DLGLOBAL, LOGL_INFO, "iu_rab_act() dummy called, NOT activating RAB\n"); + return 0; +} + int iu_tx_common_id(struct ue_conn_ctx *uectx, const char *imsi) { LOGP(DLGLOBAL, LOGL_INFO, "iu_tx_common_id() dummy called, NOT sending CommonID\n"); -- cgit v1.2.3