[PATCH] openbsc[master]: backport 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
Thu Mar 22 04:34:19 UTC 2018


Hello Jenkins Builder,

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

    https://gerrit.osmocom.org/7417

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

backport support for 3-digit MNC with leading zeros

Backport the patches with the following change-ids:
 osmo-bsc.git:
  I5b097dbb6329f284e3b4914a744d5c3ad628f715
  I8e722103344186fde118b26d8353db95a4581daa
  I78f30aef7aa224b2e9db54c3a844d8f520b3aee0
  I38ac98a4d25159cfd4f686efbfbaf8f00625a6d8
 osmo-iuh.git:
  I29ebcddd45fe3079f8883589a83cc7216a535475

Also apply change of ipac_bcch_info.cgi to struct osmo_cell_global_id in
src/ipaccess/network_listen.c, a change that appears to not have been necessary
in the new split repositories.

Related: OS#3010
Change-Id: Ibf50fd7e1ca5472d0a38fcb87c68227d6de44f42
---
M openbsc/include/openbsc/abis_nm.h
M openbsc/include/openbsc/bsc_msc_data.h
M openbsc/include/openbsc/gsm_data.h
M openbsc/include/openbsc/pcuif_proto.h
M openbsc/src/ipaccess/network_listen.c
M openbsc/src/libbsc/abis_nm.c
M openbsc/src/libbsc/bsc_ctrl_commands.c
M openbsc/src/libbsc/bsc_init.c
M openbsc/src/libbsc/bsc_vty.c
M openbsc/src/libbsc/pcu_sock.c
M openbsc/src/libbsc/system_information.c
M openbsc/src/libcommon-cs/common_cs.c
M openbsc/src/libcommon-cs/common_cs_vty.c
M openbsc/src/libcommon/gsm_data.c
M openbsc/src/libiu/iu.c
M openbsc/src/libmsc/gsm_04_08.c
M openbsc/src/osmo-bsc/osmo_bsc_api.c
M openbsc/src/osmo-bsc/osmo_bsc_ctrl.c
M openbsc/src/osmo-bsc/osmo_bsc_filter.c
M openbsc/src/osmo-bsc/osmo_bsc_msc.c
M openbsc/src/osmo-bsc/osmo_bsc_vty.c
M openbsc/tests/ctrl_test_runner.py
M openbsc/tests/nanobts_omlattr/nanobts_omlattr_test.c
23 files changed, 211 insertions(+), 160 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/openbsc refs/changes/17/7417/2

diff --git a/openbsc/include/openbsc/abis_nm.h b/openbsc/include/openbsc/abis_nm.h
index db2a659..d7ab7d5 100644
--- a/openbsc/include/openbsc/abis_nm.h
+++ b/openbsc/include/openbsc/abis_nm.h
@@ -31,13 +31,6 @@
 /* max number of attributes represented as 3GPP TS 52.021 §9.4.62 SW Description array */
 #define MAX_BTS_ATTR 5
 
-struct cell_global_id {
-	uint16_t mcc;
-	uint16_t mnc;
-	uint16_t lac;
-	uint16_t ci;
-};
-
 /* The BCCH info from an ip.access test, in host byte order
  * and already parsed... */
 struct ipac_bcch_info {
@@ -52,7 +45,7 @@
 	uint16_t frame_offset;
 	uint32_t frame_nr_offset;
 	uint8_t bsic;
-	struct cell_global_id cgi;
+	struct osmo_cell_global_id cgi;
 	uint8_t ba_list_si2[16];
 	uint8_t ba_list_si2bis[16];
 	uint8_t ba_list_si2ter[16];
diff --git a/openbsc/include/openbsc/bsc_msc_data.h b/openbsc/include/openbsc/bsc_msc_data.h
index 9a92955..1b1ffc2 100644
--- a/openbsc/include/openbsc/bsc_msc_data.h
+++ b/openbsc/include/openbsc/bsc_msc_data.h
@@ -31,6 +31,7 @@
 
 #include <osmocom/core/timer.h>
 #include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/gsm23003.h>
 
 #include <regex.h>
 
@@ -74,8 +75,7 @@
 	struct osmo_timer_list pong_timer;
 	int advanced_ping;
 	struct bsc_msc_connection *msc_con;
-	int core_mnc;
-	int core_mcc;
+	struct osmo_plmn_id core_plmn;
 	int core_lac;
 	int core_ci;
 	int rtp_base;
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index b823acc..2e1e64f 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -11,6 +11,7 @@
 #include <osmocom/core/select.h>
 #include <osmocom/core/stats.h>
 #include <osmocom/core/stat_item.h>
+#include <osmocom/gsm/gsm23003.h>
 
 #include <osmocom/crypt/auth.h>
 
@@ -317,9 +318,8 @@
 };
 
 struct gsm_network {
-	/* global parameters */
-	uint16_t country_code;
-	uint16_t network_code;
+	struct osmo_plmn_id plmn;
+
 	char *name_long;
 	char *name_short;
 	enum gsm_auth_policy auth_policy;
@@ -428,6 +428,16 @@
 	 * pointer is NULL to indicate absence of a bsc_subscribers list. */
 	struct llist_head *bsc_subscribers;
 };
+
+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;
+}
 
 struct osmo_esme;
 
@@ -568,7 +578,7 @@
 const char *bts_gprs_mode_name(enum bts_gprs_mode mode);
 int bts_gprs_mode_is_compat(struct gsm_bts *bts, enum bts_gprs_mode mode);
 
-int gsm48_ra_id_by_bts(uint8_t *buf, struct gsm_bts *bts);
+void gsm48_ra_id_by_bts(struct gsm48_ra_id *buf, struct gsm_bts *bts);
 void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts);
 struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan);
 
diff --git a/openbsc/include/openbsc/pcuif_proto.h b/openbsc/include/openbsc/pcuif_proto.h
index eb28d66..2e3f782 100644
--- a/openbsc/include/openbsc/pcuif_proto.h
+++ b/openbsc/include/openbsc/pcuif_proto.h
@@ -1,7 +1,7 @@
 #ifndef _PCUIF_PROTO_H
 #define _PCUIF_PROTO_H
 
-#define PCU_IF_VERSION		0x08
+#define PCU_IF_VERSION		0x09
 
 /* msg_type */
 #define PCU_IF_MSG_DATA_REQ	0x00	/* send data to given channel */
@@ -106,7 +106,9 @@
 	struct gsm_pcu_if_info_trx trx[8];	/* TRX infos per BTS */
 	uint8_t		bsic;
 	/* RAI */
-	uint16_t	mcc, mnc, lac, rac;
+	uint16_t	mcc, mnc;
+	uint8_t		mnc_3_digits;
+	uint16_t	lac, rac;
 	/* NSE */
 	uint16_t	nsei;
 	uint8_t		nse_timer[7];
diff --git a/openbsc/src/ipaccess/network_listen.c b/openbsc/src/ipaccess/network_listen.c
index 3b44ceb..43d82a9 100644
--- a/openbsc/src/ipaccess/network_listen.c
+++ b/openbsc/src/ipaccess/network_listen.c
@@ -185,10 +185,10 @@
 			DEBUGP(DNM, "BCCH Info parsing failed\n");
 			break;
 		}
-		DEBUGP(DNM, "==> ARFCN %u, RxLev %2u, RxQual %2u: %3d-%d, LAC %d CI %d BSIC %u\n",
+		DEBUGP(DNM, "==> ARFCN %u, RxLev %2u, RxQual %2u: %s, LAC %d CI %d BSIC %u\n",
 			binfo.arfcn, binfo.rx_lev, binfo.rx_qual,
-			binfo.cgi.mcc, binfo.cgi.mnc,
-			binfo.cgi.lac, binfo.cgi.ci, binfo.bsic);
+			osmo_plmn_name(&binfo.cgi.lai.plmn),
+			binfo.cgi.lai.lac, binfo.cgi.cell_identity, binfo.bsic);
 
 		if (binfo.arfcn != last_arfcn) {
 			/* report is on a new arfcn, need to clear channel list */
diff --git a/openbsc/src/libbsc/abis_nm.c b/openbsc/src/libbsc/abis_nm.c
index f24f6bf..8eadfa8 100644
--- a/openbsc/src/libbsc/abis_nm.c
+++ b/openbsc/src/libbsc/abis_nm.c
@@ -2785,10 +2785,12 @@
 
 void abis_nm_ipaccess_cgi(uint8_t *buf, struct gsm_bts *bts)
 {
-	/* we simply reuse the GSM48 function and overwrite the RAC
-	 * with the Cell ID */
-	gsm48_ra_id_by_bts(buf, bts);
-	*((uint16_t *)(buf + 5)) = htons(bts->cell_identity);
+	struct gsm48_ra_id *_buf = (struct gsm48_ra_id*)buf;
+	uint16_t ci = htons(bts->cell_identity);
+	/* we simply reuse the GSM48 function and write the Cell ID over the position where the RAC
+	 * starts */
+	gsm48_ra_id_by_bts(_buf, bts);
+	memcpy(&_buf->rac, &ci, sizeof(ci));
 }
 
 void gsm_trx_lock_rf(struct gsm_bts_trx *trx, bool locked, const char *reason)
@@ -2822,23 +2824,11 @@
 	return get_value_string(ipacc_testres_names, res);
 }
 
-void ipac_parse_cgi(struct cell_global_id *cid, const uint8_t *buf)
+void ipac_parse_cgi(struct osmo_cell_global_id *cid, const uint8_t *buf)
 {
-	cid->mcc = (buf[0] & 0xf) * 100;
-	cid->mcc += (buf[0] >> 4) *  10;
-	cid->mcc += (buf[1] & 0xf) *  1;
-
-	if (buf[1] >> 4 == 0xf) {
-		cid->mnc = (buf[2] & 0xf) * 10;
-		cid->mnc += (buf[2] >> 4) *  1;
-	} else {
-		cid->mnc = (buf[2] & 0xf) * 100;
-		cid->mnc += (buf[2] >> 4) *  10;
-		cid->mnc += (buf[1] >> 4) *   1;
-	}
-
-	cid->lac = ntohs(*((uint16_t *)&buf[3]));
-	cid->ci = ntohs(*((uint16_t *)&buf[5]));
+	osmo_plmn_from_bcd(buf, &cid->lai.plmn);
+	cid->lai.lac = ntohs(*((uint16_t *)&buf[3]));
+	cid->cell_identity = ntohs(*((uint16_t *)&buf[5]));
 }
 
 /* parse BCCH information IEI from wire format to struct ipac_bcch_info */
diff --git a/openbsc/src/libbsc/bsc_ctrl_commands.c b/openbsc/src/libbsc/bsc_ctrl_commands.c
index 641fe2b..8b8685a 100644
--- a/openbsc/src/libbsc/bsc_ctrl_commands.c
+++ b/openbsc/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 <openbsc/ipaccess.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/abis_nm.h>
@@ -65,8 +66,62 @@
 	return 0;
 }
 
-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;
+       if (osmo_mcc_from_str(cmd->value, &mcc))
+               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)
+{
+       if (osmo_mcc_from_str(value, 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;
+}
+
 CTRL_CMD_VTY_STRING(net_short_name, "short-name", struct gsm_network, name_short);
 CTRL_CMD_VTY_STRING(net_long_name, "long-name", struct gsm_network, name_long);
 
@@ -101,6 +156,7 @@
 static int verify_net_mcc_mnc_apply(struct ctrl_cmd *cmd, const char *value, void *d)
 {
 	char *tmp, *saveptr, *mcc, *mnc;
+	int rc = 0;
 
 	tmp = talloc_strdup(cmd, value);
 	if (!tmp)
@@ -108,39 +164,45 @@
 
 	mcc = strtok_r(tmp, ",", &saveptr);
 	mnc = strtok_r(NULL, ",", &saveptr);
-	talloc_free(tmp);
 
-	if (!mcc || !mnc)
-		return 1;
-	return 0;
+	if (osmo_mcc_from_str(mcc, NULL) || osmo_mnc_from_str(mnc, NULL, NULL))
+		rc = -1;
+
+	talloc_free(tmp);
+	return rc;
 }
 
 static int set_net_mcc_mnc_apply(struct ctrl_cmd *cmd, void *data)
 {
 	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);
+	if (osmo_mcc_from_str(mcc_str, &plmn.mcc)) {
+		cmd->reply = "Error while decoding MCC";
+		return CTRL_CMD_ERROR;
+	}
+
+	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/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c
index 0f732d7..9389c43 100644
--- a/openbsc/src/libbsc/bsc_init.c
+++ b/openbsc/src/libbsc/bsc_init.c
@@ -305,9 +305,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/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c
index 5340e11..f78247b 100644
--- a/openbsc/src/libbsc/bsc_vty.c
+++ b/openbsc/src/libbsc/bsc_vty.c
@@ -164,9 +164,8 @@
 {
 	struct pchan_load pl;
 
-	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, "  Long network name: '%s'%s",
 		net->name_long, VTY_NEWLINE);
 	vty_out(vty, "  Short network name: '%s'%s",
@@ -840,8 +839,9 @@
 	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
 
 	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, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
 	vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
 	vty_out(vty, " auth policy %s%s", gsm_auth_policy_name(gsmnet->auth_policy), VTY_NEWLINE);
diff --git a/openbsc/src/libbsc/pcu_sock.c b/openbsc/src/libbsc/pcu_sock.c
index 98e12fa..e2066ba 100644
--- a/openbsc/src/libbsc/pcu_sock.c
+++ b/openbsc/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;
+	info_ind->mnc_3_digits = bts->network->plmn.mnc_3_digits;
 	info_ind->lac = bts->location_area_code;
 	info_ind->rac = bts->gprs.rac;
 
diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c
index 5792145..a6226a4 100644
--- a/openbsc/src/libbsc/system_information.c
+++ b/openbsc/src/libbsc/system_information.c
@@ -841,9 +841,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;
@@ -895,9 +893,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))
@@ -1069,9 +1065,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/openbsc/src/libcommon-cs/common_cs.c b/openbsc/src/libcommon-cs/common_cs.c
index d299427..d8d5ec7 100644
--- a/openbsc/src/libcommon-cs/common_cs.c
+++ b/openbsc/src/libcommon-cs/common_cs.c
@@ -63,8 +63,10 @@
 	net->auto_create_subscr = true;
 	net->auto_assign_exten = true;
 
-	net->country_code = country_code;
-	net->network_code = network_code;
+	net->plmn = (struct osmo_plmn_id){
+		.mcc = country_code,
+		.mnc = network_code,
+	};
 
 	INIT_LLIST_HEAD(&net->trans_list);
 	INIT_LLIST_HEAD(&net->upqueue);
diff --git a/openbsc/src/libcommon-cs/common_cs_vty.c b/openbsc/src/libcommon-cs/common_cs_vty.c
index f7b4886..c323b11 100644
--- a/openbsc/src/libcommon-cs/common_cs_vty.c
+++ b/openbsc/src/libcommon-cs/common_cs_vty.c
@@ -60,8 +60,14 @@
       "Network Country Code to use\n")
 {
 	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+	uint16_t mcc;
 
-	gsmnet->country_code = atoi(argv[0]);
+	if (osmo_mcc_from_str(argv[0], &mcc)) {
+		vty_out(vty, "%% Error decoding MCC: %s%s", argv[0], VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	gsmnet->plmn.mcc = mcc;
 
 	return CMD_SUCCESS;
 }
@@ -75,8 +81,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/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c
index 2028f05..b45a4d3 100644
--- a/openbsc/src/libcommon/gsm_data.c
+++ b/openbsc/src/libcommon/gsm_data.c
@@ -339,20 +339,20 @@
 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,
 	};
 }
 
-int gsm48_ra_id_by_bts(uint8_t *buf, struct gsm_bts *bts)
+void gsm48_ra_id_by_bts(struct gsm48_ra_id *buf, struct gsm_bts *bts)
 {
 	struct gprs_ra_id raid;
 
 	gprs_ra_id_by_bts(&raid, bts);
-
-	return gsm48_construct_ra(buf, &raid);
+	gsm48_encode_ra(buf, &raid);
 }
 
 int gsm_parse_reg(void *ctx, regex_t *reg, char **str, int argc, const char **argv)
diff --git a/openbsc/src/libiu/iu.c b/openbsc/src/libiu/iu.c
index 8ba6fa4..b4e7ac8 100644
--- a/openbsc/src/libiu/iu.c
+++ b/openbsc/src/libiu/iu.c
@@ -57,8 +57,7 @@
  * PLMN identity is a BCD representation of the MCC and MNC.
  * See iu_grnc_id_parse(). */
 struct iu_grnc_id {
-	uint16_t mcc;
-	uint16_t mnc;
+	struct osmo_plmn_id plmn;
 	uint16_t rnc_id;
 };
 
@@ -265,8 +264,7 @@
 		     " should be 3, is %d\n", src->pLMNidentity.size);
 		return -1;
 	}
-	gsm48_mcc_mnc_from_bcd(&src->pLMNidentity.buf[0],
-			       &dst->mcc, &dst->mnc);
+	osmo_plmn_from_bcd(&src->pLMNidentity.buf[0], &dst->plmn);
 	dst->rnc_id = (uint16_t)src->rNC_ID;
 	return 0;
 }
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index 9d19025..006de7f 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -82,12 +82,6 @@
 static void schedule_reject(struct gsm_subscriber_connection *conn);
 static void release_anchor(struct gsm_subscriber_connection *conn);
 
-struct gsm_lai {
-	uint16_t mcc;
-	uint16_t mnc;
-	uint16_t lac;
-};
-
 static int apply_codec_restrictions(struct gsm_bts *bts,
 	struct gsm_mncc_bearer_cap *bcap)
 {
@@ -512,9 +506,7 @@
 	gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
 
 	lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
-	gsm48_generate_lai(lai, conn->network->country_code,
-			   conn->network->network_code,
-			   conn->bts->location_area_code);
+	gsm48_generate_lai2(lai, bts_lai(conn->bts));
 
 	if (conn->subscr->tmsi == GSM_RESERVED_TMSI) {
 		uint8_t mi[10];
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_api.c b/openbsc/src/osmo-bsc/osmo_bsc_api.c
index bac5e47..25d48c3 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_api.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_api.c
@@ -51,32 +51,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_plmn.mcc != GSM_MCC_MNC_INVALID)
+		cgi.lai.plmn.mcc = msc->core_plmn.mcc;
+	if (msc->core_plmn.mnc != GSM_MCC_MNC_INVALID) {
+		cgi.lai.plmn.mnc = msc->core_plmn.mnc;
+		cgi.lai.plmn.mnc_3_digits = msc->core_plmn.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)
@@ -239,10 +227,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;
 
@@ -281,14 +265,9 @@
 
 	/* check return value, if failed check msg for and send USSD */
 
-	network_code = get_network_code_for_msc(conn->sccp_con->msc);
-	country_code = get_country_code_for_msc(conn->sccp_con->msc);
-	lac = get_lac_for_msc(conn->sccp_con->msc, conn->bts);
-	ci = get_ci_for_msc(conn->sccp_con->msc, conn->bts);
-
 	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_con->msc, conn->bts), NULL);
 	if (!resp) {
 		LOGP(DMSC, LOGL_DEBUG, "Failed to create layer3 message.\n");
 		sccp_connection_free(conn->sccp_con->sccp);
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c b/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c
index 423ed34..54f2e0d 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c
@@ -186,10 +186,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/openbsc/src/osmo-bsc/osmo_bsc_filter.c b/openbsc/src/osmo-bsc/osmo_bsc_filter.c
index 2c84b16..0c4b3e3 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_filter.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_filter.c
@@ -33,20 +33,16 @@
 	struct gsm48_hdr *gh;
 	struct gsm48_loc_upd_req *lu;
 	struct gsm48_loc_area_id lai;
-	struct gsm_network *net;
 
 	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 = conn->bts->network;
-
 	gh = msgb_l3(msg);
 	lu = (struct gsm48_loc_upd_req *) gh->data;
 
-	gsm48_generate_lai(&lai, net->country_code, net->network_code,
-			   conn->bts->location_area_code);
+	gsm48_generate_lai2(&lai, bts_lai(conn->bts));
 
 	if (memcmp(&lai, &lu->lai, sizeof(lai)) != 0) {
 		LOGP(DMSC, LOGL_DEBUG, "Marking con for welcome USSD.\n");
@@ -319,9 +315,9 @@
 
 static int has_core_identity(struct bsc_msc_data *msc)
 {
-	if (msc->core_mnc != -1)
+	if (msc->core_plmn.mnc != GSM_MCC_MNC_INVALID)
 		return 1;
-	if (msc->core_mcc != -1)
+	if (msc->core_plmn.mcc != GSM_MCC_MNC_INVALID)
 		return 1;
 	if (msc->core_lac != -1)
 		return 1;
@@ -336,7 +332,6 @@
 int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
 {
 	struct bsc_msc_data *msc;
-	struct gsm_network *net;
 	struct gsm48_loc_area_id *lai;
 	struct gsm48_hdr *gh;
 	uint8_t pdisc;
@@ -356,7 +351,6 @@
 		return 0;
 
 	mtype = gsm48_hdr_msg_type(gh);
-	net = conn->bts->network;
 	msc = conn->sccp_con->msc;
 
 	if (mtype == GSM48_MT_MM_LOC_UPD_ACCEPT) {
@@ -364,9 +358,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,
-						   conn->bts->location_area_code);
+				gsm48_generate_lai2(lai, bts_lai(conn->bts));
 			}
 		}
 
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_msc.c b/openbsc/src/osmo-bsc/osmo_bsc_msc.c
index 8d02624..b2f8806 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_msc.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_msc.c
@@ -570,8 +570,10 @@
 	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_plmn = (struct osmo_plmn_id){
+		.mcc = GSM_MCC_MNC_INVALID,
+		.mnc = GSM_MCC_MNC_INVALID,
+	};
 	msc_data->core_ci = -1;
 	msc_data->core_lac = -1;
 	msc_data->rtp_base = 4000;
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_vty.c b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
index 7bb123d..e124b31 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_vty.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
@@ -27,6 +27,7 @@
 #include <openbsc/bsc_msg_filter.h>
 
 #include <osmocom/core/talloc.h>
+#include <osmocom/gsm/gsm48.h>
 #include <osmocom/vty/logging.h>
 
 #include <time.h>
@@ -110,12 +111,12 @@
 	if (msc->bsc_key_present)
 		vty_out(vty, " auth-key %s%s",
 			osmo_hexdump(msc->bsc_key, sizeof(msc->bsc_key)), 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_plmn.mnc != GSM_MCC_MNC_INVALID)
+		vty_out(vty, " core-mobile-network-code %s%s",
+			osmo_mnc_name(msc->core_plmn.mnc, msc->core_plmn.mnc_3_digits), VTY_NEWLINE);
+	if (msc->core_plmn.mcc != GSM_MCC_MNC_INVALID)
+		vty_out(vty, " core-mobile-country-code %s%s",
+			osmo_mcc_name(msc->core_plmn.mcc), VTY_NEWLINE);
 	if (msc->core_lac != -1)
 		vty_out(vty, " core-location-area-code %d%s",
 			msc->core_lac, VTY_NEWLINE);
@@ -264,7 +265,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_plmn.mnc = mnc;
+	data->core_plmn.mnc_3_digits = mnc_3_digits;
 	return CMD_SUCCESS;
 }
 
@@ -273,8 +282,13 @@
       "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]);
+	if (osmo_mcc_from_str(argv[0], &mcc)) {
+		vty_out(vty, "%% Error decoding MCC: %s%s", argv[0], VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	data->core_plmn.mcc = mcc;
 	return CMD_SUCCESS;
 }
 
diff --git a/openbsc/tests/ctrl_test_runner.py b/openbsc/tests/ctrl_test_runner.py
index b63dd27..cf83fad 100644
--- a/openbsc/tests/ctrl_test_runner.py
+++ b/openbsc/tests/ctrl_test_runner.py
@@ -375,27 +375,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'], '009')
 
     def testMccMncApply(self):
         # Test some invalid input
@@ -432,7 +437,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')
@@ -448,7 +453,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')
diff --git a/openbsc/tests/nanobts_omlattr/nanobts_omlattr_test.c b/openbsc/tests/nanobts_omlattr/nanobts_omlattr_test.c
index ec3eb2c..e34b19b 100644
--- a/openbsc/tests/nanobts_omlattr/nanobts_omlattr_test.c
+++ b/openbsc/tests/nanobts_omlattr/nanobts_omlattr_test.c
@@ -210,8 +210,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/7417
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: Ibf50fd7e1ca5472d0a38fcb87c68227d6de44f42
Gerrit-PatchSet: 2
Gerrit-Project: openbsc
Gerrit-Branch: master
Gerrit-Owner: Neels Hofmeyr <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder



More information about the gerrit-log mailing list