add gsm0808_cell_id_from_cgi(), gsm0808_cell_id_to_cgi()

CGI to Cell ID: for example, for Paging, osmo-msc has a CGI for a subscriber
and needs to send out a Cell Identifier IE. Makes sense to add this conversion
here.

Cell ID to CGI: for a Layer 3 Complete, a subscriber sends the current cell in
the form of a Cell Identifier, which we store as a CGI, if necessary enriched
with the local PLMN.

Add enum with bitmask values to identify parts of a CGI, for the return value
of gsm0808_cell_id_to_cgi(). Can't use enum CELL_IDENT for that, because it
doesn't have a value for just a PLMN (and is not a bitmask).

Change-Id: Ib9af67b100c4583342a2103669732dab2e577b04
diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c
index af90d00..c448f43 100644
--- a/tests/gsm0808/gsm0808_test.c
+++ b/tests/gsm0808/gsm0808_test.c
@@ -2206,29 +2206,96 @@
 	return true;
 }
 
+const enum CELL_IDENT cell_ident_discrs[] = {
+	CELL_IDENT_LAC, CELL_IDENT_CI, CELL_IDENT_LAC_AND_CI, CELL_IDENT_LAI_AND_LAC,
+	CELL_IDENT_WHOLE_GLOBAL,
+};
+
+
 static void test_cell_id_list_matching(bool test_match)
 {
 	int i, j;
 	bool ok = true;
 
-	const enum CELL_IDENT discrs[] = {
-		CELL_IDENT_LAC, CELL_IDENT_CI, CELL_IDENT_LAC_AND_CI, CELL_IDENT_LAI_AND_LAC,
-		CELL_IDENT_WHOLE_GLOBAL,
-	};
-
 	printf("\n%s(%s)\n", __func__, test_match ? "test match" : "test mismatch");
 
 	/* Autogenerate Cell ID lists from above dataset, which should match / not match. */
-	for (i = 0; i < ARRAY_SIZE(discrs); i++) {
-		for (j = 0; j < ARRAY_SIZE(discrs); j++)
+	for (i = 0; i < ARRAY_SIZE(cell_ident_discrs); i++) {
+		for (j = 0; j < ARRAY_SIZE(cell_ident_discrs); j++)
 			if (!test_cell_id_list_matching_discrs(test_match,
-							       discrs[i], discrs[j]))
+							       cell_ident_discrs[i], cell_ident_discrs[j]))
 				ok = false;
 	}
 
 	OSMO_ASSERT(ok);
 }
 
+
+static const struct gsm0808_cell_id test_gsm0808_cell_id_to_from_cgi_data[] = {
+	lac_23,
+	lac_42,
+	ci_5,
+	ci_6,
+	lac_ci_23_5,
+	lac_ci_42_6,
+	lai_23_042_23,
+	lai_23_042_42,
+	lai_23_99_23,
+	lai_23_42_23,
+	cgi_23_042_23_5,
+	cgi_23_042_42_6,
+	cgi_23_99_23_5,
+	{ .id_discr = CELL_IDENT_NO_CELL },
+	{ .id_discr = 423 },
+};
+
+static void test_gsm0808_cell_id_to_from_cgi()
+{
+	int i;
+	int j;
+
+	printf("\n%s()\n", __func__);
+
+	for (i = 0; i < ARRAY_SIZE(test_gsm0808_cell_id_to_from_cgi_data); i++) {
+		const struct gsm0808_cell_id *from_cid = &test_gsm0808_cell_id_to_from_cgi_data[i];
+		struct osmo_cell_global_id cgi = {
+			.lai = {
+				.plmn = {
+					.mcc = 777,
+					.mnc = 7,
+					.mnc_3_digits = true,
+				},
+				.lac = 7777,
+			},
+			.cell_identity = 7777,
+		};
+		struct gsm0808_cell_id cid = {};
+		int rc;
+
+		rc = gsm0808_cell_id_to_cgi(&cgi, from_cid);
+		printf("cid %s -> cgi %s", gsm0808_cell_id_name(from_cid), osmo_cgi_name(&cgi));
+
+		if (rc & OSMO_CGI_PART_PLMN)
+			printf(" PLMN");
+		if (rc & OSMO_CGI_PART_LAC)
+			printf(" LAC");
+		if (rc & OSMO_CGI_PART_CI)
+			printf(" CI");
+
+		gsm0808_cell_id_from_cgi(&cid, from_cid->id_discr, &cgi);
+		printf(" -> cid %s\n", gsm0808_cell_id_name(&cid));
+		if (!gsm0808_cell_ids_match(from_cid, &cid, true))
+			printf("      MISMATCH!\n");
+
+		for (j = 0; j < ARRAY_SIZE(cell_ident_discrs); j++) {
+			enum CELL_IDENT discr = cell_ident_discrs[j];
+
+			gsm0808_cell_id_from_cgi(&cid, discr, &cgi);
+			printf("  --> gsm0808_cell_id{%s} = %s\n", gsm0808_cell_id_discr_name(discr), gsm0808_cell_id_name(&cid));
+		}
+	}
+}
+
 int main(int argc, char **argv)
 {
 	void *ctx = talloc_named_const(NULL, 0, "gsm0808 test");
@@ -2300,6 +2367,8 @@
 	test_cell_id_list_matching(true);
 	test_cell_id_list_matching(false);
 
+	test_gsm0808_cell_id_to_from_cgi();
+
 	printf("Done\n");
 	return EXIT_SUCCESS;
 }