aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gprs/sgsn_libgtp.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2010-06-09 16:22:28 +0200
committerHarald Welte <laforge@gnumonks.org>2010-06-10 15:12:38 +0200
commitbb35c45a0202e24e76d17900dbe2d5264136ef8d (patch)
treefc7c5d9aa7747dee0c272628666683ca0496b74f /openbsc/src/gprs/sgsn_libgtp.c
parentbffeff8089a37cc5610e89e802f211ca380041e8 (diff)
[GPRS] BSSGP/SGSN: Implement Gb-Interface Paging
We now have a function that generates BSSGP PS and CS paging request. It is called from the libgtp code when we receive a GTP packet from the GGSN for a MM context that is in SUSPEND state. We then issue a PS paging request to the Cell with the BVCI where the last RA update was being performed. TODO: We still don't enqueue the GTP packet (and transmit it on paging complete), and we don't rate-limit the paging requests, i.e. every GTP packet will trigger another paging request. We probably also need some kind of logic that marks the phone as UNREGISTERED if it doesn't respond to paging requests for some time.
Diffstat (limited to 'openbsc/src/gprs/sgsn_libgtp.c')
-rw-r--r--openbsc/src/gprs/sgsn_libgtp.c40
1 files changed, 34 insertions, 6 deletions
diff --git a/openbsc/src/gprs/sgsn_libgtp.c b/openbsc/src/gprs/sgsn_libgtp.c
index 6de3c3d1f..a1d233a9a 100644
--- a/openbsc/src/gprs/sgsn_libgtp.c
+++ b/openbsc/src/gprs/sgsn_libgtp.c
@@ -357,27 +357,55 @@ static int cb_extheader_ind(struct sockaddr_in *peer)
/* Called whenever we recive a DATA packet */
static int cb_data_ind(struct pdp_t *lib, void *packet, unsigned int len)
{
+ struct bssgp_paging_info pinfo;
struct sgsn_pdp_ctx *pdp;
- struct msgb *msg = msgb_alloc_headroom(len+128, 128, "GTP->SNDCP");
+ struct sgsn_mm_ctx *mm;
+ struct msgb *msg;
uint8_t *ud;
+ int rc;
DEBUGP(DGPRS, "GTP DATA IND from GGSN, length=%u\n", len);
- /* FIXME: resolve PDP/MM context, forward to SNDCP layer */
pdp = lib->priv;
if (!pdp) {
DEBUGP(DGPRS, "GTP DATA IND from GGSN for unknown PDP\n");
return -EIO;
}
+ mm = pdp->mm;
+ msg = msgb_alloc_headroom(len+128, 128, "GTP->SNDCP");
ud = msgb_put(msg, len);
memcpy(ud, packet, len);
- msgb_tlli(msg) = pdp->mm->tlli;
- msgb_bvci(msg) = pdp->mm->bvci;
- msgb_nsei(msg) = pdp->mm->nsei;
+ msgb_tlli(msg) = mm->tlli;
+ msgb_bvci(msg) = mm->bvci;
+ msgb_nsei(msg) = mm->nsei;
+
+ switch (mm->mm_state) {
+ case GMM_REGISTERED_SUSPENDED:
+ /* initiate PS PAGING procedure */
+ memset(&pinfo, 0, sizeof(pinfo));
+ pinfo.mode = BSSGP_PAGING_PS;
+ pinfo.scope = BSSGP_PAGING_BVCI;
+ pinfo.bvci = mm->bvci;
+ pinfo.imsi = mm->imsi;
+ pinfo.ptmsi = mm->p_tmsi;
+ pinfo.drx_params = mm->drx_parms;
+ pinfo.qos[0] = 0; // FIXME
+ rc = gprs_bssgp_tx_paging(mm->nsei, 0, &pinfo);
+ /* FIXME: queue the packet we received from GTP */
+ break;
+ case GMM_REGISTERED_NORMAL:
+ break;
+ default:
+ LOGP(DGPRS, LOGL_ERROR, "GTP DATA IND for TLLI %08X in state "
+ "%u\n", mm->tlli, mm->mm_state);
+ msgb_free(msg);
+ return -1;
+ }
- return sndcp_unitdata_req(msg, &pdp->mm->llme->lle[pdp->sapi], pdp->nsapi, pdp->mm);
+ return sndcp_unitdata_req(msg, &mm->llme->lle[pdp->sapi],
+ pdp->nsapi, mm);
}
/* Called by SNDCP when it has received/re-assembled a N-PDU */