Change in osmo-msc[master]: Add support for LCLS to the MSC

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/.

laforge gerrit-no-reply at lists.osmocom.org
Mon Oct 25 10:07:48 UTC 2021


laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-msc/+/24236 )

Change subject: Add support for LCLS to the MSC
......................................................................

Add support for LCLS to the MSC

This commit is largely based on work by
Max <msuraev at sysmocom.de>

Adds LCLS parameters for A-interface transactions
This commit also adds a vty option to facilitate globally
disabling LCLS for all calls on this MSC.

Add a global call reference (GCR) to MNCC and therefore
bump the MNCC version to version 8. (This commit has to be
merged at the same time as the corresponing commit in the
osmo-sip-connector for mncc-external use.)

Depends: osmo-sip-connector Id40d7e0fed9356f801b3627c118150055e7232b1
Change-Id: I705c860e51637b4537cad65a330ecbaaca96dd5b
---
M include/osmocom/msc/debug.h
M include/osmocom/msc/gsm_data.h
M include/osmocom/msc/mncc.h
M include/osmocom/msc/ran_msg.h
M include/osmocom/msc/transaction.h
M src/libmsc/gsm_04_08_cc.c
M src/libmsc/msc_a.c
M src/libmsc/msc_vty.c
M src/libmsc/ran_msg_a.c
M src/libmsc/transaction.c
M src/osmo-msc/msc_main.c
M tests/mncc/mncc_test.ok
M tests/test_nodes.vty
13 files changed, 134 insertions(+), 12 deletions(-)

Approvals:
  fixeria: Looks good to me, but someone else must approve
  keith: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/include/osmocom/msc/debug.h b/include/osmocom/msc/debug.h
index 3347e20..0d08ceb 100644
--- a/include/osmocom/msc/debug.h
+++ b/include/osmocom/msc/debug.h
@@ -8,6 +8,7 @@
 	DCC,
 	DMM,
 	DRR,
+	DLCLS,
 	DMNCC,
 	DPAG,
 	DMSC,
diff --git a/include/osmocom/msc/gsm_data.h b/include/osmocom/msc/gsm_data.h
index 170d884..72e33a6 100644
--- a/include/osmocom/msc/gsm_data.h
+++ b/include/osmocom/msc/gsm_data.h
@@ -260,6 +260,10 @@
 
 	/* Whether to use call waiting on the network */
 	bool call_waiting;
+
+	/* Whether to use lcls on the network */
+	bool lcls_permitted;
+
 	char *sms_db_file_path;
 };
 
diff --git a/include/osmocom/msc/mncc.h b/include/osmocom/msc/mncc.h
index 1c8aff0..5002227 100644
--- a/include/osmocom/msc/mncc.h
+++ b/include/osmocom/msc/mncc.h
@@ -26,6 +26,7 @@
 
 #include <osmocom/core/linuxlist.h>
 #include <osmocom/gsm/mncc.h>
+#include <osmocom/gsm/gsm29205.h>
 
 #include <stdint.h>
 #include <netinet/in.h>
@@ -160,7 +161,7 @@
 
 	unsigned char	lchan_type;
 	unsigned char	lchan_mode;
-
+	struct osmo_gcr_parsed gcr;
 	/* A buffer to contain SDP ('\0' terminated) */
 	char		sdp[1024];
 };
@@ -171,7 +172,7 @@
 	unsigned char	data[0];
 };
 
-#define MNCC_SOCK_VERSION	7
+#define MNCC_SOCK_VERSION	8
 struct gsm_mncc_hello {
 	uint32_t	msg_type;
 	uint32_t	version;
diff --git a/include/osmocom/msc/ran_msg.h b/include/osmocom/msc/ran_msg.h
index 1303ba3..fd2439f 100644
--- a/include/osmocom/msc/ran_msg.h
+++ b/include/osmocom/msc/ran_msg.h
@@ -88,6 +88,7 @@
 	uint8_t osmux_cid;
 	bool call_id_present;
 	uint32_t call_id;
+	struct osmo_lcls *lcls;
 };
 
 struct ran_cipher_mode_command {
diff --git a/include/osmocom/msc/transaction.h b/include/osmocom/msc/transaction.h
index 928b137..14b89bb 100644
--- a/include/osmocom/msc/transaction.h
+++ b/include/osmocom/msc/transaction.h
@@ -100,6 +100,7 @@
 			struct osmo_timer_list timer_guard;
 			struct gsm_mncc msg;	/* stores setup/disconnect/release message */
 			bool mncc_initiated;	/* Whether an MNCC Release is necessary on failure */
+			struct osmo_lcls *lcls;
 		} cc;
 		struct {
 			struct gsm411_smc_inst smc_inst;
@@ -145,6 +146,8 @@
 					 const struct vlr_subscr *vsub,
 					 uint8_t sm_rp_mr);
 
+struct osmo_lcls *trans_lcls_compose(const struct gsm_trans *trans, bool use_lac);
+
 struct gsm_trans *trans_alloc(struct gsm_network *net,
 			      struct vlr_subscr *vsub,
 			      enum trans_type type, uint8_t trans_id,
diff --git a/src/libmsc/gsm_04_08_cc.c b/src/libmsc/gsm_04_08_cc.c
index a8b4665..d6a2864 100644
--- a/src/libmsc/gsm_04_08_cc.c
+++ b/src/libmsc/gsm_04_08_cc.c
@@ -318,6 +318,16 @@
 		msc_a_get(msc_a, MSC_A_USE_CC);
 		trans->msc_a = msc_a;
 		trans->paging_request = NULL;
+
+		/* Get the GCR from the MO call leg (if any). */
+		if (!trans->cc.lcls) {
+			trans->cc.lcls = trans_lcls_compose(trans, true);
+			if (trans->cc.lcls) {
+				trans->cc.lcls->gcr = trans->cc.msg.gcr;
+				trans->cc.lcls->gcr_available = true;
+			}
+		}
+
 		osmo_fsm_inst_dispatch(msc_a->c.fi, MSC_A_EV_TRANSACTION_ACCEPTED, trans);
 		/* send SETUP request to called party */
 		gsm48_cc_tx_setup(trans, &trans->cc.msg);
@@ -502,6 +512,14 @@
 	memset(&setup, 0, sizeof(struct gsm_mncc));
 	setup.callref = trans->callref;
 
+	/* New Global Call Reference */
+	if (!trans->cc.lcls)
+		trans->cc.lcls = trans_lcls_compose(trans, true);
+
+	/* Pass the LCLS GCR on to the MT call leg via MNCC */
+	if (trans->cc.lcls)
+		setup.gcr = trans->cc.lcls->gcr;
+
 	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
 	/* emergency setup is identified by msg_type */
 	if (msg_type == GSM48_MT_CC_EMERG_SETUP) {
diff --git a/src/libmsc/msc_a.c b/src/libmsc/msc_a.c
index fa8e842..9b6b602 100644
--- a/src/libmsc/msc_a.c
+++ b/src/libmsc/msc_a.c
@@ -569,6 +569,7 @@
 			.osmux_cid = msc_a->cc.call_leg->rtp[RTP_TO_RAN]->local_osmux_cid,
 			.call_id_present = true,
 			.call_id = cc_trans->callref,
+			.lcls = cc_trans->cc.lcls,
 		},
 	};
 	if (msc_a_ran_down(msc_a, MSC_ROLE_I, &msg)) {
@@ -1506,6 +1507,13 @@
 		rc = msc_a_up_ho(msc_a, d, MSC_HO_EV_RX_FAILURE);
 		break;
 
+	case RAN_MSG_LCLS_STATUS:
+		/* The BSS sends us LCLS_STATUS. We do nothing for now, but it is not an error. */
+		LOG_MSC_A(msc_a, LOGL_DEBUG, "LCLS_STATUS (%s) received from MSC-I\n",
+			  gsm0808_lcls_status_name(msg->lcls_status.status));
+		rc = 0;
+		break;
+
 	default:
 		LOG_MSC_A(msc_a, LOGL_ERROR, "Message from MSC-I not implemented: %s\n", ran_msg_type_name(msg->msg_type));
 		rc = -ENOTSUP;
diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c
index 2a4dbbb..e4e0937 100644
--- a/src/libmsc/msc_vty.c
+++ b/src/libmsc/msc_vty.c
@@ -499,6 +499,24 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN_ATTR(cfg_msc_lcls_disable, cfg_msc_lcls_disable_cmd,
+	    "lcls-permitted",
+	    "Globally allow LCLS (Local Call Local Switch) for all calls on this MSC.\n",
+	    CMD_ATTR_IMMEDIATE)
+{
+	gsmnet->lcls_permitted = true;
+	return CMD_SUCCESS;
+}
+
+DEFUN_ATTR(cfg_msc_no_lcls_disable, cfg_msc_no_lcls_disable_cmd,
+	    "no lcls-permitted",
+	    NO_STR "Globally disable LCLS (Local Call Local Switch) for all calls on this MSC.\n",
+	    CMD_ATTR_IMMEDIATE)
+{
+	gsmnet->lcls_permitted = false;
+	return CMD_SUCCESS;
+}
+
 DEFUN(cfg_msc_cs7_instance_a,
       cfg_msc_cs7_instance_a_cmd,
       "cs7-instance-a <0-15>",
@@ -764,6 +782,8 @@
 		gsmnet->ncss_guard_timeout, VTY_NEWLINE);
 	vty_out(vty, " %sassign-tmsi%s",
 		gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
+	if (gsmnet->lcls_permitted)
+		vty_out(vty, " lcls-permitted%s", VTY_NEWLINE);
 
 	vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
 		VTY_NEWLINE);
@@ -2083,6 +2103,8 @@
 	install_node(&msc_node, config_write_msc);
 	install_element(MSC_NODE, &cfg_sms_database_cmd);
 	install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
+	install_element(MSC_NODE, &cfg_msc_lcls_disable_cmd);
+	install_element(MSC_NODE, &cfg_msc_no_lcls_disable_cmd);
 	install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
 	install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
 	install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
diff --git a/src/libmsc/ran_msg_a.c b/src/libmsc/ran_msg_a.c
index 273f8dd..b50259d 100644
--- a/src/libmsc/ran_msg_a.c
+++ b/src/libmsc/ran_msg_a.c
@@ -1004,7 +1004,8 @@
 	if(ac->call_id_present == true)
 		call_id = &ac->call_id;
 
-	msg = gsm0808_create_ass(ac->channel_type, NULL, use_rtp_addr, use_scl, call_id);
+	msg = gsm0808_create_ass2(ac->channel_type, NULL, use_rtp_addr, use_scl, call_id,
+				  NULL, ac->lcls);
 	if (ac->osmux_present)
 		_gsm0808_assignment_extend_osmux(msg, ac->osmux_cid);
 	return msg;
diff --git a/src/libmsc/transaction.c b/src/libmsc/transaction.c
index 94712cc..2108ab4 100644
--- a/src/libmsc/transaction.c
+++ b/src/libmsc/transaction.c
@@ -110,6 +110,66 @@
 	return NULL;
 }
 
+struct osmo_lcls *trans_lcls_compose(const struct gsm_trans *trans, bool use_lac)
+{
+	if (!trans->net->a.sri->sccp)
+		return NULL;
+
+	struct osmo_ss7_instance *ss7 = osmo_sccp_get_ss7(trans->net->a.sri->sccp);
+	struct osmo_lcls *lcls;
+	uint8_t w = osmo_ss7_pc_width(&ss7->cfg.pc_fmt);
+
+	if (!trans) {
+		LOGP(DCC, LOGL_ERROR, "LCLS: unable to fill parameters for unallocated transaction\n");
+		return NULL;
+	}
+
+	if (!trans->net->lcls_permitted) {
+		LOGP(DCC, LOGL_NOTICE, "LCLS disabled globally\n");
+		return NULL;
+	}
+
+	if (!trans->msc_a) {
+		LOGP(DCC, LOGL_ERROR, "LCLS: unable to fill parameters for transaction without connection\n");
+		return NULL;
+	}
+
+	if (trans->msc_a->c.ran->type != OSMO_RAT_GERAN_A) {
+		LOGP(DCC, LOGL_ERROR, "LCLS: only A interface is supported at the moment\n");
+		return NULL;
+	}
+
+	lcls = talloc_zero(trans, struct osmo_lcls);
+	if (!lcls) {
+		LOGP(DCC, LOGL_ERROR, "LCLS: failed to allocate osmo_lcls\n");
+		return NULL;
+	}
+
+	LOGP(DCC, LOGL_INFO, "LCLS: using %u bits (%u bytes) for node ID\n", w, w / 8);
+
+	lcls->gcr.net_len = 3;
+	lcls->gcr.node = ss7->cfg.primary_pc;
+
+	/* net id from Q.1902.3 3-5 bytes, this function gives 3 bytes exactly */
+	osmo_plmn_to_bcd(lcls->gcr.net, &trans->net->plmn);
+
+	osmo_store32be(trans->callref, lcls->gcr.cr);
+	osmo_store16be(use_lac ? trans->msc_a->via_cell.lai.lac : trans->msc_a->via_cell.cell_identity, lcls->gcr.cr + 3);
+
+	LOGP(DCC, LOGL_INFO, "LCLS: allocated %s-based CR-ID %s\n", use_lac ? "LAC" : "CI",
+	     osmo_hexdump(lcls->gcr.cr, 5));
+
+	lcls->config = GSM0808_LCLS_CFG_BOTH_WAY;
+	lcls->control = GSM0808_LCLS_CSC_CONNECT;
+	lcls->corr_needed = true;
+	lcls->gcr_available = true;
+
+	LOGP(DCC, LOGL_DEBUG, "Filled %s\n", osmo_lcls_dump(lcls));
+	LOGP(DCC, LOGL_DEBUG, "Filled %s\n", osmo_gcr_dump(lcls));
+
+	return lcls;
+}
+
 static const char *trans_vsub_use(enum trans_type type)
 {
 	return get_value_string_or_null(trans_type_names, type) ? : "trans-type-unknown";
diff --git a/src/osmo-msc/msc_main.c b/src/osmo-msc/msc_main.c
index a0f584d..cd91d54 100644
--- a/src/osmo-msc/msc_main.c
+++ b/src/osmo-msc/msc_main.c
@@ -258,6 +258,7 @@
 
 	mgcp_client_conf_init(&net->mgw.conf);
 	net->call_waiting = true;
+	net->lcls_permitted = false;
 
 	net->mgw.tdefs = g_mgw_tdefs;
 	osmo_tdefs_reset(net->mgw.tdefs);
diff --git a/tests/mncc/mncc_test.ok b/tests/mncc/mncc_test.ok
index 9334706..7cb1201 100644
--- a/tests/mncc/mncc_test.ok
+++ b/tests/mncc/mncc_test.ok
@@ -1,15 +1,15 @@
 test_sdp_termination()
 
 struct gsm_mncc:
-empty SDP: len=1860 sdplen=1026 sdp="\0" rc=0
-empty SDP, shortest possible: len=835 sdplen=1 sdp="\0" rc=0
-empty SDP, zero len: len=834 sdplen=0 sdp=- rc=-22
-terminated SDP str: len=1860 sdplen=1026 sdp="Privacy is a desirable marketing option\0" rc=0
-terminated SDP str, shortest possible: len=874 sdplen=40 sdp="Privacy is a desirable marketing option\0" rc=0
-terminated SDP str, but len excludes nul: len=873 sdplen=39 sdp="Privacy is a desirable marketing option" rc=-22
-terminated SDP str, but len too short: len=857 sdplen=23 sdp="Privacy is a desirable " rc=-22
-len way too short: len=10 sdplen=-824 sdp=- rc=-22
-len zero: len=0 sdplen=-834 sdp=- rc=-22
+empty SDP: len=1872 sdplen=1024 sdp="\0" rc=0
+empty SDP, shortest possible: len=849 sdplen=1 sdp="\0" rc=0
+empty SDP, zero len: len=848 sdplen=0 sdp=- rc=-22
+terminated SDP str: len=1872 sdplen=1024 sdp="Privacy is a desirable marketing option\0" rc=0
+terminated SDP str, shortest possible: len=888 sdplen=40 sdp="Privacy is a desirable marketing option\0" rc=0
+terminated SDP str, but len excludes nul: len=887 sdplen=39 sdp="Privacy is a desirable marketing option" rc=-22
+terminated SDP str, but len too short: len=871 sdplen=23 sdp="Privacy is a desirable " rc=-22
+len way too short: len=10 sdplen=-838 sdp=- rc=-22
+len zero: len=0 sdplen=-848 sdp=- rc=-22
 
 struct gsm_mncc_rtp:
 empty SDP: len=1168 sdplen=1024 sdp="\0" rc=0
diff --git a/tests/test_nodes.vty b/tests/test_nodes.vty
index 268681a..315264f 100644
--- a/tests/test_nodes.vty
+++ b/tests/test_nodes.vty
@@ -48,6 +48,8 @@
 ...
   sms-database PATH
   assign-tmsi
+  lcls-permitted
+  no lcls-permitted
   mncc internal
   mncc external MNCC_SOCKET_PATH
   mncc guard-timeout <0-255>

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-msc/+/24236
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Change-Id: I705c860e51637b4537cad65a330ecbaaca96dd5b
Gerrit-Change-Number: 24236
Gerrit-PatchSet: 11
Gerrit-Owner: keith <keith at rhizomatica.org>
Gerrit-Assignee: neels <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <pmaier at sysmocom.de>
Gerrit-Reviewer: fixeria <vyanitskiy at sysmocom.de>
Gerrit-Reviewer: keith <keith at rhizomatica.org>
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: neels <nhofmeyr at sysmocom.de>
Gerrit-CC: pespin <pespin at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20211025/1a1c86a4/attachment.htm>


More information about the gerrit-log mailing list