Example #1
0
/* 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);
}
Example #2
0
/* 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);
}
Example #3
0
/*! \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);
}