From 519c7e1d428bfba728a76885c9c5394185a6497d Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 28 Jan 2018 02:45:46 +0100 Subject: Structural reform: Get rid of osmo_bsc_sccp_con There was always a 1:1 correspondence between gsm_subscriber_connection and osmo_bsc_sccp_con, so there's really no point in having two separate dynamically allocated data structures with pointers back and forth and another linked list around. Let's merge osmo_bsc_sccp_con into gsm_subscriber_connection for simplicity. The resulting code might not be elegant in places, but I've tried to do only the most simple changes in this patch, while further simplifications can be done in later subsequent patches. As a side-effect, this patch also fixes lchan clearing if the MSC (or the local SCCP provider) hard-disconnects the SCCP connection. Change-Id: Idd2b733477ee90d24dec369755a00f1c39c93f39 --- include/osmocom/bsc/gsm_data.h | 51 +++++++++++- include/osmocom/bsc/osmo_bsc.h | 53 +----------- include/osmocom/bsc/osmo_bsc_mgcp.h | 5 +- include/osmocom/bsc/osmo_bsc_sigtran.h | 6 +- src/libbsc/bsc_api.c | 2 + src/osmo-bsc/osmo_bsc_api.c | 51 +++++------- src/osmo-bsc/osmo_bsc_audio.c | 24 ++++-- src/osmo-bsc/osmo_bsc_bssap.c | 60 +++++++------- src/osmo-bsc/osmo_bsc_ctrl.c | 5 +- src/osmo-bsc/osmo_bsc_filter.c | 18 ++--- src/osmo-bsc/osmo_bsc_mgcp.c | 49 +++++------ src/osmo-bsc/osmo_bsc_sigtran.c | 144 +++++++++++++-------------------- tests/bsc/bsc_test.c | 5 +- tests/bssap/bssap_test.c | 15 ++-- 14 files changed, 222 insertions(+), 266 deletions(-) diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h index c730d9641..04dc69673 100644 --- a/include/osmocom/bsc/gsm_data.h +++ b/include/osmocom/bsc/gsm_data.h @@ -25,6 +25,7 @@ #include #include #include +#include struct mgcp_client_conf; struct mgcp_client; @@ -80,6 +81,12 @@ struct gsm_classmark { uint8_t classmark3[14]; /* if cm3 gets extended by spec, it will be truncated */ }; +enum subscr_sccp_state { + SUBSCR_SCCP_ST_NONE, + SUBSCR_SCCP_ST_WAIT_CONN_CONF, + SUBSCR_SCCP_ST_CONNECTED +}; + /* active radio connection of a mobile subscriber */ struct gsm_subscriber_connection { /* global linked list of subscriber_connections */ @@ -88,9 +95,6 @@ struct gsm_subscriber_connection { /* libbsc subscriber information (if available) */ struct bsc_subscr *bsub; - /* SCCP connection associatd with this subscriber_connection */ - struct osmo_bsc_sccp_con *sccp_con; - /* back pointers */ struct gsm_network *network; @@ -121,6 +125,47 @@ struct gsm_subscriber_connection { * capabilities, which the MSC is required to translate into the codec list. */ struct gsm0808_speech_codec_list codec_list; bool codec_list_present; + + /* flag to prevent multiple simultaneous ciphering commands */ + int ciphering_handled; + + /* state related to welcome USSD */ + uint8_t new_subscriber; + + /* state related to osmo_bsc_filter.c */ + struct bsc_filter_state filter_state; + + /* SCCP connection associatd with this subscriber_connection */ + struct { + /* for advanced ping/pong */ + int send_ping; + + /* SCCP connection realted */ + struct bsc_msc_data *msc; + + /* Sigtran connection ID */ + int conn_id; + enum subscr_sccp_state state; + } sccp; + + /* for audio handling */ + struct { + uint16_t cic; + uint32_t rtp_ip; + int rtp_port; + /* RTP address of the remote end (assigned by MSC through assignment request) */ + struct sockaddr_storage aoip_rtp_addr_remote; + + /* Local RTP address (reported back to the MSC by us with the + * assignment complete message) */ + struct sockaddr_storage aoip_rtp_addr_local; + + /* storage to keep states of the MGCP connection handler, the + * handler is created when an assignment request is received + * and is terminated when the assignment complete message is + * sent */ + struct mgcp_ctx *mgcp_ctx; + } user_plane; }; diff --git a/include/osmocom/bsc/osmo_bsc.h b/include/osmocom/bsc/osmo_bsc.h index 485c83648..678ac41d2 100644 --- a/include/osmocom/bsc/osmo_bsc.h +++ b/include/osmocom/bsc/osmo_bsc.h @@ -16,59 +16,14 @@ enum bsc_con { }; struct bsc_msc_data; -struct bsc_msc_connection; - -struct osmo_bsc_sccp_con { - /* list_head anchoring us to gsm_network.subscr_conns */ - struct llist_head entry; - - /* flag to prevent multiple simultaneous ciphering commands */ - int ciphering_handled; - - /* for audio handling */ - struct { - uint16_t cic; - uint32_t rtp_ip; - int rtp_port; - /* RTP address of the remote end (assigned by MSC through assignment request) */ - struct sockaddr_storage aoip_rtp_addr_remote; - - /* Local RTP address (reported back to the MSC by us with the - * assignment complete message) */ - struct sockaddr_storage aoip_rtp_addr_local; - - /* storage to keep states of the MGCP connection handler, the - * handler is created when an assignment request is received - * and is terminated when the assignment complete message is - * sent */ - struct mgcp_ctx *mgcp_ctx; - } user_plane; - - /* for advanced ping/pong */ - int send_ping; - - /* SCCP connection realted */ - struct bsc_msc_data *msc; - - /* back-pointer to subscriber connection */ - struct gsm_subscriber_connection *conn; - /* state related to welcome USSD */ - uint8_t new_subscriber; - - /* state related to osmo_bsc_filter.c */ - struct bsc_filter_state filter_state; - - /* Sigtran connection ID */ - int conn_id; -}; struct bsc_api *osmo_bsc_api(); -int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg); -int bsc_open_connection(struct osmo_bsc_sccp_con *sccp, struct msgb *msg); +int bsc_queue_for_msc(struct gsm_subscriber_connection *conn, struct msgb *msg); +int bsc_open_connection(struct gsm_subscriber_connection *sccp, struct msgb *msg); enum bsc_con bsc_create_new_connection(struct gsm_subscriber_connection *conn, struct bsc_msc_data *msc, int send_ping); -int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp); +int bsc_delete_connection(struct gsm_subscriber_connection *sccp); struct bsc_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn, struct msgb *); int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg); @@ -76,7 +31,7 @@ int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg); int bsc_send_welcome_ussd(struct gsm_subscriber_connection *conn); int bsc_handle_udt(struct bsc_msc_data *msc, struct msgb *msg, unsigned int length); -int bsc_handle_dt(struct osmo_bsc_sccp_con *conn, struct msgb *msg, unsigned int len); +int bsc_handle_dt(struct gsm_subscriber_connection *conn, struct msgb *msg, unsigned int len); int bsc_ctrl_cmds_install(); diff --git a/include/osmocom/bsc/osmo_bsc_mgcp.h b/include/osmocom/bsc/osmo_bsc_mgcp.h index dc2ba3475..15039f747 100644 --- a/include/osmocom/bsc/osmo_bsc_mgcp.h +++ b/include/osmocom/bsc/osmo_bsc_mgcp.h @@ -43,7 +43,7 @@ struct mgcp_ctx { /* Copy of the pointer and the data with context information * needed to process the AoIP and MGCP requests (system data) */ struct mgcp_client *mgcp; - struct osmo_bsc_sccp_con *conn; + struct gsm_subscriber_connection *conn; enum gsm48_chan_mode chan_mode; bool full_rate; struct gsm_lchan *lchan; @@ -54,7 +54,8 @@ struct mgcp_ctx { void mgcp_init(struct gsm_network *net); -struct mgcp_ctx *mgcp_assignm_req(void *ctx, struct mgcp_client *mgcp, struct osmo_bsc_sccp_con *conn, +struct mgcp_ctx *mgcp_assignm_req(void *ctx, struct mgcp_client *mgcp, + struct gsm_subscriber_connection *conn, enum gsm48_chan_mode chan_mode, bool full_rate); void mgcp_clear_complete(struct mgcp_ctx *mgcp_ctx, struct msgb *resp); void mgcp_ass_complete(struct mgcp_ctx *mgcp_ctx, struct gsm_lchan *lchan); diff --git a/include/osmocom/bsc/osmo_bsc_sigtran.h b/include/osmocom/bsc/osmo_bsc_sigtran.h index 89649036e..5cb723066 100644 --- a/include/osmocom/bsc/osmo_bsc_sigtran.h +++ b/include/osmocom/bsc/osmo_bsc_sigtran.h @@ -28,15 +28,15 @@ enum bsc_con osmo_bsc_sigtran_new_conn(struct gsm_subscriber_connection *conn, struct bsc_msc_data *msc); /* Open a new connection oriented sigtran connection */ -int osmo_bsc_sigtran_open_conn(const struct osmo_bsc_sccp_con *conn, struct msgb *msg); +int osmo_bsc_sigtran_open_conn(struct gsm_subscriber_connection *conn, struct msgb *msg); /* Send data to MSC */ -int osmo_bsc_sigtran_send(const struct osmo_bsc_sccp_con *conn, struct msgb *msg); +int osmo_bsc_sigtran_send(struct gsm_subscriber_connection *conn, struct msgb *msg); /* Delete a connection from the list with open connections * (called by osmo_bsc_api.c on failing open connections and * locally, when a connection is closed by the MSC */ -int osmo_bsc_sigtran_del_conn(struct osmo_bsc_sccp_con *sccp); +int osmo_bsc_sigtran_del_conn(struct gsm_subscriber_connection *sccp); /* Initalize osmo sigtran backhaul */ int osmo_bsc_sigtran_init(struct llist_head *mscs); diff --git a/src/libbsc/bsc_api.c b/src/libbsc/bsc_api.c index 2cb5b1032..908671935 100644 --- a/src/libbsc/bsc_api.c +++ b/src/libbsc/bsc_api.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -278,6 +279,7 @@ struct gsm_subscriber_connection *bsc_subscr_con_allocate(struct gsm_lchan *lcha lchan->conn = conn; INIT_LLIST_HEAD(&conn->ho_dtap_cache); conn->ho_penalty_timers = penalty_timers_init(conn); + conn->sccp.conn_id = -1; llist_add_tail(&conn->entry, &net->subscr_conns); return conn; } diff --git a/src/osmo-bsc/osmo_bsc_api.c b/src/osmo-bsc/osmo_bsc_api.c index 1caaeee7c..465832c82 100644 --- a/src/osmo-bsc/osmo_bsc_api.c +++ b/src/osmo-bsc/osmo_bsc_api.c @@ -32,13 +32,13 @@ #include #define return_when_not_connected(conn) \ - if (!conn->sccp_con) {\ + if (conn->sccp.state != SUBSCR_SCCP_ST_CONNECTED) {\ LOGP(DMSC, LOGL_ERROR, "MSC Connection not present.\n"); \ return; \ } #define return_when_not_connected_val(conn, ret) \ - if (!conn->sccp_con) {\ + if (conn->sccp.state != SUBSCR_SCCP_ST_CONNECTED) {\ LOGP(DMSC, LOGL_ERROR, "MSC Connection not present.\n"); \ return ret; \ } @@ -48,7 +48,7 @@ LOGP(DMSC, LOGL_ERROR, "Failed to allocate response.\n"); \ return; \ } \ - osmo_bsc_sigtran_send(conn->sccp_con, resp); + osmo_bsc_sigtran_send(conn, resp); static int bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause); static int complete_layer3(struct gsm_subscriber_connection *conn, @@ -135,12 +135,12 @@ static int bsc_filter_data(struct gsm_subscriber_connection *conn, req.ctx = conn; req.black_list = NULL; req.access_lists = bsc_access_lists(); - req.local_lst_name = conn->sccp_con->msc->acc_lst_name; + req.local_lst_name = conn->sccp.msc->acc_lst_name; req.global_lst_name = conn_get_bts(conn)->network->bsc_data->acc_lst_name; req.bsc_nr = 0; rc = bsc_msg_filter_data(gh, msgb_l3len(msg), &req, - &conn->sccp_con->filter_state, + &conn->filter_state, &cause); *lu_cause = cause.lu_reject_cause; return rc; @@ -280,27 +280,27 @@ static int complete_layer3(struct gsm_subscriber_connection *conn, } if (imsi) - conn->sccp_con->filter_state.imsi = talloc_steal(conn, imsi); - conn->sccp_con->filter_state.con_type = con_type; + conn->filter_state.imsi = talloc_steal(conn, imsi); + conn->filter_state.con_type = con_type; /* check return value, if failed check msg for and send USSD */ - network_code = get_network_code_for_msc(conn->sccp_con->msc); - country_code = get_country_code_for_msc(conn->sccp_con->msc); - lac = get_lac_for_msc(conn->sccp_con->msc, conn_get_bts(conn)); - ci = get_ci_for_msc(conn->sccp_con->msc, conn_get_bts(conn)); + network_code = get_network_code_for_msc(conn->sccp.msc); + country_code = get_country_code_for_msc(conn->sccp.msc); + lac = get_lac_for_msc(conn->sccp.msc, conn_get_bts(conn)); + ci = get_ci_for_msc(conn->sccp.msc, conn_get_bts(conn)); bsc_scan_bts_msg(conn, msg); resp = gsm0808_create_layer3(msg, network_code, country_code, lac, ci); if (!resp) { LOGP(DMSC, LOGL_DEBUG, "Failed to create layer3 message.\n"); - osmo_bsc_sigtran_del_conn(conn->sccp_con); + osmo_bsc_sigtran_del_conn(conn); return BSC_API_CONN_POL_REJECT; } - if (osmo_bsc_sigtran_open_conn(conn->sccp_con, resp) != 0) { - osmo_bsc_sigtran_del_conn(conn->sccp_con); + if (osmo_bsc_sigtran_open_conn(conn, resp) != 0) { + osmo_bsc_sigtran_del_conn(conn); msgb_free(resp); return BSC_API_CONN_POL_REJECT; } @@ -314,14 +314,11 @@ static int complete_layer3(struct gsm_subscriber_connection *conn, static int move_to_msc(struct gsm_subscriber_connection *_conn, struct msgb *msg, struct bsc_msc_data *msc) { - struct osmo_bsc_sccp_con *old_con = _conn->sccp_con; - /* * 1. Give up the old connection. * This happens by sending a clear request to the MSC, * it should end with the MSC releasing the connection. */ - old_con->conn = NULL; bsc_clear_request(_conn, 0); /* @@ -329,7 +326,6 @@ static int move_to_msc(struct gsm_subscriber_connection *_conn, * MSC. If it fails the caller will need to handle this * properly. */ - _conn->sccp_con = NULL; if (complete_layer3(_conn, msg, msc) != BSC_API_CONN_POL_ACCEPT) { gsm0808_clear(_conn); bsc_subscr_con_free(_conn); @@ -416,7 +412,7 @@ static void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, st /* Check the filter */ if (bsc_filter_data(conn, msg, &lu_cause) < 0) { bsc_maybe_lu_reject(conn, - conn->sccp_con->filter_state.con_type, + conn->filter_state.con_type, lu_cause); bsc_clear_request(conn, 0); return; @@ -435,7 +431,7 @@ static void bsc_assign_compl(struct gsm_subscriber_connection *conn, uint8_t rr_ struct msgb *resp; return_when_not_connected(conn); - if (is_ipaccess_bts(conn_get_bts(conn)) && conn->sccp_con->user_plane.rtp_ip) { + if (is_ipaccess_bts(conn_get_bts(conn)) && conn->user_plane.rtp_ip) { /* NOTE: In a network that makes use of an IPA base station * and AoIP, we have to wait until the BTS reports its RTP * IP/Port combination back to BSC via RSL. Unfortunately, the @@ -473,27 +469,18 @@ static void bsc_assign_fail(struct gsm_subscriber_connection *conn, static int bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause) { - struct osmo_bsc_sccp_con *sccp; struct msgb *resp; return_when_not_connected_val(conn, 1); LOGP(DMSC, LOGL_INFO, "Tx MSC CLEAR REQUEST\n"); - /* - * Remove the connection from BSC<->SCCP part, the SCCP part - * will either be cleared by channel release or MSC disconnect - */ - sccp = conn->sccp_con; - sccp->conn = NULL; - conn->sccp_con = NULL; - resp = gsm0808_create_clear_rqst(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE); if (!resp) { LOGP(DMSC, LOGL_ERROR, "Failed to allocate response.\n"); return 1; } - osmo_bsc_sigtran_send(sccp, resp); + osmo_bsc_sigtran_send(conn, resp); return 1; } @@ -515,14 +502,14 @@ static void bsc_mr_config(struct gsm_subscriber_connection *conn, struct bsc_msc_data *msc; struct gsm48_multi_rate_conf *ms_conf, *bts_conf; - if (!conn->sccp_con) { + if (!conn) { LOGP(DMSC, LOGL_ERROR, "No msc data available on conn %p. Audio will be broken.\n", conn); return; } - msc = conn->sccp_con->msc; + msc = conn->sccp.msc; /* initialize the data structure */ lchan->mr_ms_lv[0] = sizeof(*ms_conf); diff --git a/src/osmo-bsc/osmo_bsc_audio.c b/src/osmo-bsc/osmo_bsc_audio.c index ceec469ca..295d8543a 100644 --- a/src/osmo-bsc/osmo_bsc_audio.c +++ b/src/osmo-bsc/osmo_bsc_audio.c @@ -45,24 +45,24 @@ static int handle_abisip_signal(unsigned int subsys, unsigned int signal, return 0; con = lchan->conn; - if (!con || !con->sccp_con) + if (!con) return 0; switch (signal) { case S_ABISIP_CRCX_ACK: /* we can ask it to connect now */ LOGP(DMSC, LOGL_DEBUG, "Connecting BTS to port: %d conn: %d\n", - con->sccp_con->user_plane.rtp_port, lchan->abis_ip.conn_id); + con->user_plane.rtp_port, lchan->abis_ip.conn_id); /* If AoIP is in use, the rtp_ip, which has been communicated * via the A interface as connect_ip */ - if(con->sccp_con->user_plane.rtp_ip) - rtp_ip = con->sccp_con->user_plane.rtp_ip; + if(con->user_plane.rtp_ip) + rtp_ip = con->user_plane.rtp_ip; else rtp_ip = ntohl(INADDR_ANY); rc = rsl_ipacc_mdcx(lchan, rtp_ip, - con->sccp_con->user_plane.rtp_port, + con->user_plane.rtp_port, lchan->abis_ip.rtp_payload2); if (rc < 0) { LOGP(DMSC, LOGL_ERROR, "Failed to send MDCX: %d\n", rc); @@ -77,12 +77,22 @@ static int handle_abisip_signal(unsigned int subsys, unsigned int signal, /* No need to do anything for handover here. As soon as a HANDOVER DETECT * happens, osmo_bsc_mgcp.c will trigger the MGCP MDCX towards MGW by * receiving an S_LCHAN_HANDOVER_DETECT signal. */ - } else if (is_ipaccess_bts(conn_get_bts(con)) && con->sccp_con->user_plane.rtp_ip) { +#if 0 + /* NOTE: When an ho_lchan exists, the MDCX is part of an + * handover operation (intra-bsc). This means we will not + * inform the MSC about the event, which means that no + * assignment complete message is transmitted, we just + * inform the logic that controls the MGW about the new + * connection info */ + LOGP(DMSC, LOGL_INFO,"RTP connection handover initiated...\n"); + mgcp_handover(con->user_plane.mgcp_ctx, con->ho_lchan); +#endif + } else if (is_ipaccess_bts(conn_get_bts(con)) && con->user_plane.rtp_ip) { /* NOTE: This is only relevant on AoIP networks with * IPA based base stations. See also osmo_bsc_api.c, * function bsc_assign_compl() */ LOGP(DMSC, LOGL_INFO, "Tx MSC ASSIGN COMPL (POSTPONED)\n"); - mgcp_ass_complete(con->sccp_con->user_plane.mgcp_ctx, lchan); + mgcp_ass_complete(con->user_plane.mgcp_ctx, lchan); } break; } diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c index 0adc001be..83c884c44 100644 --- a/src/osmo-bsc/osmo_bsc_bssap.c +++ b/src/osmo-bsc/osmo_bsc_bssap.c @@ -571,19 +571,15 @@ static int bssmap_handle_paging(struct bsc_msc_data *msc, * GSM 08.08 § 3.1.9.1 and 3.2.1.21... * release our gsm_subscriber_connection and send message */ -static int bssmap_handle_clear_command(struct osmo_bsc_sccp_con *conn, +static int bssmap_handle_clear_command(struct gsm_subscriber_connection *conn, struct msgb *msg, unsigned int payload_length) { struct msgb *resp; /* TODO: handle the cause of this package */ - if (conn->conn) { - LOGP(DMSC, LOGL_INFO, "Releasing all transactions on %p\n", conn); - gsm0808_clear(conn->conn); - bsc_subscr_con_free(conn->conn); - conn->conn = NULL; - } + LOGP(DMSC, LOGL_INFO, "Releasing all transactions on %p\n", conn); + gsm0808_clear(conn); /* generate the clear complete message */ resp = gsm0808_create_clear_complete(); @@ -618,7 +614,7 @@ static int bssmap_handle_clear_command(struct osmo_bsc_sccp_con *conn, * is supporting. Currently we are doing it in a rather static * way by picking one encryption or no encryption. */ -static int bssmap_handle_cipher_mode(struct osmo_bsc_sccp_con *conn, +static int bssmap_handle_cipher_mode(struct gsm_subscriber_connection *conn, struct msgb *msg, unsigned int payload_length) { uint16_t len; @@ -633,7 +629,7 @@ static int bssmap_handle_cipher_mode(struct osmo_bsc_sccp_con *conn, uint8_t enc_bits_bsc; uint8_t enc_bits_msc; - if (!conn->conn) { + if (!conn) { LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n"); goto reject; } @@ -663,7 +659,7 @@ static int bssmap_handle_cipher_mode(struct osmo_bsc_sccp_con *conn, goto reject; } - network = conn_get_bts(conn->conn)->network; + network = conn_get_bts(conn)->network; data = TLVP_VAL(&tp, GSM0808_IE_ENCRYPTION_INFORMATION); enc_bits_msc = data[0]; enc_key = &data[1]; @@ -692,7 +688,7 @@ static int bssmap_handle_cipher_mode(struct osmo_bsc_sccp_con *conn, /* To complete the confusion, gsm0808_cipher_mode again expects the encryption as a number * from 0 to 7. */ - if (gsm0808_cipher_mode(conn->conn, network->a5_encryption, enc_key, enc_key_len, + if (gsm0808_cipher_mode(conn, network->a5_encryption, enc_key, enc_key_len, include_imeisv)) { reject_cause = GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC; goto reject; @@ -728,7 +724,7 @@ static inline int mgcp_timeslot_to_port(int multiplex, int timeslot, int base) * * See §3.2.1.1 for the message type */ -static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn, +static int bssmap_handle_assignm_req(struct gsm_subscriber_connection *conn, struct msgb *msg, unsigned int length) { struct msgb *resp; @@ -744,13 +740,13 @@ static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn, struct gsm0808_speech_codec_list *scl_ptr = NULL; int rc; - if (!conn->conn) { + if (!conn) { LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n"); return -1; } - msc = conn->msc; + msc = conn->sccp.msc; tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, length - 1, 0, 0); @@ -799,7 +795,7 @@ static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn, } /* Decode speech codec list (AoIP) */ - conn->conn->codec_list_present = false; + conn->codec_list_present = false; if (aoip) { /* Check for speech codec list element */ if (!TLVP_PRESENT(&tp, GSM0808_IE_SPEECH_CODEC_LIST)) { @@ -809,7 +805,7 @@ static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn, } /* Decode Speech Codec list */ - rc = gsm0808_dec_speech_codec_list(&conn->conn->codec_list, + rc = gsm0808_dec_speech_codec_list(&conn->codec_list, TLVP_VAL(&tp, GSM0808_IE_SPEECH_CODEC_LIST), TLVP_LEN(&tp, GSM0808_IE_SPEECH_CODEC_LIST)); if (rc < 0) { @@ -817,8 +813,8 @@ static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn, "Unable to decode speech codec list\n"); goto reject; } - conn->conn->codec_list_present = true; - scl_ptr = &conn->conn->codec_list; + conn->codec_list_present = true; + scl_ptr = &conn->codec_list; } /* Match codec information from the assignment command against the @@ -856,7 +852,8 @@ static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn, conn->user_plane.mgcp_ctx = mgcp_assignm_req(msc->network, msc->network->mgw.client, conn, chan_mode, full_rate); if (!conn->user_plane.mgcp_ctx) { - LOGP(DMSC, LOGL_ERROR, "MGCP GW failure, rejecting assignment... (id=%i)\n", conn->conn_id); + LOGP(DMSC, LOGL_ERROR, "MGCP GW failure, rejecting assignment... (id=%i)\n", + conn->sccp.conn_id); goto reject; } @@ -869,7 +866,7 @@ static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn, * to sccp-lite. */ conn->user_plane.rtp_port = mgcp_timeslot_to_port(multiplex, timeslot, msc->rtp_base); conn->user_plane.rtp_ip = 0; - return gsm0808_assign_req(conn->conn, chan_mode, full_rate); + return gsm0808_assign_req(conn, chan_mode, full_rate); } reject: @@ -917,7 +914,7 @@ static int bssmap_rcvmsg_udt(struct bsc_msc_data *msc, return ret; } -static int bssmap_rcvmsg_dt1(struct osmo_bsc_sccp_con *conn, +static int bssmap_rcvmsg_dt1(struct gsm_subscriber_connection *conn, struct msgb *msg, unsigned int length) { int ret = 0; @@ -949,7 +946,7 @@ static int bssmap_rcvmsg_dt1(struct osmo_bsc_sccp_con *conn, return ret; } -static int dtap_rcvmsg(struct osmo_bsc_sccp_con *conn, +static int dtap_rcvmsg(struct gsm_subscriber_connection *conn, struct msgb *msg, unsigned int length) { struct dtap_header *header; @@ -960,7 +957,7 @@ static int dtap_rcvmsg(struct osmo_bsc_sccp_con *conn, LOGP(DMSC, LOGL_DEBUG, "Rx MSC DTAP: %s\n", osmo_hexdump(msg->l3h, length)); - if (!conn->conn) { + if (!conn) { LOGP(DMSC, LOGL_ERROR, "No subscriber connection available\n"); return -1; } @@ -992,10 +989,10 @@ static int dtap_rcvmsg(struct osmo_bsc_sccp_con *conn, memcpy(data, msg->l3h + sizeof(*header), length - sizeof(*header)); /* pass it to the filter for extra actions */ - rc = bsc_scan_msc_msg(conn->conn, gsm48); - dtap_rc = gsm0808_submit_dtap(conn->conn, gsm48, header->link_id, 1); + rc = bsc_scan_msc_msg(conn, gsm48); + dtap_rc = gsm0808_submit_dtap(conn, gsm48, header->link_id, 1); if (rc == BSS_SEND_USSD) - bsc_send_welcome_ussd(conn->conn); + bsc_send_welcome_ussd(conn); return dtap_rc; } @@ -1029,7 +1026,7 @@ int bsc_handle_udt(struct bsc_msc_data *msc, return 0; } -int bsc_handle_dt(struct osmo_bsc_sccp_con *conn, +int bsc_handle_dt(struct gsm_subscriber_connection *conn, struct msgb *msg, unsigned int len) { if (len < sizeof(struct bssmap_header)) { @@ -1063,9 +1060,8 @@ int bssmap_send_aoip_ass_compl(struct gsm_lchan *lchan) OSMO_ASSERT(lchan->abis_ip.ass_compl.valid); OSMO_ASSERT(conn); - OSMO_ASSERT(conn->sccp_con); - LOGP(DMSC, LOGL_DEBUG, "Sending assignment complete message... (id=%i)\n", conn->sccp_con->conn_id); + LOGP(DMSC, LOGL_DEBUG, "Sending assignment complete message... (id=%i)\n", conn->sccp.conn_id); /* Extrapolate speech codec from speech mode */ gsm0808_speech_codec_from_chan_type(&sc, lchan->abis_ip.ass_compl.speech_mode); @@ -1075,15 +1071,15 @@ int bssmap_send_aoip_ass_compl(struct gsm_lchan *lchan) lchan->abis_ip.ass_compl.chosen_channel, lchan->abis_ip.ass_compl.encr_alg_id, lchan->abis_ip.ass_compl.speech_mode, - &conn->sccp_con->user_plane.aoip_rtp_addr_local, + &conn->user_plane.aoip_rtp_addr_local, &sc, NULL); if (!resp) { LOGP(DMSC, LOGL_ERROR, "Failed to generate assignment completed message! (id=%i)\n", - conn->sccp_con->conn_id); + conn->sccp.conn_id); return -EINVAL; } - return osmo_bsc_sigtran_send(conn->sccp_con, resp); + return osmo_bsc_sigtran_send(conn, resp); } diff --git a/src/osmo-bsc/osmo_bsc_ctrl.c b/src/osmo-bsc/osmo_bsc_ctrl.c index fc7908656..6092f2379 100644 --- a/src/osmo-bsc/osmo_bsc_ctrl.c +++ b/src/osmo-bsc/osmo_bsc_ctrl.c @@ -570,10 +570,7 @@ static int set_net_ussd_notify(struct ctrl_cmd *cmd, void *data) net = cmd->node; llist_for_each_entry(conn, &net->subscr_conns, entry) { - if (!conn->sccp_con) - continue; - - if (conn->sccp_con->user_plane.cic != cic) + if (conn->user_plane.cic != cic) continue; /* diff --git a/src/osmo-bsc/osmo_bsc_filter.c b/src/osmo-bsc/osmo_bsc_filter.c index 5399b7aee..c1f3e80a6 100644 --- a/src/osmo-bsc/osmo_bsc_filter.c +++ b/src/osmo-bsc/osmo_bsc_filter.c @@ -54,7 +54,7 @@ static void handle_lu_request(struct gsm_subscriber_connection *conn, if (memcmp(&lai, &lu->lai, sizeof(lai)) != 0) { LOGP(DMSC, LOGL_DEBUG, "Marking con for welcome USSD.\n"); - conn->sccp_con->new_subscriber = 1; + conn->new_subscriber = 1; } } @@ -234,15 +234,7 @@ int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg) static int send_welcome_ussd(struct gsm_subscriber_connection *conn) { - struct osmo_bsc_sccp_con *bsc_con; - - bsc_con = conn->sccp_con; - if (!bsc_con) { - LOGP(DMSC, LOGL_DEBUG, "No SCCP connection associated.\n"); - return 0; - } - - if (!bsc_con->msc->ussd_welcome_txt) { + if (!conn->sccp.msc->ussd_welcome_txt) { LOGP(DMSC, LOGL_DEBUG, "No USSD Welcome text defined.\n"); return 0; } @@ -252,7 +244,7 @@ static int send_welcome_ussd(struct gsm_subscriber_connection *conn) int bsc_send_welcome_ussd(struct gsm_subscriber_connection *conn) { - bsc_send_ussd_notify(conn, 1, conn->sccp_con->msc->ussd_welcome_txt); + bsc_send_ussd_notify(conn, 1, conn->sccp.msc->ussd_welcome_txt); bsc_send_ussd_release_complete(conn); return 0; @@ -362,7 +354,7 @@ int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg) mtype = gsm48_hdr_msg_type(gh); net = bts->network; - msc = conn->sccp_con->msc; + msc = conn->sccp.msc; if (mtype == GSM48_MT_MM_LOC_UPD_ACCEPT) { if (has_core_identity(msc)) { @@ -375,7 +367,7 @@ int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg) } } - if (conn->sccp_con->new_subscriber) + if (conn->new_subscriber) return send_welcome_ussd(conn); return 0; } else if (mtype == GSM48_MT_MM_INFO) { diff --git a/src/osmo-bsc/osmo_bsc_mgcp.c b/src/osmo-bsc/osmo_bsc_mgcp.c index bdf2dd283..4b6420e9b 100644 --- a/src/osmo-bsc/osmo_bsc_mgcp.c +++ b/src/osmo-bsc/osmo_bsc_mgcp.c @@ -151,7 +151,7 @@ static void crcx_for_bts_resp_cb(struct mgcp_response *r, void *priv); static void fsm_crcx_bts_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct mgcp_ctx *mgcp_ctx = data; - struct osmo_bsc_sccp_con *conn; + struct gsm_subscriber_connection *conn; struct msgb *msg; struct mgcp_msg mgcp_msg; struct mgcp_client *mgcp; @@ -174,7 +174,7 @@ static void fsm_crcx_bts_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data mgcp_msg = (struct mgcp_msg) { .verb = MGCP_VERB_CRCX, .presence = (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID | MGCP_MSG_PRESENCE_CONN_MODE), - .call_id = conn->conn_id, + .call_id = conn->sccp.conn_id, .conn_mode = MGCP_CONN_LOOPBACK }; if (snprintf(mgcp_msg.endpoint, MGCP_ENDPOINT_MAXLEN, MGCP_ENDPOINT_FORMAT, rtp_endpoint) >= @@ -201,7 +201,7 @@ static void crcx_for_bts_resp_cb(struct mgcp_response *r, void *priv) { struct mgcp_ctx *mgcp_ctx = priv; int rc; - struct osmo_bsc_sccp_con *conn; + struct gsm_subscriber_connection *conn; uint32_t addr; OSMO_ASSERT(mgcp_ctx); @@ -256,7 +256,7 @@ static void crcx_for_bts_resp_cb(struct mgcp_response *r, void *priv) static void fsm_proc_assignmnent_req_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct mgcp_ctx *mgcp_ctx = data; - struct osmo_bsc_sccp_con *conn; + struct gsm_subscriber_connection *conn; enum gsm48_chan_mode chan_mode; bool full_rate; int rc; @@ -273,12 +273,12 @@ static void fsm_proc_assignmnent_req_cb(struct osmo_fsm_inst *fi, uint32_t event return; } - OSMO_ASSERT(conn->conn); + OSMO_ASSERT(conn); chan_mode = mgcp_ctx->chan_mode; full_rate = mgcp_ctx->full_rate; LOGPFSML(fi, LOGL_DEBUG, "MGW proceeding assignment request...\n"); - rc = gsm0808_assign_req(conn->conn, chan_mode, full_rate); + rc = gsm0808_assign_req(conn, chan_mode, full_rate); if (rc < 0) { handle_error(mgcp_ctx, MGCP_ERR_ASSGMNT_FAIL); @@ -295,7 +295,7 @@ static void mdcx_for_bts_resp_cb(struct mgcp_response *r, void *priv); static void fsm_mdcx_bts_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct mgcp_ctx *mgcp_ctx = data; - struct osmo_bsc_sccp_con *conn; + struct gsm_subscriber_connection *conn; struct gsm_lchan *lchan; struct msgb *msg; struct mgcp_msg mgcp_msg; @@ -333,7 +333,7 @@ static void fsm_mdcx_bts_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data .verb = MGCP_VERB_MDCX, .presence = (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID | MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE | MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT), - .call_id = conn->conn_id, + .call_id = conn->sccp.conn_id, .conn_id = mgcp_ctx->conn_id_bts, .conn_mode = MGCP_CONN_RECV_SEND, .audio_ip = inet_ntoa(addr), @@ -407,7 +407,7 @@ static void crcx_for_net_resp_cb(struct mgcp_response *r, void *priv); static void fsm_crcx_net_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct mgcp_ctx *mgcp_ctx = data; - struct osmo_bsc_sccp_con *conn; + struct gsm_subscriber_connection *conn; struct msgb *msg; struct mgcp_msg mgcp_msg; struct mgcp_client *mgcp; @@ -460,7 +460,7 @@ static void fsm_crcx_net_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data .verb = MGCP_VERB_CRCX, .presence = (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID | MGCP_MSG_PRESENCE_CONN_MODE | MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT), - .call_id = conn->conn_id, + .call_id = conn->sccp.conn_id, .conn_mode = MGCP_CONN_RECV_SEND, .audio_ip = addr, .audio_port = port @@ -489,7 +489,7 @@ static void crcx_for_net_resp_cb(struct mgcp_response *r, void *priv) { struct mgcp_ctx *mgcp_ctx = priv; int rc; - struct osmo_bsc_sccp_con *conn; + struct gsm_subscriber_connection *conn; struct gsm_lchan *lchan; struct sockaddr_in *sin; uint32_t addr; @@ -581,7 +581,7 @@ static void mdcx_for_bts_ho_resp_cb(struct mgcp_response *r, void *priv); * change to ST_HALT when teardown is done. */ static void handle_teardown(struct mgcp_ctx *mgcp_ctx) { - struct osmo_bsc_sccp_con *conn; + struct gsm_subscriber_connection *conn; struct msgb *msg; struct mgcp_msg mgcp_msg; struct mgcp_client *mgcp; @@ -607,7 +607,7 @@ static void handle_teardown(struct mgcp_ctx *mgcp_ctx) mgcp_msg = (struct mgcp_msg) { .verb = MGCP_VERB_DLCX, .presence = (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID), - .call_id = conn->conn_id + .call_id = conn->sccp.conn_id }; if (snprintf(mgcp_msg.endpoint, sizeof(mgcp_msg.endpoint), MGCP_ENDPOINT_FORMAT, rtp_endpoint) >= sizeof(mgcp_msg.endpoint)) { @@ -633,7 +633,7 @@ static void handle_teardown(struct mgcp_ctx *mgcp_ctx) * change to ST_CALL when teardown is done. */ static void handle_handover(struct mgcp_ctx *mgcp_ctx) { - struct osmo_bsc_sccp_con *conn; + struct gsm_subscriber_connection *conn; struct msgb *msg; struct mgcp_msg mgcp_msg; struct mgcp_client *mgcp; @@ -663,7 +663,7 @@ static void handle_handover(struct mgcp_ctx *mgcp_ctx) .presence = (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID | MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE | MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT), - .call_id = conn->conn_id, + .call_id = conn->sccp.conn_id, .conn_id = mgcp_ctx->conn_id_bts, .conn_mode = MGCP_CONN_RECV_SEND, .audio_ip = inet_ntoa(addr), @@ -766,7 +766,7 @@ static void fsm_complete_handover(struct osmo_fsm_inst *fi, uint32_t event, void static void dlcx_for_all_resp_cb(struct mgcp_response *r, void *priv) { struct mgcp_ctx *mgcp_ctx = priv; - struct osmo_bsc_sccp_con *conn; + struct gsm_subscriber_connection *conn; struct mgcp_client *mgcp; OSMO_ASSERT(mgcp_ctx); @@ -799,7 +799,7 @@ static void dlcx_for_all_resp_cb(struct mgcp_response *r, void *priv) static void fsm_halt_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct mgcp_ctx *mgcp_ctx = (struct mgcp_ctx *)data; - struct osmo_bsc_sccp_con *conn; + struct gsm_subscriber_connection *conn; OSMO_ASSERT(mgcp_ctx); conn = mgcp_ctx->conn; @@ -960,7 +960,8 @@ static struct osmo_fsm fsm_bsc_mgcp = { * chan_mode: channel mode (system data, passed through) * full_rate: full rate flag (system data, passed through) * Returns an mgcp_context that contains system data and the OSMO-FSM */ -struct mgcp_ctx *mgcp_assignm_req(void *ctx, struct mgcp_client *mgcp, struct osmo_bsc_sccp_con *conn, +struct mgcp_ctx *mgcp_assignm_req(void *ctx, struct mgcp_client *mgcp, + struct gsm_subscriber_connection *conn, enum gsm48_chan_mode chan_mode, bool full_rate) { struct mgcp_ctx *mgcp_ctx; @@ -969,7 +970,7 @@ struct mgcp_ctx *mgcp_assignm_req(void *ctx, struct mgcp_client *mgcp, struct os OSMO_ASSERT(mgcp); OSMO_ASSERT(conn); - OSMO_ASSERT(snprintf(name, sizeof(name), "MGW_%i", conn->conn_id) < sizeof(name)); + OSMO_ASSERT(snprintf(name, sizeof(name), "MGW_%i", conn->sccp.conn_id) < sizeof(name)); /* Allocate and configure a new fsm instance */ mgcp_ctx = talloc_zero(ctx, struct mgcp_ctx); @@ -997,7 +998,7 @@ struct mgcp_ctx *mgcp_assignm_req(void *ctx, struct mgcp_client *mgcp, struct os * respmgcp_ctx: pending clear complete message to send via A-Interface */ void mgcp_clear_complete(struct mgcp_ctx *mgcp_ctx, struct msgb *resp) { - struct osmo_bsc_sccp_con *conn; + struct gsm_subscriber_connection *conn; OSMO_ASSERT(mgcp_ctx); OSMO_ASSERT(resp); @@ -1086,19 +1087,19 @@ static int mgcp_sig_ho_detect(struct gsm_lchan *new_lchan) return -EINVAL; } - if (!conn->sccp_con) { - LOGP(DHO, LOGL_ERROR, "%s HO Detect for conn without sccp_con\n", + if (!conn->sccp.conn_id) { + LOGP(DHO, LOGL_ERROR, "%s HO Detect for conn without sccp_conn_id\n", gsm_lchan_name(new_lchan)); return -EINVAL; } - if (!conn->sccp_con->user_plane.mgcp_ctx) { + if (!conn->user_plane.mgcp_ctx) { LOGP(DHO, LOGL_ERROR, "%s HO Detect for conn without MGCP ctx\n", gsm_lchan_name(new_lchan)); return -EINVAL; } - mgcp_handover(conn->sccp_con->user_plane.mgcp_ctx, new_lchan); + mgcp_handover(conn->user_plane.mgcp_ctx, new_lchan); return 0; } diff --git a/src/osmo-bsc/osmo_bsc_sigtran.c b/src/osmo-bsc/osmo_bsc_sigtran.c index 5b065105f..0ffc14687 100644 --- a/src/osmo-bsc/osmo_bsc_sigtran.c +++ b/src/osmo-bsc/osmo_bsc_sigtran.c @@ -38,28 +38,26 @@ * (a copy of the pointer location submitted with osmo_bsc_sigtran_init() */ static struct llist_head *msc_list; +extern struct gsm_network *bsc_gsmnet; + #define RESET_INTERVAL 1 /* sek */ #define SCCP_MSG_MAXSIZE 1024 #define CS7_POINTCODE_DEFAULT_OFFSET 2 -/* Internal list with connections we currently maintain. This - * list is of type struct osmo_bsc_sccp_con */ -static LLIST_HEAD(active_connections); - /* The SCCP stack will not assign connection IDs to us automatically, we * will do this ourselves using a counter variable, that counts one up * for every new connection */ static uint32_t conn_id_counter; /* Helper function to Check if the given connection id is already assigned */ -static struct osmo_bsc_sccp_con *get_bsc_conn_by_conn_id(int conn_id) +static struct gsm_subscriber_connection *get_bsc_conn_by_conn_id(int conn_id) { conn_id &= 0xFFFFFF; - struct osmo_bsc_sccp_con *bsc_con; + struct gsm_subscriber_connection *conn; - llist_for_each_entry(bsc_con, &active_connections, entry) { - if (bsc_con->conn_id == conn_id) - return bsc_con; + llist_for_each_entry(conn, &bsc_gsmnet->subscr_conns, entry) { + if (conn->sccp.conn_id == conn_id) + return conn; } return NULL; @@ -131,12 +129,12 @@ static struct bsc_msc_data *get_msc_by_addr(const struct osmo_sccp_addr *msc_add /* Send data to MSC, use the connection id which MSC it is */ static int handle_data_from_msc(int conn_id, struct msgb *msg) { - struct osmo_bsc_sccp_con *bsc_con = get_bsc_conn_by_conn_id(conn_id); + struct gsm_subscriber_connection *conn = get_bsc_conn_by_conn_id(conn_id); int rc = -EINVAL; - if (bsc_con) { + if (conn) { msg->l3h = msgb_l2(msg); - rc = bsc_handle_dt(bsc_con, msg, msgb_l2len(msg)); + rc = bsc_handle_dt(conn, msg, msgb_l2len(msg)); } else LOGP(DMSC, LOGL_NOTICE, "incoming data from unknown connection id: %i\n", conn_id); @@ -168,7 +166,7 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu) { struct osmo_scu_prim *scu_prim = (struct osmo_scu_prim *)oph; struct osmo_sccp_user *scu = _scu; - struct osmo_bsc_sccp_con *bsc_con; + struct gsm_subscriber_connection *conn; int rc = 0; switch (OSMO_PRIM_HDR(&scu_prim->oph)) { @@ -187,6 +185,9 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu) case OSMO_PRIM(OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_CONFIRM): /* Handle outbound connection confirmation */ + conn = get_bsc_conn_by_conn_id(scu_prim->u.connect.conn_id); + if (conn) + conn->sccp.state = SUBSCR_SCCP_ST_CONNECTED; if (msgb_l2len(oph->msg) > 0) { DEBUGP(DMSC, "N-CONNECT.cnf(%u, %s)\n", scu_prim->u.connect.conn_id, osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg))); @@ -201,32 +202,28 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu) osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg))); /* Incoming data is a sign of a vital connection */ - bsc_con = get_bsc_conn_by_conn_id(scu_prim->u.disconnect.conn_id); - if (bsc_con) - a_reset_conn_success(bsc_con->msc->a.reset); + conn = get_bsc_conn_by_conn_id(scu_prim->u.disconnect.conn_id); + if (conn) + a_reset_conn_success(conn->sccp.msc->a.reset); rc = handle_data_from_msc(scu_prim->u.data.conn_id, oph->msg); break; case OSMO_PRIM(OSMO_SCU_PRIM_N_DISCONNECT, PRIM_OP_INDICATION): /* indication of disconnect */ + conn = get_bsc_conn_by_conn_id(scu_prim->u.disconnect.conn_id); + if (conn) + conn->sccp.state = SUBSCR_SCCP_ST_NONE; if (msgb_l2len(oph->msg) > 0) { DEBUGP(DMSC, "N-DISCONNECT.ind(%u, %s, cause=%i)\n", scu_prim->u.disconnect.conn_id, osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)), scu_prim->u.disconnect.cause); handle_data_from_msc(scu_prim->u.disconnect.conn_id, oph->msg); - } else + } else { DEBUGP(DRANAP, "N-DISCONNECT.ind(%u, cause=%i)\n", scu_prim->u.disconnect.conn_id, scu_prim->u.disconnect.cause); - - bsc_con = get_bsc_conn_by_conn_id(scu_prim->u.disconnect.conn_id); - if (bsc_con) { - /* We might have a connectivity problem. Maybe we need to go - * through the reset procedure again? */ - if (scu_prim->u.disconnect.cause == 0) - a_reset_conn_fail(bsc_con->msc->a.reset); - - rc = osmo_bsc_sigtran_del_conn(bsc_con); } + if (conn) + rc = osmo_bsc_sigtran_del_conn(conn); break; default: @@ -244,9 +241,7 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu) enum bsc_con osmo_bsc_sigtran_new_conn(struct gsm_subscriber_connection *conn, struct bsc_msc_data *msc) { struct osmo_ss7_instance *ss7; - struct osmo_bsc_sccp_con *bsc_con; struct gsm_bts *bts = conn_get_bts(conn); - int conn_id; OSMO_ASSERT(conn); OSMO_ASSERT(msc); @@ -266,30 +261,13 @@ enum bsc_con osmo_bsc_sigtran_new_conn(struct gsm_subscriber_connection *conn, s return BSC_CON_REJECT_RF_GRACE; } - bsc_con = talloc_zero(bts, struct osmo_bsc_sccp_con); - if (!bsc_con) { - LOGP(DMSC, LOGL_ERROR, "Failed to allocate new SIGTRAN connection.\n"); - return BSC_CON_NO_MEM; - } - - bsc_con->msc = msc; - bsc_con->conn = conn; - llist_add_tail(&bsc_con->entry, &active_connections); - conn->sccp_con = bsc_con; - - /* Pick a free connection id */ - conn_id = pick_free_conn_id(msc); - if (conn_id < 0) - return BSC_CON_REJECT_NO_LINK; - bsc_con->conn_id = conn_id; - - LOGP(DMSC, LOGL_NOTICE, "Allocated new connection id: %i\n", conn_id); + conn->sccp.msc = msc; return BSC_CON_SUCCESS; } /* Open a new connection oriented sigtran connection */ -int osmo_bsc_sigtran_open_conn(const struct osmo_bsc_sccp_con *conn, struct msgb *msg) +int osmo_bsc_sigtran_open_conn(struct gsm_subscriber_connection *conn, struct msgb *msg) { struct osmo_ss7_instance *ss7; struct bsc_msc_data *msc; @@ -298,16 +276,22 @@ int osmo_bsc_sigtran_open_conn(const struct osmo_bsc_sccp_con *conn, struct msgb OSMO_ASSERT(conn); OSMO_ASSERT(msg); - OSMO_ASSERT(conn->msc); + OSMO_ASSERT(conn->sccp.msc); + OSMO_ASSERT(conn->sccp.conn_id == -1); - msc = conn->msc; + msc = conn->sccp.msc; if (a_reset_conn_ready(msc->a.reset) == false) { LOGP(DMSC, LOGL_ERROR, "MSC is not connected. Dropping.\n"); return -EINVAL; } - conn_id = conn->conn_id; + conn->sccp.conn_id = conn_id = pick_free_conn_id(msc); + if (conn->sccp.conn_id < 0) { + LOGP(DMSC, LOGL_ERROR, "Unable to allocate SCCP Connection ID\n"); + return -1; + } + LOGP(DMSC, LOGL_DEBUG, "Allocated new connection id: %d\n", conn->sccp.conn_id); ss7 = osmo_ss7_instance_find(msc->a.cs7_instance); OSMO_ASSERT(ss7); LOGP(DMSC, LOGL_NOTICE, "Opening new SIGTRAN connection (id=%i) to MSC: %s\n", conn_id, @@ -315,12 +299,14 @@ int osmo_bsc_sigtran_open_conn(const struct osmo_bsc_sccp_con *conn, struct msgb rc = osmo_sccp_tx_conn_req_msg(msc->a.sccp_user, conn_id, &msc->a.bsc_addr, &msc->a.msc_addr, msg); + if (rc >= 0) + conn->sccp.state = SUBSCR_SCCP_ST_WAIT_CONN_CONF; return rc; } /* Send data to MSC */ -int osmo_bsc_sigtran_send(const struct osmo_bsc_sccp_con *conn, struct msgb *msg) +int osmo_bsc_sigtran_send(struct gsm_subscriber_connection *conn, struct msgb *msg) { struct osmo_ss7_instance *ss7; int conn_id; @@ -329,9 +315,9 @@ int osmo_bsc_sigtran_send(const struct osmo_bsc_sccp_con *conn, struct msgb *msg OSMO_ASSERT(conn); OSMO_ASSERT(msg); - OSMO_ASSERT(conn->msc); + OSMO_ASSERT(conn->sccp.msc); - msc = conn->msc; + msc = conn->sccp.msc; /* Log the type of the message we are sending. This is just * informative, do not stop if detecting the type fails */ @@ -354,7 +340,7 @@ int osmo_bsc_sigtran_send(const struct osmo_bsc_sccp_con *conn, struct msgb *msg return -EINVAL; } - conn_id = conn->conn_id; + conn_id = conn->sccp.conn_id; ss7 = osmo_ss7_instance_find(msc->a.cs7_instance); OSMO_ASSERT(ss7); @@ -369,80 +355,66 @@ int osmo_bsc_sigtran_send(const struct osmo_bsc_sccp_con *conn, struct msgb *msg /* Delete a connection from the list with open connections * (called by osmo_bsc_api.c on failing open connections and * locally, when a connection is closed by the MSC */ -int osmo_bsc_sigtran_del_conn(struct osmo_bsc_sccp_con *conn) +int osmo_bsc_sigtran_del_conn(struct gsm_subscriber_connection *conn) { if (!conn) return 0; - if (conn->conn) { - LOGP(DMSC, LOGL_ERROR, - "sccp connection (id=%i) not cleared (gsm subscriber connection still active) -- forcefully clearing it now!\n", - conn->conn_id); - bsc_subscr_con_free(conn->conn); - conn->conn = NULL; + LOGP(DMSC, LOGL_ERROR, + "sccp connection (id=%i) not cleared (gsm subscriber connection still active) -- forcefully clearing it now!\n", conn->sccp.conn_id); - /* This bahaviour might be caused by a bad connection. Maybe we - * will have to go through the reset procedure again */ - a_reset_conn_fail(conn->msc->a.reset); - } + /* This bahaviour might be caused by a bad connection. Maybe we + * will have to go through the reset procedure again */ + a_reset_conn_fail(conn->sccp.msc->a.reset); /* Remove mgcp context if existant */ if (conn->user_plane.mgcp_ctx) mgcp_free_ctx(conn->user_plane.mgcp_ctx); - llist_del(&conn->entry); - talloc_free(conn); + /* free the "conn" and make sure any pending lchans are also free'd */ + bsc_subscr_con_free(conn); return 0; } /* Send an USSD notification in case we loose the connection to the MSC */ -static void bsc_notify_msc_lost(const struct osmo_bsc_sccp_con *conn) +static void bsc_notify_msc_lost(struct gsm_subscriber_connection *conn) { - struct gsm_subscriber_connection *subscr_conn; - /* Check if sccp conn is still present */ if (!conn) return; - subscr_conn = conn->conn; - - /* send USSD notification if string configured and conn->data is set */ - if (!subscr_conn) - return; /* check for config string */ - if (!conn->msc->ussd_msc_lost_txt) + if (!conn->sccp.msc->ussd_msc_lost_txt) return; - if (conn->msc->ussd_msc_lost_txt[0] == '\0') + if (conn->sccp.msc->ussd_msc_lost_txt[0] == '\0') return; /* send USSD notification */ - bsc_send_ussd_notify(subscr_conn, 1, subscr_conn->sccp_con->msc->ussd_msc_lost_txt); - bsc_send_ussd_release_complete(subscr_conn); + bsc_send_ussd_notify(conn, 1, conn->sccp.msc->ussd_msc_lost_txt); + bsc_send_ussd_release_complete(conn); } /* Close all open sigtran connections and channels */ void osmo_bsc_sigtran_reset(const struct bsc_msc_data *msc) { - struct osmo_bsc_sccp_con *conn; - struct osmo_bsc_sccp_con *conn_temp; + struct gsm_subscriber_connection *conn, *conn_temp; OSMO_ASSERT(msc); /* Close all open connections */ - llist_for_each_entry_safe(conn, conn_temp, &active_connections, entry) { + llist_for_each_entry_safe(conn, conn_temp, &bsc_gsmnet->subscr_conns, entry) { /* We only may close connections which actually belong to this * MSC. All other open connections are left untouched */ - if (conn->msc == msc) { + if (conn->sccp.msc == msc) { /* Notify active connection users via USSD that the MSC is down */ bsc_notify_msc_lost(conn); /* Take down all occopied RF channels */ - if (conn->conn) - gsm0808_clear(conn->conn); + gsm0808_clear(conn); /* Disconnect all Sigtran connections */ - osmo_sccp_tx_disconn(msc->a.sccp_user, conn->conn_id, &msc->a.bsc_addr, 0); + osmo_sccp_tx_disconn(msc->a.sccp_user, conn->sccp.conn_id, &msc->a.bsc_addr, 0); /* Delete subscriber connection */ osmo_bsc_sigtran_del_conn(conn); diff --git a/tests/bsc/bsc_test.c b/tests/bsc/bsc_test.c index 19bb608e0..9c35d2f60 100644 --- a/tests/bsc/bsc_test.c +++ b/tests/bsc/bsc_test.c @@ -124,17 +124,14 @@ static void test_scan(void) struct gsm_network *net = bsc_network_init(NULL, 1, 1); struct gsm_bts *bts = gsm_bts_alloc(net, 0); - struct osmo_bsc_sccp_con *sccp_con; struct bsc_msc_data *msc; struct gsm_subscriber_connection *conn; - sccp_con = talloc_zero(net, struct osmo_bsc_sccp_con); msc = talloc_zero(net, struct bsc_msc_data); conn = talloc_zero(net, struct gsm_subscriber_connection); bts->network = net; - sccp_con->msc = msc; - conn->sccp_con = sccp_con; + conn->sccp.msc = msc; conn->lchan = &bts->c0->ts[1].lchan[0]; /* start testing with proper messages */ diff --git a/tests/bssap/bssap_test.c b/tests/bssap/bssap_test.c index 861c98fa8..ad8974f73 100644 --- a/tests/bssap/bssap_test.c +++ b/tests/bssap/bssap_test.c @@ -80,22 +80,23 @@ struct { }, }; +struct gsm_network *bsc_gsmnet; + void test_cell_identifier() { int i; int rc; - struct gsm_network *net; struct bsc_msc_data *msc; struct gsm_bts *bts; - net = bsc_network_init(NULL, 1, 1); - net->bsc_data->rf_ctrl = talloc_zero(NULL, struct osmo_bsc_rf); - net->bsc_data->rf_ctrl->policy = S_RF_ON; + bsc_gsmnet = bsc_network_init(NULL, 1, 1); + bsc_gsmnet->bsc_data->rf_ctrl = talloc_zero(NULL, struct osmo_bsc_rf); + bsc_gsmnet->bsc_data->rf_ctrl->policy = S_RF_ON; - msc = talloc_zero(net, struct bsc_msc_data); - msc->network = net; + msc = talloc_zero(bsc_gsmnet, struct bsc_msc_data); + msc->network = bsc_gsmnet; - bts = gsm_bts_alloc_register(net, GSM_BTS_TYPE_UNKNOWN, 0); + bts = gsm_bts_alloc_register(bsc_gsmnet, GSM_BTS_TYPE_UNKNOWN, 0); if (bts == NULL) { fprintf(stderr, "gsm_bts_alloc_register() returned NULL\n"); return; -- cgit v1.2.3