From 02d39b2c4d3f67ef760b230d95cb1e6d7c07e8f7 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 5 Jul 2010 15:34:16 +0800 Subject: msc: Create a dummy operation to keep the channel open for five seconds * We should create the transaction for SMS, CC on the CM Service Request but for now we will use a band aid and create a dummy operarion to wait five seconds for the transaction to be opened. --- openbsc/include/openbsc/gsm_04_08.h | 1 + openbsc/include/openbsc/gsm_data.h | 9 +++++++++ openbsc/src/gsm_04_08.c | 39 +++++++++++++++++++++++++++++++++++++ openbsc/src/osmo_msc.c | 3 ++- 4 files changed, 51 insertions(+), 1 deletion(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index 33da5e5a5..aa070eb0a 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -28,6 +28,7 @@ void gsm0408_clear_request(struct gsm_subscriber_connection *conn, uint32_t caus int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg); int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id); +int gsm0408_new_conn(struct gsm_subscriber_connection *conn); enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci); enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci); diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index e03ad3a78..36591cffa 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -179,6 +179,14 @@ struct gsm_security_operation { void *cb_data; }; +/* + * A dummy to keep a connection up for at least + * a couple of seconds to work around MSC issues. + */ +struct gsm_anchor_operation { + struct timer_list timeout; +}; + /* Maximum number of neighbor cells whose average we track */ #define MAX_NEIGH_MEAS 10 /* Maximum size of the averaging window for neighbor cells */ @@ -224,6 +232,7 @@ struct gsm_subscriber_connection { */ struct gsm_loc_updating_operation *loc_operation; struct gsm_security_operation *sec_operation; + struct gsm_anchor_operation *anch_operation; /* Are we part of a special "silent" call */ int silent_call; diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index 7bf30e798..e10177d6d 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -63,6 +63,7 @@ int gsm0408_loc_upd_acc(struct gsm_subscriber_connection *conn, u_int32_t tmsi); static int gsm48_tx_simple(struct gsm_subscriber_connection *conn, u_int8_t pdisc, u_int8_t msg_type); static void schedule_reject(struct gsm_subscriber_connection *conn); +static void release_anchor(struct gsm_subscriber_connection *conn); struct gsm_lai { u_int16_t mcc; @@ -218,6 +219,9 @@ static void release_loc_updating_req(struct gsm_subscriber_connection *conn) if (!conn->loc_operation) return; + /* No need to keep the connection up */ + release_anchor(conn); + bsc_del_timer(&conn->loc_operation->updating_timer); talloc_free(conn->loc_operation); conn->loc_operation = 0; @@ -294,6 +298,7 @@ void gsm0408_clear_request(struct gsm_subscriber_connection* conn, uint32_t caus */ release_loc_updating_req(conn); release_security_operation(conn); + release_anchor(conn); /* Free all transactions that are associated with the released lchan */ /* FIXME: this is not neccessarily the right thing to do, we should @@ -3076,6 +3081,37 @@ static int gsm0408_rcv_cc(struct gsm_subscriber_connection *conn, struct msgb *m return rc; } +/* Create a dummy to wait five seconds */ +static void release_anchor(struct gsm_subscriber_connection *conn) +{ + if (!conn->anch_operation) + return; + + bsc_del_timer(&conn->anch_operation->timeout); + talloc_free(conn->anch_operation); + conn->anch_operation = NULL; +} + +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) +{ + conn->anch_operation = talloc_zero(conn, struct gsm_anchor_operation); + if (!conn->anch_operation) + return -1; + + conn->anch_operation->timeout.data = conn; + conn->anch_operation->timeout.cb = anchor_timeout; + bsc_schedule_timer(&conn->anch_operation->timeout, 5, 0); + return 0; +} + /* here we get data from the BSC level... */ int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg) { @@ -3088,6 +3124,7 @@ int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg) switch (pdisc) { case GSM48_PDISC_CC: + release_anchor(conn); rc = gsm0408_rcv_cc(conn, msg); break; case GSM48_PDISC_MM: @@ -3097,6 +3134,7 @@ int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg) rc = gsm0408_rcv_rr(conn, msg); break; case GSM48_PDISC_SMS: + release_anchor(conn); rc = gsm0411_rcv_sms(conn, msg); break; case GSM48_PDISC_MM_GPRS: @@ -3105,6 +3143,7 @@ int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg) "GSM 04.08 discriminator 0x%02x\n", pdisc); break; case GSM48_PDISC_NC_SS: + release_anchor(conn); rc = handle_rcv_ussd(conn, msg); break; default: diff --git a/openbsc/src/osmo_msc.c b/openbsc/src/osmo_msc.c index 6a94e7abb..6543a61dc 100644 --- a/openbsc/src/osmo_msc.c +++ b/openbsc/src/osmo_msc.c @@ -44,6 +44,7 @@ static void msc_clear_request(struct gsm_subscriber_connection* conn, uint32_t c static int msc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg, uint16_t chosen_channel) { + gsm0408_new_conn(conn); gsm0408_dispatch(conn, msg); /* TODO: do better */ @@ -80,7 +81,7 @@ void msc_release_connection(struct gsm_subscriber_connection *conn) return; /* check if there is a pending operation */ - if (conn->loc_operation || conn->sec_operation) + if (conn->loc_operation || conn->sec_operation || conn->anch_operation) return; llist_for_each_entry(trans, &conn->bts->network->trans_list, entry) { -- cgit v1.2.3