aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2020-10-01 06:35:56 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2020-10-15 02:09:13 +0000
commit5c5b276600c3abf257b69b11600e77599689c20d (patch)
tree128377abe70ebe8b3c9f40fe163b2d70b00e7251
parent1708d1bf1bb0d936d62f44e2d5f0b3ae09aa423f (diff)
smlc: implement initial LCS tests for OsmoSMLC
-rw-r--r--Makefile2
-rw-r--r--smlc/BSC_ConnectionHandler.ttcn95
-rw-r--r--smlc/SMLC_Tests.cfg18
-rw-r--r--smlc/SMLC_Tests.default19
-rw-r--r--smlc/SMLC_Tests.ttcn503
-rw-r--r--smlc/expected-results.xml4
-rwxr-xr-xsmlc/gen_links.sh75
-rw-r--r--smlc/osmo-smlc.cfg28
-rw-r--r--smlc/osmo-stp.cfg45
-rwxr-xr-xsmlc/regen_makefile.sh9
10 files changed, 797 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 03e7a70b..b1a7e617 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@
# limitations under the License.
SUBDIRS=bsc bsc-nat bts ccid ggsn_tests hlr mgw mme msc pcu pgw remsim sccp selftest sgsn \
- simtrace sip stp sysinfo
+ simtrace sip stp sysinfo smlc
NPROC=$(shell nproc 2>/dev/null)
ifeq ($(NPROC),)
diff --git a/smlc/BSC_ConnectionHandler.ttcn b/smlc/BSC_ConnectionHandler.ttcn
new file mode 100644
index 00000000..bd787c7b
--- /dev/null
+++ b/smlc/BSC_ConnectionHandler.ttcn
@@ -0,0 +1,95 @@
+module BSC_ConnectionHandler {
+
+/* BSC Connection Handler of SMLC Tests in TTCN-3
+ * (C) 2020 sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from SCCPasp_Types all;
+import from BSSAP_Types all;
+import from BSSAP_CodecPort all;
+import from RAN_Emulation all;
+import from BSSMAP_Templates all;
+import from BSSAP_LE_Emulation all;
+import from BSSAP_LE_Types all;
+import from BSSMAP_LE_Templates all;
+
+import from TELNETasp_PortType all;
+import from Osmocom_VTY_Functions all;
+
+/* this component represents a single subscriber connection at the SMLC. */
+type component BSC_ConnHdlr extends BSSAP_LE_ConnHdlr {
+ /* SCCP Connecction Identifier for the underlying SCCP connection */
+ var integer g_sccp_conn_id;
+
+ port TELNETasp_PT SMLCVTY;
+
+ var TestHdlrParams g_pars;
+
+ var charstring host_bsc := "127.0.0.4";
+
+ var boolean g_vty_initialized := false;
+}
+
+function f_BscConnHdlr_init_vty() runs on BSC_ConnHdlr {
+ if (not g_vty_initialized) {
+ map(self:SMLCVTY, system:SMLCVTY);
+ f_vty_set_prompts(SMLCVTY);
+ f_vty_transceive(SMLCVTY, "enable");
+ g_vty_initialized := true;
+ }
+}
+
+/* initialize all parameters */
+function f_BscConnHdlr_init() runs on BSC_ConnHdlr {
+ f_BscConnHdlr_init_vty();
+}
+
+/* Callback function from general BSSAP_LE_Emulation whenever a connectionless
+ * BSSAP_LE message arrives. Can return a PDU_BSSAP_LE that should be sent in return */
+private function BSSAP_LE_UnitdataCallback(PDU_BSSAP_LE bssap)
+runs on BSSAP_LE_Emulation_CT return template PDU_BSSAP_LE {
+ var template PDU_BSSAP_LE resp := omit;
+
+ /* answer all RESET with a RESET ACK */
+ if (match(bssap, tr_BSSMAP_LE_Reset)) {
+ resp := ts_BSSMAP_LE_ResetAck;
+ }
+
+ return resp;
+}
+
+const BssapLeOps BSC_BssapLeOps := {
+ create_cb := refers(BSSAP_LE_Emulation.ExpectedCreateCallback),
+ unitdata_cb := refers(BSSAP_LE_UnitdataCallback),
+ decode_dtap := false,
+ role_ms := false,
+ sccp_addr_local := omit,
+ sccp_addr_peer := omit
+}
+type record TestHdlrParams {
+ hexstring imsi,
+ integer bssap_le_idx,
+ SCCP_PAR_Address sccp_addr_bsc optional,
+ SCCP_PAR_Address sccp_addr_smlc optional
+};
+
+/* Note: Do not use valueof() to get a value of this template, use
+ * f_gen_test_hdlr_pars() instead in order to get a configuration that is
+ * matched to the current test situation (aoip vs. sccplite) */
+template (value) TestHdlrParams t_def_TestHdlrPars := {
+ imsi := '001019876543210'H,
+ bssap_le_idx := 0,
+ sccp_addr_bsc := omit,
+ sccp_addr_smlc := omit
+}
+
+}
diff --git a/smlc/SMLC_Tests.cfg b/smlc/SMLC_Tests.cfg
new file mode 100644
index 00000000..cc9fd6e4
--- /dev/null
+++ b/smlc/SMLC_Tests.cfg
@@ -0,0 +1,18 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./SMLC_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+SMLC_Tests.control
diff --git a/smlc/SMLC_Tests.default b/smlc/SMLC_Tests.default
new file mode 100644
index 00000000..485d2151
--- /dev/null
+++ b/smlc/SMLC_Tests.default
@@ -0,0 +1,19 @@
+[LOGGING]
+"VirtBSC-SCCP".FileMask := ERROR | WARNING | PARALLEL | VERDICTOP;
+mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
+
+[TESTPORT_PARAMETERS]
+*.SMLCVTY.CTRL_MODE := "client"
+*.SMLCVTY.CTRL_HOSTNAME := "127.0.0.1"
+*.SMLCVTY.CTRL_PORTNUM := "4271"
+*.SMLCVTY.CTRL_LOGIN_SKIPPED := "yes"
+*.SMLCVTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.SMLCVTY.CTRL_READMODE := "buffered"
+*.SMLCVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.SMLCVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
+*.SMLCVTY.PROMPT1 := "OsmoSMLC> "
+
+[MODULE_PARAMETERS]
+Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoSMLC";
+
+[EXECUTE]
diff --git a/smlc/SMLC_Tests.ttcn b/smlc/SMLC_Tests.ttcn
new file mode 100644
index 00000000..e42ed22e
--- /dev/null
+++ b/smlc/SMLC_Tests.ttcn
@@ -0,0 +1,503 @@
+module SMLC_Tests {
+
+/* Integration Tests for OsmoSMLC
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This test suite tests OsmoSMLC while emulating both multiple BTS + MS as
+ * well as the MSC. See README for more details.
+ *
+ * There are test cases that run in so-called 'handler mode' and test cases
+ * that run directly on top of the BSSAP and RSL CodecPorts. The "handler mode"
+ * tests abstract the multiplexing/demultiplexing of multiple SCCP connections
+ * and/or RSL channels and are hence suitable for higher-level test cases, while
+ * the "raw" tests directly on top of the CodecPorts are more suitable for lower-
+ * level testing.
+ */
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+
+import from BSSAP_LE_Adapter all;
+import from BSSAP_LE_CodecPort all;
+import from BSSAP_LE_Types all;
+import from BSSAP_LE_Emulation all;
+import from BSSMAP_LE_Templates all;
+import from BSSLAP_Types all;
+
+import from BSSAP_Types all;
+import from BSSMAP_Templates all;
+
+import from Osmocom_CTRL_Functions all;
+import from Osmocom_CTRL_Types all;
+import from Osmocom_CTRL_Adapter all;
+
+import from Osmocom_VTY_Functions all;
+import from TELNETasp_PortType all;
+
+import from SCCP_Templates all;
+
+import from SCCPasp_Types all;
+
+import from BSC_ConnectionHandler all;
+
+const integer NUM_BSC := 1;
+
+/* Default list of counters for 'smlc' */
+const CounterNameVals counternames_bsc := {
+ { "foo:bar", 0 }
+};
+
+type component test_CT extends CTRL_Adapter_CT {
+ var BSSAP_LE_Adapter g_bssap_le[NUM_BSC];
+ port BSSAP_LE_CODEC_PT BSSAP_LE;
+
+ port TELNETasp_PT SMLCVTY;
+
+ /* are we initialized yet */
+ var boolean g_initialized := false;
+
+ /*Configure T(tias) over VTY, seconds */
+ var integer g_smlc_sccp_timer_ias := 7 * 60;
+ /*Configure T(tiar) over VTY, seconds */
+ var integer g_smlc_sccp_timer_iar := 15 * 60;
+
+ /* global test case guard timer (actual timeout value is set in f_init()) */
+ timer T_guard := 30.0;
+
+ var CounterNameValsList g_ctr_smlc;
+ var CounterNameValsList g_ctr_bsc;
+
+}
+
+type record of BSSAP_LE_Configuration BSSAP_LE_Configurations;
+
+modulepar {
+ /* IP address at which the SMLC can be reached */
+ charstring mp_smlc_ip := "127.0.0.1";
+ /* port number to which to establish the IPA CTRL connection */
+ integer mp_smlc_ctrl_port := 4272;
+ /* IP address at which the test binds */
+ charstring mp_test_ip := "127.0.0.1";
+
+ BSSAP_LE_Configurations mp_bssap_le_cfg := {
+ {
+ sccp_service_type := "mtp3_itu",
+ sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
+ own_pc := 187, /* 0.23.3 first BSC emulation */
+ own_ssn := 250, /* BSC side SSN */
+ peer_pc := 190, /* 0.23.6 osmo-smlc */
+ peer_ssn := 252, /* SMLC side SSN */
+ sio := '83'O,
+ rctx := 1
+ }
+ };
+}
+
+private function f_gen_test_hdlr_pars(integer bssap_le_idx := 0) return TestHdlrParams {
+
+ var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
+ return pars;
+}
+
+/* Convenience functions for rate counters using g_ctr_bsc. */
+
+private function f_ctrs_smlc_init(integer bscs_count := NUM_BSC, CounterNameVals counternames := counternames_bsc) runs on test_CT {
+ g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", bscs_count, counternames);
+ log("initial msc rate counters: ", g_ctr_bsc);
+}
+
+private function f_ctrs_smlc_add(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
+ f_counter_name_vals_list_add(g_ctr_bsc, msc_nr, countername, val);
+}
+
+/* f_ctrs_smlc_init();
+ * f_do_thing(on_msc := 0);
+ * f_do_thing(on_msc := 0);
+ * f_do_other(on_msc := 1);
+ * f_ctrs_smlc_add(0, "thing", 2);
+ * f_ctrs_smlc_add(1, "other");
+ * f_ctrs_smlc_verify();
+ */
+private function f_ctrs_smlc_verify() runs on test_CT {
+ log("verifying msc rate counters: ", g_ctr_bsc);
+ f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
+}
+
+/* convenience: f_ctrs_smlc_add() and f_ctrs_smlc_verify() in one call.
+ * f_ctrs_smlc_init();
+ * f_do_thing(on_msc := 0);
+ * f_do_thing(on_msc := 0);
+ * f_do_thing(on_msc := 0);
+ * f_ctrs_smlc_expect(0, "thing", 3);
+ */
+private function f_ctrs_smlc_expect(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
+ f_ctrs_smlc_add(msc_nr, countername, val);
+ f_ctrs_smlc_verify();
+}
+
+private function f_shutdown_helper() runs on test_CT {
+ all component.stop;
+ setverdict(pass);
+ mtc.stop;
+}
+
+/* global altstep for global guard timer */
+altstep as_Tguard() runs on test_CT {
+ [] T_guard.timeout {
+ setverdict(fail, "Timeout of T_guard");
+ mtc.stop;
+ }
+}
+
+private function f_logp(TELNETasp_PT pt, charstring log_msg)
+{
+ // log on TTCN3 log output
+ log(log_msg);
+ // log in stderr log
+ f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
+}
+
+/* global initialization function
+ * \param nr_bts Number of BTSs we should start/bring up
+ * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
+ * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
+ */
+function f_init(integer nr_bsc := NUM_BSC, float guard_timeout := 30.0) runs on test_CT {
+ var integer bssap_le_idx;
+
+ if (g_initialized) {
+ return;
+ }
+ g_initialized := true;
+
+ T_guard.start(guard_timeout);
+ activate(as_Tguard());
+
+ f_init_vty("VirtBSC");
+
+ for (bssap_le_idx := 0; bssap_le_idx < nr_bsc; bssap_le_idx := bssap_le_idx+1) {
+ f_bssap_le_adapter_init(g_bssap_le[bssap_le_idx], mp_bssap_le_cfg[bssap_le_idx], "VirtBSC", BSC_BssapLeOps);
+ f_bssap_le_adapter_start(g_bssap_le[bssap_le_idx]);
+ }
+}
+
+function f_init_vty(charstring id := "foo") runs on test_CT {
+ if (SMLCVTY.checkstate("Mapped")) {
+ /* skip initialization if already executed once */
+ return;
+ }
+ map(self:SMLCVTY, system:SMLCVTY);
+ f_vty_set_prompts(SMLCVTY);
+ f_vty_transceive(SMLCVTY, "enable");
+ f_cs7_inst_0_cfg(SMLCVTY, {"sccp-timer ias " & int2str(g_smlc_sccp_timer_ias),
+ "sccp-timer iar " & int2str(g_smlc_sccp_timer_iar)});
+}
+
+type function void_fn(charstring id) runs on BSC_ConnHdlr;
+
+private function f_connect_handler(inout BSC_ConnHdlr vc_conn, integer bssap_le_idx := 0) runs on test_CT {
+ connect(vc_conn:BSSAP_LE, g_bssap_le[bssap_le_idx].vc_BSSAP_LE:CLIENT);
+ connect(vc_conn:BSSAP_LE_PROC, g_bssap_le[bssap_le_idx].vc_BSSAP_LE:PROC);
+}
+
+function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
+runs on test_CT return BSC_ConnHdlr {
+ var charstring id := testcasename();
+ var BSC_ConnHdlr vc_conn;
+ var integer bssap_le_idx := 0;
+ if (isvalue(pars)) {
+ bssap_le_idx := valueof(pars).bssap_le_idx;
+ }
+ vc_conn := BSC_ConnHdlr.create(id);
+ f_connect_handler(vc_conn, bssap_le_idx);
+ /* Emit a marker to appear in the SUT's own logging output */
+ f_logp(SMLCVTY, testcasename() & "() start");
+ vc_conn.start(f_handler_init(fn, id, pars));
+ return vc_conn;
+}
+
+private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
+runs on BSC_ConnHdlr {
+ if (isvalue(pars)) {
+ g_pars := valueof(pars);
+ }
+ fn.apply(id);
+}
+
+type record of charstring Commands;
+
+private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
+{
+ f_vty_enter_cfg_cs7_inst(pt, 0);
+ for (var integer i := 0; i < sizeof(cmds); i := i+1) {
+ f_vty_transceive(pt, cmds[i]);
+ }
+ f_vty_transceive(pt, "end");
+}
+
+template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
+ := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
+
+template PDU_BSSAP_LE tr_BSSMAP_LE_BSSLAP(template BSSLAP_PDU bsslap)
+ := tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
+
+/* BSC sends Perform Location Request that already contains a TA Layer 3 BSSLAP APDU */
+private function f_tc_smlc_location_request_with_ta_l3(charstring id) runs on BSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_BscConnHdlr_init();
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ var uint16_t cell_id := 42;
+ var BSSMAP_IE_CellIdentifier cell_ident := valueof(ts_CellID_LAC_CI(23, cell_id));
+
+ BSSAP_LE.send(ts_BSSAP_LE_Conn_Req(g_pars.sccp_addr_smlc, g_pars.sccp_addr_bsc,
+ valueof(ts_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, cell_ident, g_pars.imsi,
+ enc_BSSLAP_PDU(valueof(ts_BSSLAP_TA_Layer3(23)))))));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_CONF_IND);
+
+ /* SMLC got the TA from the BSC, now responds with geo information data. */
+ /* TODO: implement GAD coding in ttcn */
+ /* Expecting geo:
+ * 0001 .... = Location estimate: Ellipsoid point with uncertainty Circle (1)
+ * 0... .... = Sign of latitude: North (0)
+ * .010 0001 0000 1001 1100 1001 = Degrees of latitude: 2165193 (23.23000 degrees)
+ * 0001 1110 0010 1010 0101 0011 = Degrees of longitude: 1976915 (42.42000 degrees)
+ * .100 1010 = Uncertainty code: 74 (11552.7 m)
+ * [Location OSM URI: https://www.openstreetmap.org/?mlat=23.23000&mlon=42.42000&zoom=12]
+ */
+ var octetstring geo := '102109C91E2A534A'O;
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocResp(geo, omit));
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_smlc_location_request_with_ta_l3() runs on test_CT {
+ var BSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init();
+ f_sleep(1.0);
+
+ pars.sccp_addr_bsc := g_bssap_le[0].sccp_addr_own;
+ pars.sccp_addr_smlc := g_bssap_le[0].sccp_addr_peer;
+
+ vc_conn := f_start_handler(refers(f_tc_smlc_location_request_with_ta_l3), pars);
+ vc_conn.done;
+}
+
+/* BSC sends Perform Location Request without BSSLAP APDU, SMLC needs to request TA */
+private function f_tc_smlc_location_request_without_ta_l3(charstring id) runs on BSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_BscConnHdlr_init();
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ var uint16_t cell_id := 42;
+ var BSSMAP_IE_CellIdentifier cell_ident := valueof(ts_CellID_LAC_CI(23, cell_id));
+
+ BSSAP_LE.send(ts_BSSAP_LE_Conn_Req(g_pars.sccp_addr_smlc, g_pars.sccp_addr_bsc,
+ valueof(ts_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, cell_ident, g_pars.imsi))));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_CONF_IND);
+
+ /* SMLC wants to ask the TA from the SMLC explicitly in a BSSLAP TA Request message */
+ BSSAP_LE.receive(tr_BSSMAP_LE_BSSLAP(tr_BSSLAP_TA_Req));
+
+ /* BSC figures out the TA and sends it back to the SMLC */
+
+ BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Resp(cell_id, 23)));
+
+ /* SMLC got the TA from the BSC, now responds with geo information data. */
+ /* TODO: implement GAD coding in ttcn */
+ /* Expecting geo:
+ * 0001 .... = Location estimate: Ellipsoid point with uncertainty Circle (1)
+ * 0... .... = Sign of latitude: North (0)
+ * .010 0001 0000 1001 1100 1001 = Degrees of latitude: 2165193 (23.23000 degrees)
+ * 0001 1110 0010 1010 0101 0011 = Degrees of longitude: 1976915 (42.42000 degrees)
+ * .100 1010 = Uncertainty code: 74 (11552.7 m)
+ * [Location OSM URI: https://www.openstreetmap.org/?mlat=23.23000&mlon=42.42000&zoom=12]
+ */
+ var octetstring geo := '102109C91E2A534A'O;
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocResp(geo, omit));
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_smlc_location_request_without_ta_l3() runs on test_CT {
+ var BSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1);
+ f_sleep(1.0);
+
+ pars.sccp_addr_bsc := g_bssap_le[0].sccp_addr_own;
+ pars.sccp_addr_smlc := g_bssap_le[0].sccp_addr_peer;
+
+ vc_conn := f_start_handler(refers(f_tc_smlc_location_request_without_ta_l3), pars);
+ vc_conn.done;
+}
+
+/* BSC sends Perform Location Request, halfway the BSC indicates handover via BSSLAP Reset */
+private function f_tc_smlc_location_request_bsslap_reset(charstring id) runs on BSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_BscConnHdlr_init();
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ var uint16_t cell_id := 1;
+ var BSSMAP_IE_CellIdentifier cell_ident := valueof(ts_CellID_LAC_CI(1, cell_id));
+
+ BSSAP_LE.send(ts_BSSAP_LE_Conn_Req(g_pars.sccp_addr_smlc, g_pars.sccp_addr_bsc,
+ valueof(ts_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, cell_ident, g_pars.imsi))));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_CONF_IND);
+
+ /* SMLC wants to ask the TA from the SMLC explicitly in a BSSLAP TA Request message */
+ BSSAP_LE.receive(tr_BSSMAP_LE_BSSLAP(tr_BSSLAP_TA_Req));
+
+ /* BSC reports a Handover via a BSSLAP Reset */
+ BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_Reset(17, 42,
+ valueof(ts_BSSLAP_IE_ChanDesc),
+ BSSLAP_CAUSE_INTRA_BSS_HO)));
+
+ /* SMLC got the TA from the BSC via BSSLAP Reset, now responds with geo information data. */
+ /* TODO: implement GAD coding in ttcn */
+ /* Expecting geo:
+ * 0001 .... = Location estimate: Ellipsoid point with uncertainty Circle (1)
+ * 0... .... = Sign of latitude: North (0)
+ * .000 1011 0011 1000 1011 0100 = Degrees of latitude: 735412 (7.89012 degrees)
+ * 0000 0110 0101 0100 0110 1011 = Degrees of longitude: 414827 (8.90122 degrees)
+ * .101 0001 = Uncertainty code: 81 (22522.4 m)
+ * [Location OSM URI: https://www.openstreetmap.org/?mlat=7.89012&mlon=8.90122&zoom=12]
+ */
+ var octetstring geo := '100B38B406546B51'O;
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocResp(geo, omit));
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_smlc_location_request_bsslap_reset() runs on test_CT {
+ var BSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1);
+ f_sleep(1.0);
+
+ pars.sccp_addr_bsc := g_bssap_le[0].sccp_addr_own;
+ pars.sccp_addr_smlc := g_bssap_le[0].sccp_addr_peer;
+
+ vc_conn := f_start_handler(refers(f_tc_smlc_location_request_bsslap_reset), pars);
+ vc_conn.done;
+}
+
+/* BSC sends Perform Location Request, halfway the BSC aborts the request because of inter-BSC HO */
+private function f_tc_smlc_location_request_abort(charstring id) runs on BSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_BscConnHdlr_init();
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ var uint16_t cell_id := 42;
+ var BSSMAP_IE_CellIdentifier cell_ident := valueof(ts_CellID_LAC_CI(23, cell_id));
+
+ BSSAP_LE.send(ts_BSSAP_LE_Conn_Req(g_pars.sccp_addr_smlc, g_pars.sccp_addr_bsc,
+ valueof(ts_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, cell_ident, g_pars.imsi))));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_CONF_IND);
+
+ /* SMLC wants to ask the TA from the SMLC explicitly in a BSSLAP TA Request message */
+ BSSAP_LE.receive(tr_BSSMAP_LE_BSSLAP(tr_BSSLAP_TA_Req));
+
+ /* BSC aborts */
+ BSSAP_LE.send(ts_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_INTER_BSC_HO));
+
+ var PDU_BSSAP_LE bssap_le;
+ timer nothing := 7.0;
+ nothing.start;
+ alt {
+ [] BSSAP_LE.receive(tr_BSSAP_LE_BSSMAP) -> value(bssap_le) {
+ log("unexpected bssap_le: ", bssap_le);
+ setverdict(fail, "No more messages expected from SMLC");
+ mtc.stop;
+ }
+ [] nothing.timeout {
+ setverdict(pass);
+ break;
+ }
+ }
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_smlc_location_request_abort() runs on test_CT {
+ var BSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1);
+ f_sleep(1.0);
+
+ pars.sccp_addr_bsc := g_bssap_le[0].sccp_addr_own;
+ pars.sccp_addr_smlc := g_bssap_le[0].sccp_addr_peer;
+
+ vc_conn := f_start_handler(refers(f_tc_smlc_location_request_abort), pars);
+ vc_conn.done;
+}
+
+/* BSC sends Perform Location Request, SMLC asks for TA, halfway the BSC aborts the TA request */
+private function f_tc_smlc_location_request_bsslap_abort(charstring id) runs on BSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_BscConnHdlr_init();
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ var uint16_t cell_id := 42;
+ var BSSMAP_IE_CellIdentifier cell_ident := valueof(ts_CellID_LAC_CI(23, cell_id));
+
+ BSSAP_LE.send(ts_BSSAP_LE_Conn_Req(g_pars.sccp_addr_smlc, g_pars.sccp_addr_bsc,
+ valueof(ts_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, cell_ident, g_pars.imsi))));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_CONF_IND);
+
+ /* SMLC wants to ask the TA from the SMLC explicitly in a BSSLAP TA Request message */
+ BSSAP_LE.receive(tr_BSSMAP_LE_BSSLAP(tr_BSSLAP_TA_Req));
+
+ /* BSC aborts the TA Request */
+ BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_Abort(BSSLAP_CAUSE_SUPERV_TIMER_EXPIRED)));
+
+ /* Expect response without location, just an LCS Cause indicating abort */
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_smlc_location_request_bsslap_abort() runs on test_CT {
+ var BSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1);
+ f_sleep(1.0);
+
+ pars.sccp_addr_bsc := g_bssap_le[0].sccp_addr_own;
+ pars.sccp_addr_smlc := g_bssap_le[0].sccp_addr_peer;
+
+ vc_conn := f_start_handler(refers(f_tc_smlc_location_request_bsslap_abort), pars);
+ vc_conn.done;
+}
+
+control {
+if (true) {
+ execute( TC_smlc_location_request_without_ta_l3() );
+} else {
+ execute( TC_smlc_location_request_with_ta_l3() );
+ execute( TC_smlc_location_request_without_ta_l3() );
+ execute( TC_smlc_location_request_bsslap_reset() );
+ execute( TC_smlc_location_request_bsslap_abort() );
+ execute( TC_smlc_location_request_abort() );
+}
+}
+
+}
diff --git a/smlc/expected-results.xml b/smlc/expected-results.xml
new file mode 100644
index 00000000..9034822f
--- /dev/null
+++ b/smlc/expected-results.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<testsuite name='BSC_Tests' tests='209' failures='3' errors='0' skipped='1' inconc='0' time='MASKED'>
+ <testcase classname='SMLC_Tests' name='TC_smlc_location_request_for_idle_ms' time='MASKED'/>
+</testsuite>
diff --git a/smlc/gen_links.sh b/smlc/gen_links.sh
new file mode 100755
index 00000000..092b9636
--- /dev/null
+++ b/smlc/gen_links.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+#DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src
+#FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn"
+#gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
+FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h SDP_EncDec.cc"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
+FILES="Socket_API_Definitions.ttcn"
+gen_links $DIR $FILES
+
+# Required by MGCP and IPA
+DIR=$BASEDIR/titan.TestPorts.IPL4asp/src
+FILES="IPL4asp_Functions.ttcn IPL4asp_PT.cc IPL4asp_PT.hh IPL4asp_PortType.ttcn IPL4asp_Types.ttcn IPL4asp_discovery.cc IPL4asp_protocol_L234.hh"
+gen_links $DIR $FILES
+
+# required by M3UA_Emulation
+DIR=$BASEDIR/titan.ProtocolModules.M3UA/src
+FILES="M3UA_Types.ttcn"
+gen_links $DIR $FILES
+
+# required by M3UA_Emulation
+DIR=$BASEDIR/titan.TestPorts.SCTPasp/src
+FILES="SCTPasp_PT.cc SCTPasp_PT.hh SCTPasp_PortType.ttcn SCTPasp_Types.ttcn"
+gen_links $DIR $FILES
+
+# required by SCCP Emulation
+DIR=$BASEDIR/titan.ProtocolEmulations.M3UA/src
+FILES="M3UA_Emulation.ttcn"
+gen_links $DIR $FILES
+
+# required by SCCP Emulation
+DIR=$BASEDIR/titan.TestPorts.MTP3asp/src
+FILES="MTP3asp_PortType.ttcn MTP3asp_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolEmulations.SCCP/src
+FILES="SCCP_Emulation.ttcn SCCP_Mapping.ttcnpp SCCP_Types.ttcn SCCPasp_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.BSSMAP/src
+FILES="BSSAP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.MobileL3_v13.4.0/src
+FILES="MobileL3_CC_Types.ttcn MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_Types.ttcn MobileL3_RRM_Types.ttcn MobileL3_SMS_Types.ttcn MobileL3_SS_Types.ttcn MobileL3_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.SDP/src
+FILES="SDP_EncDec.cc SDP_Types.ttcn SDP_parse_.tab.c SDP_parse_.tab.h SDP_parse_parser.h SDP_parser.l
+SDP_parser.y lex.SDP_parse_.c"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.RTP/src
+FILES="RTP_EncDec.cc RTP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
+FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
+gen_links $DIR $FILES
+
+DIR=../library
+FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn GSM_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp L3_Templates.ttcn BSSMAP_Templates.ttcn BSSAP_LE_Types.ttcn RAN_Emulation.ttcnpp RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn GSM_RR_Types.ttcn RSL_Types.ttcn RSL_Emulation.ttcn MGCP_Emulation.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort.ttcn MGCP_CodecPort_CtrlFunct.ttcn MGCP_CodecPort_CtrlFunctDef.cc BSSAP_CodecPort.ttcn RAN_Adapter.ttcnpp Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn RTP_CodecPort.ttcn RTP_CodecPort_CtrlFunct.ttcn RTP_CodecPort_CtrlFunctDef.cc RTP_Emulation.ttcn IuUP_Types.ttcn IuUP_EncDec.cc IuUP_Emulation.ttcn SCCP_Templates.ttcn IPA_Testing.ttcn GSM_SystemInformation.ttcn GSM_RestOctets.ttcn "
+FILES+="BSSAP_LE_CodecPort.ttcn BSSAP_LE_Emulation.ttcn BSSAP_LE_Adapter.ttcn BSSLAP_Types.ttcn BSSMAP_LE_Templates.ttcn "
+
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/smlc/osmo-smlc.cfg b/smlc/osmo-smlc.cfg
new file mode 100644
index 00000000..3bba0b33
--- /dev/null
+++ b/smlc/osmo-smlc.cfg
@@ -0,0 +1,28 @@
+log gsmtap 172.18.23.203
+ logging level set-all debug
+ logging filter all 1
+log stderr
+ logging filter all 1
+ logging color 1
+ logging print level 1
+ logging print category 1
+ logging print category-hex 0
+ logging print extended-timestamp 1
+ logging print file basename last
+ logging level set-all debug
+
+line vty
+ no login
+ bind 0.0.0.0
+
+cs7 instance 0
+ asp asp-clnt-msc-0 2905 2905 m3ua
+ local-ip 172.18.23.20
+ local-ip fd02:db8:23::20
+ remote-ip 172.18.23.200
+ remote-ip fd02:db8:23::200
+
+cells
+ lac-ci 23 42 lat 23.23 lon 42.42
+ cgi 001 02 3 4 lat 5.678 lon 6.789
+ cgi 001 02 1 17 lat 7.890123 lon 8.90123
diff --git a/smlc/osmo-stp.cfg b/smlc/osmo-stp.cfg
new file mode 100644
index 00000000..dad1f2d1
--- /dev/null
+++ b/smlc/osmo-stp.cfg
@@ -0,0 +1,45 @@
+!
+! OsmoSTP (0.8.1) configuration saved from vty
+!!
+!
+log stderr
+ logging filter all 1
+ logging color 1
+ logging print category 1
+ logging timestamp 1
+ logging print extended-timestamp 1
+ logging level all everything
+ logging level lglobal notice
+ logging level llapd notice
+ logging level linp notice
+ logging level lmux notice
+ logging level lmi notice
+ logging level lmib notice
+ logging level lsms notice
+ logging level lctrl notice
+ logging level lgtp notice
+ logging level lstats notice
+ logging level lgsup notice
+ logging level loap notice
+ logging level lss7 debug
+ logging level lsccp debug
+ logging level lsua debug
+ logging level lm3ua debug
+ logging level lmgcp notice
+!
+line vty
+ no login
+!
+cs7 instance 0
+ xua rkm routing-key-allocation dynamic-permitted
+ asp virt-bsc0-0 23905 2905 m3ua
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.1
+ as virt-bsc0 m3ua
+ asp virt-bsc0-0
+ routing-key 1 0.23.3
+
+ route-table system
+ update route 0.23.3 7.255.7 linkset virt-bsc0
+ listen m3ua 2905
+ accept-asp-connections dynamic-permitted
diff --git a/smlc/regen_makefile.sh b/smlc/regen_makefile.sh
new file mode 100755
index 00000000..d8b86421
--- /dev/null
+++ b/smlc/regen_makefile.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+MAIN=SMLC_Tests.ttcn
+
+FILES="*.ttcn *.ttcnpp IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc SCTPasp_PT.cc RTP_EncDec.cc SDP_EncDec.cc RTP_CodecPort_CtrlFunctDef.cc MGCP_CodecPort_CtrlFunctDef.cc IuUP_EncDec.cc Native_FunctionDefs.cc TELNETasp_PT.cc *.c"
+
+export CPPFLAGS_TTCN3="-DIPA_EMULATION_RSL -DIPA_EMULATION_MGCP -DIPA_EMULATION_CTRL -DIPA_EMULATION_SCCP -DRAN_EMULATION_BSSAP -DRAN_EMULATION_MGCP -DRAN_EMULATION_CTRL -DUSE_MTP3_DISTRIBUTOR"
+
+../regen-makefile.sh $MAIN $FILES