mirror of https://gerrit.osmocom.org/libosmocore
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_match() (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 or MSC. 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. Change-Id: I5535f0d149c2173294538df75764dd181b023312
This commit is contained in:
parent
2033be8902
commit
d01ef75ab8
|
@ -78,6 +78,9 @@ const char *gsm0808_cell_id_list_name(const struct gsm0808_cell_id_list2 *cil);
|
|||
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_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);
|
||||
|
||||
uint8_t gsm0808_enc_cause(struct msgb *msg, uint16_t cause);
|
||||
uint8_t gsm0808_enc_aoip_trasp_addr(struct msgb *msg,
|
||||
|
|
|
@ -122,6 +122,8 @@ static inline int osmo_mcc_from_str(const char *mcc_str, uint16_t *mcc)
|
|||
|
||||
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);
|
||||
|
|
|
@ -1391,6 +1391,151 @@ int gsm0808_cell_id_u_name(char *buf, size_t buflen,
|
|||
}
|
||||
}
|
||||
|
||||
/* 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.
|
||||
* \param[in] exact_match If true, return true only if the CELL_IDENT types and all values are identical.
|
||||
* \returns True if the common fields of the above match.
|
||||
*/
|
||||
static 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,
|
||||
bool exact_match)
|
||||
{
|
||||
struct osmo_cell_global_id a = {};
|
||||
struct osmo_cell_global_id b = {};
|
||||
|
||||
if (exact_match && discr1 != discr2)
|
||||
return false;
|
||||
|
||||
/* 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_BSS:
|
||||
return discr1 == discr2;
|
||||
case CELL_IDENT_UTRAN_PLMN_LAC_RNC:
|
||||
case CELL_IDENT_UTRAN_RNC:
|
||||
case CELL_IDENT_UTRAN_LAC_RNC:
|
||||
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.
|
||||
* \param[in] exact_match If true, return true only if the CELL_IDENT types and all values are identical.
|
||||
* \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, bool exact_match)
|
||||
{
|
||||
return gsm0808_cell_id_u_match(id1->id_discr, &id1->id, id2->id_discr, &id2->id, exact_match);
|
||||
}
|
||||
|
||||
/*! 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.
|
||||
* \param[in] exact_match If true, consider as match only if the CELL_IDENT types and all values are identical.
|
||||
* \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, bool exact_match)
|
||||
{
|
||||
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], exact_match)) {
|
||||
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" },
|
||||
|
|
|
@ -324,6 +324,40 @@ int osmo_plmn_cmp(const struct osmo_plmn_id *a, const struct osmo_plmn_id *b)
|
|||
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)
|
||||
|
|
|
@ -210,6 +210,8 @@ gsm0808_cell_id_list_name;
|
|||
gsm0808_cell_id_list_name_buf;
|
||||
gsm0808_cell_id_discr_names;
|
||||
gsm0808_cell_id_u_name;
|
||||
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;
|
||||
|
|
|
@ -1937,6 +1937,275 @@ void test_gsm48_mr_cfg_from_gsm0808_sc_cfg()
|
|||
(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;
|
||||
bool expect_exact_match;
|
||||
};
|
||||
|
||||
#define lac_23 { .id_discr = CELL_IDENT_LAC, .id.lac = 23, }
|
||||
#define lac_42 { .id_discr = CELL_IDENT_LAC, .id.lac = 42, }
|
||||
#define ci_5 { .id_discr = CELL_IDENT_CI, .id.ci = 5, }
|
||||
#define ci_6 { .id_discr = CELL_IDENT_CI, .id.ci = 6, }
|
||||
#define lac_ci_23_5 { \
|
||||
.id_discr = CELL_IDENT_LAC_AND_CI, \
|
||||
.id.lac_and_ci = { .lac = 23, .ci = 5, }, \
|
||||
}
|
||||
#define lac_ci_42_6 { \
|
||||
.id_discr = CELL_IDENT_LAC_AND_CI, \
|
||||
.id.lac_and_ci = { .lac = 42, .ci = 6, }, \
|
||||
}
|
||||
#define 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, }, \
|
||||
}
|
||||
#define 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, }, \
|
||||
}
|
||||
#define 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, }, \
|
||||
}
|
||||
#define 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, }, \
|
||||
}
|
||||
#define 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, \
|
||||
}, \
|
||||
}
|
||||
#define 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, \
|
||||
}, \
|
||||
}
|
||||
#define 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, \
|
||||
}, \
|
||||
}
|
||||
|
||||
|
||||
static const struct test_cell_id_matching_data test_cell_id_matching_tests[] = {
|
||||
{ .id = lac_23, .match_id = lac_23, .expect_match = true, .expect_exact_match = true },
|
||||
{ .id = lac_23, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = lac_23, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lac_23, .match_id = ci_6, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lac_23, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lac_23, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = lac_23, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lac_23, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = lac_23, .match_id = lai_23_99_23, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lac_23, .match_id = lai_23_42_23, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lac_23, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lac_23, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = lac_23, .match_id = cgi_23_99_23_5, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = ci_5, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = ci_5, .match_id = lac_42, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = ci_5, .match_id = ci_5, .expect_match = true, .expect_exact_match = true },
|
||||
{ .id = ci_5, .match_id = ci_6, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = ci_5, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = ci_5, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = ci_5, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = ci_5, .match_id = lai_23_042_42, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = ci_5, .match_id = lai_23_99_23, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = ci_5, .match_id = lai_23_42_23, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = ci_5, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = ci_5, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = ci_5, .match_id = cgi_23_99_23_5, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lac_ci_23_5, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lac_ci_23_5, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = lac_ci_23_5, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lac_ci_23_5, .match_id = ci_6, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = lac_ci_23_5, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = true },
|
||||
{ .id = lac_ci_23_5, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = lac_ci_23_5, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lac_ci_23_5, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = lac_ci_23_5, .match_id = lai_23_99_23, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lac_ci_23_5, .match_id = lai_23_42_23, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lac_ci_23_5, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lac_ci_23_5, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = lac_ci_23_5, .match_id = cgi_23_99_23_5, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lai_23_042_23, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lai_23_042_23, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = lai_23_042_23, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lai_23_042_23, .match_id = ci_6, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lai_23_042_23, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lai_23_042_23, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = lai_23_042_23, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = true },
|
||||
{ .id = lai_23_042_23, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = lai_23_042_23, .match_id = lai_23_99_23, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = lai_23_042_23, .match_id = lai_23_42_23, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = lai_23_042_23, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = lai_23_042_23, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = lai_23_042_23, .match_id = cgi_23_99_23_5, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = cgi_23_042_23_5, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = cgi_23_042_23_5, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = cgi_23_042_23_5, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = cgi_23_042_23_5, .match_id = ci_6, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = cgi_23_042_23_5, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = cgi_23_042_23_5, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = cgi_23_042_23_5, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
|
||||
{ .id = cgi_23_042_23_5, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = cgi_23_042_23_5, .match_id = lai_23_99_23, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = cgi_23_042_23_5, .match_id = lai_23_42_23, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = cgi_23_042_23_5, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = true },
|
||||
{ .id = cgi_23_042_23_5, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
|
||||
{ .id = cgi_23_042_23_5, .match_id = cgi_23_99_23_5, .expect_match = false, .expect_exact_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];
|
||||
int exact_match;
|
||||
|
||||
for (exact_match = 0; exact_match < 2; exact_match++) {
|
||||
bool result;
|
||||
bool expect_result = exact_match ? d->expect_exact_match : d->expect_match;
|
||||
|
||||
result = gsm0808_cell_ids_match(&d->id, &d->match_id, (bool)exact_match);
|
||||
|
||||
printf("[%d] %s %s %s%s\n",
|
||||
i,
|
||||
gsm0808_cell_id_name(&d->id),
|
||||
gsm0808_cell_id_name2(&d->match_id),
|
||||
result ? "MATCH" : "don't match",
|
||||
exact_match ? " exactly" : "");
|
||||
if (result != expect_result) {
|
||||
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 (!gsm0808_cell_ids_match(&d->id, id, true))
|
||||
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, false);
|
||||
|
||||
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)
|
||||
{
|
||||
void *ctx = talloc_named_const(NULL, 0, "gsm0808 test");
|
||||
|
@ -2002,6 +2271,10 @@ int main(int argc, char **argv)
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -439,4 +439,190 @@ Output:
|
|||
m10_2= 0
|
||||
m12_2= 1
|
||||
|
||||
|
||||
test_cell_id_matching
|
||||
[0] LAC:23 LAC:23 MATCH
|
||||
[0] LAC:23 LAC:23 MATCH exactly
|
||||
[1] LAC:23 LAC:42 don't match
|
||||
[1] LAC:23 LAC:42 don't match exactly
|
||||
[2] LAC:23 CI:5 MATCH
|
||||
[2] LAC:23 CI:5 don't match exactly
|
||||
[3] LAC:23 CI:6 MATCH
|
||||
[3] LAC:23 CI:6 don't match exactly
|
||||
[4] LAC:23 LAC-CI:23-5 MATCH
|
||||
[4] LAC:23 LAC-CI:23-5 don't match exactly
|
||||
[5] LAC:23 LAC-CI:42-6 don't match
|
||||
[5] LAC:23 LAC-CI:42-6 don't match exactly
|
||||
[6] LAC:23 LAI:023-042-23 MATCH
|
||||
[6] LAC:23 LAI:023-042-23 don't match exactly
|
||||
[7] LAC:23 LAI:023-042-42 don't match
|
||||
[7] LAC:23 LAI:023-042-42 don't match exactly
|
||||
[8] LAC:23 LAI:023-99-23 MATCH
|
||||
[8] LAC:23 LAI:023-99-23 don't match exactly
|
||||
[9] LAC:23 LAI:023-42-23 MATCH
|
||||
[9] LAC:23 LAI:023-42-23 don't match exactly
|
||||
[10] LAC:23 CGI:023-042-23-5 MATCH
|
||||
[10] LAC:23 CGI:023-042-23-5 don't match exactly
|
||||
[11] LAC:23 CGI:023-042-42-6 don't match
|
||||
[11] LAC:23 CGI:023-042-42-6 don't match exactly
|
||||
[12] LAC:23 CGI:023-99-23-5 MATCH
|
||||
[12] LAC:23 CGI:023-99-23-5 don't match exactly
|
||||
[13] CI:5 LAC:23 MATCH
|
||||
[13] CI:5 LAC:23 don't match exactly
|
||||
[14] CI:5 LAC:42 MATCH
|
||||
[14] CI:5 LAC:42 don't match exactly
|
||||
[15] CI:5 CI:5 MATCH
|
||||
[15] CI:5 CI:5 MATCH exactly
|
||||
[16] CI:5 CI:6 don't match
|
||||
[16] CI:5 CI:6 don't match exactly
|
||||
[17] CI:5 LAC-CI:23-5 MATCH
|
||||
[17] CI:5 LAC-CI:23-5 don't match exactly
|
||||
[18] CI:5 LAC-CI:42-6 don't match
|
||||
[18] CI:5 LAC-CI:42-6 don't match exactly
|
||||
[19] CI:5 LAI:023-042-23 MATCH
|
||||
[19] CI:5 LAI:023-042-23 don't match exactly
|
||||
[20] CI:5 LAI:023-042-42 MATCH
|
||||
[20] CI:5 LAI:023-042-42 don't match exactly
|
||||
[21] CI:5 LAI:023-99-23 MATCH
|
||||
[21] CI:5 LAI:023-99-23 don't match exactly
|
||||
[22] CI:5 LAI:023-42-23 MATCH
|
||||
[22] CI:5 LAI:023-42-23 don't match exactly
|
||||
[23] CI:5 CGI:023-042-23-5 MATCH
|
||||
[23] CI:5 CGI:023-042-23-5 don't match exactly
|
||||
[24] CI:5 CGI:023-042-42-6 don't match
|
||||
[24] CI:5 CGI:023-042-42-6 don't match exactly
|
||||
[25] CI:5 CGI:023-99-23-5 MATCH
|
||||
[25] CI:5 CGI:023-99-23-5 don't match exactly
|
||||
[26] LAC-CI:23-5 LAC:23 MATCH
|
||||
[26] LAC-CI:23-5 LAC:23 don't match exactly
|
||||
[27] LAC-CI:23-5 LAC:42 don't match
|
||||
[27] LAC-CI:23-5 LAC:42 don't match exactly
|
||||
[28] LAC-CI:23-5 CI:5 MATCH
|
||||
[28] LAC-CI:23-5 CI:5 don't match exactly
|
||||
[29] LAC-CI:23-5 CI:6 don't match
|
||||
[29] LAC-CI:23-5 CI:6 don't match exactly
|
||||
[30] LAC-CI:23-5 LAC-CI:23-5 MATCH
|
||||
[30] LAC-CI:23-5 LAC-CI:23-5 MATCH exactly
|
||||
[31] LAC-CI:23-5 LAC-CI:42-6 don't match
|
||||
[31] LAC-CI:23-5 LAC-CI:42-6 don't match exactly
|
||||
[32] LAC-CI:23-5 LAI:023-042-23 MATCH
|
||||
[32] LAC-CI:23-5 LAI:023-042-23 don't match exactly
|
||||
[33] LAC-CI:23-5 LAI:023-042-42 don't match
|
||||
[33] LAC-CI:23-5 LAI:023-042-42 don't match exactly
|
||||
[34] LAC-CI:23-5 LAI:023-99-23 MATCH
|
||||
[34] LAC-CI:23-5 LAI:023-99-23 don't match exactly
|
||||
[35] LAC-CI:23-5 LAI:023-42-23 MATCH
|
||||
[35] LAC-CI:23-5 LAI:023-42-23 don't match exactly
|
||||
[36] LAC-CI:23-5 CGI:023-042-23-5 MATCH
|
||||
[36] LAC-CI:23-5 CGI:023-042-23-5 don't match exactly
|
||||
[37] LAC-CI:23-5 CGI:023-042-42-6 don't match
|
||||
[37] LAC-CI:23-5 CGI:023-042-42-6 don't match exactly
|
||||
[38] LAC-CI:23-5 CGI:023-99-23-5 MATCH
|
||||
[38] LAC-CI:23-5 CGI:023-99-23-5 don't match exactly
|
||||
[39] LAI:023-042-23 LAC:23 MATCH
|
||||
[39] LAI:023-042-23 LAC:23 don't match exactly
|
||||
[40] LAI:023-042-23 LAC:42 don't match
|
||||
[40] LAI:023-042-23 LAC:42 don't match exactly
|
||||
[41] LAI:023-042-23 CI:5 MATCH
|
||||
[41] LAI:023-042-23 CI:5 don't match exactly
|
||||
[42] LAI:023-042-23 CI:6 MATCH
|
||||
[42] LAI:023-042-23 CI:6 don't match exactly
|
||||
[43] LAI:023-042-23 LAC-CI:23-5 MATCH
|
||||
[43] LAI:023-042-23 LAC-CI:23-5 don't match exactly
|
||||
[44] LAI:023-042-23 LAC-CI:42-6 don't match
|
||||
[44] LAI:023-042-23 LAC-CI:42-6 don't match exactly
|
||||
[45] LAI:023-042-23 LAI:023-042-23 MATCH
|
||||
[45] LAI:023-042-23 LAI:023-042-23 MATCH exactly
|
||||
[46] LAI:023-042-23 LAI:023-042-42 don't match
|
||||
[46] LAI:023-042-23 LAI:023-042-42 don't match exactly
|
||||
[47] LAI:023-042-23 LAI:023-99-23 don't match
|
||||
[47] LAI:023-042-23 LAI:023-99-23 don't match exactly
|
||||
[48] LAI:023-042-23 LAI:023-42-23 don't match
|
||||
[48] LAI:023-042-23 LAI:023-42-23 don't match exactly
|
||||
[49] LAI:023-042-23 CGI:023-042-23-5 MATCH
|
||||
[49] LAI:023-042-23 CGI:023-042-23-5 don't match exactly
|
||||
[50] LAI:023-042-23 CGI:023-042-42-6 don't match
|
||||
[50] LAI:023-042-23 CGI:023-042-42-6 don't match exactly
|
||||
[51] LAI:023-042-23 CGI:023-99-23-5 don't match
|
||||
[51] LAI:023-042-23 CGI:023-99-23-5 don't match exactly
|
||||
[52] CGI:023-042-23-5 LAC:23 MATCH
|
||||
[52] CGI:023-042-23-5 LAC:23 don't match exactly
|
||||
[53] CGI:023-042-23-5 LAC:42 don't match
|
||||
[53] CGI:023-042-23-5 LAC:42 don't match exactly
|
||||
[54] CGI:023-042-23-5 CI:5 MATCH
|
||||
[54] CGI:023-042-23-5 CI:5 don't match exactly
|
||||
[55] CGI:023-042-23-5 CI:6 don't match
|
||||
[55] CGI:023-042-23-5 CI:6 don't match exactly
|
||||
[56] CGI:023-042-23-5 LAC-CI:23-5 MATCH
|
||||
[56] CGI:023-042-23-5 LAC-CI:23-5 don't match exactly
|
||||
[57] CGI:023-042-23-5 LAC-CI:42-6 don't match
|
||||
[57] CGI:023-042-23-5 LAC-CI:42-6 don't match exactly
|
||||
[58] CGI:023-042-23-5 LAI:023-042-23 MATCH
|
||||
[58] CGI:023-042-23-5 LAI:023-042-23 don't match exactly
|
||||
[59] CGI:023-042-23-5 LAI:023-042-42 don't match
|
||||
[59] CGI:023-042-23-5 LAI:023-042-42 don't match exactly
|
||||
[60] CGI:023-042-23-5 LAI:023-99-23 don't match
|
||||
[60] CGI:023-042-23-5 LAI:023-99-23 don't match exactly
|
||||
[61] CGI:023-042-23-5 LAI:023-42-23 don't match
|
||||
[61] CGI:023-042-23-5 LAI:023-42-23 don't match exactly
|
||||
[62] CGI:023-042-23-5 CGI:023-042-23-5 MATCH
|
||||
[62] CGI:023-042-23-5 CGI:023-042-23-5 MATCH exactly
|
||||
[63] CGI:023-042-23-5 CGI:023-042-42-6 don't match
|
||||
[63] CGI:023-042-23-5 CGI:023-042-42-6 don't match exactly
|
||||
[64] CGI:023-042-23-5 CGI:023-99-23-5 don't match
|
||||
[64] CGI:023-042-23-5 CGI:023-99-23-5 don't match exactly
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue