aboutsummaryrefslogtreecommitdiffstats
path: root/bsc-nat/BSCNAT_Tests.ttcn
blob: 41d58d76040b0eec6fe792cb1efa49fd2831c4bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
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() );
}

}