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;