summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-07-27 21:07:57 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-07-27 22:02:24 +0200
commitc63f6f1f324baaff41f8ea543f32479a09a71cd0 (patch)
tree58601ec5ddd1c3f8ec24d43b911b327d7a12df0e
parente7bd863f763809b152fb21655abe7e8bba557561 (diff)
expiration: Allow to disable the periodic location updating procedure
Disable the periodic LU using "no periodic location update" VTY command. In that case set the expire_lu to 0 which will then be translated to a NULL in the database layer. This leads to a bit of copy and paste in the db_sync_subscriber method but I don't see how we could easily use 'datetime(%i, 'unixepoch')' and 'NULL' at the same time. Change the query to find expired queries to check for NOT NULL and the time being in the past. This means if there are still old subscribers in the database they might not be expired. One would need to execute a query like "UPATE Subscriber SET expire_lu = 0 WHERE expire_lu is null". The same applies when disabling the periodic LU. One would need to update the database by hand. Manual tests executed/passed: 1.) periodic LU enabled: * use gst LUTest.st to do a LU * UPDATE Subscriber SET expire_lu=datetime('now'); * observe the subscriber being expired (it was) 2.) periodic LU disabled: * use gst LUTest.st to do a LU * verify that the expire_lu is NULL in the database
-rw-r--r--openbsc/include/openbsc/gsm_subscriber.h2
-rw-r--r--openbsc/src/libbsc/bsc_vty.c23
-rw-r--r--openbsc/src/libmsc/db.c59
-rw-r--r--openbsc/src/libmsc/gsm_subscriber.c13
-rw-r--r--openbsc/tests/vty_test_runner.py32
5 files changed, 101 insertions, 28 deletions
diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h
index 32e0a4e..6b577b0 100644
--- a/openbsc/include/openbsc/gsm_subscriber.h
+++ b/openbsc/include/openbsc/gsm_subscriber.h
@@ -15,6 +15,8 @@
#define GSM_SUBSCRIBER_FIRST_CONTACT 0x00000001
#define tmsi_from_string(str) strtoul(str, NULL, 10)
+#define GSM_SUBSCRIBER_NO_EXPIRATION 0x0
+
struct vty;
struct gsm_equipment {
diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c
index b2b7977..45df90f 100644
--- a/openbsc/src/libbsc/bsc_vty.c
+++ b/openbsc/src/libbsc/bsc_vty.c
@@ -506,8 +506,13 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
(sp->penalty_time*20)+20, VTY_NEWLINE);
}
- vty_out(vty, " periodic location update %u%s",
- bts->si_common.chan_desc.t3212 * 6, VTY_NEWLINE);
+ /* Is periodic LU enabled or disabled? */
+ if (bts->si_common.chan_desc.t3212 == 0)
+ vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
+ else
+ vty_out(vty, " periodic location update %u%s",
+ bts->si_common.chan_desc.t3212 * 6, VTY_NEWLINE);
+
vty_out(vty, " channel allocator %s%s",
bts->chan_alloc_reverse ? "descending" : "ascending",
VTY_NEWLINE);
@@ -2036,6 +2041,19 @@ DEFUN(cfg_bts_per_loc_upd, cfg_bts_per_loc_upd_cmd,
return CMD_SUCCESS;
}
+DEFUN(cfg_bts_no_per_loc_upd, cfg_bts_no_per_loc_upd_cmd,
+ "no periodic location update",
+ NO_STR
+ "Periodic Location Updating Interval\n"
+ "Periodic Location Updating Interval\n"
+ "Periodic Location Updating Interval\n")
+{
+ struct gsm_bts *bts = vty->index;
+
+ bts->si_common.chan_desc.t3212 = 0;
+ return CMD_SUCCESS;
+}
+
#define GPRS_TEXT "GPRS Packet Network\n"
DEFUN(cfg_bts_prs_bvci, cfg_bts_gprs_bvci_cmd,
@@ -3053,6 +3071,7 @@ int bsc_vty_init(const struct log_info *cat)
install_element(BTS_NODE, &cfg_bts_rach_ec_allowed_cmd);
install_element(BTS_NODE, &cfg_bts_ms_max_power_cmd);
install_element(BTS_NODE, &cfg_bts_per_loc_upd_cmd);
+ install_element(BTS_NODE, &cfg_bts_no_per_loc_upd_cmd);
install_element(BTS_NODE, &cfg_bts_cell_resel_hyst_cmd);
install_element(BTS_NODE, &cfg_bts_rxlev_acc_min_cmd);
install_element(BTS_NODE, &cfg_bts_cell_bar_qualify_cmd);
diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c
index 8a7ff90..21abce9 100644
--- a/openbsc/src/libmsc/db.c
+++ b/openbsc/src/libmsc/db.c
@@ -639,7 +639,7 @@ static void db_set_from_query(struct gsm_subscriber *subscr, dbi_conn result)
if (!dbi_result_field_is_null(result, "expire_lu"))
subscr->expire_lu = dbi_result_get_datetime(result, "expire_lu");
else
- subscr->expire_lu = 0;
+ subscr->expire_lu = GSM_SUBSCRIBER_NO_EXPIRATION;
subscr->authorized = dbi_result_get_uint(result, "authorized");
}
@@ -766,23 +766,42 @@ int db_sync_subscriber(struct gsm_subscriber *subscriber)
} else
q_tmsi = strdup("NULL");
- result = dbi_conn_queryf(conn,
- "UPDATE Subscriber "
- "SET updated = datetime('now'), "
- "name = %s, "
- "extension = %s, "
- "authorized = %i, "
- "tmsi = %s, "
- "lac = %i, "
- "expire_lu = datetime(%i, 'unixepoch') "
- "WHERE imsi = %s ",
- q_name,
- q_extension,
- subscriber->authorized,
- q_tmsi,
- subscriber->lac,
- (int) subscriber->expire_lu,
- subscriber->imsi);
+ if (subscriber->expire_lu == GSM_SUBSCRIBER_NO_EXPIRATION) {
+ result = dbi_conn_queryf(conn,
+ "UPDATE Subscriber "
+ "SET updated = datetime('now'), "
+ "name = %s, "
+ "extension = %s, "
+ "authorized = %i, "
+ "tmsi = %s, "
+ "lac = %i, "
+ "expire_lu = NULL "
+ "WHERE imsi = %s ",
+ q_name,
+ q_extension,
+ subscriber->authorized,
+ q_tmsi,
+ subscriber->lac,
+ subscriber->imsi);
+ } else {
+ result = dbi_conn_queryf(conn,
+ "UPDATE Subscriber "
+ "SET updated = datetime('now'), "
+ "name = %s, "
+ "extension = %s, "
+ "authorized = %i, "
+ "tmsi = %s, "
+ "lac = %i, "
+ "expire_lu = datetime(%i, 'unixepoch') "
+ "WHERE imsi = %s ",
+ q_name,
+ q_extension,
+ subscriber->authorized,
+ q_tmsi,
+ subscriber->lac,
+ (int) subscriber->expire_lu,
+ subscriber->imsi);
+ }
free(q_tmsi);
free(q_name);
@@ -852,8 +871,8 @@ int db_subscriber_expire(void *priv, void (*callback)(void *priv, long long unsi
"SELECT id "
"FROM Subscriber "
"WHERE lac != 0 AND "
- "( expire_lu is NULL "
- "OR expire_lu < datetime('now') ) "
+ "( expire_lu is NOT NULL "
+ "AND expire_lu < datetime('now') ) "
"LIMIT 1");
if (!result) {
LOGP(DDB, LOGL_ERROR, "Failed to get expired subscribers\n");
diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c
index 6abb0d8..5ace8f6 100644
--- a/openbsc/src/libmsc/gsm_subscriber.c
+++ b/openbsc/src/libmsc/gsm_subscriber.c
@@ -333,8 +333,14 @@ int subscr_update_expire_lu(struct gsm_subscriber *s, struct gsm_bts *bts)
* 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) +
+
+ /* Is expiration handling enabled? */
+ if (bts->si_common.chan_desc.t3212 == 0)
+ s->expire_lu = GSM_SUBSCRIBER_NO_EXPIRATION;
+ else
+ 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;
@@ -354,11 +360,6 @@ int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason)
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.
- */
/*
* The below will set a new expire_lu but as a side-effect
* the new lac will be saved in the database.
diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py
index 9d283fd..fb01b89 100644
--- a/openbsc/tests/vty_test_runner.py
+++ b/openbsc/tests/vty_test_runner.py
@@ -55,6 +55,37 @@ class TestVTYBase(unittest.TestCase):
self.vty = None
osmoutil.end_proc(self.proc)
+class TestVTYNITB(TestVTYBase):
+
+ def vty_command(self):
+ return ["./src/osmo-nitb/osmo-nitb", "-c",
+ "doc/examples/osmo-nitb/nanobts/openbsc.cfg"]
+
+ def vty_app(self):
+ return (4242, "./src/osmo-nitb/osmo-nitb", "OpenBSC", "nitb")
+
+ def testEnableDisablePeriodicLU(self):
+ self.vty.enable()
+ self.vty.command("configure terminal")
+ self.vty.command("network")
+ self.vty.command("bts 0")
+
+ # Test invalid input
+ self.vty.verify("periodic location update 0", ['% Unknown command.'])
+ self.vty.verify("periodic location update 5", ['% Unknown command.'])
+ self.vty.verify("periodic location update 1531", ['% Unknown command.'])
+
+ # Enable periodic lu..
+ self.vty.verify("periodic location update 60", [''])
+ res = self.vty.command("write terminal")
+ self.assertGreater(res.find('periodic location update 60'), 0)
+ self.assertEquals(res.find('no periodic location update'), -1)
+
+ # Now disable it..
+ self.vty.verify("no periodic location update", [''])
+ res = self.vty.command("write terminal")
+ self.assertEquals(res.find('periodic location update 60'), -1)
+ self.assertGreater(res.find('no periodic location update'), 0)
class TestVTYNAT(TestVTYBase):
@@ -105,6 +136,7 @@ if __name__ == '__main__':
os.chdir(workdir)
print "Running tests for specific VTY commands"
suite = unittest.TestSuite()
+ suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestVTYNITB))
add_nat_test(suite, workdir)
res = unittest.TextTestRunner(verbosity=verbose_level).run(suite)
sys.exit(len(res.errors) + len(res.failures))