gprs_bssgp: add IE parser/generator for RIM Routing Information

The RIM Routing Information IE (see also 3GPP TS 48.018, section
11.3.70) is used to control the flow of BSSGP rim messages at the SGSN.

Change-Id: I6f88a9aeeb50a612d32e9efd23040c9740bc4f11
Related: SYS#5103
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ed87aca..cb683f7 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -172,7 +172,8 @@
 gb_gprs_bssgp_test_SOURCES = gb/gprs_bssgp_test.c
 gb_gprs_bssgp_test_LDADD = $(LDADD) $(top_builddir)/src/gb/libosmogb.la $(LIBRARY_DLSYM) \
 			   $(top_builddir)/src/vty/libosmovty.la \
-			   $(top_builddir)/src/gsm/libosmogsm.la
+			   $(top_builddir)/src/gsm/libosmogsm.la \
+			   $(top_builddir)/src/gb/libosmogb.la
 
 gb_gprs_ns_test_SOURCES = gb/gprs_ns_test.c
 gb_gprs_ns_test_LDADD = $(LDADD) $(top_builddir)/src/gb/libosmogb.la $(LIBRARY_DLSYM) \
diff --git a/tests/gb/gprs_bssgp_test.c b/tests/gb/gprs_bssgp_test.c
index 52e986e..e1c920a 100644
--- a/tests/gb/gprs_bssgp_test.c
+++ b/tests/gb/gprs_bssgp_test.c
@@ -289,6 +289,137 @@
 	printf("----- %s END\n", __func__);
 }
 
+void dump_rim_ri(struct bssgp_rim_routing_info *ri)
+{
+	switch (ri->discr) {
+	case BSSGP_RIM_ROUTING_INFO_GERAN:
+		printf("GERAN cell identifier\n");
+		printf(" * mcc: %u\n", ri->geran.raid.mcc);
+		printf("   mnc: %u\n", ri->geran.raid.mnc);
+		printf("   mnc 3 digits: %u\n", ri->geran.raid.mnc_3_digits);
+		printf("   lac: %u\n", ri->geran.raid.lac);
+		printf("   rac: %u\n", ri->geran.raid.rac);
+		printf(" * cell id: %04x\n", ri->geran.cid);
+		break;
+	case BSSGP_RIM_ROUTING_INFO_UTRAN:
+		printf("UTRAN RNC identifier\n");
+		printf(" * mcc: %u\n", ri->utran.raid.mcc);
+		printf("   mnc: %u\n", ri->utran.raid.mnc);
+		printf("   mnc 3 digits: %u\n", ri->utran.raid.mnc_3_digits);
+		printf("   lac: %u\n", ri->utran.raid.lac);
+		printf("   rac: %u\n", ri->utran.raid.rac);
+		printf(" * rnc id: %04x\n", ri->utran.rncid);
+		break;
+	case BSSGP_RIM_ROUTING_INFO_EUTRAN:
+		printf("EUTRAN eNB identifier\n");
+		printf(" * mcc: %u\n", ri->eutran.tai.mcc);
+		printf("   mnc: %u\n", ri->eutran.tai.mnc);
+		printf("   mnc 3 digits: %u\n", ri->eutran.tai.mnc_3_digits);
+		printf("   tac: %u\n", ri->eutran.tai.tac);
+		printf(" * global_enb_id: %s\n",
+		       osmo_hexdump_nospc(ri->eutran.global_enb_id,
+					  ri->eutran.global_enb_id_len));
+		break;
+	default:
+		OSMO_ASSERT(false);
+	}
+}
+
+static void test_bssgp_parse_rim_ri()
+{
+	int rc;
+	struct bssgp_rim_routing_info result;
+	uint8_t testvec_geran[] =
+	    { 0x00, 0x62, 0xf2, 0x24, 0x33, 0x90, 0x00, 0x51, 0xe1 };
+	uint8_t testvec_utran[] =
+	    { 0x01, 0x62, 0xf2, 0x24, 0x33, 0x90, 0x00, 0x51, 0xe1 };
+	uint8_t testvec_eutran[] =
+	    { 0x02, 0x62, 0xf2, 0x24, 0x33, 0x90, 0x00, 0x51, 0xe1 };
+
+	printf("----- %s START\n", __func__);
+
+	rc = bssgp_parse_rim_ri(&result, testvec_geran,
+				sizeof(testvec_geran));
+	printf("rc=%d\n", rc);
+	dump_rim_ri(&result);
+	printf("\n");
+
+	rc = bssgp_parse_rim_ri(&result, testvec_utran,
+				sizeof(testvec_utran));
+	printf("rc=%d\n", rc);
+	dump_rim_ri(&result);
+	printf("\n");
+
+	rc = bssgp_parse_rim_ri(&result, testvec_eutran,
+				sizeof(testvec_eutran));
+	printf("rc=%d\n", rc);
+	dump_rim_ri(&result);
+	printf("\n");
+
+	printf("----- %s END\n", __func__);
+}
+
+static void test_bssgp_create_rim_ri()
+{
+	int rc;
+	struct bssgp_rim_routing_info ri;
+	uint8_t result[15];
+
+	printf("----- %s START\n", __func__);
+	memset(&ri, 0, sizeof(ri));
+	memset(result, 0, sizeof(result));
+	ri.discr = BSSGP_RIM_ROUTING_INFO_GERAN;
+
+	ri.geran.raid.mcc = 262;
+	ri.geran.raid.mnc = 42;
+	ri.geran.raid.mnc_3_digits = false;
+	ri.geran.raid.lac = 13200;
+	ri.geran.raid.rac = 0;
+	ri.geran.cid = 0x51e1;
+	dump_rim_ri(&ri);
+	rc = bssgp_create_rim_ri(result, &ri);
+	printf("rc=%d, ", rc);
+	if (rc > 0)
+		printf("result=%s", osmo_hexdump_nospc(result, rc));
+	printf("\n\n");
+
+	memset(&ri, 0, sizeof(ri));
+	memset(result, 0, sizeof(result));
+	ri.discr = BSSGP_RIM_ROUTING_INFO_UTRAN;
+	ri.utran.raid.mcc = 262;
+	ri.utran.raid.mnc = 42;
+	ri.utran.raid.mnc_3_digits = 0;
+	ri.utran.raid.lac = 13200;
+	ri.utran.raid.rac = 0;
+	ri.utran.rncid = 0x51e1;
+	dump_rim_ri(&ri);
+	rc = bssgp_create_rim_ri(result, &ri);
+	printf("rc=%d, ", rc);
+	if (rc > 0)
+		printf("result=%s", osmo_hexdump_nospc(result, rc));
+	printf("\n\n");
+
+	memset(&ri, 0, sizeof(ri));
+	memset(result, 0, sizeof(result));
+	ri.discr = BSSGP_RIM_ROUTING_INFO_EUTRAN;
+	ri.eutran.tai.mcc = 262;
+	ri.eutran.tai.mnc = 42;
+	ri.eutran.tai.mnc_3_digits = 0;
+	ri.eutran.tai.tac = 13200;
+	ri.eutran.global_enb_id[0] = 0x00;
+	ri.eutran.global_enb_id[1] = 0x51;
+	ri.eutran.global_enb_id[2] = 0xe1;
+	ri.eutran.global_enb_id_len = 3;
+	dump_rim_ri(&ri);
+	rc = bssgp_create_rim_ri(result, &ri);
+	printf("rc=%d, ", rc);
+	if (rc > 0)
+		printf("result=%s", osmo_hexdump_nospc(result, rc));
+	printf("\n\n");
+
+	printf("----- %s END\n", __func__);
+}
+
 static struct log_info info = {};
 
 int main(int argc, char **argv)
@@ -317,6 +448,8 @@
 	test_bssgp_bad_reset();
 	test_bssgp_flow_control_bvc();
 	test_bssgp_msgb_copy();
+	test_bssgp_parse_rim_ri();
+	test_bssgp_create_rim_ri();
 	printf("===== BSSGP test END\n\n");
 
 	exit(EXIT_SUCCESS);
diff --git a/tests/gb/gprs_bssgp_test.ok b/tests/gb/gprs_bssgp_test.ok
index c5b3e7d..744f1a7 100644
--- a/tests/gb/gprs_bssgp_test.ok
+++ b/tests/gb/gprs_bssgp_test.ok
@@ -17,5 +17,61 @@
 Old msgb: [L3]> 22 04 82 00 02 07 81 08 
 New msgb: [L3]> 22 04 82 00 02 07 81 08 
 ----- test_bssgp_msgb_copy END
+----- test_bssgp_parse_rim_ri START
+rc=9
+GERAN cell identifier
+ * mcc: 262
+   mnc: 42
+   mnc 3 digits: 0
+   lac: 13200
+   rac: 0
+ * cell id: 51e1
+
+rc=9
+UTRAN RNC identifier
+ * mcc: 262
+   mnc: 42
+   mnc 3 digits: 0
+   lac: 13200
+   rac: 0
+ * rnc id: 51e1
+
+rc=9
+EUTRAN eNB identifier
+ * mcc: 262
+   mnc: 42
+   mnc 3 digits: 0
+   tac: 13200
+ * global_enb_id: 0051e1
+
+----- test_bssgp_parse_rim_ri END
+----- test_bssgp_create_rim_ri START
+GERAN cell identifier
+ * mcc: 262
+   mnc: 42
+   mnc 3 digits: 0
+   lac: 13200
+   rac: 0
+ * cell id: 51e1
+rc=9, result=0062f22433900051e1
+
+UTRAN RNC identifier
+ * mcc: 262
+   mnc: 42
+   mnc 3 digits: 0
+   lac: 13200
+   rac: 0
+ * rnc id: 51e1
+rc=9, result=0162f22433900051e1
+
+EUTRAN eNB identifier
+ * mcc: 262
+   mnc: 42
+   mnc 3 digits: 0
+   tac: 13200
+ * global_enb_id: 0051e1
+rc=9, result=0262f22433900051e1
+
+----- test_bssgp_create_rim_ri END
 ===== BSSGP test END