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 MTP3asp_Types all; import from SCCP_Types all; import from SCCPasp_Types all; import from SCCP_Emulation all; import from MSC_Simulation all; import from BSC_MS_Simulation 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 { var MscState msc[NUM_MSC]; var BscState bsc[NUM_BSC]; 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"; 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_init() runs on test_CT { var integer i; var charstring id; 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, 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); 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, bsc[i].sccp_addr_own, bsc[i].sccp_addr_peer, id)); } } testcase TC_recv_dump() runs on test_CT { var integer i; timer T := 30.0; f_init(); 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; } } control { execute( TC_recv_dump() ); } }