[gprs] pass BSSGP UL-UNITDATA Cell ID up into GMM layer

BSSGP stores a pointer to the Cell Identifier IE in msgb->cb, which
is later used by the GMM layer to identify the cell that has sent a
given message.

This now also means that the gsm_04_08_gprs.c code is free of any
legacy references to msg->trx or struct gsm_bts.
diff --git a/openbsc/src/gprs_bssgp.c b/openbsc/src/gprs_bssgp.c
index a3fa3ec..aceedb5 100644
--- a/openbsc/src/gprs_bssgp.c
+++ b/openbsc/src/gprs_bssgp.c
@@ -205,13 +205,12 @@
 	return gprs_ns_sendmsg(bssgp_nsi, msg);
 }
 
-static void bssgp_parse_cell_id(struct gprs_ra_id *raid, uint16_t *cid,
-				const uint8_t *buf)
+uint16_t bssgp_parse_cell_id(struct gprs_ra_id *raid, const uint8_t *buf)
 {
 	/* 6 octets RAC */
 	gsm48_parse_ra(raid, buf);
 	/* 2 octets CID */
-	*cid = ntohs(*(uint16_t *) (buf+6));
+	return ntohs(*(uint16_t *) (buf+6));
 }
 
 /* Chapter 8.4 BVC-Reset Procedure */
@@ -241,8 +240,8 @@
 			return -EINVAL;
 		}
 		/* actually extract RAC / CID */
-		bssgp_parse_cell_id(&bctx->ra_id, &bctx->cell_id,
-				    TLVP_VAL(tp, BSSGP_IE_CELL_ID));
+		bctx->cell_id = bssgp_parse_cell_id(&bctx->ra_id,
+						TLVP_VAL(tp, BSSGP_IE_CELL_ID));
 		LOGP(DGPRS, LOGL_NOTICE, "Cell %u-%u-%u-%u CI %u on BVCI %u\n",
 			bctx->ra_id.mcc, bctx->ra_id.mnc, bctx->ra_id.lac,
 			bctx->ra_id.rac, bctx->cell_id, bvci);
@@ -275,7 +274,9 @@
 
 	/* FIXME: lookup bssgp_bts_ctx based on BVCI + NSEI */
 
+	/* store pointer to LLC header and CELL ID in msgb->cb */
 	msgb_llch(msg) = TLVP_VAL(&tp, BSSGP_IE_LLC_PDU);
+	msgb_bcid(msg) = TLVP_VAL(&tp, BSSGP_IE_CELL_ID);
 
 	return gprs_llc_rcvmsg(msg, &tp);
 }
diff --git a/openbsc/src/gprs_llc.c b/openbsc/src/gprs_llc.c
index fdaa7b3..6d15636 100644
--- a/openbsc/src/gprs_llc.c
+++ b/openbsc/src/gprs_llc.c
@@ -452,6 +452,8 @@
 	struct gprs_llc_entity *lle;
 	int rc = 0;
 
+	/* Identifiers from DOWN: NSEI, BVCI, TLLI */
+
 	rc = gprs_llc_hdr_parse(&llhp, lh, TLVP_LEN(tv, BSSGP_IE_LLC_PDU));
 	/* FIXME */
 
diff --git a/openbsc/src/gsm_04_08_gprs.c b/openbsc/src/gsm_04_08_gprs.c
index 7d24657..ef61ade 100644
--- a/openbsc/src/gsm_04_08_gprs.c
+++ b/openbsc/src/gsm_04_08_gprs.c
@@ -42,6 +42,7 @@
 #include <osmocore/signal.h>
 #include <osmocore/talloc.h>
 #include <openbsc/transaction.h>
+#include <openbsc/gprs_bssgp.h>
 #include <openbsc/gprs_llc.h>
 #include <openbsc/gprs_sgsn.h>
 
@@ -130,20 +131,30 @@
 /* Send a message through the underlying layer */
 static int gsm48_gmm_sendmsg(struct msgb *msg, int command)
 {
+	/* caller needs to provide TLLI, BVCI and NSEI */
 	return gprs_llc_tx_ui(msg, GPRS_SAPI_GMM, command);
 }
 
+/* copy identifiers from old message to new message, this
+ * is required so lower layers can route it correctly */
+static void gmm_copy_id(struct msgb *msg, const struct msgb *old)
+{
+	msgb_tlli(msg) = msgb_tlli(old);
+	msgb_bvci(msg) = msgb_bvci(old);
+	msgb_nsei(msg) = msgb_nsei(old);
+}
+
 /* Chapter 9.4.2: Attach accept */
 static int gsm48_tx_gmm_att_ack(struct msgb *old_msg)
 {
 	struct msgb *msg = gsm48_msgb_alloc();
 	struct gsm48_hdr *gh;
 	struct gsm48_attach_ack *aa;
+	struct gprs_ra_id ra_id;
 
 	DEBUGP(DMM, "<- GPRS ATTACH ACCEPT\n");
 
-	msgb_tlli(msg) = msgb_tlli(old_msg);
-	msg->trx = old_msg->trx;
+	gmm_copy_id(msg, old_msg);
 
 	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
 	gh->proto_discr = GSM48_PDISC_MM_GPRS;
@@ -154,7 +165,8 @@
 	aa->att_result = 1;	/* GPRS only */
 	aa->ra_upd_timer = GPRS_TMR_MINUTE | 10;
 	aa->radio_prio = 4;	/* lowest */
-	//FIXME gsm48_ra_id_by_bts(aa->ra_id.digits, old_msg->trx->bts);
+	bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
+	gsm48_construct_ra(aa->ra_id.digits, &ra_id);
 
 	/* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
 	return gsm48_gmm_sendmsg(msg, 0);
@@ -168,8 +180,7 @@
 
 	DEBUGP(DMM, "<- GPRS ATTACH REJECT\n");
 
-	msgb_tlli(msg) = msgb_tlli(old_msg);
-	msg->trx = old_msg->trx;
+	gmm_copy_id(msg, old_msg);
 
 	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
 	gh->proto_discr = GSM48_PDISC_MM_GPRS;
@@ -187,8 +198,7 @@
 
 	DEBUGP(DMM, "-> GPRS IDENTITY REQUEST: mi_type=%02x\n", id_type);
 
-	msgb_tlli(msg) = msgb_tlli(old_msg);
-	msg->trx = old_msg->trx;
+	gmm_copy_id(msg, old_msg);
 
 	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
 	gh->proto_discr = GSM48_PDISC_MM_GPRS;
@@ -228,7 +238,7 @@
 	DEBUGP(DMM, "GMM IDENTITY RESPONSE: mi_type=0x%02x MI(%s) ",
 		mi_type, mi_string);
 
-	//FIXME gprs_ra_id_by_bts(&ra_id, msg->trx->bts);
+	bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
 	ctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &ra_id);
 	if (!ctx) {
 		DEBUGP(DMM, "from unknown TLLI 0x%08x?!?\n", msgb_tlli(msg));
@@ -290,7 +300,7 @@
 	 * with a foreign TLLI (P-TMSI that was allocated to the MS before),
 	 * or with random TLLI. */
 
-	//FIXME gprs_ra_id_by_bts(&ra_id, msg->trx->bts);
+	bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
 
 	/* MS network capability 10.5.5.12 */
 	msnc_len = *cur++;
@@ -378,11 +388,11 @@
 	struct msgb *msg = gsm48_msgb_alloc();
 	struct gsm48_hdr *gh;
 	struct gsm48_ra_upd_ack *rua;
+	struct gprs_ra_id ra_id;
 
 	DEBUGP(DMM, "<- ROUTING AREA UPDATE ACCEPT\n");
 
-	msgb_tlli(msg) = msgb_tlli(old_msg);
-	msg->trx = old_msg->trx;
+	gmm_copy_id(msg, old_msg);
 
 	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
 	gh->proto_discr = GSM48_PDISC_MM_GPRS;
@@ -392,7 +402,9 @@
 	rua->force_stby = 0;	/* not indicated */
 	rua->upd_result = 0;	/* RA updated */
 	rua->ra_upd_timer = GPRS_TMR_MINUTE | 10;
-	//FIXME gsm48_ra_id_by_bts(rua->ra_id.digits, old_msg->trx->bts);
+
+	bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
+	gsm48_construct_ra(rua->ra_id.digits, &ra_id);
 
 	/* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
 	return gsm48_gmm_sendmsg(msg, 0);
@@ -406,8 +418,7 @@
 
 	DEBUGP(DMM, "<- ROUTING AREA UPDATE REJECT\n");
 
-	msgb_tlli(msg) = msgb_tlli(old_msg);
-	msg->trx = old_msg->trx;
+	gmm_copy_id(msg, old_msg);
 
 	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 2);
 	gh->proto_discr = GSM48_PDISC_MM_GPRS;
@@ -529,8 +540,7 @@
 
 	DEBUGP(DMM, "<- ACTIVATE PDP CONTEXT ACK\n");
 
-	msgb_tlli(msg) = msgb_tlli(old_msg);
-	msg->trx = old_msg->trx;
+	gmm_copy_id(msg, old_msg);
 
 	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
 	gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
@@ -554,8 +564,7 @@
 
 	DEBUGP(DMM, "<- DEACTIVATE PDP CONTEXT ACK\n");
 
-	msgb_tlli(msg) = msgb_tlli(old_msg);
-	msg->trx = old_msg->trx;
+	gmm_copy_id(msg, old_msg);
 
 	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
 	gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
@@ -652,30 +661,3 @@
 
 	return rc;
 }
-
-/* Determine the 'struct gsm_bts' from a RA ID */
-struct gsm_bts *gsm48_bts_by_ra_id(struct gsm_network *net,
-				   const uint8_t *buf, unsigned int len)
-{
-	struct gprs_ra_id raid;
-	struct gsm_bts *bts;
-
-	if (len < 6)
-		return NULL;
-
-	gsm48_parse_ra(&raid, buf);
-
-	if (net->country_code != raid.mcc ||
-	    net->network_code != raid.mnc)
-		return NULL;
-
-	llist_for_each_entry(bts, &net->bts_list, list) {
-		/* FIXME: we actually also need to check the
-		 * routing area code! */
-		if (bts->location_area_code == raid.lac)
-			return bts;
-	}
-
-	return NULL;
-}
-