blob: 9ea5149a849ec22f0267b0620a019a628564ed16 [file] [log] [blame]
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001module PCU_Tests_NS {
Pau Espin Pedrol4536c822019-12-30 13:22:32 +01002
3/* Osmocom PCU test suite for IP Sub-Network-Service (SNS) in TTCN-3
4 * (C) 2018-2019 Harald Welte <laforge@gnumonks.org>
5 * All rights reserved.
6 *
7 * Released under the terms of GNU General Public License, Version 2 or
8 * (at your option) any later version.
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
13import from General_Types all;
14import from Osmocom_Types all;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +020015import from PCU_Tests all;
Pau Espin Pedrol0e6ed2e2020-04-29 14:33:13 +020016import from SGSN_Components all;
Pau Espin Pedrol4536c822019-12-30 13:22:32 +010017import from Osmocom_Gb_Types all;
18import from NS_CodecPort all;
19import from NS_Types all;
20import from BSSGP_Types all;
21import from UD_Types all;
22import from NS_CodecPort all;
23import from NS_CodecPort_CtrlFunct all;
24import from NS_Emulation all;
25import from Native_Functions all;
26import from IPL4asp_Types all;
27import from PCUIF_Types all;
28import from PCUIF_CodecPort all;
29
30type component RAW_NS_CT {
31 /* UDP port towards the bottom (IUT) */
32 port NS_CODEC_PT NSCP[4];
33 var ConnectionId g_ns_conn_id[4] := {-1, -1, -1, -1};
34 var NSConfiguration g_nsconfig[4];
35 timer g_T_guard;
36}
37
38type component RAW_PCU_CT {
39 /* PCUIF (we emulate the BTS part) */
40 port PCUIF_CODEC_PT PCU;
41 var ConnectionId g_pcu_conn_id := -1;
42}
43
44type component RAW_Test_CT extends RAW_NS_CT, RAW_PCU_CT {
45}
46
47private altstep as_Tguard() runs on RAW_NS_CT {
48 [] g_T_guard.timeout {
49 setverdict(fail, "Timeout of T_guard");
50 mtc.stop;
51 }
52}
53
54/* FIXME: make sure to use parameters from mp_gb_cfg.cell_id in the PCU INFO IND */
55private template (value) PCUIF_info_ind ts_PCUIF_INFO_default := {
56 version := PCU_IF_VERSION,
57 flags := c_PCUIF_Flags_default,
58 trx := valueof(ts_PCUIF_InfoTrxs_def),
59 bsic := 7,
60 mcc := 262,
61 mnc := 42,
62 mnc_3_digits := 0,
63 lac := 13135,
64 rac := 0,
65 nsei := mp_nsconfig.nsei,
66 nse_timer := { 3, 3, 3, 3, 30, 3, 10 },
67 cell_timer := { 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 },
68 cell_id := 20960,
69 repeat_time := 5 * 50,
70 repeat_count := 3,
71 bvci := mp_gb_cfg.bvci,
72 t3142 := 20,
73 t3169 := 5,
74 t3191 := 5,
75 t3193_10ms := 160,
76 t3195 := 5,
77 t3101 := 10,
78 t3103 := 4,
79 t3105 := 8,
80 cv_countdown := 15,
81 dl_tbf_ext := 250 * 10, /* ms */
82 ul_tbf_ext := 250 * 10, /* ms */
83 initial_cs := 2,
84 initial_mcs := 6,
85 nsvci := { mp_nsconfig.nsvci, 0 },
86 local_pprt := { mp_nsconfig.remote_udp_port, 0 },
87 remote_port := { mp_nsconfig.local_udp_port, 0 },
88 remote_ip := { f_inet_haddr(mp_nsconfig.local_ip) , '00000000'O }
89}
90
91function f_init_pcuif() runs on RAW_PCU_CT {
92 var PCUIF_info_ind info_ind;
93 map(self:PCU, system:PCU);
94
95
96 info_ind := valueof(ts_PCUIF_INFO_default);
97
98 /* Connect the Unix Domain Socket */
99 g_pcu_conn_id := f_pcuif_listen(PCU, mp_pcu_sock_path);
100 PCU.receive(UD_connected:?);
101
102 /* Wait for PCU_VERSION and return INFO_IND */
103 PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_TXT_IND(0, PCU_VERSION, ?)));
104 /* FIXME: make sure to use parameters from mp_gb_cfg.cell_id in the PCU INFO IND */
105 var template PCUIF_Message info_ind_msg := ts_PCUIF_INFO_IND(0, info_ind);
106 PCU.send(t_SD_PCUIF(g_pcu_conn_id, info_ind_msg));
107}
108
109function f_pcuif_tx(template (value) PCUIF_Message msg) runs on RAW_PCU_CT {
110 PCU.send(t_SD_PCUIF(g_pcu_conn_id, msg));
111}
112
113function f_init_ns_codec(integer idx := 0, float guard_secs := 60.0) runs on RAW_NS_CT {
114 var Result res;
115
116 if (not g_T_guard.running) {
117 g_T_guard.start(guard_secs);
118 activate(as_Tguard());
119 }
120
121 if (not isbound(g_nsconfig) or not isbound(g_nsconfig[idx])) {
122 /* copy most parts from mp_nsconfig */
123 g_nsconfig[idx] := mp_nsconfig;
124 /* adjust those parts different for each NS-VC */
125 g_nsconfig[idx].nsvci := mp_nsconfig.nsvci + idx;
126 g_nsconfig[idx].local_udp_port := mp_nsconfig.local_udp_port + idx;
127 }
128
129 map(self:NSCP[idx], system:NSCP);
130 /* Connect the UDP socket */
131 log("connecting NSCP[", idx, "] to ", g_nsconfig[idx]);
132 res := f_IPL4_connect(NSCP[idx], g_nsconfig[idx].remote_ip, g_nsconfig[idx].remote_udp_port,
133 g_nsconfig[idx].local_ip, g_nsconfig[idx].local_udp_port, 0, { udp := {}});
134 if (not ispresent(res.connId)) {
135 setverdict(fail, "Could not connect NS UDP socket, check your configuration ", g_nsconfig[idx]);
136 mtc.stop;
137 }
138 g_ns_conn_id[idx] := res.connId;
139
140}
141
142function f_ns_exp(template PDU_NS exp_rx, integer idx := 0) runs on RAW_NS_CT return PDU_NS {
143 var NS_RecvFrom nrf;
144 log("f_ns_exp() expecting ", exp_rx);
145 alt {
146 [] NSCP[idx].receive(t_NS_RecvFrom(exp_rx)) -> value nrf { }
147 [] NSCP[idx].receive {
148 setverdict(fail, "Received unexpected NS: ", nrf);
149 mtc.stop;
150 }
151 }
152 return nrf.msg;
153}
154
155/* perform outbound NS-ALIVE procedure */
156function f_outgoing_ns_alive(integer idx := 0) runs on RAW_NS_CT {
157 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_ALIVE));
158 alt {
159 [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_ALIVE_ACK));
160 [] NSCP[idx].receive { repeat; }
161 }
162}
163
164/* perform outbound NS-ALIVE procedure */
165function f_outgoing_ns_alive_no_ack(integer idx := 0, float tout := 10.0) runs on RAW_NS_CT {
166 timer T := tout;
167 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_ALIVE));
168 T.start;
169 alt {
170 [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_ALIVE_ACK)) {
171 setverdict(fail, "Received unexpected NS-ALIVE ACK");
172 }
173 [] NSCP[idx].receive { repeat; }
174 [] T.timeout {
175 setverdict(pass);
176 }
177 }
178}
179
180/* ensure no matching message is received within 'tout' */
181function f_ensure_no_ns(template PDU_NS ns := ?, integer idx := 0, float tout := 3.0)
182runs on RAW_Test_CT {
183 timer T := tout;
184 T.start;
185 alt {
186 [] NSCP[idx].receive(t_NS_RecvFrom(ns)) {
187 setverdict(fail, "NS-ALIVE from unconfigured (possibly initial) endpoint");
188 }
189 [] T.timeout {
190 setverdict(pass);
191 }
192 }
193}
194
195/* perform outbound NS-BLOCK procedure */
196function f_outgoing_ns_block(NsCause cause, integer idx := 0) runs on RAW_NS_CT {
197 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_BLOCK(cause, g_nsconfig[idx].nsvci)));
198 alt {
199 [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_BLOCK_ACK(g_nsconfig[idx].nsvci)));
200 [] NSCP[idx].receive { repeat; }
201 }
202}
203
204/* receive NS-ALIVE and ACK it */
205altstep as_rx_alive_tx_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
206 [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_ALIVE)) {
207 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_ALIVE_ACK));
208 if (not oneshot) { repeat; }
209 }
210}
211
212/* Transmit BSSGP RESET for given BVCI and expect ACK */
213function f_tx_bvc_reset_rx_ack(BssgpBvci bvci, integer idx := 0, boolean exp_ack := true)
214runs on RAW_NS_CT {
215 var PDU_BSSGP bssgp_tx := valueof(ts_BVC_RESET(BSSGP_CAUSE_NET_SV_CAP_MOD_GT_ZERO_KBPS, bvci,
216 mp_gb_cfg.cell_id));
217 timer T := 5.0;
218 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx))));
219 T.start;
220 alt {
221 [exp_ack] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, 0,
222 decmatch tr_BVC_RESET_ACK(bvci, ?)))) {
223 setverdict(pass);
224 }
225 [exp_ack] T.timeout {
226 setverdict(fail, "No response to BVC-RESET");
227 }
228 [not exp_ack] T.timeout {
229 setverdict(pass);
230 }
231 [] NSCP[idx].receive { repeat; }
232 }
233}
234
235/* Receive a BSSGP RESET for given BVCI and ACK it */
236altstep as_rx_bvc_reset_tx_ack(BssgpBvci bvci, boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
237 var NS_RecvFrom ns_rf;
238 /* FIXME: nail down received cell_id in match */
239 [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, 0,
240 decmatch tr_BVC_RESET(?, bvci, ?))))
241 -> value ns_rf {
242 var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.msg.pDU_NS_Unitdata.nS_SDU);
243 var PDU_BSSGP bssgp_tx := valueof(ts_BVC_RESET_ACK(bvci, mp_gb_cfg.cell_id));
244 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx))));
245 if (not oneshot) { repeat; }
246 }
247}
248
249
250/* Receive a BSSGP UNBLOCK for given BVCI and ACK it */
251altstep as_rx_bvc_unblock_tx_ack(BssgpBvci bvci, boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
252 var NS_RecvFrom ns_rf;
253 [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, 0,
254 decmatch t_BVC_UNBLOCK(bvci))))
255 -> value ns_rf {
256 var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.msg.pDU_NS_Unitdata.nS_SDU);
257 var PDU_BSSGP bssgp_tx := valueof(t_BVC_UNBLOCK_ACK(bvci));
258 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx))));
259 if (not oneshot) { repeat; }
260 }
261}
262
263/* Receive a BSSGP FLOW-CONTROL-BVC and ACK it */
264altstep as_rx_bvc_fc_tx_ack(BssgpBvci bvci, boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
265 var NS_RecvFrom ns_rf;
266 [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, bvci,
267 decmatch tr_BVC_FC_BVC)))
268 -> value ns_rf {
269 var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.msg.pDU_NS_Unitdata.nS_SDU);
270 var OCT1 tag := bssgp_rx.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value;
271 var PDU_BSSGP bssgp_tx := valueof(t_BVC_FC_BVC_ACK(tag));
272 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, bvci, enc_PDU_BSSGP(bssgp_tx))));
273 if (not oneshot) { repeat; }
274 }
275}
276
277/**********************************************************************************
278 * Classic Gb/IP bring-up test cases using NS-{RESET,BLOCK,UNBLOCK} and no IP-SNS *
279 **********************************************************************************/
280
281/* Receive a NS-RESET and ACK it */
282private altstep as_rx_ns_reset_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
283 var NS_RecvFrom ns_rf;
284 [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_RESET(NS_CAUSE_OM_INTERVENTION, g_nsconfig[idx].nsvci,
285 g_nsconfig[idx].nsei))) -> value ns_rf {
286 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_RESET_ACK(g_nsconfig[idx].nsvci,
287 g_nsconfig[idx].nsei)));
288 if (not oneshot) { repeat; }
289 }
290}
291/* Receive a NS-UNBLOCK and ACK it */
292private altstep as_rx_ns_unblock_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
293 var NS_RecvFrom ns_rf;
294 [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_UNBLOCK)) -> value ns_rf {
295 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_UNBLOCK_ACK));
296 if (not oneshot) { repeat; }
297 }
298}
299
300/* test the NS-RESET procedure */
301testcase TC_ns_reset() runs on RAW_Test_CT {
302 f_init_ns_codec();
303 f_init_pcuif();
304
305
306 /* Expect inbound NS-RESET procedure */
307 as_rx_ns_reset_ack(oneshot := true);
308 setverdict(pass);
309}
310
311/* ensure NS-RESET are re-transmitted */
312testcase TC_ns_reset_retrans() runs on RAW_Test_CT {
313 f_init_ns_codec();
314 f_init_pcuif();
315
316 var integer i;
317 for (i := 0; i < 3; i := i+1) {
318 NSCP[0].receive(t_NS_RecvFrom(tr_NS_RESET(NS_CAUSE_OM_INTERVENTION,
319 g_nsconfig[0].nsvci, g_nsconfig[0].nsei)));
320 }
321
322 /* Expect inbound NS-RESET procedure */
323 as_rx_ns_reset_ack(oneshot := true);
324 setverdict(pass);
325}
326
327/* test the inbound NS-ALIVE procedure after NS-RESET */
328testcase TC_ns_alive() runs on RAW_Test_CT {
329 f_init_ns_codec();
330 f_init_pcuif();
331
332 /* Expect inbound NS-RESET procedure */
333 as_rx_ns_reset_ack(oneshot := true);
334
335 /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
336 as_rx_alive_tx_ack(oneshot := true);
337 setverdict(pass);
338}
339
340/* Test for NS-RESET after NS-ALIVE timeout */
341testcase TC_ns_alive_timeout_reset() runs on RAW_Test_CT {
342 f_init_ns_codec(guard_secs := 100.0);
343 f_init_pcuif();
344
345 /* Expect inbound NS-RESET procedure */
346 as_rx_ns_reset_ack(oneshot := true);
347
348 /* wait for at least one NS-ALIVE */
349 NSCP[0].receive(t_NS_RecvFrom(t_NS_ALIVE));
350
351 /* wait for NS-RESET to re-appear, ignoring any NS-ALIVE until then */
352 alt {
353 [] as_rx_ns_reset_ack(oneshot := true) { setverdict(pass); }
354 [] NSCP[0].receive(t_NS_RecvFrom(t_NS_ALIVE)) { repeat; }
355 }
356}
357
358/* test for NS-RESET/NS-ALIVE/NS-UNBLOCK */
359testcase TC_ns_unblock() runs on RAW_Test_CT {
360 f_init_ns_codec();
361 f_init_pcuif();
362
363 /* Expect inbound NS-RESET procedure */
364 as_rx_ns_reset_ack(oneshot := true);
365
366 /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
367 as_rx_alive_tx_ack(oneshot := true);
368 activate(as_rx_alive_tx_ack());
369
370 as_rx_ns_unblock_ack(oneshot := true);
371 setverdict(pass);
372}
373
374/* test for NS-UNBLOCK re-transmissions */
375testcase TC_ns_unblock_retrans() runs on RAW_Test_CT {
376 f_init_ns_codec();
377 f_init_pcuif();
378
379 /* Expect inbound NS-RESET procedure */
380 as_rx_ns_reset_ack(oneshot := true);
381
382 /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
383 as_rx_alive_tx_ack(oneshot := true);
384 activate(as_rx_alive_tx_ack());
385
386 /* wait for first NS-UNBLOCK, don't respond */
387 NSCP[0].receive(t_NS_RecvFrom(t_NS_UNBLOCK));
388
389 /* wait for re-transmission of NS-UNBLOCK */
390 as_rx_ns_unblock_ack(oneshot := true);
391 setverdict(pass);
392}
393
394/* full bring-up of the Gb link for NS and BSSGP layer up to BVC-FC */
395testcase TC_ns_full_bringup() runs on RAW_Test_CT {
396 f_init_ns_codec();
397 f_init_pcuif();
398
399 /* Expect inbound NS-RESET procedure */
400 as_rx_ns_reset_ack(oneshot := true);
401
402 /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
403 as_rx_alive_tx_ack(oneshot := true);
404 activate(as_rx_alive_tx_ack());
405
406 as_rx_ns_unblock_ack(oneshot := true);
407
408 f_outgoing_ns_alive();
409
410 /* Expect BVC-RESET for signaling (0) and ptp BVCI */
411 as_rx_bvc_reset_tx_ack(0, oneshot := true);
412 as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvci, oneshot := true);
413 as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvci, oneshot := true);
414
415 /* wait for one FLOW-CONTROL BVC and then ACK any further in the future */
416 as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci, oneshot := true);
417 activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci));
418 setverdict(pass);
419}
420
421/* test outbound (SGSN-originated) NS-BLOCK procedure */
422testcase TC_ns_so_block() runs on RAW_Test_CT {
423 f_init_ns_codec();
424 f_init_pcuif();
425
426 /* Expect inbound NS-RESET procedure */
427 as_rx_ns_reset_ack(oneshot := true);
428
429 /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
430 as_rx_alive_tx_ack(oneshot := true);
431 activate(as_rx_alive_tx_ack());
432
433 as_rx_ns_unblock_ack(oneshot := true);
434
435 f_outgoing_ns_alive();
436
437 f_outgoing_ns_block(NS_CAUSE_EQUIPMENT_FAILURE);
438 setverdict(pass);
439}
440
441
442control {
443 execute( TC_ns_reset() );
444 execute( TC_ns_reset_retrans() );
445 execute( TC_ns_alive() );
446 execute( TC_ns_alive_timeout_reset() );
447 execute( TC_ns_unblock() );
448 execute( TC_ns_unblock_retrans() );
449 execute( TC_ns_full_bringup() );
450 execute( TC_ns_so_block() );
451}
452
453}