Neels Hofmeyr has uploaded this change for review. ( https://gerrit.osmocom.org/11504
Change subject: gsm0808: add BSSMAP Cell Identifier matching API ...................................................................... gsm0808: add BSSMAP Cell Identifier matching API Add * osmo_lai_cmp() (to use in gsm0808_cell_id_u_matches()) * osmo_cgi_cmp() (to use in gsm0808_cell_id_u_matches()) * gsm0808_cell_id_u_matches() (to re-use for single IDs and lists) * gsm0808_cell_ids_match() * gsm0808_cell_id_matches_list() * Unit tests in gsm0808_test.c Rationale: For inter-BSC handover, it is interesting to find matches between *differing* Cell Identity kinds. For example, if a cell as CGI 23-42-3-5, and a HO for LAC-CI 3-5 should be handled, we need to see the match. This is most interesting for osmo-msc, i.e. to direct the BSSMAP Handover Request towards the correct BSC -- not yet being implemented ATM though. It is also interesting for osmo-bsc's VTY interface, to be able to manage cells' neighbors and to trigger manual handovers by various Cell Identity handles, as the user would expect them. Granted, the osmo-bsc VTY UI isn't a really pressing need to be adding this at this moment, but with the future perspective of osmo-msc also using it, I preferred to do the UI "properly" as well now. Change-Id: I5535f0d149c2173294538df75764dd181b023312 --- M include/osmocom/gsm/gsm0808_utils.h M include/osmocom/gsm/gsm23003.h M src/gsm/gsm0808_utils.c M src/gsm/gsm23003.c M src/gsm/libosmogsm.map M tests/gsm0808/gsm0808_test.c M tests/gsm0808/gsm0808_test.ok 7 files changed, 574 insertions(+), 0 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/04/11504/1 diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index f70dbdb..29730c2 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -67,6 +67,12 @@ int gsm0808_cell_id_list_name_buf(char *buf, size_t buflen, const struct gsm0808_cell_id_list2 *cil); int gsm0808_cell_id_u_name(char *buf, size_t buflen, enum CELL_IDENT id_discr, const union gsm0808_cell_id_u *u); +bool gsm0808_cell_id_u_matches(enum CELL_IDENT discr1, const union gsm0808_cell_id_u *u1, + enum CELL_IDENT discr2, const union gsm0808_cell_id_u *u2); +bool gsm0808_cell_ids_match(const struct gsm0808_cell_id *id1, const struct gsm0808_cell_id *id2); +int gsm0808_cell_id_matches_list(const struct gsm0808_cell_id *id, + const struct gsm0808_cell_id_list2 *list, + unsigned int match_nr); uint8_t gsm0808_enc_aoip_trasp_addr(struct msgb *msg, const struct sockaddr_storage *ss); diff --git a/include/osmocom/gsm/gsm23003.h b/include/osmocom/gsm/gsm23003.h index 2f380ae..cb228b7 100644 --- a/include/osmocom/gsm/gsm23003.h +++ b/include/osmocom/gsm/gsm23003.h @@ -121,6 +121,8 @@ int osmo_mnc_cmp(uint16_t a_mnc, bool a_mnc_3_digits, uint16_t b_mnc, bool b_mnc_3_digits); int osmo_plmn_cmp(const struct osmo_plmn_id *a, const struct osmo_plmn_id *b); +int osmo_lai_cmp(const struct osmo_location_area_id *a, const struct osmo_location_area_id *b); +int osmo_cgi_cmp(const struct osmo_cell_global_id *a, const struct osmo_cell_global_id *b); int osmo_gen_home_network_domain(char *out, const struct osmo_plmn_id *plmn); int osmo_parse_home_network_domain(struct osmo_plmn_id *out, const char *in); diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c index 2348105..147d069 100644 --- a/src/gsm/gsm0808_utils.c +++ b/src/gsm/gsm0808_utils.c @@ -1266,6 +1266,146 @@ } } +/* Store individual Cell Identifier information in a CGI, without clearing the remaining ones. + * This is useful to supplement one CGI with information from more than one Cell Identifier, + * which in turn is useful to match Cell Identifiers of differing kinds to each other. + * Before first invocation, clear the *dst struct externally, this function does only write those members + * that are present in parameter u. + */ +static void cell_id_to_cgi(struct osmo_cell_global_id *dst, + enum CELL_IDENT discr, const union gsm0808_cell_id_u *u) +{ + switch (discr) { + case CELL_IDENT_WHOLE_GLOBAL: + *dst = u->global; + return; + + case CELL_IDENT_LAC_AND_CI: + dst->lai.lac = u->lac_and_ci.lac; + dst->cell_identity = u->lac_and_ci.ci; + return; + + case CELL_IDENT_CI: + dst->cell_identity = u->ci; + return; + + case CELL_IDENT_LAI_AND_LAC: + dst->lai = u->lai_and_lac; + return; + + case CELL_IDENT_LAC: + dst->lai.lac = u->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: + /* No values to set. */ + return; + } +} + +/*! Return true if the common information between the two Cell Identifiers match. + * For example, if a LAC+CI is compared to LAC, return true if the LAC are the same. + * Note that CELL_IDENT_NO_CELL will always return false. + * Also CELL_IDENT_BSS will always return false, since this function cannot possibly + * know the bounds of the BSS, so the caller must handle CELL_IDENT_BSS specially. + * \param[in] discr1 Cell Identifier type. + * \param[in] u1 Cell Identifier value. + * \param[in] discr2 Other Cell Identifier type. + * \param[in] u2 Other Cell Identifier value. + * \returns True if the common fields of the above match. + */ +bool gsm0808_cell_id_u_match(enum CELL_IDENT discr1, const union gsm0808_cell_id_u *u1, + enum CELL_IDENT discr2, const union gsm0808_cell_id_u *u2) +{ + struct osmo_cell_global_id a = {}; + struct osmo_cell_global_id b = {}; + + /* First handle the odd wildcard like CELL_IDENT kinds. We can't really match any of these. */ + switch (discr1) { + case CELL_IDENT_NO_CELL: + case CELL_IDENT_UTRAN_PLMN_LAC_RNC: + case CELL_IDENT_UTRAN_RNC: + case CELL_IDENT_UTRAN_LAC_RNC: + case CELL_IDENT_BSS: + return false; + default: + break; + } + switch (discr2) { + case CELL_IDENT_NO_CELL: + case CELL_IDENT_UTRAN_PLMN_LAC_RNC: + case CELL_IDENT_UTRAN_RNC: + case CELL_IDENT_UTRAN_LAC_RNC: + case CELL_IDENT_BSS: + return false; + default: + break; + } + + /* Enrich both sides to full CGI, then compare those. First set the *other* ID's values in case + * they assign more items. For example: + * u1 = LAC:42 + * u2 = LAC+CI:23+5 + * 1) a <- LAC+CI:23+5 + * 2) a <- LAC:42 so that a = LAC+CI:42+5 + * Now we can compare those two and find a mismatch. If the LAC were the same, we would get + * identical LAC+CI and hence a match. */ + + cell_id_to_cgi(&a, discr2, u2); + cell_id_to_cgi(&a, discr1, u1); + + cell_id_to_cgi(&b, discr1, u1); + cell_id_to_cgi(&b, discr2, u2); + + return osmo_cgi_cmp(&a, &b) == 0; +} + +/*! Return true if the common information between the two Cell Identifiers match. + * For example, if a LAC+CI is compared to LAC, return true if the LAC are the same. + * Note that CELL_IDENT_NO_CELL will always return false. + * Also CELL_IDENT_BSS will always return false, since this function cannot possibly + * know the bounds of the BSS, so the caller must handle CELL_IDENT_BSS specially. + * \param[in] id1 Cell Identifier. + * \param[in] id2 Other Cell Identifier. + * \returns True if the common fields of the above match. + */ +bool gsm0808_cell_ids_match(const struct gsm0808_cell_id *id1, const struct gsm0808_cell_id *id2) +{ + return gsm0808_cell_id_u_match(id1->id_discr, &id1->id, + id2->id_discr, &id2->id); +} + +/*! Find an index in a Cell Identifier list that matches a given single Cell Identifer. + * Compare \a id against each entry in \a list using gsm0808_cell_ids_match(), and return the list index + * if a match is found. \a match_nr allows iterating all matches in the list. A match_nr <= 0 returns the + * first match in the list, match_nr == 1 the second match, etc., and if match_nr exceeds the available + * matches in the list, -1 is returned. + * \param[in] id Cell Identifier to match. + * \param[in] list Cell Identifier list to search in. + * \param[in] match_nr Ignore this many matches. + * \returns -1 if no match is found, list index if a match is found. + */ +int gsm0808_cell_id_matches_list(const struct gsm0808_cell_id *id, + const struct gsm0808_cell_id_list2 *list, + unsigned int match_nr) +{ + int i; + for (i = 0; i < list->id_list_len; i++) { + if (gsm0808_cell_id_u_match(id->id_discr, &id->id, + list->id_discr, &list->id_list[i])) { + if (match_nr) + match_nr --; + else + return i; + } + } + return -1; +} + /*! 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/gsm23003.c b/src/gsm/gsm23003.c index 4fdad48..6abda41 100644 --- a/src/gsm/gsm23003.c +++ b/src/gsm/gsm23003.c @@ -306,6 +306,40 @@ return osmo_mnc_cmp(a->mnc, a->mnc_3_digits, b->mnc, b->mnc_3_digits); } +/* Compare two LAI. + * The order of comparison is MCC, MNC, LAC. See also osmo_plmn_cmp(). + * \param a[in] "Left" side LAI. + * \param b[in] "Right" side LAI. + * \returns 0 if the LAI are equal, -1 if a < b, 1 if a > b. */ +int osmo_lai_cmp(const struct osmo_location_area_id *a, const struct osmo_location_area_id *b) +{ + int rc = osmo_plmn_cmp(&a->plmn, &b->plmn); + if (rc) + return rc; + if (a->lac < b->lac) + return -1; + if (a->lac > b->lac) + return 1; + return 0; +} + +/* Compare two CGI. + * The order of comparison is MCC, MNC, LAC, CI. See also osmo_lai_cmp(). + * \param a[in] "Left" side CGI. + * \param b[in] "Right" side CGI. + * \returns 0 if the CGI are equal, -1 if a < b, 1 if a > b. */ +int osmo_cgi_cmp(const struct osmo_cell_global_id *a, const struct osmo_cell_global_id *b) +{ + int rc = osmo_lai_cmp(&a->lai, &b->lai); + if (rc) + return rc; + if (a->cell_identity < b->cell_identity) + return -1; + if (a->cell_identity > b->cell_identity) + return 1; + return 0; +} + /*! Generate TS 23.003 Section 19.2 Home Network Realm/Domain (text form) * \param out[out] caller-provided output buffer, at least 33 bytes long * \param plmn[in] Osmocom representation of PLMN ID (MCC + MNC) diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 4813e13..ecc368e 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -203,6 +203,9 @@ gsm0808_cell_id_list_name_buf; gsm0808_cell_id_discr_names; gsm0808_cell_id_u_name; +gsm0808_cell_id_u_matches; +gsm0808_cell_ids_match; +gsm0808_cell_id_matches_list; gsm0808_chan_type_to_speech_codec; gsm0808_speech_codec_from_chan_type; gsm0808_sc_cfg_from_gsm48_mr_cfg; diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c index 0b2794f..7f121aa 100644 --- a/tests/gsm0808/gsm0808_test.c +++ b/tests/gsm0808/gsm0808_test.c @@ -1718,6 +1718,270 @@ (GSM0808_SC_CFG_DEFAULT_AMR_7_95 | GSM0808_SC_CFG_DEFAULT_AMR_12_2); } +struct test_cell_id_matching_data { + struct gsm0808_cell_id id; + struct gsm0808_cell_id match_id; + bool expect_match; +}; + +const struct gsm0808_cell_id lac_23 = { .id_discr = CELL_IDENT_LAC, .id.lac = 23, }; +const struct gsm0808_cell_id lac_42 = { .id_discr = CELL_IDENT_LAC, .id.lac = 42, }; +const struct gsm0808_cell_id ci_5 = { .id_discr = CELL_IDENT_CI, .id.ci = 5, }; +const struct gsm0808_cell_id ci_6 = { .id_discr = CELL_IDENT_CI, .id.ci = 6, }; +const struct gsm0808_cell_id lac_ci_23_5 = { + .id_discr = CELL_IDENT_LAC_AND_CI, + .id.lac_and_ci = { .lac = 23, .ci = 5, }, + }; +const struct gsm0808_cell_id lac_ci_42_6 = { + .id_discr = CELL_IDENT_LAC_AND_CI, + .id.lac_and_ci = { .lac = 42, .ci = 6, }, + }; +const struct gsm0808_cell_id lai_23_042_23 = { + .id_discr = CELL_IDENT_LAI_AND_LAC, + .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 23, }, + }; +const struct gsm0808_cell_id lai_23_042_42 = { + .id_discr = CELL_IDENT_LAI_AND_LAC, + .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 42, }, + }; +const struct gsm0808_cell_id lai_23_99_23 = { + .id_discr = CELL_IDENT_LAI_AND_LAC, + .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 99, .mnc_3_digits = false }, .lac = 23, }, + }; +const struct gsm0808_cell_id lai_23_42_23 = { + .id_discr = CELL_IDENT_LAI_AND_LAC, + .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = false }, .lac = 23, }, + }; +const struct gsm0808_cell_id cgi_23_042_23_5 = { + .id_discr = CELL_IDENT_WHOLE_GLOBAL, + .id.global = { + .lai = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 23, }, + .cell_identity = 5, + }, + }; +const struct gsm0808_cell_id cgi_23_042_42_6 = { + .id_discr = CELL_IDENT_WHOLE_GLOBAL, + .id.global = { + .lai = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 42, }, + .cell_identity = 6, + }, + }; +const struct gsm0808_cell_id cgi_23_99_23_5 = { + .id_discr = CELL_IDENT_WHOLE_GLOBAL, + .id.global = { + .lai = { .plmn = { .mcc = 23, .mnc = 99, .mnc_3_digits = false }, .lac = 23, }, + .cell_identity = 5, + }, + }; + + +const struct test_cell_id_matching_data test_cell_id_matching_tests[] = { + { .id = lac_23, .match_id = lac_23, .expect_match = true }, + { .id = lac_23, .match_id = lac_42, .expect_match = false }, + { .id = lac_23, .match_id = ci_5, .expect_match = true }, + { .id = lac_23, .match_id = ci_6, .expect_match = true }, + { .id = lac_23, .match_id = lac_ci_23_5, .expect_match = true }, + { .id = lac_23, .match_id = lac_ci_42_6, .expect_match = false }, + { .id = lac_23, .match_id = lai_23_042_23, .expect_match = true }, + { .id = lac_23, .match_id = lai_23_042_42, .expect_match = false }, + { .id = lac_23, .match_id = lai_23_99_23, .expect_match = true }, + { .id = lac_23, .match_id = lai_23_42_23, .expect_match = true }, + { .id = lac_23, .match_id = cgi_23_042_23_5, .expect_match = true }, + { .id = lac_23, .match_id = cgi_23_042_42_6, .expect_match = false }, + { .id = lac_23, .match_id = cgi_23_99_23_5, .expect_match = true }, + { .id = ci_5, .match_id = lac_23, .expect_match = true }, + { .id = ci_5, .match_id = lac_42, .expect_match = true }, + { .id = ci_5, .match_id = ci_5, .expect_match = true }, + { .id = ci_5, .match_id = ci_6, .expect_match = false }, + { .id = ci_5, .match_id = lac_ci_23_5, .expect_match = true }, + { .id = ci_5, .match_id = lac_ci_42_6, .expect_match = false }, + { .id = ci_5, .match_id = lai_23_042_23, .expect_match = true }, + { .id = ci_5, .match_id = lai_23_042_42, .expect_match = true }, + { .id = ci_5, .match_id = lai_23_99_23, .expect_match = true }, + { .id = ci_5, .match_id = lai_23_42_23, .expect_match = true }, + { .id = ci_5, .match_id = cgi_23_042_23_5, .expect_match = true }, + { .id = ci_5, .match_id = cgi_23_042_42_6, .expect_match = false }, + { .id = ci_5, .match_id = cgi_23_99_23_5, .expect_match = true }, + { .id = lac_ci_23_5, .match_id = lac_23, .expect_match = true }, + { .id = lac_ci_23_5, .match_id = lac_42, .expect_match = false }, + { .id = lac_ci_23_5, .match_id = ci_5, .expect_match = true }, + { .id = lac_ci_23_5, .match_id = ci_6, .expect_match = false }, + { .id = lac_ci_23_5, .match_id = lac_ci_23_5, .expect_match = true }, + { .id = lac_ci_23_5, .match_id = lac_ci_42_6, .expect_match = false }, + { .id = lac_ci_23_5, .match_id = lai_23_042_23, .expect_match = true }, + { .id = lac_ci_23_5, .match_id = lai_23_042_42, .expect_match = false }, + { .id = lac_ci_23_5, .match_id = lai_23_99_23, .expect_match = true }, + { .id = lac_ci_23_5, .match_id = lai_23_42_23, .expect_match = true }, + { .id = lac_ci_23_5, .match_id = cgi_23_042_23_5, .expect_match = true }, + { .id = lac_ci_23_5, .match_id = cgi_23_042_42_6, .expect_match = false }, + { .id = lac_ci_23_5, .match_id = cgi_23_99_23_5, .expect_match = true }, + { .id = lai_23_042_23, .match_id = lac_23, .expect_match = true }, + { .id = lai_23_042_23, .match_id = lac_42, .expect_match = false }, + { .id = lai_23_042_23, .match_id = ci_5, .expect_match = true }, + { .id = lai_23_042_23, .match_id = ci_6, .expect_match = true }, + { .id = lai_23_042_23, .match_id = lac_ci_23_5, .expect_match = true }, + { .id = lai_23_042_23, .match_id = lac_ci_42_6, .expect_match = false }, + { .id = lai_23_042_23, .match_id = lai_23_042_23, .expect_match = true }, + { .id = lai_23_042_23, .match_id = lai_23_042_42, .expect_match = false }, + { .id = lai_23_042_23, .match_id = lai_23_99_23, .expect_match = false }, + { .id = lai_23_042_23, .match_id = lai_23_42_23, .expect_match = false }, + { .id = lai_23_042_23, .match_id = cgi_23_042_23_5, .expect_match = true }, + { .id = lai_23_042_23, .match_id = cgi_23_042_42_6, .expect_match = false }, + { .id = lai_23_042_23, .match_id = cgi_23_99_23_5, .expect_match = false }, + { .id = cgi_23_042_23_5, .match_id = lac_23, .expect_match = true }, + { .id = cgi_23_042_23_5, .match_id = lac_42, .expect_match = false }, + { .id = cgi_23_042_23_5, .match_id = ci_5, .expect_match = true }, + { .id = cgi_23_042_23_5, .match_id = ci_6, .expect_match = false }, + { .id = cgi_23_042_23_5, .match_id = lac_ci_23_5, .expect_match = true }, + { .id = cgi_23_042_23_5, .match_id = lac_ci_42_6, .expect_match = false }, + { .id = cgi_23_042_23_5, .match_id = lai_23_042_23, .expect_match = true }, + { .id = cgi_23_042_23_5, .match_id = lai_23_042_42, .expect_match = false }, + { .id = cgi_23_042_23_5, .match_id = lai_23_99_23, .expect_match = false }, + { .id = cgi_23_042_23_5, .match_id = lai_23_42_23, .expect_match = false }, + { .id = cgi_23_042_23_5, .match_id = cgi_23_042_23_5, .expect_match = true }, + { .id = cgi_23_042_23_5, .match_id = cgi_23_042_42_6, .expect_match = false }, + { .id = cgi_23_042_23_5, .match_id = cgi_23_99_23_5, .expect_match = false }, +}; + + +static void test_cell_id_matching() +{ + int i; + bool ok = true; + printf("\n%s\n", __func__); + + for (i = 0; i < ARRAY_SIZE(test_cell_id_matching_tests); i++) { + const struct test_cell_id_matching_data *d = &test_cell_id_matching_tests[i]; + bool result; + + result = gsm0808_cell_ids_match(&d->id, &d->match_id); + + printf("[%d] %s %s %s\n", + i, + gsm0808_cell_id_name(&d->id), + gsm0808_cell_id_name2(&d->match_id), + result ? "MATCH" : "don't match"); + if (result != d->expect_match) { + printf(" ERROR: expected %s\n", d->expect_match ? "MATCH" : "no match"); + ok = false; + } + } + + OSMO_ASSERT(ok); +} + +static bool test_cell_id_list_matching_discrs(bool test_match, + enum CELL_IDENT id_discr, + enum CELL_IDENT list_discr) +{ + int i, j; + const struct gsm0808_cell_id *id = NULL; + struct gsm0808_cell_id_list2 list = {}; + int match_idx = -1; + int result; + + for (i = 0; i < ARRAY_SIZE(test_cell_id_matching_tests); i++) { + const struct test_cell_id_matching_data *d = &test_cell_id_matching_tests[i]; + if (id_discr != d->id.id_discr) + continue; + id = &d->id; + break; + } + + if (!id) { + printf("Did not find any entry for %s\n", gsm0808_cell_id_discr_name(id_discr)); + return true; + } + + /* Collect those entries with exactly this id on the left, of type list_discr on the right. + * Collect the mismatches first, for more interesting match indexes in the results. */ + for (j = 0; j < 2; j++) { + bool collect_matches = (bool)j; + + /* If we want to have a mismatching list, don't add any entries that match. */ + if (!test_match && collect_matches) + continue; + + for (i = 0; i < ARRAY_SIZE(test_cell_id_matching_tests); i++) { + const struct test_cell_id_matching_data *d = &test_cell_id_matching_tests[i]; + struct gsm0808_cell_id_list2 add; + + /* Ignore those with a different d->id */ + if (d->id.id_discr != id->id_discr + || !gsm0808_cell_ids_match(&d->id, id)) + continue; + + /* Ignore those with a different d->match_id discr */ + if (d->match_id.id_discr != list_discr) + continue; + + if (collect_matches != d->expect_match) + continue; + + if (match_idx < 0 && d->expect_match) { + match_idx = list.id_list_len; + } + + gsm0808_cell_id_to_list(&add, &d->match_id); + gsm0808_cell_id_list_add(&list, &add); + } + } + + if (!list.id_list_len) { + printf("%s vs. %s: No match_id entries to test %s\n", + gsm0808_cell_id_name(id), + gsm0808_cell_id_discr_name(list_discr), + test_match ? "MATCH" : "mismatch"); + return true; + } + + result = gsm0808_cell_id_matches_list(id, &list, 0); + + printf("%s and %s: ", + gsm0808_cell_id_name(id), + gsm0808_cell_id_list_name(&list)); + if (result >= 0) + printf("MATCH at [%d]\n", result); + else + printf("mismatch\n"); + + if (test_match + && (result < 0 || result != match_idx)) { + printf(" ERROR: expected MATCH at %d\n", match_idx); + return false; + } + + if (!test_match && result >= 0) { + printf(" ERROR: expected mismatch\n"); + return false; + } + + return true; +} + +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++) + if (!test_cell_id_list_matching_discrs(test_match, + discrs[i], discrs[j])) + ok = false; + } + + OSMO_ASSERT(ok); +} + int main(int argc, char **argv) { printf("Testing generation of GSM0808 messages\n"); @@ -1773,6 +2037,10 @@ test_gsm0808_sc_cfg_from_gsm48_mr_cfg(); test_gsm48_mr_cfg_from_gsm0808_sc_cfg(); + test_cell_id_matching(); + test_cell_id_list_matching(true); + test_cell_id_list_matching(false); + printf("Done\n"); return EXIT_SUCCESS; } diff --git a/tests/gsm0808/gsm0808_test.ok b/tests/gsm0808/gsm0808_test.ok index 58bc509..9ee54df 100644 --- a/tests/gsm0808/gsm0808_test.ok +++ b/tests/gsm0808/gsm0808_test.ok @@ -432,4 +432,125 @@ m10_2= 0 m12_2= 1 + +test_cell_id_matching +[0] LAC:23 LAC:23 MATCH +[1] LAC:23 LAC:42 don't match +[2] LAC:23 CI:5 MATCH +[3] LAC:23 CI:6 MATCH +[4] LAC:23 LAC-CI:23-5 MATCH +[5] LAC:23 LAC-CI:42-6 don't match +[6] LAC:23 LAI:023-042-23 MATCH +[7] LAC:23 LAI:023-042-42 don't match +[8] LAC:23 LAI:023-99-23 MATCH +[9] LAC:23 LAI:023-42-23 MATCH +[10] LAC:23 CGI:023-042-23-5 MATCH +[11] LAC:23 CGI:023-042-42-6 don't match +[12] LAC:23 CGI:023-99-23-5 MATCH +[13] CI:5 LAC:23 MATCH +[14] CI:5 LAC:42 MATCH +[15] CI:5 CI:5 MATCH +[16] CI:5 CI:6 don't match +[17] CI:5 LAC-CI:23-5 MATCH +[18] CI:5 LAC-CI:42-6 don't match +[19] CI:5 LAI:023-042-23 MATCH +[20] CI:5 LAI:023-042-42 MATCH +[21] CI:5 LAI:023-99-23 MATCH +[22] CI:5 LAI:023-42-23 MATCH +[23] CI:5 CGI:023-042-23-5 MATCH +[24] CI:5 CGI:023-042-42-6 don't match +[25] CI:5 CGI:023-99-23-5 MATCH +[26] LAC-CI:23-5 LAC:23 MATCH +[27] LAC-CI:23-5 LAC:42 don't match +[28] LAC-CI:23-5 CI:5 MATCH +[29] LAC-CI:23-5 CI:6 don't match +[30] LAC-CI:23-5 LAC-CI:23-5 MATCH +[31] LAC-CI:23-5 LAC-CI:42-6 don't match +[32] LAC-CI:23-5 LAI:023-042-23 MATCH +[33] LAC-CI:23-5 LAI:023-042-42 don't match +[34] LAC-CI:23-5 LAI:023-99-23 MATCH +[35] LAC-CI:23-5 LAI:023-42-23 MATCH +[36] LAC-CI:23-5 CGI:023-042-23-5 MATCH +[37] LAC-CI:23-5 CGI:023-042-42-6 don't match +[38] LAC-CI:23-5 CGI:023-99-23-5 MATCH +[39] LAI:023-042-23 LAC:23 MATCH +[40] LAI:023-042-23 LAC:42 don't match +[41] LAI:023-042-23 CI:5 MATCH +[42] LAI:023-042-23 CI:6 MATCH +[43] LAI:023-042-23 LAC-CI:23-5 MATCH +[44] LAI:023-042-23 LAC-CI:42-6 don't match +[45] LAI:023-042-23 LAI:023-042-23 MATCH +[46] LAI:023-042-23 LAI:023-042-42 don't match +[47] LAI:023-042-23 LAI:023-99-23 don't match +[48] LAI:023-042-23 LAI:023-42-23 don't match +[49] LAI:023-042-23 CGI:023-042-23-5 MATCH +[50] LAI:023-042-23 CGI:023-042-42-6 don't match +[51] LAI:023-042-23 CGI:023-99-23-5 don't match +[52] CGI:023-042-23-5 LAC:23 MATCH +[53] CGI:023-042-23-5 LAC:42 don't match +[54] CGI:023-042-23-5 CI:5 MATCH +[55] CGI:023-042-23-5 CI:6 don't match +[56] CGI:023-042-23-5 LAC-CI:23-5 MATCH +[57] CGI:023-042-23-5 LAC-CI:42-6 don't match +[58] CGI:023-042-23-5 LAI:023-042-23 MATCH +[59] CGI:023-042-23-5 LAI:023-042-42 don't match +[60] CGI:023-042-23-5 LAI:023-99-23 don't match +[61] CGI:023-042-23-5 LAI:023-42-23 don't match +[62] CGI:023-042-23-5 CGI:023-042-23-5 MATCH +[63] CGI:023-042-23-5 CGI:023-042-42-6 don't match +[64] CGI:023-042-23-5 CGI:023-99-23-5 don't match + +test_cell_id_list_matching(test match) +LAC:23 and LAC[2]:{42, 23}: MATCH at [1] +LAC:23 and CI[2]:{5, 6}: MATCH at [0] +LAC:23 and LAC-CI[2]:{42-6, 23-5}: MATCH at [1] +LAC:23 and LAI[4]:{023-042-42, 023-042-23, 023-99-23, 023-42-23}: MATCH at [1] +LAC:23 and CGI[3]:{023-042-42-6, 023-042-23-5, 023-99-23-5}: MATCH at [1] +CI:5 and LAC[2]:{23, 42}: MATCH at [0] +CI:5 and CI[2]:{6, 5}: MATCH at [1] +CI:5 and LAC-CI[2]:{42-6, 23-5}: MATCH at [1] +CI:5 and LAI[4]:{023-042-23, 023-042-42, 023-99-23, 023-42-23}: MATCH at [0] +CI:5 and CGI[3]:{023-042-42-6, 023-042-23-5, 023-99-23-5}: MATCH at [1] +LAC-CI:23-5 and LAC[2]:{42, 23}: MATCH at [1] +LAC-CI:23-5 and CI[2]:{6, 5}: MATCH at [1] +LAC-CI:23-5 and LAC-CI[2]:{42-6, 23-5}: MATCH at [1] +LAC-CI:23-5 and LAI[4]:{023-042-42, 023-042-23, 023-99-23, 023-42-23}: MATCH at [1] +LAC-CI:23-5 and CGI[3]:{023-042-42-6, 023-042-23-5, 023-99-23-5}: MATCH at [1] +LAI:023-042-23 and LAC[2]:{42, 23}: MATCH at [1] +LAI:023-042-23 and CI[2]:{5, 6}: MATCH at [0] +LAI:023-042-23 and LAC-CI[2]:{42-6, 23-5}: MATCH at [1] +LAI:023-042-23 and LAI[4]:{023-042-42, 023-99-23, 023-42-23, 023-042-23}: MATCH at [3] +LAI:023-042-23 and CGI[3]:{023-042-42-6, 023-99-23-5, 023-042-23-5}: MATCH at [2] +CGI:023-042-23-5 and LAC[2]:{42, 23}: MATCH at [1] +CGI:023-042-23-5 and CI[2]:{6, 5}: MATCH at [1] +CGI:023-042-23-5 and LAC-CI[2]:{42-6, 23-5}: MATCH at [1] +CGI:023-042-23-5 and LAI[4]:{023-042-42, 023-99-23, 023-42-23, 023-042-23}: MATCH at [3] +CGI:023-042-23-5 and CGI[3]:{023-042-42-6, 023-99-23-5, 023-042-23-5}: MATCH at [2] + +test_cell_id_list_matching(test mismatch) +LAC:23 and LAC[1]:{42}: mismatch +LAC:23 vs. CI: No match_id entries to test mismatch +LAC:23 and LAC-CI[1]:{42-6}: mismatch +LAC:23 and LAI[1]:{023-042-42}: mismatch +LAC:23 and CGI[1]:{023-042-42-6}: mismatch +CI:5 vs. LAC: No match_id entries to test mismatch +CI:5 and CI[1]:{6}: mismatch +CI:5 and LAC-CI[1]:{42-6}: mismatch +CI:5 vs. LAI: No match_id entries to test mismatch +CI:5 and CGI[1]:{023-042-42-6}: mismatch +LAC-CI:23-5 and LAC[1]:{42}: mismatch +LAC-CI:23-5 and CI[1]:{6}: mismatch +LAC-CI:23-5 and LAC-CI[1]:{42-6}: mismatch +LAC-CI:23-5 and LAI[1]:{023-042-42}: mismatch +LAC-CI:23-5 and CGI[1]:{023-042-42-6}: mismatch +LAI:023-042-23 and LAC[1]:{42}: mismatch +LAI:023-042-23 vs. CI: No match_id entries to test mismatch +LAI:023-042-23 and LAC-CI[1]:{42-6}: mismatch +LAI:023-042-23 and LAI[3]:{023-042-42, 023-99-23, 023-42-23}: mismatch +LAI:023-042-23 and CGI[2]:{023-042-42-6, 023-99-23-5}: mismatch +CGI:023-042-23-5 and LAC[1]:{42}: mismatch +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 Done -- To view, visit https://gerrit.osmocom.org/11504 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-MessageType: newchange Gerrit-Change-Id: I5535f0d149c2173294538df75764dd181b023312 Gerrit-Change-Number: 11504 Gerrit-PatchSet: 1 Gerrit-Owner: Neels Hofmeyr <nhofm...@sysmocom.de>