summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-06-30 15:30:47 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-07-27 21:39:13 +0200
commite7bd863f763809b152fb21655abe7e8bba557561 (patch)
treedd6b2a11d9aeec000ebbbb44ed178d4a0dfd0970
parentb97089432f43505329b57630c5520d555ec998d1 (diff)
expiration: Speculative fixes for the periodic expiring handling
We were expiring subscribers during active calls. This is because the T3212 is stopped under certain conditions but we didn't stop that timer at all. Remember if T3212 timer was stopped due something done by NITB and update the expiration time at the end of the radio connection, as the phone should restart it when returning to MM Idle. It is a bit difficult to decide when we should set the flag. E.g. in a CM Service Request we don't know if we accept the service and during a LU we already send MM messages before we accept or reject the subscriber. The easiest is to set the flag when receiving a paging response on known subscribers and at the end of the authentication process. Do not expire a subscriber that has an active connection that is marked with the flag, e.g. we would still expire a subscriber that is being paged. Manual tests executed/passed: * gst LUTest.st verified that a expiration date was set * gst SMSTest.st (doing another LU but forcing a timeout on the SMS sending). Verified that the expire_lu was updated.
-rw-r--r--openbsc/include/openbsc/gsm_data.h3
-rw-r--r--openbsc/include/openbsc/gsm_subscriber.h1
-rw-r--r--openbsc/src/libmsc/gsm_04_08.c9
-rw-r--r--openbsc/src/libmsc/gsm_subscriber.c58
-rw-r--r--openbsc/src/libmsc/osmo_msc.c11
-rw-r--r--openbsc/tests/channel/channel_test.c1
6 files changed, 66 insertions, 17 deletions
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 05e0490..8741505 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -104,6 +104,9 @@ struct gsm_subscriber_connection {
/* To whom we are allocated at the moment */
struct gsm_subscriber *subscr;
+ /* LU expiration handling */
+ uint8_t expire_timer_stopped;
+
/*
* Operations that have a state and might be pending
*/
diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h
index 78f9710..32e0a4e 100644
--- a/openbsc/include/openbsc/gsm_subscriber.h
+++ b/openbsc/include/openbsc/gsm_subscriber.h
@@ -100,6 +100,7 @@ char *subscr_name(struct gsm_subscriber *subscr);
int subscr_purge_inactive(struct gsm_network *net);
void subscr_update_from_db(struct gsm_subscriber *subscr);
void subscr_expire(struct gsm_network *net);
+int subscr_update_expire_lu(struct gsm_subscriber *subscr, struct gsm_bts *bts);
/* internal */
struct gsm_subscriber *subscr_alloc(void);
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index 7f38be2..eea0736 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -829,6 +829,9 @@ static int _gsm48_rx_mm_serv_req_sec_cb(
struct gsm_subscriber_connection *conn = data;
int rc = 0;
+ /* auth failed or succeeded, the timer was stopped */
+ conn->expire_timer_stopped = 1;
+
switch (event) {
case GSM_SECURITY_AUTH_FAILED:
/* Nothing to do */
@@ -930,6 +933,9 @@ static int gsm48_rx_mm_serv_req(struct gsm_subscriber_connection *conn, struct m
memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
db_sync_equipment(&subscr->equipment);
+ /* we will send a MM message soon */
+ conn->expire_timer_stopped = 1;
+
return gsm48_secure_channel(conn, req->cipher_key_seq,
_gsm48_rx_mm_serv_req_sec_cb, NULL);
}
@@ -1123,6 +1129,9 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m
memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv);
db_sync_equipment(&subscr->equipment);
+ /* We received a paging */
+ conn->expire_timer_stopped = 1;
+
rc = gsm48_handle_paging_resp(conn, msg, subscr);
return rc;
}
diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c
index 7ff4407..6abb0d8 100644
--- a/openbsc/src/libmsc/gsm_subscriber.c
+++ b/openbsc/src/libmsc/gsm_subscriber.c
@@ -1,7 +1,7 @@
/* The concept of a subscriber for the MSC, roughly HLR/VLR functionality */
/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009,2013 by Holger Hans Peter Freyther <zecke@selfish.org>
*
* All Rights Reserved
*
@@ -37,6 +37,7 @@
#include <openbsc/paging.h>
#include <openbsc/signal.h>
#include <openbsc/db.h>
+#include <openbsc/chan_alloc.h>
void *tall_sub_req_ctx;
@@ -323,6 +324,21 @@ struct gsm_subscriber *subscr_get_by_id(struct gsm_network *net,
return db_get_subscriber(net, GSM_SUBSCRIBER_ID, buf);
}
+int subscr_update_expire_lu(struct gsm_subscriber *s, struct gsm_bts *bts)
+{
+ int rc;
+
+ /* Table 10.5.33: The T3212 timeout value field is coded as the
+ * binary representation of the timeout value for
+ * periodic updating in decihours. Mark the subscriber as
+ * inactive if it missed two consecutive location updates.
+ * Timeout is twice the t3212 value plus one minute */
+ s->expire_lu = time(NULL) +
+ (bts->si_common.chan_desc.t3212 * 60 * 6 * 2) + 60;
+ rc = db_sync_subscriber(s);
+ db_subscriber_update(s);
+ return rc;
+}
int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason)
{
@@ -335,24 +351,19 @@ int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason)
/* Indicate "attached to LAC" */
s->lac = bts->location_area_code;
+ LOGP(DMM, LOGL_INFO, "Subscriber %s ATTACHED LAC=%u\n",
+ subscr_name(s), s->lac);
+
/* FIXME: We should allow 0 for T3212 as well to disable the
* location update period. In that case we will need a way to
* indicate that in the database and then reenable that value in
* VTY.
*/
-
- /* Table 10.5.33: The T3212 timeout value field is coded as the
- * binary representation of the timeout value for
- * periodic updating in decihours. Mark the subscriber as
- * inactive if it missed two consecutive location updates.
- * Timeout is twice the t3212 value plus one minute */
- s->expire_lu = time(NULL) +
- (bts->si_common.chan_desc.t3212 * 60 * 6 * 2) + 60;
-
- LOGP(DMM, LOGL_INFO, "Subscriber %s ATTACHED LAC=%u\n",
- subscr_name(s), s->lac);
- rc = db_sync_subscriber(s);
- db_subscriber_update(s);
+ /*
+ * The below will set a new expire_lu but as a side-effect
+ * the new lac will be saved in the database.
+ */
+ rc = subscr_update_expire_lu(s, bts);
osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_ATTACHED, s);
break;
case GSM_SUBSCRIBER_UPDATE_DETACHED:
@@ -383,8 +394,23 @@ void subscr_update_from_db(struct gsm_subscriber *sub)
static void subscr_expire_callback(void *data, long long unsigned int id)
{
struct gsm_network *net = data;
- struct gsm_subscriber *s =
- subscr_get_by_id(net, id);
+ struct gsm_subscriber *s = subscr_get_by_id(net, id);
+ struct gsm_subscriber_connection *conn = connection_for_subscr(s);
+
+ /*
+ * The subscriber is active and the phone stopped the timer. As
+ * we don't want to periodically update the database for active
+ * subscribers we will just do it when the subscriber was selected
+ * for expiration. This way on the next around another subscriber
+ * will be selected.
+ */
+ if (conn && conn->expire_timer_stopped) {
+ LOGP(DMM, LOGL_DEBUG, "Not expiring subscriber %s (ID %llu)\n",
+ subscr_name(s), id);
+ subscr_update_expire_lu(s, conn->bts);
+ return;
+ }
+
LOGP(DMM, LOGL_NOTICE, "Expiring inactive subscriber %s (ID %llu)\n",
subscr_name(s), id);
diff --git a/openbsc/src/libmsc/osmo_msc.c b/openbsc/src/libmsc/osmo_msc.c
index 452de62..31b72b9 100644
--- a/openbsc/src/libmsc/osmo_msc.c
+++ b/openbsc/src/libmsc/osmo_msc.c
@@ -1,7 +1,7 @@
/* main MSC management code... */
/*
- * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010,2013 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2010 by On-Waves
*
* All Rights Reserved
@@ -158,6 +158,15 @@ void msc_release_connection(struct gsm_subscriber_connection *conn)
return;
/* no more connections, asking to release the channel */
+
+ /*
+ * We had stopped the LU expire timer T3212. Now we are about
+ * to send the MS back to the idle state and this should lead
+ * to restarting the timer. Set the new expiration time.
+ */
+ if (conn->expire_timer_stopped)
+ subscr_update_expire_lu(conn->subscr, conn->bts);
+
conn->in_release = 1;
gsm0808_clear(conn);
if (conn->put_channel) {
diff --git a/openbsc/tests/channel/channel_test.c b/openbsc/tests/channel/channel_test.c
index 440e180..ab0d9eb 100644
--- a/openbsc/tests/channel/channel_test.c
+++ b/openbsc/tests/channel/channel_test.c
@@ -89,6 +89,7 @@ void gsm_net_update_ctype(struct gsm_network *network) {}
void gsm48_secure_channel() {}
void paging_request_stop() {}
void vty_out() {}
+void* connection_for_subscr(void) { abort(); return NULL; }
struct tlv_definition nm_att_tlvdef;