aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 05e04906e..874150535 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 78f9710c5..32e0a4e96 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 7f38be28e..eea073614 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 7ff44075c..6abb0d832 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 452de62d5..31b72b925 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 440e1803c..ab0d9eb0b 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;