diff options
Diffstat (limited to 'openbsc/src/gprs/gprs_sgsn.c')
-rw-r--r-- | openbsc/src/gprs/gprs_sgsn.c | 71 |
1 files changed, 61 insertions, 10 deletions
diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c index 65f789d6d..9e7143540 100644 --- a/openbsc/src/gprs/gprs_sgsn.c +++ b/openbsc/src/gprs/gprs_sgsn.c @@ -39,6 +39,9 @@ #include <openbsc/gprs_utils.h> #include <openbsc/signal.h> #include "openbsc/gprs_llc.h" +#include <openbsc/iu.h> + +#include <pdp.h> #include <time.h> @@ -91,13 +94,26 @@ static const struct rate_ctr_group_desc pdpctx_ctrg_desc = { }; /* look-up a SGSN MM context based on TLLI + RAI */ +struct sgsn_mm_ctx *sgsn_mm_ctx_by_ue_ctx(const void *uectx) +{ + struct sgsn_mm_ctx *ctx; + + llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) { + if (ctx->ran_type == MM_CTX_T_UTRAN_Iu && uectx == ctx->iu.ue_ctx) + return ctx; + } + + return NULL; +} + +/* look-up a SGSN MM context based on TLLI + RAI */ struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli, const struct gprs_ra_id *raid) { struct sgsn_mm_ctx *ctx; llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) { - if ((tlli == ctx->tlli || tlli == ctx->tlli_new) && + if ((tlli == ctx->gb.tlli || tlli == ctx->gb.tlli_new) && gprs_ra_id_equals(raid, &ctx->ra)) return ctx; } @@ -165,7 +181,8 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t tlli, return NULL; memcpy(&ctx->ra, raid, sizeof(ctx->ra)); - ctx->tlli = tlli; + ctx->ran_type = MM_CTX_T_GERAN_Gb; + ctx->gb.tlli = tlli; ctx->mm_state = GMM_DEREGISTERED; ctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL; ctx->ctrg = rate_ctr_group_alloc(ctx, &mmctx_ctrg_desc, tlli); @@ -176,6 +193,34 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t tlli, return ctx; } +/* Allocate a new SGSN MM context */ +struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_iu(void *uectx) +{ + struct sgsn_mm_ctx *ctx; + + ctx = talloc_zero(tall_bsc_ctx, struct sgsn_mm_ctx); + if (!ctx) + return NULL; + + ctx->ran_type = MM_CTX_T_UTRAN_Iu; + ctx->iu.ue_ctx = uectx; + ctx->iu.new_key = 1; + ctx->mm_state = GMM_DEREGISTERED; + ctx->pmm_state = PMM_DETACHED; + ctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL; + ctx->ctrg = rate_ctr_group_alloc(ctx, &mmctx_ctrg_desc, 0); + + /* Need to get RAID from IU conn */ + ctx->ra = ctx->iu.ue_ctx->ra_id; + + INIT_LLIST_HEAD(&ctx->pdp_list); + + llist_add(&ctx->list, &sgsn_mm_ctxts); + + return ctx; +} + + /* this is a hard _free_ function, it doesn't clean up the PDP contexts * in libgtp! */ static void sgsn_mm_ctx_free(struct sgsn_mm_ctx *mm) @@ -196,10 +241,11 @@ static void sgsn_mm_ctx_free(struct sgsn_mm_ctx *mm) void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *mm) { - struct gprs_llc_llme *llme = mm->llme; - uint32_t tlli = mm->tlli; + struct gprs_llc_llme *llme = mm->gb.llme; + uint32_t tlli = mm->gb.tlli; struct sgsn_pdp_ctx *pdp, *pdp2; struct sgsn_signal_data sig_data; + enum sgsn_ran_type ran_type; /* Forget about ongoing look-ups */ if (mm->ggsn_lookup) { @@ -233,11 +279,15 @@ void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *mm) subscr_put(subscr); } + ran_type = mm->ran_type; + sgsn_mm_ctx_free(mm); mm = NULL; - /* TLLI unassignment, must be called after sgsn_mm_ctx_free */ - gprs_llgmm_assign(llme, tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL); + if (ran_type == MM_CTX_T_GERAN_Gb) { + /* TLLI unassignment, must be called after sgsn_mm_ctx_free */ + gprs_llgmm_assign(llme, tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL); + } } @@ -290,7 +340,6 @@ struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm, return pdp; } -#include <pdp.h> /* * This function will not trigger any GSM DEACT PDP ACK messages, so you * probably want to call sgsn_delete_pdp_ctx() instead if the connection @@ -307,8 +356,10 @@ void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp) LOGPDPCTXP(LOGL_INFO, pdp, "Forcing release of PDP context\n"); - /* Force the deactivation of the SNDCP layer */ - sndcp_sm_deactivate_ind(&pdp->mm->llme->lle[pdp->sapi], pdp->nsapi); + if (pdp->mm->ran_type == MM_CTX_T_GERAN_Gb) { + /* Force the deactivation of the SNDCP layer */ + sndcp_sm_deactivate_ind(&pdp->mm->gb.llme->lle[pdp->sapi], pdp->nsapi); + } memset(&sig_data, 0, sizeof(sig_data)); sig_data.pdp = pdp; @@ -751,7 +802,7 @@ static void sgsn_llme_cleanup_free(struct gprs_llc_llme *llme) struct sgsn_mm_ctx *mmctx = NULL; llist_for_each_entry(mmctx, &sgsn_mm_ctxts, list) { - if (llme == mmctx->llme) { + if (llme == mmctx->gb.llme) { gsm0408_gprs_access_cancelled(mmctx, SGSN_ERROR_CAUSE_NONE); return; } |