aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Maier <pmaier@sysmocom.de>2020-12-14 22:28:19 +0100
committerPhilipp Maier <pmaier@sysmocom.de>2020-12-16 21:58:04 +0100
commitbd10c21cc4cf439e6137fe1c3c9f7321b21526a3 (patch)
tree5d50ed7e41cc54c5987f13ad79fcafda9ca8d880
parent8806796976e0997179cd6a8dd484520748c1c1e0 (diff)
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
-rw-r--r--include/Makefile.am1
-rw-r--r--include/osmocom/gprs/gprs_bssgp.h32
-rw-r--r--include/osmocom/gprs/protocol/gsm_24_301.h11
-rw-r--r--src/gb/gprs_bssgp.c87
-rw-r--r--src/gb/libosmogb.map2
-rw-r--r--tests/Makefile.am3
-rw-r--r--tests/gb/gprs_bssgp_test.c133
-rw-r--r--tests/gb/gprs_bssgp_test.ok56
8 files changed, 324 insertions, 1 deletions
diff --git a/include/Makefile.am b/include/Makefile.am
index 0cb9cd28..842b8720 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -76,6 +76,7 @@ nobase_include_HEADERS = \
osmocom/gprs/protocol/gsm_04_60.h \
osmocom/gprs/protocol/gsm_08_16.h \
osmocom/gprs/protocol/gsm_08_18.h \
+ osmocom/gprs/protocol/gsm_24_301.h \
osmocom/gsm/a5.h \
osmocom/gsm/abis_nm.h \
osmocom/gsm/apn.h \
diff --git a/include/osmocom/gprs/gprs_bssgp.h b/include/osmocom/gprs/gprs_bssgp.h
index dfbd9b73..70770449 100644
--- a/include/osmocom/gprs/gprs_bssgp.h
+++ b/include/osmocom/gprs/gprs_bssgp.h
@@ -10,6 +10,7 @@
#include <osmocom/gsm/prim.h>
#include <osmocom/gprs/protocol/gsm_08_18.h>
+#include <osmocom/gprs/protocol/gsm_24_301.h>
/* gprs_bssgp_util.c */
@@ -175,6 +176,37 @@ uint16_t bssgp_parse_cell_id(struct gprs_ra_id *raid, const uint8_t *buf);
int bssgp_create_cell_id(uint8_t *buf, const struct gprs_ra_id *raid,
uint16_t cid);
+enum bssgp_rim_routing_info_discr {
+ BSSGP_RIM_ROUTING_INFO_GERAN,
+ BSSGP_RIM_ROUTING_INFO_UTRAN,
+ BSSGP_RIM_ROUTING_INFO_EUTRAN,
+};
+
+/*! BSSGP RIM Routing information, see also 3GPP TS 48.018, section 11.3.70 */
+struct bssgp_rim_routing_info {
+ enum bssgp_rim_routing_info_discr discr;
+ union {
+ struct {
+ struct gprs_ra_id raid;
+ uint16_t cid;
+ } geran;
+ struct {
+ struct gprs_ra_id raid;
+ uint16_t rncid;
+ } utran;
+ struct {
+ struct osmo_eutran_tai tai;
+ /* See also 3GPP TS 36.413 9.2.1.37 and 3GPP TS 36.401 */
+ uint8_t global_enb_id[8];
+ uint8_t global_enb_id_len;
+ } eutran;
+ };
+};
+
+int bssgp_parse_rim_ri(struct bssgp_rim_routing_info *ri, const uint8_t *buf,
+ unsigned int len);
+int bssgp_create_rim_ri(uint8_t *buf, const struct bssgp_rim_routing_info *ri);
+
/* Wrapper around TLV parser to parse BSSGP IEs */
static inline int bssgp_tlv_parse(struct tlv_parsed *tp, const uint8_t *buf, int len)
{
diff --git a/include/osmocom/gprs/protocol/gsm_24_301.h b/include/osmocom/gprs/protocol/gsm_24_301.h
new file mode 100644
index 00000000..d4bcd87e
--- /dev/null
+++ b/include/osmocom/gprs/protocol/gsm_24_301.h
@@ -0,0 +1,11 @@
+/*! \file gsm_24_301.h */
+
+#pragma once
+
+/*! Tracking area TS 24.301, section 9.9.3.32 */
+struct osmo_eutran_tai {
+ uint16_t mcc;
+ uint16_t mnc;
+ bool mnc_3_digits;
+ uint16_t tac;
+};
diff --git a/src/gb/gprs_bssgp.c b/src/gb/gprs_bssgp.c
index 696c451b..09f63739 100644
--- a/src/gb/gprs_bssgp.c
+++ b/src/gb/gprs_bssgp.c
@@ -326,6 +326,93 @@ int bssgp_create_cell_id(uint8_t *buf, const struct gprs_ra_id *raid,
return 8;
}
+/*! Parse a RIM Routing information IE (3GPP TS 48.018, chapter 11.3.70).
+ * \param[out] ri user provided memory to store the parsed results.
+ * \param[in] buf input buffer of the value part of the IE.
+ * \returns length of parsed octets, -EINVAL on error. */
+int bssgp_parse_rim_ri(struct bssgp_rim_routing_info *ri, const uint8_t *buf,
+ unsigned int len)
+{
+ struct gprs_ra_id raid_temp;
+
+ memset(ri, 0, sizeof(*ri));
+ if (len < 2)
+ return -EINVAL;
+
+ ri->discr = buf[0] & 0x0f;
+
+ switch (ri->discr) {
+ case BSSGP_RIM_ROUTING_INFO_GERAN:
+ if (len < 9)
+ return -EINVAL;
+ ri->geran.cid = bssgp_parse_cell_id(&ri->geran.raid, buf + 1);
+ return 9;
+ case BSSGP_RIM_ROUTING_INFO_UTRAN:
+ if (len < 9)
+ return -EINVAL;
+ gsm48_parse_ra(&ri->utran.raid, buf + 1);
+ ri->utran.rncid = osmo_load16be(buf + 7);
+ return 9;
+ case BSSGP_RIM_ROUTING_INFO_EUTRAN:
+ if (len < 7 || len > 14)
+ return -EINVAL;
+ /* Note: 3GPP TS 24.301 Figure 9.9.3.32.1 and 3GPP TS 24.008
+ * Figure 10.5.130 specify MCC/MNC encoding in the same way,
+ * so we can re-use gsm48_parse_ra() for that. */
+ gsm48_parse_ra(&raid_temp, buf + 1);
+ ri->eutran.tai.mcc = raid_temp.mcc;
+ ri->eutran.tai.mnc = raid_temp.mnc;
+ ri->eutran.tai.mnc_3_digits = raid_temp.mnc_3_digits;
+ ri->eutran.tai.tac = osmo_load16be(buf + 4);
+ memcpy(ri->eutran.global_enb_id, buf + 6, len - 6);
+ ri->eutran.global_enb_id_len = len - 6;
+ return len;
+ default:
+ return -EINVAL;
+ }
+}
+
+/*! Encode a RIM Routing information IE (3GPP TS 48.018, chapter 11.3.70).
+ * \param[out] buf user provided memory (at least 14 byte) for the generated value part of the IE.
+ * \param[in] ri user provided input data struct.
+ * \returns length of encoded octets, -EINVAL on error. */
+int bssgp_create_rim_ri(uint8_t *buf, const struct bssgp_rim_routing_info *ri)
+{
+ int rc;
+ struct gprs_ra_id raid_temp;
+
+ buf[0] = ri->discr & 0x0f;
+ buf++;
+
+ switch (ri->discr) {
+ case BSSGP_RIM_ROUTING_INFO_GERAN:
+ rc = bssgp_create_cell_id(buf, &ri->geran.raid, ri->geran.cid);
+ if (rc < 0)
+ return -EINVAL;
+ return rc + 1;
+ case BSSGP_RIM_ROUTING_INFO_UTRAN:
+ gsm48_encode_ra((struct gsm48_ra_id *)buf, &ri->utran.raid);
+ osmo_store16be(ri->utran.rncid, buf + 6);
+ return 9;
+ case BSSGP_RIM_ROUTING_INFO_EUTRAN:
+ /* Note: 3GPP TS 24.301 Figure 9.9.3.32.1 and 3GPP TS 24.008
+ * Figure 10.5.130 specify MCC/MNC encoding in the same way,
+ * so we can re-use gsm48_encode_ra() for that. */
+ raid_temp.mcc = ri->eutran.tai.mcc;
+ raid_temp.mnc = ri->eutran.tai.mnc;
+ raid_temp.mnc_3_digits = ri->eutran.tai.mnc_3_digits;
+ gsm48_encode_ra((struct gsm48_ra_id *)buf, &raid_temp);
+ osmo_store16be(ri->eutran.tai.tac, buf + 3);
+ OSMO_ASSERT(ri->eutran.global_enb_id_len <=
+ sizeof(ri->eutran.global_enb_id));
+ memcpy(buf + 5, ri->eutran.global_enb_id,
+ ri->eutran.global_enb_id_len);
+ return ri->eutran.global_enb_id_len + 6;
+ default:
+ return -EINVAL;
+ }
+}
+
/* Chapter 8.4 BVC-Reset Procedure */
static int bssgp_rx_bvc_reset(struct msgb *msg, struct tlv_parsed *tp,
uint16_t ns_bvci)
diff --git a/src/gb/libosmogb.map b/src/gb/libosmogb.map
index 59405b0a..8f638fff 100644
--- a/src/gb/libosmogb.map
+++ b/src/gb/libosmogb.map
@@ -2,6 +2,7 @@ LIBOSMOGB_1.0 {
global:
bssgp_cause_str;
bssgp_create_cell_id;
+bssgp_create_rim_ri;
bssgp_pdu_str;
bssgp_fc_in;
bssgp_fc_init;
@@ -13,6 +14,7 @@ bssgp_msgb_copy;
bssgp_msgb_tlli_put;
bssgp_msgb_ra_put;
bssgp_parse_cell_id;
+bssgp_parse_rim_ri;
bssgp_set_bssgp_callback;
bssgp_tx_bvc_block;
bssgp_tx_bvc_reset;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ed87aca8..cb683f79 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -172,7 +172,8 @@ gb_bssgp_fc_test_LDADD = $(LDADD) $(top_builddir)/src/gb/libosmogb.la \
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 52e986e8..e1c920a9 100644
--- a/tests/gb/gprs_bssgp_test.c
+++ b/tests/gb/gprs_bssgp_test.c
@@ -289,6 +289,137 @@ static void test_bssgp_msgb_copy()
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 @@ int main(int argc, char **argv)
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 c5b3e7d1..744f1a79 100644
--- a/tests/gb/gprs_bssgp_test.ok
+++ b/tests/gb/gprs_bssgp_test.ok
@@ -17,5 +17,61 @@ Got message: 26 1e 81 2a 05 82 10 22 03 82 c0 40 01 82 08 11 1c 82 60 20 3c 81 7
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