GPRS/GMM: Correctly look up MM Context in RA Update
If a MS changes RA, the RA will arrive in the new cell using the old TLLI (masked as foreign TLLI). So we need to look-up the TLLI in a special way, using the old RA as indicated in the 04.08 GMM message. There is still another bug remaining: As we somehow create a new LLC, the sequence numbers of our responses start from 0 again, which is not what the MS expects. This needs to be fixed in a follow-up patch.
This commit is contained in:
parent
985263e55f
commit
f6bd340df6
|
@ -899,6 +899,7 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
|
|||
}
|
||||
|
||||
/* Look-up the MM context based on old RA-ID and TLLI */
|
||||
mmctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &old_ra_id);
|
||||
if (!mmctx || mmctx->mm_state == GMM_DEREGISTERED) {
|
||||
/* The MS has to perform GPRS attach */
|
||||
DEBUGPC(DMM, " REJECT\n");
|
||||
|
|
|
@ -82,6 +82,12 @@ static int ra_id_equals(const struct gprs_ra_id *id1,
|
|||
id1->lac == id2->lac && id1->rac == id2->rac);
|
||||
}
|
||||
|
||||
/* See 03.02 Chapter 2.6 */
|
||||
static inline uint32_t tlli_foreign(uint32_t tlli)
|
||||
{
|
||||
return ((tlli | 0x80000000) & ~0x40000000);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
@ -96,7 +102,8 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
|
|||
}
|
||||
|
||||
tlli_type = gprs_tlli_type(tlli);
|
||||
if (tlli_type == TLLI_LOCAL) {
|
||||
switch (tlli_type) {
|
||||
case TLLI_LOCAL:
|
||||
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
|
||||
if ((ctx->p_tmsi | 0xC0000000) == tlli ||
|
||||
(ctx->p_tmsi_old && (ctx->p_tmsi_old | 0xC0000000) == tlli)) {
|
||||
|
@ -104,6 +111,16 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
|
|||
return ctx;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TLLI_FOREIGN:
|
||||
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
|
||||
if (tlli == tlli_foreign(ctx->tlli) &&
|
||||
ra_id_equals(raid, &ctx->ra))
|
||||
return ctx;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
Loading…
Reference in New Issue