[PATCH] osmo-bsc[master]: implement support for 3-digit MNC with leading zeros

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Neels Hofmeyr gerrit-no-reply at lists.osmocom.org
Mon Mar 5 01:26:59 UTC 2018


Hello Harald Welte, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/6668

to look at the new patch set (#6).

implement support for 3-digit MNC with leading zeros

Add 3-digit flags and use the new RAI and LAI API from libosmocore throughout
the code base to be able to handle an MNC < 100 that has three digits (leading
zeros).

The changes to abis_test and gsm0408_test show that this code now handles
3-digit MNC correctly, by not dropping the leading zero as 0xf in the encoded
PLMN.

Re-implement CTRL commands 'mcc', 'mnc' and 'mcc-mnc-apply' to preserve the
presence of the third digit of the MNC. Always reply with all leading zeros.
Adjust the expected results in ctrl_test_runner.py, to show that it works.

Depends: Id2240f7f518494c9df6c8bda52c0d5092f90f221 (libosmocore),
	 Ib7176b1d65a03b76f41f94bc9d3293a8a07d24c6 (libosmocore)
Change-Id: I8e722103344186fde118b26d8353db95a4581daa
---
M include/osmocom/bsc/bsc_msc_data.h
M include/osmocom/bsc/gsm_data.h
M src/libbsc/bsc_ctrl_commands.c
M src/libbsc/bsc_init.c
M src/libbsc/bsc_vty.c
M src/libbsc/gsm_data.c
M src/libbsc/net_init.c
M src/libbsc/pcu_sock.c
M src/libbsc/system_information.c
M src/osmo-bsc/osmo_bsc_api.c
M src/osmo-bsc/osmo_bsc_bssap.c
M src/osmo-bsc/osmo_bsc_ctrl.c
M src/osmo-bsc/osmo_bsc_filter.c
M src/osmo-bsc/osmo_bsc_msc.c
M src/osmo-bsc/osmo_bsc_vty.c
M tests/abis/abis_test.c
M tests/abis/abis_test.ok
M tests/bssap/bssap_test.err
M tests/ctrl_test_runner.py
M tests/gsm0408/gsm0408_test.c
M tests/gsm0408/gsm0408_test.ok
M tests/nanobts_omlattr/nanobts_omlattr_test.c
22 files changed, 231 insertions(+), 167 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/68/6668/6

diff --git a/include/osmocom/bsc/bsc_msc_data.h b/include/osmocom/bsc/bsc_msc_data.h
index a3e0106..cbda10d 100644
--- a/include/osmocom/bsc/bsc_msc_data.h
+++ b/include/osmocom/bsc/bsc_msc_data.h
@@ -78,8 +78,9 @@
 	struct osmo_timer_list pong_timer;
 	int advanced_ping;
 	struct bsc_msc_connection *msc_con;
-	int core_mnc;
-	int core_mcc;
+	uint16_t core_mcc;
+	uint16_t core_mnc;
+	bool core_mnc_3_digits;
 	int core_lac;
 	int core_ci;
 	int rtp_base;
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index 8692469..27aa261 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -13,6 +13,7 @@
 #include <osmocom/core/stats.h>
 #include <osmocom/core/stat_item.h>
 #include <osmocom/gsm/protocol/gsm_08_08.h>
+#include <osmocom/gsm/gsm48.h>
 
 #include <osmocom/crypt/auth.h>
 
@@ -1197,9 +1198,8 @@
 	 * these have in common, like country and network code, put in yet
 	 * separate structs and placed as members in osmo_bsc and osmo_msc. */
 
-	/* global parameters */
-	uint16_t country_code;
-	uint16_t network_code;
+	struct osmo_plmn_id plmn;
+
 	/* bit-mask of permitted encryption algorithms. LSB=A5/0, MSB=A5/7 */
 	uint8_t a5_encryption_mask;
 	int neci;
@@ -1275,6 +1275,16 @@
 	} mgw;
 };
 
+static inline const struct osmo_location_area_id *bts_lai(struct gsm_bts *bts)
+{
+	static struct osmo_location_area_id lai;
+	lai = (struct osmo_location_area_id){
+		.plmn = bts->network->plmn,
+		.lac = bts->location_area_code,
+	};
+	return &lai;
+}
+
 extern void talloc_ctx_init(void *ctx_root);
 
 int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type);
diff --git a/src/libbsc/bsc_ctrl_commands.c b/src/libbsc/bsc_ctrl_commands.c
index 41d2361..b5aa77d 100644
--- a/src/libbsc/bsc_ctrl_commands.c
+++ b/src/libbsc/bsc_ctrl_commands.c
@@ -22,6 +22,7 @@
 #include <time.h>
 
 #include <osmocom/ctrl/control_cmd.h>
+#include <osmocom/gsm/gsm48.h>
 #include <osmocom/bsc/ipaccess.h>
 #include <osmocom/bsc/gsm_data.h>
 #include <osmocom/bsc/abis_nm.h>
@@ -30,8 +31,65 @@
 #include <osmocom/bsc/osmo_bsc_rf.h>
 #include <osmocom/bsc/bsc_msc_data.h>
 
-CTRL_CMD_DEFINE_RANGE(net_mnc, "mnc", struct gsm_network, network_code, 0, 999);
-CTRL_CMD_DEFINE_RANGE(net_mcc, "mcc", struct gsm_network, country_code, 1, 999);
+CTRL_CMD_DEFINE(net_mcc, "mcc");
+static int get_net_mcc(struct ctrl_cmd *cmd, void *_data)
+{
+	struct gsm_network *net = cmd->node;
+	cmd->reply = talloc_asprintf(cmd, "%s", osmo_mcc_name(net->plmn.mcc));
+	if (!cmd->reply) {
+		cmd->reply = "OOM";
+		return CTRL_CMD_ERROR;
+	}
+	return CTRL_CMD_REPLY;
+}
+static int set_net_mcc(struct ctrl_cmd *cmd, void *_data)
+{
+	struct gsm_network *net = cmd->node;
+	uint16_t mcc;
+	/* re-use the string parsing logic from osmo_mnc_from_str(), we just don't need the 3-digits
+	 * indicator. */
+	if (osmo_mnc_from_str(cmd->value, &mcc, NULL))
+		return -1;
+	net->plmn.mcc = mcc;
+	return get_net_mcc(cmd, _data);
+}
+static int verify_net_mcc(struct ctrl_cmd *cmd, const char *value, void *_data)
+{
+	/* re-use the string parsing logic from osmo_mnc_from_str(), we just don't need the 3-digits
+	 * indicator. */
+	if (osmo_mnc_from_str(value, NULL, NULL))
+		return -1;
+	return 0;
+}
+
+CTRL_CMD_DEFINE(net_mnc, "mnc");
+static int get_net_mnc(struct ctrl_cmd *cmd, void *_data)
+{
+	struct gsm_network *net = cmd->node;
+	cmd->reply = talloc_asprintf(cmd, "%s", osmo_mnc_name(net->plmn.mnc, net->plmn.mnc_3_digits));
+	if (!cmd->reply) {
+		cmd->reply = "OOM";
+		return CTRL_CMD_ERROR;
+	}
+	return CTRL_CMD_REPLY;
+}
+static int set_net_mnc(struct ctrl_cmd *cmd, void *_data)
+{
+	struct gsm_network *net = cmd->node;
+	struct osmo_plmn_id plmn = net->plmn;
+	if (osmo_mnc_from_str(cmd->value, &plmn.mnc, &plmn.mnc_3_digits)) {
+		cmd->reply = "Error while decoding MNC";
+		return CTRL_CMD_ERROR;
+	}
+	net->plmn = plmn;
+	return get_net_mnc(cmd, _data);
+}
+static int verify_net_mnc(struct ctrl_cmd *cmd, const char *value, void *_data)
+{
+	if (osmo_mnc_from_str(value, NULL, NULL))
+		return -1;
+	return 0;
+}
 
 static int set_net_apply_config(struct ctrl_cmd *cmd, void *data)
 {
@@ -75,6 +133,10 @@
 
 	if (!mcc || !mnc)
 		return 1;
+
+	if (osmo_mnc_from_str(mnc, NULL, NULL))
+		return 1;
+
 	return 0;
 }
 
@@ -82,28 +144,35 @@
 {
 	struct gsm_network *net = cmd->node;
 	char *tmp, *saveptr, *mcc_str, *mnc_str;
-	int mcc, mnc;
+	struct osmo_plmn_id plmn;
 
 	tmp = talloc_strdup(cmd, cmd->value);
 	if (!tmp)
 		goto oom;
 
-
 	mcc_str = strtok_r(tmp, ",", &saveptr);
 	mnc_str = strtok_r(NULL, ",", &saveptr);
 
-	mcc = atoi(mcc_str);
-	mnc = atoi(mnc_str);
+	/* re-use the string parsing logic from osmo_mnc_from_str(), we just don't need the 3-digits
+	 * indicator. */
+	if (osmo_mnc_from_str(mcc_str, &plmn.mcc, NULL)) {
+		cmd->reply = "Error while decoding MCC";
+		return 1;
+	}
+
+	if (osmo_mnc_from_str(mnc_str, &plmn.mnc, &plmn.mnc_3_digits)) {
+		cmd->reply = "Error while decoding MNC";
+		return CTRL_CMD_ERROR;
+	}
 
 	talloc_free(tmp);
 
-	if (net->network_code == mnc && net->country_code == mcc) {
+	if (!osmo_plmn_cmp(&net->plmn, &plmn)) {
 		cmd->reply = "Nothing changed";
 		return CTRL_CMD_REPLY;
 	}
 
-	net->network_code = mnc;
-	net->country_code = mcc;
+	net->plmn = plmn;
 
 	return set_net_apply_config(cmd, data);
 
diff --git a/src/libbsc/bsc_init.c b/src/libbsc/bsc_init.c
index a2f0504..f164533 100644
--- a/src/libbsc/bsc_init.c
+++ b/src/libbsc/bsc_init.c
@@ -326,9 +326,10 @@
 	unsigned int i;
 
 	LOGP(DRSL, LOGL_NOTICE, "bootstrapping RSL for BTS/TRX (%u/%u) "
-		"on ARFCN %u using MCC=%u MNC=%u LAC=%u CID=%u BSIC=%u\n",
-		trx->bts->nr, trx->nr, trx->arfcn, bsc_gsmnet->country_code,
-		bsc_gsmnet->network_code, trx->bts->location_area_code,
+		"on ARFCN %u using MCC-MNC %s LAC=%u CID=%u BSIC=%u\n",
+		trx->bts->nr, trx->nr, trx->arfcn,
+		osmo_plmn_name(&bsc_gsmnet->plmn),
+		trx->bts->location_area_code,
 		trx->bts->cell_identity, trx->bts->bsic);
 
 	/*
diff --git a/src/libbsc/bsc_vty.c b/src/libbsc/bsc_vty.c
index 3dac29e..69559b6 100644
--- a/src/libbsc/bsc_vty.c
+++ b/src/libbsc/bsc_vty.c
@@ -203,9 +203,8 @@
 	struct pchan_load pl;
 	int i;
 
-	vty_out(vty, "BSC is on Country Code %u, Network Code %u "
-		"and has %u BTS%s", net->country_code, net->network_code,
-		net->num_bts, VTY_NEWLINE);
+	vty_out(vty, "BSC is on MCC-MNC %s and has %u BTS%s",
+		osmo_plmn_name(&net->plmn), net->num_bts, VTY_NEWLINE);
 	vty_out(vty, "%s", VTY_NEWLINE);
 	vty_out(vty, "  Encryption:");
 	for (i = 0; i < 8; i++) {
@@ -955,8 +954,9 @@
 	int i;
 
 	vty_out(vty, "network%s", VTY_NEWLINE);
-	vty_out(vty, " network country code %u%s", gsmnet->country_code, VTY_NEWLINE);
-	vty_out(vty, " mobile network code %u%s", gsmnet->network_code, VTY_NEWLINE);
+	vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
+	vty_out(vty, " mobile network code %s%s",
+		osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
 	vty_out(vty, " encryption a5");
 	for (i = 0; i < 8; i++) {
 		if (gsmnet->a5_encryption_mask & (1 << i))
@@ -4513,8 +4513,15 @@
       "Network Country Code to use\n")
 {
 	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+	uint16_t mcc;
 
-	gsmnet->country_code = atoi(argv[0]);
+	/* Re-use osmo_mnc_from_str() for MCC */
+	if (osmo_mnc_from_str(argv[0], &mcc, NULL)) {
+		vty_out(vty, "%% Error decoding MCC: %s%s", argv[0], VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	gsmnet->plmn.mcc = mcc;
 
 	return CMD_SUCCESS;
 }
@@ -4528,8 +4535,16 @@
       "Mobile Network Code to use\n")
 {
 	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+	uint16_t mnc;
+	bool mnc_3_digits;
 
-	gsmnet->network_code = atoi(argv[0]);
+	if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
+		vty_out(vty, "%% Error decoding MNC: %s%s", argv[0], VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	gsmnet->plmn.mnc = mnc;
+	gsmnet->plmn.mnc_3_digits = mnc_3_digits;
 
 	return CMD_SUCCESS;
 }
diff --git a/src/libbsc/gsm_data.c b/src/libbsc/gsm_data.c
index d4a6a70..686e9c5 100644
--- a/src/libbsc/gsm_data.c
+++ b/src/libbsc/gsm_data.c
@@ -272,8 +272,9 @@
 void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts)
 {
 	*raid = (struct gprs_ra_id){
-		.mcc = bts->network->country_code,
-		.mnc = bts->network->network_code,
+		.mcc = bts->network->plmn.mcc,
+		.mnc = bts->network->plmn.mnc,
+		.mnc_3_digits = bts->network->plmn.mnc_3_digits,
 		.lac = bts->location_area_code,
 		.rac = bts->gprs.rac,
 	};
diff --git a/src/libbsc/net_init.c b/src/libbsc/net_init.c
index e44c335..d5ea5b2 100644
--- a/src/libbsc/net_init.c
+++ b/src/libbsc/net_init.c
@@ -47,8 +47,10 @@
 	if (!net)
 		return NULL;
 
-	net->country_code = 1;
-	net->network_code = 1;
+	net->plmn = (struct osmo_plmn_id){
+		.mcc = 1,
+		.mnc = 1,
+	};
 
 	/* Permit a compile-time default of A5/3 and A5/1 */
 	net->a5_encryption_mask = (1 << 3) | (1 << 1);
diff --git a/src/libbsc/pcu_sock.c b/src/libbsc/pcu_sock.c
index 9f1c80c..85af598 100644
--- a/src/libbsc/pcu_sock.c
+++ b/src/libbsc/pcu_sock.c
@@ -152,8 +152,9 @@
 		info_ind->flags |= PCU_IF_FLAG_SYSMO;
 
 	/* RAI */
-	info_ind->mcc = bts->network->country_code;
-	info_ind->mnc = bts->network->network_code;
+	info_ind->mcc = bts->network->plmn.mcc;
+	info_ind->mnc = bts->network->plmn.mnc;
+	/* TODO: plmn.mnc_3_digits */
 	info_ind->lac = bts->location_area_code;
 	info_ind->rac = bts->gprs.rac;
 
diff --git a/src/libbsc/system_information.c b/src/libbsc/system_information.c
index 750bba4..c7c85b0 100644
--- a/src/libbsc/system_information.c
+++ b/src/libbsc/system_information.c
@@ -860,9 +860,7 @@
 	si3->header.system_information = GSM48_MT_RR_SYSINFO_3;
 
 	si3->cell_identity = htons(bts->cell_identity);
-	gsm48_generate_lai(&si3->lai, bts->network->country_code,
-			   bts->network->network_code,
-			   bts->location_area_code);
+	gsm48_generate_lai2(&si3->lai, bts_lai(bts));
 	si3->control_channel_desc = bts->si_common.chan_desc;
 	si3->cell_options = bts->si_common.cell_options;
 	si3->cell_sel_par = bts->si_common.cell_sel_par;
@@ -914,9 +912,7 @@
 	si4->header.skip_indicator = 0;
 	si4->header.system_information = GSM48_MT_RR_SYSINFO_4;
 
-	gsm48_generate_lai(&si4->lai, bts->network->country_code,
-			   bts->network->network_code,
-			   bts->location_area_code);
+	gsm48_generate_lai2(&si4->lai, bts_lai(bts));
 	si4->cell_sel_par = bts->si_common.cell_sel_par;
 	si4->rach_control = bts->si_common.rach_control;
 	if (acc_ramp_is_enabled(&bts->acc_ramp))
@@ -1088,9 +1084,7 @@
 	si6->skip_indicator = 0;
 	si6->system_information = GSM48_MT_RR_SYSINFO_6;
 	si6->cell_identity = htons(bts->cell_identity);
-	gsm48_generate_lai(&si6->lai, bts->network->country_code,
-			   bts->network->network_code,
-			   bts->location_area_code);
+	gsm48_generate_lai2(&si6->lai, bts_lai(bts));
 	si6->cell_options = bts->si_common.cell_options;
 	si6->ncc_permitted = bts->si_common.ncc_permitted;
 	/* allow/disallow DTXu */
diff --git a/src/osmo-bsc/osmo_bsc_api.c b/src/osmo-bsc/osmo_bsc_api.c
index 465832c..65bca20 100644
--- a/src/osmo-bsc/osmo_bsc_api.c
+++ b/src/osmo-bsc/osmo_bsc_api.c
@@ -54,32 +54,20 @@
 static int complete_layer3(struct gsm_subscriber_connection *conn,
 			   struct msgb *msg, struct bsc_msc_data *msc);
 
-static uint16_t get_network_code_for_msc(struct bsc_msc_data *msc)
+static struct osmo_cell_global_id *cgi_for_msc(struct bsc_msc_data *msc, struct gsm_bts *bts)
 {
-	if (msc->core_mnc != -1)
-		return msc->core_mnc;
-	return msc->network->network_code;
-}
+	static struct osmo_cell_global_id cgi;
+	cgi.lai.plmn = msc->network->plmn;
+	if (msc->core_mcc != GSM_MCC_MNC_INVALID)
+		cgi.lai.plmn.mcc = msc->core_mcc;
+	if (msc->core_mnc != GSM_MCC_MNC_INVALID) {
+		cgi.lai.plmn.mnc = msc->core_mnc;
+		cgi.lai.plmn.mnc_3_digits = msc->core_mnc_3_digits;
+	}
+	cgi.lai.lac = (msc->core_lac != -1) ? msc->core_lac : bts->location_area_code;
+	cgi.cell_identity = (msc->core_ci != -1) ? msc->core_ci : bts->cell_identity;
 
-static uint16_t get_country_code_for_msc(struct bsc_msc_data *msc)
-{
-	if (msc->core_mcc != -1)
-		return msc->core_mcc;
-	return msc->network->country_code;
-}
-
-static uint16_t get_lac_for_msc(struct bsc_msc_data *msc, struct gsm_bts *bts)
-{
-	if (msc->core_lac != -1)
-		return msc->core_lac;
-	return bts->location_area_code;
-}
-
-static uint16_t get_ci_for_msc(struct bsc_msc_data *msc, struct gsm_bts *bts)
-{
-	if (msc->core_ci != -1)
-		return msc->core_ci;
-	return bts->cell_identity;
+	return &cgi;
 }
 
 static void bsc_maybe_lu_reject(struct gsm_subscriber_connection *conn, int con_type, int cause)
@@ -242,10 +230,6 @@
 	char *imsi = NULL;
 	struct timeval tv;
 	struct msgb *resp;
-	uint16_t network_code;
-	uint16_t country_code;
-	uint16_t lac;
-	uint16_t ci;
 	enum bsc_con ret;
 	int send_ping = msc->advanced_ping;
 
@@ -285,14 +269,9 @@
 
 	/* check return value, if failed check msg for and send USSD */
 
-	network_code = get_network_code_for_msc(conn->sccp.msc);
-	country_code = get_country_code_for_msc(conn->sccp.msc);
-	lac = get_lac_for_msc(conn->sccp.msc, conn_get_bts(conn));
-	ci = get_ci_for_msc(conn->sccp.msc, conn_get_bts(conn));
-
 	bsc_scan_bts_msg(conn, msg);
 
-	resp = gsm0808_create_layer3(msg, network_code, country_code, lac, ci);
+	resp = gsm0808_create_layer3_2(msg, cgi_for_msc(conn->sccp.msc, conn_get_bts(conn)), NULL);
 	if (!resp) {
 		LOGP(DMSC, LOGL_DEBUG, "Failed to create layer3 message.\n");
 		osmo_bsc_sigtran_del_conn(conn);
diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c
index d07cc55..db749a3 100644
--- a/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/src/osmo-bsc/osmo_bsc_bssap.c
@@ -262,15 +262,14 @@
 
 /* Decode 5-byte LAI list element data (see TS 08.08 3.2.2.27) into MCC/MNC/LAC.
  * Return 0 if successful, negative on error. */
-static int
-decode_lai(const uint8_t *data, uint16_t *mcc, uint16_t *mnc, uint16_t *lac)
+static void
+decode_lai(const uint8_t *data, struct osmo_location_area_id *laid)
 {
 	struct gsm48_loc_area_id lai;
 
 	/* Copy data to stack to prevent unaligned access in gsm48_decode_lai(). */
 	memcpy(&lai, data, sizeof(lai)); /* don't byte swap yet */
-
-	return gsm48_decode_lai(&lai, mcc, mnc, lac) != 0 ? -1 : 0;
+	gsm48_decode_lai2(&lai, laid);
 }
 
 static void
@@ -290,37 +289,33 @@
 	uint16_t ci;
 	int i = 0;
 	while (remain >= sizeof(struct gsm48_loc_area_id) + sizeof(ci)) {
-		uint16_t mcc, mnc, lac, *ci_be;
+		struct osmo_location_area_id lai;
+		uint16_t *ci_be;
 		size_t lai_offset = 1 + i * (sizeof(struct gsm48_loc_area_id) + sizeof(ci));
-		if (decode_lai(&data[lai_offset], &mcc, &mnc, &lac) != 0) {
-			LOGP(DMSC, LOGL_ERROR, "Paging IMSI %s: Invalid LAI in Cell Identifier List "
-			     "for BSS (0x%x), paging entire BSS anyway (%s)\n",
-			     mi_string, CELL_IDENT_BSS, osmo_hexdump(data, data_length));
-			page_all_bts(msc, tmsi, mi_string, chan_needed);
-			return;
-		}
+		decode_lai(&data[lai_offset], &lai);
 		ci_be = (uint16_t *)(&data[lai_offset + sizeof(struct gsm48_loc_area_id)]);
 		ci = osmo_load16be(ci_be);
-		if (mcc == msc->network->country_code && mnc == msc->network->network_code) {
+		if (!osmo_plmn_cmp(&lai.plmn, &msc->network->plmn)) {
 			int paged = 0;
 			struct gsm_bts *bts;
 			llist_for_each_entry(bts, &msc->network->bts_list, list) {
-				if (bts->location_area_code != lac)
+				if (bts->location_area_code != lai.lac)
 					continue;
 				if (bts->cell_identity != ci)
 					continue;
 				/* ignore errors from page_subscriber(); keep trying other BTS */
-				page_subscriber(msc, bts, tmsi, lac, mi_string, chan_needed);
+				page_subscriber(msc, bts, tmsi, lai.lac, mi_string, chan_needed);
 				paged = 1;
 			}
 			if (!paged) {
 				LOGP(DMSC, LOGL_NOTICE, "Paging IMSI %s: BTS with LAC %d and CI %d not found\n",
-				     mi_string, lac, ci);
+				     mi_string, lai.lac, ci);
 			}
 		} else {
-			LOGP(DMSC, LOGL_DEBUG, "Paging IMSI %s: MCC/MNC in Cell Identifier List "
-			     "(%d/%d) do not match our network (%d/%d)\n", mi_string, mcc, mnc,
-			     msc->network->country_code, msc->network->network_code);
+			LOGP(DMSC, LOGL_DEBUG, "Paging IMSI %s: MCC-MNC in Cell Identifier List "
+			     "(%s) do not match our network (%s)\n",
+			     mi_string, osmo_plmn_name(&lai.plmn),
+			     osmo_plmn_name2(&msc->network->plmn));
 		}
 		remain -= sizeof(struct gsm48_loc_area_id) + sizeof(ci);
 		i++;
@@ -389,32 +384,27 @@
 {
 	int i = 0;
 	while (remain >= sizeof(struct gsm48_loc_area_id)) {
-		uint16_t mcc, mnc, lac;
-		if (decode_lai(&data[1 + i * sizeof(struct gsm48_loc_area_id)], &mcc, &mnc, &lac) != 0) {
-			LOGP(DMSC, LOGL_ERROR, "Paging IMSI %s: Invalid LAI in Cell Identifier List "
-			     "for BSS (0x%x), paging entire BSS anyway (%s)\n",
-			     mi_string, CELL_IDENT_BSS, osmo_hexdump(data, data_length));
-			page_all_bts(msc, tmsi, mi_string, chan_needed);
-			return;
-		}
-		if (mcc == msc->network->country_code && mnc == msc->network->network_code) {
+		struct osmo_location_area_id lai;
+		decode_lai(&data[1 + i * sizeof(struct gsm48_loc_area_id)], &lai);
+		if (!osmo_plmn_cmp(&lai.plmn, &msc->network->plmn)) {
 			int paged = 0;
 			struct gsm_bts *bts;
 			llist_for_each_entry(bts, &msc->network->bts_list, list) {
-				if (bts->location_area_code != lac)
+				if (bts->location_area_code != lai.lac)
 					continue;
 				/* ignore errors from page_subscriber(); keep trying other BTS */
-				page_subscriber(msc, bts, tmsi, lac, mi_string, chan_needed);
+				page_subscriber(msc, bts, tmsi, lai.lac, mi_string, chan_needed);
 				paged = 1;
 			}
 			if (!paged) {
 				LOGP(DMSC, LOGL_NOTICE, "Paging IMSI %s: BTS with LAC %d not found\n",
-				     mi_string, lac);
+				     mi_string, lai.lac);
 			}
 		} else {
-			LOGP(DMSC, LOGL_DEBUG, "Paging IMSI %s: MCC/MNC in Cell Identifier List "
-			     "(%d/%d) do not match our network (%d/%d)\n", mi_string, mcc, mnc,
-			     msc->network->country_code, msc->network->network_code);
+			LOGP(DMSC, LOGL_DEBUG, "Paging IMSI %s: MCC-MNC in Cell Identifier List "
+			     "(%s) do not match our network (%s)\n",
+			     mi_string, osmo_plmn_name(&lai.plmn),
+			     osmo_plmn_name2(&msc->network->plmn));
 		}
 		remain -= sizeof(struct gsm48_loc_area_id);
 		i++;
diff --git a/src/osmo-bsc/osmo_bsc_ctrl.c b/src/osmo-bsc/osmo_bsc_ctrl.c
index 6092f23..5f88b85 100644
--- a/src/osmo-bsc/osmo_bsc_ctrl.c
+++ b/src/osmo-bsc/osmo_bsc_ctrl.c
@@ -207,10 +207,11 @@
 	policy = osmo_bsc_rf_get_policy_name(osmo_bsc_rf_get_policy_by_bts(bts));
 
 	cmd->reply = talloc_asprintf_append(cmd->reply,
-				",%s,%s,%s,%d,%d",
+				",%s,%s,%s,%s,%s",
 				oper, admin, policy,
-				bts->network->country_code,
-				bts->network->network_code);
+				osmo_mcc_name(bts->network->plmn.mcc),
+				osmo_mnc_name(bts->network->plmn.mnc,
+					      bts->network->plmn.mnc_3_digits));
 
 	osmo_bsc_send_trap(cmd, msc_con);
 	talloc_free(cmd);
diff --git a/src/osmo-bsc/osmo_bsc_filter.c b/src/osmo-bsc/osmo_bsc_filter.c
index c1f3e80..0f2eb61 100644
--- a/src/osmo-bsc/osmo_bsc_filter.c
+++ b/src/osmo-bsc/osmo_bsc_filter.c
@@ -36,21 +36,16 @@
 	struct gsm48_hdr *gh;
 	struct gsm48_loc_upd_req *lu;
 	struct gsm48_loc_area_id lai;
-	struct gsm_network *net;
-	struct gsm_bts *bts = conn_get_bts(conn);
 
 	if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*lu)) {
 		LOGP(DMSC, LOGL_ERROR, "LU too small to look at: %u\n", msgb_l3len(msg));
 		return;
 	}
 
-	net = bts->network;
-
 	gh = msgb_l3(msg);
 	lu = (struct gsm48_loc_upd_req *) gh->data;
 
-	gsm48_generate_lai(&lai, net->country_code, net->network_code,
-			   bts->location_area_code);
+	gsm48_generate_lai2(&lai, bts_lai(conn_get_bts(conn)));
 
 	if (memcmp(&lai, &lu->lai, sizeof(lai)) != 0) {
 		LOGP(DMSC, LOGL_DEBUG, "Marking con for welcome USSD.\n");
@@ -315,9 +310,9 @@
 
 static int has_core_identity(struct bsc_msc_data *msc)
 {
-	if (msc->core_mnc != -1)
+	if (msc->core_mnc != GSM_MCC_MNC_INVALID)
 		return 1;
-	if (msc->core_mcc != -1)
+	if (msc->core_mcc != GSM_MCC_MNC_INVALID)
 		return 1;
 	if (msc->core_lac != -1)
 		return 1;
@@ -332,8 +327,6 @@
 int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
 {
 	struct bsc_msc_data *msc;
-	struct gsm_bts *bts = conn_get_bts(conn);
-	struct gsm_network *net;
 	struct gsm48_loc_area_id *lai;
 	struct gsm48_hdr *gh;
 	uint8_t pdisc;
@@ -353,7 +346,6 @@
 		return 0;
 
 	mtype = gsm48_hdr_msg_type(gh);
-	net = bts->network;
 	msc = conn->sccp.msc;
 
 	if (mtype == GSM48_MT_MM_LOC_UPD_ACCEPT) {
@@ -361,9 +353,7 @@
 			if (msgb_l3len(msg) >= sizeof(*gh) + sizeof(*lai)) {
 				/* overwrite LAI in the message */
 				lai = (struct gsm48_loc_area_id *) &gh->data[0];
-				gsm48_generate_lai(lai, net->country_code,
-						   net->network_code,
-						   bts->location_area_code);
+				gsm48_generate_lai2(lai, bts_lai(conn_get_bts(conn)));
 			}
 		}
 
diff --git a/src/osmo-bsc/osmo_bsc_msc.c b/src/osmo-bsc/osmo_bsc_msc.c
index 46be2e6..61f1018 100644
--- a/src/osmo-bsc/osmo_bsc_msc.c
+++ b/src/osmo-bsc/osmo_bsc_msc.c
@@ -581,8 +581,9 @@
 	INIT_LLIST_HEAD(&msc_data->dests);
 	msc_data->ping_timeout = 20;
 	msc_data->pong_timeout = 5;
-	msc_data->core_mnc = -1;
-	msc_data->core_mcc = -1;
+	msc_data->core_mnc = GSM_MCC_MNC_INVALID;
+	msc_data->core_mnc_3_digits = false;
+	msc_data->core_mcc = GSM_MCC_MNC_INVALID;
 	msc_data->core_ci = -1;
 	msc_data->core_lac = -1;
 	msc_data->rtp_base = 4000;
diff --git a/src/osmo-bsc/osmo_bsc_vty.c b/src/osmo-bsc/osmo_bsc_vty.c
index e173b4a..f5fc91a 100644
--- a/src/osmo-bsc/osmo_bsc_vty.c
+++ b/src/osmo-bsc/osmo_bsc_vty.c
@@ -27,6 +27,7 @@
 #include <osmocom/bsc/bsc_msg_filter.h>
 
 #include <osmocom/core/talloc.h>
+#include <osmocom/gsm/gsm48.h>
 #include <osmocom/vty/logging.h>
 #include <osmocom/mgcp_client/mgcp_client.h>
 
@@ -107,12 +108,12 @@
 	struct bsc_msc_dest *dest;
 
 	vty_out(vty, "msc %d%s", msc->nr, VTY_NEWLINE);
-	if (msc->core_mnc != -1)
-		vty_out(vty, " core-mobile-network-code %d%s",
-			msc->core_mnc, VTY_NEWLINE);
-	if (msc->core_mcc != -1)
-		vty_out(vty, " core-mobile-country-code %d%s",
-			msc->core_mcc, VTY_NEWLINE);
+	if (msc->core_mnc != GSM_MCC_MNC_INVALID)
+		vty_out(vty, " core-mobile-network-code %s%s",
+			osmo_mnc_name(msc->core_mnc, msc->core_mnc_3_digits), VTY_NEWLINE);
+	if (msc->core_mcc != GSM_MCC_MNC_INVALID)
+		vty_out(vty, " core-mobile-country-code %s%s",
+			osmo_mcc_name(msc->core_mcc), VTY_NEWLINE);
 	if (msc->core_lac != -1)
 		vty_out(vty, " core-location-area-code %d%s",
 			msc->core_lac, VTY_NEWLINE);
@@ -236,7 +237,15 @@
       "Use this network code for the core network\n" "MNC value\n")
 {
 	struct bsc_msc_data *data = bsc_msc_data(vty);
-	data->core_mnc = atoi(argv[0]);
+	uint16_t mnc;
+	bool mnc_3_digits;
+	
+	if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
+		vty_out(vty, "%% Error decoding MNC: %s%s", argv[0], VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	data->core_mnc = mnc;
+	data->core_mnc_3_digits = mnc_3_digits;
 	return CMD_SUCCESS;
 }
 
@@ -245,8 +254,14 @@
       "core-mobile-country-code <1-999>",
       "Use this country code for the core network\n" "MCC value\n")
 {
+	uint16_t mcc;
 	struct bsc_msc_data *data = bsc_msc_data(vty);
-	data->core_mcc = atoi(argv[0]);
+	/* Re-use osmo_mnc_from_str() for MCC */
+	if (osmo_mnc_from_str(argv[0], &mcc, NULL)) {
+		vty_out(vty, "%% Error decoding MCC: %s%s", argv[0], VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	data->core_mcc = mcc;
 	return CMD_SUCCESS;
 }
 
diff --git a/tests/abis/abis_test.c b/tests/abis/abis_test.c
index 6369b07..bb70a15 100644
--- a/tests/abis/abis_test.c
+++ b/tests/abis/abis_test.c
@@ -101,8 +101,7 @@
 		.plmn = { .mcc = 1, .mnc = 2, .mnc_3_digits = true },
 		.lac = 3,
 		.cell_identity = 4,
-		.expect = "00f120" /* FAIL: should be "002100" */
-			"0003" "0004",
+		.expect = "002100" "0003" "0004",
 	},
 	{
 		.plmn = { .mcc = 0, .mnc = 0, .mnc_3_digits = false },
@@ -114,8 +113,7 @@
 		.plmn = { .mcc = 0, .mnc = 0, .mnc_3_digits = true },
 		.lac = 0,
 		.cell_identity = 0,
-		.expect = "00f000" /* FAIL: should be "000000" */
-			"0000" "0000",
+		.expect = "000000" "0000" "0000",
 	},
 	{
 		.plmn = { .mcc = 999, .mnc = 999, .mnc_3_digits = false },
@@ -133,8 +131,7 @@
 		.plmn = { .mcc = 909, .mnc = 90, .mnc_3_digits = true },
 		.lac = 0xabcd,
 		.cell_identity = 0x2345,
-		.expect = "09f909" /* FAIL: should be "090990" */
-			"abcd" "2345",
+		.expect = "090990" "abcd" "2345",
 	},
 };
 
@@ -151,8 +148,7 @@
 		char *result;
 		bool ok;
 
-		net.country_code = t->plmn.mcc;
-		net.network_code = t->plmn.mnc;
+		net.plmn = t->plmn;
 		bts.network = &net;
 		bts.location_area_code = t->lac;
 		bts.cell_identity = t->cell_identity;
diff --git a/tests/abis/abis_test.ok b/tests/abis/abis_test.ok
index ff7772c..e7e309c 100644
--- a/tests/abis/abis_test.ok
+++ b/tests/abis/abis_test.ok
@@ -8,9 +8,9 @@
 SELECTED: 0
 test_sw_selection(): OK
 test_abis_nm_ipaccess_cgi[0]: result=00f12000030004 pass
-test_abis_nm_ipaccess_cgi[1]: result=00f12000030004 pass
+test_abis_nm_ipaccess_cgi[1]: result=00210000030004 pass
 test_abis_nm_ipaccess_cgi[2]: result=00f00000000000 pass
-test_abis_nm_ipaccess_cgi[3]: result=00f00000000000 pass
+test_abis_nm_ipaccess_cgi[3]: result=00000000000000 pass
 test_abis_nm_ipaccess_cgi[4]: result=999999ffffffff pass
 test_abis_nm_ipaccess_cgi[5]: result=09f909abcd2345 pass
-test_abis_nm_ipaccess_cgi[6]: result=09f909abcd2345 pass
+test_abis_nm_ipaccess_cgi[6]: result=090990abcd2345 pass
diff --git a/tests/bssap/bssap_test.err b/tests/bssap/bssap_test.err
index 18bfbca..8ae3b22 100644
--- a/tests/bssap/bssap_test.err
+++ b/tests/bssap/bssap_test.err
@@ -16,7 +16,7 @@
 2:
 DMSC Rx MSC UDT: 00 19 52 08 08 59 51 20 69 00 07 43 94 09 04 01 08 44 60 1a 06 04 15 f5 49 00 65 
 DMSC Rx MSC UDT BSSMAP PAGING
-DMSC Paging IMSI 515029600703449: MCC/MNC in Cell Identifier List (515/94) do not match our network (1/1)
+DMSC Paging IMSI 515029600703449: MCC-MNC in Cell Identifier List (515-94) do not match our network (001-01)
 bsc_handle_udt() returned 0
 
 3:
diff --git a/tests/ctrl_test_runner.py b/tests/ctrl_test_runner.py
index 41765ff..f43c09a 100755
--- a/tests/ctrl_test_runner.py
+++ b/tests/ctrl_test_runner.py
@@ -371,32 +371,32 @@
         r = self.do_get('mcc')
         self.assertEquals(r['mtype'], 'GET_REPLY')
         self.assertEquals(r['var'], 'mcc')
-        self.assertEquals(r['value'], '23')
+        self.assertEquals(r['value'], '023')
 
         r = self.do_set('mcc', '023')
         r = self.do_get('mcc')
         self.assertEquals(r['mtype'], 'GET_REPLY')
         self.assertEquals(r['var'], 'mcc')
-        self.assertEquals(r['value'], '23')
+        self.assertEquals(r['value'], '023')
 
     def testMnc(self):
         r = self.do_set('mnc', '9')
         r = self.do_get('mnc')
         self.assertEquals(r['mtype'], 'GET_REPLY')
         self.assertEquals(r['var'], 'mnc')
-        self.assertEquals(r['value'], '9')
+        self.assertEquals(r['value'], '09')
 
         r = self.do_set('mnc', '09')
         r = self.do_get('mnc')
         self.assertEquals(r['mtype'], 'GET_REPLY')
         self.assertEquals(r['var'], 'mnc')
-        self.assertEquals(r['value'], '9')
+        self.assertEquals(r['value'], '09')
 
         r = self.do_set('mnc', '009')
         r = self.do_get('mnc')
         self.assertEquals(r['mtype'], 'GET_REPLY')
         self.assertEquals(r['var'], 'mnc')
-        self.assertEquals(r['value'], '9') # FAIL: expecting '009'
+        self.assertEquals(r['value'], '009')
 
 
     def testMccMncApply(self):
@@ -434,7 +434,7 @@
         r = self.do_get('mnc')
         self.assertEquals(r['mtype'], 'GET_REPLY')
         self.assertEquals(r['var'], 'mnc')
-        self.assertEquals(r['value'], '4')
+        self.assertEquals(r['value'], '04')
 
         r = self.do_get('mcc')
         self.assertEquals(r['mtype'], 'GET_REPLY')
@@ -450,7 +450,7 @@
         r = self.do_get('mnc')
         self.assertEquals(r['mtype'], 'GET_REPLY')
         self.assertEquals(r['var'], 'mnc')
-        self.assertEquals(r['value'], '3')
+        self.assertEquals(r['value'], '03')
 
         r = self.do_get('mcc')
         self.assertEquals(r['mtype'], 'GET_REPLY')
@@ -466,12 +466,12 @@
         r = self.do_get('mnc')
         self.assertEquals(r['mtype'], 'GET_REPLY')
         self.assertEquals(r['var'], 'mnc')
-        self.assertEquals(r['value'], '3') # FAIL: expecting '003'
+        self.assertEquals(r['value'], '003')
 
         r = self.do_get('mcc')
         self.assertEquals(r['mtype'], 'GET_REPLY')
         self.assertEquals(r['var'], 'mcc')
-        self.assertEquals(r['value'], '2')
+        self.assertEquals(r['value'], '002')
 
         # Set same MNC with 3 digits
         r = self.do_set('mcc-mnc-apply', '2,003')
@@ -482,12 +482,12 @@
         r = self.do_get('mnc')
         self.assertEquals(r['mtype'], 'GET_REPLY')
         self.assertEquals(r['var'], 'mnc')
-        self.assertEquals(r['value'], '3') # FAIL: expecting '003'
+        self.assertEquals(r['value'], '003')
 
         r = self.do_get('mcc')
         self.assertEquals(r['mtype'], 'GET_REPLY')
         self.assertEquals(r['var'], 'mcc')
-        self.assertEquals(r['value'], '2')
+        self.assertEquals(r['value'], '002')
 
 class TestCtrlNAT(TestCtrlBase):
 
diff --git a/tests/gsm0408/gsm0408_test.c b/tests/gsm0408/gsm0408_test.c
index 9f5a5c4..e8d5501 100644
--- a/tests/gsm0408/gsm0408_test.c
+++ b/tests/gsm0408/gsm0408_test.c
@@ -730,7 +730,7 @@
 		.lac = 3,
 		.rac = 4,
 		.expect = {
-			.digits = { 0x00, 0xf1, 0x20 }, /* FAIL: should be { 0x00, 0x21, 0x00 }, */
+			.digits = { 0x00, 0x21, 0x00 },
 			.lac = 0x0300, /* network byte order of 3 */
 			.rac = 4,
 		},
@@ -748,7 +748,7 @@
 		.lac = 0,
 		.rac = 0,
 		.expect = {
-			.digits = { 0x00, 0xf0, 0x00 }, /* FAIL: should be { 0, 0, 0 } */
+			.digits = {},
 		},
 	},
 	{
@@ -776,7 +776,7 @@
 		.lac = 0xabcd,
 		.rac = 0xab,
 		.expect = {
-			.digits = { 0x09, 0xf9, 0x09 }, /* FAIL: should be { 0x09, 0x09, 0x90 }, */
+			.digits = { 0x09, 0x09, 0x90 },
 			.lac = 0xcdab,
 			.rac = 0xab,
 		},
@@ -795,8 +795,7 @@
 		struct gsm48_ra_id result = {};
 		bool ok;
 
-		net.country_code = t->plmn.mcc;
-		net.network_code = t->plmn.mnc;
+		net.plmn = t->plmn;
 		bts.network = &net;
 		bts.location_area_code = t->lac;
 		bts.gprs.rac = t->rac;
diff --git a/tests/gsm0408/gsm0408_test.ok b/tests/gsm0408/gsm0408_test.ok
index 686018b..00f87d5 100644
--- a/tests/gsm0408/gsm0408_test.ok
+++ b/tests/gsm0408/gsm0408_test.ok
@@ -215,10 +215,10 @@
 SI5bis: 06 05 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
 SI5ter: 06 06 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
 test_gsm48_ra_id_by_bts[0]: digits='00f120' lac=0x0300=htons(3) rac=0x04=4 pass
-test_gsm48_ra_id_by_bts[1]: digits='00f120' lac=0x0300=htons(3) rac=0x04=4 pass
+test_gsm48_ra_id_by_bts[1]: digits='002100' lac=0x0300=htons(3) rac=0x04=4 pass
 test_gsm48_ra_id_by_bts[2]: digits='00f000' lac=0x0000=htons(0) rac=0x00=0 pass
-test_gsm48_ra_id_by_bts[3]: digits='00f000' lac=0x0000=htons(0) rac=0x00=0 pass
+test_gsm48_ra_id_by_bts[3]: digits='000000' lac=0x0000=htons(0) rac=0x00=0 pass
 test_gsm48_ra_id_by_bts[4]: digits='999999' lac=0xffff=htons(65535) rac=0xff=255 pass
 test_gsm48_ra_id_by_bts[5]: digits='09f909' lac=0xcdab=htons(43981) rac=0xab=171 pass
-test_gsm48_ra_id_by_bts[6]: digits='09f909' lac=0xcdab=htons(43981) rac=0xab=171 pass
+test_gsm48_ra_id_by_bts[6]: digits='090990' lac=0xcdab=htons(43981) rac=0xab=171 pass
 Done.
diff --git a/tests/nanobts_omlattr/nanobts_omlattr_test.c b/tests/nanobts_omlattr/nanobts_omlattr_test.c
index 0554f43..6fa221c 100644
--- a/tests/nanobts_omlattr/nanobts_omlattr_test.c
+++ b/tests/nanobts_omlattr/nanobts_omlattr_test.c
@@ -218,8 +218,7 @@
 	bts->rach_ldavg_slots = -1;
 	bts->c0->arfcn = 866;
 	bts->cell_identity = 1337;
-	bts->network->country_code = 1;
-	bts->network->network_code = 1;
+	bts->network->plmn = (struct osmo_plmn_id){ .mcc=1, .mnc=1 };
 	bts->location_area_code = 1;
 	bts->gprs.rac = 0;
 	uint8_t attr_bts_expected[] =

-- 
To view, visit https://gerrit.osmocom.org/6668
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I8e722103344186fde118b26d8353db95a4581daa
Gerrit-PatchSet: 6
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Owner: Neels Hofmeyr <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder



More information about the gerrit-log mailing list