diff options
author | Neels Hofmeyr <nhofmeyr@sysmocom.de> | 2016-01-18 16:02:23 +0100 |
---|---|---|
committer | Neels Hofmeyr <nhofmeyr@sysmocom.de> | 2016-03-03 16:19:09 +0100 |
commit | 48e091ea2bbd15b983cc08eed9f6e0bc58acac6d (patch) | |
tree | 884f05a9c0980a07970b6b71b568d9880d4da39e /openbsc/src/gprs/iu.c | |
parent | 712074cb171a9139a40d564a35a07b59871c2389 (diff) |
Add some Iu-CS functions (in the wrong place though, wip)
Diffstat (limited to 'openbsc/src/gprs/iu.c')
-rw-r--r-- | openbsc/src/gprs/iu.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/openbsc/src/gprs/iu.c b/openbsc/src/gprs/iu.c index f30d844ac..0c1650d74 100644 --- a/openbsc/src/gprs/iu.c +++ b/openbsc/src/gprs/iu.c @@ -460,3 +460,81 @@ int iu_init(void *ctx, const char *listen_addr, uint16_t listen_port, user = osmo_sua_user_create(ctx, sccp_sap_up, ctx); return osmo_sua_server_listen(user, listen_addr, listen_port); } + +/* Return an existing Iu-CS subscriber connection record for the given link and + * connection IDs, or return NULL if not found. */ +static struct gsm_subscriber_connection *subscr_conn_lookup_iu(struct gsm_network *network, + uint8_t link_id, + uint32_t conn_id) +{ + struct gsm_subscriber_connection *conn; + llist_for_each_entry(conn, &network->subscr_conns, entry) { + if (conn->via_iface != IFACE_IUCS) + continue; + if (conn->iu.link_id != link_id) + continue; + if (conn->iu.conn_id != conn_id) + continue; + return conn; + } + return NULL; +} + +/* Receive MM/CC message from Iu-CS (SCCP user SAP). + * msg->dest must reference a struct ue_conn_ctx. link_id identifies the SCTP + * peer that sent the msg. + * + * For A-interface see libbsc/bsc_api.c gsm0408_rcvmsg(). */ +int gsm0408_rcvmsg_iucs(struct gsm_network *network, struct msgb *msg, uint8_t link_id) +{ + int rc; + struct ue_conn_ctx ue_ctx; + struct gsm_subscriber_connection conn; + + ue_ctx = msg->dest; + + /* TODO: are there message types that could allow us to skip this + * search? */ + conn = subscr_conn_lookup_iu(network, link_id, ue_ctx->conn_id); + + if (lchan->conn) { + /* if we already have a connection, handle DTAP. + gsm0408_dispatch() is aka msc_dtap() */ + gsm0408_dispatch(conn, msg); + } else { + /* allocate a new connection */ + rc = BSC_API_CONN_POL_REJECT; + conn = subscr_conn_allocate_iu(msg->lchan); + if (!lchan->conn) { + lchan_release(lchan, 1, RSL_REL_NORMAL); + return -1; + } + + /* fwd via bsc_api to send COMPLETE L3 INFO to MSC */ + rc = api->compl_l3(lchan->conn, msg, 0); + + if (rc != BSC_API_CONN_POL_ACCEPT) { + lchan->conn->lchan = NULL; + subscr_con_free(lchan->conn); + lchan_release(lchan, 1, RSL_REL_NORMAL); + } + } + + return 0; +} + +/* For A-interface see libbsc/bsc_api.c subscr_con_allocate() */ +struct gsm_subscriber_connection *subscr_conn_allocate_iu(struct gsm_bts *bts) + /* TODO "bts"? this is an hNodeB, really. */ +{ + struct gsm_subscriber_connection *conn; + + conn = talloc_zero(bts->network, struct gsm_subscriber_connection); + if (!conn) + return NULL; + + conn->via_iface = IFACE_IUCS; + conn->bts = bts; + llist_add_tail(&conn->entry, &bts->network->subscr_conns); + return conn; +} |