aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2015-01-06 16:32:41 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2015-01-18 18:27:19 +0100
commit0f47b8fae743769a6627f8654444b4f0d665e050 (patch)
treebfe14ac19d8734332d818776e86344773ff9b20e /openbsc/src
parentb8fb1409d1ed18dc198b430895a74e680640c2b1 (diff)
gprs: Add expiry timeout for subscriber entries
Set the expiry delay after the subscriber has been deleted (e.g. by freeing the MM context). If cancelled, the subscriber will be deleted immediately and no timeout will be set. If the expiry time is set to SGSN_TIMEOUT_NEVER, no timer will be started and the subscriber entry will be kept until it is cancelled. The following VTY command is added to the sgsn node: - subscriber-expiry-time <0-999999> set expiry time in seconds - no subscriber-expiry-time set to SGSN_TIMEOUT_NEVER The default is an expiry time of 0 seconds, which means that the subscriber entries are wiped out immediately after an MM context is destroyed. Note that unused MM contexts are not expired yet. Therefore the subscriber will only be expired after a successful MM detach. Sponsored-by: On-Waves ehf
Diffstat (limited to 'openbsc/src')
-rw-r--r--openbsc/src/gprs/gprs_subscriber.c47
-rw-r--r--openbsc/src/gprs/sgsn_vty.c35
2 files changed, 80 insertions, 2 deletions
diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c
index 9fe6ad2f7..9d79f0006 100644
--- a/openbsc/src/gprs/gprs_subscriber.c
+++ b/openbsc/src/gprs/gprs_subscriber.c
@@ -73,6 +73,43 @@ static int gsup_read_cb(struct gprs_gsup_client *gsupc, struct msgb *msg)
return rc;
}
+static void sgsn_subscriber_timeout_cb(void *subscr_);
+int gprs_subscr_purge(struct gsm_subscriber *subscr);
+
+void gprs_subscr_stop_timer(struct gsm_subscriber *subscr)
+{
+ if (subscr->sgsn_data->timer.data) {
+ osmo_timer_del(&subscr->sgsn_data->timer);
+ subscr->sgsn_data->timer.cb = NULL;
+ OSMO_ASSERT(subscr->sgsn_data->timer.data == subscr);
+ subscr->sgsn_data->timer.data = NULL;
+ subscr_put(subscr);
+ }
+}
+
+void gprs_subscr_start_timer(struct gsm_subscriber *subscr, unsigned seconds)
+{
+ if (!subscr->sgsn_data->timer.data) {
+ subscr->sgsn_data->timer.cb = sgsn_subscriber_timeout_cb;
+ subscr->sgsn_data->timer.data = subscr_get(subscr);
+ }
+
+ osmo_timer_schedule(&subscr->sgsn_data->timer, seconds, 0);
+}
+
+static void sgsn_subscriber_timeout_cb(void *subscr_)
+{
+ struct gsm_subscriber *subscr = subscr_;
+
+ LOGGSUBSCRP(LOGL_INFO, subscr,
+ "Expired, deleting subscriber entry\n");
+
+ /* Make sure, the timer is cleaned up */
+ subscr->keep_in_ram = 0;
+ gprs_subscr_stop_timer(subscr);
+ /* The subscr is freed now, if the timer was the last user */
+}
+
static struct sgsn_subscriber_data *sgsn_subscriber_data_alloc(void *ctx)
{
struct sgsn_subscriber_data *sdata;
@@ -97,7 +134,7 @@ struct gsm_subscriber *gprs_subscr_get_or_create(const char *imsi)
if (!subscr->sgsn_data)
subscr->sgsn_data = sgsn_subscriber_data_alloc(subscr);
- subscr->keep_in_ram = 1;
+ gprs_subscr_stop_timer(subscr);
return subscr;
}
@@ -116,8 +153,14 @@ void gprs_subscr_delete(struct gsm_subscriber *subscr)
}
if ((subscr->flags & GPRS_SUBSCRIBER_CANCELLED) ||
- (subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT))
+ (subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT)) {
subscr->keep_in_ram = 0;
+ gprs_subscr_stop_timer(subscr);
+ } else if (sgsn->cfg.subscriber_expiry_timeout != SGSN_TIMEOUT_NEVER) {
+ gprs_subscr_start_timer(subscr, sgsn->cfg.subscriber_expiry_timeout);
+ } else {
+ subscr->keep_in_ram = 1;
+ }
subscr_put(subscr);
}
diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c
index 4deb2acb4..1241c17e5 100644
--- a/openbsc/src/gprs/sgsn_vty.c
+++ b/openbsc/src/gprs/sgsn_vty.c
@@ -151,6 +151,10 @@ static int config_write_sgsn(struct vty *vty)
llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
+ if (g_cfg->subscriber_expiry_timeout != SGSN_TIMEOUT_NEVER)
+ vty_out(vty, " subscriber-expiry-timeout %d%s",
+ g_cfg->subscriber_expiry_timeout, VTY_NEWLINE);
+
return CMD_SUCCESS;
}
@@ -401,6 +405,7 @@ static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr,
char expire_time[200];
struct gsm_auth_tuple *at;
int at_idx;
+ struct timeval tv;
vty_out(vty, " ID: %llu, Authorized: %d%s", subscr->id,
subscr->authorized, VTY_NEWLINE);
@@ -446,6 +451,17 @@ static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr,
vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
}
+ /* print the expiration time if the timer is active */
+ if (osmo_timer_pending(&subscr->sgsn_data->timer)) {
+ osmo_timer_remaining(&subscr->sgsn_data->timer, NULL, &tv);
+ strftime(expire_time, sizeof(expire_time),
+ "%a, %d %b %Y %T %z",
+ localtime(&subscr->sgsn_data->timer.timeout.tv_sec));
+ expire_time[sizeof(expire_time) - 1] = '\0';
+ vty_out(vty, " Expires in: %ds (%s)%s",
+ (int)tv.tv_sec, expire_time, VTY_NEWLINE);
+ }
+
if (subscr->flags)
vty_out(vty, " Flags: %s%s%s%s%s",
subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT ?
@@ -687,7 +703,24 @@ DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
return CMD_SUCCESS;
}
+DEFUN(cfg_subscriber_expiry_timeout, cfg_subscriber_expiry_timeout_cmd,
+ "subscriber-expiry-timeout <0-999999>",
+ "Set the expiry time for unused subscriber entries\n"
+ "Expiry time in seconds\n")
+{
+ g_cfg->subscriber_expiry_timeout = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_no_subscriber_expiry_timeout, cfg_no_subscriber_expiry_timeout_cmd,
+ "no subscriber-expiry-timeout",
+ NO_STR "Set the expiry time for unused subscriber entries\n")
+{
+ g_cfg->subscriber_expiry_timeout = atoi(argv[0]);
+
+ return CMD_SUCCESS;
+}
int sgsn_vty_init(void)
{
@@ -716,6 +749,8 @@ int sgsn_vty_init(void)
install_element(SGSN_NODE, &cfg_auth_policy_cmd);
install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
+ install_element(SGSN_NODE, &cfg_subscriber_expiry_timeout_cmd);
+ install_element(SGSN_NODE, &cfg_no_subscriber_expiry_timeout_cmd);
return 0;
}