[PATCH] osmo-bsc[master]: Structural reform: Get rid of osmo_bsc_sccp_con

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

dexter gerrit-no-reply at lists.osmocom.org
Fri Feb 16 18:13:03 UTC 2018


Review at  https://gerrit.osmocom.org/6542

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
---
M include/osmocom/bsc/gsm_data.h
M include/osmocom/bsc/osmo_bsc.h
M include/osmocom/bsc/osmo_bsc_mgcp.h
M include/osmocom/bsc/osmo_bsc_sigtran.h
M src/libbsc/bsc_api.c
M src/osmo-bsc/osmo_bsc_api.c
M src/osmo-bsc/osmo_bsc_audio.c
M src/osmo-bsc/osmo_bsc_bssap.c
M src/osmo-bsc/osmo_bsc_ctrl.c
M src/osmo-bsc/osmo_bsc_filter.c
M src/osmo-bsc/osmo_bsc_mgcp.c
M src/osmo-bsc/osmo_bsc_sigtran.c
M tests/bsc/bsc_test.c
M tests/bssap/bssap_test.c
14 files changed, 218 insertions(+), 262 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/42/6542/1

diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index c730d96..04dc696 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -25,6 +25,7 @@
 #include <osmocom/gsm/protocol/gsm_12_21.h>
 #include <osmocom/abis/e1_input.h>
 #include <osmocom/bsc/meas_rep.h>
+#include <osmocom/bsc/bsc_msg_filter.h>
 
 struct mgcp_client_conf;
 struct mgcp_client;
@@ -80,6 +81,12 @@
 	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 */
@@ -87,9 +94,6 @@
 
 	/* 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 @@
 	 * 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 485c836..678ac41 100644
--- a/include/osmocom/bsc/osmo_bsc.h
+++ b/include/osmocom/bsc/osmo_bsc.h
@@ -16,59 +16,14 @@
 };
 
 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_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 dc2ba34..15039f7 100644
--- a/include/osmocom/bsc/osmo_bsc_mgcp.h
+++ b/include/osmocom/bsc/osmo_bsc_mgcp.h
@@ -43,7 +43,7 @@
 	/* 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 @@
 
 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 8964903..5cb7230 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 2cb5b10..9086719 100644
--- a/src/libbsc/bsc_api.c
+++ b/src/libbsc/bsc_api.c
@@ -32,6 +32,7 @@
 #include <osmocom/bsc/gsm_04_08_utils.h>
 #include <osmocom/bsc/bsc_subscriber.h>
 #include <osmocom/bsc/penalty_timers.h>
+#include <osmocom/bsc/osmo_bsc_sigtran.h>
 
 #include <osmocom/gsm/protocol/gsm_08_08.h>
 #include <osmocom/gsm/gsm48.h>
@@ -278,6 +279,7 @@
 	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 1caaeee..465832c 100644
--- a/src/osmo-bsc/osmo_bsc_api.c
+++ b/src/osmo-bsc/osmo_bsc_api.c
@@ -32,13 +32,13 @@
 #include <osmocom/bsc/osmo_bsc_sigtran.h>
 
 #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 @@
 	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 @@
 	}
 
 	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 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 @@
 	 * 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 @@
 	/* 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 @@
 	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,19 +469,10 @@
 
 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) {
@@ -493,7 +480,7 @@
 		return 1;
 	}
 
-	osmo_bsc_sigtran_send(sccp, resp);
+	osmo_bsc_sigtran_send(conn, resp);
 	return 1;
 }
 
@@ -515,14 +502,14 @@
 	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 ceec469..295d854 100644
--- a/src/osmo-bsc/osmo_bsc_audio.c
+++ b/src/osmo-bsc/osmo_bsc_audio.c
@@ -45,24 +45,24 @@
 		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 @@
 			/* 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 0adc001..87a2a91 100644
--- a/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/src/osmo-bsc/osmo_bsc_bssap.c
@@ -571,19 +571,15 @@
  * 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 @@
  * 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 @@
 	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 @@
 		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 @@
 
 	/* 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 @@
  *
  * 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 @@
 	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);
 
@@ -856,7 +852,8 @@
 		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 @@
 		 * 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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 
 	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 @@
 					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 fc79086..6092f23 100644
--- a/src/osmo-bsc/osmo_bsc_ctrl.c
+++ b/src/osmo-bsc/osmo_bsc_ctrl.c
@@ -570,10 +570,7 @@
 
 	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 5399b7a..c1f3e80 100644
--- a/src/osmo-bsc/osmo_bsc_filter.c
+++ b/src/osmo-bsc/osmo_bsc_filter.c
@@ -54,7 +54,7 @@
 
 	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 @@
 
 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 @@
 
 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 @@
 
 	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 @@
 			}
 		}
 
-		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 bdf2dd2..4b6420e 100644
--- a/src/osmo-bsc/osmo_bsc_mgcp.c
+++ b/src/osmo-bsc/osmo_bsc_mgcp.c
@@ -151,7 +151,7 @@
 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 @@
 	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 @@
 {
 	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 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 @@
 		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 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 @@
 		.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 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 @@
 		.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 @@
 {
 	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 @@
  * 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 @@
 	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 @@
  * 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 @@
 		.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 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 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 @@
  * 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 @@
 	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 @@
  * 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 @@
 		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 5b06510..0ffc146 100644
--- a/src/osmo-bsc/osmo_bsc_sigtran.c
+++ b/src/osmo-bsc/osmo_bsc_sigtran.c
@@ -38,13 +38,11 @@
  * (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
@@ -52,14 +50,14 @@
 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 @@
 /* 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 @@
 {
 	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 @@
 
 	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 @@
 		       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 @@
 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 @@
 		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 @@
 
 	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 @@
 
 	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 @@
 
 	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 @@
 		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 @@
 /* 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 19bb608..9c35d2f 100644
--- a/tests/bsc/bsc_test.c
+++ b/tests/bsc/bsc_test.c
@@ -124,17 +124,14 @@
 
 	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 861c98f..ad8974f 100644
--- a/tests/bssap/bssap_test.c
+++ b/tests/bssap/bssap_test.c
@@ -80,22 +80,23 @@
 	},
 };
 
+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;

-- 
To view, visit https://gerrit.osmocom.org/6542
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Idd2b733477ee90d24dec369755a00f1c39c93f39
Gerrit-PatchSet: 1
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Owner: dexter <pmaier at sysmocom.de>



More information about the gerrit-log mailing list