mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-10-23 08:12:01 +00:00
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
This commit is contained in:
committed by
Neels Hofmeyr
parent
7564acac24
commit
e005619dc6
@@ -115,8 +115,13 @@ enum ran_type {
|
||||
|
||||
/* 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;
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -176,13 +176,15 @@ void release_security_operation(struct gsm_subscriber_connection *conn)
|
||||
|
||||
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,
|
||||
@@ -306,8 +308,7 @@ static void release_loc_updating_req(struct gsm_subscriber_connection *conn, int
|
||||
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)
|
||||
@@ -318,6 +319,8 @@ static void allocate_loc_updating_req(struct gsm_subscriber_connection *conn)
|
||||
|
||||
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)
|
||||
@@ -3743,7 +3746,7 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg)
|
||||
return 0;
|
||||
}
|
||||
/* Assign lchan */
|
||||
trans->conn = conn;
|
||||
trans->conn = subscr_con_get(conn);
|
||||
subscr_put(subscr);
|
||||
} else {
|
||||
/* update the subscriber we deal with */
|
||||
@@ -3892,7 +3895,7 @@ static int gsm0408_rcv_cc(struct gsm_subscriber_connection *conn, struct msgb *m
|
||||
return -ENOMEM;
|
||||
}
|
||||
/* Assign transaction */
|
||||
trans->conn = conn;
|
||||
trans->conn = subscr_con_get(conn);
|
||||
}
|
||||
|
||||
/* find function for current state and message */
|
||||
@@ -3921,6 +3924,7 @@ static void release_anchor(struct gsm_subscriber_connection *conn)
|
||||
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)
|
||||
@@ -3928,7 +3932,6 @@ static void anchor_timeout(void *_data)
|
||||
struct gsm_subscriber_connection *con = _data;
|
||||
|
||||
release_anchor(con);
|
||||
msc_release_connection(con);
|
||||
}
|
||||
|
||||
int gsm0408_new_conn(struct gsm_subscriber_connection *conn)
|
||||
@@ -3937,6 +3940,7 @@ int gsm0408_new_conn(struct gsm_subscriber_connection *conn)
|
||||
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);
|
||||
|
@@ -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 @@ int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn,
|
||||
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 @@ int gsm411_send_sms(struct gsm_subscriber_connection *conn, struct gsm_sms *sms)
|
||||
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);
|
||||
|
@@ -144,22 +144,21 @@ struct bsc_api *msc_bsc_api() {
|
||||
}
|
||||
|
||||
/* 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 @@ void msc_release_connection(struct gsm_subscriber_connection *conn)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@@ -55,6 +55,7 @@ static int paging_cb_silent(unsigned int hooknum, unsigned int event,
|
||||
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;
|
||||
@@ -146,7 +147,7 @@ int gsm_silent_call_stop(struct gsm_subscriber *subscr)
|
||||
conn->lchan->ts->nr, conn->lchan->ts->trx->arfcn);
|
||||
|
||||
conn->silent_call = 0;
|
||||
msc_release_connection(conn);
|
||||
subscr_con_put(conn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -111,7 +111,7 @@ void trans_free(struct gsm_trans *trans)
|
||||
llist_del(&trans->entry);
|
||||
|
||||
if (trans->conn)
|
||||
msc_release_connection(trans->conn);
|
||||
subscr_con_put(trans->conn);
|
||||
|
||||
trans->conn = NULL;
|
||||
talloc_free(trans);
|
||||
|
@@ -48,13 +48,17 @@ int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
||||
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 @@ int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
||||
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 @@ int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
||||
rc = gsm0480_send_ussd_reject(conn, msg, &req);
|
||||
}
|
||||
|
||||
/* check if we can release it */
|
||||
msc_release_connection(conn);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user