module BSCNAT_Tests { /* osmo-bsc_nat test suite in TTCN-3 * (C) 2018-2019 sysmocom - s.f.m.c. GmbH * Author: Daniel Willmann * 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 Osmocom_Types all; import from IPL4asp_Types all; import from IPA_Emulation all; import from RAN_Emulation all; import from MTP3asp_Types all; import from Osmocom_CTRL_Functions all; import from Osmocom_CTRL_Types all; import from Osmocom_CTRL_Adapter all; import from SCCP_Types all; import from SCCPasp_Types all; import from SCCP_Emulation all; import from MSC_Simulation all; import from MSC_ConnectionHandler all; import from BSC_MS_Simulation all; import from BSC_MS_ConnectionHandler all; import from Osmocom_VTY_Functions all; import from TELNETasp_PortType all; const integer NUM_MSC := 1; const integer NUM_BSC := 1; type record BscState { BSC_CT BSC, MSC_SCCP_MTP3_parameters sccp_pars, SCCP_PAR_Address sccp_addr_own, SCCP_PAR_Address sccp_addr_peer } type record MscState { MSC_CT MSC, MSC_SCCP_MTP3_parameters sccp_pars, SCCP_PAR_Address sccp_addr_own } type component test_CT extends CTRL_Adapter_CT { var MscState msc[NUM_MSC]; var BscState bsc[NUM_BSC]; port TELNETasp_PT BSCNATVTY; var boolean g_initialized := false; var octetstring g_sio := '83'O; } modulepar { PortNumber mp_bsc_port := 49999; charstring mp_bsc_ip := "127.0.0.1"; PortNumber mp_msc_port := 5000; charstring mp_msc_ip := "127.0.0.1"; /* port number to which to establish the IPA CTRL connection */ integer mp_nat_ctrl_port := 4250; /* port number to which to establish the SCCPLite connection */ PortNumber mp_nat_port := 5000; charstring mp_nat_ip := "127.0.0.1"; charstring mp_sccp_service_type := "mtp3_itu"; integer mp_bsc_pc := 196; integer mp_bsc_ssn := 254; integer mp_msc_pc := 185; /* 0.23.1 */ integer mp_msc_ssn := 254; } /* construct a SCCP_PAR_Address with just PC + SSN and no GT */ template (value) SCCP_PAR_Address ts_SccpAddr_PC_SSN(integer pc, integer ssn) := { addressIndicator := { pointCodeIndic := '1'B, ssnIndicator := '1'B, globalTitleIndic := '0000'B, routingIndicator := '1'B }, signPointCode := SCCP_SPC_int2bit(pc, mp_sccp_service_type, '83'O), //signPointCode := SCCP_SPC_int2bit(pc, mp_sccp_service_type, g_sio), subsystemNumber := ssn, globalTitle := omit } template MTP3_Field_sio ts_sio(octetstring sio_in) := { ni := substr(oct2bit(sio_in),0,2), prio := substr(oct2bit(sio_in),2,2), si := substr(oct2bit(sio_in),4,4) } template MSC_SCCP_MTP3_parameters ts_SCCP_Pars(octetstring sio, integer opc, integer dpc, integer local_ssn) := { sio := ts_sio(sio), opc := opc, dpc := dpc, sls := 0, sccp_serviceType := mp_sccp_service_type, ssn := local_ssn }; function f_init_BscState(inout BscState bsc_st, integer opc, integer dpc, integer local_ssn, integer remote_ssn) runs on test_CT { bsc_st.sccp_pars := valueof(ts_SCCP_Pars(g_sio, opc, dpc, local_ssn)); bsc_st.sccp_addr_own := valueof(ts_SccpAddr_PC_SSN(opc, local_ssn)); bsc_st.sccp_addr_peer := valueof(ts_SccpAddr_PC_SSN(dpc, remote_ssn)); } function f_init_MscState(inout MscState msc_st, integer opc, integer dpc, integer local_ssn, integer remote_ssn) runs on test_CT { msc_st.sccp_pars := valueof(ts_SCCP_Pars(g_sio, opc, dpc, local_ssn)); msc_st.sccp_addr_own := valueof(ts_SccpAddr_PC_SSN(opc, local_ssn)); } function f_vty_allow_osmux(boolean allow) runs on test_CT { if (allow) { f_vty_config(BSCNATVTY, "mgcp", "osmux on"); } else { f_vty_config(BSCNATVTY, "mgcp", "osmux off"); } } function f_init_vty(charstring id := "foo") runs on test_CT { if (BSCNATVTY.checkstate("Mapped")) { /* skip initialization if already executed once */ return; } map(self:BSCNATVTY, system:BSCNATVTY); f_vty_set_prompts(BSCNATVTY); f_vty_transceive(BSCNATVTY, "enable"); } function f_init(void_fn_bsc_ms fn_bsc_ms, void_fn_bsc fn_bsc, BssmapCreateCallback cb_msc, boolean use_osmux) runs on test_CT { var integer i; var charstring id; f_init_vty("VirtBSCNAT"); f_vty_allow_osmux(use_osmux); f_ipa_ctrl_start(mp_nat_ip, mp_nat_ctrl_port); for (i := 0; i < NUM_MSC; i := i+1) { f_init_MscState(msc[i], mp_msc_pc +i, mp_bsc_pc, mp_msc_ssn, mp_bsc_ssn); id := "MSC" & int2str(i); msc[i].MSC := MSC_CT.create(id); msc[i].MSC.start(MSC_Simulation.main(mp_msc_ip, mp_msc_port + i, msc[i].sccp_pars, msc[i].sccp_addr_own, cb_msc, id)); } /* Wait for bsc_nat to attach to MSC. Before that all BSC connections will be dropped */ f_sleep(5.0); for (i := 0; i < NUM_BSC; i := i+1) { f_init_BscState(bsc[i], mp_bsc_pc +i, mp_msc_pc, mp_bsc_ssn, mp_msc_ssn); id := "BSC" & int2str(i); bsc[i].BSC := BSC_CT.create(id); var BSC_MS_TestHdlrParams pars; pars.sccp_addr_own := bsc[i].sccp_addr_own; pars.sccp_addr_remote := bsc[i].sccp_addr_peer; pars.use_osmux := use_osmux; bsc[i].BSC.start(BSC_MS_Simulation.main(mp_nat_ip, mp_nat_port, mp_bsc_ip, mp_bsc_port+i, bsc[i].sccp_pars, pars, fn_bsc_ms, fn_bsc, id)); } } function f_wait_finish(timer T) runs on test_CT { var integer i; alt { /* wait for BSC to stop. The idea is that the BSC components terminate first */ [] bsc[0].BSC.done { } [] T.timeout { setverdict(fail); } } all component.stop; /* terminate the MSCs */ for (i := 0; i < NUM_MSC; i := i+1) { msc[i].MSC.stop; } setverdict(pass); } function f_TC_recv_dump(boolean use_osmux := false) runs on test_CT { timer T := 30.0; T.start; f_init(refers(bsc_ms_establish_fully), refers(bsc_do_nothing), refers(CreateCallback_establish_fully), use_osmux); f_wait_finish(T); } testcase TC_recv_dump() runs on test_CT { f_TC_recv_dump(); } testcase TC_recv_dump_osmux() runs on test_CT { f_TC_recv_dump(true); } testcase TC_ctrl_location() runs on test_CT { timer T := 30.0; T.start; f_init(refers(bsc_ms_do_nothing), refers(bsc_ctrl_location), refers(CreateCallback_establish_fully), false); f_ctrl_exp_trap(IPA_CTRL, "net.0.bsc.0.bts.0.location-state", "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01", 10.0); f_ctrl_set(IPA_CTRL, "net.0.bsc.0.rf_locked", "1"); f_wait_finish(T); } control { execute( TC_recv_dump() ); execute( TC_recv_dump_osmux() ); execute( TC_ctrl_location() ); } }