aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gprs/gprs_subscriber.c
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2015-01-08 16:23:25 +0100
committerJacob Erlbeck <jerlbeck@sysmocom.de>2015-01-19 08:30:01 +0100
commita688976f10bfb0c14954a066aa133f28bce3a541 (patch)
tree4cc0642f3b953433a5064d4992dbdad51a67c4ac /openbsc/src/gprs/gprs_subscriber.c
parent743dec4c0c80383556efac60f03d307287ecf024 (diff)
gprs: Block other GSUP procedures during PURGE_MS
GSM 09.02, 19.4.1.4 mandates that no other MAP procedures shall be started until the PURGE_MS procedure has been completed. This patch implements this by adding corresponding state and checks to gprs_subscr_purge, gprs_subscr_location_update, and gprs_subscr_update_auth_info. If an Update Location or a Send Auth Info Req procedure is not started because of blocking, the retry mechanism is aborted to shorten the blocking time. The outstanding Purge MS procedure itself is not aborted. Sponsored-by: On-Waves ehf
Diffstat (limited to 'openbsc/src/gprs/gprs_subscriber.c')
-rw-r--r--openbsc/src/gprs/gprs_subscriber.c56
1 files changed, 55 insertions, 1 deletions
diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c
index 8399ea137..88e037e9d 100644
--- a/openbsc/src/gprs/gprs_subscriber.c
+++ b/openbsc/src/gprs/gprs_subscriber.c
@@ -76,6 +76,23 @@ static int gsup_read_cb(struct gprs_gsup_client *gsupc, struct msgb *msg)
return rc;
}
+static int check_blocking(
+ struct gsm_subscriber *subscr,
+ enum sgsn_subscriber_proc what)
+{
+ if (subscr->sgsn_data->blocked_by == SGSN_SUBSCR_PROC_NONE ||
+ subscr->sgsn_data->blocked_by == what)
+ return 1;
+
+ return 0;
+}
+
+static void abort_blocking_procedure(struct gsm_subscriber *subscr)
+{
+ /* Best effort, stop retries at least */
+ subscr->sgsn_data->retries = SGSN_SUBSCR_MAX_RETRIES;
+}
+
static void sgsn_subscriber_timeout_cb(void *subscr_);
int gprs_subscr_purge(struct gsm_subscriber *subscr);
@@ -132,6 +149,10 @@ static void sgsn_subscriber_timeout_cb(void *subscr_)
return;
force_cleanup:
+ /* Make sure to clear blocking */
+ if (check_blocking(subscr, SGSN_SUBSCR_PROC_PURGE))
+ subscr->sgsn_data->blocked_by = SGSN_SUBSCR_PROC_NONE;
+
/* Make sure, the timer is cleaned up */
subscr->keep_in_ram = 0;
gprs_subscr_stop_timer(subscr);
@@ -544,17 +565,42 @@ int gprs_subscr_rx_gsup_message(struct msgb *msg)
int gprs_subscr_purge(struct gsm_subscriber *subscr)
{
struct gprs_gsup_message gsup_msg = {0};
+ int rc;
+
+ if (!check_blocking(subscr, SGSN_SUBSCR_PROC_PURGE)) {
+ LOGGSUBSCRP(
+ LOGL_NOTICE, subscr,
+ "Cannot purge MS subscriber, blocked\n");
+ return -EAGAIN;
+ }
+
+ /* GSM 09.02, 19.4.1.4 requires other MAP requests to be blocked until
+ * this procedure is completed
+ */
+ subscr->sgsn_data->blocked_by = SGSN_SUBSCR_PROC_PURGE;
LOGGSUBSCRP(LOGL_INFO, subscr, "purging MS subscriber\n");
gsup_msg.message_type = GPRS_GSUP_MSGT_PURGE_MS_REQUEST;
- return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
+ rc = gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
+ if (rc < 0)
+ subscr->sgsn_data->blocked_by = SGSN_SUBSCR_PROC_NONE;
+
+ return rc;
}
int gprs_subscr_query_auth_info(struct gsm_subscriber *subscr)
{
struct gprs_gsup_message gsup_msg = {0};
+ if (!check_blocking(subscr, SGSN_SUBSCR_PROC_UPD_AUTH)) {
+ LOGGSUBSCRP(
+ LOGL_NOTICE, subscr,
+ "Cannot start update auth info request procedure, blocked\n");
+ abort_blocking_procedure(subscr);
+ return -EAGAIN;
+ }
+
LOGGSUBSCRP(LOGL_INFO, subscr,
"subscriber auth info is not available\n");
@@ -566,6 +612,14 @@ int gprs_subscr_location_update(struct gsm_subscriber *subscr)
{
struct gprs_gsup_message gsup_msg = {0};
+ if (!check_blocking(subscr, SGSN_SUBSCR_PROC_UPD_LOC)) {
+ LOGGSUBSCRP(
+ LOGL_NOTICE, subscr,
+ "Cannot start update location procedure, blocked\n");
+ abort_blocking_procedure(subscr);
+ return -EAGAIN;
+ }
+
LOGGSUBSCRP(LOGL_INFO, subscr,
"subscriber data is not available\n");