osmo-msc: Integrate A interface into existing call control

The MSC already has some basic call control handling mechanism, that
was primarily used with 3G before. However, the already existing
code that handles the 3G calls is also perfectly fine for handling
2G calls. This commit integrates the A interface without breaking
it for 3G.

Change-Id: Ib61cf2987823958314c9016d5a3f494c1aaaabbc
This commit is contained in:
Philipp Maier 2017-05-29 13:18:44 +02:00 committed by Neels Hofmeyr
parent 714b2281b8
commit 2878423b95
3 changed files with 72 additions and 13 deletions

View File

@ -29,6 +29,8 @@
#include <openbsc/a_iface.h>
#include <openbsc/a_iface_bssap.h>
#include <openbsc/transaction.h>
#include <openbsc/mgcpgw_client.h>
#include <osmocom/core/byteswap.h>
/* A pointer to the GSM network we work with. By the current paradigm,
* there can only be one gsm_network per MSC. The pointer is set once
@ -128,15 +130,14 @@ int a_assign(struct gsm_trans *trans)
{
struct gsm_subscriber_connection *conn;
struct gsm0808_channel_type ct;
uint16_t cic;
uint16_t *cic_ptr = NULL;
struct sockaddr_storage *ss = NULL;
struct gsm0808_speech_codec_list *scl = NULL;
uint32_t *ci_ptr = NULL;
struct msgb *msg;
struct sockaddr_storage rtp_addr;
struct sockaddr_in rtp_addr_in;
conn = trans->conn;
OSMO_ASSERT(conn);
struct msgb *msg;
/* FIXME: This is still work in progress */
/* Some fake parameters for testing */
@ -145,14 +146,19 @@ int a_assign(struct gsm_trans *trans)
ct.perm_spch[0] = GSM0808_PERM_FR1;
ct.perm_spch_len = 1;
cic = 0x0023;
cic_ptr = &cic;
/* Package RTP-Address data */
memset(&rtp_addr_in, 0, sizeof(rtp_addr_in));
rtp_addr_in.sin_family = AF_INET;
rtp_addr_in.sin_port = osmo_htons(conn->iu.mgcp_rtp_port_ue);
rtp_addr_in.sin_addr.s_addr = osmo_htonl(mgcpgw_client_remote_addr_n(gsm_network->mgcpgw.client));
msg = gsm0808_create_ass(&ct, cic_ptr, ss, scl, ci_ptr);
memset(&rtp_addr, 0, sizeof(rtp_addr));
memcpy(&rtp_addr, &rtp_addr_in, sizeof(rtp_addr_in));
msg = gsm0808_create_ass(&ct, NULL, &rtp_addr, scl, ci_ptr);
LOGP(DMSC, LOGL_DEBUG, "N-DATA.req(%u, %s)\n", conn->a.conn_id, osmo_hexdump(msg->data, msg->len));
return osmo_sccp_tx_data_msg(conn->a.scu, conn->a.conn_id, msg);
}
/* Callback function, called by the SSCP stack when data arrives */

View File

@ -30,6 +30,9 @@
#include <openbsc/a_iface_bssap.h>
#include <openbsc/iu.h>
#include <openbsc/osmo_msc.h>
#include <osmocom/core/byteswap.h>
#define IP_V4_ADDR_LEN 4
/* Addresses of all BSCs which have been registered to this MSC */
static LLIST_HEAD(bsc_addr_list);
@ -526,14 +529,52 @@ static int bssmap_ass_compl(struct osmo_sccp_user *scu, struct a_conn_info *a_co
{
struct gsm_network *network = a_conn_info->network;
struct gsm_subscriber_connection *conn;
struct mgcpgw_client *mgcp;
struct tlv_parsed tp;
struct sockaddr_storage rtp_addr;
struct sockaddr_in *rtp_addr_in;
int rc;
conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
if (!conn)
goto fail;
mgcp = conn->network->mgcpgw.client;
OSMO_ASSERT(mgcp);
LOGP(DMSC, LOGL_NOTICE, "BSC sends assignment complete message (conn_id=%i)\n", conn->a.conn_id);
/* Inform the MSC about the assignment completion event */
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0);
if (!TLVP_PRESENT(&tp, GSM0808_IE_AOIP_TRASP_ADDR)) {
LOGP(DMSC, LOGL_ERROR, "AoIP transport identifier missing -- discarding message!\n");
goto fail;
}
/* Decode AoIP transport address element */
rc = gsm0808_dec_aoip_trasp_addr(&rtp_addr, TLVP_VAL(&tp, GSM0808_IE_AOIP_TRASP_ADDR), TLVP_LEN(&tp, GSM0808_IE_AOIP_TRASP_ADDR));
if (rc < 0) {
LOGP(DMSC, LOGL_ERROR, "Unable to decode aoip transport address.\n");
goto fail;
}
/* use address / port supplied with the AoIP
* transport address element */
if(rtp_addr.ss_family == AF_INET)
{
rtp_addr_in = (struct sockaddr_in *)&rtp_addr;
conn->iu.mgcp_rtp_port_ue = osmo_ntohs(rtp_addr_in->sin_port);
/* FIXME: We also get the IP-Address of the remote (e.g. BTS)
* end with the response. Currently we just ignore that address.
* Instead we expect that our local MGCP gateway and the code
* controlling it, magically knows the IP of the remote end. */
} else {
LOGP(DMSC, LOGL_ERROR, "Unsopported addressing scheme. (supports only IPV4)\n");
goto fail;
}
/* FIXME: Seems to be related to authentication or,
encryption. Is this really in the right place? */
msc_rx_sec_mode_compl(conn);
msgb_free(msg);

View File

@ -171,9 +171,17 @@ static void mgcp_response_rab_act_cs_crcx(struct mgcp_response *r, void *priv)
conn->iu.mgcp_rtp_port_cn = r->audio_port;
rtp_ip = mgcpgw_client_remote_addr_n(conn->network->mgcpgw.client);
iu_rab_act_cs(uectx, conn->iu.rab_id, rtp_ip,
conn->iu.mgcp_rtp_port_ue);
/* use_x213_nsap == 0 for ip.access nano3G */
if (trans->conn->via_ran == RAN_UTRAN_IU) {
/* Assign a voice channel via RANAP on 3G */
iu_rab_act_cs(uectx, conn->iu.rab_id, rtp_ip,
conn->iu.mgcp_rtp_port_ue);
/* use_x213_nsap == 0 for ip.access nano3G */
} else if (trans->conn->via_ran == RAN_GERAN_A) {
/* Assign a voice channel via A on 2G */
return a_assign(trans);
} else
goto rab_act_cs_error;
rab_act_cs_error:
/* FIXME abort call, invalidate conn, ... */
@ -212,7 +220,11 @@ int msc_call_assignment(struct gsm_trans *trans)
switch (conn->via_ran) {
case RAN_GERAN_A:
return a_assign(trans);
/* FIXME We first go for conn_iu_rab_act_cs(), this function
* will create a loopback rtp connection first and then call
* a_assign(). Probably we need to find another name for
* conn_iu_rab_act_cs? */
return conn_iu_rab_act_cs(trans);
case RAN_UTRAN_IU:
#ifdef BUILD_IU