blob: 0771cf98c94db70f254b73659f69ac481e1d1849 [file] [log] [blame]
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001module PCU_Tests_RAW {
2
3/* "RAW" PCU tests: Talk directly to the PCU socket of OsmoPCU on the one hand side (emulating
4 the BTS/BSC side PCU socket server) and the Gb interface on the other hand side. No NS/BSSGP
5 Emulation is used; rather, we simply use the NS_CodecPort to implement both standard and non-
6 standard procedures on the NS and BSSGP level. The goal of these tests is to test exactly
7 those NS and BSSGP implementations on the BSS (PCU) side. */
8
Harald Welte34b5a952019-05-27 11:54:11 +02009/* (C) 2018-2019 Harald Welte <laforge@gnumonks.org>
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +020010 * (C) 2019 Vadim Yanitskiy <axilirator@gmail.com>
Harald Welte34b5a952019-05-27 11:54:11 +020011 * All rights reserved.
12 *
13 * Released under the terms of GNU General Public License, Version 2 or
14 * (at your option) any later version.
15 *
16 * SPDX-License-Identifier: GPL-2.0-or-later
17 */
18
Harald Welte9fbcf4b2018-12-07 07:56:52 +010019import from General_Types all;
20import from Osmocom_Types all;
Harald Welte7fd25cf2019-03-21 22:14:02 +010021import from GSM_Types all;
22import from GSM_RR_Types all;
23
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +020024import from RLCMAC_CSN1_Types all;
25import from RLCMAC_Types all;
26
Harald Welte9fbcf4b2018-12-07 07:56:52 +010027import from NS_Types all;
28import from BSSGP_Types all;
29import from Osmocom_Gb_Types all;
30
31import from BSSGP_Emulation all; /* BssgpConfig */
32import from NS_Emulation all; /* NSConfiguration */
33
34import from UD_Types all;
35import from PCUIF_Types all;
36import from PCUIF_CodecPort all;
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +020037import from PCUIF_RAW_Components all;
Harald Welte9fbcf4b2018-12-07 07:56:52 +010038import from IPL4asp_Types all;
39import from NS_CodecPort all;
40import from NS_CodecPort_CtrlFunct all;
41import from Native_Functions all;
42import from PCU_Tests all;
43
44modulepar {
45 charstring mp_pcu_sock_path := PCU_SOCK_DEFAULT;
46}
47
48type component RAW_NS_CT {
49 /* UDP port towards the bottom (IUT) */
Harald Weltebf768242019-02-21 22:19:21 +010050 port NS_CODEC_PT NSCP[4];
51 var ConnectionId g_ns_conn_id[4] := {-1, -1, -1, -1};
52 var NSConfiguration g_nsconfig[4];
Harald Welte9fbcf4b2018-12-07 07:56:52 +010053 timer g_T_guard;
Harald Welteea3c7e92019-03-01 19:34:55 +010054}
Harald Welte9fbcf4b2018-12-07 07:56:52 +010055
Harald Welteea3c7e92019-03-01 19:34:55 +010056type component RAW_PCU_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +010057 /* PCUIF (we emulate the BTS part) */
58 port PCUIF_CODEC_PT PCU;
59 var ConnectionId g_pcu_conn_id := -1;
60}
61
Harald Welteea3c7e92019-03-01 19:34:55 +010062type component RAW_Test_CT extends RAW_NS_CT, RAW_PCU_CT {
63}
64
Harald Welte9fbcf4b2018-12-07 07:56:52 +010065private altstep as_Tguard() runs on RAW_NS_CT {
66 [] g_T_guard.timeout {
67 setverdict(fail, "Timeout of T_guard");
68 mtc.stop;
69 }
70}
71
Pau Espin Pedrolf787b092019-10-04 18:34:05 +020072/* FIXME: make sure to use parameters from mp_gb_cfg.cell_id in the PCU INFO IND */
73template (value) PCUIF_info_ind ts_PCUIF_INFO_default := {
74 version := PCU_IF_VERSION,
75 flags := c_PCUIF_Flags_default,
76 trx := valueof(ts_PCUIF_InfoTrxs_def),
77 bsic := 7,
78 mcc := 262,
79 mnc := 42,
80 mnc_3_digits := 0,
81 lac := 13135,
82 rac := 0,
83 nsei := mp_nsconfig.nsei,
84 nse_timer := { 3, 3, 3, 3, 30, 3, 10 },
85 cell_timer := { 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 },
86 cell_id := 20960,
87 repeat_time := 5 * 50,
88 repeat_count := 3,
89 bvci := mp_gb_cfg.bvci,
90 t3142 := 20,
91 t3169 := 5,
92 t3191 := 5,
93 t3193_10ms := 160,
94 t3195 := 5,
95 t3101 := 10,
96 t3103 := 4,
97 t3105 := 8,
98 cv_countdown := 15,
99 dl_tbf_ext := 250 * 10, /* ms */
100 ul_tbf_ext := 250 * 10, /* ms */
101 initial_cs := 2,
102 initial_mcs := 6,
103 nsvci := { mp_nsconfig.nsvci, 0 },
104 local_pprt := { mp_nsconfig.remote_udp_port, 0 },
105 remote_port := { mp_nsconfig.local_udp_port, 0 },
106 remote_ip := { f_inet_haddr(mp_nsconfig.local_ip) , '00000000'O }
107}
108
Harald Welteea3c7e92019-03-01 19:34:55 +0100109function f_init_pcuif() runs on RAW_PCU_CT {
Pau Espin Pedrolf787b092019-10-04 18:34:05 +0200110 var PCUIF_info_ind info_ind;
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100111 map(self:PCU, system:PCU);
112
Pau Espin Pedrolf787b092019-10-04 18:34:05 +0200113
114 info_ind := valueof(ts_PCUIF_INFO_default);
115
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100116 /* Connect the Unix Domain Socket */
117 g_pcu_conn_id := f_pcuif_listen(PCU, mp_pcu_sock_path);
118 PCU.receive(UD_connected:?);
119
120 /* Wait for PCU_VERSION and return INFO_IND */
121 PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_TXT_IND(0, PCU_VERSION, ?)));
122 /* FIXME: make sure to use parameters from mp_gb_cfg.cell_id in the PCU INFO IND */
Pau Espin Pedrolf787b092019-10-04 18:34:05 +0200123 var template PCUIF_Message info_ind_msg := ts_PCUIF_INFO_IND(0, info_ind);
124 PCU.send(t_SD_PCUIF(g_pcu_conn_id, info_ind_msg));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100125}
126
Harald Welte0466d162019-03-21 21:30:21 +0100127function f_pcuif_tx(template (value) PCUIF_Message msg) runs on RAW_PCU_CT {
128 PCU.send(t_SD_PCUIF(g_pcu_conn_id, msg));
129}
130
Harald Weltebf768242019-02-21 22:19:21 +0100131function f_init_ns_codec(integer idx := 0, float guard_secs := 60.0) runs on RAW_NS_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100132 var Result res;
Harald Weltebf768242019-02-21 22:19:21 +0100133
134 if (not g_T_guard.running) {
135 g_T_guard.start(guard_secs);
136 activate(as_Tguard());
137 }
138
139 if (not isbound(g_nsconfig) or not isbound(g_nsconfig[idx])) {
140 /* copy most parts from mp_nsconfig */
141 g_nsconfig[idx] := mp_nsconfig;
142 /* adjust those parts different for each NS-VC */
143 g_nsconfig[idx].nsvci := mp_nsconfig.nsvci + idx;
144 g_nsconfig[idx].local_udp_port := mp_nsconfig.local_udp_port + idx;
145 }
146
147 map(self:NSCP[idx], system:NSCP);
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100148 /* Connect the UDP socket */
Harald Weltebf768242019-02-21 22:19:21 +0100149 log("connecting NSCP[", idx, "] to ", g_nsconfig[idx]);
150 res := f_IPL4_connect(NSCP[idx], g_nsconfig[idx].remote_ip, g_nsconfig[idx].remote_udp_port,
151 g_nsconfig[idx].local_ip, g_nsconfig[idx].local_udp_port, 0, { udp := {}});
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100152 if (not ispresent(res.connId)) {
Harald Weltebf768242019-02-21 22:19:21 +0100153 setverdict(fail, "Could not connect NS UDP socket, check your configuration ", g_nsconfig[idx]);
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100154 mtc.stop;
155 }
Harald Weltebf768242019-02-21 22:19:21 +0100156 g_ns_conn_id[idx] := res.connId;
157
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100158}
159
Harald Weltebf768242019-02-21 22:19:21 +0100160function f_ns_exp(template PDU_NS exp_rx, integer idx := 0) runs on RAW_NS_CT return PDU_NS {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100161 var NS_RecvFrom nrf;
162 log("f_ns_exp() expecting ", exp_rx);
163 alt {
Harald Weltebf768242019-02-21 22:19:21 +0100164 [] NSCP[idx].receive(t_NS_RecvFrom(exp_rx)) -> value nrf { }
165 [] NSCP[idx].receive {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100166 setverdict(fail, "Received unexpected NS: ", nrf);
167 mtc.stop;
168 }
169 }
170 return nrf.msg;
171}
172
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100173/* perform outbound NS-ALIVE procedure */
Harald Weltebf768242019-02-21 22:19:21 +0100174function f_outgoing_ns_alive(integer idx := 0) runs on RAW_NS_CT {
175 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_ALIVE));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100176 alt {
Harald Weltebf768242019-02-21 22:19:21 +0100177 [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_ALIVE_ACK));
178 [] NSCP[idx].receive { repeat; }
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100179 }
180}
181
Harald Welteecd159e2019-03-16 13:36:07 +0100182/* perform outbound NS-ALIVE procedure */
183function f_outgoing_ns_alive_no_ack(integer idx := 0, float tout := 10.0) runs on RAW_NS_CT {
184 timer T := tout;
185 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_ALIVE));
186 T.start;
187 alt {
188 [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_ALIVE_ACK)) {
189 setverdict(fail, "Received unexpected NS-ALIVE ACK");
190 }
191 [] NSCP[idx].receive { repeat; }
192 [] T.timeout {
193 setverdict(pass);
194 }
195 }
196}
197
198/* ensure no matching message is received within 'tout' */
199function f_ensure_no_ns(template PDU_NS ns := ?, integer idx := 0, float tout := 3.0)
200runs on RAW_Test_CT {
201 timer T := tout;
202 T.start;
203 alt {
204 [] NSCP[idx].receive(t_NS_RecvFrom(ns)) {
205 setverdict(fail, "NS-ALIVE from unconfigured (possibly initial) endpoint");
206 }
207 [] T.timeout {
208 setverdict(pass);
209 }
210 }
211}
212
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100213/* perform outbound NS-BLOCK procedure */
Harald Weltebf768242019-02-21 22:19:21 +0100214function f_outgoing_ns_block(NsCause cause, integer idx := 0) runs on RAW_NS_CT {
215 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_BLOCK(cause, g_nsconfig[idx].nsvci)));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100216 alt {
Harald Weltebf768242019-02-21 22:19:21 +0100217 [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_BLOCK_ACK(g_nsconfig[idx].nsvci)));
218 [] NSCP[idx].receive { repeat; }
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100219 }
220}
221
222/* receive NS-ALIVE and ACK it */
Harald Weltebf768242019-02-21 22:19:21 +0100223altstep as_rx_alive_tx_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
224 [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_ALIVE)) {
225 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_ALIVE_ACK));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100226 if (not oneshot) { repeat; }
227 }
228}
229
Harald Welte64d07312019-03-20 09:48:39 +0100230/* Transmit BSSGP RESET for given BVCI and expect ACK */
231function f_tx_bvc_reset_rx_ack(BssgpBvci bvci, integer idx := 0, boolean exp_ack := true)
232runs on RAW_NS_CT {
233 var PDU_BSSGP bssgp_tx := valueof(ts_BVC_RESET(BSSGP_CAUSE_NET_SV_CAP_MOD_GT_ZERO_KBPS, bvci,
234 mp_gb_cfg.cell_id));
235 timer T := 5.0;
236 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx))));
237 T.start;
238 alt {
239 [exp_ack] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, 0,
240 decmatch tr_BVC_RESET_ACK(bvci, ?)))) {
241 setverdict(pass);
242 }
243 [exp_ack] T.timeout {
244 setverdict(fail, "No response to BVC-RESET");
245 }
246 [not exp_ack] T.timeout {
247 setverdict(pass);
248 }
249 [] NSCP[idx].receive { repeat; }
250 }
251}
252
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100253/* Receive a BSSGP RESET for given BVCI and ACK it */
Harald Weltebf768242019-02-21 22:19:21 +0100254altstep as_rx_bvc_reset_tx_ack(BssgpBvci bvci, boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100255 var NS_RecvFrom ns_rf;
256 /* FIXME: nail down received cell_id in match */
Harald Weltebf768242019-02-21 22:19:21 +0100257 [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, 0,
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100258 decmatch tr_BVC_RESET(?, bvci, ?))))
259 -> value ns_rf {
260 var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.msg.pDU_NS_Unitdata.nS_SDU);
261 var PDU_BSSGP bssgp_tx := valueof(ts_BVC_RESET_ACK(bvci, mp_gb_cfg.cell_id));
Harald Weltebf768242019-02-21 22:19:21 +0100262 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx))));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100263 if (not oneshot) { repeat; }
264 }
265}
266
267
268/* Receive a BSSGP UNBLOCK for given BVCI and ACK it */
Harald Weltebf768242019-02-21 22:19:21 +0100269altstep as_rx_bvc_unblock_tx_ack(BssgpBvci bvci, boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100270 var NS_RecvFrom ns_rf;
Harald Weltebf768242019-02-21 22:19:21 +0100271 [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, 0,
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100272 decmatch t_BVC_UNBLOCK(bvci))))
273 -> value ns_rf {
274 var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.msg.pDU_NS_Unitdata.nS_SDU);
275 var PDU_BSSGP bssgp_tx := valueof(t_BVC_UNBLOCK_ACK(bvci));
Harald Weltebf768242019-02-21 22:19:21 +0100276 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx))));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100277 if (not oneshot) { repeat; }
278 }
279}
280
281/* Receive a BSSGP FLOW-CONTROL-BVC and ACK it */
Harald Weltebf768242019-02-21 22:19:21 +0100282altstep as_rx_bvc_fc_tx_ack(BssgpBvci bvci, boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100283 var NS_RecvFrom ns_rf;
Harald Weltebf768242019-02-21 22:19:21 +0100284 [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, bvci,
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100285 decmatch tr_BVC_FC_BVC)))
286 -> value ns_rf {
287 var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.msg.pDU_NS_Unitdata.nS_SDU);
288 var OCT1 tag := bssgp_rx.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value;
289 var PDU_BSSGP bssgp_tx := valueof(t_BVC_FC_BVC_ACK(tag));
Harald Weltebf768242019-02-21 22:19:21 +0100290 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, bvci, enc_PDU_BSSGP(bssgp_tx))));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100291 if (not oneshot) { repeat; }
292 }
293}
294
295/**********************************************************************************
296 * Classic Gb/IP bring-up test cases using NS-{RESET,BLOCK,UNBLOCK} and no IP-SNS *
297 **********************************************************************************/
298
299/* Receive a NS-RESET and ACK it */
Harald Weltebf768242019-02-21 22:19:21 +0100300private altstep as_rx_ns_reset_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100301 var NS_RecvFrom ns_rf;
Harald Weltebf768242019-02-21 22:19:21 +0100302 [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_RESET(NS_CAUSE_OM_INTERVENTION, g_nsconfig[idx].nsvci,
303 g_nsconfig[idx].nsei))) -> value ns_rf {
304 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_RESET_ACK(g_nsconfig[idx].nsvci,
305 g_nsconfig[idx].nsei)));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100306 if (not oneshot) { repeat; }
307 }
308}
309/* Receive a NS-UNBLOCK and ACK it */
Harald Weltebf768242019-02-21 22:19:21 +0100310private altstep as_rx_ns_unblock_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100311 var NS_RecvFrom ns_rf;
Harald Weltebf768242019-02-21 22:19:21 +0100312 [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_UNBLOCK)) -> value ns_rf {
313 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_UNBLOCK_ACK));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100314 if (not oneshot) { repeat; }
315 }
316}
317
318/* test the NS-RESET procedure */
Harald Welteea3c7e92019-03-01 19:34:55 +0100319testcase TC_ns_reset() runs on RAW_Test_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100320 f_init_ns_codec();
321 f_init_pcuif();
322
323
324 /* Expect inbound NS-RESET procedure */
325 as_rx_ns_reset_ack(oneshot := true);
326 setverdict(pass);
327}
328
329/* ensure NS-RESET are re-transmitted */
Harald Welteea3c7e92019-03-01 19:34:55 +0100330testcase TC_ns_reset_retrans() runs on RAW_Test_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100331 f_init_ns_codec();
332 f_init_pcuif();
333
334 var integer i;
335 for (i := 0; i < 3; i := i+1) {
Harald Weltebf768242019-02-21 22:19:21 +0100336 NSCP[0].receive(t_NS_RecvFrom(tr_NS_RESET(NS_CAUSE_OM_INTERVENTION,
337 g_nsconfig[0].nsvci, g_nsconfig[0].nsei)));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100338 }
339
340 /* Expect inbound NS-RESET procedure */
341 as_rx_ns_reset_ack(oneshot := true);
342 setverdict(pass);
343}
344
345/* test the inbound NS-ALIVE procedure after NS-RESET */
Harald Welteea3c7e92019-03-01 19:34:55 +0100346testcase TC_ns_alive() runs on RAW_Test_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100347 f_init_ns_codec();
348 f_init_pcuif();
349
350 /* Expect inbound NS-RESET procedure */
351 as_rx_ns_reset_ack(oneshot := true);
352
353 /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
354 as_rx_alive_tx_ack(oneshot := true);
355 setverdict(pass);
356}
357
358/* Test for NS-RESET after NS-ALIVE timeout */
Harald Welteea3c7e92019-03-01 19:34:55 +0100359testcase TC_ns_alive_timeout_reset() runs on RAW_Test_CT {
Harald Weltebf768242019-02-21 22:19:21 +0100360 f_init_ns_codec(guard_secs := 100.0);
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100361 f_init_pcuif();
362
363 /* Expect inbound NS-RESET procedure */
364 as_rx_ns_reset_ack(oneshot := true);
365
366 /* wait for at least one NS-ALIVE */
Harald Weltebf768242019-02-21 22:19:21 +0100367 NSCP[0].receive(t_NS_RecvFrom(t_NS_ALIVE));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100368
369 /* wait for NS-RESET to re-appear, ignoring any NS-ALIVE until then */
370 alt {
371 [] as_rx_ns_reset_ack(oneshot := true) { setverdict(pass); }
Harald Weltebf768242019-02-21 22:19:21 +0100372 [] NSCP[0].receive(t_NS_RecvFrom(t_NS_ALIVE)) { repeat; }
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100373 }
374}
375
376/* test for NS-RESET/NS-ALIVE/NS-UNBLOCK */
Harald Welteea3c7e92019-03-01 19:34:55 +0100377testcase TC_ns_unblock() runs on RAW_Test_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100378 f_init_ns_codec();
379 f_init_pcuif();
380
381 /* Expect inbound NS-RESET procedure */
382 as_rx_ns_reset_ack(oneshot := true);
383
384 /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
385 as_rx_alive_tx_ack(oneshot := true);
386 activate(as_rx_alive_tx_ack());
387
388 as_rx_ns_unblock_ack(oneshot := true);
389 setverdict(pass);
390}
391
392/* test for NS-UNBLOCK re-transmissions */
Harald Welteea3c7e92019-03-01 19:34:55 +0100393testcase TC_ns_unblock_retrans() runs on RAW_Test_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100394 f_init_ns_codec();
395 f_init_pcuif();
396
397 /* Expect inbound NS-RESET procedure */
398 as_rx_ns_reset_ack(oneshot := true);
399
400 /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
401 as_rx_alive_tx_ack(oneshot := true);
402 activate(as_rx_alive_tx_ack());
403
404 /* wait for first NS-UNBLOCK, don't respond */
Harald Weltebf768242019-02-21 22:19:21 +0100405 NSCP[0].receive(t_NS_RecvFrom(t_NS_UNBLOCK));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100406
407 /* wait for re-transmission of NS-UNBLOCK */
408 as_rx_ns_unblock_ack(oneshot := true);
409 setverdict(pass);
410}
411
412/* full bring-up of the Gb link for NS and BSSGP layer up to BVC-FC */
Harald Welteea3c7e92019-03-01 19:34:55 +0100413testcase TC_ns_full_bringup() runs on RAW_Test_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100414 f_init_ns_codec();
415 f_init_pcuif();
416
417 /* Expect inbound NS-RESET procedure */
418 as_rx_ns_reset_ack(oneshot := true);
419
420 /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
421 as_rx_alive_tx_ack(oneshot := true);
422 activate(as_rx_alive_tx_ack());
423
424 as_rx_ns_unblock_ack(oneshot := true);
425
426 f_outgoing_ns_alive();
427
428 /* Expect BVC-RESET for signaling (0) and ptp BVCI */
429 as_rx_bvc_reset_tx_ack(0, oneshot := true);
430 as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvci, oneshot := true);
431 as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvci, oneshot := true);
432
433 /* wait for one FLOW-CONTROL BVC and then ACK any further in the future */
434 as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci, oneshot := true);
435 activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci));
436 setverdict(pass);
437}
438
439/* test outbound (SGSN-originated) NS-BLOCK procedure */
Harald Welteea3c7e92019-03-01 19:34:55 +0100440testcase TC_ns_so_block() runs on RAW_Test_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100441 f_init_ns_codec();
442 f_init_pcuif();
443
444 /* Expect inbound NS-RESET procedure */
445 as_rx_ns_reset_ack(oneshot := true);
446
447 /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
448 as_rx_alive_tx_ack(oneshot := true);
449 activate(as_rx_alive_tx_ack());
450
451 as_rx_ns_unblock_ack(oneshot := true);
452
453 f_outgoing_ns_alive();
454
455 f_outgoing_ns_block(NS_CAUSE_EQUIPMENT_FAILURE);
456 setverdict(pass);
457}
458
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200459type component RAW_PCU_Test_CT extends bssgp_CT {
460 /* Connection to the BTS component (one for now) */
461 port RAW_PCU_MSG_PT BTS;
462 /* Connection to the PCUIF component */
463 port RAW_PCU_MSG_PT PCUIF;
464
465 /* Guard timeout */
466 timer g_T_guard := 60.0;
467};
468
469private altstep as_Tguard_RAW() runs on RAW_PCU_Test_CT {
470 [] g_T_guard.timeout {
471 setverdict(fail, "Timeout of T_guard");
472 mtc.stop;
473 }
474}
475
Pau Espin Pedrolf787b092019-10-04 18:34:05 +0200476private function f_init_raw(charstring id, template (value) PCUIF_info_ind info_ind := ts_PCUIF_INFO_default)
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200477runs on RAW_PCU_Test_CT {
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200478 var RAW_PCUIF_CT vc_PCUIF;
479 var RAW_PCU_BTS_CT vc_BTS;
480
481 /* Start the guard timer */
482 g_T_guard.start;
483 activate(as_Tguard_RAW());
484
485 /* Init PCU interface component */
486 vc_PCUIF := RAW_PCUIF_CT.create("PCUIF-" & id);
487 connect(vc_PCUIF:MTC, self:PCUIF);
488 map(vc_PCUIF:PCU, system:PCU);
489
490 /* Create one BTS component (we may want more some day) */
491 vc_BTS := RAW_PCU_BTS_CT.create("BTS-" & id);
492 connect(vc_BTS:PCUIF, vc_PCUIF:BTS);
493 connect(vc_BTS:TC, self:BTS);
494
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200495 vc_PCUIF.start(f_PCUIF_CT_handler(mp_pcu_sock_path));
Pau Espin Pedrolf787b092019-10-04 18:34:05 +0200496 vc_BTS.start(f_BTS_CT_handler(0, valueof(info_ind)));
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200497
498 /* Wait until the BTS is ready (SI13 negotiated) */
499 BTS.receive(tr_RAW_PCU_EV(BTS_EV_SI13_NEGO));
500}
501
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200502/* FIXME: properly encode RA (see TS 24.060, table 11.2.5.2) */
503private function f_establish_tbf(out GsmRrMessage rr_imm_ass, uint8_t bts_nr := 0,
504 uint16_t ra := oct2int('3A'O), uint8_t is_11bit := 0,
505 PCUIF_BurstType burst_type := BURST_TYPE_0,
506 TimingAdvance ta := 0)
507runs on RAW_PCU_Test_CT return boolean {
508 var PCUIF_Message pcu_msg;
509 var GsmRrMessage rr_msg;
510 var uint32_t fn;
511 timer T;
512
513 /* FIXME: ask the BTS component to give us the current TDMA fn */
514 fn := 1337 + ta;
515
516 /* Send RACH.ind */
517 log("Sending RACH.ind on fn=", fn, " with RA=", ra, ", TA=", ta);
518 BTS.send(ts_PCUIF_RACH_IND(bts_nr := bts_nr,
519 ra := ra, is_11bit := is_11bit,
520 burst_type := burst_type,
521 fn := fn, arfcn := 871,
522 qta := ta * 4));
523
524 /* Expect Immediate (TBF) Assignment on TS0/AGCH */
525 T.start(2.0);
526 alt {
527 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := bts_nr, trx_nr := ?, ts_nr := 0,
528 sapi := PCU_IF_SAPI_AGCH, data := ?))
529 -> value pcu_msg {
530 rr_imm_ass := dec_GsmRrMessage(pcu_msg.u.data_req.data);
531 log("Rx Immediate Assignment: ", rr_imm_ass);
532
533 /* Make sure this assignment is for us
534 * TODO: Uplink or Downlink TBF? */
535 if (match(rr_imm_ass, tr_IMM_TBF_ASS(?, ra, fn))) {
536 setverdict(pass);
537 return true;
538 }
539
540 /* Not for us? Wait for more. */
541 repeat;
542 }
543 [] BTS.receive { repeat; }
544 [] T.timeout {
545 setverdict(fail, "Timeout waiting for Immediate Assignment");
546 }
547 }
548
549 return false;
550}
551
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200552private function f_imm_ass_verify_ul_tbf_ass(GsmRrMessage rr_imm_ass, out PacketUlAssign ul_tbf_ass)
553runs on RAW_PCU_Test_CT return boolean {
554
555 /* Make sure we received an UL TBF Assignment */
556 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
557 ul_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
558 log("Rx Uplink TBF assignment: ", ul_tbf_ass);
559 setverdict(pass);
560 } else {
561 setverdict(fail, "Failed to match UL TBF Assignment");
562 return false;
563 }
564
565 /* Make sure we have got a TBF with Dynamic Block Allocation */
566 if (ul_tbf_ass.dynamic == omit) {
567 setverdict(fail, "Single Block Allocation is not handled by ", testcasename());
568 return false;
569 }
570
571 return true;
572}
573
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200574/* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
575private function f_pcuif_tx_data_ind(octetstring data, int16_t lqual_cb := 0)
576runs on RAW_PCU_Test_CT {
577
578 BTS.send(ts_PCUIF_DATA_IND(bts_nr := 0, trx_nr := 0, ts_nr := 7, block_nr := 0,
579 sapi := PCU_IF_SAPI_PDTCH, data := data,
580 fn := 0, arfcn := 871, lqual_cb := lqual_cb));
581 BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PDTCH_BLOCK_SENT));
582}
583
584/* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
585private function f_pcuif_rx_data_req(out PCUIF_Message pcu_msg)
586runs on RAW_PCU_Test_CT {
587 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
588 sapi := PCU_IF_SAPI_PDTCH, fn := 0,
589 arfcn := 871, block_nr := 0));
590 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
591 sapi := PCU_IF_SAPI_PDTCH)) -> value pcu_msg;
592}
593
594private function f_tx_rlcmac_ul_block(template (value) RlcmacUlBlock ul_data, int16_t lqual_cb := 0)
595runs on RAW_PCU_Test_CT {
596 var octetstring data;
597 /* Encode the payload of DATA.ind */
598 data := enc_RlcmacUlBlock(valueof(ul_data));
599 data := f_pad_oct(data, 23, '00'O); /* CS-1 */
600
601 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
602 f_pcuif_tx_data_ind(data, lqual_cb);
603}
604
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200605private function f_tx_rlcmac_ul_n_blocks(PacketUlAssign ul_tbf_ass, integer num_blocks := 1)
606runs on RAW_PCU_Test_CT {
607 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
608 tfi := ul_tbf_ass.dynamic.tfi_assignment,
609 cv := num_blocks - 1, /* num UL blocks to be sent (to be overridden in loop) */
610 bsn := 0, /* TODO: what should be here? */
611 blocks := { /* To be generated in loop */ });
612
613 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
614 ul_data.data.tlli := '00000001'O;
615
616 for (var integer i := 0; i < num_blocks; i := i + 1) {
617 /* Prepare a new UL block (CV, random payload) */
618 ul_data.data.mac_hdr.countdown := (num_blocks - i - 1);
619 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
620 f_tx_rlcmac_ul_block(ul_data);
621 }
622}
623
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200624private function f_rx_rlcmac_dl_block(out RlcmacDlBlock dl_block)
625runs on RAW_PCU_Test_CT {
626 var PCUIF_Message pcu_msg;
627 f_pcuif_rx_data_req(pcu_msg);
628 dl_block := dec_RlcmacDlBlock(pcu_msg.u.data_req.data);
629}
630
631private function f_rx_rlcmac_dl_block_exp_ack_nack(out RlcmacDlBlock dl_block)
632runs on RAW_PCU_Test_CT {
633 f_rx_rlcmac_dl_block(dl_block);
634 if (not match(dl_block, tr_RLCMAC_ACK_NACK(ul_tfi := ?, tlli := ?))) {
635 setverdict(fail, "Failed to match Packet Uplink ACK / NACK");
636 mtc.stop;
637 }
638}
639
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200640private function f_rx_rlcmac_dl_block_exp_dummy(out RlcmacDlBlock dl_block)
641runs on RAW_PCU_Test_CT {
642 f_rx_rlcmac_dl_block(dl_block);
643 if (not match(dl_block, tr_RLCMAC_DUMMY_CTRL())) {
644 setverdict(fail, "Failed to match Packet DUMMY DL");
645 mtc.stop;
646 }
647}
648
Vadim Yanitskiy740ae762019-09-29 16:13:41 +0700649testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
650 var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.cell_id.ra_id);
651 var GprsTlli tlli := 'FFFFFFFF'O;
652 timer T;
653
654 /* Initialize NS/BSSGP side */
655 f_init_bssgp();
656
657 /* Initialize the PCU interface abstraction */
658 f_init_raw(testcasename());
659
660 /* Establish BSSGP connection to the PCU */
661 f_bssgp_establish();
662
663 BTS.send(ts_PCUIF_SUSP_REQ(0, tlli, ra_id, 0));
664
665 T.start(2.0);
666 alt {
667 [] BSSGP_SIG[0].receive(tr_BSSGP_SUSPEND(tlli, mp_gb_cfg.cell_id.ra_id)) {
668 setverdict(pass);
669 }
670 [] T.timeout {
671 setverdict(fail, "Timeout waiting for BSSGP SUSPEND");
672 }
673 }
674}
675
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200676/* Test of correct Timing Advance at the time of TBF establishment
677 * (derived from timing offset of the Access Burst). */
678testcase TC_ta_rach_imm_ass() runs on RAW_PCU_Test_CT {
679 var GsmRrMessage rr_msg;
680 var boolean ok;
681
682 /* Initialize the PCU interface abstraction */
683 f_init_raw(testcasename());
684
685 /* We cannot send too many TBF requests in a short time because
686 * at some point the PCU will fail to allocate a new TBF. */
687 for (var TimingAdvance ta := 0; ta < 64; ta := ta + 16) {
688 /* Establish an Uplink TBF (send RACH.ind with current TA) */
689 ok := f_establish_tbf(rr_msg, bts_nr := 0, ta := ta);
690 if (not ok) {
691 setverdict(fail, "Failed to establish an Uplink TBF");
692 mtc.stop;
693 }
694
695 /* Make sure Timing Advance IE matches out expectations */
696 if (match(rr_msg, tr_IMM_TBF_ASS(dl := false, ta := ta))) {
697 setverdict(pass);
698 }
699 }
700}
701
Vadim Yanitskiy1f72b0a2019-10-01 05:58:45 +0700702/* Verify that the PCU generates valid PTCCH/D messages
703 * while neither Uplink nor Downlink TBF is established. */
704testcase TC_ta_ptcch_idle() runs on RAW_PCU_Test_CT {
705 var PTCCHDownlinkMsg ptcch_msg;
706 var PCUIF_Message pcu_msg;
707 timer T;
708
709 /* Initialize the PCU interface abstraction */
710 f_init_raw(testcasename());
711
712 /* Sent an RTS.req for PTCCH/D */
713 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
714 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
715 arfcn := 871, block_nr := 0));
716 T.start(5.0);
717 alt {
718 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
719 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
720 log("Rx DATA.req message: ", pcu_msg);
721 setverdict(pass);
722 }
723 [] BTS.receive(PCUIF_Message:?) { repeat; }
724 [] T.timeout {
725 setverdict(fail, "Timeout waiting for a PTCCH/D block");
726 mtc.stop;
727 }
728 }
729
730 ptcch_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
731 log("Decoded PTCCH/D message: ", ptcch_msg);
732
733 /* Make sure the message is encoded correctly
734 * TODO: do we expect all TA values to be equal '1111111'B? */
735 if (not match(ptcch_msg, tr_PTCCHDownlinkMsg)) {
736 setverdict(fail, "Malformed PTCCH/D message");
737 mtc.stop;
738 }
739}
740
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700741/* Test of correct Timing Advance during an active Uplink TBF.
742 *
743 * Unlike the circuit-switched domain, Uplink transmissions on PDCH time-slots
744 * are not continuous and there can be long time gaps between them. This happens
745 * due to a bursty nature of packet data. The actual Timing Advance of a MS may
746 * significantly change between such rare Uplink transmissions, so GPRS introduces
747 * additional mechanisms to control Timing Advance, and thus reduce interference
748 * between neighboring TDMA time-slots.
749 *
750 * At the moment of Uplink TBF establishment, initial Timing Advance is measured
751 * from ToA (Timing of Arrival) of an Access Burst. This is covered by another
752 * test case - TC_ta_rach_imm_ass. In response to that Access Burst the network
753 * sends Immediate Assignment on AGCH, which _may_ contain Timing Advance Index
754 * among with the initial Timing Advance value. And here PTCCH comes to play.
755 *
756 * PTCCH is a unidirectional channel on which the network can instruct a sub-set
757 * of 16 MS (whether TBFs are active or not) to adjust their Timing Advance
758 * continuously. To ensure continuous measurements of the signal propagation
759 * delay, the MSs shall transmit Access Bursts on Uplink (PTCCH/U) on sub-slots
760 * defined by an assigned Timing Advance Index (see 3GPP TS 45.002).
761 *
762 * The purpose of this test case is to verify the assignment of Timing Advance
763 * Index, and the process of Timing Advance notification on PTCCH/D. The MTC
764 * first establishes several Uplink TBFs, but does not transmit any Uplink
765 * blocks on them. During 4 TDMA multi-frame periods the MTC is sending RACH
766 * indications to the PCU, checking the correctness of two received PTCCH/D
767 * messages (period of PTCCH/D is two multi-frames).
768 */
769private altstep as_ta_ptcch(uint8_t bts_nr := 0, integer toa_factor := 0)
770runs on RAW_PCU_Test_CT {
771 var integer counter := 0;
772 var RAW_PCU_Event event;
773
774 /* Send Access Bursts on PTCCH/U for every TA Index */
775 [] BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PTCCH_UL_BURST)) -> value event {
776 log("Sending an Access Burst on PTCCH/U",
777 ", fn=", event.data.tdma_fn,
778 ", ToA=", counter * toa_factor);
779 /* TODO: do we care about RA and burst format? */
780 BTS.send(ts_PCUIF_RACH_IND(bts_nr := bts_nr,
781 ra := oct2int('3A'O),
782 is_11bit := 0,
783 burst_type := BURST_TYPE_0,
784 fn := event.data.tdma_fn,
785 arfcn := 871,
786 qta := counter * toa_factor * 4,
787 sapi := PCU_IF_SAPI_PTCCH));
788 counter := counter + 1;
789 repeat;
790 }
791}
792
793private function f_TC_ta_ptcch_ul_multi_tbf(template PTCCHDownlinkMsg t_ta_msg)
794runs on RAW_PCU_Test_CT {
795 var PTCCHDownlinkMsg ta_msg;
796 var PCUIF_Message pcu_msg;
797 timer T;
798
799 /* First, send an RTS.req for the upcoming PTCCH/D block */
800 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
801 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
802 arfcn := 871, block_nr := 0));
803 T.start(2.0);
804 alt {
805 /* Keep sending of Access Bursts during two multi-frames (period of PTCCH/D)
806 * with increasing ToA (Timing of Arrival) values: 0, 7, 14, 28, 35... */
807 [] as_ta_ptcch(bts_nr := 0, toa_factor := 7);
808 /* In the end of 2nd multi-frame we should receive a PTCCH/D block */
809 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
810 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
811 ta_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
812 log("Rx PTCCH/D message: ", ta_msg);
813
814 /* Make sure Timing Advance values match our expectations */
815 if (match(ta_msg, t_ta_msg)) {
816 setverdict(pass);
817 } else {
818 setverdict(fail, "PTCCH/D message does not match: ", t_ta_msg);
819 }
820 }
821 [] BTS.receive { repeat; }
822 [] T.timeout {
823 setverdict(fail, "Timeout waiting for a PTCCH/D block");
824 mtc.stop;
825 }
826 }
827}
828
829testcase TC_ta_ptcch_ul_multi_tbf() runs on RAW_PCU_Test_CT {
830 var template PacketUlAssign t_ul_tbf_ass;
831 var PacketUlAssign ul_tbf_ass[7];
832 var GsmRrMessage rr_msg[7];
833 var boolean ok;
834
835 /* Initialize the PCU interface abstraction */
836 f_init_raw(testcasename());
837
838 /* Enable forwarding of PTCCH/U TDMA events to us */
839 BTS.send(ts_RAW_PCU_CMD(TDMA_CMD_ENABLE_PTCCH_UL_FWD));
840
841 /* Establish 7 Uplink TBFs (USF flag is 3 bits long, '111'B is reserved) */
842 for (var integer i := 0; i < 7; i := i + 1) {
843 ok := f_establish_tbf(rr_msg[i], ta := 0);
844 if (not ok) {
845 setverdict(fail, "Failed to establish an Uplink TBF #", i);
846 mtc.stop;
847 }
848
849 /* Make sure we received an UL TBF Assignment */
850 if (match(rr_msg[i], tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
851 ul_tbf_ass[i] := rr_msg[i].payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
852 log("Rx Uplink TBF assignment for #", i, ": ", ul_tbf_ass[i]);
853 } else {
854 setverdict(fail, "Failed to match UL TBF Assignment for #", i);
855 mtc.stop;
856 }
857
858 /* We expect incremental TFI/USF assignment (dynamic allocation) */
859 t_ul_tbf_ass := tr_PacketUlDynAssign(tfi := i, usf := i);
860 if (not match(ul_tbf_ass[i], t_ul_tbf_ass)) {
861 setverdict(fail, "Failed to match Packet Uplink Assignment for #", i);
862 mtc.stop;
863 }
864
865 /* We also expect Timing Advance Index to be a part of the assignment */
866 if (ul_tbf_ass[i].dynamic.ta_index != i) {
867 setverdict(fail, "Failed to match Timing Advance Index for #", i);
868 /* Keep going, the current OsmoPCU does not assign TA Index */
869 }
870 }
871
872 /* Now we have all 7 TBFs established in one-phase access mode,
873 * however we will not be sending any data on them. Instead, we
874 * will be sending RACH.ind on PTCCH/U during 4 multi-frame
875 * periods (TAI 0..8), and then will check two PTCCH/D blocks.
876 *
877 * Why not 4 TBFs at once? Because Uplink is delayed by 3 TDMA
878 * time-slots, so at the moment of scheduling a PTCCH/D block
879 * the PCU has odd number of PTCCH/U Access Bursts received. */
880 f_TC_ta_ptcch_ul_multi_tbf(tr_PTCCHDownlinkMsg(
881 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
882 /* Other values are not known (yet) */
883 tai3_ta := ?));
884 f_TC_ta_ptcch_ul_multi_tbf(tr_PTCCHDownlinkMsg(
885 /* Other values are out of our interest */
886 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
887 tai3_ta := 28, tai4_ta := 35, tai5_ta := 42,
888 /* Other values are not known (yet) */
889 tai6_ta := ?));
890}
891
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200892/* Default link quality adaptation (Coding Scheme) ranges:
893/* CS1: ... 6 dB, CS2: 5 .. 8 dB, CS3: 7 .. 13 db, CS4: 12 ... dB */
894private template integer CS1_lqual_dB_range := (-infinity .. 6);
895private template integer CS2_lqual_dB_range := (5 .. 8);
896private template integer CS3_lqual_dB_range := (7 .. 13);
897private template integer CS4_lqual_dB_range := (12 .. infinity);
898
899testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200900 var GsmRrMessage rr_imm_ass;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200901 var PacketUlAssign ul_tbf_ass;
902 var RlcmacDlBlock dl_block;
903 var PCUIF_Message pcu_msg;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200904 var octetstring data;
905 var boolean ok;
906
907 /* Initialize the PCU interface abstraction */
908 f_init_raw(testcasename());
909
910 /* Establish an Uplink TBF */
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200911 ok := f_establish_tbf(rr_imm_ass);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200912 if (not ok) {
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200913 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200914 mtc.stop;
915 }
916
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200917 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
918 if (not ok) {
919 setverdict(fail, "Immediate Assignment not an Uplink TBF");
Vadim Yanitskiy6276b6c2019-09-29 19:48:26 +0700920 mtc.stop;
921 }
922
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200923 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
924 tfi := ul_tbf_ass.dynamic.tfi_assignment,
925 cv := 15, /* 15 UL blocks to be sent (to be overridden in loop) */
926 bsn := 0, /* TODO: what should be here? */
927 blocks := { /* To be generated in loop */ });
928
929 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
930 ul_data.data.tlli := '00000001'O;
931
932 /* 16 UL blocks (0 .. 32 dB, step = 2 dB) */
933 for (var integer i := 0; i < 16; i := i + 1) {
934 /* Prepare a new UL block (CV, random payload) */
935 ul_data.data.mac_hdr.countdown := (15 - i);
936 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
937
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200938 /* Link quality in dB and our CS1-4 expectations */
939 var integer lqual := i * 2;
940
941 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
942 log("Sending DATA.ind with link quality (dB): ", lqual);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200943 f_tx_rlcmac_ul_block(ul_data, lqual * 10);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200944
945 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200946 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200947
948 log("Rx Packet Uplink ACK / NACK with Channel Coding Command: ",
949 dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd);
950
951 /* Match the received Channel Coding Command */
952 var template ChCodingCommand ch_coding;
953 select (lqual) {
954 case (CS1_lqual_dB_range) { ch_coding := CH_CODING_CS1; }
955 case (CS2_lqual_dB_range) { ch_coding := CH_CODING_CS2; }
956 case (CS3_lqual_dB_range) { ch_coding := CH_CODING_CS3; }
957 case (CS4_lqual_dB_range) { ch_coding := CH_CODING_CS4; }
958 }
959
960 if (not match(dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd, ch_coding)) {
961 setverdict(fail, "Channel Coding does not match our expectations: ", ch_coding);
962 } else {
963 setverdict(pass);
964 }
965 }
966}
967
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200968/* Verify PCU drops TBF after some time of inactivity. */
969testcase TC_t3169() runs on RAW_PCU_Test_CT {
970 var PCUIF_info_ind info_ind;
971 var GsmRrMessage rr_imm_ass;
972 var PacketUlAssign ul_tbf_ass;
973 var RlcmacDlBlock dl_block;
974 var PCUIF_Message pcu_msg;
975 var octetstring data;
976 var boolean ok;
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +0200977 var OCT4 tlli := '00000001'O;
978
979 /* Initialize NS/BSSGP side */
980 f_init_bssgp();
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200981
982 info_ind := valueof(ts_PCUIF_INFO_default);
983 /* Set timer to 1 sec (default 5) to speedup test: */
984 info_ind.t3169 := 1;
985
986 /* Initialize the PCU interface abstraction */
987 f_init_raw(testcasename(), info_ind);
988
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +0200989 /* Establish BSSGP connection to the PCU */
990 f_bssgp_establish();
991 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
992
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200993 /* Establish an Uplink TBF */
994 ok := f_establish_tbf(rr_imm_ass);
995 if (not ok) {
996 setverdict(fail, "Failed to establish TBF");
997 mtc.stop;
998 }
999
1000 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1001 if (not ok) {
1002 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1003 mtc.stop;
1004 }
1005
1006 /* Send one UL block and make sure it is ACKED fine */
1007 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1008 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block);
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001009 /* UL block should be received in SGSN */
1010 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001011
1012 /* Wait until T3169 fires (plus 1 extra sec to make sure) */
1013 f_sleep(int2float(info_ind.t3169) + 1.0);
1014
1015 /* Send an UL block once again, the TBF should be gone by now so no ACK */
1016 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1017 f_rx_rlcmac_dl_block_exp_dummy(dl_block);
1018}
1019
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001020
1021control {
1022 execute( TC_ns_reset() );
1023 execute( TC_ns_reset_retrans() );
1024 execute( TC_ns_alive() );
1025 execute( TC_ns_alive_timeout_reset() );
1026 execute( TC_ns_unblock() );
1027 execute( TC_ns_unblock_retrans() );
1028 execute( TC_ns_full_bringup() );
1029 execute( TC_ns_so_block() );
Harald Welte7fd25cf2019-03-21 22:14:02 +01001030
1031 execute( TC_pcuif_suspend() );
Vadim Yanitskiy1f72b0a2019-10-01 05:58:45 +07001032 execute( TC_ta_ptcch_idle() );
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +02001033 execute( TC_ta_rach_imm_ass() );
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001034 execute( TC_ta_ptcch_ul_multi_tbf() );
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001035 execute( TC_cs_lqual_ul_tbf() );
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001036 execute( TC_t3169() );
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001037}
1038
1039
1040
1041
1042
1043
1044}