diff --git a/openbsc/include/openbsc/gprs_gmm.h b/openbsc/include/openbsc/gprs_gmm.h index 2cea6f419..b91b489d3 100644 --- a/openbsc/include/openbsc/gprs_gmm.h +++ b/openbsc/include/openbsc/gprs_gmm.h @@ -11,4 +11,8 @@ int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp); int gsm0408_gprs_rcvmsg(struct msgb *msg, struct gprs_llc_llme *llme); +int gprs_gmm_rx_suspend(struct gprs_ra_id *raid, uint32_t tlli); +int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli, + uint8_t suspend_ref); + #endif /* _GPRS_GMM_H */ diff --git a/openbsc/src/gprs/gprs_bssgp.c b/openbsc/src/gprs/gprs_bssgp.c index 89b78662e..c7c49d4bd 100644 --- a/openbsc/src/gprs/gprs_bssgp.c +++ b/openbsc/src/gprs/gprs_bssgp.c @@ -40,6 +40,7 @@ #include #include #include +#include void *bssgp_tall_ctx = NULL; @@ -363,6 +364,7 @@ static int bssgp_rx_suspend(struct msgb *msg, struct tlv_parsed *tp, (struct bssgp_normal_hdr *) msgb_bssgph(msg); struct gprs_ra_id raid; uint32_t tlli; + int rc; if (!TLVP_PRESENT(tp, BSSGP_IE_TLLI) || !TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) { @@ -378,8 +380,11 @@ static int bssgp_rx_suspend(struct msgb *msg, struct tlv_parsed *tp, gsm48_parse_ra(&raid, TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA)); - /* FIXME: pass the SUSPEND request to GMM */ - /* SEND SUSPEND_ACK or SUSPEND_NACK */ + /* Inform GMM about the SUSPEND request */ + rc = gprs_gmm_rx_suspend(&raid, tlli); + if (rc < 0) + return bssgp_tx_suspend_nack(msgb_nsei(msg), tlli, NULL); + bssgp_tx_suspend_ack(msgb_nsei(msg), tlli, &raid, 0); return 0; @@ -392,6 +397,8 @@ static int bssgp_rx_resume(struct msgb *msg, struct tlv_parsed *tp, (struct bssgp_normal_hdr *) msgb_bssgph(msg); struct gprs_ra_id raid; uint32_t tlli; + uint8_t suspend_ref; + int rc; if (!TLVP_PRESENT(tp, BSSGP_IE_TLLI) || !TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA) || @@ -402,13 +409,18 @@ static int bssgp_rx_resume(struct msgb *msg, struct tlv_parsed *tp, } tlli = ntohl(*(uint32_t *)TLVP_VAL(tp, BSSGP_IE_TLLI)); + suspend_ref = *TLVP_VAL(tp, BSSGP_IE_SUSPEND_REF_NR); DEBUGP(DBSSGP, "BSSGP BVCI=%u TLLI=0x%08x RESUME\n", ctx->bvci, tlli); gsm48_parse_ra(&raid, TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA)); - /* FIXME: pass the RESUME request to GMM */ - /* SEND RESUME_ACK or RESUME_NACK */ + /* Inform GMM about the RESUME request */ + rc = gprs_gmm_rx_resume(&raid, tlli, suspend_ref); + if (rc < 0) + return bssgp_tx_resume_nack(msgb_nsei(msg), tlli, &raid, + NULL); + bssgp_tx_resume_ack(msgb_nsei(msg), tlli, &raid); return 0; } diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c index ad9a546ec..17d2ed07f 100644 --- a/openbsc/src/gprs/gprs_gmm.c +++ b/openbsc/src/gprs/gprs_gmm.c @@ -1270,3 +1270,51 @@ int gsm0408_gprs_rcvmsg(struct msgb *msg, struct gprs_llc_llme *llme) return rc; } + +int gprs_gmm_rx_suspend(struct gprs_ra_id *raid, uint32_t tlli) +{ + struct sgsn_mm_ctx *mmctx; + + mmctx = sgsn_mm_ctx_by_tlli(tlli, raid); + if (!mmctx) { + LOGP(DMM, LOGL_NOTICE, "SUSPEND request for unknown " + "TLLI=%08x\n", tlli); + return -EINVAL; + } + + if (mmctx->mm_state != GMM_REGISTERED_NORMAL) { + LOGP(DMM, LOGL_NOTICE, "SUSPEND request while state " + "!= REGISTERED (TLLI=%08x)\n", tlli); + return -EINVAL; + } + + /* Transition from REGISTERED_NORMAL to REGISTERED_SUSPENDED */ + mmctx->mm_state = GMM_REGISTERED_SUSPENDED; + return 0; +} + +int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli, + uint8_t suspend_ref) +{ + struct sgsn_mm_ctx *mmctx; + + /* FIXME: make use of suspend reference? */ + + mmctx = sgsn_mm_ctx_by_tlli(tlli, raid); + if (!mmctx) { + LOGP(DMM, LOGL_NOTICE, "RESUME request for unknown " + "TLLI=%08x\n", tlli); + return -EINVAL; + } + + if (mmctx->mm_state != GMM_REGISTERED_SUSPENDED) { + LOGP(DMM, LOGL_NOTICE, "RESUME request while state " + "!= SUSPENDED (TLLI=%08x)\n", tlli); + /* FIXME: should we not simply ignore it? */ + return -EINVAL; + } + + /* Transition from SUSPENDED to NORMAL */ + mmctx->mm_state = GMM_REGISTERED_NORMAL; + return 0; +}