bssgp_rim: add encoder/decoder for NACC related RIM containers

BSSGP RIM uses a number of nested containers to signal RIM application
specific payload information in a generic way. Lets add the container
structurs required for NACC.

Depends: libosmocore If48f412c32e8e5a3e604a78d12b74787a4786374
Change-Id: Ibbc7fd67658e3040c12abb5706fe9d1f31894352
Related: SYS#5103
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e0220bd..10306aa 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -75,7 +75,7 @@
 endif
 
 if ENABLE_GB
-check_PROGRAMS += gb/bssgp_fc_test gb/gprs_bssgp_test gb/gprs_ns_test gb/gprs_ns2_test fr/fr_test
+check_PROGRAMS += gb/bssgp_fc_test gb/gprs_bssgp_test gb/gprs_bssgp_rim_test gb/gprs_ns_test gb/gprs_ns2_test fr/fr_test
 endif
 
 utils_utils_test_SOURCES = utils/utils_test.c
@@ -176,6 +176,10 @@
 			   $(top_builddir)/src/gsm/libosmogsm.la \
 			   $(top_builddir)/src/gb/libosmogb.la
 
+gb_gprs_bssgp_rim_test_SOURCES = gb/gprs_bssgp_rim_test.c
+gb_gprs_bssgp_rim_test_LDADD = $(LDADD) $(top_builddir)/src/gb/libosmogb.la $(LIBRARY_DLSYM) \
+			       $(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) \
 			$(top_builddir)/src/vty/libosmovty.la \
@@ -334,6 +338,7 @@
              gsm0808/gsm0808_test.ok gb/bssgp_fc_tests.err		\
              gb/bssgp_fc_tests.ok gb/bssgp_fc_tests.sh			\
              gb/gprs_bssgp_test.ok gb/gprs_ns_test.ok gea/gea_test.ok	\
+	     gb/gprs_bssgp_rim_test.ok					\
              gb/gprs_ns2_vty.vty gb/osmoappdesc.py gb/osmo-ns-dummy.cfg \
              gb/gprs_ns2_test.ok					\
              gprs/gprs_test.ok kasumi/kasumi_test.ok			\
diff --git a/tests/gb/gprs_bssgp_rim_test.c b/tests/gb/gprs_bssgp_rim_test.c
new file mode 100644
index 0000000..8c6a00d
--- /dev/null
+++ b/tests/gb/gprs_bssgp_rim_test.c
@@ -0,0 +1,664 @@
+/* Test routines for the BSSGP implementation in libosmogb
+ *
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH
+ * Author: Philipp Maier <pmaier@sysmocom.de>
+ *
+ * Skeleton based on bssgp_fc_test.c
+ * (C) 2012 by Harald Welte <laforge@gnumonks.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#undef _GNU_SOURCE
+#define _GNU_SOURCE
+
+#include <osmocom/core/application.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/gprs/gprs_bssgp.h>
+#include <osmocom/gprs/gprs_ns.h>
+#include <osmocom/gprs/gprs_bssgp_rim.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+void dump_bssgp_ran_inf_req_app_cont_nacc(struct bssgp_ran_inf_req_app_cont_nacc *app_cont)
+{
+	printf(" app_cont: bssgp_ran_inf_req_app_cont_nacc:\n");
+	printf("  reprt_cell.rai.lac.plmn.mcc = %u\n", app_cont->reprt_cell.rai.lac.plmn.mcc);
+	printf("  reprt_cell.rai.lac.plmn.mnc = %u\n", app_cont->reprt_cell.rai.lac.plmn.mnc);
+	printf("  reprt_cell.rai.lac.plmn.mnc_3_digits = %u\n", app_cont->reprt_cell.rai.lac.plmn.mnc_3_digits);
+	printf("  reprt_cell.rai.lac.lac = %u\n", app_cont->reprt_cell.rai.lac.lac);
+	printf("  reprt_cell.rai.rac = %u\n", app_cont->reprt_cell.rai.rac);
+	printf("  reprt_cell.cell_identity = %04x\n", app_cont->reprt_cell.cell_identity);
+}
+
+void dump_bssgp_ran_inf_req_rim_cont(struct bssgp_ran_inf_req_rim_cont *rim_cont)
+{
+	printf("bssgp_ran_inf_req_rim_cont:\n");
+	printf(" app_id = %02x\n", rim_cont->app_id);
+	printf(" seq_num = %08x\n", rim_cont->seq_num);
+	printf(" pdu_ind.ack_requested = %u\n", rim_cont->pdu_ind.ack_requested);
+	printf(" pdu_ind.pdu_type_ext = %u\n", rim_cont->pdu_ind.pdu_type_ext);
+	printf(" prot_ver = %u\n", rim_cont->prot_ver);
+	switch (rim_cont->app_id) {
+	case BSSGP_RAN_INF_APP_ID_NACC:
+		dump_bssgp_ran_inf_req_app_cont_nacc(&rim_cont->u.app_cont_nacc);
+		break;
+	case BSSGP_RAN_INF_APP_ID_SI3:
+	case BSSGP_RAN_INF_APP_ID_MBMS:
+	case BSSGP_RAN_INF_APP_ID_SON:
+	case BSSGP_RAN_INF_APP_ID_UTRA_SI:
+		printf(" app_cont: (not implemented yet)\n");
+		break;
+	default:
+		printf(" app_cont: (illegal application identifier)\n");
+	}
+	if (rim_cont->son_trans_app_id) {
+		printf(" son_trans_app_id: %s\n",
+		       osmo_hexdump_nospc(rim_cont->son_trans_app_id, rim_cont->son_trans_app_id_len));
+		printf(" son_trans_app_id_len: %lu\n", rim_cont->son_trans_app_id_len);
+	}
+}
+
+static void test_bssgp_dec_ran_inf_req_rim_cont_nacc()
+{
+	int rc;
+	struct bssgp_ran_inf_req_rim_cont rim_cont_dec;
+	uint8_t testvec[] =
+	    { 0x4b, 0x81, 0x01, 0x4c, 0x84, 0x00, 0x00, 0x00, 0x01, 0x4f, 0x81, 0x02, 0x55, 0x81, 0x01, 0x4d, 0x88,
+    0x62, 0xf2, 0x24, 0x33, 0x90, 0x00, 0x51, 0xe1 };
+
+	printf("----- %s START\n", __func__);
+
+	rc = bssgp_dec_ran_inf_req_rim_cont(&rim_cont_dec, testvec, sizeof(testvec));
+	printf("rc=%d, ", rc);
+	if (rc == 0)
+		dump_bssgp_ran_inf_req_rim_cont(&rim_cont_dec);
+
+	printf("----- %s END\n", __func__);
+}
+
+static void test_bssgp_enc_ran_inf_req_rim_cont_nacc()
+{
+	int rc;
+	struct bssgp_ran_inf_req_rim_cont rim_cont = { };
+	uint8_t result[256];
+	printf("----- %s START\n", __func__);
+
+	rim_cont.app_id = BSSGP_RAN_INF_APP_ID_NACC;
+	rim_cont.seq_num = 1;
+	rim_cont.pdu_ind.ack_requested = 0;
+	rim_cont.pdu_ind.pdu_type_ext = 1;
+	rim_cont.prot_ver = 1;
+	rim_cont.son_trans_app_id = NULL;
+	rim_cont.son_trans_app_id_len = 0;
+	rim_cont.u.app_cont_nacc.reprt_cell.rai.lac.plmn.mcc = 262;
+	rim_cont.u.app_cont_nacc.reprt_cell.rai.lac.plmn.mnc = 42;
+	rim_cont.u.app_cont_nacc.reprt_cell.rai.lac.plmn.mnc_3_digits = 0;
+	rim_cont.u.app_cont_nacc.reprt_cell.rai.lac.lac = 13200;
+	rim_cont.u.app_cont_nacc.reprt_cell.rai.rac = 0;
+	rim_cont.u.app_cont_nacc.reprt_cell.cell_identity = 0x51e1;
+
+	dump_bssgp_ran_inf_req_rim_cont(&rim_cont);
+
+	rc = bssgp_enc_ran_inf_req_rim_cont(result, sizeof(result), &rim_cont);
+	printf("rc=%d, ", rc);
+	if (rc > 0)
+		printf("result=%s", osmo_hexdump_nospc(result, rc));
+	printf("\n");
+	printf("----- %s END\n", __func__);
+}
+
+static void dump_bssgp_ran_inf_app_cont_nacc(struct bssgp_ran_inf_app_cont_nacc *app_cont)
+{
+	unsigned int i;
+	unsigned int silen;
+	printf(" app_cont: bssgp_ran_inf_app_cont_nacc:\n");
+	printf("  reprt_cell.rai.lac.plmn.mcc = %u\n", app_cont->reprt_cell.rai.lac.plmn.mcc);
+	printf("  reprt_cell.rai.lac.plmn.mnc = %u\n", app_cont->reprt_cell.rai.lac.plmn.mnc);
+	printf("  reprt_cell.rai.lac.plmn.mnc_3_digits = %u\n", app_cont->reprt_cell.rai.lac.plmn.mnc_3_digits);
+	printf("  reprt_cell.rai.lac.lac = %u\n", app_cont->reprt_cell.rai.lac.lac);
+	printf("  reprt_cell.rai.rac = %u\n", app_cont->reprt_cell.rai.rac);
+	printf("  reprt_cell.cell_identity = %04x\n", app_cont->reprt_cell.cell_identity);
+	printf("  type_psi = %u\n", app_cont->type_psi);
+	printf("  num_si = %u\n", app_cont->num_si);
+
+	if (app_cont->type_psi)
+		silen = 22;
+	else
+		silen = 21;
+
+	for (i = 0; i < app_cont->num_si; i++)
+		printf(" si[%u] = %s\n", i, osmo_hexdump_nospc(app_cont->si[i], silen));
+}
+
+static void dump_bssgp_app_err_cont_nacc(struct bssgp_app_err_cont_nacc *app_cont)
+{
+	printf(" app_err_cont: bssgp_app_err_cont_nacc:\n");
+	printf("  macc_cause = %02x\n", app_cont->nacc_cause);
+	if (app_cont->err_app_cont) {
+		printf("  err_app_cont: %s\n", osmo_hexdump_nospc(app_cont->err_app_cont, app_cont->err_app_cont_len));
+		printf("  err_app_cont_len: %lu\n", app_cont->err_app_cont_len);
+	}
+}
+
+static void dump_bssgp_ran_inf_rim_cont(struct bssgp_ran_inf_rim_cont *rim_cont)
+{
+	printf("bssgp_ran_inf_rim_cont:\n");
+	printf(" app_id = %02x\n", rim_cont->app_id);
+	printf(" seq_num = %08x\n", rim_cont->seq_num);
+	printf(" pdu_ind.ack_requested = %u\n", rim_cont->pdu_ind.ack_requested);
+	printf(" pdu_ind.pdu_type_ext = %u\n", rim_cont->pdu_ind.pdu_type_ext);
+	printf(" prot_ver = %u\n", rim_cont->prot_ver);
+	printf(" app_err = %u\n", rim_cont->app_err);
+	if (rim_cont->app_err) {
+		switch (rim_cont->app_id) {
+		case BSSGP_RAN_INF_APP_ID_NACC:
+			dump_bssgp_app_err_cont_nacc(&rim_cont->u.app_err_cont_nacc);
+			break;
+		case BSSGP_RAN_INF_APP_ID_SI3:
+		case BSSGP_RAN_INF_APP_ID_MBMS:
+		case BSSGP_RAN_INF_APP_ID_SON:
+		case BSSGP_RAN_INF_APP_ID_UTRA_SI:
+			printf(" app_err_cont: (not implemented yet)\n");
+			break;
+		default:
+			printf(" app_err_cont: (illegal application identifier)\n");
+		}
+	} else {
+		switch (rim_cont->app_id) {
+		case BSSGP_RAN_INF_APP_ID_NACC:
+			dump_bssgp_ran_inf_app_cont_nacc(&rim_cont->u.app_cont_nacc);
+			break;
+		case BSSGP_RAN_INF_APP_ID_SI3:
+		case BSSGP_RAN_INF_APP_ID_MBMS:
+		case BSSGP_RAN_INF_APP_ID_SON:
+		case BSSGP_RAN_INF_APP_ID_UTRA_SI:
+			printf(" app_cont: (not implemented yet)\n");
+			break;
+		default:
+			printf(" app_cont: (illegal application identifier)\n");
+		}
+	}
+	if (rim_cont->son_trans_app_id) {
+		printf(" son_trans_app_id: %s\n",
+		       osmo_hexdump_nospc(rim_cont->son_trans_app_id, rim_cont->son_trans_app_id_len));
+		printf(" son_trans_app_id_len: %lu\n", rim_cont->son_trans_app_id_len);
+	}
+}
+
+static void test_bssgp_dec_ran_inf_rim_cont_nacc()
+{
+	int rc;
+	struct bssgp_ran_inf_rim_cont rim_cont_dec;
+	uint8_t testvec[] =
+	    { 0x4b, 0x81, 0x01, 0x4c, 0x84, 0x00, 0x00, 0x00, 0x02, 0x4f, 0x81, 0x02, 0x55, 0x81, 0x01, 0x4e, 0xc8,
+		0x62, 0xf2, 0x24, 0x33, 0x4f, 0x00, 0x51, 0xe0, 0x06, 0x19, 0x8f, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00,
+		    0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x2b, 0x1b, 0x75, 0x30, 0x00, 0xf1, 0x10,
+		    0x23, 0x6e,
+		0xc9, 0x03, 0x3c, 0x27, 0x47, 0x40, 0x79, 0x00, 0x00, 0x3c, 0x0b, 0x2b, 0x2b, 0x00, 0x90, 0x00, 0x18,
+		    0x5a, 0x6f,
+		0xc9, 0xe0, 0x84, 0x10, 0xab, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b
+	};
+
+	printf("----- %s START\n", __func__);
+
+	rc = bssgp_dec_ran_inf_rim_cont(&rim_cont_dec, testvec, sizeof(testvec));
+	printf("rc=%d, ", rc);
+	if (rc == 0)
+		dump_bssgp_ran_inf_rim_cont(&rim_cont_dec);
+
+	printf("----- %s END\n", __func__);
+}
+
+static void test_bssgp_dec_ran_inf_rim_cont_err_nacc()
+{
+	int rc;
+	struct bssgp_ran_inf_rim_cont rim_cont_dec;
+	uint8_t testvec[] =
+	    { 0x4b, 0x81, 0x01, 0x4c, 0x84, 0x00, 0x00, 0x00, 0x01, 0x4f, 0x81, 0x02, 0x55, 0x81, 0x01, 0x56, 0x86,
+    0x01, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
+
+	printf("----- %s START\n", __func__);
+
+	rc = bssgp_dec_ran_inf_rim_cont(&rim_cont_dec, testvec, sizeof(testvec));
+	printf("rc=%d, ", rc);
+	if (rc == 0)
+		dump_bssgp_ran_inf_rim_cont(&rim_cont_dec);
+
+	printf("----- %s END\n", __func__);
+}
+
+static void test_bssgp_enc_ran_inf_rim_cont_nacc()
+{
+	int rc;
+	struct bssgp_ran_inf_rim_cont rim_cont = { };
+
+	uint8_t si1[] =
+	    { 0x19, 0x8f, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x79, 0x00, 0x00, 0x2b
+	};
+	uint8_t si3[] =
+	    { 0x1b, 0x75, 0x30, 0x00, 0xf1, 0x10, 0x23, 0x6e, 0xc9, 0x03, 0x3c, 0x27, 0x47, 0x40, 0x79, 0x00, 0x00,
+		0x3c, 0x0b, 0x2b, 0x2b
+	};
+	uint8_t si13[] =
+	    { 0x00, 0x90, 0x00, 0x18, 0x5a, 0x6f, 0xc9, 0xe0, 0x84, 0x10, 0xab, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b,
+		0x2b, 0x2b, 0x2b, 0x2b
+	};
+
+	uint8_t result[256];
+	printf("----- %s START\n", __func__);
+
+	rim_cont.app_id = BSSGP_RAN_INF_APP_ID_NACC;
+	rim_cont.seq_num = 1;
+	rim_cont.pdu_ind.ack_requested = 0;
+	rim_cont.pdu_ind.pdu_type_ext = 1;
+	rim_cont.prot_ver = 1;
+	rim_cont.son_trans_app_id = NULL;
+	rim_cont.son_trans_app_id_len = 0;
+	rim_cont.app_err = false;
+	rim_cont.u.app_cont_nacc.reprt_cell.rai.lac.plmn.mcc = 262;
+	rim_cont.u.app_cont_nacc.reprt_cell.rai.lac.plmn.mnc = 42;
+	rim_cont.u.app_cont_nacc.reprt_cell.rai.lac.plmn.mnc_3_digits = 0;
+	rim_cont.u.app_cont_nacc.reprt_cell.rai.lac.lac = 13135;
+	rim_cont.u.app_cont_nacc.reprt_cell.rai.rac = 0;
+	rim_cont.u.app_cont_nacc.reprt_cell.cell_identity = 0x51e0;
+	rim_cont.u.app_cont_nacc.type_psi = 0;
+	rim_cont.u.app_cont_nacc.num_si = 3;
+	rim_cont.u.app_cont_nacc.si[0] = si1;
+	rim_cont.u.app_cont_nacc.si[1] = si3;
+	rim_cont.u.app_cont_nacc.si[2] = si13;
+
+	dump_bssgp_ran_inf_rim_cont(&rim_cont);
+
+	rc = bssgp_enc_ran_inf_rim_cont(result, sizeof(result), &rim_cont);
+	printf("rc=%d, ", rc);
+	if (rc > 0)
+		printf("result=%s", osmo_hexdump_nospc(result, rc));
+	printf("\n");
+	printf("----- %s END\n", __func__);
+}
+
+static void test_bssgp_enc_ran_inf_rim_cont_err_nacc()
+{
+	int rc;
+	struct bssgp_ran_inf_rim_cont rim_cont = { };
+	uint8_t err_app_cont[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
+
+	uint8_t result[256];
+	printf("----- %s START\n", __func__);
+
+	rim_cont.app_id = BSSGP_RAN_INF_APP_ID_NACC;
+	rim_cont.seq_num = 1;
+	rim_cont.pdu_ind.ack_requested = 0;
+	rim_cont.pdu_ind.pdu_type_ext = 1;
+	rim_cont.prot_ver = 1;
+	rim_cont.son_trans_app_id = NULL;
+	rim_cont.son_trans_app_id_len = 0;
+	rim_cont.app_err = true;
+	rim_cont.u.app_err_cont_nacc.nacc_cause = BSSGP_NACC_CAUSE_SYNTAX_ERR;
+	rim_cont.u.app_err_cont_nacc.err_app_cont = err_app_cont;
+	rim_cont.u.app_err_cont_nacc.err_app_cont_len = sizeof(err_app_cont);
+	dump_bssgp_ran_inf_rim_cont(&rim_cont);
+
+	rc = bssgp_enc_ran_inf_rim_cont(result, sizeof(result), &rim_cont);
+	printf("rc=%d, ", rc);
+	if (rc > 0)
+		printf("result=%s", osmo_hexdump_nospc(result, rc));
+	printf("\n");
+	printf("----- %s END\n", __func__);
+}
+
+static void dump_bssgp_ran_inf_ack_rim_cont(struct bssgp_ran_inf_ack_rim_cont *rim_cont)
+{
+	printf("bssgp_ran_inf_ack_rim_cont:\n");
+	printf(" app_id = %02x\n", rim_cont->app_id);
+	printf(" seq_num = %08x\n", rim_cont->seq_num);
+	printf(" prot_ver = %u\n", rim_cont->prot_ver);
+	if (rim_cont->son_trans_app_id) {
+		printf(" son_trans_app_id: %s\n",
+		       osmo_hexdump_nospc(rim_cont->son_trans_app_id, rim_cont->son_trans_app_id_len));
+		printf(" son_trans_app_id_len: %lu\n", rim_cont->son_trans_app_id_len);
+	}
+}
+
+static void test_bssgp_dec_ran_inf_ack_rim_cont()
+{
+	int rc;
+	struct bssgp_ran_inf_ack_rim_cont rim_cont_dec;
+	uint8_t testvec[] = { 0x4b, 0x81, 0x01, 0x4c, 0x84, 0x00, 0x00, 0x00, 0x01, 0x55, 0x81, 0x01 };
+
+	printf("----- %s START\n", __func__);
+
+	rc = bssgp_dec_ran_inf_ack_rim_cont(&rim_cont_dec, testvec, sizeof(testvec));
+	printf("rc=%d, ", rc);
+	if (rc == 0)
+		dump_bssgp_ran_inf_ack_rim_cont(&rim_cont_dec);
+
+	printf("----- %s END\n", __func__);
+}
+
+static void test_bssgp_enc_ran_inf_ack_rim_cont()
+{
+	int rc;
+	struct bssgp_ran_inf_ack_rim_cont rim_cont = { };
+	uint8_t result[256];
+	printf("----- %s START\n", __func__);
+
+	rim_cont.app_id = BSSGP_RAN_INF_APP_ID_NACC;
+	rim_cont.seq_num = 1;
+	rim_cont.prot_ver = 1;
+	rim_cont.son_trans_app_id = NULL;
+	rim_cont.son_trans_app_id_len = 0;
+	dump_bssgp_ran_inf_ack_rim_cont(&rim_cont);
+
+	rc = bssgp_enc_ran_inf_ack_rim_cont(result, sizeof(result), &rim_cont);
+	printf("rc=%d, ", rc);
+	if (rc > 0)
+		printf("result=%s", osmo_hexdump_nospc(result, rc));
+	printf("\n");
+	printf("----- %s END\n", __func__);
+}
+
+void dump_bssgp_ran_inf_err_rim_cont(struct bssgp_ran_inf_err_rim_cont *rim_cont)
+{
+	printf("bssgp_ran_inf_err_rim_cont:\n");
+	printf(" app_id = %02x\n", rim_cont->app_id);
+	printf(" cause = %02x\n", rim_cont->cause);
+	printf(" prot_ver = %u\n", rim_cont->prot_ver);
+	if (rim_cont->err_pdu) {
+		printf(" err_pdu: %s\n", osmo_hexdump_nospc(rim_cont->err_pdu, rim_cont->err_pdu_len));
+		printf(" err_pdu_len: %lu\n", rim_cont->err_pdu_len);
+	}
+	if (rim_cont->son_trans_app_id) {
+		printf(" son_trans_app_id: %s\n",
+		       osmo_hexdump_nospc(rim_cont->son_trans_app_id, rim_cont->son_trans_app_id_len));
+		printf(" son_trans_app_id_len: %lu\n", rim_cont->son_trans_app_id_len);
+	}
+}
+
+static void test_bssgp_dec_ran_inf_err_rim_cont()
+{
+	int rc;
+	struct bssgp_ran_inf_err_rim_cont rim_cont_dec;
+	uint8_t testvec[] =
+	    { 0x4b, 0x81, 0x17, 0x07, 0x81, 0x2b, 0x55, 0x81, 0x01, 0x15, 0x85, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
+
+	printf("----- %s START\n", __func__);
+
+	rc = bssgp_dec_ran_inf_err_rim_cont(&rim_cont_dec, testvec, sizeof(testvec));
+	printf("rc=%d, ", rc);
+	if (rc == 0)
+		dump_bssgp_ran_inf_err_rim_cont(&rim_cont_dec);
+
+	printf("----- %s END\n", __func__);
+}
+
+static void test_bssgp_enc_ran_inf_err_rim_cont()
+{
+	int rc;
+	struct bssgp_ran_inf_err_rim_cont rim_cont = { };
+	uint8_t err_pdu[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
+	uint8_t result[256];
+	printf("----- %s START\n", __func__);
+
+	rim_cont.app_id = 23;
+	rim_cont.cause = 0x2b;
+	rim_cont.prot_ver = 1;
+	rim_cont.err_pdu = err_pdu;
+	rim_cont.err_pdu_len = sizeof(err_pdu);
+	rim_cont.son_trans_app_id = NULL;
+	rim_cont.son_trans_app_id_len = 0;
+	dump_bssgp_ran_inf_err_rim_cont(&rim_cont);
+
+	rc = bssgp_enc_ran_inf_err_rim_cont(result, sizeof(result), &rim_cont);
+	printf("rc=%d, ", rc);
+	if (rc > 0)
+		printf("result=%s", osmo_hexdump_nospc(result, rc));
+	printf("\n");
+	printf("----- %s END\n", __func__);
+}
+
+void dump_bssgp_ran_inf_app_err_rim_cont(struct bssgp_ran_inf_app_err_rim_cont *rim_cont)
+{
+	printf("bssgp_ran_inf_app_err_rim_cont:\n");
+	printf(" app_id = %02x\n", rim_cont->app_id);
+	printf(" seq_num = %08x\n", rim_cont->seq_num);
+	printf(" pdu_ind.ack_requested = %u\n", rim_cont->pdu_ind.ack_requested);
+	printf(" pdu_ind.pdu_type_ext = %u\n", rim_cont->pdu_ind.pdu_type_ext);
+	printf(" prot_ver = %u\n", rim_cont->prot_ver);
+	switch (rim_cont->app_id) {
+	case BSSGP_RAN_INF_APP_ID_NACC:
+		dump_bssgp_app_err_cont_nacc(&rim_cont->u.app_err_cont_nacc);
+		break;
+	case BSSGP_RAN_INF_APP_ID_SI3:
+	case BSSGP_RAN_INF_APP_ID_MBMS:
+	case BSSGP_RAN_INF_APP_ID_SON:
+	case BSSGP_RAN_INF_APP_ID_UTRA_SI:
+		printf(" app_err_cont: (not implemented yet)\n");
+		break;
+	default:
+		printf(" app_err_cont: (illegal application identifier)\n");
+	}
+}
+
+static void test_bssgp_dec_ran_inf_app_err_rim_cont_nacc()
+{
+	int rc;
+	struct bssgp_ran_inf_app_err_rim_cont rim_cont_dec;
+	uint8_t testvec[] =
+	    { 0x4b, 0x81, 0x01, 0x4c, 0x84, 0x00, 0x00, 0x00, 0x01, 0x4f, 0x81, 0x02, 0x55, 0x81, 0x01, 0x56, 0x85,
+		0xaa, 0xbb, 0xcc, 0xdd, 0xee
+	};
+
+	printf("----- %s START\n", __func__);
+
+	rc = bssgp_dec_ran_inf_app_err_rim_cont(&rim_cont_dec, testvec, sizeof(testvec));
+	printf("rc=%d, ", rc);
+	if (rc == 0)
+		dump_bssgp_ran_inf_app_err_rim_cont(&rim_cont_dec);
+
+	printf("----- %s END\n", __func__);
+}
+
+static void test_bssgp_enc_ran_inf_app_err_rim_cont_nacc()
+{
+	int rc;
+	struct bssgp_ran_inf_app_err_rim_cont rim_cont = { };
+	uint8_t err_app_cont[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
+	uint8_t result[256];
+
+	printf("----- %s START\n", __func__);
+	rim_cont.app_id = BSSGP_RAN_INF_APP_ID_NACC;
+	rim_cont.seq_num = 1;
+	rim_cont.pdu_ind.ack_requested = 0;
+	rim_cont.pdu_ind.pdu_type_ext = 1;
+	rim_cont.prot_ver = 1;
+	rim_cont.u.app_err_cont_nacc.nacc_cause = BSSGP_NACC_CAUSE_SYNTAX_ERR;
+	rim_cont.u.app_err_cont_nacc.err_app_cont = err_app_cont;
+	rim_cont.u.app_err_cont_nacc.err_app_cont_len = sizeof(err_app_cont);
+	dump_bssgp_ran_inf_app_err_rim_cont(&rim_cont);
+
+	rc = bssgp_enc_ran_inf_app_err_rim_cont(result, sizeof(result), &rim_cont);
+	printf("rc=%d, ", rc);
+	if (rc > 0)
+		printf("result=%s", osmo_hexdump_nospc(result, rc));
+	printf("\n");
+	printf("----- %s END\n", __func__);
+}
+
+static void test_bssgp_dec_ran_inf_req_app_cont_nacc()
+{
+	int rc;
+	struct bssgp_ran_inf_req_app_cont_nacc app_cont_dec;
+	uint8_t testvec[] = { 0x62, 0xf2, 0x24, 0x33, 0x90, 0x00, 0x51, 0xe1 };
+
+	printf("----- %s START\n", __func__);
+
+	rc = bssgp_dec_ran_inf_req_app_cont_nacc(&app_cont_dec, testvec, sizeof(testvec));
+	printf("rc=%d, ", rc);
+	if (rc == 0)
+		dump_bssgp_ran_inf_req_app_cont_nacc(&app_cont_dec);
+
+	printf("----- %s END\n", __func__);
+}
+
+static void test_bssgp_enc_ran_inf_req_app_cont_nacc()
+{
+	int rc;
+	struct bssgp_ran_inf_req_app_cont_nacc app_cont = { };
+	uint8_t result[256];
+	printf("----- %s START\n", __func__);
+
+	app_cont.reprt_cell.rai.lac.plmn.mcc = 262;
+	app_cont.reprt_cell.rai.lac.plmn.mnc = 42;
+	app_cont.reprt_cell.rai.lac.plmn.mnc_3_digits = 0;
+	app_cont.reprt_cell.rai.lac.lac = 13200;
+	app_cont.reprt_cell.rai.rac = 0;
+	app_cont.reprt_cell.cell_identity = 0x51e1;
+	dump_bssgp_ran_inf_req_app_cont_nacc(&app_cont);
+
+	rc = bssgp_enc_ran_inf_req_app_cont_nacc(result, sizeof(result), &app_cont);
+	printf("rc=%d, ", rc);
+	if (rc > 0)
+		printf("result=%s", osmo_hexdump_nospc(result, rc));
+	printf("\n");
+	printf("----- %s END\n", __func__);
+}
+
+static void test_bssgp_dec_ran_inf_app_cont_nacc()
+{
+	int rc;
+	struct bssgp_ran_inf_app_cont_nacc app_cont_dec;
+	uint8_t testvec[] =
+	    { 0x62, 0xf2, 0x24, 0x33, 0x4f, 0x00, 0x51, 0xe0, 0x06, 0x19, 0x8f, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x2b, 0x1b, 0x75, 0x30, 0x00, 0xf1, 0x10,
+    0x23, 0x6e, 0xc9, 0x03, 0x3c, 0x27, 0x47, 0x40, 0x79, 0x00, 0x00, 0x3c, 0x0b, 0x2b, 0x2b, 0x00, 0x90, 0x00, 0x18,
+    0x5a, 0x6f, 0xc9, 0xe0, 0x84, 0x10, 0xab, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b };
+
+	printf("----- %s START\n", __func__);
+
+	rc = bssgp_dec_ran_inf_app_cont_nacc(&app_cont_dec, testvec, sizeof(testvec));
+	printf("rc=%d, ", rc);
+	if (rc == 0)
+		dump_bssgp_ran_inf_app_cont_nacc(&app_cont_dec);
+
+	printf("----- %s END\n", __func__);
+}
+
+static void test_bssgp_enc_ran_inf_app_cont_nacc()
+{
+	int rc;
+	struct bssgp_ran_inf_app_cont_nacc app_cont = { };
+
+	uint8_t si1[] =
+	    { 0x19, 0x8f, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x79, 0x00, 0x00, 0x2b };
+	uint8_t si3[] =
+	    { 0x1b, 0x75, 0x30, 0x00, 0xf1, 0x10, 0x23, 0x6e, 0xc9, 0x03, 0x3c, 0x27, 0x47, 0x40, 0x79, 0x00, 0x00,
+	0x3c, 0x0b, 0x2b, 0x2b };
+	uint8_t si13[] =
+	    { 0x00, 0x90, 0x00, 0x18, 0x5a, 0x6f, 0xc9, 0xe0, 0x84, 0x10, 0xab, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b,
+       0x2b, 0x2b, 0x2b, 0x2b };
+
+	uint8_t result[256];
+	printf("----- %s START\n", __func__);
+
+	app_cont.reprt_cell.rai.lac.plmn.mcc = 262;
+	app_cont.reprt_cell.rai.lac.plmn.mnc = 42;
+	app_cont.reprt_cell.rai.lac.plmn.mnc_3_digits = 0;
+	app_cont.reprt_cell.rai.lac.lac = 13135;
+	app_cont.reprt_cell.rai.rac = 0;
+	app_cont.reprt_cell.cell_identity = 0x51e1;
+	app_cont.type_psi = false;
+	app_cont.num_si = 3;
+	app_cont.si[0] = si1;
+	app_cont.si[1] = si3;
+	app_cont.si[2] = si13;
+	dump_bssgp_ran_inf_app_cont_nacc(&app_cont);
+
+	rc = bssgp_enc_ran_inf_app_cont_nacc(result, sizeof(result), &app_cont);
+	printf("rc=%d, ", rc);
+	if (rc > 0)
+		printf("result=%s", osmo_hexdump_nospc(result, rc));
+	printf("\n");
+	printf("----- %s END\n", __func__);
+}
+
+static void test_bssgp_dec_app_err_cont_nacc()
+{
+	int rc;
+	struct bssgp_app_err_cont_nacc app_cont_dec;
+	uint8_t testvec[] = { 0x01, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
+
+	printf("----- %s START\n", __func__);
+
+	rc = bssgp_dec_app_err_cont_nacc(&app_cont_dec, testvec, sizeof(testvec));
+	printf("rc=%d, ", rc);
+	if (rc == 0)
+		dump_bssgp_app_err_cont_nacc(&app_cont_dec);
+
+	printf("----- %s END\n", __func__);
+}
+
+static void test_bssgp_enc_app_err_cont_nacc()
+{
+	int rc;
+	struct bssgp_app_err_cont_nacc app_cont = { };
+	uint8_t err_app_cont[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
+	uint8_t result[256];
+	printf("----- %s START\n", __func__);
+
+	app_cont.nacc_cause = BSSGP_NACC_CAUSE_SYNTAX_ERR;
+	app_cont.err_app_cont = err_app_cont;
+	app_cont.err_app_cont_len = sizeof(err_app_cont);
+	dump_bssgp_app_err_cont_nacc(&app_cont);
+
+	rc = bssgp_enc_app_err_cont_nacc(result, sizeof(result), &app_cont);
+	printf("rc=%d, ", rc);
+	if (rc > 0)
+		printf("result=%s", osmo_hexdump_nospc(result, rc));
+	printf("\n");
+	printf("----- %s END\n", __func__);
+}
+
+int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
+{
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	printf("===== BSSGP RIM test START\n");
+
+	/* RIM containers */
+	test_bssgp_dec_ran_inf_req_rim_cont_nacc();
+	test_bssgp_enc_ran_inf_req_rim_cont_nacc();
+	test_bssgp_dec_ran_inf_rim_cont_nacc();
+	test_bssgp_dec_ran_inf_rim_cont_err_nacc();
+	test_bssgp_enc_ran_inf_rim_cont_nacc();
+	test_bssgp_enc_ran_inf_rim_cont_err_nacc();
+	test_bssgp_dec_ran_inf_ack_rim_cont();
+	test_bssgp_enc_ran_inf_ack_rim_cont();
+	test_bssgp_dec_ran_inf_err_rim_cont();
+	test_bssgp_enc_ran_inf_err_rim_cont();
+	test_bssgp_dec_ran_inf_app_err_rim_cont_nacc();
+	test_bssgp_enc_ran_inf_app_err_rim_cont_nacc();
+
+	/* Application containers */
+	test_bssgp_dec_ran_inf_req_app_cont_nacc();
+	test_bssgp_enc_ran_inf_req_app_cont_nacc();
+	test_bssgp_dec_ran_inf_app_cont_nacc();
+	test_bssgp_enc_ran_inf_app_cont_nacc();
+	test_bssgp_dec_app_err_cont_nacc();
+	test_bssgp_enc_app_err_cont_nacc();
+
+	printf("===== BSSGP RIM test END\n\n");
+
+	exit(EXIT_SUCCESS);
+}
diff --git a/tests/gb/gprs_bssgp_rim_test.ok b/tests/gb/gprs_bssgp_rim_test.ok
new file mode 100644
index 0000000..d075ca3
--- /dev/null
+++ b/tests/gb/gprs_bssgp_rim_test.ok
@@ -0,0 +1,220 @@
+===== BSSGP RIM test START
+----- test_bssgp_dec_ran_inf_req_rim_cont_nacc START
+rc=0, bssgp_ran_inf_req_rim_cont:
+ app_id = 01
+ seq_num = 00000001
+ pdu_ind.ack_requested = 0
+ pdu_ind.pdu_type_ext = 1
+ prot_ver = 1
+ app_cont: bssgp_ran_inf_req_app_cont_nacc:
+  reprt_cell.rai.lac.plmn.mcc = 262
+  reprt_cell.rai.lac.plmn.mnc = 42
+  reprt_cell.rai.lac.plmn.mnc_3_digits = 0
+  reprt_cell.rai.lac.lac = 13200
+  reprt_cell.rai.rac = 0
+  reprt_cell.cell_identity = 51e1
+----- test_bssgp_dec_ran_inf_req_rim_cont_nacc END
+----- test_bssgp_enc_ran_inf_req_rim_cont_nacc START
+bssgp_ran_inf_req_rim_cont:
+ app_id = 01
+ seq_num = 00000001
+ pdu_ind.ack_requested = 0
+ pdu_ind.pdu_type_ext = 1
+ prot_ver = 1
+ app_cont: bssgp_ran_inf_req_app_cont_nacc:
+  reprt_cell.rai.lac.plmn.mcc = 262
+  reprt_cell.rai.lac.plmn.mnc = 42
+  reprt_cell.rai.lac.plmn.mnc_3_digits = 0
+  reprt_cell.rai.lac.lac = 13200
+  reprt_cell.rai.rac = 0
+  reprt_cell.cell_identity = 51e1
+rc=25, result=4b81014c84000000014f81025581014d8862f22433900051e1
+----- test_bssgp_enc_ran_inf_req_rim_cont_nacc END
+----- test_bssgp_dec_ran_inf_rim_cont_nacc START
+rc=0, bssgp_ran_inf_rim_cont:
+ app_id = 01
+ seq_num = 00000002
+ pdu_ind.ack_requested = 0
+ pdu_ind.pdu_type_ext = 1
+ prot_ver = 1
+ app_err = 0
+ app_cont: bssgp_ran_inf_app_cont_nacc:
+  reprt_cell.rai.lac.plmn.mcc = 262
+  reprt_cell.rai.lac.plmn.mnc = 42
+  reprt_cell.rai.lac.plmn.mnc_3_digits = 0
+  reprt_cell.rai.lac.lac = 13135
+  reprt_cell.rai.rac = 0
+  reprt_cell.cell_identity = 51e0
+  type_psi = 0
+  num_si = 3
+ si[0] = 198fb100000000000000000000000000007900002b
+ si[1] = 1b753000f110236ec9033c2747407900003c0b2b2b
+ si[2] = 009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b
+----- test_bssgp_dec_ran_inf_rim_cont_nacc END
+----- test_bssgp_dec_ran_inf_rim_cont_err_nacc START
+rc=0, bssgp_ran_inf_rim_cont:
+ app_id = 01
+ seq_num = 00000001
+ pdu_ind.ack_requested = 0
+ pdu_ind.pdu_type_ext = 1
+ prot_ver = 1
+ app_err = 1
+ app_err_cont: bssgp_app_err_cont_nacc:
+  macc_cause = 01
+  err_app_cont: aabbccddee
+  err_app_cont_len: 5
+----- test_bssgp_dec_ran_inf_rim_cont_err_nacc END
+----- test_bssgp_enc_ran_inf_rim_cont_nacc START
+bssgp_ran_inf_rim_cont:
+ app_id = 01
+ seq_num = 00000001
+ pdu_ind.ack_requested = 0
+ pdu_ind.pdu_type_ext = 1
+ prot_ver = 1
+ app_err = 0
+ app_cont: bssgp_ran_inf_app_cont_nacc:
+  reprt_cell.rai.lac.plmn.mcc = 262
+  reprt_cell.rai.lac.plmn.mnc = 42
+  reprt_cell.rai.lac.plmn.mnc_3_digits = 0
+  reprt_cell.rai.lac.lac = 13135
+  reprt_cell.rai.rac = 0
+  reprt_cell.cell_identity = 51e0
+  type_psi = 0
+  num_si = 3
+ si[0] = 198fb100000000000000000000000000007900002b
+ si[1] = 1b753000f110236ec9033c2747407900003c0b2b2b
+ si[2] = 009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b
+rc=89, result=4b81014c84000000014f81025581014ec862f224334f0051e006198fb100000000000000000000000000007900002b1b753000f110236ec9033c2747407900003c0b2b2b009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b
+----- test_bssgp_enc_ran_inf_rim_cont_nacc END
+----- test_bssgp_enc_ran_inf_rim_cont_err_nacc START
+bssgp_ran_inf_rim_cont:
+ app_id = 01
+ seq_num = 00000001
+ pdu_ind.ack_requested = 0
+ pdu_ind.pdu_type_ext = 1
+ prot_ver = 1
+ app_err = 1
+ app_err_cont: bssgp_app_err_cont_nacc:
+  macc_cause = 01
+  err_app_cont: aabbccddee
+  err_app_cont_len: 5
+rc=23, result=4b81014c84000000014f8102558101568601aabbccddee
+----- test_bssgp_enc_ran_inf_rim_cont_err_nacc END
+----- test_bssgp_dec_ran_inf_ack_rim_cont START
+rc=0, bssgp_ran_inf_ack_rim_cont:
+ app_id = 01
+ seq_num = 00000001
+ prot_ver = 1
+----- test_bssgp_dec_ran_inf_ack_rim_cont END
+----- test_bssgp_enc_ran_inf_ack_rim_cont START
+bssgp_ran_inf_ack_rim_cont:
+ app_id = 01
+ seq_num = 00000001
+ prot_ver = 1
+rc=12, result=4b81014c8400000001558101
+----- test_bssgp_enc_ran_inf_ack_rim_cont END
+----- test_bssgp_dec_ran_inf_err_rim_cont START
+rc=0, bssgp_ran_inf_err_rim_cont:
+ app_id = 17
+ cause = 2b
+ prot_ver = 1
+ err_pdu: aabbccddee
+ err_pdu_len: 5
+----- test_bssgp_dec_ran_inf_err_rim_cont END
+----- test_bssgp_enc_ran_inf_err_rim_cont START
+bssgp_ran_inf_err_rim_cont:
+ app_id = 17
+ cause = 2b
+ prot_ver = 1
+ err_pdu: aabbccddee
+ err_pdu_len: 5
+rc=16, result=4b811707812b5581011585aabbccddee
+----- test_bssgp_enc_ran_inf_err_rim_cont END
+----- test_bssgp_dec_ran_inf_app_err_rim_cont_nacc START
+rc=0, bssgp_ran_inf_app_err_rim_cont:
+ app_id = 01
+ seq_num = 00000001
+ pdu_ind.ack_requested = 0
+ pdu_ind.pdu_type_ext = 1
+ prot_ver = 1
+ app_err_cont: bssgp_app_err_cont_nacc:
+  macc_cause = aa
+  err_app_cont: bbccddee
+  err_app_cont_len: 4
+----- test_bssgp_dec_ran_inf_app_err_rim_cont_nacc END
+----- test_bssgp_enc_ran_inf_app_err_rim_cont_nacc START
+bssgp_ran_inf_app_err_rim_cont:
+ app_id = 01
+ seq_num = 00000001
+ pdu_ind.ack_requested = 0
+ pdu_ind.pdu_type_ext = 1
+ prot_ver = 1
+ app_err_cont: bssgp_app_err_cont_nacc:
+  macc_cause = 01
+  err_app_cont: aabbccddee
+  err_app_cont_len: 5
+rc=23, result=4b81014c84000000014f8102558101568601aabbccddee
+----- test_bssgp_enc_ran_inf_app_err_rim_cont_nacc END
+----- test_bssgp_dec_ran_inf_req_app_cont_nacc START
+rc=0,  app_cont: bssgp_ran_inf_req_app_cont_nacc:
+  reprt_cell.rai.lac.plmn.mcc = 262
+  reprt_cell.rai.lac.plmn.mnc = 42
+  reprt_cell.rai.lac.plmn.mnc_3_digits = 0
+  reprt_cell.rai.lac.lac = 13200
+  reprt_cell.rai.rac = 0
+  reprt_cell.cell_identity = 51e1
+----- test_bssgp_dec_ran_inf_req_app_cont_nacc END
+----- test_bssgp_enc_ran_inf_req_app_cont_nacc START
+ app_cont: bssgp_ran_inf_req_app_cont_nacc:
+  reprt_cell.rai.lac.plmn.mcc = 262
+  reprt_cell.rai.lac.plmn.mnc = 42
+  reprt_cell.rai.lac.plmn.mnc_3_digits = 0
+  reprt_cell.rai.lac.lac = 13200
+  reprt_cell.rai.rac = 0
+  reprt_cell.cell_identity = 51e1
+rc=8, result=62f22433900051e1
+----- test_bssgp_enc_ran_inf_req_app_cont_nacc END
+----- test_bssgp_dec_ran_inf_app_cont_nacc START
+rc=0,  app_cont: bssgp_ran_inf_app_cont_nacc:
+  reprt_cell.rai.lac.plmn.mcc = 262
+  reprt_cell.rai.lac.plmn.mnc = 42
+  reprt_cell.rai.lac.plmn.mnc_3_digits = 0
+  reprt_cell.rai.lac.lac = 13135
+  reprt_cell.rai.rac = 0
+  reprt_cell.cell_identity = 51e0
+  type_psi = 0
+  num_si = 3
+ si[0] = 198fb100000000000000000000000000007900002b
+ si[1] = 1b753000f110236ec9033c2747407900003c0b2b2b
+ si[2] = 009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b
+----- test_bssgp_dec_ran_inf_app_cont_nacc END
+----- test_bssgp_enc_ran_inf_app_cont_nacc START
+ app_cont: bssgp_ran_inf_app_cont_nacc:
+  reprt_cell.rai.lac.plmn.mcc = 262
+  reprt_cell.rai.lac.plmn.mnc = 42
+  reprt_cell.rai.lac.plmn.mnc_3_digits = 0
+  reprt_cell.rai.lac.lac = 13135
+  reprt_cell.rai.rac = 0
+  reprt_cell.cell_identity = 51e1
+  type_psi = 0
+  num_si = 3
+ si[0] = 198fb100000000000000000000000000007900002b
+ si[1] = 1b753000f110236ec9033c2747407900003c0b2b2b
+ si[2] = 009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b
+rc=72, result=62f224334f0051e106198fb100000000000000000000000000007900002b1b753000f110236ec9033c2747407900003c0b2b2b009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b
+----- test_bssgp_enc_ran_inf_app_cont_nacc END
+----- test_bssgp_dec_app_err_cont_nacc START
+rc=0,  app_err_cont: bssgp_app_err_cont_nacc:
+  macc_cause = 01
+  err_app_cont: aabbccddee
+  err_app_cont_len: 5
+----- test_bssgp_dec_app_err_cont_nacc END
+----- test_bssgp_enc_app_err_cont_nacc START
+ app_err_cont: bssgp_app_err_cont_nacc:
+  macc_cause = 01
+  err_app_cont: aabbccddee
+  err_app_cont_len: 5
+rc=6, result=01aabbccddee
+----- test_bssgp_enc_app_err_cont_nacc END
+===== BSSGP RIM test END
+
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 75ce039..d715a3e 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -215,6 +215,12 @@
 AT_CHECK([$abs_top_builddir/tests/gb/gprs_bssgp_test], [0], [expout], [ignore])
 AT_CLEANUP
 
+AT_SETUP([gprs-bssgp-rim])
+AT_KEYWORDS([gprs-bssgp-rim])
+cat $abs_srcdir/gb/gprs_bssgp_rim_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/gb/gprs_bssgp_rim_test], [0], [expout], [ignore])
+AT_CLEANUP
+
 AT_SETUP([gprs-ns])
 AT_KEYWORDS([gprs-ns])
 cat $abs_srcdir/gb/gprs_ns_test.ok > expout