pcu_l1_if: get rid of strange paging group calculation

The PCU uses a 16 bit integer value as paging group which does in fact
not really resamble the paging group. Instead it encodes the last three
digits of the IMSI from which the paging group can be calculated. The
value is then eventually converted back to Ascii-digits and then sent
over the PCU-IF interface. Lets get rid of this weird conversion and
use the IMSI directly.

Change-Id: I40d7fc14c9591b3de091e425faaf325421c70a0e
diff --git a/src/bts.cpp b/src/bts.cpp
index 504ba27..524961d 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -1131,7 +1131,7 @@
 		if (the_pcu->pcu_if_version >= 0x0b)
 			pcu_l1if_tx_pch_dt(bts, immediate_assignment, plen, tbf->imsi(), tbf->tlli());
 		else
-			pcu_l1if_tx_pch(bts, immediate_assignment, plen, ms_paging_group(tbf_ms(tbf)));
+			pcu_l1if_tx_pch(bts, immediate_assignment, plen, tbf->imsi());
 	}
 
 	bitvec_free(immediate_assignment);
diff --git a/src/gprs_bssgp_pcu.c b/src/gprs_bssgp_pcu.c
index f441437..656342e 100644
--- a/src/gprs_bssgp_pcu.c
+++ b/src/gprs_bssgp_pcu.c
@@ -289,7 +289,6 @@
 	struct osmo_mobile_identity mi_imsi;
 	struct osmo_mobile_identity paging_mi;
 	struct gprs_rlcmac_bts *bts;
-	uint16_t pgroup;
 	int rc;
 
 	rate_ctr_inc(rate_ctr_group_get_ctr(the_pcu->bssgp.ctrs, SGSN_CTR_RX_PAGING_PS));
@@ -304,11 +303,6 @@
 		LOGP(DBSSGP, LOGL_NOTICE, "Failed to parse IMSI IE (rc=%d)\n", rc);
 		return bssgp_tx_status(BSSGP_CAUSE_INV_MAND_INF, NULL, msg);
 	}
-	pgroup = imsi2paging_group(mi_imsi.imsi);
-	if (pgroup > 999) {
-		LOGP(DBSSGP, LOGL_NOTICE, "Failed to compute IMSI %s paging group\n", mi_imsi.imsi);
-		return bssgp_tx_status(BSSGP_CAUSE_INV_MAND_INF, NULL, msg);
-	}
 
 	if ((rc = get_paging_ps_mi(&paging_mi, tp)) > 0)
 		return bssgp_tx_status((enum gprs_bssgp_cause) rc, NULL, msg);
@@ -320,7 +314,7 @@
 			bts_do_rate_ctr_inc(bts, CTR_PCH_REQUESTS_ALREADY);
 			continue;
 		}
-		if (gprs_rlcmac_paging_request(bts, &paging_mi, pgroup) < 0)
+		if (gprs_rlcmac_paging_request(bts, &paging_mi, mi_imsi.imsi) < 0)
 			continue;
 		bts_pch_timer_start(bts, &paging_mi, mi_imsi.imsi);
 	}
diff --git a/src/gprs_ms.c b/src/gprs_ms.c
index eb76fa2..7ecaae4 100644
--- a/src/gprs_ms.c
+++ b/src/gprs_ms.c
@@ -577,18 +577,6 @@
 		tbf_update_state_fsm_name(dl_tbf_as_tbf(ms->dl_tbf));
 }
 
-uint16_t ms_paging_group(struct GprsMs *ms)
-{
-	uint16_t pgroup;
-	if (!ms_imsi_is_valid(ms))
-		return 0; /* 000 is the special "all paging" group */
-	if ((pgroup = imsi2paging_group(ms_imsi(ms))) > 999) {
-		LOGPMS(ms, DRLCMAC, LOGL_ERROR, "IMSI to paging group failed!\n");
-		return 0;
-	}
-	return pgroup;
-}
-
 void ms_set_ta(struct GprsMs *ms, uint8_t ta_)
 {
 	if (ta_ == ms->ta)
diff --git a/src/gprs_ms.h b/src/gprs_ms.h
index 835ff18..9b957ac 100644
--- a/src/gprs_ms.h
+++ b/src/gprs_ms.h
@@ -131,7 +131,6 @@
 void ms_set_tlli(struct GprsMs *ms, uint32_t tlli);
 bool ms_confirm_tlli(struct GprsMs *ms, uint32_t tlli);
 void ms_set_imsi(struct GprsMs *ms, const char *imsi);
-uint16_t ms_paging_group(struct GprsMs *ms);
 
 void ms_update_l1_meas(struct GprsMs *ms, const struct pcu_l1_meas *meas);
 
diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp
index 1ea0872..ea7fb9a 100644
--- a/src/gprs_rlcmac.cpp
+++ b/src/gprs_rlcmac.cpp
@@ -29,7 +29,7 @@
 extern void *tall_pcu_ctx;
 
 int gprs_rlcmac_paging_request(struct gprs_rlcmac_bts *bts, const struct osmo_mobile_identity *mi,
-			       uint16_t pgroup)
+			       const char *imsi)
 {
 	if (log_check_level(DRLCMAC, LOGL_NOTICE)) {
 		char str[64];
@@ -44,7 +44,7 @@
 		return -1;
 	}
 	bts_do_rate_ctr_inc(bts, CTR_PCH_REQUESTS);
-	pcu_l1if_tx_pch(bts, paging_request, plen, pgroup);
+	pcu_l1if_tx_pch(bts, paging_request, plen, imsi);
 	bitvec_free(paging_request);
 
 	return 0;
diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h
index 22a33b4..43f5095 100644
--- a/src/gprs_rlcmac.h
+++ b/src/gprs_rlcmac.h
@@ -100,7 +100,7 @@
 
 extern "C" {
 #endif
-int gprs_rlcmac_paging_request(struct gprs_rlcmac_bts *bts, const struct osmo_mobile_identity *mi, uint16_t pgroup);
+int gprs_rlcmac_paging_request(struct gprs_rlcmac_bts *bts, const struct osmo_mobile_identity *mi, const char *imsi);
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp
index 6ec806b..84d39cb 100644
--- a/src/pcu_l1_if.cpp
+++ b/src/pcu_l1_if.cpp
@@ -59,8 +59,6 @@
 
 extern void *tall_pcu_ctx;
 
-#define PAGING_GROUP_LEN 3
-
 struct e1_ccu_conn_pars {
 	struct llist_head entry;
 
@@ -78,27 +76,6 @@
  * when it is needed. */
 static LLIST_HEAD(e1_ccu_table);
 
-/* returns [0,999] on success, > 999 on error */
-uint16_t imsi2paging_group(const char* imsi)
-{
-	uint16_t pgroup = 0;
-	size_t len;
-
-	len = (imsi != NULL) ? strlen(imsi) : 0;
-	if (len < PAGING_GROUP_LEN)
-		return 0xFFFF;
-	imsi += len - PAGING_GROUP_LEN;
-
-	while (*imsi != '\0') {
-		if (!isdigit(*imsi))
-			return 0xFFFF;
-		pgroup *= 10;
-		pgroup += *imsi - '0';
-		imsi++;
-	}
-	return pgroup;
-}
-
 /*
  * PCU messages
  */
@@ -286,24 +263,23 @@
 	pcu_tx_data_req(bts, 0, 0, PCU_IF_SAPI_AGCH, 0, 0, 0, data, sizeof(data));
 }
 
-void pcu_l1if_tx_pch(struct gprs_rlcmac_bts *bts, bitvec *block, int plen, uint16_t pgroup)
+#define IMSI_DIGITS_FOR_PAGING 3
+void pcu_l1if_tx_pch(struct gprs_rlcmac_bts *bts, bitvec *block, int plen, const char *imsi)
 {
-	uint8_t data[PAGING_GROUP_LEN + GSM_MACBLOCK_LEN];
-	int i;
+	uint8_t data[IMSI_DIGITS_FOR_PAGING + GSM_MACBLOCK_LEN];
 
-	/* prepend paging group */
-	for (i = 0; i < PAGING_GROUP_LEN; i++) {
-		data[PAGING_GROUP_LEN - 1 - i] = '0' + (char)(pgroup % 10);
-		pgroup = pgroup / 10;
-	}
-	OSMO_ASSERT(pgroup == 0);
+	/* prepend last three IMSI digits (if present) from which BTS/BSC will calculate the paging group */
+	if (imsi && strlen(imsi) >= IMSI_DIGITS_FOR_PAGING)
+		memcpy(data, imsi + strlen(imsi) - IMSI_DIGITS_FOR_PAGING, IMSI_DIGITS_FOR_PAGING);
+	else
+		memset(data, '0', IMSI_DIGITS_FOR_PAGING);
 
 	/* block provided by upper layer comes without first byte (plen),
 	 * prepend it manually:
 	 */
-	OSMO_ASSERT(sizeof(data) >= PAGING_GROUP_LEN + 1 + block->data_len);
+	OSMO_ASSERT(sizeof(data) >= IMSI_DIGITS_FOR_PAGING + 1 + block->data_len);
 	data[3] = (plen << 2) | 0x01;
-	bitvec_pack(block, data + PAGING_GROUP_LEN + 1);
+	bitvec_pack(block, data + IMSI_DIGITS_FOR_PAGING + 1);
 
 	if (the_pcu->gsmtap_categ_mask & (1 << PCU_GSMTAP_C_DL_PCH))
 		gsmtap_send(the_pcu->gsmtap, 0, 0, GSMTAP_CHANNEL_PCH, 0, 0, 0, 0, data + 3, GSM_MACBLOCK_LEN);
diff --git a/src/pcu_l1_if.h b/src/pcu_l1_if.h
index d3d70e4..3865402 100644
--- a/src/pcu_l1_if.h
+++ b/src/pcu_l1_if.h
@@ -148,7 +148,7 @@
 		       uint8_t *data, size_t data_len);
 void pcu_l1if_tx_agch(struct gprs_rlcmac_bts *bts, bitvec *block, int len);
 
-void pcu_l1if_tx_pch(struct gprs_rlcmac_bts *bts, bitvec *block, int plen, uint16_t pgroup);
+void pcu_l1if_tx_pch(struct gprs_rlcmac_bts *bts, bitvec *block, int plen, const char *imsi);
 void pcu_l1if_tx_pch_dt(struct gprs_rlcmac_bts *bts, bitvec *block, int plen, const char *imsi, uint32_t tlli);
 #endif
 
@@ -176,7 +176,6 @@
 	uint8_t len, uint32_t fn, struct pcu_l1_meas *meas);
 
 void pcu_rx_block_time(struct gprs_rlcmac_bts *bts, uint16_t arfcn, uint32_t fn, uint8_t ts_no);
-uint16_t imsi2paging_group(const char* imsi);
 
 struct e1_conn_pars {
 	/* Number of E1 line */