blob: ab412c4d169a9bfd0c8091a42b268e26af6d5ca7 [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
Pau Espin Pedrol4536c822019-12-30 13:22:32 +010019friend module PCU_Tests_RAW_NS;
20
Harald Welte9fbcf4b2018-12-07 07:56:52 +010021import from General_Types all;
22import from Osmocom_Types all;
Harald Welte7fd25cf2019-03-21 22:14:02 +010023import from GSM_Types all;
24import from GSM_RR_Types all;
25
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +010026import from Osmocom_VTY_Functions all;
27import from TELNETasp_PortType all;
28
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +020029import from RLCMAC_CSN1_Types all;
30import from RLCMAC_Types all;
31
Oliver Smith8f9daab2019-10-09 09:27:19 +020032import from MobileL3_CommonIE_Types all;
33import from L3_Templates all;
34
Harald Welte9fbcf4b2018-12-07 07:56:52 +010035import from NS_Types all;
36import from BSSGP_Types all;
37import from Osmocom_Gb_Types all;
38
39import from BSSGP_Emulation all; /* BssgpConfig */
40import from NS_Emulation all; /* NSConfiguration */
41
42import from UD_Types all;
43import from PCUIF_Types all;
44import from PCUIF_CodecPort all;
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +020045import from PCUIF_RAW_Components all;
Harald Welte9fbcf4b2018-12-07 07:56:52 +010046import from IPL4asp_Types all;
Harald Welte9fbcf4b2018-12-07 07:56:52 +010047import from Native_Functions all;
48import from PCU_Tests all;
49
50modulepar {
51 charstring mp_pcu_sock_path := PCU_SOCK_DEFAULT;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +010052
53 float X2002 := 0.2; /* Timer -2002, IMM ASSIGN confirm delay */
Harald Welte9fbcf4b2018-12-07 07:56:52 +010054}
55
Harald Welte9fbcf4b2018-12-07 07:56:52 +010056
Pau Espin Pedrolf787b092019-10-04 18:34:05 +020057/* FIXME: make sure to use parameters from mp_gb_cfg.cell_id in the PCU INFO IND */
Pau Espin Pedrol4536c822019-12-30 13:22:32 +010058private template (value) PCUIF_info_ind ts_PCUIF_INFO_default := {
Pau Espin Pedrolf787b092019-10-04 18:34:05 +020059 version := PCU_IF_VERSION,
60 flags := c_PCUIF_Flags_default,
61 trx := valueof(ts_PCUIF_InfoTrxs_def),
62 bsic := 7,
63 mcc := 262,
64 mnc := 42,
65 mnc_3_digits := 0,
66 lac := 13135,
67 rac := 0,
68 nsei := mp_nsconfig.nsei,
69 nse_timer := { 3, 3, 3, 3, 30, 3, 10 },
70 cell_timer := { 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 },
71 cell_id := 20960,
72 repeat_time := 5 * 50,
73 repeat_count := 3,
74 bvci := mp_gb_cfg.bvci,
75 t3142 := 20,
76 t3169 := 5,
77 t3191 := 5,
78 t3193_10ms := 160,
79 t3195 := 5,
80 t3101 := 10,
81 t3103 := 4,
82 t3105 := 8,
83 cv_countdown := 15,
84 dl_tbf_ext := 250 * 10, /* ms */
85 ul_tbf_ext := 250 * 10, /* ms */
86 initial_cs := 2,
87 initial_mcs := 6,
88 nsvci := { mp_nsconfig.nsvci, 0 },
89 local_pprt := { mp_nsconfig.remote_udp_port, 0 },
90 remote_port := { mp_nsconfig.local_udp_port, 0 },
91 remote_ip := { f_inet_haddr(mp_nsconfig.local_ip) , '00000000'O }
92}
93
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +010094type record lqual_range {
95 /* component reference to the IPA_Client component used for RSL */
96 uint8_t low,
97 uint8_t high
98}
99
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200100type component RAW_PCU_Test_CT extends bssgp_CT {
101 /* Connection to the BTS component (one for now) */
102 port RAW_PCU_MSG_PT BTS;
103 /* Connection to the PCUIF component */
104 port RAW_PCU_MSG_PT PCUIF;
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100105 /* VTY connection to the PCU */
106 port TELNETasp_PT PCUVTY;
107
108 /* Uplink CS/MCS thresholds, default from pcu_main.c: */
109 var lqual_range g_cs_lqual_ranges[4] := {{low := 0, high := 6},
110 {low := 5, high := 8},
111 {low := 7, high := 13},
112 {low := 12,high := 35}};
113 var lqual_range g_mcs_lqual_ranges[9] := {{low := 0, high := 6},
114 {low := 5, high := 8},
115 {low := 7, high := 13},
116 {low := 12,high := 15},
117 {low := 14, high := 17},
118 {low := 16, high := 18},
119 {low := 17,high := 20},
120 {low := 19, high := 24},
121 {low := 23,high := 35}};
122 var uint8_t g_cs_initial_dl := 1;
123 var uint8_t g_cs_initial_ul := 1;
124 var uint8_t g_mcs_initial_dl := 1;
125 var uint8_t g_mcs_initial_ul := 1;
126 var uint8_t g_cs_max_dl := 4;
127 var uint8_t g_cs_max_ul := 4;
128 var uint8_t g_mcs_max_dl := 9;
129 var uint8_t g_mcs_max_ul := 9;
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200130
131 /* Guard timeout */
132 timer g_T_guard := 60.0;
133};
134
135private altstep as_Tguard_RAW() runs on RAW_PCU_Test_CT {
136 [] g_T_guard.timeout {
137 setverdict(fail, "Timeout of T_guard");
138 mtc.stop;
139 }
140}
141
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100142private function f_pcuvty_set_allowed_cs_mcs() runs on RAW_PCU_Test_CT {
143 f_vty_config2(PCUVTY, {"pcu"}, "cs " & int2str(g_cs_initial_dl) & " " & int2str(g_cs_initial_ul));
144 f_vty_config2(PCUVTY, {"pcu"}, "cs max " & int2str(g_cs_max_dl) & " " & int2str(g_cs_max_ul));
145
146 f_vty_config2(PCUVTY, {"pcu"}, "mcs " & int2str(g_mcs_initial_dl) & " " & int2str(g_mcs_initial_ul));
147 f_vty_config2(PCUVTY, {"pcu"}, "mcs max " & int2str(g_mcs_max_dl) & " " & int2str(g_mcs_max_ul));
148}
149
150private function f_pcuvty_set_link_quality_ranges() runs on RAW_PCU_Test_CT {
151 var charstring cmd;
152
153 cmd := "cs link-quality-ranges" &
154 " cs1 " & int2str(g_cs_lqual_ranges[0].high) &
155 " cs2 " & int2str(g_cs_lqual_ranges[1].low) & " " & int2str(g_cs_lqual_ranges[1].high) &
156 " cs3 " & int2str(g_cs_lqual_ranges[2].low) & " " & int2str(g_cs_lqual_ranges[2].high) &
157 " cs4 " & int2str(g_cs_lqual_ranges[3].low);
158 f_vty_config2(PCUVTY, {"pcu"}, cmd);
159
160 cmd := "mcs link-quality-ranges" &
161 " mcs1 " & int2str(g_mcs_lqual_ranges[0].high) &
162 " mcs2 " & int2str(g_mcs_lqual_ranges[1].low) & " " & int2str(g_mcs_lqual_ranges[1].high) &
163 " mcs3 " & int2str(g_mcs_lqual_ranges[2].low) & " " & int2str(g_mcs_lqual_ranges[2].high) &
164 " mcs4 " & int2str(g_mcs_lqual_ranges[3].low) & " " & int2str(g_mcs_lqual_ranges[3].high) &
165 " mcs5 " & int2str(g_mcs_lqual_ranges[4].low) & " " & int2str(g_mcs_lqual_ranges[4].high) &
166 " mcs6 " & int2str(g_mcs_lqual_ranges[5].low) & " " & int2str(g_mcs_lqual_ranges[5].high) &
167 " mcs7 " & int2str(g_mcs_lqual_ranges[6].low) & " " & int2str(g_mcs_lqual_ranges[6].high) &
168 " mcs8 " & int2str(g_mcs_lqual_ranges[7].low) & " " & int2str(g_mcs_lqual_ranges[7].high) &
169 " mcs9 " & int2str(g_mcs_lqual_ranges[8].low);
170 f_vty_config2(PCUVTY, {"pcu"}, cmd);
171}
172
173private function f_init_vty(charstring id) runs on RAW_PCU_Test_CT {
174 map(self:PCUVTY, system:PCUVTY);
175 f_vty_set_prompts(PCUVTY);
176 f_vty_transceive(PCUVTY, "enable");
177}
178
Pau Espin Pedrolf787b092019-10-04 18:34:05 +0200179private function f_init_raw(charstring id, template (value) PCUIF_info_ind info_ind := ts_PCUIF_INFO_default)
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200180runs on RAW_PCU_Test_CT {
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200181 var RAW_PCUIF_CT vc_PCUIF;
182 var RAW_PCU_BTS_CT vc_BTS;
183
184 /* Start the guard timer */
185 g_T_guard.start;
186 activate(as_Tguard_RAW());
187
188 /* Init PCU interface component */
189 vc_PCUIF := RAW_PCUIF_CT.create("PCUIF-" & id);
190 connect(vc_PCUIF:MTC, self:PCUIF);
191 map(vc_PCUIF:PCU, system:PCU);
192
193 /* Create one BTS component (we may want more some day) */
194 vc_BTS := RAW_PCU_BTS_CT.create("BTS-" & id);
195 connect(vc_BTS:PCUIF, vc_PCUIF:BTS);
196 connect(vc_BTS:TC, self:BTS);
197
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100198 f_init_vty(id);
199
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200200 vc_PCUIF.start(f_PCUIF_CT_handler(mp_pcu_sock_path));
Pau Espin Pedrolf787b092019-10-04 18:34:05 +0200201 vc_BTS.start(f_BTS_CT_handler(0, valueof(info_ind)));
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200202
203 /* Wait until the BTS is ready (SI13 negotiated) */
204 BTS.receive(tr_RAW_PCU_EV(BTS_EV_SI13_NEGO));
205}
206
Pau Espin Pedrol89486332019-12-05 14:05:46 +0100207template AckNackDescription t_AckNackDescription_init := {
208 final_ack := '0'B,
209 starting_seq_nr := 0,
210 receive_block_bitmap := '0000000000000000000000000000000000000000000000000000000000000000'B
211}
212
213/* TS 44.060 sec 12.3 Ack/Nack Description */
214private function f_acknackdesc_ack_block(inout AckNackDescription desc, uint7_t bsn, BIT1 final_ack := '0'B)
215{
216 var integer i;
217 var integer inc := bsn - desc.starting_seq_nr + 1;
218 /* Filling hole? */
219 if (bsn < desc.starting_seq_nr) {
220 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - (desc.starting_seq_nr - bsn)] := int2bit(1, 1);
221 return;
222 }
223
224 /* SSN is increased, and so RBB values need to be moved */
225 for (i := 0; i < lengthof(desc.receive_block_bitmap) - inc; i := i+1) {
226 desc.receive_block_bitmap[i] := desc.receive_block_bitmap[i + inc];
227 }
228 for (i := lengthof(desc.receive_block_bitmap) - inc; i < lengthof(desc.receive_block_bitmap) - 1; i := i+1) {
229 desc.receive_block_bitmap[i] := int2bit(0, 1);
230 }
231 /* Now we can set current bit and update SSN */
232 desc.starting_seq_nr := bsn + 1;
233 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - 1] := int2bit(1, 1);
234
235 /* Finally update the final_ack bit as requested: */
236 desc.final_ack := final_ack;
237}
238
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200239/* FIXME: properly encode RA (see TS 24.060, table 11.2.5.2) */
240private function f_establish_tbf(out GsmRrMessage rr_imm_ass, uint8_t bts_nr := 0,
241 uint16_t ra := oct2int('3A'O), uint8_t is_11bit := 0,
242 PCUIF_BurstType burst_type := BURST_TYPE_0,
243 TimingAdvance ta := 0)
244runs on RAW_PCU_Test_CT return boolean {
245 var PCUIF_Message pcu_msg;
246 var GsmRrMessage rr_msg;
247 var uint32_t fn;
248 timer T;
249
250 /* FIXME: ask the BTS component to give us the current TDMA fn */
251 fn := 1337 + ta;
252
253 /* Send RACH.ind */
254 log("Sending RACH.ind on fn=", fn, " with RA=", ra, ", TA=", ta);
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700255 BTS.send(ts_PCUIF_RACH_IND(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200256 ra := ra, is_11bit := is_11bit,
257 burst_type := burst_type,
258 fn := fn, arfcn := 871,
259 qta := ta * 4));
260
261 /* Expect Immediate (TBF) Assignment on TS0/AGCH */
262 T.start(2.0);
263 alt {
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700264 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200265 sapi := PCU_IF_SAPI_AGCH, data := ?))
266 -> value pcu_msg {
267 rr_imm_ass := dec_GsmRrMessage(pcu_msg.u.data_req.data);
268 log("Rx Immediate Assignment: ", rr_imm_ass);
269
270 /* Make sure this assignment is for us
271 * TODO: Uplink or Downlink TBF? */
272 if (match(rr_imm_ass, tr_IMM_TBF_ASS(?, ra, fn))) {
273 setverdict(pass);
274 return true;
275 }
276
277 /* Not for us? Wait for more. */
278 repeat;
279 }
280 [] BTS.receive { repeat; }
281 [] T.timeout {
282 setverdict(fail, "Timeout waiting for Immediate Assignment");
283 }
284 }
285
286 return false;
287}
288
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200289private function f_imm_ass_verify_ul_tbf_ass(GsmRrMessage rr_imm_ass, out PacketUlAssign ul_tbf_ass)
290runs on RAW_PCU_Test_CT return boolean {
291
292 /* Make sure we received an UL TBF Assignment */
293 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
294 ul_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
295 log("Rx Uplink TBF assignment: ", ul_tbf_ass);
296 setverdict(pass);
297 } else {
298 setverdict(fail, "Failed to match UL TBF Assignment");
299 return false;
300 }
301
302 /* Make sure we have got a TBF with Dynamic Block Allocation */
303 if (ul_tbf_ass.dynamic == omit) {
304 setverdict(fail, "Single Block Allocation is not handled by ", testcasename());
305 return false;
306 }
307
308 return true;
309}
310
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +0200311private function f_imm_ass_verify_dl_tbf_ass(GsmRrMessage rr_imm_ass, out PacketDlAssign dl_tbf_ass)
312runs on RAW_PCU_Test_CT return boolean {
313
314 /* Make sure we received a DL TBF Assignment */
315 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := true, rest := tr_IaRestOctets_DLAss(?)))) {
316 dl_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.dl;
317 log("Rx Downlink TBF assignment: ", dl_tbf_ass);
318 setverdict(pass);
319 } else {
320 setverdict(fail, "Failed to match DL TBF Assignment");
321 return false;
322 }
323
324 return true;
325}
326
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200327/* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100328private 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 +0200329runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100330 var template RAW_PCU_EventParam ev_param := {tdma_fn := ? };
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200331 BTS.send(ts_PCUIF_DATA_IND(bts_nr := 0, trx_nr := 0, ts_nr := 7, block_nr := 0,
332 sapi := PCU_IF_SAPI_PDTCH, data := data,
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100333 fn := fn, arfcn := 871, lqual_cb := lqual_cb));
334 if (fn != 0) {
335 ev_param := {tdma_fn := fn };
336 }
337 BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PDTCH_BLOCK_SENT, ev_param));
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200338}
339
340/* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
341private function f_pcuif_rx_data_req(out PCUIF_Message pcu_msg)
342runs on RAW_PCU_Test_CT {
343 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
344 sapi := PCU_IF_SAPI_PDTCH, fn := 0,
345 arfcn := 871, block_nr := 0));
346 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
347 sapi := PCU_IF_SAPI_PDTCH)) -> value pcu_msg;
348}
349
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +0200350/* Expect an Immediate Assignment (paging) from PCU on PCUIF on specified sapi. */
351private function f_pcuif_rx_pch_imm_tbf_ass(out GsmRrMessage rr_imm_ass)
352runs on RAW_PCU_Test_CT {
353 var PCUIF_Message pcu_msg;
354 var octetstring macblock;
355 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
356 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
357 /* First 3 bytes contain paging group: */
358 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
359 rr_imm_ass := dec_GsmRrMessage(macblock);
360 if (not match(rr_imm_ass, tr_IMM_TBF_ASS())) {
361 setverdict(fail, "Failed to match Immediate Assignment: ", rr_imm_ass);
362 mtc.stop;
363 }
364 BTS.send(ts_PCUIF_DATA_CNF(bts_nr := 0, trx_nr := 0, ts_nr := 0, block_nr := 0,
Pau Espin Pedrolf04ba542019-12-23 14:47:44 +0100365 fn := pcu_msg.u.data_req.fn, arfcn := 871, sapi := PCU_IF_SAPI_PCH, data := macblock));
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +0200366}
367
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100368/* Expect a Paging Request Type 1 from PCU on PCUIF on specified sapi. */
Pau Espin Pedrol925818a2020-01-02 14:06:51 +0100369private function f_pcuif_rx_pch_pag_req1(out integer imsi_suff_rx, out GsmRrMessage rr_pag_req1)
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100370runs on RAW_PCU_Test_CT {
371 var PCUIF_Message pcu_msg;
Pau Espin Pedrol925818a2020-01-02 14:06:51 +0100372 var octetstring imsi_suff_octstr;
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100373 var octetstring macblock;
374 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
375 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
Pau Espin Pedrol925818a2020-01-02 14:06:51 +0100376 /* First 3 bytes contain IMSI suffix to calculate paging group: */
377 imsi_suff_octstr := substr(pcu_msg.u.data_req.data, 0, 3);
378 imsi_suff_rx := str2int(oct2char(imsi_suff_octstr[0])) * 100 +
379 str2int(oct2char(imsi_suff_octstr[1])) * 10 +
380 str2int(oct2char(imsi_suff_octstr[2]));
381
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100382 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
383 rr_pag_req1 := dec_GsmRrMessage(macblock);
384 if (not match(rr_pag_req1, tr_PAG_REQ1())) {
385 setverdict(fail, "Failed to match Paging Request Type 1: ", rr_pag_req1);
386 mtc.stop;
387 }
388 BTS.send(ts_PCUIF_DATA_CNF(bts_nr := 0, trx_nr := 0, ts_nr := 0, block_nr := 0,
389 fn := pcu_msg.u.data_req.fn, arfcn := 871, sapi := PCU_IF_SAPI_PCH, data := macblock));
390}
391
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100392private 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 +0200393runs on RAW_PCU_Test_CT {
394 var octetstring data;
395 /* Encode the payload of DATA.ind */
396 data := enc_RlcmacUlBlock(valueof(ul_data));
397 data := f_pad_oct(data, 23, '00'O); /* CS-1 */
398
399 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100400 f_pcuif_tx_data_ind(data, lqual_cb, fn);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200401}
402
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200403private function f_tx_rlcmac_ul_n_blocks(PacketUlAssign ul_tbf_ass, integer num_blocks := 1)
404runs on RAW_PCU_Test_CT {
405 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
406 tfi := ul_tbf_ass.dynamic.tfi_assignment,
407 cv := num_blocks - 1, /* num UL blocks to be sent (to be overridden in loop) */
408 bsn := 0, /* TODO: what should be here? */
409 blocks := { /* To be generated in loop */ });
410
411 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
412 ul_data.data.tlli := '00000001'O;
413
414 for (var integer i := 0; i < num_blocks; i := i + 1) {
415 /* Prepare a new UL block (CV, random payload) */
416 ul_data.data.mac_hdr.countdown := (num_blocks - i - 1);
417 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
418 f_tx_rlcmac_ul_block(ul_data);
419 }
420}
421
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100422private function f_rx_rlcmac_dl_block(out RlcmacDlBlock dl_block, out uint32_t dl_fn)
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200423runs on RAW_PCU_Test_CT {
424 var PCUIF_Message pcu_msg;
425 f_pcuif_rx_data_req(pcu_msg);
426 dl_block := dec_RlcmacDlBlock(pcu_msg.u.data_req.data);
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100427 dl_fn := pcu_msg.u.data_req.fn;
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200428}
429
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100430private 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 +0200431runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100432 var uint32_t dl_fn;
433
434 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Pau Espin Pedrol21659632019-12-02 19:12:08 +0100435 if (not match(dl_block, tr_RLCMAC_UL_ACK_NACK(ul_tfi := ?, tlli := ?))) {
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200436 setverdict(fail, "Failed to match Packet Uplink ACK / NACK");
437 mtc.stop;
438 }
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100439
440 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200441}
442
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200443private function f_rx_rlcmac_dl_block_exp_dummy(out RlcmacDlBlock dl_block)
444runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100445 var uint32_t dl_fn;
446
447 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200448 if (not match(dl_block, tr_RLCMAC_DUMMY_CTRL())) {
449 setverdict(fail, "Failed to match Packet DUMMY DL");
450 mtc.stop;
451 }
452}
453
Pau Espin Pedrolff8da192019-12-05 17:23:58 +0100454private function f_rx_rlcmac_dl_block_exp_pkt_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
455runs on RAW_PCU_Test_CT {
456 var uint32_t dl_fn;
457
458 f_rx_rlcmac_dl_block(dl_block, dl_fn);
459 if (not match(dl_block, tr_RLCMAC_DL_PACKET_ASS())) {
460 setverdict(fail, "Failed to match Packet Downlink Assignment");
461 mtc.stop;
462 }
463
464 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
465}
466
Oliver Smith8f9daab2019-10-09 09:27:19 +0200467private function f_rx_rlcmac_dl_block_exp_pkt_pag_req(out RlcmacDlBlock dl_block)
468runs on RAW_PCU_Test_CT {
469 var uint32_t dl_fn;
470
471 f_rx_rlcmac_dl_block(dl_block, dl_fn);
472 if (not match(dl_block, tr_RLCMAC_PACKET_PAG_REQ())) {
473 setverdict(fail, "Failed to match Packet Paging Request: ", dl_block, " vs ", tr_RLCMAC_PACKET_PAG_REQ());
474 mtc.stop;
475 }
476}
477
Pau Espin Pedrol89486332019-12-05 14:05:46 +0100478private 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 +0100479runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100480 var PCUIF_Message pcu_msg;
481 var uint32_t dl_fn;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100482 var template RlcmacDlBlock dl_template := tr_RLCMAC_DATA_RRBP;
483 dl_template.data.blocks := ?;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100484
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100485 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100486 if (not match(dl_block, dl_template)) {
487 setverdict(fail, "Failed to match Packet data: ", dl_block, " vs ", dl_template);
488 mtc.stop;
489 }
Pau Espin Pedrol6e3b6892019-12-04 19:24:16 +0100490
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100491 ack_fn := dl_fn + f_rrbp_fn_delay(dl_block.data.mac_hdr.mac_hdr.rrbp);
492
Pau Espin Pedrol89486332019-12-05 14:05:46 +0100493 if (not match(dl_block.data.mac_hdr.hdr_ext.bsn, exp_bsn)) {
494 setverdict(fail, "DL block BSN doesn't match: ",
495 dl_block.data.blocks[0].hdr.length_ind, " vs exp ", exp_bsn);
496 }
497
Pau Espin Pedrol6e3b6892019-12-04 19:24:16 +0100498 if (lengthof(dl_block.data.blocks) < 1) {
499 setverdict(fail, "DL block has no LLC payload: ", dl_block);
500 mtc.stop;
501 }
502
503 if (ispresent(dl_block.data.blocks[0].hdr) and dl_block.data.blocks[0].hdr.length_ind != lengthof(data)) {
504 setverdict(fail, "DL block has LLC header with wrong expected size: ",
505 dl_block.data.blocks[0].hdr.length_ind, " vs ", lengthof(data));
506 mtc.stop;
507 }
508
509 if (dl_block.data.blocks[0].payload != data) {
510 setverdict(fail, "Failed to match content of LLC payload in DL Block: ", dl_block, " vs ", data);
511 mtc.stop;
512 }
513
514 /* Check next data blocks contain dummy frames */
515 if (lengthof(dl_block.data.blocks) > 1 and substr(dl_block.data.blocks[1].payload, 0, 3) != '43C001'O) {
516 setverdict(fail, "Second data payload is not a dummy frame: ", dl_block.data.blocks[1].payload);
517 mtc.stop;
518 }
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100519}
520
Vadim Yanitskiy740ae762019-09-29 16:13:41 +0700521testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
522 var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.cell_id.ra_id);
523 var GprsTlli tlli := 'FFFFFFFF'O;
524 timer T;
525
526 /* Initialize NS/BSSGP side */
527 f_init_bssgp();
528
529 /* Initialize the PCU interface abstraction */
530 f_init_raw(testcasename());
531
532 /* Establish BSSGP connection to the PCU */
533 f_bssgp_establish();
534
535 BTS.send(ts_PCUIF_SUSP_REQ(0, tlli, ra_id, 0));
536
537 T.start(2.0);
538 alt {
539 [] BSSGP_SIG[0].receive(tr_BSSGP_SUSPEND(tlli, mp_gb_cfg.cell_id.ra_id)) {
540 setverdict(pass);
541 }
542 [] T.timeout {
543 setverdict(fail, "Timeout waiting for BSSGP SUSPEND");
544 }
545 }
546}
547
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200548/* Test of correct Timing Advance at the time of TBF establishment
549 * (derived from timing offset of the Access Burst). */
550testcase TC_ta_rach_imm_ass() runs on RAW_PCU_Test_CT {
551 var GsmRrMessage rr_msg;
552 var boolean ok;
553
554 /* Initialize the PCU interface abstraction */
555 f_init_raw(testcasename());
556
557 /* We cannot send too many TBF requests in a short time because
558 * at some point the PCU will fail to allocate a new TBF. */
559 for (var TimingAdvance ta := 0; ta < 64; ta := ta + 16) {
560 /* Establish an Uplink TBF (send RACH.ind with current TA) */
561 ok := f_establish_tbf(rr_msg, bts_nr := 0, ta := ta);
562 if (not ok) {
563 setverdict(fail, "Failed to establish an Uplink TBF");
564 mtc.stop;
565 }
566
567 /* Make sure Timing Advance IE matches out expectations */
568 if (match(rr_msg, tr_IMM_TBF_ASS(dl := false, ta := ta))) {
569 setverdict(pass);
570 }
571 }
572}
573
Vadim Yanitskiy1f72b0a2019-10-01 05:58:45 +0700574/* Verify that the PCU generates valid PTCCH/D messages
575 * while neither Uplink nor Downlink TBF is established. */
576testcase TC_ta_ptcch_idle() runs on RAW_PCU_Test_CT {
577 var PTCCHDownlinkMsg ptcch_msg;
578 var PCUIF_Message pcu_msg;
579 timer T;
580
581 /* Initialize the PCU interface abstraction */
582 f_init_raw(testcasename());
583
584 /* Sent an RTS.req for PTCCH/D */
585 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
586 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
587 arfcn := 871, block_nr := 0));
588 T.start(5.0);
589 alt {
590 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
591 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
592 log("Rx DATA.req message: ", pcu_msg);
593 setverdict(pass);
594 }
595 [] BTS.receive(PCUIF_Message:?) { repeat; }
596 [] T.timeout {
597 setverdict(fail, "Timeout waiting for a PTCCH/D block");
598 mtc.stop;
599 }
600 }
601
602 ptcch_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
603 log("Decoded PTCCH/D message: ", ptcch_msg);
604
605 /* Make sure the message is encoded correctly
606 * TODO: do we expect all TA values to be equal '1111111'B? */
607 if (not match(ptcch_msg, tr_PTCCHDownlinkMsg)) {
608 setverdict(fail, "Malformed PTCCH/D message");
609 mtc.stop;
610 }
611}
612
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700613/* Test of correct Timing Advance during an active Uplink TBF.
614 *
615 * Unlike the circuit-switched domain, Uplink transmissions on PDCH time-slots
616 * are not continuous and there can be long time gaps between them. This happens
617 * due to a bursty nature of packet data. The actual Timing Advance of a MS may
618 * significantly change between such rare Uplink transmissions, so GPRS introduces
619 * additional mechanisms to control Timing Advance, and thus reduce interference
620 * between neighboring TDMA time-slots.
621 *
622 * At the moment of Uplink TBF establishment, initial Timing Advance is measured
623 * from ToA (Timing of Arrival) of an Access Burst. This is covered by another
624 * test case - TC_ta_rach_imm_ass. In response to that Access Burst the network
625 * sends Immediate Assignment on AGCH, which _may_ contain Timing Advance Index
626 * among with the initial Timing Advance value. And here PTCCH comes to play.
627 *
628 * PTCCH is a unidirectional channel on which the network can instruct a sub-set
629 * of 16 MS (whether TBFs are active or not) to adjust their Timing Advance
630 * continuously. To ensure continuous measurements of the signal propagation
631 * delay, the MSs shall transmit Access Bursts on Uplink (PTCCH/U) on sub-slots
632 * defined by an assigned Timing Advance Index (see 3GPP TS 45.002).
633 *
634 * The purpose of this test case is to verify the assignment of Timing Advance
635 * Index, and the process of Timing Advance notification on PTCCH/D. The MTC
636 * first establishes several Uplink TBFs, but does not transmit any Uplink
637 * blocks on them. During 4 TDMA multi-frame periods the MTC is sending RACH
638 * indications to the PCU, checking the correctness of two received PTCCH/D
639 * messages (period of PTCCH/D is two multi-frames).
640 */
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700641
642/* List of ToA values for Access Bursts to be sent on PTCCH/U,
643 * each ToA (Timing of Arrival) value is in units of 1/4 of
644 * a symbol (i.e. 1 symbol is 4 QTA units). */
645type record length(16) of int16_t PTCCH_TAI_ToA_MAP;
646const PTCCH_TAI_ToA_MAP ptcch_toa_map_def := {
647 0, 0, 0, 0,
648 0, 0, 0, 0,
649 0, 0, 0, 0,
650 0, 0, 0, 0
651};
652
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700653private 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 +0700654 in PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def)
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700655runs on RAW_PCU_Test_CT {
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700656 var RAW_PCU_Event event;
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700657 var integer ss;
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700658
659 /* Send Access Bursts on PTCCH/U for every TA Index */
660 [] BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PTCCH_UL_BURST)) -> value event {
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700661 ss := f_tdma_ptcch_fn2ss(event.data.tdma_fn);
662 if (ss < 0) { mtc.stop; } /* Shall not happen */
663
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700664 log("Sending an Access Burst on PTCCH/U",
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700665 ", sub-slot=", ss, " (TAI)",
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700666 ", fn=", event.data.tdma_fn,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700667 ", ToA=", toa_map[ss], " (QTA)");
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700668 /* TODO: do we care about RA and burst format? */
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700669 BTS.send(ts_PCUIF_RACH_IND(bts_nr, trx_nr, ts_nr,
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700670 ra := oct2int('3A'O),
671 is_11bit := 0,
672 burst_type := BURST_TYPE_0,
673 fn := event.data.tdma_fn,
674 arfcn := 871,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700675 qta := toa_map[ss],
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700676 sapi := PCU_IF_SAPI_PTCCH));
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700677 repeat;
678 }
679}
680
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700681private function f_TC_ta_ptcch_ul_multi_tbf(in PTCCH_TAI_ToA_MAP ptcch_toa_map,
682 template PTCCHDownlinkMsg t_ta_msg)
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700683runs on RAW_PCU_Test_CT {
684 var PTCCHDownlinkMsg ta_msg;
685 var PCUIF_Message pcu_msg;
686 timer T;
687
688 /* First, send an RTS.req for the upcoming PTCCH/D block */
689 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
690 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
691 arfcn := 871, block_nr := 0));
692 T.start(2.0);
693 alt {
694 /* Keep sending of Access Bursts during two multi-frames (period of PTCCH/D)
695 * with increasing ToA (Timing of Arrival) values: 0, 7, 14, 28, 35... */
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700696 [] as_ta_ptcch(bts_nr := 0, trx_nr := 0, ts_nr := 7, toa_map := ptcch_toa_map);
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700697 /* In the end of 2nd multi-frame we should receive a PTCCH/D block */
698 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
699 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
700 ta_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
701 log("Rx PTCCH/D message: ", ta_msg);
702
703 /* Make sure Timing Advance values match our expectations */
704 if (match(ta_msg, t_ta_msg)) {
705 setverdict(pass);
706 } else {
707 setverdict(fail, "PTCCH/D message does not match: ", t_ta_msg);
708 }
709 }
710 [] BTS.receive { repeat; }
711 [] T.timeout {
712 setverdict(fail, "Timeout waiting for a PTCCH/D block");
713 mtc.stop;
714 }
715 }
716}
717
718testcase TC_ta_ptcch_ul_multi_tbf() runs on RAW_PCU_Test_CT {
719 var template PacketUlAssign t_ul_tbf_ass;
720 var PacketUlAssign ul_tbf_ass[7];
721 var GsmRrMessage rr_msg[7];
722 var boolean ok;
723
724 /* Initialize the PCU interface abstraction */
725 f_init_raw(testcasename());
726
727 /* Enable forwarding of PTCCH/U TDMA events to us */
728 BTS.send(ts_RAW_PCU_CMD(TDMA_CMD_ENABLE_PTCCH_UL_FWD));
729
730 /* Establish 7 Uplink TBFs (USF flag is 3 bits long, '111'B is reserved) */
731 for (var integer i := 0; i < 7; i := i + 1) {
732 ok := f_establish_tbf(rr_msg[i], ta := 0);
733 if (not ok) {
734 setverdict(fail, "Failed to establish an Uplink TBF #", i);
735 mtc.stop;
736 }
737
738 /* Make sure we received an UL TBF Assignment */
739 if (match(rr_msg[i], tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
740 ul_tbf_ass[i] := rr_msg[i].payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
741 log("Rx Uplink TBF assignment for #", i, ": ", ul_tbf_ass[i]);
742 } else {
743 setverdict(fail, "Failed to match UL TBF Assignment for #", i);
744 mtc.stop;
745 }
746
747 /* We expect incremental TFI/USF assignment (dynamic allocation) */
748 t_ul_tbf_ass := tr_PacketUlDynAssign(tfi := i, usf := i);
749 if (not match(ul_tbf_ass[i], t_ul_tbf_ass)) {
750 setverdict(fail, "Failed to match Packet Uplink Assignment for #", i);
751 mtc.stop;
752 }
753
754 /* We also expect Timing Advance Index to be a part of the assignment */
755 if (ul_tbf_ass[i].dynamic.ta_index != i) {
756 setverdict(fail, "Failed to match Timing Advance Index for #", i);
757 /* Keep going, the current OsmoPCU does not assign TA Index */
758 }
759 }
760
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700761 /* Prepare a list of ToA values for Access Bursts to be sent on PTCCH/U */
762 var PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def;
763 for (var integer i := 0; i < 7; i := i + 1) {
764 /* ToA in units of 1/4 of a symbol */
765 toa_map[i] := (i + 1) * 7 * 4;
766 }
767
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700768 /* Now we have all 7 TBFs established in one-phase access mode,
769 * however we will not be sending any data on them. Instead, we
770 * will be sending RACH.ind on PTCCH/U during 4 multi-frame
771 * periods (TAI 0..8), and then will check two PTCCH/D blocks.
772 *
773 * Why not 4 TBFs at once? Because Uplink is delayed by 3 TDMA
774 * time-slots, so at the moment of scheduling a PTCCH/D block
775 * the PCU has odd number of PTCCH/U Access Bursts received. */
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700776 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700777 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
778 /* Other values are not known (yet) */
779 tai3_ta := ?));
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700780 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700781 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
782 tai3_ta := 28, tai4_ta := 35, tai5_ta := 42,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700783 /* Other values are out of our interest */
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700784 tai6_ta := ?));
785}
786
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700787/* Default link quality adaptation (Coding Scheme) ranges (inclusive).
788 * OsmoPCU (VTY): cs link-quality-ranges cs1 6 cs2 5 8 cs3 7 13 cs4 12
789 *
790 * NOTE: the ranges are intentionally overlapping because OsmoPCU
791 * does not change CS/MCS on the range borders (5-6, 7-8, 12-13). */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200792private template integer CS1_lqual_dB_range := (-infinity .. 6);
793private template integer CS2_lqual_dB_range := (5 .. 8);
794private template integer CS3_lqual_dB_range := (7 .. 13);
795private template integer CS4_lqual_dB_range := (12 .. infinity);
796
797testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200798 var GsmRrMessage rr_imm_ass;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200799 var PacketUlAssign ul_tbf_ass;
800 var RlcmacDlBlock dl_block;
801 var PCUIF_Message pcu_msg;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200802 var octetstring data;
803 var boolean ok;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100804 var uint32_t unused_fn;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200805
806 /* Initialize the PCU interface abstraction */
807 f_init_raw(testcasename());
808
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100809 f_pcuvty_set_allowed_cs_mcs();
810 f_pcuvty_set_link_quality_ranges();
811
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200812 /* Establish an Uplink TBF */
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200813 ok := f_establish_tbf(rr_imm_ass);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200814 if (not ok) {
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200815 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200816 mtc.stop;
817 }
818
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200819 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
820 if (not ok) {
821 setverdict(fail, "Immediate Assignment not an Uplink TBF");
Vadim Yanitskiy6276b6c2019-09-29 19:48:26 +0700822 mtc.stop;
823 }
824
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200825 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
826 tfi := ul_tbf_ass.dynamic.tfi_assignment,
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100827 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200828 bsn := 0, /* TODO: what should be here? */
829 blocks := { /* To be generated in loop */ });
830
831 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
832 ul_data.data.tlli := '00000001'O;
833
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700834 /* The actual / old link quality values. We need to keep track of the old
835 * (basically previous) link quality value, because OsmoPCU actually
836 * changes the coding scheme if not only the actual, but also the old
837 * value leaves the current link quality range (window). */
838 var integer lqual := 0;
839 var integer lqual_old;
840
841 /* 16 UL blocks (0 .. 15 dB, step = 1 dB) */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200842 for (var integer i := 0; i < 16; i := i + 1) {
843 /* Prepare a new UL block (CV, random payload) */
844 ul_data.data.mac_hdr.countdown := (15 - i);
845 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
846
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700847 /* Update the old / actual link quality */
848 lqual_old := lqual;
849 lqual := i;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200850
851 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
852 log("Sending DATA.ind with link quality (dB): ", lqual);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200853 f_tx_rlcmac_ul_block(ul_data, lqual * 10);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200854
855 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100856 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200857
858 log("Rx Packet Uplink ACK / NACK with Channel Coding Command: ",
859 dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd);
860
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700861 /* Match the received Channel Coding Command. Since we are increasing
862 * the link quality value on each iteration and not decreasing, there
863 * is no need to check the both old and current link quality values. */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200864 var template ChCodingCommand ch_coding;
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700865 select (lqual_old) {
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200866 case (CS1_lqual_dB_range) { ch_coding := CH_CODING_CS1; }
867 case (CS2_lqual_dB_range) { ch_coding := CH_CODING_CS2; }
868 case (CS3_lqual_dB_range) { ch_coding := CH_CODING_CS3; }
869 case (CS4_lqual_dB_range) { ch_coding := CH_CODING_CS4; }
870 }
871
872 if (not match(dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd, ch_coding)) {
873 setverdict(fail, "Channel Coding does not match our expectations: ", ch_coding);
874 } else {
875 setverdict(pass);
876 }
877 }
878}
879
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100880/* Test the max UL CS set by VTY works fine */
881testcase TC_cs_initial_ul() runs on RAW_PCU_Test_CT {
882 var GsmRrMessage rr_imm_ass;
883 var PacketUlAssign ul_tbf_ass;
884 var RlcmacDlBlock dl_block;
885 var boolean ok;
886 var integer lqual_cb;
887 var ChCodingCommand last_ch_coding;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100888 var uint32_t unused_fn;
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100889
890 /* Initialize the PCU interface abstraction */
891 f_init_raw(testcasename());
892
893 /* Set initial UL CS to 3 */
894 g_cs_initial_ul := 3;
895 f_pcuvty_set_allowed_cs_mcs();
896 f_pcuvty_set_link_quality_ranges();
897
898 /* Take lqual (dB->cB) so that we stay in that CS */
899 lqual_cb := g_cs_lqual_ranges[2].low * 10;
900
901 /* Establish an Uplink TBF */
902 ok := f_establish_tbf(rr_imm_ass);
903 if (not ok) {
904 setverdict(fail, "Failed to establish TBF");
905 mtc.stop;
906 }
907
908 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
909 if (not ok) {
910 setverdict(fail, "Immediate Assignment not an Uplink TBF");
911 mtc.stop;
912 }
913
914 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
915 tfi := ul_tbf_ass.dynamic.tfi_assignment,
916 cv := 3, /* 8 UL blocks to be sent (to be overridden in loop) */
917 bsn := 0, /* TODO: what should be here? */
918 blocks := { /* To be generated in loop */ });
919
920 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
921 ul_data.data.tlli := '00000001'O;
922
923 /* 3 UL blocks, check we are in same initial CS: */
924 for (var integer i := 0; i < 3; i := i + 1) {
925 /* Prepare a new UL block (CV, random payload) */
926 ul_data.data.mac_hdr.countdown := (7 - i);
927 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
928
929 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
930 f_tx_rlcmac_ul_block(ul_data, lqual_cb);
931
932 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100933 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100934 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
935 }
936
937 if (last_ch_coding != CH_CODING_CS3) {
938 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
939 mtc.stop;
940 }
941
942 setverdict(pass);
943
944 /* Remaining UL blocks are used to make sure regardless of initial
945 /* lqual, we can go lower at any time */
946
947 /* 5 UL blocks, check we are in same initial CS: */
948 for (var integer i := 3; i < 8; i := i + 1) {
949 /* Prepare a new UL block (CV, random payload) */
950 ul_data.data.mac_hdr.countdown := (7 - i);
951 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
952
953 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
954 f_tx_rlcmac_ul_block(ul_data, 0); /* 0 dB, make sure we downgrade CS */
955
956 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100957 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100958
959 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
960 }
961
962 if (last_ch_coding != CH_CODING_CS1) {
963 setverdict(fail, "Channel Coding does not match our expectations (CS-1): ", last_ch_coding);
964 } else {
965 setverdict(pass);
966 }
967}
968
969/* Test the max UL CS set by VTY works fine */
970testcase TC_cs_max_ul() runs on RAW_PCU_Test_CT {
971 var GsmRrMessage rr_imm_ass;
972 var PacketUlAssign ul_tbf_ass;
973 var RlcmacDlBlock dl_block;
974 var boolean ok;
975 var ChCodingCommand last_ch_coding;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100976 var uint32_t unused_fn;
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100977
978 /* Initialize the PCU interface abstraction */
979 f_init_raw(testcasename());
980
981 /* Set maximum allowed UL CS to 3 */
982 g_cs_max_ul := 3;
983 f_pcuvty_set_allowed_cs_mcs();
984 f_pcuvty_set_link_quality_ranges();
985
986 /* Establish an Uplink TBF */
987 ok := f_establish_tbf(rr_imm_ass);
988 if (not ok) {
989 setverdict(fail, "Failed to establish TBF");
990 mtc.stop;
991 }
992
993 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
994 if (not ok) {
995 setverdict(fail, "Immediate Assignment not an Uplink TBF");
996 mtc.stop;
997 }
998
999 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1000 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1001 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
1002 bsn := 0, /* TODO: what should be here? */
1003 blocks := { /* To be generated in loop */ });
1004
1005 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1006 ul_data.data.tlli := '00000001'O;
1007
1008 /* 16 UL blocks */
1009 for (var integer i := 0; i < 16; i := i + 1) {
1010 /* Prepare a new UL block (CV, random payload) */
1011 ul_data.data.mac_hdr.countdown := (15 - i);
1012 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1013
1014 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1015 f_tx_rlcmac_ul_block(ul_data, 40*10); /* 40 dB */
1016
1017 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001018 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001019
1020 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1021 }
1022
1023 if (last_ch_coding != CH_CODING_CS3) {
1024 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
1025 } else {
1026 setverdict(pass);
1027 }
1028}
1029
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001030/* Verify PCU drops TBF after some time of inactivity. */
1031testcase TC_t3169() runs on RAW_PCU_Test_CT {
1032 var PCUIF_info_ind info_ind;
1033 var GsmRrMessage rr_imm_ass;
1034 var PacketUlAssign ul_tbf_ass;
1035 var RlcmacDlBlock dl_block;
1036 var PCUIF_Message pcu_msg;
1037 var octetstring data;
1038 var boolean ok;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001039 var uint32_t unused_fn;
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001040 var OCT4 tlli := '00000001'O;
1041
1042 /* Initialize NS/BSSGP side */
1043 f_init_bssgp();
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001044
1045 info_ind := valueof(ts_PCUIF_INFO_default);
1046 /* Set timer to 1 sec (default 5) to speedup test: */
1047 info_ind.t3169 := 1;
1048
1049 /* Initialize the PCU interface abstraction */
1050 f_init_raw(testcasename(), info_ind);
1051
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001052 /* Establish BSSGP connection to the PCU */
1053 f_bssgp_establish();
1054 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1055
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001056 /* Establish an Uplink TBF */
1057 ok := f_establish_tbf(rr_imm_ass);
1058 if (not ok) {
1059 setverdict(fail, "Failed to establish TBF");
1060 mtc.stop;
1061 }
1062
1063 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1064 if (not ok) {
1065 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1066 mtc.stop;
1067 }
1068
1069 /* Send one UL block and make sure it is ACKED fine */
1070 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001071 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001072 /* UL block should be received in SGSN */
1073 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001074
1075 /* Wait until T3169 fires (plus 1 extra sec to make sure) */
1076 f_sleep(int2float(info_ind.t3169) + 1.0);
1077
1078 /* Send an UL block once again, the TBF should be gone by now so no ACK */
1079 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1080 f_rx_rlcmac_dl_block_exp_dummy(dl_block);
1081}
1082
Pau Espin Pedrolff8da192019-12-05 17:23:58 +01001083/* Verify that a Downlink TBF can be assigned using PACCH shortly after the
1084 * release of prev DL TBF due to MS staying in PDCH for a while (T3192, in PCU
1085 * T3193) after DL TBF release */
1086testcase TC_t3193() runs on RAW_PCU_Test_CT {
1087 var GsmRrMessage rr_imm_ass;
1088 var PacketDlAssign dl_tbf_ass;
1089 var RlcmacDlBlock dl_block;
1090 var octetstring data := f_rnd_octstring(10);
1091 var boolean ok;
1092 var uint32_t sched_fn;
1093 var OCT4 tlli := '00000001'O;
1094 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1095
1096 /* Initialize NS/BSSGP side */
1097 f_init_bssgp();
1098
1099 /* Initialize the PCU interface abstraction */
1100 f_init_raw(testcasename());
1101
1102 /* Establish BSSGP connection to the PCU */
1103 f_bssgp_establish();
1104 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1105
1106 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1107 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1108 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1109 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1110 if (not ok) {
1111 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1112 mtc.stop;
1113 }
1114 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1115 f_sleep(X2002);
1116 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1117
1118 /* ACK the DL block */
1119 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1120 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1121 /* we are done with the DL-TBF here so far, let's clean up our local state: */
1122 ack_nack_desc := valueof(t_AckNackDescription_init)
1123
1124 /* Now that final DL block is ACKED and TBF is released, T3193 in PCU
1125 (T3192 in MS) was started and until it fires the MS will be abailable
1126 on PDCH in case new data arrives from SGSN. Let's verify it: */
1127 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1128 f_rx_rlcmac_dl_block_exp_pkt_ass(dl_block, sched_fn);
1129 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1130
1131 /* Now that we confirmed the new assignment in the dl-tbf, lets receive the data and ack it */
1132 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1133 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1134 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1135}
1136
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001137/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1138 * answered, so TBFs for uplink and later for downlink are created.
1139 */
1140testcase TC_mo_ping_pong() runs on RAW_PCU_Test_CT {
1141 var GsmRrMessage rr_imm_ass;
1142 var PacketUlAssign ul_tbf_ass;
1143 var PacketDlAssign dl_tbf_ass;
1144 var RlcmacDlBlock dl_block;
1145 var PCUIF_Message pcu_msg;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001146 var octetstring data := f_rnd_octstring(10);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001147 var boolean ok;
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +01001148 var uint32_t sched_fn;
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001149 var OCT4 tlli := '00000001'O;
Pau Espin Pedrol89486332019-12-05 14:05:46 +01001150 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001151
1152 /* Initialize NS/BSSGP side */
1153 f_init_bssgp();
1154
1155 /* Initialize the PCU interface abstraction */
1156 f_init_raw(testcasename());
1157
1158 /* Establish BSSGP connection to the PCU */
1159 f_bssgp_establish();
1160 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1161
1162 /* Establish an Uplink TBF */
1163 ok := f_establish_tbf(rr_imm_ass);
1164 if (not ok) {
1165 setverdict(fail, "Failed to establish TBF");
1166 mtc.stop;
1167 }
1168 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1169 if (not ok) {
1170 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1171 mtc.stop;
1172 }
1173
1174 /* Send one UL block and make sure it is ACKED fine */
1175 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001176 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1177 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1178 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001179
1180 /* UL block should be received in SGSN */
1181 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1182
1183 /* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001184 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001185 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1186
1187 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1188 if (not ok) {
1189 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1190 mtc.stop;
1191 }
1192
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001193 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1194 f_sleep(X2002);
Pau Espin Pedrol89486332019-12-05 14:05:46 +01001195 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001196
1197 /* ACK the DL block */
Pau Espin Pedrol89486332019-12-05 14:05:46 +01001198 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 +01001199 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 +02001200}
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001201
Pau Espin Pedrola7b75662019-12-05 16:39:55 +01001202/* Verify that if PCU doesn't get an ACK for first DL block after IMM ASS, it
1203 * will retry by retransmitting both the IMM ASS + DL block after poll (ack)
1204 * timeout occurs (specified by sent RRBP on DL block). */
1205testcase TC_imm_ass_dl_block_retrans() runs on RAW_PCU_Test_CT {
1206 var GsmRrMessage rr_imm_ass;
1207 var PacketDlAssign dl_tbf_ass;
1208 var RlcmacDlBlock dl_block;
1209 var octetstring data := f_rnd_octstring(10);
1210 var boolean ok;
1211 var uint32_t sched_fn;
1212 var OCT4 tlli := '00000001'O;
1213 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1214
1215 /* Initialize NS/BSSGP side */
1216 f_init_bssgp();
1217
1218 /* Initialize the PCU interface abstraction */
1219 f_init_raw(testcasename());
1220
1221 /* Establish BSSGP connection to the PCU */
1222 f_bssgp_establish();
1223 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1224
1225 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1226 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1227 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1228 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1229 if (not ok) {
1230 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1231 mtc.stop;
1232 }
1233
1234 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1235 f_sleep(X2002);
1236 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1237
1238 /* Now we don't ack the dl block (emulate MS failed receiveing IMM ASS
1239 * or GPRS DL, or DL ACK was lost for some reason). As a result, PCU
1240 * should retrigger IMM ASS + GPRS DL procedure after poll timeout. */
1241 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1242 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1243 if (not ok) {
1244 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1245 mtc.stop;
1246 }
1247 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1248 f_sleep(X2002);
1249 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1250
1251 /* ACK the DL block */
1252 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1253 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1254}
1255
Vadim Yanitskiy322c7932020-01-01 23:03:47 +01001256private function f_pkt_paging_match_imsi(in PacketPagingReq req, hexstring imsi) {
1257 var MobileIdentityLV_Paging mi_lv := req.repeated_pageinfo.cs.mobile_identity;
1258 var MobileIdentityV mi := dec_MobileIdentityV(mi_lv.mobile_id);
1259
1260 if (mi_lv.len != 8) { /* 8 octets: type of ID (3 bits) + even/odd flag (1 bit) + 15 BCD-encoded digits (60 bits) */
1261 setverdict(fail, "Mobile Identity length mismatch: ",
1262 "expected: 8, got: ", mi_lv.len);
1263 mtc.stop;
1264 }
1265
1266 /* Make sure MI contains IMSI before referencing it */
1267 if (mi.typeOfIdentity != '001'B) {
1268 setverdict(fail, "Mobile Identity must be of type IMSI ('001'B), ",
1269 "got: ", mi.typeOfIdentity);
1270 mtc.stop;
1271 } else if (mi.oddEvenInd_identity.imsi.digits != imsi) {
1272 setverdict(fail, "Mobile Identity contains unexpected IMSI, ",
1273 "expected: ", imsi, " got: ", mi.oddEvenInd_identity.imsi.digits);
1274 mtc.stop;
1275 }
1276}
1277
Oliver Smith8f9daab2019-10-09 09:27:19 +02001278/* Test CS paging over the BTS<->PCU socket.
1279 * When a (class B or C, not A) MS has an active TBF (or is on the PDCH), the MS can not react on CS paging over CCCH.
1280 * Paging should be send on the PACCH.
1281 *
1282 * 1. Send a Paging Request over PCU socket.
1283 * 2. Send a Ready-To-Send message over PCU socket
1284 * 3. Expect a Paging Frame
1285 */
1286testcase TC_paging_cs_from_bts() runs on RAW_PCU_Test_CT {
1287 var GsmRrMessage rr_imm_ass;
1288 var PacketUlAssign ul_tbf_ass;
1289 var RlcmacDlBlock dl_block;
1290 var boolean ok;
1291 var OCT4 tlli := '00000001'O;
1292 var MobileL3_CommonIE_Types.MobileIdentityLV mi;
1293 var octetstring mi_enc_lv;
Oliver Smith8f9daab2019-10-09 09:27:19 +02001294 var hexstring imsi := f_gen_imsi(42);
1295
1296 /* Initialize NS/BSSGP side */
1297 f_init_bssgp();
1298
1299 /* Initialize the PCU interface abstraction */
1300 f_init_raw(testcasename());
1301
1302 /* Establish BSSGP connection to the PCU */
1303 f_bssgp_establish();
1304 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1305
1306 /* Establish an Uplink TBF */
1307 ok := f_establish_tbf(rr_imm_ass);
1308 if (not ok) {
1309 setverdict(fail, "Failed to establish TBF");
1310 mtc.stop;
1311 }
1312
1313 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1314 if (not ok) {
1315 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1316 mtc.stop;
1317 }
1318
1319
1320 /* build mobile Identity */
1321 mi := valueof(ts_MI_IMSI_LV(imsi));
1322 mi_enc_lv := enc_MobileIdentityLV(mi);
1323 /* Send paging request */
1324 BTS.send(ts_PCUIF_PAG_REQ(bts_nr := 0, id_lv := mi_enc_lv, chan_needed := 0,
1325 sapi :=PCU_IF_SAPI_PDTCH));
1326
1327 /* Receive it on BTS side towards MS */
1328 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
Vadim Yanitskiy5e518732020-01-01 21:27:18 +01001329
Vadim Yanitskiy322c7932020-01-01 23:03:47 +01001330 /* Make sure that Packet Paging Request contains the same IMSI */
1331 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1332
Oliver Smith8f9daab2019-10-09 09:27:19 +02001333 setverdict(pass);
1334}
1335
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001336/* Test CS paging over Gb (SGSN->PCU->BTS[PDCH]).
1337 */
1338private function f_tc_paging_cs_from_sgsn(Nsvci bvci) runs on RAW_PCU_Test_CT {
1339 var GsmRrMessage rr_imm_ass;
1340 var PacketUlAssign ul_tbf_ass;
1341 var RlcmacDlBlock dl_block;
1342 var boolean ok;
1343 var OCT4 tlli := '00000001'O;
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001344 var hexstring imsi := f_gen_imsi(42);
1345
1346 /* Initialize NS/BSSGP side */
1347 f_init_bssgp();
1348
1349 /* Initialize the PCU interface abstraction */
1350 f_init_raw(testcasename());
1351
1352 /* Establish BSSGP connection to the PCU */
1353 f_bssgp_establish();
1354 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1355
1356 /* Establish an Uplink TBF */
1357 ok := f_establish_tbf(rr_imm_ass);
1358 if (not ok) {
1359 setverdict(fail, "Failed to establish TBF");
1360 mtc.stop;
1361 }
1362
1363 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1364 if (not ok) {
1365 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1366 mtc.stop;
1367 }
1368
1369 /* Send paging request */
1370 BSSGP[0].send(ts_BSSGP_CS_PAGING_IMSI(bvci, imsi));
1371
1372 /* Receive it on BTS side towards MS */
1373 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
1374
Vadim Yanitskiy322c7932020-01-01 23:03:47 +01001375 /* Make sure that Packet Paging Request contains the same IMSI */
1376 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1377
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001378 setverdict(pass);
1379}
1380
1381testcase TC_paging_cs_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1382 f_tc_paging_cs_from_sgsn(0);
1383}
1384
1385testcase TC_paging_cs_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1386 f_tc_paging_cs_from_sgsn(mp_gb_cfg.bvci);
1387}
1388
1389/* Test PS paging over Gb (SGSN->PCU->BTS[CCCH]).
1390 */
1391private function f_tc_paging_ps_from_sgsn(Nsvci bvci) runs on RAW_PCU_Test_CT {
1392 var GsmRrMessage rr_pag_req1;
1393 var OCT4 tlli := '00000001'O;
Pau Espin Pedrol925818a2020-01-02 14:06:51 +01001394 var integer imsi_suff_rx;
1395 var integer imsi_suff_tx := 423;
1396 var hexstring imsi := f_gen_imsi(imsi_suff_tx);
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001397
1398 /* Initialize NS/BSSGP side */
1399 f_init_bssgp();
1400
1401 /* Initialize the PCU interface abstraction */
1402 f_init_raw(testcasename());
1403
1404 /* Establish BSSGP connection to the PCU */
1405 f_bssgp_establish();
1406 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1407
1408 /* Send paging request */
1409 BSSGP[0].send(ts_BSSGP_PS_PAGING_IMSI(bvci, imsi));
1410
1411 /* Receive it on BTS side towards MS */
Pau Espin Pedrol925818a2020-01-02 14:06:51 +01001412 f_pcuif_rx_pch_pag_req1(imsi_suff_rx, rr_pag_req1);
1413 if (imsi_suff_rx != imsi_suff_tx) {
1414 setverdict(fail, "Wrong IMSI suffix: expected ", imsi_suff_tx, " but received ", imsi_suff_rx);
1415 mtc.stop;
1416 }
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001417
1418 setverdict(pass);
1419}
1420
1421testcase TC_paging_ps_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1422 f_tc_paging_ps_from_sgsn(0);
1423}
1424
1425testcase TC_paging_ps_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1426 f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvci);
1427}
1428
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001429control {
Harald Welte7fd25cf2019-03-21 22:14:02 +01001430 execute( TC_pcuif_suspend() );
Vadim Yanitskiy1f72b0a2019-10-01 05:58:45 +07001431 execute( TC_ta_ptcch_idle() );
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +02001432 execute( TC_ta_rach_imm_ass() );
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001433 execute( TC_ta_ptcch_ul_multi_tbf() );
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001434 execute( TC_cs_lqual_ul_tbf() );
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001435 execute( TC_cs_initial_ul() );
1436 execute( TC_cs_max_ul() );
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001437 execute( TC_t3169() );
Pau Espin Pedrolff8da192019-12-05 17:23:58 +01001438 execute( TC_t3193() );
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001439 execute( TC_mo_ping_pong() );
Pau Espin Pedrola7b75662019-12-05 16:39:55 +01001440 execute( TC_imm_ass_dl_block_retrans() );
Oliver Smith8f9daab2019-10-09 09:27:19 +02001441 execute( TC_paging_cs_from_bts() );
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001442 execute (TC_paging_cs_from_sgsn_sign() );
1443 execute (TC_paging_cs_from_sgsn_ptp() );
1444 execute (TC_paging_ps_from_sgsn_sign() );
1445 execute (TC_paging_ps_from_sgsn_ptp() );
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001446}
1447
1448
1449
1450
1451
1452
1453}