diff options
author | Neels Hofmeyr <neels@hofmeyr.de> | 2019-02-10 22:28:27 +0100 |
---|---|---|
committer | Neels Hofmeyr <neels@hofmeyr.de> | 2019-03-08 05:25:07 +0100 |
commit | 3a5045302f51faf104e64783977f710d36e06e3f (patch) | |
tree | 70ec869e4843a8330df1133ee617b1a7d740bd21 | |
parent | d4b79c877291e58bf7fafcfd3c771c9e66fa3f5b (diff) |
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
-rw-r--r-- | include/osmocom/gsm/gsm0808_utils.h | 3 | ||||
-rw-r--r-- | include/osmocom/gsm/gsm23003.h | 9 | ||||
-rw-r--r-- | src/gsm/gsm0808_utils.c | 87 | ||||
-rw-r--r-- | src/gsm/libosmogsm.map | 2 | ||||
-rw-r--r-- | tests/gsm0808/gsm0808_test.c | 85 | ||||
-rw-r--r-- | tests/gsm0808/gsm0808_test.ok | 92 |
6 files changed, 270 insertions, 8 deletions
diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index 2b48be76..53f145c5 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -84,6 +84,9 @@ int gsm0808_cell_id_u_name(char *buf, size_t buflen, bool gsm0808_cell_ids_match(const struct gsm0808_cell_id *id1, const struct gsm0808_cell_id *id2, bool exact_match); int gsm0808_cell_id_matches_list(const struct gsm0808_cell_id *id, const struct gsm0808_cell_id_list2 *list, unsigned int match_nr, bool exact_match); +void gsm0808_cell_id_from_cgi(struct gsm0808_cell_id *cid, enum CELL_IDENT id_discr, + const struct osmo_cell_global_id *cgi); +int gsm0808_cell_id_to_cgi(struct osmo_cell_global_id *cgi, const struct gsm0808_cell_id *cid); uint8_t gsm0808_enc_cause(struct msgb *msg, uint16_t cause); uint8_t gsm0808_enc_aoip_trasp_addr(struct msgb *msg, diff --git a/include/osmocom/gsm/gsm23003.h b/include/osmocom/gsm/gsm23003.h index b34a677b..cf622ce0 100644 --- a/include/osmocom/gsm/gsm23003.h +++ b/include/osmocom/gsm/gsm23003.h @@ -30,6 +30,15 @@ struct osmo_cell_global_id { uint16_t cell_identity; }; +/*! Bitmask of items contained in a struct osmo_cell_global_id. + * See also gsm0808_cell_id_to_cgi(). + */ +enum osmo_cgi_part { + OSMO_CGI_PART_PLMN = 1, + OSMO_CGI_PART_LAC = 2, + OSMO_CGI_PART_CI = 4, +}; + /* Actually defined in 3GPP TS 48.008 3.2.2.27 Cell Identifier List, * but conceptually belongs with the above structures. */ struct osmo_lac_and_ci_id { diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c index 54775981..dd14d3ca 100644 --- a/src/gsm/gsm0808_utils.c +++ b/src/gsm/gsm0808_utils.c @@ -1577,6 +1577,93 @@ int gsm0808_cell_id_matches_list(const struct gsm0808_cell_id *id, const struct return -1; } +/*! Copy information from a CGI to form a Cell Identifier of the specified kind. + * \param [out] cid Compose new Cell Identifier here. + * \param [in] id_discr Which kind of Cell Identifier to compose. + * \param [in] cgi Cell Global Identifier to form the Cell Identifier from. + */ +void gsm0808_cell_id_from_cgi(struct gsm0808_cell_id *cid, enum CELL_IDENT id_discr, + const struct osmo_cell_global_id *cgi) +{ + *cid = (struct gsm0808_cell_id){ + .id_discr = id_discr, + }; + + switch (id_discr) { + case CELL_IDENT_WHOLE_GLOBAL: + cid->id.global = *cgi; + return; + + case CELL_IDENT_LAC_AND_CI: + cid->id.lac_and_ci = (struct osmo_lac_and_ci_id){ + .lac = cgi->lai.lac, + .ci = cgi->cell_identity, + }; + return; + + case CELL_IDENT_CI: + cid->id.ci = cgi->cell_identity; + return; + + case CELL_IDENT_LAI: + cid->id.lai_and_lac = cgi->lai; + return; + + case CELL_IDENT_LAC: + cid->id.lac = cgi->lai.lac; + return; + + case CELL_IDENT_NO_CELL: + case CELL_IDENT_BSS: + case CELL_IDENT_UTRAN_PLMN_LAC_RNC: + case CELL_IDENT_UTRAN_RNC: + case CELL_IDENT_UTRAN_LAC_RNC: + default: + return; + }; +} + +/*! Overwrite parts of cgi with values from a Cell Identifier. + * Place only those items given in cid into cgi, leaving other values unchanged. + * \param[out] cgi Cell Global Identity to write to. + * \param[in] cid Cell Identity to read from. + * \return a bitmask of items that were set: OSMO_CGI_PART_PLMN | OSMO_CGI_PART_LAC | OSMO_CGI_PART_CI; 0 if nothing was + * written to cgi. + */ +int gsm0808_cell_id_to_cgi(struct osmo_cell_global_id *cgi, const struct gsm0808_cell_id *cid) +{ + switch (cid->id_discr) { + case CELL_IDENT_WHOLE_GLOBAL: + *cgi = cid->id.global; + return OSMO_CGI_PART_PLMN | OSMO_CGI_PART_LAC | OSMO_CGI_PART_CI; + + case CELL_IDENT_LAC_AND_CI: + cgi->lai.lac = cid->id.lac_and_ci.lac; + cgi->cell_identity = cid->id.lac_and_ci.ci; + return OSMO_CGI_PART_LAC | OSMO_CGI_PART_CI; + + case CELL_IDENT_CI: + cgi->cell_identity = cid->id.ci; + return OSMO_CGI_PART_CI; + + case CELL_IDENT_LAI: + cgi->lai = cid->id.lai_and_lac; + return OSMO_CGI_PART_PLMN | OSMO_CGI_PART_LAC; + + case CELL_IDENT_LAC: + cgi->lai.lac = cid->id.lac; + return OSMO_CGI_PART_LAC; + + case CELL_IDENT_NO_CELL: + case CELL_IDENT_BSS: + case CELL_IDENT_UTRAN_PLMN_LAC_RNC: + case CELL_IDENT_UTRAN_RNC: + case CELL_IDENT_UTRAN_LAC_RNC: + default: + return 0; + }; +} + /*! value_string[] for enum CELL_IDENT. */ const struct value_string gsm0808_cell_id_discr_names[] = { { CELL_IDENT_WHOLE_GLOBAL, "CGI" }, diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 2d47d7a7..3fadc5a0 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -205,6 +205,8 @@ gsm0808_dec_cell_id_list; gsm0808_dec_cell_id_list2; gsm0808_cell_id_list_add; gsm0808_cell_id_to_list; +gsm0808_cell_id_to_cgi; +gsm0808_cell_id_from_cgi; gsm0808_enc_cell_id; gsm0808_dec_cell_id; gsm0808_cell_id_name; diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c index af90d00c..c448f439 100644 --- a/tests/gsm0808/gsm0808_test.c +++ b/tests/gsm0808/gsm0808_test.c @@ -2206,29 +2206,96 @@ static bool test_cell_id_list_matching_discrs(bool test_match, 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 @@ int main(int argc, char **argv) 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; } diff --git a/tests/gsm0808/gsm0808_test.ok b/tests/gsm0808/gsm0808_test.ok index e7df007a..60353262 100644 --- a/tests/gsm0808/gsm0808_test.ok +++ b/tests/gsm0808/gsm0808_test.ok @@ -629,4 +629,96 @@ CGI:023-042-23-5 and CI[1]:{6}: mismatch CGI:023-042-23-5 and LAC-CI[1]:{42-6}: mismatch CGI:023-042-23-5 and LAI[3]:{023-042-42, 023-99-23, 023-42-23}: mismatch CGI:023-042-23-5 and CGI[2]:{023-042-42-6, 023-99-23-5}: mismatch + +test_gsm0808_cell_id_to_from_cgi() +cid LAC:23 -> cgi 777-007-23-7777 LAC -> cid LAC:23 + --> gsm0808_cell_id{LAC} = LAC:23 + --> gsm0808_cell_id{CI} = CI:7777 + --> gsm0808_cell_id{LAC-CI} = LAC-CI:23-7777 + --> gsm0808_cell_id{LAI} = LAI:777-007-23 + --> gsm0808_cell_id{CGI} = CGI:777-007-23-7777 +cid LAC:42 -> cgi 777-007-42-7777 LAC -> cid LAC:42 + --> gsm0808_cell_id{LAC} = LAC:42 + --> gsm0808_cell_id{CI} = CI:7777 + --> gsm0808_cell_id{LAC-CI} = LAC-CI:42-7777 + --> gsm0808_cell_id{LAI} = LAI:777-007-42 + --> gsm0808_cell_id{CGI} = CGI:777-007-42-7777 +cid CI:5 -> cgi 777-007-7777-5 CI -> cid CI:5 + --> gsm0808_cell_id{LAC} = LAC:7777 + --> gsm0808_cell_id{CI} = CI:5 + --> gsm0808_cell_id{LAC-CI} = LAC-CI:7777-5 + --> gsm0808_cell_id{LAI} = LAI:777-007-7777 + --> gsm0808_cell_id{CGI} = CGI:777-007-7777-5 +cid CI:6 -> cgi 777-007-7777-6 CI -> cid CI:6 + --> gsm0808_cell_id{LAC} = LAC:7777 + --> gsm0808_cell_id{CI} = CI:6 + --> gsm0808_cell_id{LAC-CI} = LAC-CI:7777-6 + --> gsm0808_cell_id{LAI} = LAI:777-007-7777 + --> gsm0808_cell_id{CGI} = CGI:777-007-7777-6 +cid LAC-CI:23-5 -> cgi 777-007-23-5 LAC CI -> cid LAC-CI:23-5 + --> gsm0808_cell_id{LAC} = LAC:23 + --> gsm0808_cell_id{CI} = CI:5 + --> gsm0808_cell_id{LAC-CI} = LAC-CI:23-5 + --> gsm0808_cell_id{LAI} = LAI:777-007-23 + --> gsm0808_cell_id{CGI} = CGI:777-007-23-5 +cid LAC-CI:42-6 -> cgi 777-007-42-6 LAC CI -> cid LAC-CI:42-6 + --> gsm0808_cell_id{LAC} = LAC:42 + --> gsm0808_cell_id{CI} = CI:6 + --> gsm0808_cell_id{LAC-CI} = LAC-CI:42-6 + --> gsm0808_cell_id{LAI} = LAI:777-007-42 + --> gsm0808_cell_id{CGI} = CGI:777-007-42-6 +cid LAI:023-042-23 -> cgi 023-042-23-7777 PLMN LAC -> cid LAI:023-042-23 + --> gsm0808_cell_id{LAC} = LAC:23 + --> gsm0808_cell_id{CI} = CI:7777 + --> gsm0808_cell_id{LAC-CI} = LAC-CI:23-7777 + --> gsm0808_cell_id{LAI} = LAI:023-042-23 + --> gsm0808_cell_id{CGI} = CGI:023-042-23-7777 +cid LAI:023-042-42 -> cgi 023-042-42-7777 PLMN LAC -> cid LAI:023-042-42 + --> gsm0808_cell_id{LAC} = LAC:42 + --> gsm0808_cell_id{CI} = CI:7777 + --> gsm0808_cell_id{LAC-CI} = LAC-CI:42-7777 + --> gsm0808_cell_id{LAI} = LAI:023-042-42 + --> gsm0808_cell_id{CGI} = CGI:023-042-42-7777 +cid LAI:023-99-23 -> cgi 023-99-23-7777 PLMN LAC -> cid LAI:023-99-23 + --> gsm0808_cell_id{LAC} = LAC:23 + --> gsm0808_cell_id{CI} = CI:7777 + --> gsm0808_cell_id{LAC-CI} = LAC-CI:23-7777 + --> gsm0808_cell_id{LAI} = LAI:023-99-23 + --> gsm0808_cell_id{CGI} = CGI:023-99-23-7777 +cid LAI:023-42-23 -> cgi 023-42-23-7777 PLMN LAC -> cid LAI:023-42-23 + --> gsm0808_cell_id{LAC} = LAC:23 + --> gsm0808_cell_id{CI} = CI:7777 + --> gsm0808_cell_id{LAC-CI} = LAC-CI:23-7777 + --> gsm0808_cell_id{LAI} = LAI:023-42-23 + --> gsm0808_cell_id{CGI} = CGI:023-42-23-7777 +cid CGI:023-042-23-5 -> cgi 023-042-23-5 PLMN LAC CI -> cid CGI:023-042-23-5 + --> gsm0808_cell_id{LAC} = LAC:23 + --> gsm0808_cell_id{CI} = CI:5 + --> gsm0808_cell_id{LAC-CI} = LAC-CI:23-5 + --> gsm0808_cell_id{LAI} = LAI:023-042-23 + --> gsm0808_cell_id{CGI} = CGI:023-042-23-5 +cid CGI:023-042-42-6 -> cgi 023-042-42-6 PLMN LAC CI -> cid CGI:023-042-42-6 + --> gsm0808_cell_id{LAC} = LAC:42 + --> gsm0808_cell_id{CI} = CI:6 + --> gsm0808_cell_id{LAC-CI} = LAC-CI:42-6 + --> gsm0808_cell_id{LAI} = LAI:023-042-42 + --> gsm0808_cell_id{CGI} = CGI:023-042-42-6 +cid CGI:023-99-23-5 -> cgi 023-99-23-5 PLMN LAC CI -> cid CGI:023-99-23-5 + --> gsm0808_cell_id{LAC} = LAC:23 + --> gsm0808_cell_id{CI} = CI:5 + --> gsm0808_cell_id{LAC-CI} = LAC-CI:23-5 + --> gsm0808_cell_id{LAI} = LAI:023-99-23 + --> gsm0808_cell_id{CGI} = CGI:023-99-23-5 +cid NO-CELL:NO-CELL -> cgi 777-007-7777-7777 -> cid NO-CELL:NO-CELL + --> gsm0808_cell_id{LAC} = LAC:7777 + --> gsm0808_cell_id{CI} = CI:7777 + --> gsm0808_cell_id{LAC-CI} = LAC-CI:7777-7777 + --> gsm0808_cell_id{LAI} = LAI:777-007-7777 + --> gsm0808_cell_id{CGI} = CGI:777-007-7777-7777 +cid unknown 0x1a7:unknown 0x1a7 -> cgi 777-007-7777-7777 -> cid unknown 0x1a7:unknown 0x1a7 + --> gsm0808_cell_id{LAC} = LAC:7777 + --> gsm0808_cell_id{CI} = CI:7777 + --> gsm0808_cell_id{LAC-CI} = LAC-CI:7777-7777 + --> gsm0808_cell_id{LAI} = LAI:777-007-7777 + --> gsm0808_cell_id{CGI} = CGI:777-007-7777-7777 Done |