blob: 2fc42c1e5742568f20d4ee01bcf1902133275595 [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
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +010024import from Osmocom_VTY_Functions all;
25import from TELNETasp_PortType all;
26
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +020027import from RLCMAC_CSN1_Types all;
28import from RLCMAC_Types all;
29
Harald Welte9fbcf4b2018-12-07 07:56:52 +010030import from NS_Types all;
31import from BSSGP_Types all;
32import from Osmocom_Gb_Types all;
33
34import from BSSGP_Emulation all; /* BssgpConfig */
35import from NS_Emulation all; /* NSConfiguration */
36
37import from UD_Types all;
38import from PCUIF_Types all;
39import from PCUIF_CodecPort all;
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +020040import from PCUIF_RAW_Components all;
Harald Welte9fbcf4b2018-12-07 07:56:52 +010041import from IPL4asp_Types all;
42import from NS_CodecPort all;
43import from NS_CodecPort_CtrlFunct all;
44import from Native_Functions all;
45import from PCU_Tests all;
46
47modulepar {
48 charstring mp_pcu_sock_path := PCU_SOCK_DEFAULT;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +010049
50 float X2002 := 0.2; /* Timer -2002, IMM ASSIGN confirm delay */
Harald Welte9fbcf4b2018-12-07 07:56:52 +010051}
52
53type component RAW_NS_CT {
54 /* UDP port towards the bottom (IUT) */
Harald Weltebf768242019-02-21 22:19:21 +010055 port NS_CODEC_PT NSCP[4];
56 var ConnectionId g_ns_conn_id[4] := {-1, -1, -1, -1};
57 var NSConfiguration g_nsconfig[4];
Harald Welte9fbcf4b2018-12-07 07:56:52 +010058 timer g_T_guard;
Harald Welteea3c7e92019-03-01 19:34:55 +010059}
Harald Welte9fbcf4b2018-12-07 07:56:52 +010060
Harald Welteea3c7e92019-03-01 19:34:55 +010061type component RAW_PCU_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +010062 /* PCUIF (we emulate the BTS part) */
63 port PCUIF_CODEC_PT PCU;
64 var ConnectionId g_pcu_conn_id := -1;
65}
66
Harald Welteea3c7e92019-03-01 19:34:55 +010067type component RAW_Test_CT extends RAW_NS_CT, RAW_PCU_CT {
68}
69
Harald Welte9fbcf4b2018-12-07 07:56:52 +010070private altstep as_Tguard() runs on RAW_NS_CT {
71 [] g_T_guard.timeout {
72 setverdict(fail, "Timeout of T_guard");
73 mtc.stop;
74 }
75}
76
Pau Espin Pedrolf787b092019-10-04 18:34:05 +020077/* FIXME: make sure to use parameters from mp_gb_cfg.cell_id in the PCU INFO IND */
78template (value) PCUIF_info_ind ts_PCUIF_INFO_default := {
79 version := PCU_IF_VERSION,
80 flags := c_PCUIF_Flags_default,
81 trx := valueof(ts_PCUIF_InfoTrxs_def),
82 bsic := 7,
83 mcc := 262,
84 mnc := 42,
85 mnc_3_digits := 0,
86 lac := 13135,
87 rac := 0,
88 nsei := mp_nsconfig.nsei,
89 nse_timer := { 3, 3, 3, 3, 30, 3, 10 },
90 cell_timer := { 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 },
91 cell_id := 20960,
92 repeat_time := 5 * 50,
93 repeat_count := 3,
94 bvci := mp_gb_cfg.bvci,
95 t3142 := 20,
96 t3169 := 5,
97 t3191 := 5,
98 t3193_10ms := 160,
99 t3195 := 5,
100 t3101 := 10,
101 t3103 := 4,
102 t3105 := 8,
103 cv_countdown := 15,
104 dl_tbf_ext := 250 * 10, /* ms */
105 ul_tbf_ext := 250 * 10, /* ms */
106 initial_cs := 2,
107 initial_mcs := 6,
108 nsvci := { mp_nsconfig.nsvci, 0 },
109 local_pprt := { mp_nsconfig.remote_udp_port, 0 },
110 remote_port := { mp_nsconfig.local_udp_port, 0 },
111 remote_ip := { f_inet_haddr(mp_nsconfig.local_ip) , '00000000'O }
112}
113
Harald Welteea3c7e92019-03-01 19:34:55 +0100114function f_init_pcuif() runs on RAW_PCU_CT {
Pau Espin Pedrolf787b092019-10-04 18:34:05 +0200115 var PCUIF_info_ind info_ind;
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100116 map(self:PCU, system:PCU);
117
Pau Espin Pedrolf787b092019-10-04 18:34:05 +0200118
119 info_ind := valueof(ts_PCUIF_INFO_default);
120
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100121 /* Connect the Unix Domain Socket */
122 g_pcu_conn_id := f_pcuif_listen(PCU, mp_pcu_sock_path);
123 PCU.receive(UD_connected:?);
124
125 /* Wait for PCU_VERSION and return INFO_IND */
126 PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_TXT_IND(0, PCU_VERSION, ?)));
127 /* 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 +0200128 var template PCUIF_Message info_ind_msg := ts_PCUIF_INFO_IND(0, info_ind);
129 PCU.send(t_SD_PCUIF(g_pcu_conn_id, info_ind_msg));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100130}
131
Harald Welte0466d162019-03-21 21:30:21 +0100132function f_pcuif_tx(template (value) PCUIF_Message msg) runs on RAW_PCU_CT {
133 PCU.send(t_SD_PCUIF(g_pcu_conn_id, msg));
134}
135
Harald Weltebf768242019-02-21 22:19:21 +0100136function f_init_ns_codec(integer idx := 0, float guard_secs := 60.0) runs on RAW_NS_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100137 var Result res;
Harald Weltebf768242019-02-21 22:19:21 +0100138
139 if (not g_T_guard.running) {
140 g_T_guard.start(guard_secs);
141 activate(as_Tguard());
142 }
143
144 if (not isbound(g_nsconfig) or not isbound(g_nsconfig[idx])) {
145 /* copy most parts from mp_nsconfig */
146 g_nsconfig[idx] := mp_nsconfig;
147 /* adjust those parts different for each NS-VC */
148 g_nsconfig[idx].nsvci := mp_nsconfig.nsvci + idx;
149 g_nsconfig[idx].local_udp_port := mp_nsconfig.local_udp_port + idx;
150 }
151
152 map(self:NSCP[idx], system:NSCP);
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100153 /* Connect the UDP socket */
Harald Weltebf768242019-02-21 22:19:21 +0100154 log("connecting NSCP[", idx, "] to ", g_nsconfig[idx]);
155 res := f_IPL4_connect(NSCP[idx], g_nsconfig[idx].remote_ip, g_nsconfig[idx].remote_udp_port,
156 g_nsconfig[idx].local_ip, g_nsconfig[idx].local_udp_port, 0, { udp := {}});
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100157 if (not ispresent(res.connId)) {
Harald Weltebf768242019-02-21 22:19:21 +0100158 setverdict(fail, "Could not connect NS UDP socket, check your configuration ", g_nsconfig[idx]);
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100159 mtc.stop;
160 }
Harald Weltebf768242019-02-21 22:19:21 +0100161 g_ns_conn_id[idx] := res.connId;
162
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100163}
164
Harald Weltebf768242019-02-21 22:19:21 +0100165function 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 +0100166 var NS_RecvFrom nrf;
167 log("f_ns_exp() expecting ", exp_rx);
168 alt {
Harald Weltebf768242019-02-21 22:19:21 +0100169 [] NSCP[idx].receive(t_NS_RecvFrom(exp_rx)) -> value nrf { }
170 [] NSCP[idx].receive {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100171 setverdict(fail, "Received unexpected NS: ", nrf);
172 mtc.stop;
173 }
174 }
175 return nrf.msg;
176}
177
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100178/* perform outbound NS-ALIVE procedure */
Harald Weltebf768242019-02-21 22:19:21 +0100179function f_outgoing_ns_alive(integer idx := 0) runs on RAW_NS_CT {
180 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_ALIVE));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100181 alt {
Harald Weltebf768242019-02-21 22:19:21 +0100182 [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_ALIVE_ACK));
183 [] NSCP[idx].receive { repeat; }
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100184 }
185}
186
Harald Welteecd159e2019-03-16 13:36:07 +0100187/* perform outbound NS-ALIVE procedure */
188function f_outgoing_ns_alive_no_ack(integer idx := 0, float tout := 10.0) runs on RAW_NS_CT {
189 timer T := tout;
190 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_ALIVE));
191 T.start;
192 alt {
193 [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_ALIVE_ACK)) {
194 setverdict(fail, "Received unexpected NS-ALIVE ACK");
195 }
196 [] NSCP[idx].receive { repeat; }
197 [] T.timeout {
198 setverdict(pass);
199 }
200 }
201}
202
203/* ensure no matching message is received within 'tout' */
204function f_ensure_no_ns(template PDU_NS ns := ?, integer idx := 0, float tout := 3.0)
205runs on RAW_Test_CT {
206 timer T := tout;
207 T.start;
208 alt {
209 [] NSCP[idx].receive(t_NS_RecvFrom(ns)) {
210 setverdict(fail, "NS-ALIVE from unconfigured (possibly initial) endpoint");
211 }
212 [] T.timeout {
213 setverdict(pass);
214 }
215 }
216}
217
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100218/* perform outbound NS-BLOCK procedure */
Harald Weltebf768242019-02-21 22:19:21 +0100219function f_outgoing_ns_block(NsCause cause, integer idx := 0) runs on RAW_NS_CT {
220 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 +0100221 alt {
Harald Weltebf768242019-02-21 22:19:21 +0100222 [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_BLOCK_ACK(g_nsconfig[idx].nsvci)));
223 [] NSCP[idx].receive { repeat; }
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100224 }
225}
226
227/* receive NS-ALIVE and ACK it */
Harald Weltebf768242019-02-21 22:19:21 +0100228altstep as_rx_alive_tx_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
229 [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_ALIVE)) {
230 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_ALIVE_ACK));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100231 if (not oneshot) { repeat; }
232 }
233}
234
Harald Welte64d07312019-03-20 09:48:39 +0100235/* Transmit BSSGP RESET for given BVCI and expect ACK */
236function f_tx_bvc_reset_rx_ack(BssgpBvci bvci, integer idx := 0, boolean exp_ack := true)
237runs on RAW_NS_CT {
238 var PDU_BSSGP bssgp_tx := valueof(ts_BVC_RESET(BSSGP_CAUSE_NET_SV_CAP_MOD_GT_ZERO_KBPS, bvci,
239 mp_gb_cfg.cell_id));
240 timer T := 5.0;
241 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx))));
242 T.start;
243 alt {
244 [exp_ack] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, 0,
245 decmatch tr_BVC_RESET_ACK(bvci, ?)))) {
246 setverdict(pass);
247 }
248 [exp_ack] T.timeout {
249 setverdict(fail, "No response to BVC-RESET");
250 }
251 [not exp_ack] T.timeout {
252 setverdict(pass);
253 }
254 [] NSCP[idx].receive { repeat; }
255 }
256}
257
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100258/* Receive a BSSGP RESET for given BVCI and ACK it */
Harald Weltebf768242019-02-21 22:19:21 +0100259altstep 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 +0100260 var NS_RecvFrom ns_rf;
261 /* FIXME: nail down received cell_id in match */
Harald Weltebf768242019-02-21 22:19:21 +0100262 [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, 0,
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100263 decmatch tr_BVC_RESET(?, bvci, ?))))
264 -> value ns_rf {
265 var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.msg.pDU_NS_Unitdata.nS_SDU);
266 var PDU_BSSGP bssgp_tx := valueof(ts_BVC_RESET_ACK(bvci, mp_gb_cfg.cell_id));
Harald Weltebf768242019-02-21 22:19:21 +0100267 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 +0100268 if (not oneshot) { repeat; }
269 }
270}
271
272
273/* Receive a BSSGP UNBLOCK for given BVCI and ACK it */
Harald Weltebf768242019-02-21 22:19:21 +0100274altstep 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 +0100275 var NS_RecvFrom ns_rf;
Harald Weltebf768242019-02-21 22:19:21 +0100276 [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, 0,
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100277 decmatch t_BVC_UNBLOCK(bvci))))
278 -> value ns_rf {
279 var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.msg.pDU_NS_Unitdata.nS_SDU);
280 var PDU_BSSGP bssgp_tx := valueof(t_BVC_UNBLOCK_ACK(bvci));
Harald Weltebf768242019-02-21 22:19:21 +0100281 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 +0100282 if (not oneshot) { repeat; }
283 }
284}
285
286/* Receive a BSSGP FLOW-CONTROL-BVC and ACK it */
Harald Weltebf768242019-02-21 22:19:21 +0100287altstep 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 +0100288 var NS_RecvFrom ns_rf;
Harald Weltebf768242019-02-21 22:19:21 +0100289 [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, bvci,
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100290 decmatch tr_BVC_FC_BVC)))
291 -> value ns_rf {
292 var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.msg.pDU_NS_Unitdata.nS_SDU);
293 var OCT1 tag := bssgp_rx.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value;
294 var PDU_BSSGP bssgp_tx := valueof(t_BVC_FC_BVC_ACK(tag));
Harald Weltebf768242019-02-21 22:19:21 +0100295 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 +0100296 if (not oneshot) { repeat; }
297 }
298}
299
300/**********************************************************************************
301 * Classic Gb/IP bring-up test cases using NS-{RESET,BLOCK,UNBLOCK} and no IP-SNS *
302 **********************************************************************************/
303
304/* Receive a NS-RESET and ACK it */
Harald Weltebf768242019-02-21 22:19:21 +0100305private altstep as_rx_ns_reset_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100306 var NS_RecvFrom ns_rf;
Harald Weltebf768242019-02-21 22:19:21 +0100307 [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_RESET(NS_CAUSE_OM_INTERVENTION, g_nsconfig[idx].nsvci,
308 g_nsconfig[idx].nsei))) -> value ns_rf {
309 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_RESET_ACK(g_nsconfig[idx].nsvci,
310 g_nsconfig[idx].nsei)));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100311 if (not oneshot) { repeat; }
312 }
313}
314/* Receive a NS-UNBLOCK and ACK it */
Harald Weltebf768242019-02-21 22:19:21 +0100315private altstep as_rx_ns_unblock_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100316 var NS_RecvFrom ns_rf;
Harald Weltebf768242019-02-21 22:19:21 +0100317 [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_UNBLOCK)) -> value ns_rf {
318 NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_UNBLOCK_ACK));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100319 if (not oneshot) { repeat; }
320 }
321}
322
323/* test the NS-RESET procedure */
Harald Welteea3c7e92019-03-01 19:34:55 +0100324testcase TC_ns_reset() runs on RAW_Test_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100325 f_init_ns_codec();
326 f_init_pcuif();
327
328
329 /* Expect inbound NS-RESET procedure */
330 as_rx_ns_reset_ack(oneshot := true);
331 setverdict(pass);
332}
333
334/* ensure NS-RESET are re-transmitted */
Harald Welteea3c7e92019-03-01 19:34:55 +0100335testcase TC_ns_reset_retrans() runs on RAW_Test_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100336 f_init_ns_codec();
337 f_init_pcuif();
338
339 var integer i;
340 for (i := 0; i < 3; i := i+1) {
Harald Weltebf768242019-02-21 22:19:21 +0100341 NSCP[0].receive(t_NS_RecvFrom(tr_NS_RESET(NS_CAUSE_OM_INTERVENTION,
342 g_nsconfig[0].nsvci, g_nsconfig[0].nsei)));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100343 }
344
345 /* Expect inbound NS-RESET procedure */
346 as_rx_ns_reset_ack(oneshot := true);
347 setverdict(pass);
348}
349
350/* test the inbound NS-ALIVE procedure after NS-RESET */
Harald Welteea3c7e92019-03-01 19:34:55 +0100351testcase TC_ns_alive() runs on RAW_Test_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100352 f_init_ns_codec();
353 f_init_pcuif();
354
355 /* Expect inbound NS-RESET procedure */
356 as_rx_ns_reset_ack(oneshot := true);
357
358 /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
359 as_rx_alive_tx_ack(oneshot := true);
360 setverdict(pass);
361}
362
363/* Test for NS-RESET after NS-ALIVE timeout */
Harald Welteea3c7e92019-03-01 19:34:55 +0100364testcase TC_ns_alive_timeout_reset() runs on RAW_Test_CT {
Harald Weltebf768242019-02-21 22:19:21 +0100365 f_init_ns_codec(guard_secs := 100.0);
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100366 f_init_pcuif();
367
368 /* Expect inbound NS-RESET procedure */
369 as_rx_ns_reset_ack(oneshot := true);
370
371 /* wait for at least one NS-ALIVE */
Harald Weltebf768242019-02-21 22:19:21 +0100372 NSCP[0].receive(t_NS_RecvFrom(t_NS_ALIVE));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100373
374 /* wait for NS-RESET to re-appear, ignoring any NS-ALIVE until then */
375 alt {
376 [] as_rx_ns_reset_ack(oneshot := true) { setverdict(pass); }
Harald Weltebf768242019-02-21 22:19:21 +0100377 [] NSCP[0].receive(t_NS_RecvFrom(t_NS_ALIVE)) { repeat; }
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100378 }
379}
380
381/* test for NS-RESET/NS-ALIVE/NS-UNBLOCK */
Harald Welteea3c7e92019-03-01 19:34:55 +0100382testcase TC_ns_unblock() runs on RAW_Test_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100383 f_init_ns_codec();
384 f_init_pcuif();
385
386 /* Expect inbound NS-RESET procedure */
387 as_rx_ns_reset_ack(oneshot := true);
388
389 /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
390 as_rx_alive_tx_ack(oneshot := true);
391 activate(as_rx_alive_tx_ack());
392
393 as_rx_ns_unblock_ack(oneshot := true);
394 setverdict(pass);
395}
396
397/* test for NS-UNBLOCK re-transmissions */
Harald Welteea3c7e92019-03-01 19:34:55 +0100398testcase TC_ns_unblock_retrans() runs on RAW_Test_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100399 f_init_ns_codec();
400 f_init_pcuif();
401
402 /* Expect inbound NS-RESET procedure */
403 as_rx_ns_reset_ack(oneshot := true);
404
405 /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
406 as_rx_alive_tx_ack(oneshot := true);
407 activate(as_rx_alive_tx_ack());
408
409 /* wait for first NS-UNBLOCK, don't respond */
Harald Weltebf768242019-02-21 22:19:21 +0100410 NSCP[0].receive(t_NS_RecvFrom(t_NS_UNBLOCK));
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100411
412 /* wait for re-transmission of NS-UNBLOCK */
413 as_rx_ns_unblock_ack(oneshot := true);
414 setverdict(pass);
415}
416
417/* full bring-up of the Gb link for NS and BSSGP layer up to BVC-FC */
Harald Welteea3c7e92019-03-01 19:34:55 +0100418testcase TC_ns_full_bringup() runs on RAW_Test_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100419 f_init_ns_codec();
420 f_init_pcuif();
421
422 /* Expect inbound NS-RESET procedure */
423 as_rx_ns_reset_ack(oneshot := true);
424
425 /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
426 as_rx_alive_tx_ack(oneshot := true);
427 activate(as_rx_alive_tx_ack());
428
429 as_rx_ns_unblock_ack(oneshot := true);
430
431 f_outgoing_ns_alive();
432
433 /* Expect BVC-RESET for signaling (0) and ptp BVCI */
434 as_rx_bvc_reset_tx_ack(0, oneshot := true);
435 as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvci, oneshot := true);
436 as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvci, oneshot := true);
437
438 /* wait for one FLOW-CONTROL BVC and then ACK any further in the future */
439 as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci, oneshot := true);
440 activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci));
441 setverdict(pass);
442}
443
444/* test outbound (SGSN-originated) NS-BLOCK procedure */
Harald Welteea3c7e92019-03-01 19:34:55 +0100445testcase TC_ns_so_block() runs on RAW_Test_CT {
Harald Welte9fbcf4b2018-12-07 07:56:52 +0100446 f_init_ns_codec();
447 f_init_pcuif();
448
449 /* Expect inbound NS-RESET procedure */
450 as_rx_ns_reset_ack(oneshot := true);
451
452 /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
453 as_rx_alive_tx_ack(oneshot := true);
454 activate(as_rx_alive_tx_ack());
455
456 as_rx_ns_unblock_ack(oneshot := true);
457
458 f_outgoing_ns_alive();
459
460 f_outgoing_ns_block(NS_CAUSE_EQUIPMENT_FAILURE);
461 setverdict(pass);
462}
463
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100464type record lqual_range {
465 /* component reference to the IPA_Client component used for RSL */
466 uint8_t low,
467 uint8_t high
468}
469
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200470type component RAW_PCU_Test_CT extends bssgp_CT {
471 /* Connection to the BTS component (one for now) */
472 port RAW_PCU_MSG_PT BTS;
473 /* Connection to the PCUIF component */
474 port RAW_PCU_MSG_PT PCUIF;
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100475 /* VTY connection to the PCU */
476 port TELNETasp_PT PCUVTY;
477
478 /* Uplink CS/MCS thresholds, default from pcu_main.c: */
479 var lqual_range g_cs_lqual_ranges[4] := {{low := 0, high := 6},
480 {low := 5, high := 8},
481 {low := 7, high := 13},
482 {low := 12,high := 35}};
483 var lqual_range g_mcs_lqual_ranges[9] := {{low := 0, high := 6},
484 {low := 5, high := 8},
485 {low := 7, high := 13},
486 {low := 12,high := 15},
487 {low := 14, high := 17},
488 {low := 16, high := 18},
489 {low := 17,high := 20},
490 {low := 19, high := 24},
491 {low := 23,high := 35}};
492 var uint8_t g_cs_initial_dl := 1;
493 var uint8_t g_cs_initial_ul := 1;
494 var uint8_t g_mcs_initial_dl := 1;
495 var uint8_t g_mcs_initial_ul := 1;
496 var uint8_t g_cs_max_dl := 4;
497 var uint8_t g_cs_max_ul := 4;
498 var uint8_t g_mcs_max_dl := 9;
499 var uint8_t g_mcs_max_ul := 9;
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200500
501 /* Guard timeout */
502 timer g_T_guard := 60.0;
503};
504
505private altstep as_Tguard_RAW() runs on RAW_PCU_Test_CT {
506 [] g_T_guard.timeout {
507 setverdict(fail, "Timeout of T_guard");
508 mtc.stop;
509 }
510}
511
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100512private function f_pcuvty_set_allowed_cs_mcs() runs on RAW_PCU_Test_CT {
513 f_vty_config2(PCUVTY, {"pcu"}, "cs " & int2str(g_cs_initial_dl) & " " & int2str(g_cs_initial_ul));
514 f_vty_config2(PCUVTY, {"pcu"}, "cs max " & int2str(g_cs_max_dl) & " " & int2str(g_cs_max_ul));
515
516 f_vty_config2(PCUVTY, {"pcu"}, "mcs " & int2str(g_mcs_initial_dl) & " " & int2str(g_mcs_initial_ul));
517 f_vty_config2(PCUVTY, {"pcu"}, "mcs max " & int2str(g_mcs_max_dl) & " " & int2str(g_mcs_max_ul));
518}
519
520private function f_pcuvty_set_link_quality_ranges() runs on RAW_PCU_Test_CT {
521 var charstring cmd;
522
523 cmd := "cs link-quality-ranges" &
524 " cs1 " & int2str(g_cs_lqual_ranges[0].high) &
525 " cs2 " & int2str(g_cs_lqual_ranges[1].low) & " " & int2str(g_cs_lqual_ranges[1].high) &
526 " cs3 " & int2str(g_cs_lqual_ranges[2].low) & " " & int2str(g_cs_lqual_ranges[2].high) &
527 " cs4 " & int2str(g_cs_lqual_ranges[3].low);
528 f_vty_config2(PCUVTY, {"pcu"}, cmd);
529
530 cmd := "mcs link-quality-ranges" &
531 " mcs1 " & int2str(g_mcs_lqual_ranges[0].high) &
532 " mcs2 " & int2str(g_mcs_lqual_ranges[1].low) & " " & int2str(g_mcs_lqual_ranges[1].high) &
533 " mcs3 " & int2str(g_mcs_lqual_ranges[2].low) & " " & int2str(g_mcs_lqual_ranges[2].high) &
534 " mcs4 " & int2str(g_mcs_lqual_ranges[3].low) & " " & int2str(g_mcs_lqual_ranges[3].high) &
535 " mcs5 " & int2str(g_mcs_lqual_ranges[4].low) & " " & int2str(g_mcs_lqual_ranges[4].high) &
536 " mcs6 " & int2str(g_mcs_lqual_ranges[5].low) & " " & int2str(g_mcs_lqual_ranges[5].high) &
537 " mcs7 " & int2str(g_mcs_lqual_ranges[6].low) & " " & int2str(g_mcs_lqual_ranges[6].high) &
538 " mcs8 " & int2str(g_mcs_lqual_ranges[7].low) & " " & int2str(g_mcs_lqual_ranges[7].high) &
539 " mcs9 " & int2str(g_mcs_lqual_ranges[8].low);
540 f_vty_config2(PCUVTY, {"pcu"}, cmd);
541}
542
543private function f_init_vty(charstring id) runs on RAW_PCU_Test_CT {
544 map(self:PCUVTY, system:PCUVTY);
545 f_vty_set_prompts(PCUVTY);
546 f_vty_transceive(PCUVTY, "enable");
547}
548
Pau Espin Pedrolf787b092019-10-04 18:34:05 +0200549private function f_init_raw(charstring id, template (value) PCUIF_info_ind info_ind := ts_PCUIF_INFO_default)
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200550runs on RAW_PCU_Test_CT {
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200551 var RAW_PCUIF_CT vc_PCUIF;
552 var RAW_PCU_BTS_CT vc_BTS;
553
554 /* Start the guard timer */
555 g_T_guard.start;
556 activate(as_Tguard_RAW());
557
558 /* Init PCU interface component */
559 vc_PCUIF := RAW_PCUIF_CT.create("PCUIF-" & id);
560 connect(vc_PCUIF:MTC, self:PCUIF);
561 map(vc_PCUIF:PCU, system:PCU);
562
563 /* Create one BTS component (we may want more some day) */
564 vc_BTS := RAW_PCU_BTS_CT.create("BTS-" & id);
565 connect(vc_BTS:PCUIF, vc_PCUIF:BTS);
566 connect(vc_BTS:TC, self:BTS);
567
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100568 f_init_vty(id);
569
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200570 vc_PCUIF.start(f_PCUIF_CT_handler(mp_pcu_sock_path));
Pau Espin Pedrolf787b092019-10-04 18:34:05 +0200571 vc_BTS.start(f_BTS_CT_handler(0, valueof(info_ind)));
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200572
573 /* Wait until the BTS is ready (SI13 negotiated) */
574 BTS.receive(tr_RAW_PCU_EV(BTS_EV_SI13_NEGO));
575}
576
Pau Espin Pedrol89486332019-12-05 14:05:46 +0100577template AckNackDescription t_AckNackDescription_init := {
578 final_ack := '0'B,
579 starting_seq_nr := 0,
580 receive_block_bitmap := '0000000000000000000000000000000000000000000000000000000000000000'B
581}
582
583/* TS 44.060 sec 12.3 Ack/Nack Description */
584private function f_acknackdesc_ack_block(inout AckNackDescription desc, uint7_t bsn, BIT1 final_ack := '0'B)
585{
586 var integer i;
587 var integer inc := bsn - desc.starting_seq_nr + 1;
588 /* Filling hole? */
589 if (bsn < desc.starting_seq_nr) {
590 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - (desc.starting_seq_nr - bsn)] := int2bit(1, 1);
591 return;
592 }
593
594 /* SSN is increased, and so RBB values need to be moved */
595 for (i := 0; i < lengthof(desc.receive_block_bitmap) - inc; i := i+1) {
596 desc.receive_block_bitmap[i] := desc.receive_block_bitmap[i + inc];
597 }
598 for (i := lengthof(desc.receive_block_bitmap) - inc; i < lengthof(desc.receive_block_bitmap) - 1; i := i+1) {
599 desc.receive_block_bitmap[i] := int2bit(0, 1);
600 }
601 /* Now we can set current bit and update SSN */
602 desc.starting_seq_nr := bsn + 1;
603 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - 1] := int2bit(1, 1);
604
605 /* Finally update the final_ack bit as requested: */
606 desc.final_ack := final_ack;
607}
608
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200609/* FIXME: properly encode RA (see TS 24.060, table 11.2.5.2) */
610private function f_establish_tbf(out GsmRrMessage rr_imm_ass, uint8_t bts_nr := 0,
611 uint16_t ra := oct2int('3A'O), uint8_t is_11bit := 0,
612 PCUIF_BurstType burst_type := BURST_TYPE_0,
613 TimingAdvance ta := 0)
614runs on RAW_PCU_Test_CT return boolean {
615 var PCUIF_Message pcu_msg;
616 var GsmRrMessage rr_msg;
617 var uint32_t fn;
618 timer T;
619
620 /* FIXME: ask the BTS component to give us the current TDMA fn */
621 fn := 1337 + ta;
622
623 /* Send RACH.ind */
624 log("Sending RACH.ind on fn=", fn, " with RA=", ra, ", TA=", ta);
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700625 BTS.send(ts_PCUIF_RACH_IND(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200626 ra := ra, is_11bit := is_11bit,
627 burst_type := burst_type,
628 fn := fn, arfcn := 871,
629 qta := ta * 4));
630
631 /* Expect Immediate (TBF) Assignment on TS0/AGCH */
632 T.start(2.0);
633 alt {
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700634 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200635 sapi := PCU_IF_SAPI_AGCH, data := ?))
636 -> value pcu_msg {
637 rr_imm_ass := dec_GsmRrMessage(pcu_msg.u.data_req.data);
638 log("Rx Immediate Assignment: ", rr_imm_ass);
639
640 /* Make sure this assignment is for us
641 * TODO: Uplink or Downlink TBF? */
642 if (match(rr_imm_ass, tr_IMM_TBF_ASS(?, ra, fn))) {
643 setverdict(pass);
644 return true;
645 }
646
647 /* Not for us? Wait for more. */
648 repeat;
649 }
650 [] BTS.receive { repeat; }
651 [] T.timeout {
652 setverdict(fail, "Timeout waiting for Immediate Assignment");
653 }
654 }
655
656 return false;
657}
658
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200659private function f_imm_ass_verify_ul_tbf_ass(GsmRrMessage rr_imm_ass, out PacketUlAssign ul_tbf_ass)
660runs on RAW_PCU_Test_CT return boolean {
661
662 /* Make sure we received an UL TBF Assignment */
663 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
664 ul_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
665 log("Rx Uplink TBF assignment: ", ul_tbf_ass);
666 setverdict(pass);
667 } else {
668 setverdict(fail, "Failed to match UL TBF Assignment");
669 return false;
670 }
671
672 /* Make sure we have got a TBF with Dynamic Block Allocation */
673 if (ul_tbf_ass.dynamic == omit) {
674 setverdict(fail, "Single Block Allocation is not handled by ", testcasename());
675 return false;
676 }
677
678 return true;
679}
680
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +0200681private function f_imm_ass_verify_dl_tbf_ass(GsmRrMessage rr_imm_ass, out PacketDlAssign dl_tbf_ass)
682runs on RAW_PCU_Test_CT return boolean {
683
684 /* Make sure we received a DL TBF Assignment */
685 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := true, rest := tr_IaRestOctets_DLAss(?)))) {
686 dl_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.dl;
687 log("Rx Downlink TBF assignment: ", dl_tbf_ass);
688 setverdict(pass);
689 } else {
690 setverdict(fail, "Failed to match DL TBF Assignment");
691 return false;
692 }
693
694 return true;
695}
696
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200697/* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100698private function f_pcuif_tx_data_ind(octetstring data, int16_t lqual_cb := 0, uint32_t fn := 0)
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200699runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100700 var template RAW_PCU_EventParam ev_param := {tdma_fn := ? };
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200701 BTS.send(ts_PCUIF_DATA_IND(bts_nr := 0, trx_nr := 0, ts_nr := 7, block_nr := 0,
702 sapi := PCU_IF_SAPI_PDTCH, data := data,
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100703 fn := fn, arfcn := 871, lqual_cb := lqual_cb));
704 if (fn != 0) {
705 ev_param := {tdma_fn := fn };
706 }
707 BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PDTCH_BLOCK_SENT, ev_param));
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200708}
709
710/* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
711private function f_pcuif_rx_data_req(out PCUIF_Message pcu_msg)
712runs on RAW_PCU_Test_CT {
713 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
714 sapi := PCU_IF_SAPI_PDTCH, fn := 0,
715 arfcn := 871, block_nr := 0));
716 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
717 sapi := PCU_IF_SAPI_PDTCH)) -> value pcu_msg;
718}
719
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +0200720/* Expect an Immediate Assignment (paging) from PCU on PCUIF on specified sapi. */
721private function f_pcuif_rx_pch_imm_tbf_ass(out GsmRrMessage rr_imm_ass)
722runs on RAW_PCU_Test_CT {
723 var PCUIF_Message pcu_msg;
724 var octetstring macblock;
725 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
726 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
727 /* First 3 bytes contain paging group: */
728 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
729 rr_imm_ass := dec_GsmRrMessage(macblock);
730 if (not match(rr_imm_ass, tr_IMM_TBF_ASS())) {
731 setverdict(fail, "Failed to match Immediate Assignment: ", rr_imm_ass);
732 mtc.stop;
733 }
734 BTS.send(ts_PCUIF_DATA_CNF(bts_nr := 0, trx_nr := 0, ts_nr := 0, block_nr := 0,
735 fn := 0, arfcn := 871, sapi := PCU_IF_SAPI_PCH, data := macblock));
736}
737
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100738private function f_tx_rlcmac_ul_block(template (value) RlcmacUlBlock ul_data, int16_t lqual_cb := 0, uint32_t fn := 0)
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200739runs on RAW_PCU_Test_CT {
740 var octetstring data;
741 /* Encode the payload of DATA.ind */
742 data := enc_RlcmacUlBlock(valueof(ul_data));
743 data := f_pad_oct(data, 23, '00'O); /* CS-1 */
744
745 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100746 f_pcuif_tx_data_ind(data, lqual_cb, fn);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200747}
748
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200749private function f_tx_rlcmac_ul_n_blocks(PacketUlAssign ul_tbf_ass, integer num_blocks := 1)
750runs on RAW_PCU_Test_CT {
751 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
752 tfi := ul_tbf_ass.dynamic.tfi_assignment,
753 cv := num_blocks - 1, /* num UL blocks to be sent (to be overridden in loop) */
754 bsn := 0, /* TODO: what should be here? */
755 blocks := { /* To be generated in loop */ });
756
757 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
758 ul_data.data.tlli := '00000001'O;
759
760 for (var integer i := 0; i < num_blocks; i := i + 1) {
761 /* Prepare a new UL block (CV, random payload) */
762 ul_data.data.mac_hdr.countdown := (num_blocks - i - 1);
763 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
764 f_tx_rlcmac_ul_block(ul_data);
765 }
766}
767
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100768private function f_rx_rlcmac_dl_block(out RlcmacDlBlock dl_block, out uint32_t dl_fn)
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200769runs on RAW_PCU_Test_CT {
770 var PCUIF_Message pcu_msg;
771 f_pcuif_rx_data_req(pcu_msg);
772 dl_block := dec_RlcmacDlBlock(pcu_msg.u.data_req.data);
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100773 dl_fn := pcu_msg.u.data_req.fn;
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200774}
775
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100776private function f_rx_rlcmac_dl_block_exp_ack_nack(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200777runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100778 var uint32_t dl_fn;
779
780 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Pau Espin Pedrol21659632019-12-02 19:12:08 +0100781 if (not match(dl_block, tr_RLCMAC_UL_ACK_NACK(ul_tfi := ?, tlli := ?))) {
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200782 setverdict(fail, "Failed to match Packet Uplink ACK / NACK");
783 mtc.stop;
784 }
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100785
786 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200787}
788
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200789private function f_rx_rlcmac_dl_block_exp_dummy(out RlcmacDlBlock dl_block)
790runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100791 var uint32_t dl_fn;
792
793 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200794 if (not match(dl_block, tr_RLCMAC_DUMMY_CTRL())) {
795 setverdict(fail, "Failed to match Packet DUMMY DL");
796 mtc.stop;
797 }
798}
799
Pau Espin Pedrolff8da192019-12-05 17:23:58 +0100800private function f_rx_rlcmac_dl_block_exp_pkt_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
801runs on RAW_PCU_Test_CT {
802 var uint32_t dl_fn;
803
804 f_rx_rlcmac_dl_block(dl_block, dl_fn);
805 if (not match(dl_block, tr_RLCMAC_DL_PACKET_ASS())) {
806 setverdict(fail, "Failed to match Packet Downlink Assignment");
807 mtc.stop;
808 }
809
810 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
811}
812
Pau Espin Pedrol89486332019-12-05 14:05:46 +0100813private function f_rx_rlcmac_dl_block_exp_data(out RlcmacDlBlock dl_block, out uint32_t ack_fn, octetstring data, template (present) uint7_t exp_bsn := ?)
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100814runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100815 var PCUIF_Message pcu_msg;
816 var uint32_t dl_fn;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100817 var template RlcmacDlBlock dl_template := tr_RLCMAC_DATA_RRBP;
818 dl_template.data.blocks := ?;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100819
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100820 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100821 if (not match(dl_block, dl_template)) {
822 setverdict(fail, "Failed to match Packet data: ", dl_block, " vs ", dl_template);
823 mtc.stop;
824 }
Pau Espin Pedrol6e3b6892019-12-04 19:24:16 +0100825
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100826 ack_fn := dl_fn + f_rrbp_fn_delay(dl_block.data.mac_hdr.mac_hdr.rrbp);
827
Pau Espin Pedrol89486332019-12-05 14:05:46 +0100828 if (not match(dl_block.data.mac_hdr.hdr_ext.bsn, exp_bsn)) {
829 setverdict(fail, "DL block BSN doesn't match: ",
830 dl_block.data.blocks[0].hdr.length_ind, " vs exp ", exp_bsn);
831 }
832
Pau Espin Pedrol6e3b6892019-12-04 19:24:16 +0100833 if (lengthof(dl_block.data.blocks) < 1) {
834 setverdict(fail, "DL block has no LLC payload: ", dl_block);
835 mtc.stop;
836 }
837
838 if (ispresent(dl_block.data.blocks[0].hdr) and dl_block.data.blocks[0].hdr.length_ind != lengthof(data)) {
839 setverdict(fail, "DL block has LLC header with wrong expected size: ",
840 dl_block.data.blocks[0].hdr.length_ind, " vs ", lengthof(data));
841 mtc.stop;
842 }
843
844 if (dl_block.data.blocks[0].payload != data) {
845 setverdict(fail, "Failed to match content of LLC payload in DL Block: ", dl_block, " vs ", data);
846 mtc.stop;
847 }
848
849 /* Check next data blocks contain dummy frames */
850 if (lengthof(dl_block.data.blocks) > 1 and substr(dl_block.data.blocks[1].payload, 0, 3) != '43C001'O) {
851 setverdict(fail, "Second data payload is not a dummy frame: ", dl_block.data.blocks[1].payload);
852 mtc.stop;
853 }
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100854}
855
Vadim Yanitskiy740ae762019-09-29 16:13:41 +0700856testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
857 var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.cell_id.ra_id);
858 var GprsTlli tlli := 'FFFFFFFF'O;
859 timer T;
860
861 /* Initialize NS/BSSGP side */
862 f_init_bssgp();
863
864 /* Initialize the PCU interface abstraction */
865 f_init_raw(testcasename());
866
867 /* Establish BSSGP connection to the PCU */
868 f_bssgp_establish();
869
870 BTS.send(ts_PCUIF_SUSP_REQ(0, tlli, ra_id, 0));
871
872 T.start(2.0);
873 alt {
874 [] BSSGP_SIG[0].receive(tr_BSSGP_SUSPEND(tlli, mp_gb_cfg.cell_id.ra_id)) {
875 setverdict(pass);
876 }
877 [] T.timeout {
878 setverdict(fail, "Timeout waiting for BSSGP SUSPEND");
879 }
880 }
881}
882
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200883/* Test of correct Timing Advance at the time of TBF establishment
884 * (derived from timing offset of the Access Burst). */
885testcase TC_ta_rach_imm_ass() runs on RAW_PCU_Test_CT {
886 var GsmRrMessage rr_msg;
887 var boolean ok;
888
889 /* Initialize the PCU interface abstraction */
890 f_init_raw(testcasename());
891
892 /* We cannot send too many TBF requests in a short time because
893 * at some point the PCU will fail to allocate a new TBF. */
894 for (var TimingAdvance ta := 0; ta < 64; ta := ta + 16) {
895 /* Establish an Uplink TBF (send RACH.ind with current TA) */
896 ok := f_establish_tbf(rr_msg, bts_nr := 0, ta := ta);
897 if (not ok) {
898 setverdict(fail, "Failed to establish an Uplink TBF");
899 mtc.stop;
900 }
901
902 /* Make sure Timing Advance IE matches out expectations */
903 if (match(rr_msg, tr_IMM_TBF_ASS(dl := false, ta := ta))) {
904 setverdict(pass);
905 }
906 }
907}
908
Vadim Yanitskiy1f72b0a2019-10-01 05:58:45 +0700909/* Verify that the PCU generates valid PTCCH/D messages
910 * while neither Uplink nor Downlink TBF is established. */
911testcase TC_ta_ptcch_idle() runs on RAW_PCU_Test_CT {
912 var PTCCHDownlinkMsg ptcch_msg;
913 var PCUIF_Message pcu_msg;
914 timer T;
915
916 /* Initialize the PCU interface abstraction */
917 f_init_raw(testcasename());
918
919 /* Sent an RTS.req for PTCCH/D */
920 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
921 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
922 arfcn := 871, block_nr := 0));
923 T.start(5.0);
924 alt {
925 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
926 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
927 log("Rx DATA.req message: ", pcu_msg);
928 setverdict(pass);
929 }
930 [] BTS.receive(PCUIF_Message:?) { repeat; }
931 [] T.timeout {
932 setverdict(fail, "Timeout waiting for a PTCCH/D block");
933 mtc.stop;
934 }
935 }
936
937 ptcch_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
938 log("Decoded PTCCH/D message: ", ptcch_msg);
939
940 /* Make sure the message is encoded correctly
941 * TODO: do we expect all TA values to be equal '1111111'B? */
942 if (not match(ptcch_msg, tr_PTCCHDownlinkMsg)) {
943 setverdict(fail, "Malformed PTCCH/D message");
944 mtc.stop;
945 }
946}
947
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700948/* Test of correct Timing Advance during an active Uplink TBF.
949 *
950 * Unlike the circuit-switched domain, Uplink transmissions on PDCH time-slots
951 * are not continuous and there can be long time gaps between them. This happens
952 * due to a bursty nature of packet data. The actual Timing Advance of a MS may
953 * significantly change between such rare Uplink transmissions, so GPRS introduces
954 * additional mechanisms to control Timing Advance, and thus reduce interference
955 * between neighboring TDMA time-slots.
956 *
957 * At the moment of Uplink TBF establishment, initial Timing Advance is measured
958 * from ToA (Timing of Arrival) of an Access Burst. This is covered by another
959 * test case - TC_ta_rach_imm_ass. In response to that Access Burst the network
960 * sends Immediate Assignment on AGCH, which _may_ contain Timing Advance Index
961 * among with the initial Timing Advance value. And here PTCCH comes to play.
962 *
963 * PTCCH is a unidirectional channel on which the network can instruct a sub-set
964 * of 16 MS (whether TBFs are active or not) to adjust their Timing Advance
965 * continuously. To ensure continuous measurements of the signal propagation
966 * delay, the MSs shall transmit Access Bursts on Uplink (PTCCH/U) on sub-slots
967 * defined by an assigned Timing Advance Index (see 3GPP TS 45.002).
968 *
969 * The purpose of this test case is to verify the assignment of Timing Advance
970 * Index, and the process of Timing Advance notification on PTCCH/D. The MTC
971 * first establishes several Uplink TBFs, but does not transmit any Uplink
972 * blocks on them. During 4 TDMA multi-frame periods the MTC is sending RACH
973 * indications to the PCU, checking the correctness of two received PTCCH/D
974 * messages (period of PTCCH/D is two multi-frames).
975 */
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700976
977/* List of ToA values for Access Bursts to be sent on PTCCH/U,
978 * each ToA (Timing of Arrival) value is in units of 1/4 of
979 * a symbol (i.e. 1 symbol is 4 QTA units). */
980type record length(16) of int16_t PTCCH_TAI_ToA_MAP;
981const PTCCH_TAI_ToA_MAP ptcch_toa_map_def := {
982 0, 0, 0, 0,
983 0, 0, 0, 0,
984 0, 0, 0, 0,
985 0, 0, 0, 0
986};
987
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700988private altstep as_ta_ptcch(uint8_t bts_nr := 0, uint8_t trx_nr := 0, uint8_t ts_nr := 7,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700989 in PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def)
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700990runs on RAW_PCU_Test_CT {
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700991 var RAW_PCU_Event event;
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700992 var integer ss;
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700993
994 /* Send Access Bursts on PTCCH/U for every TA Index */
995 [] BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PTCCH_UL_BURST)) -> value event {
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700996 ss := f_tdma_ptcch_fn2ss(event.data.tdma_fn);
997 if (ss < 0) { mtc.stop; } /* Shall not happen */
998
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700999 log("Sending an Access Burst on PTCCH/U",
Vadim Yanitskiy20f87002019-10-06 00:51:50 +07001000 ", sub-slot=", ss, " (TAI)",
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001001 ", fn=", event.data.tdma_fn,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +07001002 ", ToA=", toa_map[ss], " (QTA)");
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001003 /* TODO: do we care about RA and burst format? */
Vadim Yanitskiy36558d92019-11-17 02:23:51 +07001004 BTS.send(ts_PCUIF_RACH_IND(bts_nr, trx_nr, ts_nr,
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001005 ra := oct2int('3A'O),
1006 is_11bit := 0,
1007 burst_type := BURST_TYPE_0,
1008 fn := event.data.tdma_fn,
1009 arfcn := 871,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +07001010 qta := toa_map[ss],
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001011 sapi := PCU_IF_SAPI_PTCCH));
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001012 repeat;
1013 }
1014}
1015
Vadim Yanitskiy20f87002019-10-06 00:51:50 +07001016private function f_TC_ta_ptcch_ul_multi_tbf(in PTCCH_TAI_ToA_MAP ptcch_toa_map,
1017 template PTCCHDownlinkMsg t_ta_msg)
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001018runs on RAW_PCU_Test_CT {
1019 var PTCCHDownlinkMsg ta_msg;
1020 var PCUIF_Message pcu_msg;
1021 timer T;
1022
1023 /* First, send an RTS.req for the upcoming PTCCH/D block */
1024 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
1025 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
1026 arfcn := 871, block_nr := 0));
1027 T.start(2.0);
1028 alt {
1029 /* Keep sending of Access Bursts during two multi-frames (period of PTCCH/D)
1030 * with increasing ToA (Timing of Arrival) values: 0, 7, 14, 28, 35... */
Vadim Yanitskiy36558d92019-11-17 02:23:51 +07001031 [] as_ta_ptcch(bts_nr := 0, trx_nr := 0, ts_nr := 7, toa_map := ptcch_toa_map);
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001032 /* In the end of 2nd multi-frame we should receive a PTCCH/D block */
1033 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
1034 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
1035 ta_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
1036 log("Rx PTCCH/D message: ", ta_msg);
1037
1038 /* Make sure Timing Advance values match our expectations */
1039 if (match(ta_msg, t_ta_msg)) {
1040 setverdict(pass);
1041 } else {
1042 setverdict(fail, "PTCCH/D message does not match: ", t_ta_msg);
1043 }
1044 }
1045 [] BTS.receive { repeat; }
1046 [] T.timeout {
1047 setverdict(fail, "Timeout waiting for a PTCCH/D block");
1048 mtc.stop;
1049 }
1050 }
1051}
1052
1053testcase TC_ta_ptcch_ul_multi_tbf() runs on RAW_PCU_Test_CT {
1054 var template PacketUlAssign t_ul_tbf_ass;
1055 var PacketUlAssign ul_tbf_ass[7];
1056 var GsmRrMessage rr_msg[7];
1057 var boolean ok;
1058
1059 /* Initialize the PCU interface abstraction */
1060 f_init_raw(testcasename());
1061
1062 /* Enable forwarding of PTCCH/U TDMA events to us */
1063 BTS.send(ts_RAW_PCU_CMD(TDMA_CMD_ENABLE_PTCCH_UL_FWD));
1064
1065 /* Establish 7 Uplink TBFs (USF flag is 3 bits long, '111'B is reserved) */
1066 for (var integer i := 0; i < 7; i := i + 1) {
1067 ok := f_establish_tbf(rr_msg[i], ta := 0);
1068 if (not ok) {
1069 setverdict(fail, "Failed to establish an Uplink TBF #", i);
1070 mtc.stop;
1071 }
1072
1073 /* Make sure we received an UL TBF Assignment */
1074 if (match(rr_msg[i], tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
1075 ul_tbf_ass[i] := rr_msg[i].payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
1076 log("Rx Uplink TBF assignment for #", i, ": ", ul_tbf_ass[i]);
1077 } else {
1078 setverdict(fail, "Failed to match UL TBF Assignment for #", i);
1079 mtc.stop;
1080 }
1081
1082 /* We expect incremental TFI/USF assignment (dynamic allocation) */
1083 t_ul_tbf_ass := tr_PacketUlDynAssign(tfi := i, usf := i);
1084 if (not match(ul_tbf_ass[i], t_ul_tbf_ass)) {
1085 setverdict(fail, "Failed to match Packet Uplink Assignment for #", i);
1086 mtc.stop;
1087 }
1088
1089 /* We also expect Timing Advance Index to be a part of the assignment */
1090 if (ul_tbf_ass[i].dynamic.ta_index != i) {
1091 setverdict(fail, "Failed to match Timing Advance Index for #", i);
1092 /* Keep going, the current OsmoPCU does not assign TA Index */
1093 }
1094 }
1095
Vadim Yanitskiy20f87002019-10-06 00:51:50 +07001096 /* Prepare a list of ToA values for Access Bursts to be sent on PTCCH/U */
1097 var PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def;
1098 for (var integer i := 0; i < 7; i := i + 1) {
1099 /* ToA in units of 1/4 of a symbol */
1100 toa_map[i] := (i + 1) * 7 * 4;
1101 }
1102
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001103 /* Now we have all 7 TBFs established in one-phase access mode,
1104 * however we will not be sending any data on them. Instead, we
1105 * will be sending RACH.ind on PTCCH/U during 4 multi-frame
1106 * periods (TAI 0..8), and then will check two PTCCH/D blocks.
1107 *
1108 * Why not 4 TBFs at once? Because Uplink is delayed by 3 TDMA
1109 * time-slots, so at the moment of scheduling a PTCCH/D block
1110 * the PCU has odd number of PTCCH/U Access Bursts received. */
Vadim Yanitskiy20f87002019-10-06 00:51:50 +07001111 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001112 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
1113 /* Other values are not known (yet) */
1114 tai3_ta := ?));
Vadim Yanitskiy20f87002019-10-06 00:51:50 +07001115 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001116 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
1117 tai3_ta := 28, tai4_ta := 35, tai5_ta := 42,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +07001118 /* Other values are out of our interest */
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001119 tai6_ta := ?));
1120}
1121
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +07001122/* Default link quality adaptation (Coding Scheme) ranges (inclusive).
1123 * OsmoPCU (VTY): cs link-quality-ranges cs1 6 cs2 5 8 cs3 7 13 cs4 12
1124 *
1125 * NOTE: the ranges are intentionally overlapping because OsmoPCU
1126 * does not change CS/MCS on the range borders (5-6, 7-8, 12-13). */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001127private template integer CS1_lqual_dB_range := (-infinity .. 6);
1128private template integer CS2_lqual_dB_range := (5 .. 8);
1129private template integer CS3_lqual_dB_range := (7 .. 13);
1130private template integer CS4_lqual_dB_range := (12 .. infinity);
1131
1132testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +02001133 var GsmRrMessage rr_imm_ass;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001134 var PacketUlAssign ul_tbf_ass;
1135 var RlcmacDlBlock dl_block;
1136 var PCUIF_Message pcu_msg;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001137 var octetstring data;
1138 var boolean ok;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001139 var uint32_t unused_fn;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001140
1141 /* Initialize the PCU interface abstraction */
1142 f_init_raw(testcasename());
1143
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +01001144 f_pcuvty_set_allowed_cs_mcs();
1145 f_pcuvty_set_link_quality_ranges();
1146
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001147 /* Establish an Uplink TBF */
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +02001148 ok := f_establish_tbf(rr_imm_ass);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001149 if (not ok) {
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +02001150 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001151 mtc.stop;
1152 }
1153
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +02001154 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1155 if (not ok) {
1156 setverdict(fail, "Immediate Assignment not an Uplink TBF");
Vadim Yanitskiy6276b6c2019-09-29 19:48:26 +07001157 mtc.stop;
1158 }
1159
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001160 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1161 tfi := ul_tbf_ass.dynamic.tfi_assignment,
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001162 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001163 bsn := 0, /* TODO: what should be here? */
1164 blocks := { /* To be generated in loop */ });
1165
1166 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1167 ul_data.data.tlli := '00000001'O;
1168
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +07001169 /* The actual / old link quality values. We need to keep track of the old
1170 * (basically previous) link quality value, because OsmoPCU actually
1171 * changes the coding scheme if not only the actual, but also the old
1172 * value leaves the current link quality range (window). */
1173 var integer lqual := 0;
1174 var integer lqual_old;
1175
1176 /* 16 UL blocks (0 .. 15 dB, step = 1 dB) */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001177 for (var integer i := 0; i < 16; i := i + 1) {
1178 /* Prepare a new UL block (CV, random payload) */
1179 ul_data.data.mac_hdr.countdown := (15 - i);
1180 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1181
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +07001182 /* Update the old / actual link quality */
1183 lqual_old := lqual;
1184 lqual := i;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001185
1186 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1187 log("Sending DATA.ind with link quality (dB): ", lqual);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +02001188 f_tx_rlcmac_ul_block(ul_data, lqual * 10);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001189
1190 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001191 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001192
1193 log("Rx Packet Uplink ACK / NACK with Channel Coding Command: ",
1194 dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd);
1195
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +07001196 /* Match the received Channel Coding Command. Since we are increasing
1197 * the link quality value on each iteration and not decreasing, there
1198 * is no need to check the both old and current link quality values. */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001199 var template ChCodingCommand ch_coding;
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +07001200 select (lqual_old) {
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001201 case (CS1_lqual_dB_range) { ch_coding := CH_CODING_CS1; }
1202 case (CS2_lqual_dB_range) { ch_coding := CH_CODING_CS2; }
1203 case (CS3_lqual_dB_range) { ch_coding := CH_CODING_CS3; }
1204 case (CS4_lqual_dB_range) { ch_coding := CH_CODING_CS4; }
1205 }
1206
1207 if (not match(dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd, ch_coding)) {
1208 setverdict(fail, "Channel Coding does not match our expectations: ", ch_coding);
1209 } else {
1210 setverdict(pass);
1211 }
1212 }
1213}
1214
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001215/* Test the max UL CS set by VTY works fine */
1216testcase TC_cs_initial_ul() runs on RAW_PCU_Test_CT {
1217 var GsmRrMessage rr_imm_ass;
1218 var PacketUlAssign ul_tbf_ass;
1219 var RlcmacDlBlock dl_block;
1220 var boolean ok;
1221 var integer lqual_cb;
1222 var ChCodingCommand last_ch_coding;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001223 var uint32_t unused_fn;
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001224
1225 /* Initialize the PCU interface abstraction */
1226 f_init_raw(testcasename());
1227
1228 /* Set initial UL CS to 3 */
1229 g_cs_initial_ul := 3;
1230 f_pcuvty_set_allowed_cs_mcs();
1231 f_pcuvty_set_link_quality_ranges();
1232
1233 /* Take lqual (dB->cB) so that we stay in that CS */
1234 lqual_cb := g_cs_lqual_ranges[2].low * 10;
1235
1236 /* Establish an Uplink TBF */
1237 ok := f_establish_tbf(rr_imm_ass);
1238 if (not ok) {
1239 setverdict(fail, "Failed to establish TBF");
1240 mtc.stop;
1241 }
1242
1243 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1244 if (not ok) {
1245 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1246 mtc.stop;
1247 }
1248
1249 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1250 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1251 cv := 3, /* 8 UL blocks to be sent (to be overridden in loop) */
1252 bsn := 0, /* TODO: what should be here? */
1253 blocks := { /* To be generated in loop */ });
1254
1255 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1256 ul_data.data.tlli := '00000001'O;
1257
1258 /* 3 UL blocks, check we are in same initial CS: */
1259 for (var integer i := 0; i < 3; i := i + 1) {
1260 /* Prepare a new UL block (CV, random payload) */
1261 ul_data.data.mac_hdr.countdown := (7 - i);
1262 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1263
1264 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1265 f_tx_rlcmac_ul_block(ul_data, lqual_cb);
1266
1267 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001268 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001269 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1270 }
1271
1272 if (last_ch_coding != CH_CODING_CS3) {
1273 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
1274 mtc.stop;
1275 }
1276
1277 setverdict(pass);
1278
1279 /* Remaining UL blocks are used to make sure regardless of initial
1280 /* lqual, we can go lower at any time */
1281
1282 /* 5 UL blocks, check we are in same initial CS: */
1283 for (var integer i := 3; i < 8; i := i + 1) {
1284 /* Prepare a new UL block (CV, random payload) */
1285 ul_data.data.mac_hdr.countdown := (7 - i);
1286 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1287
1288 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1289 f_tx_rlcmac_ul_block(ul_data, 0); /* 0 dB, make sure we downgrade CS */
1290
1291 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001292 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001293
1294 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1295 }
1296
1297 if (last_ch_coding != CH_CODING_CS1) {
1298 setverdict(fail, "Channel Coding does not match our expectations (CS-1): ", last_ch_coding);
1299 } else {
1300 setverdict(pass);
1301 }
1302}
1303
1304/* Test the max UL CS set by VTY works fine */
1305testcase TC_cs_max_ul() runs on RAW_PCU_Test_CT {
1306 var GsmRrMessage rr_imm_ass;
1307 var PacketUlAssign ul_tbf_ass;
1308 var RlcmacDlBlock dl_block;
1309 var boolean ok;
1310 var ChCodingCommand last_ch_coding;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001311 var uint32_t unused_fn;
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001312
1313 /* Initialize the PCU interface abstraction */
1314 f_init_raw(testcasename());
1315
1316 /* Set maximum allowed UL CS to 3 */
1317 g_cs_max_ul := 3;
1318 f_pcuvty_set_allowed_cs_mcs();
1319 f_pcuvty_set_link_quality_ranges();
1320
1321 /* Establish an Uplink TBF */
1322 ok := f_establish_tbf(rr_imm_ass);
1323 if (not ok) {
1324 setverdict(fail, "Failed to establish TBF");
1325 mtc.stop;
1326 }
1327
1328 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1329 if (not ok) {
1330 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1331 mtc.stop;
1332 }
1333
1334 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1335 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1336 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
1337 bsn := 0, /* TODO: what should be here? */
1338 blocks := { /* To be generated in loop */ });
1339
1340 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1341 ul_data.data.tlli := '00000001'O;
1342
1343 /* 16 UL blocks */
1344 for (var integer i := 0; i < 16; i := i + 1) {
1345 /* Prepare a new UL block (CV, random payload) */
1346 ul_data.data.mac_hdr.countdown := (15 - i);
1347 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1348
1349 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1350 f_tx_rlcmac_ul_block(ul_data, 40*10); /* 40 dB */
1351
1352 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001353 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001354
1355 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1356 }
1357
1358 if (last_ch_coding != CH_CODING_CS3) {
1359 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
1360 } else {
1361 setverdict(pass);
1362 }
1363}
1364
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001365/* Verify PCU drops TBF after some time of inactivity. */
1366testcase TC_t3169() runs on RAW_PCU_Test_CT {
1367 var PCUIF_info_ind info_ind;
1368 var GsmRrMessage rr_imm_ass;
1369 var PacketUlAssign ul_tbf_ass;
1370 var RlcmacDlBlock dl_block;
1371 var PCUIF_Message pcu_msg;
1372 var octetstring data;
1373 var boolean ok;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001374 var uint32_t unused_fn;
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001375 var OCT4 tlli := '00000001'O;
1376
1377 /* Initialize NS/BSSGP side */
1378 f_init_bssgp();
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001379
1380 info_ind := valueof(ts_PCUIF_INFO_default);
1381 /* Set timer to 1 sec (default 5) to speedup test: */
1382 info_ind.t3169 := 1;
1383
1384 /* Initialize the PCU interface abstraction */
1385 f_init_raw(testcasename(), info_ind);
1386
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001387 /* Establish BSSGP connection to the PCU */
1388 f_bssgp_establish();
1389 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1390
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001391 /* Establish an Uplink TBF */
1392 ok := f_establish_tbf(rr_imm_ass);
1393 if (not ok) {
1394 setverdict(fail, "Failed to establish TBF");
1395 mtc.stop;
1396 }
1397
1398 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1399 if (not ok) {
1400 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1401 mtc.stop;
1402 }
1403
1404 /* Send one UL block and make sure it is ACKED fine */
1405 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001406 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001407 /* UL block should be received in SGSN */
1408 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001409
1410 /* Wait until T3169 fires (plus 1 extra sec to make sure) */
1411 f_sleep(int2float(info_ind.t3169) + 1.0);
1412
1413 /* Send an UL block once again, the TBF should be gone by now so no ACK */
1414 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1415 f_rx_rlcmac_dl_block_exp_dummy(dl_block);
1416}
1417
Pau Espin Pedrolff8da192019-12-05 17:23:58 +01001418/* Verify that a Downlink TBF can be assigned using PACCH shortly after the
1419 * release of prev DL TBF due to MS staying in PDCH for a while (T3192, in PCU
1420 * T3193) after DL TBF release */
1421testcase TC_t3193() runs on RAW_PCU_Test_CT {
1422 var GsmRrMessage rr_imm_ass;
1423 var PacketDlAssign dl_tbf_ass;
1424 var RlcmacDlBlock dl_block;
1425 var octetstring data := f_rnd_octstring(10);
1426 var boolean ok;
1427 var uint32_t sched_fn;
1428 var OCT4 tlli := '00000001'O;
1429 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1430
1431 /* Initialize NS/BSSGP side */
1432 f_init_bssgp();
1433
1434 /* Initialize the PCU interface abstraction */
1435 f_init_raw(testcasename());
1436
1437 /* Establish BSSGP connection to the PCU */
1438 f_bssgp_establish();
1439 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1440
1441 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1442 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1443 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1444 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1445 if (not ok) {
1446 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1447 mtc.stop;
1448 }
1449 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1450 f_sleep(X2002);
1451 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1452
1453 /* ACK the DL block */
1454 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1455 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1456 /* we are done with the DL-TBF here so far, let's clean up our local state: */
1457 ack_nack_desc := valueof(t_AckNackDescription_init)
1458
1459 /* Now that final DL block is ACKED and TBF is released, T3193 in PCU
1460 (T3192 in MS) was started and until it fires the MS will be abailable
1461 on PDCH in case new data arrives from SGSN. Let's verify it: */
1462 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1463 f_rx_rlcmac_dl_block_exp_pkt_ass(dl_block, sched_fn);
1464 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1465
1466 /* Now that we confirmed the new assignment in the dl-tbf, lets receive the data and ack it */
1467 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1468 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1469 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1470}
1471
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001472/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1473 * answered, so TBFs for uplink and later for downlink are created.
1474 */
1475testcase TC_mo_ping_pong() runs on RAW_PCU_Test_CT {
1476 var GsmRrMessage rr_imm_ass;
1477 var PacketUlAssign ul_tbf_ass;
1478 var PacketDlAssign dl_tbf_ass;
1479 var RlcmacDlBlock dl_block;
1480 var PCUIF_Message pcu_msg;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001481 var octetstring data := f_rnd_octstring(10);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001482 var boolean ok;
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +01001483 var uint32_t sched_fn;
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001484 var OCT4 tlli := '00000001'O;
Pau Espin Pedrol89486332019-12-05 14:05:46 +01001485 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001486
1487 /* Initialize NS/BSSGP side */
1488 f_init_bssgp();
1489
1490 /* Initialize the PCU interface abstraction */
1491 f_init_raw(testcasename());
1492
1493 /* Establish BSSGP connection to the PCU */
1494 f_bssgp_establish();
1495 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1496
1497 /* Establish an Uplink TBF */
1498 ok := f_establish_tbf(rr_imm_ass);
1499 if (not ok) {
1500 setverdict(fail, "Failed to establish TBF");
1501 mtc.stop;
1502 }
1503 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1504 if (not ok) {
1505 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1506 mtc.stop;
1507 }
1508
1509 /* Send one UL block and make sure it is ACKED fine */
1510 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001511 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1512 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1513 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001514
1515 /* UL block should be received in SGSN */
1516 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1517
1518 /* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001519 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001520 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1521
1522 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1523 if (not ok) {
1524 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1525 mtc.stop;
1526 }
1527
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001528 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1529 f_sleep(X2002);
Pau Espin Pedrol89486332019-12-05 14:05:46 +01001530 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001531
1532 /* ACK the DL block */
Pau Espin Pedrol89486332019-12-05 14:05:46 +01001533 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +01001534 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001535}
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001536
Pau Espin Pedrola7b75662019-12-05 16:39:55 +01001537/* Verify that if PCU doesn't get an ACK for first DL block after IMM ASS, it
1538 * will retry by retransmitting both the IMM ASS + DL block after poll (ack)
1539 * timeout occurs (specified by sent RRBP on DL block). */
1540testcase TC_imm_ass_dl_block_retrans() runs on RAW_PCU_Test_CT {
1541 var GsmRrMessage rr_imm_ass;
1542 var PacketDlAssign dl_tbf_ass;
1543 var RlcmacDlBlock dl_block;
1544 var octetstring data := f_rnd_octstring(10);
1545 var boolean ok;
1546 var uint32_t sched_fn;
1547 var OCT4 tlli := '00000001'O;
1548 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1549
1550 /* Initialize NS/BSSGP side */
1551 f_init_bssgp();
1552
1553 /* Initialize the PCU interface abstraction */
1554 f_init_raw(testcasename());
1555
1556 /* Establish BSSGP connection to the PCU */
1557 f_bssgp_establish();
1558 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1559
1560 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1561 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1562 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1563 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1564 if (not ok) {
1565 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1566 mtc.stop;
1567 }
1568
1569 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1570 f_sleep(X2002);
1571 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1572
1573 /* Now we don't ack the dl block (emulate MS failed receiveing IMM ASS
1574 * or GPRS DL, or DL ACK was lost for some reason). As a result, PCU
1575 * should retrigger IMM ASS + GPRS DL procedure after poll timeout. */
1576 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1577 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1578 if (not ok) {
1579 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1580 mtc.stop;
1581 }
1582 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1583 f_sleep(X2002);
1584 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1585
1586 /* ACK the DL block */
1587 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1588 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1589}
1590
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001591control {
1592 execute( TC_ns_reset() );
1593 execute( TC_ns_reset_retrans() );
1594 execute( TC_ns_alive() );
1595 execute( TC_ns_alive_timeout_reset() );
1596 execute( TC_ns_unblock() );
1597 execute( TC_ns_unblock_retrans() );
1598 execute( TC_ns_full_bringup() );
1599 execute( TC_ns_so_block() );
Harald Welte7fd25cf2019-03-21 22:14:02 +01001600
1601 execute( TC_pcuif_suspend() );
Vadim Yanitskiy1f72b0a2019-10-01 05:58:45 +07001602 execute( TC_ta_ptcch_idle() );
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +02001603 execute( TC_ta_rach_imm_ass() );
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001604 execute( TC_ta_ptcch_ul_multi_tbf() );
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001605 execute( TC_cs_lqual_ul_tbf() );
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001606 execute( TC_cs_initial_ul() );
1607 execute( TC_cs_max_ul() );
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001608 execute( TC_t3169() );
Pau Espin Pedrolff8da192019-12-05 17:23:58 +01001609 execute( TC_t3193() );
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001610 execute( TC_mo_ping_pong() );
Pau Espin Pedrola7b75662019-12-05 16:39:55 +01001611 execute( TC_imm_ass_dl_block_retrans() );
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001612}
1613
1614
1615
1616
1617
1618
1619}