diff options
author | Harald Welte <laforge@gnumonks.org> | 2010-12-24 23:07:18 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2010-12-26 19:20:07 +0100 |
commit | c728eeaf9b3fc71c9434e6ae3515d4ddc12e66d8 (patch) | |
tree | 6c3103907a941e819c73e22c45ce6170bb43a0e0 /openbsc | |
parent | a9b473a3c25d5b0f0993c3c53f6004b0e86fca5c (diff) |
SGSN: Avoid duplicate MM contexts in case MS and SGSN disagree on P-TMSI
Diffstat (limited to 'openbsc')
-rw-r--r-- | openbsc/include/openbsc/gprs_sgsn.h | 1 | ||||
-rw-r--r-- | openbsc/src/gprs/gprs_gmm.c | 15 | ||||
-rw-r--r-- | openbsc/src/gprs/gprs_sgsn.c | 15 |
3 files changed, 31 insertions, 0 deletions
diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h index fb1b2882b..b470c536c 100644 --- a/openbsc/include/openbsc/gprs_sgsn.h +++ b/openbsc/include/openbsc/gprs_sgsn.h @@ -119,6 +119,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi); /* Allocate a new SGSN MM context */ struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t tlli, const struct gprs_ra_id *raid); +void sgsn_mm_ctx_free(struct sgsn_mm_ctx *mm); enum pdp_ctx_state { diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c index ee6e3665b..4f1fe0524 100644 --- a/openbsc/src/gprs/gprs_gmm.c +++ b/openbsc/src/gprs/gprs_gmm.c @@ -594,6 +594,19 @@ static int gsm48_rx_gmm_id_resp(struct sgsn_mm_ctx *ctx, struct msgb *msg) /* we already have a mm context with current TLLI, but no * P-TMSI / IMSI yet. What we now need to do is to fill * this initial context with data from the HLR */ + if (strlen(ctx->imsi) == 0) { + /* Check if we already have a MM context for this IMSI */ + struct sgsn_mm_ctx *ictx; + ictx = sgsn_mm_ctx_by_imsi(mi_string); + if (ictx) { + DEBUGP(DMM, "Deleting old MM Context for same IMSI ", + "p_tmsi_old=0x%08x, p_tmsi_new=0x%08x\n", + ictx->p_tmsi, ctx->p_tmsi); + gprs_llgmm_assign(ictx->llme, ictx->tlli, + 0xffffffff, GPRS_ALGO_GEA0, NULL); + sgsn_mm_ctx_free(ictx); + } + } strncpy(ctx->imsi, mi_string, sizeof(ctx->imei)); break; case GSM_MI_TYPE_IMEI: @@ -704,6 +717,8 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg, if (!ctx) ctx = sgsn_mm_ctx_by_ptmsi(tmsi); if (!ctx) { + /* Allocate a context as most of our code expects one. + * Context will not have an IMSI ultil ID RESP is received */ ctx = sgsn_mm_ctx_alloc(msgb_tlli(msg), &ra_id); ctx->p_tmsi = tmsi; } diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c index f5580037e..142ff4738 100644 --- a/openbsc/src/gprs/gprs_sgsn.c +++ b/openbsc/src/gprs/gprs_sgsn.c @@ -173,6 +173,21 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t tlli, return ctx; } +void sgsn_mm_ctx_free(struct sgsn_mm_ctx *mm) +{ + struct sgsn_pdp_ctx *pdp, *pdp2; + + /* Unlink from global list of MM contexts */ + llist_del(&mm->list); + + /* Free all PDP contexts */ + llist_for_each_entry_safe(pdp, pdp2, &mm->pdp_list, list) + sgsn_pdp_ctx_free(pdp); + + rate_ctr_group_free(mm->ctrg); + + talloc_free(mm); +} /* look up PDP context by MM context and NSAPI */ struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm, |