/* Called by SNDCP when it has received/re-assembled a N-PDU */ int sgsn_rx_sndcp_ud_ind(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi, struct msgb *msg, uint32_t npdu_len, uint8_t *npdu) { struct sgsn_mm_ctx *mmctx; struct sgsn_pdp_ctx *pdp; /* look-up the MM context for this message */ mmctx = sgsn_mm_ctx_by_tlli(tlli, ra_id); if (!mmctx) { LOGP(DGPRS, LOGL_ERROR, "Cannot find MM CTX for TLLI %08x\n", tlli); return -EIO; } /* look-up the PDP context for this message */ pdp = sgsn_pdp_ctx_by_nsapi(mmctx, nsapi); if (!pdp) { LOGP(DGPRS, LOGL_ERROR, "Cannot find PDP CTX for " "TLLI=%08x, NSAPI=%u\n", tlli, nsapi); return -EIO; } if (!pdp->lib) { LOGP(DGPRS, LOGL_ERROR, "PDP CTX without libgtp\n"); return -EIO; } rate_ctr_inc(&pdp->ctrg->ctr[PDP_CTR_PKTS_UDATA_IN]); rate_ctr_add(&pdp->ctrg->ctr[PDP_CTR_BYTES_UDATA_IN], npdu_len); rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_UDATA_IN]); rate_ctr_add(&mmctx->ctrg->ctr[GMM_CTR_BYTES_UDATA_IN], npdu_len); return gtp_data_req(pdp->ggsn->gsn, pdp->lib, npdu, npdu_len); }
/* 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 sgsn_mm_ctx *mm; struct msgb *msg; uint8_t *ud; int rc; DEBUGP(DGPRS, "GTP DATA IND from GGSN, length=%u\n", len); 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+256, 128, "GTP->SNDCP"); ud = msgb_put(msg, len); memcpy(ud, packet, len); 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); rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PAGING_PS]); /* 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; } rate_ctr_inc(&pdp->ctrg->ctr[PDP_CTR_PKTS_UDATA_OUT]); rate_ctr_add(&pdp->ctrg->ctr[PDP_CTR_BYTES_UDATA_OUT], len); rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PKTS_UDATA_OUT]); rate_ctr_add(&mm->ctrg->ctr[GMM_CTR_BYTES_UDATA_OUT], len); return sndcp_unitdata_req(msg, &mm->llme->lle[pdp->sapi], pdp->nsapi, mm); }
/*! \brief RL-UL-UNITDATA.req (Chapter 10.2.2) * \param[in] bctx BVC Context * \param[in] tlli TLLI to identify MS * \param[in] qos_profile Pointer to three octests of QoS profile * \param[in] llc_pdu msgb pointer containing UL Unitdata IE payload */ int bssgp_tx_ul_ud(struct bssgp_bvc_ctx *bctx, uint32_t tlli, const uint8_t *qos_profile, struct msgb *llc_pdu) { struct msgb *msg = llc_pdu; uint8_t bssgp_cid[8]; uint8_t bssgp_align[3] = {0, 0, 0}; struct bssgp_ud_hdr *budh; int align = sizeof(*budh); /* FIXME: Optional LSA Identifier List, PFI */ /* Cell Identifier */ bssgp_create_cell_id(bssgp_cid, &bctx->ra_id, bctx->cell_id); align += 2; /* add T+L */ align += sizeof(bssgp_cid); /* First push alignment IE */ align += 2; /* add T+L */ align = (4 - align) & 3; /* how many octest are required to align? */ msgb_tvlv_push(msg, BSSGP_IE_ALIGNMENT, align, bssgp_align); /* Push other IEs */ msgb_tvlv_push(msg, BSSGP_IE_CELL_ID, sizeof(bssgp_cid), bssgp_cid); /* User Data Header */ budh = (struct bssgp_ud_hdr *) msgb_push(msg, sizeof(*budh)); budh->tlli = htonl(tlli); memcpy(budh->qos_profile, qos_profile, 3); budh->pdu_type = BSSGP_PDUT_UL_UNITDATA; /* set NSEI and BVCI in msgb cb */ msgb_nsei(msg) = bctx->nsei; msgb_bvci(msg) = bctx->bvci; rate_ctr_inc(&bctx->ctrg->ctr[BSSGP_CTR_PKTS_OUT]); rate_ctr_add(&bctx->ctrg->ctr[BSSGP_CTR_BYTES_OUT], msg->len); return gprs_ns_sendmsg(bssgp_nsi, msg); }