aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Santos <jrsantos@jonathanrsantos.com>2011-06-10 17:07:45 -0400
committerJonathan Santos <jrsantos@jonathanrsantos.com>2011-06-23 17:45:19 -0400
commit8f3a5a2f0bbcd94e122639c45a9f7f0e73c46865 (patch)
tree3c5fa716efa0b7728b767536431368c641d3693c
parent749a666d849743353473813210cbf6899005c6c4 (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--include/openbsc/sgsn.h2
-rw-r--r--src/gprs/gprs_gmm.c25
-rw-r--r--src/gprs/sgsn_libgtp.c16
3 files changed, 35 insertions, 8 deletions
diff --git a/include/openbsc/sgsn.h b/include/openbsc/sgsn.h
index 84db87e91..7ca7e1c44 100644
--- a/include/openbsc/sgsn.h
+++ b/include/openbsc/sgsn.h
@@ -48,7 +48,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/src/gprs/gprs_gmm.c b/src/gprs/gprs_gmm.c
index 467c7a0bd..942d93f47 100644
--- a/src/gprs/gprs_gmm.c
+++ b/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. */
@@ -772,7 +787,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.. */
}
@@ -866,7 +881,7 @@ 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%04x\n",
pdp->nsapi, pdp_status);
- sgsn_delete_pdp_ctx(pdp);
+ sgsn_delete_pdp_ctx(pdp, 0);
}
}
}
@@ -1393,7 +1408,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 */
@@ -1413,7 +1428,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)
@@ -1437,7 +1452,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/src/gprs/sgsn_libgtp.c b/src/gprs/sgsn_libgtp.c
index 7b10a45a3..b2d8874ac 100644
--- a/src/gprs/sgsn_libgtp.c
+++ b/src/gprs/sgsn_libgtp.c
@@ -208,12 +208,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 {
@@ -312,6 +320,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);