summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Santos <jrsantos@jonathanrsantos.com>2011-06-10 17:07:45 -0400
committerHarald Welte <laforge@gnumonks.org>2011-10-16 21:36:25 +0200
commit069830d42b1467c02ef77c3d30fc845347842211 (patch)
tree27d37b4148c1ddebc032d4a0c270c432f3cdb8e6
parentb551e46948c1471008e7ec3ad17b60340894bc41 (diff)
gprs: Delete GMM and PDP contexts if ATTACH_REQUEST received from already-attached MS
TS 24.008 version 9.5.0 Release 9 sec 4.7.3.1.6: If an ATTACH REQUEST message is received in state GMM-REGISTERED the network may initiate the GMM common procedures; if it turned out that the ATTACH REQUEST message was send by an MS that has already been attached, the GMM context, PDP contexts and MBMS contexts, if any, are deleted and the new ATTACH REQUEST is progressed.
-rw-r--r--openbsc/include/openbsc/sgsn.h2
-rw-r--r--openbsc/src/gprs/gprs_gmm.c27
-rw-r--r--openbsc/src/gprs/sgsn_libgtp.c16
3 files changed, 36 insertions, 9 deletions
diff --git a/openbsc/include/openbsc/sgsn.h b/openbsc/include/openbsc/sgsn.h
index 966b4e68b..816dfc43f 100644
--- a/openbsc/include/openbsc/sgsn.h
+++ b/openbsc/include/openbsc/sgsn.h
@@ -47,7 +47,7 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
struct sgsn_mm_ctx *mmctx,
uint16_t nsapi,
struct tlv_parsed *tp);
-int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx);
+int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx, int implicit);
/* gprs_sndcp.c */
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index 2f1f99d0c..0848b51b8 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -635,6 +635,21 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
DEBUGP(DMM, "-> GMM ATTACH REQUEST ");
+ if (ctx && ((ctx->mm_state == GMM_REGISTERED_NORMAL) ||
+ (ctx->mm_state == GMM_REGISTERED_SUSPENDED))) {
+ struct sgsn_pdp_ctx *pdp, *pdp2;
+
+ LOGP(DMM, LOGL_NOTICE, "Attach requested by already-attached "
+ "mobile. Deleting existing contexts\n");
+
+ llist_for_each_entry_safe(pdp, pdp2, &ctx->pdp_list, list) {
+ sgsn_delete_pdp_ctx(pdp, 1);
+ }
+
+ sgsn_mm_ctx_free(ctx);
+ ctx = NULL;
+ }
+
/* As per TS 04.08 Chapter 4.7.1.4, the attach request arrives either
* with a foreign TLLI (P-TMSI that was allocated to the MS before),
* or with random TLLI. */
@@ -786,7 +801,7 @@ static int gsm48_rx_gmm_det_req(struct sgsn_mm_ctx *ctx, struct msgb *msg)
llist_for_each_entry_safe(pdp, pdp2, &ctx->pdp_list, list) {
LOGP(DMM, LOGL_NOTICE, "Dropping PDP context for NSAPI=%u "
"due to GPRS DETACH REQUEST\n", pdp->nsapi);
- sgsn_delete_pdp_ctx(pdp);
+ sgsn_delete_pdp_ctx(pdp, 0);
/* FIXME: the callback wants to transmit a DEACT PDP CTX ACK,
* which is quite stupid for a MS that has just detached.. */
}
@@ -881,14 +896,14 @@ static void process_ms_ctx_status(struct sgsn_mm_ctx *mmctx,
LOGP(DMM, LOGL_NOTICE, "Dropping PDP context for NSAPI=%u "
"due to PDP CTX STATUS IE= 0x%02x%02x\n",
pdp->nsapi, pdp_status[1], pdp_status[0]);
- sgsn_delete_pdp_ctx(pdp);
+ sgsn_delete_pdp_ctx(pdp, 0);
}
} else {
if (!(pdp_status[1] & (1 << (pdp->nsapi - 8)))) {
LOGP(DMM, LOGL_NOTICE, "Dropping PDP context for NSAPI=%u "
"due to PDP CTX STATUS IE= 0x%02x%02x\n",
pdp->nsapi, pdp_status[1], pdp_status[0]);
- sgsn_delete_pdp_ctx(pdp);
+ sgsn_delete_pdp_ctx(pdp, 0);
}
}
}
@@ -1432,7 +1447,7 @@ static int gsm48_rx_gsm_deact_pdp_req(struct sgsn_mm_ctx *mm, struct msgb *msg)
return _gsm48_tx_gsm_deact_pdp_acc(mm, transaction_id);
}
- return sgsn_delete_pdp_ctx(pdp);
+ return sgsn_delete_pdp_ctx(pdp, 0);
}
/* Section 9.5.9: Deactivate PDP Context Accept */
@@ -1452,7 +1467,7 @@ static int gsm48_rx_gsm_deact_pdp_ack(struct sgsn_mm_ctx *mm, struct msgb *msg)
return 0;
}
- return sgsn_delete_pdp_ctx(pdp);
+ return sgsn_delete_pdp_ctx(pdp, 0);
}
static int gsm48_rx_gsm_status(struct sgsn_mm_ctx *ctx, struct msgb *msg)
@@ -1476,7 +1491,7 @@ static void pdpctx_timer_cb(void *_pdp)
if (pdp->num_T_exp >= 4) {
LOGP(DMM, LOGL_NOTICE, "T3395 expired >= 5 times\n");
pdp->state = PDP_STATE_INACTIVE;
- sgsn_delete_pdp_ctx(pdp);
+ sgsn_delete_pdp_ctx(pdp, 0);
break;
}
gsm48_tx_gsm_deact_pdp_req(pdp, GSM_CAUSE_NET_FAIL);
diff --git a/openbsc/src/gprs/sgsn_libgtp.c b/openbsc/src/gprs/sgsn_libgtp.c
index 71694a433..cf39c0287 100644
--- a/openbsc/src/gprs/sgsn_libgtp.c
+++ b/openbsc/src/gprs/sgsn_libgtp.c
@@ -207,12 +207,20 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
}
/* SGSN wants to delete a PDP context */
-int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx)
+int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx, int implicit)
{
LOGP(DGPRS, LOGL_ERROR, "Delete PDP Context\n");
+ if (implicit != 0) {
+ /* Deactivate the SNDCP layer */
+ sndcp_sm_deactivate_ind(&pctx->mm->llme->lle[pctx->sapi], pctx->nsapi);
+ }
+
/* FIXME: decide if we need teardown or not ! */
- return gtp_delete_context_req(pctx->ggsn->gsn, pctx->lib, pctx, 1);
+ return gtp_delete_context_req(pctx->ggsn->gsn,
+ pctx->lib,
+ implicit == 0 ? pctx : NULL,
+ 1);
}
struct cause_map {
@@ -311,6 +319,10 @@ static int delete_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
DEBUGP(DGPRS, "Received DELETE PDP CTX CONF, cause=%d(%s)\n",
cause, get_value_string(gtp_cause_strs, cause));
+ if (!pctx) {
+ return 0;
+ }
+
/* Deactivate the SNDCP layer */
sndcp_sm_deactivate_ind(&pctx->mm->llme->lle[pctx->sapi], pctx->nsapi);