aboutsummaryrefslogtreecommitdiffstats
path: root/src/libvlr
diff options
context:
space:
mode:
authorStefan Sperling <ssperling@sysmocom.de>2018-05-15 14:48:04 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2018-05-23 14:55:00 +0200
commitdefc3c8caf518306637ac579ec9b856f50dbb8ec (patch)
tree71d14ec1340b9231eb0497dce43f26cec7138563 /src/libvlr
parent2d95ab67d100a4747f7965b5be07e00453222f87 (diff)
implement periodic Location Update expiry in the VLR
Remove subscribers which fail to send periodic Location Updates from the list of subscribers known to the VLR. This complements the IMSI detach procedure: periodic LU expiry triggers an implicit IMSI detach. Expired subscribers are purged from a periodic timer which iterates over all subscribers once per minute. Subscribers with an active connection do not expire. This is controlled by the subscriber conn FSM which sets a subscriber's the LU expiry timeout value to GSM_SUBSCRIBER_NO_EXPIRATION while a connection is active. Add support for fake time with osmo_clock_gettime() to msc_vlr tests. This functionality existed in OpenBSC but was lost during the nitb split. This code took some inspiration from the OpenBSC implementation. Related: OS#1976 Change-Id: Iebdee8b12d22acfcfb265ee41e71cfc8d9eb3ba9
Diffstat (limited to 'src/libvlr')
-rw-r--r--src/libvlr/vlr.c49
-rw-r--r--src/libvlr/vlr_lu_fsm.c2
2 files changed, 50 insertions, 1 deletions
diff --git a/src/libvlr/vlr.c b/src/libvlr/vlr.c
index 2d232be74..29098b15b 100644
--- a/src/libvlr/vlr.c
+++ b/src/libvlr/vlr.c
@@ -22,6 +22,7 @@
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/fsm.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/timer.h>
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/gsm/gsup.h>
#include <osmocom/gsm/apn.h>
@@ -460,6 +461,50 @@ int vlr_subscr_changed(struct vlr_subscr *vsub)
return 0;
}
+void vlr_subscr_enable_expire_lu(struct vlr_subscr *vsub)
+{
+ struct gsm_network *net = vsub->vlr->user_ctx; /* XXX move t3212 into struct vlr_instance? */
+ struct timespec now;
+
+ /* 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. */
+ if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
+ vsub->expire_lu = now.tv_sec + (net->t3212 * 60 * 6 * 2) + 60;
+ } else {
+ LOGP(DVLR, LOGL_ERROR,
+ "%s: Could not enable Location Update expiry: unable to read current time\n", vlr_subscr_name(vsub));
+ /* Disable LU expiry for this subscriber. This subscriber will only be freed after an explicit IMSI detach. */
+ vsub->expire_lu = VLR_SUBSCRIBER_NO_EXPIRATION;
+ }
+}
+
+void vlr_subscr_expire_lu(void *data)
+{
+ struct vlr_instance *vlr = data;
+ struct vlr_subscr *vsub, *vsub_tmp;
+ struct timespec now;
+
+ if (llist_empty(&vlr->subscribers))
+ goto done;
+
+ if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) != 0) {
+ LOGP(DVLR, LOGL_ERROR, "Skipping Location Update expiry: Could not read current time\n");
+ goto done;
+ }
+
+ llist_for_each_entry_safe(vsub, vsub_tmp, &vlr->subscribers, list) {
+ if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION || vsub->expire_lu > now.tv_sec)
+ continue;
+
+ LOGP(DVLR, LOGL_DEBUG, "%s: Location Update expired\n", vlr_subscr_name(vsub));
+ vlr_subscr_rx_imsi_detach(vsub);
+ }
+
+done:
+ osmo_timer_schedule(&vlr->lu_expire_timer, VLR_SUBSCRIBER_LU_EXPIRATION_INTERVAL, 0);
+}
+
/***********************************************************************
* PDP context data
***********************************************************************/
@@ -1093,12 +1138,14 @@ bool vlr_subscr_expire(struct vlr_subscr *vsub)
return false;
}
+/* See TS 23.012 version 9.10.0 4.3.2.1 "Process Detach_IMSI_VLR" */
int vlr_subscr_rx_imsi_detach(struct vlr_subscr *vsub)
{
/* paranoia: should any LU or PARQ FSMs still be running, stop them. */
vlr_subscr_cancel_attach_fsm(vsub, OSMO_FSM_TERM_ERROR, GSM48_REJECT_CONGESTION);
vsub->imsi_detached_flag = true;
+ vsub->expire_lu = VLR_SUBSCRIBER_NO_EXPIRATION;
/* balancing the get from vlr_lu_compl_fsm_success() */
vlr_subscr_expire(vsub);
@@ -1165,6 +1212,8 @@ int vlr_start(const char *gsup_unit_name, struct vlr_instance *vlr,
return -ENOMEM;
vlr->gsup_client->data = vlr;
+ osmo_timer_setup(&vlr->lu_expire_timer, vlr_subscr_expire_lu, vlr);
+ osmo_timer_schedule(&vlr->lu_expire_timer, VLR_SUBSCRIBER_LU_EXPIRATION_INTERVAL, 0);
return 0;
}
diff --git a/src/libvlr/vlr_lu_fsm.c b/src/libvlr/vlr_lu_fsm.c
index 3073bd6dc..bf2355132 100644
--- a/src/libvlr/vlr_lu_fsm.c
+++ b/src/libvlr/vlr_lu_fsm.c
@@ -356,7 +356,7 @@ static void vlr_lu_compl_fsm_success(struct osmo_fsm_inst *fi)
struct vlr_subscr *vsub = lcvp->vsub;
if (!vsub->lu_complete) {
vsub->lu_complete = true;
- /* Balanced by vlr_subscr_rx_imsi_detach() */
+ /* Balanced by vlr_subscr_expire() */
vlr_subscr_get(vsub);
}
_vlr_lu_compl_fsm_done(fi, VLR_FSM_RESULT_SUCCESS, 0);