blob: ac2aaf3b0168add4f034593e37bad5c337ba017d [file] [log] [blame]
Harald Weltea0895f92018-03-08 11:51:23 +01001module PCU_Tests {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002
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
9/* (C) 2018-2019 Harald Welte <laforge@gnumonks.org>
10 * (C) 2019 Vadim Yanitskiy <axilirator@gmail.com>
11 * 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
19friend module PCU_Tests_NS;
20
21import from General_Types all;
22import from Osmocom_Types all;
23import from GSM_Types all;
24import from GSM_RR_Types all;
25
26import from Osmocom_VTY_Functions all;
27import from TELNETasp_PortType all;
28
29import from MobileL3_GMM_SM_Types all;
30import from RLCMAC_CSN1_Types all;
Pau Espin Pedrole8d7d162020-04-29 19:07:36 +020031import from RLCMAC_CSN1_Templates all;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +020032import from RLCMAC_Types all;
Pau Espin Pedrole8d7d162020-04-29 19:07:36 +020033import from RLCMAC_Templates all;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +020034
35import from MobileL3_CommonIE_Types all;
36import from L3_Templates all;
37
38import from NS_Types all;
39import from BSSGP_Types all;
40import from Osmocom_Gb_Types all;
41
42import from BSSGP_Emulation all; /* BssgpConfig */
43import from NS_Emulation all; /* NSConfiguration */
44
45import from UD_Types all;
46import from PCUIF_Types all;
47import from PCUIF_CodecPort all;
48import from PCUIF_Components all;
49import from IPL4asp_Types all;
50import from Native_Functions all;
51import from SGSN_Components all;
52
53modulepar {
54 charstring mp_pcu_sock_path := PCU_SOCK_DEFAULT;
55
56 float X2002 := 0.2; /* Timer -2002, IMM ASSIGN confirm delay */
57}
58
59
60/* FIXME: make sure to use parameters from mp_gb_cfg.cell_id in the PCU INFO IND */
61private template (value) PCUIF_info_ind ts_PCUIF_INFO_default := {
62 version := PCU_IF_VERSION,
63 flags := c_PCUIF_Flags_default,
64 trx := valueof(ts_PCUIF_InfoTrxs_def),
65 bsic := 7,
66 mcc := 262,
67 mnc := 42,
68 mnc_3_digits := 0,
69 lac := 13135,
70 rac := 0,
71 nsei := mp_nsconfig.nsei,
72 nse_timer := { 3, 3, 3, 3, 30, 3, 10 },
73 cell_timer := { 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 },
74 cell_id := 20960,
75 repeat_time := 5 * 50,
76 repeat_count := 3,
77 bvci := mp_gb_cfg.bvci,
78 t3142 := 20,
79 t3169 := 5,
80 t3191 := 5,
81 t3193_10ms := 160,
82 t3195 := 5,
83 t3101 := 10,
84 t3103 := 4,
85 t3105 := 8,
86 cv_countdown := 15,
87 dl_tbf_ext := 250 * 10, /* ms */
88 ul_tbf_ext := 250 * 10, /* ms */
89 initial_cs := 2,
90 initial_mcs := 6,
91 nsvci := { mp_nsconfig.nsvci, 0 },
92 local_pprt := { mp_nsconfig.remote_udp_port, 0 },
93 remote_port := { mp_nsconfig.local_udp_port, 0 },
94 remote_ip := { f_inet_haddr(mp_nsconfig.local_ip) , '00000000'O }
95}
96
97type record lqual_range {
98 /* component reference to the IPA_Client component used for RSL */
99 uint8_t low,
100 uint8_t high
101}
102
103type component RAW_PCU_Test_CT extends bssgp_CT {
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700104 /* PCU interface abstraction component */
105 var RAW_PCUIF_CT vc_PCUIF;
106 /* Virtual BTS component */
107 var RAW_PCU_BTS_CT vc_BTS;
108
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200109 /* Connection to the BTS component (one for now) */
110 port RAW_PCU_MSG_PT BTS;
111 /* Connection to the PCUIF component */
112 port RAW_PCU_MSG_PT PCUIF;
113 /* VTY connection to the PCU */
114 port TELNETasp_PT PCUVTY;
115
116 /* Uplink CS/MCS thresholds, default from pcu_main.c: */
117 var lqual_range g_cs_lqual_ranges[4] := {{low := 0, high := 6},
118 {low := 5, high := 8},
119 {low := 7, high := 13},
120 {low := 12,high := 35}};
121 var lqual_range g_mcs_lqual_ranges[9] := {{low := 0, high := 6},
122 {low := 5, high := 8},
123 {low := 7, high := 13},
124 {low := 12,high := 15},
125 {low := 14, high := 17},
126 {low := 16, high := 18},
127 {low := 17,high := 20},
128 {low := 19, high := 24},
129 {low := 23,high := 35}};
130 var uint8_t g_cs_initial_dl := 1;
131 var uint8_t g_cs_initial_ul := 1;
132 var uint8_t g_mcs_initial_dl := 1;
133 var uint8_t g_mcs_initial_ul := 1;
134 var uint8_t g_cs_max_dl := 4;
135 var uint8_t g_cs_max_ul := 4;
136 var uint8_t g_mcs_max_dl := 9;
137 var uint8_t g_mcs_max_ul := 9;
138
139 var boolean g_egprs_only := false;
140
141 /* Guard timeout */
142 timer g_T_guard := 60.0;
143};
144
145private altstep as_Tguard_RAW() runs on RAW_PCU_Test_CT {
146 [] g_T_guard.timeout {
147 setverdict(fail, "Timeout of T_guard");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700148 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200149 }
150}
151
152private function f_pcuvty_set_allowed_cs_mcs() runs on RAW_PCU_Test_CT {
153 f_vty_config2(PCUVTY, {"pcu"}, "cs " & int2str(g_cs_initial_dl) & " " & int2str(g_cs_initial_ul));
154 f_vty_config2(PCUVTY, {"pcu"}, "cs max " & int2str(g_cs_max_dl) & " " & int2str(g_cs_max_ul));
155
156 f_vty_config2(PCUVTY, {"pcu"}, "mcs " & int2str(g_mcs_initial_dl) & " " & int2str(g_mcs_initial_ul));
157 f_vty_config2(PCUVTY, {"pcu"}, "mcs max " & int2str(g_mcs_max_dl) & " " & int2str(g_mcs_max_ul));
158}
159
160private function f_pcuvty_set_link_quality_ranges() runs on RAW_PCU_Test_CT {
161 var charstring cmd;
162
163 cmd := "cs link-quality-ranges" &
164 " cs1 " & int2str(g_cs_lqual_ranges[0].high) &
165 " cs2 " & int2str(g_cs_lqual_ranges[1].low) & " " & int2str(g_cs_lqual_ranges[1].high) &
166 " cs3 " & int2str(g_cs_lqual_ranges[2].low) & " " & int2str(g_cs_lqual_ranges[2].high) &
167 " cs4 " & int2str(g_cs_lqual_ranges[3].low);
168 f_vty_config2(PCUVTY, {"pcu"}, cmd);
169
170 cmd := "mcs link-quality-ranges" &
171 " mcs1 " & int2str(g_mcs_lqual_ranges[0].high) &
172 " mcs2 " & int2str(g_mcs_lqual_ranges[1].low) & " " & int2str(g_mcs_lqual_ranges[1].high) &
173 " mcs3 " & int2str(g_mcs_lqual_ranges[2].low) & " " & int2str(g_mcs_lqual_ranges[2].high) &
174 " mcs4 " & int2str(g_mcs_lqual_ranges[3].low) & " " & int2str(g_mcs_lqual_ranges[3].high) &
175 " mcs5 " & int2str(g_mcs_lqual_ranges[4].low) & " " & int2str(g_mcs_lqual_ranges[4].high) &
176 " mcs6 " & int2str(g_mcs_lqual_ranges[5].low) & " " & int2str(g_mcs_lqual_ranges[5].high) &
177 " mcs7 " & int2str(g_mcs_lqual_ranges[6].low) & " " & int2str(g_mcs_lqual_ranges[6].high) &
178 " mcs8 " & int2str(g_mcs_lqual_ranges[7].low) & " " & int2str(g_mcs_lqual_ranges[7].high) &
179 " mcs9 " & int2str(g_mcs_lqual_ranges[8].low);
180 f_vty_config2(PCUVTY, {"pcu"}, cmd);
181}
182
183private function f_init_vty(charstring id) runs on RAW_PCU_Test_CT {
184 map(self:PCUVTY, system:PCUVTY);
185 f_vty_set_prompts(PCUVTY);
186 f_vty_transceive(PCUVTY, "enable");
187
188 if (g_egprs_only) {
189 f_vty_config2(PCUVTY, {"pcu"}, "egprs only");
190 } else {
191 f_vty_config2(PCUVTY, {"pcu"}, "no egprs");
192 }
193}
194
Pau Espin Pedrol2456dad2020-04-30 20:22:38 +0200195function f_init_raw(charstring id, template (value) PCUIF_info_ind info_ind := ts_PCUIF_INFO_default)
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200196runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200197 /* Start the guard timer */
198 g_T_guard.start;
199 activate(as_Tguard_RAW());
200
201 /* Init PCU interface component */
202 vc_PCUIF := RAW_PCUIF_CT.create("PCUIF-" & id);
203 connect(vc_PCUIF:MTC, self:PCUIF);
204 map(vc_PCUIF:PCU, system:PCU);
205
206 /* Create one BTS component (we may want more some day) */
207 vc_BTS := RAW_PCU_BTS_CT.create("BTS-" & id);
208 connect(vc_BTS:PCUIF, vc_PCUIF:BTS);
209 connect(vc_BTS:TC, self:BTS);
210
211 f_init_vty(id);
212
213 vc_PCUIF.start(f_PCUIF_CT_handler(mp_pcu_sock_path));
214 vc_BTS.start(f_BTS_CT_handler(0, valueof(info_ind)));
215
216 /* Wait until the BTS is ready (SI13 negotiated) */
217 BTS.receive(tr_RAW_PCU_EV(BTS_EV_SI13_NEGO));
218}
219
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700220private function f_shutdown(charstring file, integer line,
221 boolean final := false)
222runs on RAW_PCU_Test_CT {
223 /* Determine if the test case was aborted in the middle */
224 if (not final) {
225 log("Test case ", testcasename(), " aborted at ", file, ":", line);
226 } else {
227 /* Guard verdict to avoid 'none' */
228 setverdict(pass);
229 }
230
231 /* Properly shutdown virtual BTS and its clock generator */
232 BTS.send(ts_RAW_PCU_CMD(GENERAL_CMD_SHUTDOWN));
233 vc_BTS.done; /* wait untill it's done */
234
235 /* Shutdown the others and MTC */
236 all component.stop;
237 mtc.stop;
238}
239
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200240template AckNackDescription t_AckNackDescription_init := {
241 final_ack := '0'B,
242 starting_seq_nr := 0,
243 receive_block_bitmap := '0000000000000000000000000000000000000000000000000000000000000000'B
244}
245
246private function f_rlcmac_dl_block_get_tfi(RlcmacDlBlock dl_block) return uint5_t {
247 if (ischosen(dl_block.data)) {
248 return dl_block.data.mac_hdr.hdr_ext.tfi;
249 } else {
250 return dl_block.data_egprs.mac_hdr.tfi;
251 }
252}
253
254/* TS 44.060 sec 12.3 Ack/Nack Description */
255private function f_acknackdesc_ack_block(inout AckNackDescription desc, RlcmacDlBlock dl_block, BIT1 final_ack := '0'B)
256{
257 var uint7_t bsn;
258 var integer i;
259 var integer inc;
260
261 if (ischosen(dl_block.data)) {
262 bsn := dl_block.data.mac_hdr.hdr_ext.bsn;
263 } else {
264 bsn := dl_block.data_egprs.mac_hdr.bsn1;
265 }
266
267 inc := bsn - desc.starting_seq_nr + 1;
268 /* Filling hole? */
269 if (bsn < desc.starting_seq_nr) {
270 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - (desc.starting_seq_nr - bsn)] := int2bit(1, 1);
271 return;
272 }
273
274 /* SSN is increased, and so RBB values need to be moved */
275 for (i := 0; i < lengthof(desc.receive_block_bitmap) - inc; i := i+1) {
276 desc.receive_block_bitmap[i] := desc.receive_block_bitmap[i + inc];
277 }
278 for (i := lengthof(desc.receive_block_bitmap) - inc; i < lengthof(desc.receive_block_bitmap) - 1; i := i+1) {
279 desc.receive_block_bitmap[i] := int2bit(0, 1);
280 }
281 /* Now we can set current bit and update SSN */
282 desc.starting_seq_nr := bsn + 1;
283 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - 1] := int2bit(1, 1);
284
285 /* Finally update the final_ack bit as requested: */
286 desc.final_ack := final_ack;
287}
288
289/* This function can be used to send DATA.cnf in response to the IUT originated DATA.req.
290 * NOTE: it's the responsibility of caller to make sure that pcu_msg contains u.data_req. */
291private function f_pcuif_tx_data_cnf(in PCUIF_Message pcu_msg)
292runs on RAW_PCU_Test_CT {
293 var PCUIF_Message pcu_msg_cnf := {
294 msg_type := PCU_IF_MSG_DATA_CNF,
295 bts_nr := pcu_msg.bts_nr,
296 spare := pcu_msg.spare,
297 u := { data_cnf := pcu_msg.u.data_req }
298 };
299
300 /* PCU wants DATA.cnf containing basically everything that was in DATA.req,
301 * but PCU_IF_SAPI_PCH is a special case - paging group shall be excluded. */
302 if (pcu_msg.u.data_req.sapi == PCU_IF_SAPI_PCH) {
303 pcu_msg_cnf.u.data_cnf.data := substr(pcu_msg.u.data_req.data, 3,
304 pcu_msg.u.data_req.len - 3);
305 }
306
307 BTS.send(pcu_msg_cnf);
308}
309
310private function f_pcuif_rx_imm_ass(out GsmRrMessage rr_imm_ass,
311 template PCUIF_Sapi sapi := PCU_IF_SAPI_AGCH,
312 template GsmRrMessage t_imm_ass := ?,
313 uint8_t bts_nr := 0)
314runs on RAW_PCU_Test_CT return boolean {
315 var PCUIF_Message pcu_msg;
316 var octetstring data;
317 timer T;
318
319 T.start(2.0);
320 alt {
321 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
322 sapi := sapi, data := ?)) -> value pcu_msg {
323 /* On PCH the payload is prefixed with paging group (3 octets): skip it.
324 * TODO: add an additional template parameter, so we can match it. */
325 if (pcu_msg.u.data_req.sapi == PCU_IF_SAPI_PCH) {
326 data := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
327 } else {
328 data := pcu_msg.u.data_req.data;
329 }
330
331 rr_imm_ass := dec_GsmRrMessage(data);
332 if (not match(rr_imm_ass, t_imm_ass)) {
333 /* Not for us? Wait for more. */
334 repeat;
335 }
336
337 log("Rx Immediate Assignment: ", rr_imm_ass);
338 setverdict(pass);
339 return true;
340 }
341 [] BTS.receive { repeat; }
342 [] T.timeout {
343 setverdict(fail, "Timeout waiting for Immediate Assignment");
344 }
345 }
346
347 return false;
348}
349
Vadim Yanitskiyf74ae992020-05-06 16:05:51 +0700350/* One phase packet access (see 3GPP TS 44.018, table 9.1.8.1) */
351private const BIT8 chan_req_def := '01111000'B;
352
Vadim Yanitskiy85cb9912020-05-06 16:29:43 +0700353/* Establish an Uplink TBF by sending RACH.ind towards the PCU */
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200354private function f_establish_tbf(out GsmRrMessage rr_imm_ass, uint8_t bts_nr := 0,
Vadim Yanitskiyf74ae992020-05-06 16:05:51 +0700355 uint16_t ra := bit2int(chan_req_def),
356 uint8_t is_11bit := 0,
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200357 PCUIF_BurstType burst_type := BURST_TYPE_0,
358 TimingAdvance ta := 0)
359runs on RAW_PCU_Test_CT return boolean {
360 var uint32_t fn;
361
362 /* FIXME: ask the BTS component to give us the current TDMA fn */
363 fn := 1337 + ta;
364
365 /* Send RACH.ind */
366 log("Sending RACH.ind on fn=", fn, " with RA=", ra, ", TA=", ta);
367 BTS.send(ts_PCUIF_RACH_IND(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
368 ra := ra, is_11bit := is_11bit,
369 burst_type := burst_type,
370 fn := fn, arfcn := 871,
371 qta := ta * 4));
372
373 /* 3GPP TS 44.018, table 9.1.8.1, note 2b: Request Reference shall be set to 127
374 * when Immediate Assignment is triggered by EGPRS Packet Channel Request. Here
375 * we assume that 11 bit RA always contains EGPRS Packet Channel Request. */
376 if (is_11bit != 0) { ra := 127; }
377
378 /* Expect Immediate (TBF) Assignment on TS0/AGCH */
379 return f_pcuif_rx_imm_ass(rr_imm_ass, PCU_IF_SAPI_AGCH,
Vadim Yanitskiy85cb9912020-05-06 16:29:43 +0700380 tr_IMM_TBF_ASS(false, ra, fn),
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200381 bts_nr := bts_nr);
382}
383
Vadim Yanitskiy5b649cc2020-05-06 16:35:38 +0700384private function f_imm_ass_verify_ul_tbf_ass(in GsmRrMessage rr_imm_ass, out PacketUlAssign ul_tbf_ass)
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200385runs on RAW_PCU_Test_CT return boolean {
386
387 /* Make sure we received an UL TBF Assignment */
388 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
389 ul_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
390 log("Rx Uplink TBF assignment: ", ul_tbf_ass);
391 setverdict(pass);
392 } else {
393 setverdict(fail, "Failed to match UL TBF Assignment");
394 return false;
395 }
396
397 /* Make sure we have got a TBF with Dynamic Block Allocation */
398 if (ul_tbf_ass.dynamic == omit) {
399 setverdict(fail, "Single Block Allocation is not handled by ", testcasename());
400 return false;
401 }
402
403 return true;
404}
405
Vadim Yanitskiy5b649cc2020-05-06 16:35:38 +0700406private function f_imm_ass_verify_dl_tbf_ass(in GsmRrMessage rr_imm_ass, out PacketDlAssign dl_tbf_ass)
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200407runs on RAW_PCU_Test_CT return boolean {
408
409 /* Make sure we received a DL TBF Assignment */
410 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := true, rest := tr_IaRestOctets_DLAss(?)))) {
411 dl_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.dl;
412 log("Rx Downlink TBF assignment: ", dl_tbf_ass);
413 setverdict(pass);
414 } else {
415 setverdict(fail, "Failed to match DL TBF Assignment");
416 return false;
417 }
418
419 return true;
420}
421
422/* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
Pau Espin Pedrol2456dad2020-04-30 20:22:38 +0200423function f_pcuif_tx_data_ind(octetstring data, int16_t lqual_cb := 0, uint32_t fn := 0)
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200424runs on RAW_PCU_Test_CT {
425 var template RAW_PCU_EventParam ev_param := {tdma_fn := ? };
426 BTS.send(ts_PCUIF_DATA_IND(bts_nr := 0, trx_nr := 0, ts_nr := 7, block_nr := 0,
427 sapi := PCU_IF_SAPI_PDTCH, data := data,
428 fn := fn, arfcn := 871, lqual_cb := lqual_cb));
429 if (fn != 0) {
430 ev_param := {tdma_fn := fn };
431 }
432 BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PDTCH_BLOCK_SENT, ev_param));
433}
434
435/* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
436private function f_pcuif_rx_data_req(out PCUIF_Message pcu_msg)
437runs on RAW_PCU_Test_CT {
438 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
439 sapi := PCU_IF_SAPI_PDTCH, fn := 0,
440 arfcn := 871, block_nr := 0));
441 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
442 sapi := PCU_IF_SAPI_PDTCH)) -> value pcu_msg;
443}
444
445/* Expect an Immediate Assignment (paging) from PCU on PCUIF on specified sapi. */
446private function f_pcuif_rx_pch_imm_tbf_ass(out GsmRrMessage rr_imm_ass)
447runs on RAW_PCU_Test_CT {
448 var PCUIF_Message pcu_msg;
449 var octetstring macblock;
450 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
451 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
452 /* First 3 bytes contain paging group: */
453 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
454 rr_imm_ass := dec_GsmRrMessage(macblock);
455 if (not match(rr_imm_ass, tr_IMM_TBF_ASS())) {
456 setverdict(fail, "Failed to match Immediate Assignment: ", rr_imm_ass);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700457 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200458 }
459 f_pcuif_tx_data_cnf(pcu_msg);
460}
461
462/* Expect a Paging Request Type 1 from PCU on PCUIF on specified sapi. */
463private function f_pcuif_rx_pch_pag_req1(template MobileIdentityV mi1 := ?,
464 template integer pag_group := ?)
465runs on RAW_PCU_Test_CT return GsmRrMessage {
466 var GsmRrMessage rr_pag_req1;
467 var PCUIF_Message pcu_msg;
468 var octetstring imsi_suff_octstr;
469 var integer pag_group_rx;
470 var octetstring macblock;
471
472 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
473 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
474
475 /* First 3 bytes contain IMSI suffix to calculate paging group: */
476 imsi_suff_octstr := substr(pcu_msg.u.data_req.data, 0, 3);
477 pag_group_rx := str2int(oct2char(imsi_suff_octstr[0])) * 100 +
478 str2int(oct2char(imsi_suff_octstr[1])) * 10 +
479 str2int(oct2char(imsi_suff_octstr[2]));
480
481 /* Make sure we've got RR Paging Request Type 1 for a given MI */
482 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
483 rr_pag_req1 := dec_GsmRrMessage(macblock);
484 if (not match(rr_pag_req1, tr_PAG_REQ1(tr_MI_LV(mi1)))) {
485 setverdict(fail, "Failed to match Paging Request Type 1: ", rr_pag_req1);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700486 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200487 }
488
489 /* Make sure that received paging froup matches the expected one */
490 if (not match(pag_group_rx, pag_group)) {
491 setverdict(fail, "Paging group", pag_group_rx, " does not match expected ", pag_group);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700492 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200493 }
494
495 f_pcuif_tx_data_cnf(pcu_msg);
496 return rr_pag_req1;
497}
498
499private function f_tx_rlcmac_ul_block(template (value) RlcmacUlBlock ul_data, int16_t lqual_cb := 0, uint32_t fn := 0)
500runs on RAW_PCU_Test_CT {
501 var octetstring data;
502 /* Encode the payload of DATA.ind */
503 data := enc_RlcmacUlBlock(valueof(ul_data));
504 data := f_pad_oct(data, 23, '00'O); /* CS-1 */
505
506 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
507 f_pcuif_tx_data_ind(data, lqual_cb, fn);
508}
509
510private function f_tx_rlcmac_ul_n_blocks(PacketUlAssign ul_tbf_ass, integer num_blocks := 1)
511runs on RAW_PCU_Test_CT {
512 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
513 tfi := ul_tbf_ass.dynamic.tfi_assignment,
514 cv := num_blocks - 1, /* num UL blocks to be sent (to be overridden in loop) */
515 bsn := 0, /* TODO: what should be here? */
516 blocks := { /* To be generated in loop */ });
517
518 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
519 ul_data.data.tlli := '00000001'O;
520
521 for (var integer i := 0; i < num_blocks; i := i + 1) {
522 /* Prepare a new UL block (CV, random payload) */
523 ul_data.data.mac_hdr.countdown := (num_blocks - i - 1);
524 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
525 f_tx_rlcmac_ul_block(ul_data);
526 }
527}
528
529private function f_rx_rlcmac_dl_block(out RlcmacDlBlock dl_block, out uint32_t dl_fn, template (present) CodingScheme exp_cs_mcs := ?)
530runs on RAW_PCU_Test_CT {
531 var PCUIF_Message pcu_msg;
532 f_pcuif_rx_data_req(pcu_msg);
533 dl_block := dec_RlcmacDlBlock(pcu_msg.u.data_req.data);
534 dl_fn := pcu_msg.u.data_req.fn;
535
536 var integer len := lengthof(pcu_msg.u.data_req.data);
537 var CodingScheme cs_mcs := f_rlcmac_block_len2cs_mcs(len)
538 if (not match(f_rlcmac_block_len2cs_mcs(len), exp_cs_mcs)) {
539 setverdict(fail, "Failed to match Coding Scheme exp ", exp_cs_mcs, " vs ", cs_mcs, " (", len, ")");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700540 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200541 }
542}
543
544private function f_rx_rlcmac_dl_block_exp_ack_nack(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
545runs on RAW_PCU_Test_CT {
546 var uint32_t dl_fn;
547
548 f_rx_rlcmac_dl_block(dl_block, dl_fn);
549 if (not match(dl_block, tr_RLCMAC_UL_ACK_NACK(ul_tfi := ?, tlli := ?))) {
550 setverdict(fail, "Failed to match Packet Uplink ACK / NACK");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700551 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200552 }
553
554 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
555}
556
557private function f_rx_rlcmac_dl_block_exp_dummy(out RlcmacDlBlock dl_block)
558runs on RAW_PCU_Test_CT {
559 var uint32_t dl_fn;
560
561 f_rx_rlcmac_dl_block(dl_block, dl_fn);
562 if (not match(dl_block, tr_RLCMAC_DUMMY_CTRL())) {
563 setverdict(fail, "Failed to match Packet DUMMY DL");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700564 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200565 }
566}
567
568private function f_rx_rlcmac_dl_block_exp_pkt_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
569runs on RAW_PCU_Test_CT {
570 var uint32_t dl_fn;
571
572 f_rx_rlcmac_dl_block(dl_block, dl_fn);
573 if (not match(dl_block, tr_RLCMAC_DL_PACKET_ASS())) {
574 setverdict(fail, "Failed to match Packet Downlink Assignment");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700575 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200576 }
577
578 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
579}
580
581private function f_rx_rlcmac_dl_block_exp_pkt_ul_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
582runs on RAW_PCU_Test_CT {
583 var uint32_t dl_fn;
584
585 f_rx_rlcmac_dl_block(dl_block, dl_fn);
586 if (not match(dl_block, tr_RLCMAC_UL_PACKET_ASS())) {
587 setverdict(fail, "Failed to match Packet Uplink Assignment");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700588 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200589 }
590
591 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
592}
593
594
595private function f_rx_rlcmac_dl_block_exp_pkt_pag_req(out RlcmacDlBlock dl_block)
596runs on RAW_PCU_Test_CT {
597 var uint32_t dl_fn;
598
599 f_rx_rlcmac_dl_block(dl_block, dl_fn);
600 if (not match(dl_block, tr_RLCMAC_PACKET_PAG_REQ())) {
601 setverdict(fail, "Failed to match Packet Paging Request: ", dl_block, " vs ", tr_RLCMAC_PACKET_PAG_REQ());
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700602 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200603 }
604}
605
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700606private function f_rlcmac_dl_block_verify_data_gprs(RlcmacDlBlock dl_block, uint32_t dl_fn,
607 out uint32_t ack_fn, octetstring data,
608 template (present) uint7_t exp_bsn := ?,
609 template (present) CodingScheme exp_cs := ?)
610runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200611 log("verifying dl data block (gprs): ", dl_block);
612
613 ack_fn := dl_fn + f_rrbp_fn_delay(dl_block.data.mac_hdr.mac_hdr.rrbp);
614
615 if (not match(dl_block.data.mac_hdr.hdr_ext.bsn, exp_bsn)) {
616 setverdict(fail, "DL block BSN doesn't match: ",
617 dl_block.data.blocks[0].hdr.length_ind, " vs exp ", exp_bsn);
618 }
619
620 if (lengthof(dl_block.data.blocks) < 1) {
621 setverdict(fail, "DL block has no LLC payload: ", dl_block);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700622 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200623 }
624
625 if (ispresent(dl_block.data.blocks[0].hdr) and dl_block.data.blocks[0].hdr.length_ind != lengthof(data)) {
626 setverdict(fail, "DL block has LLC header with wrong expected size: ",
627 dl_block.data.blocks[0].hdr.length_ind, " vs ", lengthof(data));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700628 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200629 }
630
631 if (dl_block.data.blocks[0].payload != data) {
632 setverdict(fail, "Failed to match content of LLC payload in DL Block: ", dl_block, " vs ", data);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700633 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200634 }
635
636 /* Check next data blocks contain dummy frames */
637 if (lengthof(dl_block.data.blocks) > 1 and substr(dl_block.data.blocks[1].payload, 0, 3) != '43C001'O) {
638 setverdict(fail, "Second data payload is not a dummy frame: ", dl_block.data.blocks[1].payload);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700639 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200640 }
641
642 /* TODO: check exp_cs */
643}
644
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700645private function f_rlcmac_dl_block_verify_data_egprs(RlcmacDlBlock dl_block, uint32_t dl_fn,
646 out uint32_t ack_fn, octetstring data,
647 template (present) uint14_t exp_bsn := ?,
648 template (present) CodingScheme exp_cs := ?)
649runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200650 log("verifying dl data block (egprs): ", dl_block);
651
652 ack_fn := dl_fn + f_rrbp_fn_delay(dl_block.data_egprs.mac_hdr.rrbp);
653
654 if (not match(dl_block.data_egprs.mac_hdr.bsn1, exp_bsn)) {
655 setverdict(fail, "DL block BSN doesn't match: ",
656 dl_block.data_egprs.blocks[0].hdr.length_ind, " vs exp ", exp_bsn);
657 }
658
659 if (lengthof(dl_block.data_egprs.blocks) < 1) {
660 setverdict(fail, "DL block has no LLC payload: ", dl_block);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700661 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200662 }
663
664 if (ispresent(dl_block.data_egprs.blocks[0].hdr) and dl_block.data_egprs.blocks[0].hdr.length_ind != lengthof(data)) {
665 setverdict(fail, "DL block has LLC header with wrong expected size: ",
666 dl_block.data_egprs.blocks[0].hdr.length_ind, " vs ", lengthof(data));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700667 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200668 }
669
670 if (dl_block.data_egprs.blocks[0].payload != data) {
671 setverdict(fail, "Failed to match content of LLC payload in DL Block: ", dl_block, " vs ", data);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700672 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200673 }
674
675 /* Check next data blocks contain dummy frames */
676 if (lengthof(dl_block.data_egprs.blocks) > 1 and substr(dl_block.data_egprs.blocks[1].payload, 0, 3) != '43C001'O) {
677 setverdict(fail, "Second data payload is not a dummy frame: ", dl_block.data.blocks[1].payload);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700678 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200679 }
680
681 /* TODO: Check exp_cs. In the case of EGPRS, first check mac_hdr.header_type and then decode CPS = exp_cs based on mac_hdr.header_type.
682 See wireshark's egprs_Header_type1_coding_puncturing_scheme_to_mcs. */
683}
684
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700685private function f_rx_rlcmac_dl_block_exp_data(out RlcmacDlBlock dl_block, out uint32_t ack_fn,
686 octetstring data,
687 template (present) uint7_t exp_bsn := ?,
688 template (present) CodingScheme exp_cs := ?)
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200689runs on RAW_PCU_Test_CT {
690 var PCUIF_Message pcu_msg;
691 var uint32_t dl_fn;
692 var boolean is_egprs := false;
693 var template RlcmacDlBlock dl_template := tr_RLCMAC_DATA_RRBP;
694 dl_template.data.blocks := ?;
695
696 f_rx_rlcmac_dl_block(dl_block, dl_fn);
697 if (not match(dl_block, dl_template)) {
698 dl_template := tr_RLCMAC_DATA_EGPRS;
699 dl_template.data_egprs.blocks := ?;
700 if (not match(dl_block, dl_template)) {
701 setverdict(fail, "Failed to match Packet data: ", dl_block, " vs ", dl_template);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700702 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200703 }
704 is_egprs := true;
705 }
706
707 if (is_egprs) {
708 f_rlcmac_dl_block_verify_data_egprs(dl_block, dl_fn, ack_fn, data, exp_bsn, exp_cs);
709 } else {
710 f_rlcmac_dl_block_verify_data_gprs(dl_block, dl_fn, ack_fn, data, exp_bsn, exp_cs);
711 }
712}
713
714testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
715 var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.cell_id.ra_id);
716 var GprsTlli tlli := 'FFFFFFFF'O;
717 timer T;
718
719 /* Initialize NS/BSSGP side */
720 f_init_bssgp();
721
722 /* Initialize the PCU interface abstraction */
723 f_init_raw(testcasename());
724
725 /* Establish BSSGP connection to the PCU */
726 f_bssgp_establish();
727
728 BTS.send(ts_PCUIF_SUSP_REQ(0, tlli, ra_id, 0));
729
730 T.start(2.0);
731 alt {
732 [] BSSGP_SIG[0].receive(tr_BSSGP_SUSPEND(tlli, mp_gb_cfg.cell_id.ra_id)) {
733 setverdict(pass);
734 }
735 [] T.timeout {
736 setverdict(fail, "Timeout waiting for BSSGP SUSPEND");
737 }
738 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700739
740 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200741}
742
743/* Test of correct Timing Advance at the time of TBF establishment
744 * (derived from timing offset of the Access Burst). */
745testcase TC_ta_rach_imm_ass() runs on RAW_PCU_Test_CT {
746 var GsmRrMessage rr_msg;
747 var boolean ok;
748
749 /* Initialize the PCU interface abstraction */
750 f_init_raw(testcasename());
751
752 /* We cannot send too many TBF requests in a short time because
753 * at some point the PCU will fail to allocate a new TBF. */
754 for (var TimingAdvance ta := 0; ta < 64; ta := ta + 16) {
755 /* Establish an Uplink TBF (send RACH.ind with current TA) */
756 ok := f_establish_tbf(rr_msg, bts_nr := 0, ta := ta);
757 if (not ok) {
758 setverdict(fail, "Failed to establish an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700759 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200760 }
761
762 /* Make sure Timing Advance IE matches out expectations */
Vadim Yanitskiy8685b382020-05-06 16:53:26 +0700763 if (rr_msg.payload.imm_ass.timing_advance != ta) {
764 setverdict(fail, "Timing Advance mismatch: ",
765 rr_msg.payload.imm_ass.timing_advance,
766 " vs expected ", ta);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700767 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200768 }
769 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700770
771 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200772}
773
774/* Verify Timing Advance value(s) indicated during the packet Downlink assignment
775 * procedure as per 3GPP TS 44.018, section 3.5.3. There seems to be a bug in the
776 * IUT that causes it to send an unreasonable Timing Advance value > 0 despite
777 * no active TBF exists at the moment of establishment (idle mode). */
778testcase TC_ta_idle_dl_tbf_ass() runs on RAW_PCU_Test_CT {
779 var OCT4 tlli := f_rnd_octstring(4);
780 var GsmRrMessage rr_imm_ass;
781
782 /* Initialize NS/BSSGP side */
783 f_init_bssgp();
784
785 /* Initialize the PCU interface abstraction */
786 f_init_raw(testcasename());
787
788 /* Establish BSSGP connection to the PCU */
789 f_bssgp_establish();
790 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
791
792 /* SGSN sends some DL data, PCU will initiate Packet Downlink
793 * Assignment on CCCH (PCH). We don't care about the payload. */
794 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, f_rnd_octstring(10)));
795 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass); // TODO: match by TLLI!
796
797 /* Make sure that Timing Advance is 0 (the actual value is not known yet).
798 * As per 3GPP S 44.018, section 3.5.3.1.2, the network *shall* initiate
799 * the procedures defined in 3GPP TS 44.060 or use the polling mechanism. */
800 if (not match(rr_imm_ass, tr_IMM_TBF_ASS(ta := 0))) {
801 setverdict(fail, "Timing Advance value doesn't match");
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200802 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700803
804 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200805}
806
807/* Verify that the PCU generates valid PTCCH/D messages
808 * while neither Uplink nor Downlink TBF is established. */
809testcase TC_ta_ptcch_idle() runs on RAW_PCU_Test_CT {
810 var PTCCHDownlinkMsg ptcch_msg;
811 var PCUIF_Message pcu_msg;
812 timer T;
813
814 /* Initialize the PCU interface abstraction */
815 f_init_raw(testcasename());
816
817 /* Sent an RTS.req for PTCCH/D */
818 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
819 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
820 arfcn := 871, block_nr := 0));
821 T.start(5.0);
822 alt {
823 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
824 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
825 log("Rx DATA.req message: ", pcu_msg);
826 setverdict(pass);
827 }
828 [] BTS.receive(PCUIF_Message:?) { repeat; }
829 [] T.timeout {
830 setverdict(fail, "Timeout waiting for a PTCCH/D block");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700831 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200832 }
833 }
834
835 ptcch_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
836 log("Decoded PTCCH/D message: ", ptcch_msg);
837
838 /* Make sure the message is encoded correctly
839 * TODO: do we expect all TA values to be equal '1111111'B? */
840 if (not match(ptcch_msg, tr_PTCCHDownlinkMsg)) {
841 setverdict(fail, "Malformed PTCCH/D message");
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200842 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700843
844 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200845}
846
847/* Test of correct Timing Advance during an active Uplink TBF.
848 *
849 * Unlike the circuit-switched domain, Uplink transmissions on PDCH time-slots
850 * are not continuous and there can be long time gaps between them. This happens
851 * due to a bursty nature of packet data. The actual Timing Advance of a MS may
852 * significantly change between such rare Uplink transmissions, so GPRS introduces
853 * additional mechanisms to control Timing Advance, and thus reduce interference
854 * between neighboring TDMA time-slots.
855 *
856 * At the moment of Uplink TBF establishment, initial Timing Advance is measured
857 * from ToA (Timing of Arrival) of an Access Burst. This is covered by another
858 * test case - TC_ta_rach_imm_ass. In response to that Access Burst the network
859 * sends Immediate Assignment on AGCH, which _may_ contain Timing Advance Index
860 * among with the initial Timing Advance value. And here PTCCH comes to play.
861 *
862 * PTCCH is a unidirectional channel on which the network can instruct a sub-set
863 * of 16 MS (whether TBFs are active or not) to adjust their Timing Advance
864 * continuously. To ensure continuous measurements of the signal propagation
865 * delay, the MSs shall transmit Access Bursts on Uplink (PTCCH/U) on sub-slots
866 * defined by an assigned Timing Advance Index (see 3GPP TS 45.002).
867 *
868 * The purpose of this test case is to verify the assignment of Timing Advance
869 * Index, and the process of Timing Advance notification on PTCCH/D. The MTC
870 * first establishes several Uplink TBFs, but does not transmit any Uplink
871 * blocks on them. During 4 TDMA multi-frame periods the MTC is sending RACH
872 * indications to the PCU, checking the correctness of two received PTCCH/D
873 * messages (period of PTCCH/D is two multi-frames).
874 */
875
876/* List of ToA values for Access Bursts to be sent on PTCCH/U,
877 * each ToA (Timing of Arrival) value is in units of 1/4 of
878 * a symbol (i.e. 1 symbol is 4 QTA units). */
879type record length(16) of int16_t PTCCH_TAI_ToA_MAP;
880const PTCCH_TAI_ToA_MAP ptcch_toa_map_def := {
881 0, 0, 0, 0,
882 0, 0, 0, 0,
883 0, 0, 0, 0,
884 0, 0, 0, 0
885};
886
887private altstep as_ta_ptcch(uint8_t bts_nr := 0, uint8_t trx_nr := 0, uint8_t ts_nr := 7,
888 in PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def)
889runs on RAW_PCU_Test_CT {
890 var RAW_PCU_Event event;
891 var integer ss;
892
893 /* Send Access Bursts on PTCCH/U for every TA Index */
894 [] BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PTCCH_UL_BURST)) -> value event {
895 ss := f_tdma_ptcch_fn2ss(event.data.tdma_fn);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700896 if (ss < 0) { /* Shall not happen */
897 f_shutdown(__BFILE__, __LINE__);
898 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200899
900 log("Sending an Access Burst on PTCCH/U",
901 ", sub-slot=", ss, " (TAI)",
902 ", fn=", event.data.tdma_fn,
903 ", ToA=", toa_map[ss], " (QTA)");
904 /* TODO: do we care about RA and burst format? */
905 BTS.send(ts_PCUIF_RACH_IND(bts_nr, trx_nr, ts_nr,
906 ra := oct2int('3A'O),
907 is_11bit := 0,
908 burst_type := BURST_TYPE_0,
909 fn := event.data.tdma_fn,
910 arfcn := 871,
911 qta := toa_map[ss],
912 sapi := PCU_IF_SAPI_PTCCH));
913 repeat;
914 }
915}
916
917private function f_TC_ta_ptcch_ul_multi_tbf(in PTCCH_TAI_ToA_MAP ptcch_toa_map,
918 template PTCCHDownlinkMsg t_ta_msg)
919runs on RAW_PCU_Test_CT {
920 var PTCCHDownlinkMsg ta_msg;
921 var PCUIF_Message pcu_msg;
922 timer T;
923
924 /* First, send an RTS.req for the upcoming PTCCH/D block */
925 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
926 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
927 arfcn := 871, block_nr := 0));
928 T.start(2.0);
929 alt {
930 /* Keep sending of Access Bursts during two multi-frames (period of PTCCH/D)
931 * with increasing ToA (Timing of Arrival) values: 0, 7, 14, 28, 35... */
932 [] as_ta_ptcch(bts_nr := 0, trx_nr := 0, ts_nr := 7, toa_map := ptcch_toa_map);
933 /* In the end of 2nd multi-frame we should receive a PTCCH/D block */
934 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
935 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
936 ta_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
937 log("Rx PTCCH/D message: ", ta_msg);
938
939 /* Make sure Timing Advance values match our expectations */
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700940 if (not match(ta_msg, t_ta_msg)) {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200941 setverdict(fail, "PTCCH/D message does not match: ", t_ta_msg);
942 }
943 }
944 [] BTS.receive { repeat; }
945 [] T.timeout {
946 setverdict(fail, "Timeout waiting for a PTCCH/D block");
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200947 }
948 }
949}
950
951testcase TC_ta_ptcch_ul_multi_tbf() runs on RAW_PCU_Test_CT {
952 var template PacketUlAssign t_ul_tbf_ass;
953 var PacketUlAssign ul_tbf_ass[7];
954 var GsmRrMessage rr_msg[7];
955 var boolean ok;
956
957 /* Initialize the PCU interface abstraction */
958 f_init_raw(testcasename());
959
960 /* Enable forwarding of PTCCH/U TDMA events to us */
961 BTS.send(ts_RAW_PCU_CMD(TDMA_CMD_ENABLE_PTCCH_UL_FWD));
962
963 /* Establish 7 Uplink TBFs (USF flag is 3 bits long, '111'B is reserved) */
964 for (var integer i := 0; i < 7; i := i + 1) {
965 ok := f_establish_tbf(rr_msg[i], ta := 0);
966 if (not ok) {
967 setverdict(fail, "Failed to establish an Uplink TBF #", i);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700968 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200969 }
970
971 /* Make sure we received an UL TBF Assignment */
972 if (match(rr_msg[i], tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
973 ul_tbf_ass[i] := rr_msg[i].payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
974 log("Rx Uplink TBF assignment for #", i, ": ", ul_tbf_ass[i]);
975 } else {
976 setverdict(fail, "Failed to match UL TBF Assignment for #", i);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700977 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200978 }
979
980 /* We expect incremental TFI/USF assignment (dynamic allocation) */
981 t_ul_tbf_ass := tr_PacketUlDynAssign(tfi := i, usf := i);
982 if (not match(ul_tbf_ass[i], t_ul_tbf_ass)) {
983 setverdict(fail, "Failed to match Packet Uplink Assignment for #", i);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700984 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200985 }
986
987 /* We also expect Timing Advance Index to be a part of the assignment */
988 if (ul_tbf_ass[i].dynamic.ta_index != i) {
989 setverdict(fail, "Failed to match Timing Advance Index for #", i);
990 /* Keep going, the current OsmoPCU does not assign TA Index */
991 }
992 }
993
994 /* Prepare a list of ToA values for Access Bursts to be sent on PTCCH/U */
995 var PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def;
996 for (var integer i := 0; i < 7; i := i + 1) {
997 /* ToA in units of 1/4 of a symbol */
998 toa_map[i] := (i + 1) * 7 * 4;
999 }
1000
1001 /* Now we have all 7 TBFs established in one-phase access mode,
1002 * however we will not be sending any data on them. Instead, we
1003 * will be sending RACH.ind on PTCCH/U during 4 multi-frame
1004 * periods (TAI 0..8), and then will check two PTCCH/D blocks.
1005 *
1006 * Why not 4 TBFs at once? Because Uplink is delayed by 3 TDMA
1007 * time-slots, so at the moment of scheduling a PTCCH/D block
1008 * the PCU has odd number of PTCCH/U Access Bursts received. */
1009 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
1010 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
1011 /* Other values are not known (yet) */
1012 tai3_ta := ?));
1013 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
1014 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
1015 tai3_ta := 28, tai4_ta := 35, tai5_ta := 42,
1016 /* Other values are out of our interest */
1017 tai6_ta := ?));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001018
1019 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001020}
1021
1022/* Default link quality adaptation (Coding Scheme) ranges (inclusive).
1023 * OsmoPCU (VTY): cs link-quality-ranges cs1 6 cs2 5 8 cs3 7 13 cs4 12
1024 *
1025 * NOTE: the ranges are intentionally overlapping because OsmoPCU
1026 * does not change CS/MCS on the range borders (5-6, 7-8, 12-13). */
1027private template integer CS1_lqual_dB_range := (-infinity .. 6);
1028private template integer CS2_lqual_dB_range := (5 .. 8);
1029private template integer CS3_lqual_dB_range := (7 .. 13);
1030private template integer CS4_lqual_dB_range := (12 .. infinity);
1031
1032testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
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;
1039 var uint32_t unused_fn;
1040
1041 /* Initialize the PCU interface abstraction */
1042 f_init_raw(testcasename());
1043
1044 f_pcuvty_set_allowed_cs_mcs();
1045 f_pcuvty_set_link_quality_ranges();
1046
1047 /* Establish an Uplink TBF */
1048 ok := f_establish_tbf(rr_imm_ass);
1049 if (not ok) {
1050 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001051 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001052 }
1053
1054 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1055 if (not ok) {
1056 setverdict(fail, "Immediate Assignment not an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001057 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001058 }
1059
1060 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1061 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1062 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
1063 bsn := 0, /* TODO: what should be here? */
1064 blocks := { /* To be generated in loop */ });
1065
1066 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1067 ul_data.data.tlli := '00000001'O;
1068
1069 /* The actual / old link quality values. We need to keep track of the old
1070 * (basically previous) link quality value, because OsmoPCU actually
1071 * changes the coding scheme if not only the actual, but also the old
1072 * value leaves the current link quality range (window). */
1073 var integer lqual := 0;
1074 var integer lqual_old;
1075
1076 /* 16 UL blocks (0 .. 15 dB, step = 1 dB) */
1077 for (var integer i := 0; i < 16; i := i + 1) {
1078 /* Prepare a new UL block (CV, random payload) */
1079 ul_data.data.mac_hdr.countdown := (15 - i);
1080 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1081
1082 /* Update the old / actual link quality */
1083 lqual_old := lqual;
1084 lqual := i;
1085
1086 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1087 log("Sending DATA.ind with link quality (dB): ", lqual);
1088 f_tx_rlcmac_ul_block(ul_data, lqual * 10);
1089
1090 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1091 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1092
1093 log("Rx Packet Uplink ACK / NACK with Channel Coding Command: ",
1094 dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd);
1095
1096 /* Match the received Channel Coding Command. Since we are increasing
1097 * the link quality value on each iteration and not decreasing, there
1098 * is no need to check the both old and current link quality values. */
1099 var template ChCodingCommand ch_coding;
1100 select (lqual_old) {
1101 case (CS1_lqual_dB_range) { ch_coding := CH_CODING_CS1; }
1102 case (CS2_lqual_dB_range) { ch_coding := CH_CODING_CS2; }
1103 case (CS3_lqual_dB_range) { ch_coding := CH_CODING_CS3; }
1104 case (CS4_lqual_dB_range) { ch_coding := CH_CODING_CS4; }
1105 }
1106
1107 if (not match(dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd, ch_coding)) {
1108 setverdict(fail, "Channel Coding does not match our expectations: ", ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001109 }
1110 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001111
1112 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001113}
1114
1115/* Test the max UL CS set by VTY works fine */
1116testcase TC_cs_initial_ul() runs on RAW_PCU_Test_CT {
1117 var GsmRrMessage rr_imm_ass;
1118 var PacketUlAssign ul_tbf_ass;
1119 var RlcmacDlBlock dl_block;
1120 var boolean ok;
1121 var integer lqual_cb;
1122 var ChCodingCommand last_ch_coding;
1123 var uint32_t unused_fn;
1124
1125 /* Initialize the PCU interface abstraction */
1126 f_init_raw(testcasename());
1127
1128 /* Set initial UL CS to 3 */
1129 g_cs_initial_ul := 3;
1130 f_pcuvty_set_allowed_cs_mcs();
1131 f_pcuvty_set_link_quality_ranges();
1132
1133 /* Take lqual (dB->cB) so that we stay in that CS */
1134 lqual_cb := g_cs_lqual_ranges[2].low * 10;
1135
1136 /* Establish an Uplink TBF */
1137 ok := f_establish_tbf(rr_imm_ass);
1138 if (not ok) {
1139 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001140 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001141 }
1142
1143 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1144 if (not ok) {
1145 setverdict(fail, "Immediate Assignment not an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001146 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001147 }
1148
1149 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1150 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1151 cv := 3, /* 8 UL blocks to be sent (to be overridden in loop) */
1152 bsn := 0, /* TODO: what should be here? */
1153 blocks := { /* To be generated in loop */ });
1154
1155 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1156 ul_data.data.tlli := '00000001'O;
1157
1158 /* 3 UL blocks, check we are in same initial CS: */
1159 for (var integer i := 0; i < 3; i := i + 1) {
1160 /* Prepare a new UL block (CV, random payload) */
1161 ul_data.data.mac_hdr.countdown := (7 - i);
1162 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1163
1164 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1165 f_tx_rlcmac_ul_block(ul_data, lqual_cb);
1166
1167 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1168 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1169 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1170 }
1171
1172 if (last_ch_coding != CH_CODING_CS3) {
1173 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001174 }
1175
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001176 /* Remaining UL blocks are used to make sure regardless of initial
1177 /* lqual, we can go lower at any time */
1178
1179 /* 5 UL blocks, check we are in same initial CS: */
1180 for (var integer i := 3; i < 8; i := i + 1) {
1181 /* Prepare a new UL block (CV, random payload) */
1182 ul_data.data.mac_hdr.countdown := (7 - i);
1183 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1184
1185 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1186 f_tx_rlcmac_ul_block(ul_data, 0); /* 0 dB, make sure we downgrade CS */
1187
1188 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1189 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1190
1191 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1192 }
1193
1194 if (last_ch_coding != CH_CODING_CS1) {
1195 setverdict(fail, "Channel Coding does not match our expectations (CS-1): ", last_ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001196 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001197
1198 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001199}
1200
1201/* Test the max UL CS set by VTY works fine */
1202testcase TC_cs_max_ul() runs on RAW_PCU_Test_CT {
1203 var GsmRrMessage rr_imm_ass;
1204 var PacketUlAssign ul_tbf_ass;
1205 var RlcmacDlBlock dl_block;
1206 var boolean ok;
1207 var ChCodingCommand last_ch_coding;
1208 var uint32_t unused_fn;
1209
1210 /* Initialize the PCU interface abstraction */
1211 f_init_raw(testcasename());
1212
1213 /* Set maximum allowed UL CS to 3 */
1214 g_cs_max_ul := 3;
1215 f_pcuvty_set_allowed_cs_mcs();
1216 f_pcuvty_set_link_quality_ranges();
1217
1218 /* Establish an Uplink TBF */
1219 ok := f_establish_tbf(rr_imm_ass);
1220 if (not ok) {
1221 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001222 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001223 }
1224
1225 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1226 if (not ok) {
1227 setverdict(fail, "Immediate Assignment not an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001228 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001229 }
1230
1231 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1232 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1233 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
1234 bsn := 0, /* TODO: what should be here? */
1235 blocks := { /* To be generated in loop */ });
1236
1237 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1238 ul_data.data.tlli := '00000001'O;
1239
1240 /* 16 UL blocks */
1241 for (var integer i := 0; i < 16; i := i + 1) {
1242 /* Prepare a new UL block (CV, random payload) */
1243 ul_data.data.mac_hdr.countdown := (15 - i);
1244 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1245
1246 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1247 f_tx_rlcmac_ul_block(ul_data, 40*10); /* 40 dB */
1248
1249 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1250 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1251
1252 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1253 }
1254
1255 if (last_ch_coding != CH_CODING_CS3) {
1256 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001257 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001258
1259 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001260}
1261
1262/* Verify PCU drops TBF after some time of inactivity. */
1263testcase TC_t3169() runs on RAW_PCU_Test_CT {
1264 var PCUIF_info_ind info_ind;
1265 var GsmRrMessage rr_imm_ass;
1266 var PacketUlAssign ul_tbf_ass;
1267 var RlcmacDlBlock dl_block;
1268 var PCUIF_Message pcu_msg;
1269 var octetstring data;
1270 var boolean ok;
1271 var uint32_t unused_fn;
1272 var OCT4 tlli := '00000001'O;
1273
1274 /* Initialize NS/BSSGP side */
1275 f_init_bssgp();
1276
1277 info_ind := valueof(ts_PCUIF_INFO_default);
1278 /* Set timer to 1 sec (default 5) to speedup test: */
1279 info_ind.t3169 := 1;
1280
1281 /* Initialize the PCU interface abstraction */
1282 f_init_raw(testcasename(), info_ind);
1283
1284 /* Establish BSSGP connection to the PCU */
1285 f_bssgp_establish();
1286 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1287
1288 /* Establish an Uplink TBF */
1289 ok := f_establish_tbf(rr_imm_ass);
1290 if (not ok) {
1291 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001292 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001293 }
1294
1295 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1296 if (not ok) {
1297 setverdict(fail, "Immediate Assignment not an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001298 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001299 }
1300
1301 /* Send one UL block and make sure it is ACKED fine */
1302 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1303 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1304 /* UL block should be received in SGSN */
1305 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1306
1307 /* Wait until T3169 fires (plus 1 extra sec to make sure) */
1308 f_sleep(int2float(info_ind.t3169) + 1.0);
1309
1310 /* Send an UL block once again, the TBF should be gone by now so no ACK */
1311 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1312 f_rx_rlcmac_dl_block_exp_dummy(dl_block);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001313
1314 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001315}
1316
1317/* Verify that a Downlink TBF can be assigned using PACCH shortly after the
1318 * release of prev DL TBF due to MS staying in PDCH for a while (T3192, in PCU
1319 * T3193) after DL TBF release */
1320testcase TC_t3193() runs on RAW_PCU_Test_CT {
1321 var GsmRrMessage rr_imm_ass;
1322 var PacketDlAssign dl_tbf_ass;
1323 var RlcmacDlBlock dl_block;
1324 var octetstring data := f_rnd_octstring(10);
1325 var boolean ok;
1326 var uint32_t sched_fn;
1327 var OCT4 tlli := '00000001'O;
1328 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1329
1330 /* Initialize NS/BSSGP side */
1331 f_init_bssgp();
1332
1333 /* Initialize the PCU interface abstraction */
1334 f_init_raw(testcasename());
1335
1336 /* Establish BSSGP connection to the PCU */
1337 f_bssgp_establish();
1338 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1339
1340 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1341 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1342 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1343 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1344 if (not ok) {
1345 setverdict(fail, "Immediate Assignment not a Downlink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001346 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001347 }
1348 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1349 f_sleep(X2002);
1350 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1351
1352 /* ACK the DL block */
1353 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
1354 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc), 0, sched_fn);
1355 /* we are done with the DL-TBF here so far, let's clean up our local state: */
1356 ack_nack_desc := valueof(t_AckNackDescription_init)
1357
1358 /* Now that final DL block is ACKED and TBF is released, T3193 in PCU
1359 (T3192 in MS) was started and until it fires the MS will be abailable
1360 on PDCH in case new data arrives from SGSN. Let's verify it: */
1361 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1362 f_rx_rlcmac_dl_block_exp_pkt_ass(dl_block, sched_fn);
1363 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1364
1365 /* Now that we confirmed the new assignment in the dl-tbf, lets receive the data and ack it */
1366 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1367 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
1368 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc), 0, sched_fn);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001369
1370 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001371}
1372
1373/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1374 * answered, so TBFs for uplink and later for downlink are created.
1375 */
1376private function f_TC_mo_ping_pong(template (omit) MSRadioAccessCapabilityV ms_racap := omit, template (present) CodingScheme exp_cs_mcs := ?) runs on RAW_PCU_Test_CT {
1377 var GsmRrMessage rr_imm_ass;
1378 var PacketUlAssign ul_tbf_ass;
1379 var PacketDlAssign dl_tbf_ass;
1380 var RlcmacDlBlock dl_block;
1381 var PCUIF_Message pcu_msg;
1382 var octetstring data := f_rnd_octstring(10);
1383 var boolean ok;
1384 var uint32_t sched_fn;
1385 var OCT4 tlli := '00000001'O;
1386 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1387
1388 /* Initialize NS/BSSGP side */
1389 f_init_bssgp();
1390
1391 /* Initialize the PCU interface abstraction */
1392 f_init_raw(testcasename());
1393
1394 /* Establish BSSGP connection to the PCU */
1395 f_bssgp_establish();
1396 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1397
1398 /* Establish an Uplink TBF */
1399 ok := f_establish_tbf(rr_imm_ass);
1400 if (not ok) {
1401 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001402 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001403 }
1404 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1405 if (not ok) {
1406 setverdict(fail, "Immediate Assignment not an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001407 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001408 }
1409
1410 if (not istemplatekind(ms_racap, "omit")) {
1411 /* Send PACKET RESOURCE REQUEST to upgrade to EGPRS
1412 * (see 3GPP TS 04.60 "7.1.3.1 Initiation of the Packet resource request procedure")
1413 */
1414 f_tx_rlcmac_ul_block(ts_RLC_UL_CTRL_ACK(valueof(ts_RlcMacUlCtrl_PKT_RES_REQ(tlli, ms_racap))), 0);
1415 f_rx_rlcmac_dl_block_exp_pkt_ul_ass(dl_block, sched_fn);
1416 if (dl_block.ctrl.payload.u.ul_assignment.identity.tlli.tlli != tlli) {
1417 setverdict(fail, "Wrong TLLI ", dl_block.ctrl.payload.u.ul_assignment.identity.tlli, " received vs exp ", tlli);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001418 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001419 }
1420 }
1421
1422 /* Send one UL block and make sure it is ACKED fine */
1423 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1424 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1425 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1426 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1427
1428 /* UL block should be received in SGSN */
1429 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1430
1431 /* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
1432 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1433 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1434
1435 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1436 if (not ok) {
1437 setverdict(fail, "Immediate Assignment not a Downlink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001438 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001439 }
1440
1441 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1442 f_sleep(X2002);
1443 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0, exp_cs_mcs);
1444
1445 /* ACK the DL block */
1446 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
1447 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc), 0, sched_fn);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001448
1449 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001450}
1451
1452/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1453 * answered, so TBFs for uplink and later for downlink are created.
1454 */
1455testcase TC_mo_ping_pong() runs on RAW_PCU_Test_CT {
1456 var CodingScheme exp_cs_mcs := CS_1;
1457 f_TC_mo_ping_pong(omit, exp_cs_mcs);
1458}
1459
1460
1461testcase TC_mo_ping_pong_with_ul_racap() runs on RAW_PCU_Test_CT {
1462 var MultislotCap_GPRS mscap_gprs := {
1463 gprsmultislotclass := '00011'B,
1464 gprsextendeddynalloccap := '0'B
1465 };
1466 var MSRadioAccessCapabilityV ms_racap := { valueof(ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs, omit)) };
1467 var CodingScheme exp_cs_mcs := CS_2;
1468
1469 f_TC_mo_ping_pong(ms_racap, exp_cs_mcs);
1470}
1471
1472/* Test scenario where SGSN wants to send some data against MS and it is
1473 * answered by the MS on PDCH, so TBFs for downlink and later for uplink are created.
1474 */
1475private function f_TC_mt_ping_pong(template (omit) MSRadioAccessCapabilityV_BSSGP ms_racap := omit, template (present) CodingScheme exp_cs_mcs := ?) 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;
1481 var octetstring data := f_rnd_octstring(10);
1482 var boolean ok;
1483 var uint32_t sched_fn;
1484 var OCT4 tlli := '00000001'O;
1485 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1486
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 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1498 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data, ms_racap));
1499 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1500
1501 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1502 if (not ok) {
1503 setverdict(fail, "Immediate Assignment not a Downlink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001504 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001505 }
1506
1507 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1508 f_sleep(X2002);
1509 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0, exp_cs_mcs);
1510
1511 /* ACK the DL block */
1512 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
1513 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc), 0, sched_fn);
1514
1515 /* Now MS wants to answer the DL data, Establish an Uplink TBF */
1516 ok := f_establish_tbf(rr_imm_ass);
1517 if (not ok) {
1518 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001519 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001520 }
1521 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1522 if (not ok) {
1523 setverdict(fail, "Immediate Assignment not an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001524 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001525 }
1526
1527 /* Send one UL block and make sure it is ACKED fine */
1528 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1529 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1530 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1531 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1532
1533 /* UL block should be received in SGSN */
1534 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001535
1536 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001537}
1538
1539testcase TC_mt_ping_pong() runs on RAW_PCU_Test_CT {
1540 var CodingScheme exp_cs_mcs := CS_1;
1541 f_TC_mt_ping_pong(omit, exp_cs_mcs);
1542}
1543
1544/* TC_mt_ping_pong, but DL-UNITDATA contains RA Access capability with (M)CS
1545/* information about the MS */
1546testcase TC_mt_ping_pong_with_dl_racap() runs on RAW_PCU_Test_CT {
1547 var MultislotCap_GPRS_BSSGP mscap_gprs := {
1548 gprsmultislotclass := '00011'B,
1549 gprsextendeddynalloccap := '0'B
1550 } ;
1551 var MSRadioAccessCapabilityV_BSSGP ms_racap := { valueof(ts_RaCapRec_BSSGP('0001'B /* E-GSM */, mscap_gprs, omit)) };
1552 var CodingScheme exp_cs_mcs := CS_2;
1553 f_TC_mt_ping_pong(ms_racap, exp_cs_mcs);
1554}
1555
1556/* Verify that if PCU doesn't get an ACK for first DL block after IMM ASS, it
1557 * will retry by retransmitting both the IMM ASS + DL block after poll (ack)
1558 * timeout occurs (specified by sent RRBP on DL block). */
1559testcase TC_imm_ass_dl_block_retrans() runs on RAW_PCU_Test_CT {
1560 var GsmRrMessage rr_imm_ass;
1561 var PacketDlAssign dl_tbf_ass;
1562 var RlcmacDlBlock dl_block;
1563 var octetstring data := f_rnd_octstring(10);
1564 var boolean ok;
1565 var uint32_t sched_fn;
1566 var OCT4 tlli := '00000001'O;
1567 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1568
1569 /* Initialize NS/BSSGP side */
1570 f_init_bssgp();
1571
1572 /* Initialize the PCU interface abstraction */
1573 f_init_raw(testcasename());
1574
1575 /* Establish BSSGP connection to the PCU */
1576 f_bssgp_establish();
1577 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1578
1579 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1580 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1581 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1582 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1583 if (not ok) {
1584 setverdict(fail, "Immediate Assignment not a Downlink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001585 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001586 }
1587
1588 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1589 f_sleep(X2002);
1590 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1591
1592 /* Now we don't ack the dl block (emulate MS failed receiveing IMM ASS
1593 * or GPRS DL, or DL ACK was lost for some reason). As a result, PCU
1594 * should retrigger IMM ASS + GPRS DL procedure after poll timeout. */
1595 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1596 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1597 if (not ok) {
1598 setverdict(fail, "Immediate Assignment not a Downlink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001599 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001600 }
1601 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1602 f_sleep(X2002);
1603 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1604
1605 /* ACK the DL block */
1606 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
1607 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc), 0, sched_fn);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001608
1609 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001610}
1611
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001612private function f_pkt_paging_match_imsi(in PacketPagingReq req, hexstring imsi)
1613runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001614 var MobileIdentityLV_Paging mi_lv := req.repeated_pageinfo.cs.mobile_identity;
1615 var MobileIdentityV mi := dec_MobileIdentityV(mi_lv.mobile_id);
1616
1617 if (mi_lv.len != 8) { /* 8 octets: type of ID (3 bits) + even/odd flag (1 bit) + 15 BCD-encoded digits (60 bits) */
1618 setverdict(fail, "Mobile Identity length mismatch: ",
1619 "expected: 8, got: ", mi_lv.len);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001620 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001621 }
1622
1623 /* Make sure MI contains IMSI before referencing it */
1624 if (mi.typeOfIdentity != '001'B) {
1625 setverdict(fail, "Mobile Identity must be of type IMSI ('001'B), ",
1626 "got: ", mi.typeOfIdentity);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001627 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001628 } else if (mi.oddEvenInd_identity.imsi.digits != imsi) {
1629 setverdict(fail, "Mobile Identity contains unexpected IMSI, ",
1630 "expected: ", imsi, " got: ", mi.oddEvenInd_identity.imsi.digits);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001631 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001632 }
1633}
1634
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001635private function f_pkt_paging_match_tmsi(in PacketPagingReq req, template GsmTmsi tmsi)
1636runs on RAW_PCU_Test_CT {
1637 var MobileIdentityLV_Paging mi_lv := req.repeated_pageinfo.cs.mobile_identity;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001638 if (not match(req.repeated_pageinfo.cs.tmsi, tmsi)) {
1639 setverdict(fail, "Mobile Identity (TMSI/P-TMSI) mismatch: ",
1640 "expected: ", tmsi, "got: ", req.repeated_pageinfo.cs.tmsi);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001641 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001642 }
1643}
1644
1645/* Test CS paging over the BTS<->PCU socket.
1646 * 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.
1647 * Paging should be send on the PACCH.
1648 *
1649 * 1. Send a Paging Request over PCU socket.
1650 * 2. Send a Ready-To-Send message over PCU socket
1651 * 3. Expect a Paging Frame
1652 */
1653testcase TC_paging_cs_from_bts() runs on RAW_PCU_Test_CT {
1654 var GsmRrMessage rr_imm_ass;
1655 var PacketUlAssign ul_tbf_ass;
1656 var RlcmacDlBlock dl_block;
1657 var boolean ok;
1658 var OCT4 tlli := '00000001'O;
1659 var MobileIdentityLV mi;
1660 var octetstring mi_enc_lv;
1661 var hexstring imsi := f_gen_imsi(42);
1662
1663 /* Initialize NS/BSSGP side */
1664 f_init_bssgp();
1665
1666 /* Initialize the PCU interface abstraction */
1667 f_init_raw(testcasename());
1668
1669 /* Establish BSSGP connection to the PCU */
1670 f_bssgp_establish();
1671 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1672
1673 /* Establish an Uplink TBF */
1674 ok := f_establish_tbf(rr_imm_ass);
1675 if (not ok) {
1676 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001677 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001678 }
1679
1680 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1681 if (not ok) {
1682 setverdict(fail, "Immediate Assignment not an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001683 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001684 }
1685
1686
1687 /* build mobile Identity */
1688 mi := valueof(ts_MI_IMSI_LV(imsi));
1689 mi_enc_lv := enc_MobileIdentityLV(mi);
1690 /* Send paging request */
1691 BTS.send(ts_PCUIF_PAG_REQ(bts_nr := 0, id_lv := mi_enc_lv, chan_needed := 0,
1692 sapi :=PCU_IF_SAPI_PDTCH));
1693
1694 /* Receive it on BTS side towards MS */
1695 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
1696
1697 /* Make sure that Packet Paging Request contains the same IMSI */
1698 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1699
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001700 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001701}
1702
1703/* Test CS paging over Gb (SGSN->PCU->BTS[PDCH]).
1704 */
1705private function f_tc_paging_cs_from_sgsn(Nsvci bvci, boolean use_ptmsi := false)
1706runs on RAW_PCU_Test_CT {
1707 var GsmRrMessage rr_imm_ass;
1708 var PacketUlAssign ul_tbf_ass;
1709 var RlcmacDlBlock dl_block;
1710 var boolean ok;
1711 var OCT4 tlli := '00000001'O;
1712 var hexstring imsi := f_gen_imsi(42);
1713 var GsmTmsi tmsi;
1714
1715 /* Initialize NS/BSSGP side */
1716 f_init_bssgp();
1717
1718 /* Initialize the PCU interface abstraction */
1719 f_init_raw(testcasename());
1720
1721 /* Establish BSSGP connection to the PCU */
1722 f_bssgp_establish();
1723 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1724
1725 /* Establish an Uplink TBF */
1726 ok := f_establish_tbf(rr_imm_ass);
1727 if (not ok) {
1728 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001729 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001730 }
1731
1732 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1733 if (not ok) {
1734 setverdict(fail, "Immediate Assignment not an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001735 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001736 }
1737
1738 /* Send paging request with or without TMSI */
1739 if (use_ptmsi) {
1740 tmsi := oct2int(f_rnd_octstring(4)); /* Random P-TMSI */
1741 BSSGP[0].send(ts_BSSGP_CS_PAGING_PTMSI(bvci, imsi, tmsi));
1742 } else {
1743 BSSGP[0].send(ts_BSSGP_CS_PAGING_IMSI(bvci, imsi));
1744 }
1745
1746 /* Receive it on BTS side towards MS */
1747 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
1748
1749 /* Make sure that Packet Paging Request contains the same P-TMSI/IMSI */
1750 if (use_ptmsi) {
1751 f_pkt_paging_match_tmsi(dl_block.ctrl.payload.u.paging, tmsi);
1752 } else {
1753 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1754 }
1755
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001756 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001757}
1758
1759testcase TC_paging_cs_from_sgsn_sign_ptmsi() runs on RAW_PCU_Test_CT {
1760 f_tc_paging_cs_from_sgsn(0, true);
1761}
1762
1763testcase TC_paging_cs_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1764 f_tc_paging_cs_from_sgsn(0);
1765}
1766
1767testcase TC_paging_cs_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1768 f_tc_paging_cs_from_sgsn(mp_gb_cfg.bvci);
1769}
1770
1771/* Test PS paging over Gb (SGSN->PCU->BTS[CCCH]).
1772 */
1773private function f_tc_paging_ps_from_sgsn(Nsvci bvci, boolean use_ptmsi := false)
1774runs on RAW_PCU_Test_CT {
1775 var OCT4 tlli := '00000001'O;
1776 var integer imsi_suff_tx := 423;
1777 var hexstring imsi := f_gen_imsi(imsi_suff_tx);
1778
1779 /* Initialize NS/BSSGP side */
1780 f_init_bssgp();
1781
1782 /* Initialize the PCU interface abstraction */
1783 f_init_raw(testcasename());
1784
1785 /* Establish BSSGP connection to the PCU */
1786 f_bssgp_establish();
1787 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1788
1789 /* Send BSSGP PAGING-PS (with or without TMSI), wait for RR Paging Request Type 1.
1790 * Make sure that both paging group (IMSI suffix) and Mobile Identity match. */
1791 if (use_ptmsi) {
1792 var OCT4 tmsi := f_rnd_octstring(4); /* Random P-TMSI */
1793 BSSGP[0].send(ts_BSSGP_PS_PAGING_PTMSI(bvci, imsi, oct2int(tmsi)));
1794 f_pcuif_rx_pch_pag_req1(t_MI_TMSI(tmsi), imsi_suff_tx);
1795 } else {
1796 BSSGP[0].send(ts_BSSGP_PS_PAGING_IMSI(bvci, imsi));
1797 f_pcuif_rx_pch_pag_req1(tr_MI_IMSI(imsi), imsi_suff_tx);
1798 }
1799
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001800 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001801}
1802
1803testcase TC_paging_ps_from_sgsn_sign_ptmsi() runs on RAW_PCU_Test_CT {
1804 f_tc_paging_ps_from_sgsn(0, true);
1805}
1806
1807testcase TC_paging_ps_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1808 f_tc_paging_ps_from_sgsn(0);
1809}
1810
1811testcase TC_paging_ps_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1812 f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvci);
1813}
1814
1815private function f_TC_egprs_pkt_chan_req(in EGPRSPktChRequest req,
1816 template GsmRrMessage t_imm_ass := ?,
1817 PCUIF_BurstType bt := BURST_TYPE_1)
1818runs on RAW_PCU_Test_CT {
1819 var GsmRrMessage rr_msg;
1820 var uint16_t ra11;
1821 var boolean ok;
1822
1823 ra11 := enc_EGPRSPktChRequest2uint(req);
1824 log("Sending EGPRS Packet Channel Request (", ra11, "): ", req);
1825
1826 ok := f_establish_tbf(rr_msg, ra := ra11, is_11bit := 1, burst_type := bt);
1827 if (not ok) {
1828 setverdict(fail, "Failed to establush an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001829 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001830 }
1831
1832 if (not match(rr_msg, t_imm_ass)) {
1833 setverdict(fail, "Immediate Assignment does not match");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001834 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001835 }
1836
1837 setverdict(pass);
1838}
1839
1840testcase TC_egprs_pkt_chan_req_signalling() runs on RAW_PCU_Test_CT {
1841 var template GsmRrMessage imm_ass;
1842 var template IaRestOctets rest;
1843 var template EgprsUlAss ul_ass;
1844
1845 /* Initialize the PCU interface abstraction */
1846 f_init_raw(testcasename());
1847
1848 var EGPRSPktChRequest req := {
1849 /* NOTE: other fields are set in the loop */
1850 signalling := { tag := '110011'B }
1851 };
1852
1853 for (var integer i := 0; i < 6; i := i + 1) {
1854 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
1855 req.signalling.random_bits := ext_ra;
1856
1857 /* For signalling, do we expect Multiblock UL TBF Assignment? */
1858 ul_ass := tr_EgprsUlAssMultiblock(ext_ra := ext_ra);
1859 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
1860 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
1861
1862 f_TC_egprs_pkt_chan_req(req, imm_ass);
1863 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001864
1865 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001866}
1867
1868testcase TC_egprs_pkt_chan_req_one_phase() runs on RAW_PCU_Test_CT {
1869 var template GsmRrMessage imm_ass;
1870 var template IaRestOctets rest;
1871 var template EgprsUlAss ul_ass;
1872
1873 /* Initialize the PCU interface abstraction */
1874 f_init_raw(testcasename());
1875
1876 var EGPRSPktChRequest req := {
1877 /* NOTE: other fields are set in the loop */
1878 one_phase := { tag := '0'B }
1879 };
1880
1881 for (var integer i := 0; i < 6; i := i + 1) {
1882 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
1883 var BIT5 mslot_class := int2bit(f_rnd_int(32), 5);
1884 var BIT2 priority := substr(ext_ra, 0, 2);
1885 var BIT3 rand := substr(ext_ra, 2, 3);
1886
1887 req.one_phase.multislot_class := mslot_class;
1888 req.one_phase.priority := priority;
1889 req.one_phase.random_bits := rand;
1890
1891 /* For one phase access, do we expect Dynamic UL TBF Assignment? */
1892 ul_ass := tr_EgprsUlAssDynamic(ext_ra := ext_ra);
1893 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
1894 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
1895
1896 f_TC_egprs_pkt_chan_req(req, imm_ass);
1897 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001898
1899 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001900}
1901
1902testcase TC_egprs_pkt_chan_req_two_phase() runs on RAW_PCU_Test_CT {
1903 var template GsmRrMessage imm_ass;
1904 var template IaRestOctets rest;
1905 var template EgprsUlAss ul_ass;
1906
1907 /* Initialize the PCU interface abstraction */
1908 f_init_raw(testcasename());
1909
1910 var EGPRSPktChRequest req := {
1911 /* NOTE: other fields are set in the loop */
1912 two_phase := { tag := '110000'B }
1913 };
1914
1915 for (var integer i := 0; i < 6; i := i + 1) {
1916 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
1917 var BIT2 priority := substr(ext_ra, 0, 2);
1918 var BIT3 rand := substr(ext_ra, 2, 3);
1919
1920 req.two_phase.priority := priority;
1921 req.two_phase.random_bits := rand;
1922
1923 /* For two phase access, do we expect Multiblock UL TBF Assignment? */
1924 ul_ass := tr_EgprsUlAssMultiblock(ext_ra := ext_ra);
1925 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
1926 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
1927
1928 f_TC_egprs_pkt_chan_req(req, imm_ass);
1929 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001930
1931 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001932}
1933
1934control {
1935 execute( TC_pcuif_suspend() );
1936 execute( TC_ta_ptcch_idle() );
1937 execute( TC_ta_rach_imm_ass() );
1938 execute( TC_ta_idle_dl_tbf_ass() );
1939 execute( TC_ta_ptcch_ul_multi_tbf() );
1940 execute( TC_cs_lqual_ul_tbf() );
1941 execute( TC_cs_initial_ul() );
1942 execute( TC_cs_max_ul() );
1943 execute( TC_t3169() );
1944 execute( TC_t3193() );
1945 execute( TC_mo_ping_pong() );
1946 execute( TC_mo_ping_pong_with_ul_racap() );
1947 execute( TC_mt_ping_pong() );
1948 execute( TC_mt_ping_pong_with_dl_racap() );
1949 execute( TC_imm_ass_dl_block_retrans() );
1950 execute( TC_paging_cs_from_bts() );
1951 execute( TC_paging_cs_from_sgsn_sign_ptmsi() );
1952 execute( TC_paging_cs_from_sgsn_sign() );
1953 execute( TC_paging_cs_from_sgsn_ptp() );
1954 execute( TC_paging_ps_from_sgsn_sign_ptmsi() );
1955 execute( TC_paging_ps_from_sgsn_sign() );
1956 execute( TC_paging_ps_from_sgsn_ptp() );
1957
1958 /* EGPRS specific test cases */
1959 execute( TC_egprs_pkt_chan_req_signalling() );
1960 execute( TC_egprs_pkt_chan_req_one_phase() );
1961 execute( TC_egprs_pkt_chan_req_two_phase() );
1962}
1963
1964
1965
1966
1967
1968
Harald Weltea419df22019-03-21 17:23:04 +01001969}