[PATCH] openbsc[master]: Introduce subscriber_connection ref-counting

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/.

Neels Hofmeyr gerrit-no-reply at lists.osmocom.org
Thu Jan 26 00:52:37 UTC 2017


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

Introduce subscriber_connection ref-counting

This introduces a reference count for gsm_subscriber_connection. Every
user of the connection needs to hold a reference until done.  Once the
reference count dorps to zero, the connection is cleared towards the
BSC (which subsequently will clear any logical channels associated with
it).

Related: OS#1592
Change-Id: I8c05e6c81f246ff8b5bf91312f80410b1a85f15e
---
M openbsc/include/openbsc/gsm_data.h
M openbsc/include/openbsc/osmo_msc.h
M openbsc/src/libmsc/gsm_04_08.c
M openbsc/src/libmsc/gsm_04_11.c
M openbsc/src/libmsc/osmo_msc.c
M openbsc/src/libmsc/silent_call.c
M openbsc/src/libmsc/transaction.c
M openbsc/src/libmsc/ussd.c
8 files changed, 64 insertions(+), 20 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/openbsc refs/changes/81/1681/1

diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index ac573c4..d477284 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -106,8 +106,13 @@
 
 /* active radio connection of a mobile subscriber */
 struct gsm_subscriber_connection {
+	/* global linked list of subscriber_connections */
 	struct llist_head entry;
 
+	/* usage count. If this drops to zero, we start the release
+	 * towards A/Iu */
+	uint32_t use_count;
+
 	/* To whom we are allocated at the moment */
 	struct gsm_subscriber *subscr;
 
diff --git a/openbsc/include/openbsc/osmo_msc.h b/openbsc/include/openbsc/osmo_msc.h
index beb3f5e..8f57ce2 100644
--- a/openbsc/include/openbsc/osmo_msc.h
+++ b/openbsc/include/openbsc/osmo_msc.h
@@ -6,6 +6,7 @@
 #include "bsc_api.h"
 
 struct bsc_api *msc_bsc_api();
-void msc_release_connection(struct gsm_subscriber_connection *conn);
+struct gsm_subscriber_connection *subscr_con_get(struct gsm_subscriber_connection *conn);
+void subscr_con_put(struct gsm_subscriber_connection *conn);
 
 #endif
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index 8380710..b37ef60 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -176,13 +176,15 @@
 
 	talloc_free(conn->sec_operation);
 	conn->sec_operation = NULL;
-	msc_release_connection(conn);
+	subscr_con_put(conn);
 }
 
 void allocate_security_operation(struct gsm_subscriber_connection *conn)
 {
 	conn->sec_operation = talloc_zero(tall_authciphop_ctx,
 	                                  struct gsm_security_operation);
+	if (conn->sec_operation)
+		subscr_con_get(conn);
 }
 
 int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq,
@@ -305,8 +307,7 @@
 	osmo_timer_del(&conn->loc_operation->updating_timer);
 	talloc_free(conn->loc_operation);
 	conn->loc_operation = NULL;
-	if (release)
-		msc_release_connection(conn);
+	subscr_con_put(conn);
 }
 
 static void allocate_loc_updating_req(struct gsm_subscriber_connection *conn)
@@ -317,6 +318,8 @@
 
 	conn->loc_operation = talloc_zero(tall_locop_ctx,
 					   struct gsm_loc_updating_operation);
+	if (conn->loc_operation)
+		subscr_con_get(conn);
 }
 
 static int finish_lu(struct gsm_subscriber_connection *conn)
@@ -3487,7 +3490,7 @@
 			return 0;
 		}
 		/* Assign lchan */
-		trans->conn = conn;
+		trans->conn = subscr_con_get(conn);
 		subscr_put(subscr);
 	} else {
 		/* update the subscriber we deal with */
@@ -3636,7 +3639,7 @@
 			return -ENOMEM;
 		}
 		/* Assign transaction */
-		trans->conn = conn;
+		trans->conn = subscr_con_get(conn);
 	}
 
 	/* find function for current state and message */
@@ -3665,6 +3668,7 @@
 	osmo_timer_del(&conn->anch_operation->timeout);
 	talloc_free(conn->anch_operation);
 	conn->anch_operation = NULL;
+	subscr_con_put(conn);
 }
 
 static void anchor_timeout(void *_data)
@@ -3672,7 +3676,6 @@
 	struct gsm_subscriber_connection *con = _data;
 
 	release_anchor(con);
-	msc_release_connection(con);
 }
 
 int gsm0408_new_conn(struct gsm_subscriber_connection *conn)
@@ -3681,6 +3684,7 @@
 	if (!conn->anch_operation)
 		return -1;
 
+	subscr_con_get(conn);
 	conn->anch_operation->timeout.data = conn;
 	conn->anch_operation->timeout.cb = anchor_timeout;
 	osmo_timer_schedule(&conn->anch_operation->timeout, 5, 0);
diff --git a/openbsc/src/libmsc/gsm_04_11.c b/openbsc/src/libmsc/gsm_04_11.c
index 6164a08..e395cd4 100644
--- a/openbsc/src/libmsc/gsm_04_11.c
+++ b/openbsc/src/libmsc/gsm_04_11.c
@@ -56,6 +56,7 @@
 #include <openbsc/bsc_rll.h>
 #include <openbsc/chan_alloc.h>
 #include <openbsc/bsc_api.h>
+#include <openbsc/osmo_msc.h>
 
 #ifdef BUILD_SMPP
 #include "smpp_smsc.h"
@@ -831,7 +832,7 @@
 		gsm411_smr_init(&trans->sms.smr_inst, 0, 1,
 			gsm411_rl_recv, gsm411_mn_send);
 
-		trans->conn = conn;
+		trans->conn = subscr_con_get(conn);
 
 		new_trans = 1;
 	}
@@ -910,7 +911,7 @@
 		gsm411_rl_recv, gsm411_mn_send);
 	trans->sms.sms = sms;
 
-	trans->conn = conn;
+	trans->conn = subscr_con_get(conn);
 
 	/* Hardcode SMSC Originating Address for now */
 	data = (uint8_t *)msgb_put(msg, 8);
diff --git a/openbsc/src/libmsc/osmo_msc.c b/openbsc/src/libmsc/osmo_msc.c
index 2389980..92bc846 100644
--- a/openbsc/src/libmsc/osmo_msc.c
+++ b/openbsc/src/libmsc/osmo_msc.c
@@ -144,22 +144,21 @@
 }
 
 /* lchan release handling */
-void msc_release_connection(struct gsm_subscriber_connection *conn)
+static void msc_release_connection(struct gsm_subscriber_connection *conn)
 {
 	/* skip when we are in release, e.g. due an error */
 	if (conn->in_release)
 		return;
 
-	/* skip releasing of silent calls as they have no transaction */
 	if (conn->silent_call)
-		return;
+		LOGP(DMSC, LOGL_ERROR, "release_connection() but silent_call active?!?\n");
 
 	/* check if there is a pending operation */
 	if (conn->loc_operation || conn->sec_operation || conn->anch_operation)
-		return;
+		LOGP(DMSC, LOGL_ERROR, "relase_connection() but {loc,sec,anch}_operation alive?!?\n");
 
 	if (trans_has_conn(conn))
-		return;
+		LOGP(DMSC, LOGL_ERROR, "release_conncetion() but transactions alive?!?\n");
 
 	/* no more connections, asking to release the channel */
 
@@ -175,3 +174,35 @@
 	gsm0808_clear(conn);
 	msc_subscr_con_free(conn);
 }
+
+/* increment the ref-count. Needs to be called by every user */
+struct gsm_subscriber_connection *subscr_con_get(struct gsm_subscriber_connection *conn)
+{
+	OSMO_ASSERT(conn);
+
+	if (conn->in_release)
+		return NULL;
+
+	conn->use_count++;
+	DEBUGP(DMSC, "increased subscr_con use_count to %u\n", conn->use_count);
+
+	return conn;
+}
+
+/* decrement the ref-count. Once it reaches zero, we release */
+void subscr_con_put(struct gsm_subscriber_connection *conn)
+{
+	OSMO_ASSERT(conn);
+
+	if (conn->use_count == 0) {
+		LOGP(DMSC, LOGL_ERROR, "tryin to decrement conn use count, but is alrady 0\n");
+		return;
+	}
+
+	conn->use_count--;
+	DEBUGP(DMSC, "decreased subscr_con use_count to %u\n", conn->use_count);
+
+	if (conn->use_count == 0) {
+		msc_release_connection(conn);
+	}
+}
diff --git a/openbsc/src/libmsc/silent_call.c b/openbsc/src/libmsc/silent_call.c
index 131a178..b5b4813 100644
--- a/openbsc/src/libmsc/silent_call.c
+++ b/openbsc/src/libmsc/silent_call.c
@@ -55,6 +55,7 @@
 		DEBUGPC(DLSMS, "success, using Timeslot %u on ARFCN %u\n",
 			conn->lchan->ts->nr, conn->lchan->ts->trx->arfcn);
 		conn->silent_call = 1;
+		subscr_con_get(conn);
 		/* increment lchan reference count */
 		osmo_signal_dispatch(SS_SCALL, S_SCALL_SUCCESS, &sigdata);
 		break;
@@ -142,7 +143,7 @@
 		conn->lchan->ts->nr, conn->lchan->ts->trx->arfcn);
 
 	conn->silent_call = 0;
-	msc_release_connection(conn);
+	subscr_con_put(conn);
 
 	return 0;
 }
diff --git a/openbsc/src/libmsc/transaction.c b/openbsc/src/libmsc/transaction.c
index dba4bed..4d0cdb1 100644
--- a/openbsc/src/libmsc/transaction.c
+++ b/openbsc/src/libmsc/transaction.c
@@ -111,7 +111,7 @@
 	llist_del(&trans->entry);
 
 	if (trans->conn)
-		msc_release_connection(trans->conn);
+		subscr_con_put(trans->conn);
 
 	trans->conn = NULL;
 	talloc_free(trans);
diff --git a/openbsc/src/libmsc/ussd.c b/openbsc/src/libmsc/ussd.c
index f12c1f2..a27b163 100644
--- a/openbsc/src/libmsc/ussd.c
+++ b/openbsc/src/libmsc/ussd.c
@@ -48,13 +48,17 @@
 	struct ss_request req;
 	struct gsm48_hdr *gh;
 
+	/* TODO: Use subscriber_connection ref-counting if we ever want
+	 * to keep the connection alive due ot ongoing USSD exchange.
+	 * As we answer everytying synchronously so far, there's no need
+	 * yet */
+
 	memset(&req, 0, sizeof(req));
 	gh = msgb_l3(msg);
 	rc = gsm0480_decode_ss_request(gh, msgb_l3len(msg), &req);
 	if (!rc) {
 		DEBUGP(DMM, "Unhandled SS\n");
 		rc = gsm0480_send_ussd_reject(conn, msg, &req);
-		msc_release_connection(conn);
 		return rc;
 	}
 
@@ -63,7 +67,6 @@
 		if (req.ss_code > 0) {
 			/* Assume interrogateSS or modification of it and reject */
 			rc = gsm0480_send_ussd_reject(conn, msg, &req);
-			msc_release_connection(conn);
 			return rc;
 		}
 		/* Still assuming a Release-Complete and returning */
@@ -78,8 +81,6 @@
 		rc = gsm0480_send_ussd_reject(conn, msg, &req);
 	}
 
-	/* check if we can release it */
-	msc_release_connection(conn);
 	return rc;
 }
 

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I8c05e6c81f246ff8b5bf91312f80410b1a85f15e
Gerrit-PatchSet: 1
Gerrit-Project: openbsc
Gerrit-Branch: master
Gerrit-Owner: Neels Hofmeyr <nhofmeyr at sysmocom.de>



More information about the gerrit-log mailing list