blob: 81ff8be50ef3b6d4e87aabe4f8cd147af8d8d048 [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
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200246private function f_rlcmac_dl_block_get_tfi(RlcmacDlBlock dl_block)
247runs on RAW_PCU_Test_CT return uint5_t {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200248 if (ischosen(dl_block.data)) {
249 return dl_block.data.mac_hdr.hdr_ext.tfi;
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200250 } else if (ischosen(dl_block.data_egprs)) {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200251 return dl_block.data_egprs.mac_hdr.tfi;
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200252 } else { /* Ctrl block */
Pau Espin Pedrol45b664b2020-05-14 15:16:40 +0200253 if (match(dl_block, tr_RLCMAC_UL_PACKET_ASS_GPRS(?, tr_PktUlAssGprsDynamic(tr_DynamicAllocation(?))))) {
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200254 return dl_block.ctrl.payload.u.ul_assignment.gprs.dyn_block_alloc.ul_tfi_assignment;
255 }
Pau Espin Pedrol45b664b2020-05-14 15:16:40 +0200256 if (match(dl_block, tr_RLCMAC_UL_PACKET_ASS_EGPRS(?, tr_PktUlAssEgprsDynamic(tr_DynamicAllocation(?))))) {
257 return dl_block.ctrl.payload.u.ul_assignment.egprs.dyn_block_alloc.ul_tfi_assignment;
258 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200259 }
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200260 setverdict(fail, "DlBlock doesn't contain a TFI:", dl_block);
261 f_shutdown(__BFILE__, __LINE__);
262 return 0; /* make compiler happy */
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200263}
264
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +0200265/* Get the Chan coding command from a dl block containing PACCH UL Assignment */
266private function f_rlcmac_dl_block_get_assigned_ul_cs_mcs(RlcmacDlBlock dl_block)
267runs on RAW_PCU_Test_CT return CodingScheme {
268 if (match(dl_block, tr_RLCMAC_UL_PACKET_ASS_GPRS(?, tr_PktUlAssGprsDynamic(?)))) {
269 return f_rlcmac_block_ChCodingCommand2cs_mcs(dl_block.ctrl.payload.u.ul_assignment.gprs.ch_coding_cmd);
270 }
271 if (match(dl_block, tr_RLCMAC_UL_PACKET_ASS_EGPRS(?, tr_PktUlAssEgprsDynamic(?)))) {
272 return f_rlcmac_block_EgprsChCodingCommand2cs_mcs(dl_block.ctrl.payload.u.ul_assignment.egprs.chan_coding_cmd);
273 }
274 setverdict(fail, "DlBlock doesn't contain CS_MCS information:", dl_block);
275 f_shutdown(__BFILE__, __LINE__);
276 return CS_1; /* make compiler happy */
277}
278
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200279/* TS 44.060 sec 12.3 Ack/Nack Description */
280private function f_acknackdesc_ack_block(inout AckNackDescription desc, RlcmacDlBlock dl_block, BIT1 final_ack := '0'B)
281{
282 var uint7_t bsn;
283 var integer i;
284 var integer inc;
285
286 if (ischosen(dl_block.data)) {
287 bsn := dl_block.data.mac_hdr.hdr_ext.bsn;
288 } else {
289 bsn := dl_block.data_egprs.mac_hdr.bsn1;
290 }
291
292 inc := bsn - desc.starting_seq_nr + 1;
293 /* Filling hole? */
294 if (bsn < desc.starting_seq_nr) {
295 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - (desc.starting_seq_nr - bsn)] := int2bit(1, 1);
296 return;
297 }
298
299 /* SSN is increased, and so RBB values need to be moved */
300 for (i := 0; i < lengthof(desc.receive_block_bitmap) - inc; i := i+1) {
301 desc.receive_block_bitmap[i] := desc.receive_block_bitmap[i + inc];
302 }
303 for (i := lengthof(desc.receive_block_bitmap) - inc; i < lengthof(desc.receive_block_bitmap) - 1; i := i+1) {
304 desc.receive_block_bitmap[i] := int2bit(0, 1);
305 }
306 /* Now we can set current bit and update SSN */
307 desc.starting_seq_nr := bsn + 1;
308 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - 1] := int2bit(1, 1);
309
310 /* Finally update the final_ack bit as requested: */
311 desc.final_ack := final_ack;
312}
313
314/* This function can be used to send DATA.cnf in response to the IUT originated DATA.req.
315 * NOTE: it's the responsibility of caller to make sure that pcu_msg contains u.data_req. */
316private function f_pcuif_tx_data_cnf(in PCUIF_Message pcu_msg)
317runs on RAW_PCU_Test_CT {
318 var PCUIF_Message pcu_msg_cnf := {
319 msg_type := PCU_IF_MSG_DATA_CNF,
320 bts_nr := pcu_msg.bts_nr,
321 spare := pcu_msg.spare,
322 u := { data_cnf := pcu_msg.u.data_req }
323 };
324
325 /* PCU wants DATA.cnf containing basically everything that was in DATA.req,
326 * but PCU_IF_SAPI_PCH is a special case - paging group shall be excluded. */
327 if (pcu_msg.u.data_req.sapi == PCU_IF_SAPI_PCH) {
328 pcu_msg_cnf.u.data_cnf.data := substr(pcu_msg.u.data_req.data, 3,
329 pcu_msg.u.data_req.len - 3);
330 }
331
332 BTS.send(pcu_msg_cnf);
333}
334
335private function f_pcuif_rx_imm_ass(out GsmRrMessage rr_imm_ass,
336 template PCUIF_Sapi sapi := PCU_IF_SAPI_AGCH,
337 template GsmRrMessage t_imm_ass := ?,
338 uint8_t bts_nr := 0)
339runs on RAW_PCU_Test_CT return boolean {
340 var PCUIF_Message pcu_msg;
341 var octetstring data;
342 timer T;
343
344 T.start(2.0);
345 alt {
346 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
347 sapi := sapi, data := ?)) -> value pcu_msg {
348 /* On PCH the payload is prefixed with paging group (3 octets): skip it.
349 * TODO: add an additional template parameter, so we can match it. */
350 if (pcu_msg.u.data_req.sapi == PCU_IF_SAPI_PCH) {
351 data := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
352 } else {
353 data := pcu_msg.u.data_req.data;
354 }
355
356 rr_imm_ass := dec_GsmRrMessage(data);
357 if (not match(rr_imm_ass, t_imm_ass)) {
358 /* Not for us? Wait for more. */
359 repeat;
360 }
361
362 log("Rx Immediate Assignment: ", rr_imm_ass);
363 setverdict(pass);
364 return true;
365 }
366 [] BTS.receive { repeat; }
367 [] T.timeout {
368 setverdict(fail, "Timeout waiting for Immediate Assignment");
369 }
370 }
371
372 return false;
373}
374
Vadim Yanitskiyf74ae992020-05-06 16:05:51 +0700375/* One phase packet access (see 3GPP TS 44.018, table 9.1.8.1) */
376private const BIT8 chan_req_def := '01111000'B;
377
Vadim Yanitskiy85cb9912020-05-06 16:29:43 +0700378/* Establish an Uplink TBF by sending RACH.ind towards the PCU */
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200379private function f_establish_tbf(out GsmRrMessage rr_imm_ass, uint8_t bts_nr := 0,
Vadim Yanitskiyf74ae992020-05-06 16:05:51 +0700380 uint16_t ra := bit2int(chan_req_def),
381 uint8_t is_11bit := 0,
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200382 PCUIF_BurstType burst_type := BURST_TYPE_0,
383 TimingAdvance ta := 0)
384runs on RAW_PCU_Test_CT return boolean {
385 var uint32_t fn;
386
387 /* FIXME: ask the BTS component to give us the current TDMA fn */
388 fn := 1337 + ta;
389
390 /* Send RACH.ind */
391 log("Sending RACH.ind on fn=", fn, " with RA=", ra, ", TA=", ta);
392 BTS.send(ts_PCUIF_RACH_IND(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
393 ra := ra, is_11bit := is_11bit,
394 burst_type := burst_type,
395 fn := fn, arfcn := 871,
396 qta := ta * 4));
397
398 /* 3GPP TS 44.018, table 9.1.8.1, note 2b: Request Reference shall be set to 127
399 * when Immediate Assignment is triggered by EGPRS Packet Channel Request. Here
400 * we assume that 11 bit RA always contains EGPRS Packet Channel Request. */
401 if (is_11bit != 0) { ra := 127; }
402
403 /* Expect Immediate (TBF) Assignment on TS0/AGCH */
404 return f_pcuif_rx_imm_ass(rr_imm_ass, PCU_IF_SAPI_AGCH,
Vadim Yanitskiy85cb9912020-05-06 16:29:43 +0700405 tr_IMM_TBF_ASS(false, ra, fn),
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200406 bts_nr := bts_nr);
407}
408
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200409private function f_imm_ass_verify_ul_tbf_ass(in GsmRrMessage rr_imm_ass, out PacketUlAssign ul_tbf_ass, template PacketUlAssign ul_ass := tr_PacketUlDynAssign)
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +0700410runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200411
412 /* Make sure we received an UL TBF Assignment */
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200413 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(ul_ass)))) {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200414 ul_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
415 log("Rx Uplink TBF assignment: ", ul_tbf_ass);
416 setverdict(pass);
417 } else {
418 setverdict(fail, "Failed to match UL TBF Assignment");
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +0700419 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200420 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200421}
422
Vadim Yanitskiy5b649cc2020-05-06 16:35:38 +0700423private function f_imm_ass_verify_dl_tbf_ass(in GsmRrMessage rr_imm_ass, out PacketDlAssign dl_tbf_ass)
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +0700424runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200425
426 /* Make sure we received a DL TBF Assignment */
427 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := true, rest := tr_IaRestOctets_DLAss(?)))) {
428 dl_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.dl;
429 log("Rx Downlink TBF assignment: ", dl_tbf_ass);
430 setverdict(pass);
431 } else {
432 setverdict(fail, "Failed to match DL TBF Assignment");
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +0700433 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200434 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200435}
436
437/* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
Pau Espin Pedrol2456dad2020-04-30 20:22:38 +0200438function f_pcuif_tx_data_ind(octetstring data, int16_t lqual_cb := 0, uint32_t fn := 0)
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200439runs on RAW_PCU_Test_CT {
440 var template RAW_PCU_EventParam ev_param := {tdma_fn := ? };
441 BTS.send(ts_PCUIF_DATA_IND(bts_nr := 0, trx_nr := 0, ts_nr := 7, block_nr := 0,
442 sapi := PCU_IF_SAPI_PDTCH, data := data,
443 fn := fn, arfcn := 871, lqual_cb := lqual_cb));
444 if (fn != 0) {
445 ev_param := {tdma_fn := fn };
446 }
447 BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PDTCH_BLOCK_SENT, ev_param));
448}
449
450/* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
451private function f_pcuif_rx_data_req(out PCUIF_Message pcu_msg)
452runs on RAW_PCU_Test_CT {
453 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
454 sapi := PCU_IF_SAPI_PDTCH, fn := 0,
455 arfcn := 871, block_nr := 0));
456 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
457 sapi := PCU_IF_SAPI_PDTCH)) -> value pcu_msg;
458}
459
460/* Expect an Immediate Assignment (paging) from PCU on PCUIF on specified sapi. */
461private function f_pcuif_rx_pch_imm_tbf_ass(out GsmRrMessage rr_imm_ass)
462runs on RAW_PCU_Test_CT {
463 var PCUIF_Message pcu_msg;
464 var octetstring macblock;
465 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
466 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
467 /* First 3 bytes contain paging group: */
468 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
469 rr_imm_ass := dec_GsmRrMessage(macblock);
470 if (not match(rr_imm_ass, tr_IMM_TBF_ASS())) {
471 setverdict(fail, "Failed to match Immediate Assignment: ", rr_imm_ass);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700472 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200473 }
474 f_pcuif_tx_data_cnf(pcu_msg);
475}
476
477/* Expect a Paging Request Type 1 from PCU on PCUIF on specified sapi. */
478private function f_pcuif_rx_pch_pag_req1(template MobileIdentityV mi1 := ?,
479 template integer pag_group := ?)
480runs on RAW_PCU_Test_CT return GsmRrMessage {
481 var GsmRrMessage rr_pag_req1;
482 var PCUIF_Message pcu_msg;
483 var octetstring imsi_suff_octstr;
484 var integer pag_group_rx;
485 var octetstring macblock;
486
487 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
488 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
489
490 /* First 3 bytes contain IMSI suffix to calculate paging group: */
491 imsi_suff_octstr := substr(pcu_msg.u.data_req.data, 0, 3);
492 pag_group_rx := str2int(oct2char(imsi_suff_octstr[0])) * 100 +
493 str2int(oct2char(imsi_suff_octstr[1])) * 10 +
494 str2int(oct2char(imsi_suff_octstr[2]));
495
496 /* Make sure we've got RR Paging Request Type 1 for a given MI */
497 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
498 rr_pag_req1 := dec_GsmRrMessage(macblock);
499 if (not match(rr_pag_req1, tr_PAG_REQ1(tr_MI_LV(mi1)))) {
500 setverdict(fail, "Failed to match Paging Request Type 1: ", rr_pag_req1);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700501 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200502 }
503
504 /* Make sure that received paging froup matches the expected one */
505 if (not match(pag_group_rx, pag_group)) {
506 setverdict(fail, "Paging group", pag_group_rx, " does not match expected ", pag_group);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700507 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200508 }
509
510 f_pcuif_tx_data_cnf(pcu_msg);
511 return rr_pag_req1;
512}
513
514private function f_tx_rlcmac_ul_block(template (value) RlcmacUlBlock ul_data, int16_t lqual_cb := 0, uint32_t fn := 0)
515runs on RAW_PCU_Test_CT {
516 var octetstring data;
517 /* Encode the payload of DATA.ind */
518 data := enc_RlcmacUlBlock(valueof(ul_data));
519 data := f_pad_oct(data, 23, '00'O); /* CS-1 */
520
521 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
522 f_pcuif_tx_data_ind(data, lqual_cb, fn);
523}
524
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200525private function f_tx_rlcmac_ul_n_blocks(uint5_t tfi, integer num_blocks := 1, template (omit) GprsTlli tlli := omit)
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200526runs on RAW_PCU_Test_CT {
527 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200528 tfi := tfi,
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200529 cv := num_blocks - 1, /* num UL blocks to be sent (to be overridden in loop) */
530 bsn := 0, /* TODO: what should be here? */
531 blocks := { /* To be generated in loop */ });
532
Pau Espin Pedrol4aac3d02020-05-13 15:13:49 +0200533 if (not istemplatekind(tlli, "omit")) {
534 ul_data.data.mac_hdr.tlli_ind := true;
535 ul_data.data.tlli := tlli;
536 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200537
538 for (var integer i := 0; i < num_blocks; i := i + 1) {
539 /* Prepare a new UL block (CV, random payload) */
540 ul_data.data.mac_hdr.countdown := (num_blocks - i - 1);
541 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
542 f_tx_rlcmac_ul_block(ul_data);
543 }
544}
545
546private function f_rx_rlcmac_dl_block(out RlcmacDlBlock dl_block, out uint32_t dl_fn, template (present) CodingScheme exp_cs_mcs := ?)
547runs on RAW_PCU_Test_CT {
548 var PCUIF_Message pcu_msg;
549 f_pcuif_rx_data_req(pcu_msg);
550 dl_block := dec_RlcmacDlBlock(pcu_msg.u.data_req.data);
551 dl_fn := pcu_msg.u.data_req.fn;
552
553 var integer len := lengthof(pcu_msg.u.data_req.data);
554 var CodingScheme cs_mcs := f_rlcmac_block_len2cs_mcs(len)
555 if (not match(f_rlcmac_block_len2cs_mcs(len), exp_cs_mcs)) {
556 setverdict(fail, "Failed to match Coding Scheme exp ", exp_cs_mcs, " vs ", cs_mcs, " (", len, ")");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700557 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200558 }
559}
560
561private function f_rx_rlcmac_dl_block_exp_ack_nack(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
562runs on RAW_PCU_Test_CT {
563 var uint32_t dl_fn;
564
565 f_rx_rlcmac_dl_block(dl_block, dl_fn);
566 if (not match(dl_block, tr_RLCMAC_UL_ACK_NACK(ul_tfi := ?, tlli := ?))) {
567 setverdict(fail, "Failed to match Packet Uplink ACK / NACK");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700568 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200569 }
570
Vadim Yanitskiy2742bcd2020-05-10 12:45:18 +0700571 poll_fn := f_rrbp_ack_fn(dl_fn, dl_block.ctrl.mac_hdr.rrbp);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200572}
573
574private function f_rx_rlcmac_dl_block_exp_dummy(out RlcmacDlBlock dl_block)
575runs on RAW_PCU_Test_CT {
576 var uint32_t dl_fn;
577
578 f_rx_rlcmac_dl_block(dl_block, dl_fn);
579 if (not match(dl_block, tr_RLCMAC_DUMMY_CTRL())) {
580 setverdict(fail, "Failed to match Packet DUMMY DL");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700581 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200582 }
583}
584
585private function f_rx_rlcmac_dl_block_exp_pkt_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
586runs on RAW_PCU_Test_CT {
587 var uint32_t dl_fn;
588
589 f_rx_rlcmac_dl_block(dl_block, dl_fn);
590 if (not match(dl_block, tr_RLCMAC_DL_PACKET_ASS())) {
591 setverdict(fail, "Failed to match Packet Downlink Assignment");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700592 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200593 }
594
Vadim Yanitskiy2742bcd2020-05-10 12:45:18 +0700595 poll_fn := f_rrbp_ack_fn(dl_fn, dl_block.ctrl.mac_hdr.rrbp);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200596}
597
598private function f_rx_rlcmac_dl_block_exp_pkt_ul_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
599runs on RAW_PCU_Test_CT {
600 var uint32_t dl_fn;
601
602 f_rx_rlcmac_dl_block(dl_block, dl_fn);
603 if (not match(dl_block, tr_RLCMAC_UL_PACKET_ASS())) {
604 setverdict(fail, "Failed to match Packet Uplink Assignment");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700605 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200606 }
607
Vadim Yanitskiy2742bcd2020-05-10 12:45:18 +0700608 poll_fn := f_rrbp_ack_fn(dl_fn, dl_block.ctrl.mac_hdr.rrbp);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200609}
610
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200611private function f_rx_rlcmac_dl_block_exp_pkt_dl_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
612runs on RAW_PCU_Test_CT {
613 var uint32_t dl_fn;
614
615 f_rx_rlcmac_dl_block(dl_block, dl_fn);
616 if (not match(dl_block, tr_RLCMAC_DL_PACKET_ASS())) {
617 setverdict(fail, "Failed to match Packet Downlink Assignment");
618 f_shutdown(__BFILE__, __LINE__);
619 }
620
621 poll_fn := f_rrbp_ack_fn(dl_fn, dl_block.ctrl.mac_hdr.rrbp);
622}
623
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200624
625private function f_rx_rlcmac_dl_block_exp_pkt_pag_req(out RlcmacDlBlock dl_block)
626runs on RAW_PCU_Test_CT {
627 var uint32_t dl_fn;
628
629 f_rx_rlcmac_dl_block(dl_block, dl_fn);
630 if (not match(dl_block, tr_RLCMAC_PACKET_PAG_REQ())) {
631 setverdict(fail, "Failed to match Packet Paging Request: ", dl_block, " vs ", tr_RLCMAC_PACKET_PAG_REQ());
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700632 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200633 }
634}
635
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700636/* This function does what could probably be done with templates */
637private function f_rlcmac_dl_block_verify_data_gprs(in RlcmacDlDataBlock data_block,
638 template (present) octetstring data := ?,
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700639 template (present) uint7_t exp_bsn := ?,
640 template (present) CodingScheme exp_cs := ?)
641runs on RAW_PCU_Test_CT {
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700642 if (not match(data_block.mac_hdr.hdr_ext.bsn, exp_bsn)) {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200643 setverdict(fail, "DL block BSN doesn't match: ",
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700644 data_block.mac_hdr.hdr_ext.bsn, " vs exp ", exp_bsn);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200645 }
646
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700647 if (lengthof(data_block.blocks) < 1) {
648 setverdict(fail, "DL block has no LLC payload: ", data_block);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700649 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200650 }
651
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700652 if (not match(data_block.blocks[0].payload, data)) {
653 setverdict(fail, "Failed to match content of LLC payload in DL Block: ",
654 data_block.blocks[0].payload, " vs ", data);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700655 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200656 }
657
658 /* Check next data blocks contain dummy frames */
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700659 if (lengthof(data_block.blocks) > 1 and substr(data_block.blocks[1].payload, 0, 3) != '43C001'O) {
660 setverdict(fail, "Second data payload is not a dummy frame: ",
661 data_block.blocks[1].payload);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700662 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200663 }
664
665 /* TODO: check exp_cs */
666}
667
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700668/* This function does what could probably be done with templates */
669private function f_rlcmac_dl_block_verify_data_egprs(in RlcmacDlEgprsDataBlock data_block,
670 template (present) octetstring data := ?,
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700671 template (present) uint14_t exp_bsn := ?,
672 template (present) CodingScheme exp_cs := ?)
673runs on RAW_PCU_Test_CT {
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700674 if (not match(data_block.mac_hdr.bsn1, exp_bsn)) {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200675 setverdict(fail, "DL block BSN doesn't match: ",
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700676 data_block.mac_hdr.bsn1, " vs exp ", exp_bsn);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200677 }
678
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700679 if (lengthof(data_block.blocks) < 1) {
680 setverdict(fail, "DL block has no LLC payload: ", data_block);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700681 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200682 }
683
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700684 if (not match(data_block.blocks[0].payload, data)) {
685 setverdict(fail, "Failed to match content of LLC payload in DL Block: ",
686 data_block.blocks[0].payload, " vs ", data);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700687 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200688 }
689
690 /* Check next data blocks contain dummy frames */
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700691 if (lengthof(data_block.blocks) > 1 and substr(data_block.blocks[1].payload, 0, 3) != '43C001'O) {
692 setverdict(fail, "Second data payload is not a dummy frame: ",
693 data_block.blocks[1].payload);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700694 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200695 }
696
697 /* 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.
698 See wireshark's egprs_Header_type1_coding_puncturing_scheme_to_mcs. */
699}
700
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700701/* High level (task specific) helper for receiving and matching GPRS/EGPRS data blocks */
702private function f_rx_rlcmac_dl_block_exp_data(out RlcmacDlBlock dl_block, out uint32_t dl_fn,
703 template (present) octetstring data := ?,
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700704 template (present) uint7_t exp_bsn := ?,
705 template (present) CodingScheme exp_cs := ?)
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200706runs on RAW_PCU_Test_CT {
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700707 /* FIXME: ideally we should use an alt statement with timeout here, rather than
708 * having +100500 layers of abstraction. This would facilitate developing the
709 * multi-TBF/-TRX/-BTS tests, where you cannot expect that the first received
710 * block is exactly what you need. */
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200711 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700712
713 /* Make sure it's either GPRS or EGPRS data block */
714 if (not match(dl_block, tr_RLCMAC_DATA)) {
715 setverdict(fail, "Failed to match DL DATA: ", dl_block, " vs ", tr_RLCMAC_DATA);
716 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200717 }
718
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700719 if (ischosen(dl_block.data_egprs)) {
720 f_rlcmac_dl_block_verify_data_egprs(dl_block.data_egprs, data, exp_bsn, exp_cs);
721 } else if (ischosen(dl_block.data)) {
722 f_rlcmac_dl_block_verify_data_gprs(dl_block.data, data, exp_bsn, exp_cs);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200723 } else {
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700724 /* Should not happen, but the caller may theoretically give us a template for CTRL */
725 setverdict(fail, "DL block is neither GPRS nor EGPRS data block: ", dl_block);
726 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200727 }
728}
729
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700730private function f_dl_block_ack_fn(in RlcmacDlBlock dl_block, uint32_t dl_fn)
731runs on RAW_PCU_Test_CT return uint32_t {
732 var boolean rrbp_valid;
733 var MacRrbp rrbp;
734
735 /* The argument must be either a GPRS or EGPRS data block */
736 if (ischosen(dl_block.data_egprs)) {
737 rrbp_valid := true; /* always valid */
738 rrbp := dl_block.data_egprs.mac_hdr.rrbp;
739 } else if (ischosen(dl_block.data)) {
740 rrbp_valid := dl_block.data.mac_hdr.mac_hdr.rrbp_valid;
741 rrbp := dl_block.data.mac_hdr.mac_hdr.rrbp;
742 } else {
Pau Espin Pedrol1832cd82020-05-13 16:42:24 +0200743 rrbp_valid := dl_block.ctrl.mac_hdr.rrbp_valid;
744 rrbp := dl_block.ctrl.mac_hdr.rrbp;
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700745 }
746
747 /* Make sure that the given block really needs to be ACKnowledged */
748 if (not rrbp_valid) {
749 setverdict(fail, "DL block shall not be ACKnowledged, field RRBP is not valid");
750 f_shutdown(__BFILE__, __LINE__);
751 }
752
753 return f_rrbp_ack_fn(dl_fn, rrbp);
754}
755
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200756testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
757 var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.cell_id.ra_id);
758 var GprsTlli tlli := 'FFFFFFFF'O;
759 timer T;
760
761 /* Initialize NS/BSSGP side */
762 f_init_bssgp();
763
764 /* Initialize the PCU interface abstraction */
765 f_init_raw(testcasename());
766
767 /* Establish BSSGP connection to the PCU */
768 f_bssgp_establish();
769
770 BTS.send(ts_PCUIF_SUSP_REQ(0, tlli, ra_id, 0));
771
772 T.start(2.0);
773 alt {
774 [] BSSGP_SIG[0].receive(tr_BSSGP_SUSPEND(tlli, mp_gb_cfg.cell_id.ra_id)) {
775 setverdict(pass);
776 }
777 [] T.timeout {
778 setverdict(fail, "Timeout waiting for BSSGP SUSPEND");
779 }
780 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700781
782 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200783}
784
785/* Test of correct Timing Advance at the time of TBF establishment
786 * (derived from timing offset of the Access Burst). */
787testcase TC_ta_rach_imm_ass() runs on RAW_PCU_Test_CT {
788 var GsmRrMessage rr_msg;
789 var boolean ok;
790
791 /* Initialize the PCU interface abstraction */
792 f_init_raw(testcasename());
793
794 /* We cannot send too many TBF requests in a short time because
795 * at some point the PCU will fail to allocate a new TBF. */
796 for (var TimingAdvance ta := 0; ta < 64; ta := ta + 16) {
797 /* Establish an Uplink TBF (send RACH.ind with current TA) */
798 ok := f_establish_tbf(rr_msg, bts_nr := 0, ta := ta);
799 if (not ok) {
800 setverdict(fail, "Failed to establish an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700801 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200802 }
803
804 /* Make sure Timing Advance IE matches out expectations */
Vadim Yanitskiy8685b382020-05-06 16:53:26 +0700805 if (rr_msg.payload.imm_ass.timing_advance != ta) {
806 setverdict(fail, "Timing Advance mismatch: ",
807 rr_msg.payload.imm_ass.timing_advance,
808 " vs expected ", ta);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700809 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200810 }
811 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700812
813 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200814}
815
816/* Verify Timing Advance value(s) indicated during the packet Downlink assignment
817 * procedure as per 3GPP TS 44.018, section 3.5.3. There seems to be a bug in the
818 * IUT that causes it to send an unreasonable Timing Advance value > 0 despite
819 * no active TBF exists at the moment of establishment (idle mode). */
820testcase TC_ta_idle_dl_tbf_ass() runs on RAW_PCU_Test_CT {
821 var OCT4 tlli := f_rnd_octstring(4);
822 var GsmRrMessage rr_imm_ass;
823
824 /* Initialize NS/BSSGP side */
825 f_init_bssgp();
826
827 /* Initialize the PCU interface abstraction */
828 f_init_raw(testcasename());
829
830 /* Establish BSSGP connection to the PCU */
831 f_bssgp_establish();
832 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
833
834 /* SGSN sends some DL data, PCU will initiate Packet Downlink
835 * Assignment on CCCH (PCH). We don't care about the payload. */
836 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, f_rnd_octstring(10)));
837 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass); // TODO: match by TLLI!
838
839 /* Make sure that Timing Advance is 0 (the actual value is not known yet).
840 * As per 3GPP S 44.018, section 3.5.3.1.2, the network *shall* initiate
841 * the procedures defined in 3GPP TS 44.060 or use the polling mechanism. */
842 if (not match(rr_imm_ass, tr_IMM_TBF_ASS(ta := 0))) {
843 setverdict(fail, "Timing Advance value doesn't match");
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200844 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700845
846 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200847}
848
849/* Verify that the PCU generates valid PTCCH/D messages
850 * while neither Uplink nor Downlink TBF is established. */
851testcase TC_ta_ptcch_idle() runs on RAW_PCU_Test_CT {
852 var PTCCHDownlinkMsg ptcch_msg;
853 var PCUIF_Message pcu_msg;
854 timer T;
855
856 /* Initialize the PCU interface abstraction */
857 f_init_raw(testcasename());
858
859 /* Sent an RTS.req for PTCCH/D */
860 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
861 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
862 arfcn := 871, block_nr := 0));
863 T.start(5.0);
864 alt {
865 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
866 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
867 log("Rx DATA.req message: ", pcu_msg);
868 setverdict(pass);
869 }
870 [] BTS.receive(PCUIF_Message:?) { repeat; }
871 [] T.timeout {
872 setverdict(fail, "Timeout waiting for a PTCCH/D block");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700873 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200874 }
875 }
876
877 ptcch_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
878 log("Decoded PTCCH/D message: ", ptcch_msg);
879
880 /* Make sure the message is encoded correctly
881 * TODO: do we expect all TA values to be equal '1111111'B? */
882 if (not match(ptcch_msg, tr_PTCCHDownlinkMsg)) {
883 setverdict(fail, "Malformed PTCCH/D message");
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200884 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700885
886 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200887}
888
889/* Test of correct Timing Advance during an active Uplink TBF.
890 *
891 * Unlike the circuit-switched domain, Uplink transmissions on PDCH time-slots
892 * are not continuous and there can be long time gaps between them. This happens
893 * due to a bursty nature of packet data. The actual Timing Advance of a MS may
894 * significantly change between such rare Uplink transmissions, so GPRS introduces
895 * additional mechanisms to control Timing Advance, and thus reduce interference
896 * between neighboring TDMA time-slots.
897 *
898 * At the moment of Uplink TBF establishment, initial Timing Advance is measured
899 * from ToA (Timing of Arrival) of an Access Burst. This is covered by another
900 * test case - TC_ta_rach_imm_ass. In response to that Access Burst the network
901 * sends Immediate Assignment on AGCH, which _may_ contain Timing Advance Index
902 * among with the initial Timing Advance value. And here PTCCH comes to play.
903 *
904 * PTCCH is a unidirectional channel on which the network can instruct a sub-set
905 * of 16 MS (whether TBFs are active or not) to adjust their Timing Advance
906 * continuously. To ensure continuous measurements of the signal propagation
907 * delay, the MSs shall transmit Access Bursts on Uplink (PTCCH/U) on sub-slots
908 * defined by an assigned Timing Advance Index (see 3GPP TS 45.002).
909 *
910 * The purpose of this test case is to verify the assignment of Timing Advance
911 * Index, and the process of Timing Advance notification on PTCCH/D. The MTC
912 * first establishes several Uplink TBFs, but does not transmit any Uplink
913 * blocks on them. During 4 TDMA multi-frame periods the MTC is sending RACH
914 * indications to the PCU, checking the correctness of two received PTCCH/D
915 * messages (period of PTCCH/D is two multi-frames).
916 */
917
918/* List of ToA values for Access Bursts to be sent on PTCCH/U,
919 * each ToA (Timing of Arrival) value is in units of 1/4 of
920 * a symbol (i.e. 1 symbol is 4 QTA units). */
921type record length(16) of int16_t PTCCH_TAI_ToA_MAP;
922const PTCCH_TAI_ToA_MAP ptcch_toa_map_def := {
923 0, 0, 0, 0,
924 0, 0, 0, 0,
925 0, 0, 0, 0,
926 0, 0, 0, 0
927};
928
929private altstep as_ta_ptcch(uint8_t bts_nr := 0, uint8_t trx_nr := 0, uint8_t ts_nr := 7,
930 in PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def)
931runs on RAW_PCU_Test_CT {
932 var RAW_PCU_Event event;
933 var integer ss;
934
935 /* Send Access Bursts on PTCCH/U for every TA Index */
936 [] BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PTCCH_UL_BURST)) -> value event {
937 ss := f_tdma_ptcch_fn2ss(event.data.tdma_fn);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700938 if (ss < 0) { /* Shall not happen */
939 f_shutdown(__BFILE__, __LINE__);
940 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200941
942 log("Sending an Access Burst on PTCCH/U",
943 ", sub-slot=", ss, " (TAI)",
944 ", fn=", event.data.tdma_fn,
945 ", ToA=", toa_map[ss], " (QTA)");
946 /* TODO: do we care about RA and burst format? */
947 BTS.send(ts_PCUIF_RACH_IND(bts_nr, trx_nr, ts_nr,
948 ra := oct2int('3A'O),
949 is_11bit := 0,
950 burst_type := BURST_TYPE_0,
951 fn := event.data.tdma_fn,
952 arfcn := 871,
953 qta := toa_map[ss],
954 sapi := PCU_IF_SAPI_PTCCH));
955 repeat;
956 }
957}
958
959private function f_TC_ta_ptcch_ul_multi_tbf(in PTCCH_TAI_ToA_MAP ptcch_toa_map,
960 template PTCCHDownlinkMsg t_ta_msg)
961runs on RAW_PCU_Test_CT {
962 var PTCCHDownlinkMsg ta_msg;
963 var PCUIF_Message pcu_msg;
964 timer T;
965
966 /* First, send an RTS.req for the upcoming PTCCH/D block */
967 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
968 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
969 arfcn := 871, block_nr := 0));
970 T.start(2.0);
971 alt {
972 /* Keep sending of Access Bursts during two multi-frames (period of PTCCH/D)
973 * with increasing ToA (Timing of Arrival) values: 0, 7, 14, 28, 35... */
974 [] as_ta_ptcch(bts_nr := 0, trx_nr := 0, ts_nr := 7, toa_map := ptcch_toa_map);
975 /* In the end of 2nd multi-frame we should receive a PTCCH/D block */
976 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
977 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
978 ta_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
979 log("Rx PTCCH/D message: ", ta_msg);
980
981 /* Make sure Timing Advance values match our expectations */
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700982 if (not match(ta_msg, t_ta_msg)) {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200983 setverdict(fail, "PTCCH/D message does not match: ", t_ta_msg);
984 }
985 }
986 [] BTS.receive { repeat; }
987 [] T.timeout {
988 setverdict(fail, "Timeout waiting for a PTCCH/D block");
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200989 }
990 }
991}
992
993testcase TC_ta_ptcch_ul_multi_tbf() runs on RAW_PCU_Test_CT {
994 var template PacketUlAssign t_ul_tbf_ass;
995 var PacketUlAssign ul_tbf_ass[7];
996 var GsmRrMessage rr_msg[7];
997 var boolean ok;
998
999 /* Initialize the PCU interface abstraction */
1000 f_init_raw(testcasename());
1001
1002 /* Enable forwarding of PTCCH/U TDMA events to us */
1003 BTS.send(ts_RAW_PCU_CMD(TDMA_CMD_ENABLE_PTCCH_UL_FWD));
1004
1005 /* Establish 7 Uplink TBFs (USF flag is 3 bits long, '111'B is reserved) */
1006 for (var integer i := 0; i < 7; i := i + 1) {
1007 ok := f_establish_tbf(rr_msg[i], ta := 0);
1008 if (not ok) {
1009 setverdict(fail, "Failed to establish an Uplink TBF #", i);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001010 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001011 }
1012
1013 /* Make sure we received an UL TBF Assignment */
1014 if (match(rr_msg[i], tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
1015 ul_tbf_ass[i] := rr_msg[i].payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
1016 log("Rx Uplink TBF assignment for #", i, ": ", ul_tbf_ass[i]);
1017 } else {
1018 setverdict(fail, "Failed to match UL TBF Assignment for #", i);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001019 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001020 }
1021
1022 /* We expect incremental TFI/USF assignment (dynamic allocation) */
1023 t_ul_tbf_ass := tr_PacketUlDynAssign(tfi := i, usf := i);
1024 if (not match(ul_tbf_ass[i], t_ul_tbf_ass)) {
1025 setverdict(fail, "Failed to match Packet Uplink Assignment for #", i);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001026 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001027 }
1028
1029 /* We also expect Timing Advance Index to be a part of the assignment */
1030 if (ul_tbf_ass[i].dynamic.ta_index != i) {
1031 setverdict(fail, "Failed to match Timing Advance Index for #", i);
1032 /* Keep going, the current OsmoPCU does not assign TA Index */
1033 }
1034 }
1035
1036 /* Prepare a list of ToA values for Access Bursts to be sent on PTCCH/U */
1037 var PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def;
1038 for (var integer i := 0; i < 7; i := i + 1) {
1039 /* ToA in units of 1/4 of a symbol */
1040 toa_map[i] := (i + 1) * 7 * 4;
1041 }
1042
1043 /* Now we have all 7 TBFs established in one-phase access mode,
1044 * however we will not be sending any data on them. Instead, we
1045 * will be sending RACH.ind on PTCCH/U during 4 multi-frame
1046 * periods (TAI 0..8), and then will check two PTCCH/D blocks.
1047 *
1048 * Why not 4 TBFs at once? Because Uplink is delayed by 3 TDMA
1049 * time-slots, so at the moment of scheduling a PTCCH/D block
1050 * the PCU has odd number of PTCCH/U Access Bursts received. */
1051 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
1052 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
1053 /* Other values are not known (yet) */
1054 tai3_ta := ?));
1055 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
1056 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
1057 tai3_ta := 28, tai4_ta := 35, tai5_ta := 42,
1058 /* Other values are out of our interest */
1059 tai6_ta := ?));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001060
1061 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001062}
1063
1064/* Default link quality adaptation (Coding Scheme) ranges (inclusive).
1065 * OsmoPCU (VTY): cs link-quality-ranges cs1 6 cs2 5 8 cs3 7 13 cs4 12
1066 *
1067 * NOTE: the ranges are intentionally overlapping because OsmoPCU
1068 * does not change CS/MCS on the range borders (5-6, 7-8, 12-13). */
1069private template integer CS1_lqual_dB_range := (-infinity .. 6);
1070private template integer CS2_lqual_dB_range := (5 .. 8);
1071private template integer CS3_lqual_dB_range := (7 .. 13);
1072private template integer CS4_lqual_dB_range := (12 .. infinity);
1073
1074testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
1075 var GsmRrMessage rr_imm_ass;
1076 var PacketUlAssign ul_tbf_ass;
1077 var RlcmacDlBlock dl_block;
1078 var PCUIF_Message pcu_msg;
1079 var octetstring data;
1080 var boolean ok;
1081 var uint32_t unused_fn;
1082
1083 /* Initialize the PCU interface abstraction */
1084 f_init_raw(testcasename());
1085
1086 f_pcuvty_set_allowed_cs_mcs();
1087 f_pcuvty_set_link_quality_ranges();
1088
1089 /* Establish an Uplink TBF */
1090 ok := f_establish_tbf(rr_imm_ass);
1091 if (not ok) {
1092 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001093 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001094 }
1095
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001096 /* Make sure we've got an Uplink TBF assignment */
1097 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001098
1099 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1100 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1101 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
1102 bsn := 0, /* TODO: what should be here? */
1103 blocks := { /* To be generated in loop */ });
1104
1105 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1106 ul_data.data.tlli := '00000001'O;
1107
1108 /* The actual / old link quality values. We need to keep track of the old
1109 * (basically previous) link quality value, because OsmoPCU actually
1110 * changes the coding scheme if not only the actual, but also the old
1111 * value leaves the current link quality range (window). */
1112 var integer lqual := 0;
1113 var integer lqual_old;
1114
1115 /* 16 UL blocks (0 .. 15 dB, step = 1 dB) */
1116 for (var integer i := 0; i < 16; i := i + 1) {
1117 /* Prepare a new UL block (CV, random payload) */
1118 ul_data.data.mac_hdr.countdown := (15 - i);
1119 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1120
1121 /* Update the old / actual link quality */
1122 lqual_old := lqual;
1123 lqual := i;
1124
1125 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1126 log("Sending DATA.ind with link quality (dB): ", lqual);
1127 f_tx_rlcmac_ul_block(ul_data, lqual * 10);
1128
1129 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1130 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1131
1132 log("Rx Packet Uplink ACK / NACK with Channel Coding Command: ",
1133 dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd);
1134
1135 /* Match the received Channel Coding Command. Since we are increasing
1136 * the link quality value on each iteration and not decreasing, there
1137 * is no need to check the both old and current link quality values. */
1138 var template ChCodingCommand ch_coding;
1139 select (lqual_old) {
1140 case (CS1_lqual_dB_range) { ch_coding := CH_CODING_CS1; }
1141 case (CS2_lqual_dB_range) { ch_coding := CH_CODING_CS2; }
1142 case (CS3_lqual_dB_range) { ch_coding := CH_CODING_CS3; }
1143 case (CS4_lqual_dB_range) { ch_coding := CH_CODING_CS4; }
1144 }
1145
1146 if (not match(dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd, ch_coding)) {
1147 setverdict(fail, "Channel Coding does not match our expectations: ", ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001148 }
1149 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001150
1151 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001152}
1153
1154/* Test the max UL CS set by VTY works fine */
1155testcase TC_cs_initial_ul() runs on RAW_PCU_Test_CT {
1156 var GsmRrMessage rr_imm_ass;
1157 var PacketUlAssign ul_tbf_ass;
1158 var RlcmacDlBlock dl_block;
1159 var boolean ok;
1160 var integer lqual_cb;
1161 var ChCodingCommand last_ch_coding;
1162 var uint32_t unused_fn;
1163
1164 /* Initialize the PCU interface abstraction */
1165 f_init_raw(testcasename());
1166
1167 /* Set initial UL CS to 3 */
1168 g_cs_initial_ul := 3;
1169 f_pcuvty_set_allowed_cs_mcs();
1170 f_pcuvty_set_link_quality_ranges();
1171
1172 /* Take lqual (dB->cB) so that we stay in that CS */
1173 lqual_cb := g_cs_lqual_ranges[2].low * 10;
1174
1175 /* Establish an Uplink TBF */
1176 ok := f_establish_tbf(rr_imm_ass);
1177 if (not ok) {
1178 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001179 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001180 }
1181
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001182 /* Make sure we've got an Uplink TBF assignment */
1183 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001184
1185 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1186 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1187 cv := 3, /* 8 UL blocks to be sent (to be overridden in loop) */
1188 bsn := 0, /* TODO: what should be here? */
1189 blocks := { /* To be generated in loop */ });
1190
1191 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1192 ul_data.data.tlli := '00000001'O;
1193
1194 /* 3 UL blocks, check we are in same initial CS: */
1195 for (var integer i := 0; i < 3; i := i + 1) {
1196 /* Prepare a new UL block (CV, random payload) */
1197 ul_data.data.mac_hdr.countdown := (7 - i);
1198 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1199
1200 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1201 f_tx_rlcmac_ul_block(ul_data, lqual_cb);
1202
1203 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1204 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1205 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1206 }
1207
1208 if (last_ch_coding != CH_CODING_CS3) {
1209 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001210 }
1211
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001212 /* Remaining UL blocks are used to make sure regardless of initial
1213 /* lqual, we can go lower at any time */
1214
1215 /* 5 UL blocks, check we are in same initial CS: */
1216 for (var integer i := 3; i < 8; i := i + 1) {
1217 /* Prepare a new UL block (CV, random payload) */
1218 ul_data.data.mac_hdr.countdown := (7 - i);
1219 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1220
1221 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1222 f_tx_rlcmac_ul_block(ul_data, 0); /* 0 dB, make sure we downgrade CS */
1223
1224 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1225 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1226
1227 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1228 }
1229
1230 if (last_ch_coding != CH_CODING_CS1) {
1231 setverdict(fail, "Channel Coding does not match our expectations (CS-1): ", last_ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001232 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001233
1234 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001235}
1236
1237/* Test the max UL CS set by VTY works fine */
1238testcase TC_cs_max_ul() runs on RAW_PCU_Test_CT {
1239 var GsmRrMessage rr_imm_ass;
1240 var PacketUlAssign ul_tbf_ass;
1241 var RlcmacDlBlock dl_block;
1242 var boolean ok;
1243 var ChCodingCommand last_ch_coding;
1244 var uint32_t unused_fn;
1245
1246 /* Initialize the PCU interface abstraction */
1247 f_init_raw(testcasename());
1248
1249 /* Set maximum allowed UL CS to 3 */
1250 g_cs_max_ul := 3;
1251 f_pcuvty_set_allowed_cs_mcs();
1252 f_pcuvty_set_link_quality_ranges();
1253
1254 /* Establish an Uplink TBF */
1255 ok := f_establish_tbf(rr_imm_ass);
1256 if (not ok) {
1257 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001258 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001259 }
1260
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001261 /* Make sure we've got an Uplink TBF assignment */
1262 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001263
1264 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1265 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1266 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
1267 bsn := 0, /* TODO: what should be here? */
1268 blocks := { /* To be generated in loop */ });
1269
1270 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1271 ul_data.data.tlli := '00000001'O;
1272
1273 /* 16 UL blocks */
1274 for (var integer i := 0; i < 16; i := i + 1) {
1275 /* Prepare a new UL block (CV, random payload) */
1276 ul_data.data.mac_hdr.countdown := (15 - i);
1277 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1278
1279 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1280 f_tx_rlcmac_ul_block(ul_data, 40*10); /* 40 dB */
1281
1282 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1283 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1284
1285 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1286 }
1287
1288 if (last_ch_coding != CH_CODING_CS3) {
1289 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001290 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001291
1292 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001293}
1294
1295/* Verify PCU drops TBF after some time of inactivity. */
1296testcase TC_t3169() runs on RAW_PCU_Test_CT {
1297 var PCUIF_info_ind info_ind;
1298 var GsmRrMessage rr_imm_ass;
1299 var PacketUlAssign ul_tbf_ass;
1300 var RlcmacDlBlock dl_block;
1301 var PCUIF_Message pcu_msg;
1302 var octetstring data;
1303 var boolean ok;
1304 var uint32_t unused_fn;
1305 var OCT4 tlli := '00000001'O;
1306
1307 /* Initialize NS/BSSGP side */
1308 f_init_bssgp();
1309
1310 info_ind := valueof(ts_PCUIF_INFO_default);
1311 /* Set timer to 1 sec (default 5) to speedup test: */
1312 info_ind.t3169 := 1;
1313
1314 /* Initialize the PCU interface abstraction */
1315 f_init_raw(testcasename(), info_ind);
1316
1317 /* Establish BSSGP connection to the PCU */
1318 f_bssgp_establish();
1319 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1320
1321 /* Establish an Uplink TBF */
1322 ok := f_establish_tbf(rr_imm_ass);
1323 if (not ok) {
1324 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001325 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001326 }
1327
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001328 /* Make sure we've got an Uplink TBF assignment */
1329 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001330
Pau Espin Pedrol4aac3d02020-05-13 15:13:49 +02001331 /* Send one UL block (with TLLI since we are in One-Phase Access
1332 contention resoultion) and make sure it is ACKED fine */
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001333 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass.dynamic.tfi_assignment, 1, tlli);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001334 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1335 /* UL block should be received in SGSN */
1336 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1337
1338 /* Wait until T3169 fires (plus 1 extra sec to make sure) */
1339 f_sleep(int2float(info_ind.t3169) + 1.0);
1340
1341 /* Send an UL block once again, the TBF should be gone by now so no ACK */
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001342 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass.dynamic.tfi_assignment, 1);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001343 f_rx_rlcmac_dl_block_exp_dummy(dl_block);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001344
1345 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001346}
1347
1348/* Verify that a Downlink TBF can be assigned using PACCH shortly after the
1349 * release of prev DL TBF due to MS staying in PDCH for a while (T3192, in PCU
1350 * T3193) after DL TBF release */
1351testcase TC_t3193() runs on RAW_PCU_Test_CT {
1352 var GsmRrMessage rr_imm_ass;
1353 var PacketDlAssign dl_tbf_ass;
1354 var RlcmacDlBlock dl_block;
1355 var octetstring data := f_rnd_octstring(10);
1356 var boolean ok;
1357 var uint32_t sched_fn;
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001358 var uint32_t dl_fn;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001359 var OCT4 tlli := '00000001'O;
1360 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1361
1362 /* Initialize NS/BSSGP side */
1363 f_init_bssgp();
1364
1365 /* Initialize the PCU interface abstraction */
1366 f_init_raw(testcasename());
1367
1368 /* Establish BSSGP connection to the PCU */
1369 f_bssgp_establish();
1370 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1371
1372 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1373 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1374 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001375
1376 /* Make sure we've got a Downlink TBF assignment */
1377 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1378
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001379 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1380 f_sleep(X2002);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001381 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001382
1383 /* ACK the DL block */
1384 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001385 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1386 0, f_dl_block_ack_fn(dl_block, dl_fn));
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001387 /* we are done with the DL-TBF here so far, let's clean up our local state: */
1388 ack_nack_desc := valueof(t_AckNackDescription_init)
1389
1390 /* Now that final DL block is ACKED and TBF is released, T3193 in PCU
1391 (T3192 in MS) was started and until it fires the MS will be abailable
1392 on PDCH in case new data arrives from SGSN. Let's verify it: */
1393 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1394 f_rx_rlcmac_dl_block_exp_pkt_ass(dl_block, sched_fn);
1395 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1396
1397 /* Now that we confirmed the new assignment in the dl-tbf, lets receive the data and ack it */
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001398 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001399 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001400 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1401 0, f_dl_block_ack_fn(dl_block, dl_fn));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001402
1403 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001404}
1405
1406/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1407 * answered, so TBFs for uplink and later for downlink are created.
1408 */
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001409private function f_TC_mo_ping_pong_1phase_access(template (present) CodingScheme exp_cs_mcs := ?) runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001410 var GsmRrMessage rr_imm_ass;
1411 var PacketUlAssign ul_tbf_ass;
1412 var PacketDlAssign dl_tbf_ass;
1413 var RlcmacDlBlock dl_block;
1414 var PCUIF_Message pcu_msg;
1415 var octetstring data := f_rnd_octstring(10);
1416 var boolean ok;
1417 var uint32_t sched_fn;
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001418 var uint32_t dl_fn;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001419 var OCT4 tlli := '00000001'O;
1420 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1421
1422 /* Initialize NS/BSSGP side */
1423 f_init_bssgp();
1424
1425 /* Initialize the PCU interface abstraction */
1426 f_init_raw(testcasename());
1427
1428 /* Establish BSSGP connection to the PCU */
1429 f_bssgp_establish();
1430 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1431
1432 /* Establish an Uplink TBF */
1433 ok := f_establish_tbf(rr_imm_ass);
1434 if (not ok) {
1435 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001436 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001437 }
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001438
1439 /* Make sure we've got an Uplink TBF assignment */
1440 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001441
Pau Espin Pedrol4aac3d02020-05-13 15:13:49 +02001442 /* Send one UL block (with TLLI since we are in One-Phase Access
1443 contention resoultion) and make sure it is ACKED fine */
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001444 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass.dynamic.tfi_assignment, 1, tlli);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001445 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1446 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1447 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1448
1449 /* UL block should be received in SGSN */
1450 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1451
1452 /* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
1453 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1454 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1455
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001456 /* Make sure we've got a Downlink TBF assignment */
1457 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001458
1459 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1460 f_sleep(X2002);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001461 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0, exp_cs_mcs);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001462
1463 /* ACK the DL block */
1464 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001465 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1466 0, f_dl_block_ack_fn(dl_block, dl_fn));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001467
1468 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001469}
1470
1471/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1472 * answered, so TBFs for uplink and later for downlink are created.
1473 */
1474testcase TC_mo_ping_pong() runs on RAW_PCU_Test_CT {
1475 var CodingScheme exp_cs_mcs := CS_1;
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001476 f_TC_mo_ping_pong_1phase_access(exp_cs_mcs);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001477}
1478
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001479/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1480 * answered, so TBFs for uplink and later for downlink are created.
1481 */
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +02001482private function f_TC_mo_ping_pong_2phase_access(template (value) MSRadioAccessCapabilityV ms_racap,
1483 template (present) CodingScheme exp_ul_cs_mcs := ?,
1484 template (present) CodingScheme exp_dl_cs_mcs := ?)
1485runs on RAW_PCU_Test_CT {
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001486 var GsmRrMessage rr_imm_ass;
1487 var PacketUlAssign ul_tbf_ass;
1488 var PacketDlAssign dl_tbf_ass;
1489 var RlcmacDlBlock dl_block;
1490 var PCUIF_Message pcu_msg;
1491 var octetstring data := f_rnd_octstring(10);
1492 var boolean ok;
1493 var uint32_t sched_fn;
1494 var uint32_t dl_fn;
1495 var OCT4 tlli := '00000001'O;
1496 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +02001497 var CodingScheme cs_mcs;
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001498 /* 0111 0xxx: Single block packet access; one block period on a PDCH is needed for two phase packet access or other RR signalling purpose. */
1499 var uint16_t ra := oct2int('70'O);
1500
1501 /* Initialize NS/BSSGP side */
1502 f_init_bssgp();
1503
1504 /* Initialize the PCU interface abstraction */
1505 f_init_raw(testcasename());
1506
1507 /* Establish BSSGP connection to the PCU */
1508 f_bssgp_establish();
1509 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1510
1511 /* Establish an Uplink TBF */
1512 ok := f_establish_tbf(rr_imm_ass, ra := ra);
1513 if (not ok) {
1514 setverdict(fail, "Failed to establish TBF");
1515 f_shutdown(__BFILE__, __LINE__);
1516 }
1517
1518 /* Make sure we've got an Uplink TBF assignment */
1519 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass, tr_PacketUlSglAssign);
1520
1521 /* Send PACKET RESOURCE REQUEST to upgrade to EGPRS
1522 * (see 3GPP TS 04.60 "7.1.3.1 Initiation of the Packet resource request procedure")
1523 */
1524 f_tx_rlcmac_ul_block(ts_RLC_UL_CTRL_ACK(valueof(ts_RlcMacUlCtrl_PKT_RES_REQ(tlli, ms_racap))), 0);
1525 f_rx_rlcmac_dl_block_exp_pkt_ul_ass(dl_block, sched_fn);
1526 if (dl_block.ctrl.payload.u.ul_assignment.identity.tlli.tlli != tlli) {
1527 setverdict(fail, "Wrong TLLI ", dl_block.ctrl.payload.u.ul_assignment.identity.tlli, " received vs exp ", tlli);
1528 f_shutdown(__BFILE__, __LINE__);
1529 }
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +02001530 cs_mcs := f_rlcmac_dl_block_get_assigned_ul_cs_mcs(dl_block);
1531 if (not match(cs_mcs, exp_ul_cs_mcs)) {
1532 setverdict(fail, "Wrong CS_MCS ", cs_mcs, " received vs exp ", exp_ul_cs_mcs);
1533 f_shutdown(__BFILE__, __LINE__);
1534 }
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001535
1536 /* Send one UL block (without TLLI since we are in Second-Phase Access)
1537 and make sure it is ACKED fine */
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +02001538 f_tx_rlcmac_ul_n_blocks(f_rlcmac_dl_block_get_tfi(dl_block), 1); /* TODO: send using cs_mcs */
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001539
1540 //f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1541 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1542 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1543
1544 /* UL block should be received in SGSN */
1545 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1546
1547 /* Now SGSN sends some DL data, PCU will page on PACCH */
1548 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1549 f_rx_rlcmac_dl_block_exp_pkt_dl_ass(dl_block, sched_fn);
1550 /* DL Ass sets poll+rrbp requesting PACKET CONTROL ACK */
1551 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1552
1553 /* After acking the dl assignment, dl tbf goes into FLOW state and PCU will provide DL data when BTS asks for it */
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +02001554 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0, exp_dl_cs_mcs);
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001555
1556 /* ACK the DL block */
1557 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
1558 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1559 0, f_dl_block_ack_fn(dl_block, dl_fn));
1560
1561 f_shutdown(__BFILE__, __LINE__, final := true);
1562}
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001563
1564testcase TC_mo_ping_pong_with_ul_racap() runs on RAW_PCU_Test_CT {
1565 var MultislotCap_GPRS mscap_gprs := {
1566 gprsmultislotclass := '00011'B,
1567 gprsextendeddynalloccap := '0'B
1568 };
1569 var MSRadioAccessCapabilityV ms_racap := { valueof(ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs, omit)) };
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +02001570 var CodingScheme exp_ul_cs_mcs := f_rlcmac_block_int2cs_mcs(g_mcs_initial_ul, false);
1571 var CodingScheme exp_dl_cs_mcs := CS_2;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001572
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +02001573 f_TC_mo_ping_pong_2phase_access(ms_racap, exp_ul_cs_mcs, exp_dl_cs_mcs);
1574}
1575
1576testcase TC_mo_ping_pong_with_ul_racap_egprs_only() runs on RAW_PCU_Test_CT {
1577 /* Initialize the PCU interface abstraction with EGPRS-only */
1578 g_egprs_only := true;
1579
1580 var MultislotCap_GPRS mscap_gprs := {
1581 gprsmultislotclass := '00011'B,
1582 gprsextendeddynalloccap := '0'B
1583 };
1584 var MultislotCap_EGPRS mscap_egprs := {
1585 egprsmultislotclass := '00011'B,
1586 egprsextendeddynalloccap := '0'B
1587 };
1588 var MSRadioAccessCapabilityV ms_racap := { valueof(ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs, mscap_egprs)) };
1589 var CodingScheme exp_ul_cs_mcs := f_rlcmac_block_int2cs_mcs(g_mcs_initial_ul, true);
1590 var CodingScheme exp_dl_cs_mcs := MCS_1;
1591
1592 f_TC_mo_ping_pong_2phase_access(ms_racap, exp_ul_cs_mcs, exp_dl_cs_mcs);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001593}
1594
1595/* Test scenario where SGSN wants to send some data against MS and it is
1596 * answered by the MS on PDCH, so TBFs for downlink and later for uplink are created.
1597 */
1598private 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 {
1599 var GsmRrMessage rr_imm_ass;
1600 var PacketUlAssign ul_tbf_ass;
1601 var PacketDlAssign dl_tbf_ass;
1602 var RlcmacDlBlock dl_block;
1603 var PCUIF_Message pcu_msg;
1604 var octetstring data := f_rnd_octstring(10);
1605 var boolean ok;
1606 var uint32_t sched_fn;
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001607 var uint32_t dl_fn;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001608 var OCT4 tlli := '00000001'O;
1609 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1610
1611 /* Initialize NS/BSSGP side */
1612 f_init_bssgp();
1613
1614 /* Initialize the PCU interface abstraction */
1615 f_init_raw(testcasename());
1616
1617 /* Establish BSSGP connection to the PCU */
1618 f_bssgp_establish();
1619 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1620
1621 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1622 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data, ms_racap));
1623 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1624
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001625 /* Make sure we've got a Downlink TBF assignment */
1626 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001627
1628 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1629 f_sleep(X2002);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001630 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0, exp_cs_mcs);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001631
1632 /* ACK the DL block */
1633 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001634 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1635 0, f_dl_block_ack_fn(dl_block, dl_fn));
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001636
1637 /* Now MS wants to answer the DL data, Establish an Uplink TBF */
1638 ok := f_establish_tbf(rr_imm_ass);
1639 if (not ok) {
1640 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001641 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001642 }
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001643
1644 /* Make sure we've got an Uplink TBF assignment */
1645 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001646
Pau Espin Pedrol4aac3d02020-05-13 15:13:49 +02001647 /* Send one UL block (with TLLI since we are in One-Phase Access
1648 contention resoultion) and make sure it is ACKED fine */
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001649 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass.dynamic.tfi_assignment, 1, tlli);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001650 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1651 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1652 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1653
1654 /* UL block should be received in SGSN */
1655 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001656
1657 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001658}
1659
1660testcase TC_mt_ping_pong() runs on RAW_PCU_Test_CT {
1661 var CodingScheme exp_cs_mcs := CS_1;
1662 f_TC_mt_ping_pong(omit, exp_cs_mcs);
1663}
1664
1665/* TC_mt_ping_pong, but DL-UNITDATA contains RA Access capability with (M)CS
1666/* information about the MS */
1667testcase TC_mt_ping_pong_with_dl_racap() runs on RAW_PCU_Test_CT {
1668 var MultislotCap_GPRS_BSSGP mscap_gprs := {
1669 gprsmultislotclass := '00011'B,
1670 gprsextendeddynalloccap := '0'B
1671 } ;
1672 var MSRadioAccessCapabilityV_BSSGP ms_racap := { valueof(ts_RaCapRec_BSSGP('0001'B /* E-GSM */, mscap_gprs, omit)) };
1673 var CodingScheme exp_cs_mcs := CS_2;
1674 f_TC_mt_ping_pong(ms_racap, exp_cs_mcs);
1675}
1676
1677/* Verify that if PCU doesn't get an ACK for first DL block after IMM ASS, it
1678 * will retry by retransmitting both the IMM ASS + DL block after poll (ack)
1679 * timeout occurs (specified by sent RRBP on DL block). */
1680testcase TC_imm_ass_dl_block_retrans() runs on RAW_PCU_Test_CT {
1681 var GsmRrMessage rr_imm_ass;
1682 var PacketDlAssign dl_tbf_ass;
1683 var RlcmacDlBlock dl_block;
1684 var octetstring data := f_rnd_octstring(10);
1685 var boolean ok;
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001686 var uint32_t dl_fn;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001687 var OCT4 tlli := '00000001'O;
1688 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1689
1690 /* Initialize NS/BSSGP side */
1691 f_init_bssgp();
1692
1693 /* Initialize the PCU interface abstraction */
1694 f_init_raw(testcasename());
1695
1696 /* Establish BSSGP connection to the PCU */
1697 f_bssgp_establish();
1698 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1699
1700 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1701 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1702 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001703
1704 /* Make sure we've got a Downlink TBF assignment */
1705 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001706
1707 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1708 f_sleep(X2002);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001709 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001710
1711 /* Now we don't ack the dl block (emulate MS failed receiveing IMM ASS
1712 * or GPRS DL, or DL ACK was lost for some reason). As a result, PCU
1713 * should retrigger IMM ASS + GPRS DL procedure after poll timeout. */
1714 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001715
1716 /* Make sure we've got a Downlink TBF assignment */
1717 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1718
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001719 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1720 f_sleep(X2002);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001721 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001722
1723 /* ACK the DL block */
1724 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001725 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1726 0, f_dl_block_ack_fn(dl_block, dl_fn));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001727
1728 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001729}
1730
Vadim Yanitskiy71238c12020-05-11 03:48:06 +07001731/* Verify scheduling of multiple Downlink data blocks during one RRBP. */
1732testcase TC_dl_flow_more_blocks() runs on RAW_PCU_Test_CT {
1733 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1734 var octetstring data := f_rnd_octstring(16);
1735 var OCT4 tlli := f_rnd_octstring(4);
1736 var PacketDlAssign dl_tbf_ass;
1737 var GsmRrMessage rr_imm_ass;
1738 var RlcmacDlBlock dl_block;
1739 var uint32_t ack_fn;
1740 var uint32_t fn;
1741 timer T := 5.0;
1742
1743 /* Initialize NS/BSSGP side */
1744 f_init_bssgp();
1745
1746 /* Initialize the PCU interface abstraction */
1747 f_init_raw(testcasename());
1748
1749 /* Establish BSSGP connection to the PCU */
1750 f_bssgp_establish();
1751 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1752
1753 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1754 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1755 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1756
1757 /* Make sure we've got a Downlink TBF assignment with DL TFI */
1758 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1759 if (not ispresent(dl_tbf_ass.group1)) {
1760 setverdict(fail, "Immediate Assignment contains no DL TFI");
1761 f_shutdown(__BFILE__, __LINE__);
1762 }
1763
1764 /* Get DL TFI from received Downlink TBF assignment */
1765 var uint5_t tfi := dl_tbf_ass.group1.tfi_assignment;
1766
1767 /* Wait timer X2002 and DL block is available after CCCH IMM ASS */
1768 f_sleep(X2002);
1769
1770 /* Expect the first (GPRS DL) block with bsn=0 and rrbp_valid=1 */
1771 f_rx_rlcmac_dl_block_exp_data(dl_block, fn, data, 0);
1772 f_acknackdesc_ack_block(ack_nack_desc, dl_block);
1773
1774 /* TDMA frame number on which we are supposed to send the ACK */
1775 ack_fn := f_dl_block_ack_fn(dl_block, fn);
1776
1777 /* SGSN sends more blocks during the indicated RRBP */
1778 for (var integer bsn := 1; bsn < 63; bsn := bsn + 1) {
1779 data := f_rnd_octstring(16); /* Random LLC data */
1780 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1781
1782 f_rx_rlcmac_dl_block_exp_data(dl_block, fn, data, bsn);
1783
1784 /* Make sure this block has the same TFI as was assigned
1785 * FIXME: this is only valid for GPRS, not EGPRS. */
1786 if (dl_block.data.mac_hdr.hdr_ext.tfi != tfi) {
1787 setverdict(fail, "Rx DL data block with unexpected TFI: ",
1788 dl_block.data.mac_hdr.hdr_ext.tfi);
1789 f_shutdown(__BFILE__, __LINE__);
1790 }
1791
1792 /* Keep Ack/Nack description updated */
1793 f_acknackdesc_ack_block(ack_nack_desc, dl_block);
1794
1795 /* Break if this is the end of RRBP */
1796 if (fn == ack_fn) {
1797 ack_nack_desc.final_ack := '1'B;
1798 break;
1799 }
1800 }
1801
1802 /* This is the end of RRBP, send Packet Downlink Ack/Nack */
1803 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(tfi, ack_nack_desc), fn := fn);
1804
1805 /* Make sure that the next block (after the Ack) is dummy */
1806 f_rx_rlcmac_dl_block_exp_dummy(dl_block);
1807
1808 f_shutdown(__BFILE__, __LINE__, final := true);
1809}
1810
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001811private function f_pkt_paging_match_imsi(in PacketPagingReq req, hexstring imsi)
1812runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001813 var MobileIdentityLV_Paging mi_lv := req.repeated_pageinfo.cs.mobile_identity;
1814 var MobileIdentityV mi := dec_MobileIdentityV(mi_lv.mobile_id);
1815
1816 if (mi_lv.len != 8) { /* 8 octets: type of ID (3 bits) + even/odd flag (1 bit) + 15 BCD-encoded digits (60 bits) */
1817 setverdict(fail, "Mobile Identity length mismatch: ",
1818 "expected: 8, got: ", mi_lv.len);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001819 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001820 }
1821
1822 /* Make sure MI contains IMSI before referencing it */
1823 if (mi.typeOfIdentity != '001'B) {
1824 setverdict(fail, "Mobile Identity must be of type IMSI ('001'B), ",
1825 "got: ", mi.typeOfIdentity);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001826 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001827 } else if (mi.oddEvenInd_identity.imsi.digits != imsi) {
1828 setverdict(fail, "Mobile Identity contains unexpected IMSI, ",
1829 "expected: ", imsi, " got: ", mi.oddEvenInd_identity.imsi.digits);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001830 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001831 }
1832}
1833
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001834private function f_pkt_paging_match_tmsi(in PacketPagingReq req, template GsmTmsi tmsi)
1835runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001836 if (not match(req.repeated_pageinfo.cs.tmsi, tmsi)) {
1837 setverdict(fail, "Mobile Identity (TMSI/P-TMSI) mismatch: ",
1838 "expected: ", tmsi, "got: ", req.repeated_pageinfo.cs.tmsi);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001839 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001840 }
1841}
1842
1843/* Test CS paging over the BTS<->PCU socket.
1844 * 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.
1845 * Paging should be send on the PACCH.
1846 *
1847 * 1. Send a Paging Request over PCU socket.
1848 * 2. Send a Ready-To-Send message over PCU socket
1849 * 3. Expect a Paging Frame
1850 */
1851testcase TC_paging_cs_from_bts() runs on RAW_PCU_Test_CT {
1852 var GsmRrMessage rr_imm_ass;
1853 var PacketUlAssign ul_tbf_ass;
1854 var RlcmacDlBlock dl_block;
1855 var boolean ok;
1856 var OCT4 tlli := '00000001'O;
1857 var MobileIdentityLV mi;
1858 var octetstring mi_enc_lv;
1859 var hexstring imsi := f_gen_imsi(42);
1860
1861 /* Initialize NS/BSSGP side */
1862 f_init_bssgp();
1863
1864 /* Initialize the PCU interface abstraction */
1865 f_init_raw(testcasename());
1866
1867 /* Establish BSSGP connection to the PCU */
1868 f_bssgp_establish();
1869 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1870
1871 /* Establish an Uplink TBF */
1872 ok := f_establish_tbf(rr_imm_ass);
1873 if (not ok) {
1874 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001875 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001876 }
1877
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001878 /* Make sure we've got an Uplink TBF assignment */
1879 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001880
1881 /* build mobile Identity */
1882 mi := valueof(ts_MI_IMSI_LV(imsi));
1883 mi_enc_lv := enc_MobileIdentityLV(mi);
1884 /* Send paging request */
1885 BTS.send(ts_PCUIF_PAG_REQ(bts_nr := 0, id_lv := mi_enc_lv, chan_needed := 0,
1886 sapi :=PCU_IF_SAPI_PDTCH));
1887
1888 /* Receive it on BTS side towards MS */
1889 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
1890
1891 /* Make sure that Packet Paging Request contains the same IMSI */
1892 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1893
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001894 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001895}
1896
1897/* Test CS paging over Gb (SGSN->PCU->BTS[PDCH]).
1898 */
1899private function f_tc_paging_cs_from_sgsn(Nsvci bvci, boolean use_ptmsi := false)
1900runs on RAW_PCU_Test_CT {
1901 var GsmRrMessage rr_imm_ass;
1902 var PacketUlAssign ul_tbf_ass;
1903 var RlcmacDlBlock dl_block;
1904 var boolean ok;
1905 var OCT4 tlli := '00000001'O;
1906 var hexstring imsi := f_gen_imsi(42);
1907 var GsmTmsi tmsi;
1908
1909 /* Initialize NS/BSSGP side */
1910 f_init_bssgp();
1911
1912 /* Initialize the PCU interface abstraction */
1913 f_init_raw(testcasename());
1914
1915 /* Establish BSSGP connection to the PCU */
1916 f_bssgp_establish();
1917 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1918
1919 /* Establish an Uplink TBF */
1920 ok := f_establish_tbf(rr_imm_ass);
1921 if (not ok) {
1922 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001923 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001924 }
1925
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001926 /* Make sure we've got an Uplink TBF assignment */
1927 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001928
1929 /* Send paging request with or without TMSI */
1930 if (use_ptmsi) {
1931 tmsi := oct2int(f_rnd_octstring(4)); /* Random P-TMSI */
1932 BSSGP[0].send(ts_BSSGP_CS_PAGING_PTMSI(bvci, imsi, tmsi));
1933 } else {
1934 BSSGP[0].send(ts_BSSGP_CS_PAGING_IMSI(bvci, imsi));
1935 }
1936
1937 /* Receive it on BTS side towards MS */
1938 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
1939
1940 /* Make sure that Packet Paging Request contains the same P-TMSI/IMSI */
1941 if (use_ptmsi) {
1942 f_pkt_paging_match_tmsi(dl_block.ctrl.payload.u.paging, tmsi);
1943 } else {
1944 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1945 }
1946
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001947 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001948}
1949
1950testcase TC_paging_cs_from_sgsn_sign_ptmsi() runs on RAW_PCU_Test_CT {
1951 f_tc_paging_cs_from_sgsn(0, true);
1952}
1953
1954testcase TC_paging_cs_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1955 f_tc_paging_cs_from_sgsn(0);
1956}
1957
1958testcase TC_paging_cs_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1959 f_tc_paging_cs_from_sgsn(mp_gb_cfg.bvci);
1960}
1961
1962/* Test PS paging over Gb (SGSN->PCU->BTS[CCCH]).
1963 */
1964private function f_tc_paging_ps_from_sgsn(Nsvci bvci, boolean use_ptmsi := false)
1965runs on RAW_PCU_Test_CT {
1966 var OCT4 tlli := '00000001'O;
1967 var integer imsi_suff_tx := 423;
1968 var hexstring imsi := f_gen_imsi(imsi_suff_tx);
1969
1970 /* Initialize NS/BSSGP side */
1971 f_init_bssgp();
1972
1973 /* Initialize the PCU interface abstraction */
1974 f_init_raw(testcasename());
1975
1976 /* Establish BSSGP connection to the PCU */
1977 f_bssgp_establish();
1978 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1979
1980 /* Send BSSGP PAGING-PS (with or without TMSI), wait for RR Paging Request Type 1.
1981 * Make sure that both paging group (IMSI suffix) and Mobile Identity match. */
1982 if (use_ptmsi) {
1983 var OCT4 tmsi := f_rnd_octstring(4); /* Random P-TMSI */
1984 BSSGP[0].send(ts_BSSGP_PS_PAGING_PTMSI(bvci, imsi, oct2int(tmsi)));
1985 f_pcuif_rx_pch_pag_req1(t_MI_TMSI(tmsi), imsi_suff_tx);
1986 } else {
1987 BSSGP[0].send(ts_BSSGP_PS_PAGING_IMSI(bvci, imsi));
1988 f_pcuif_rx_pch_pag_req1(tr_MI_IMSI(imsi), imsi_suff_tx);
1989 }
1990
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001991 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001992}
1993
1994testcase TC_paging_ps_from_sgsn_sign_ptmsi() runs on RAW_PCU_Test_CT {
1995 f_tc_paging_ps_from_sgsn(0, true);
1996}
1997
1998testcase TC_paging_ps_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1999 f_tc_paging_ps_from_sgsn(0);
2000}
2001
2002testcase TC_paging_ps_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
2003 f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvci);
2004}
2005
2006private function f_TC_egprs_pkt_chan_req(in EGPRSPktChRequest req,
2007 template GsmRrMessage t_imm_ass := ?,
2008 PCUIF_BurstType bt := BURST_TYPE_1)
2009runs on RAW_PCU_Test_CT {
2010 var GsmRrMessage rr_msg;
2011 var uint16_t ra11;
2012 var boolean ok;
2013
2014 ra11 := enc_EGPRSPktChRequest2uint(req);
2015 log("Sending EGPRS Packet Channel Request (", ra11, "): ", req);
2016
2017 ok := f_establish_tbf(rr_msg, ra := ra11, is_11bit := 1, burst_type := bt);
2018 if (not ok) {
2019 setverdict(fail, "Failed to establush an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07002020 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002021 }
2022
2023 if (not match(rr_msg, t_imm_ass)) {
2024 setverdict(fail, "Immediate Assignment does not match");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07002025 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002026 }
2027
2028 setverdict(pass);
2029}
2030
2031testcase TC_egprs_pkt_chan_req_signalling() runs on RAW_PCU_Test_CT {
2032 var template GsmRrMessage imm_ass;
2033 var template IaRestOctets rest;
2034 var template EgprsUlAss ul_ass;
2035
2036 /* Initialize the PCU interface abstraction */
2037 f_init_raw(testcasename());
2038
2039 var EGPRSPktChRequest req := {
2040 /* NOTE: other fields are set in the loop */
2041 signalling := { tag := '110011'B }
2042 };
2043
2044 for (var integer i := 0; i < 6; i := i + 1) {
2045 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
2046 req.signalling.random_bits := ext_ra;
2047
2048 /* For signalling, do we expect Multiblock UL TBF Assignment? */
2049 ul_ass := tr_EgprsUlAssMultiblock(ext_ra := ext_ra);
2050 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
2051 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
2052
2053 f_TC_egprs_pkt_chan_req(req, imm_ass);
2054 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07002055
2056 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002057}
2058
2059testcase TC_egprs_pkt_chan_req_one_phase() runs on RAW_PCU_Test_CT {
2060 var template GsmRrMessage imm_ass;
2061 var template IaRestOctets rest;
2062 var template EgprsUlAss ul_ass;
2063
2064 /* Initialize the PCU interface abstraction */
2065 f_init_raw(testcasename());
2066
2067 var EGPRSPktChRequest req := {
2068 /* NOTE: other fields are set in the loop */
2069 one_phase := { tag := '0'B }
2070 };
2071
2072 for (var integer i := 0; i < 6; i := i + 1) {
2073 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
2074 var BIT5 mslot_class := int2bit(f_rnd_int(32), 5);
2075 var BIT2 priority := substr(ext_ra, 0, 2);
2076 var BIT3 rand := substr(ext_ra, 2, 3);
2077
2078 req.one_phase.multislot_class := mslot_class;
2079 req.one_phase.priority := priority;
2080 req.one_phase.random_bits := rand;
2081
2082 /* For one phase access, do we expect Dynamic UL TBF Assignment? */
2083 ul_ass := tr_EgprsUlAssDynamic(ext_ra := ext_ra);
2084 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
2085 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
2086
2087 f_TC_egprs_pkt_chan_req(req, imm_ass);
2088 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07002089
2090 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002091}
2092
2093testcase TC_egprs_pkt_chan_req_two_phase() runs on RAW_PCU_Test_CT {
2094 var template GsmRrMessage imm_ass;
2095 var template IaRestOctets rest;
2096 var template EgprsUlAss ul_ass;
2097
2098 /* Initialize the PCU interface abstraction */
2099 f_init_raw(testcasename());
2100
2101 var EGPRSPktChRequest req := {
2102 /* NOTE: other fields are set in the loop */
2103 two_phase := { tag := '110000'B }
2104 };
2105
2106 for (var integer i := 0; i < 6; i := i + 1) {
2107 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
2108 var BIT2 priority := substr(ext_ra, 0, 2);
2109 var BIT3 rand := substr(ext_ra, 2, 3);
2110
2111 req.two_phase.priority := priority;
2112 req.two_phase.random_bits := rand;
2113
2114 /* For two phase access, do we expect Multiblock UL TBF Assignment? */
2115 ul_ass := tr_EgprsUlAssMultiblock(ext_ra := ext_ra);
2116 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
2117 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
2118
2119 f_TC_egprs_pkt_chan_req(req, imm_ass);
2120 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07002121
2122 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002123}
2124
2125control {
2126 execute( TC_pcuif_suspend() );
2127 execute( TC_ta_ptcch_idle() );
2128 execute( TC_ta_rach_imm_ass() );
2129 execute( TC_ta_idle_dl_tbf_ass() );
2130 execute( TC_ta_ptcch_ul_multi_tbf() );
2131 execute( TC_cs_lqual_ul_tbf() );
2132 execute( TC_cs_initial_ul() );
2133 execute( TC_cs_max_ul() );
2134 execute( TC_t3169() );
2135 execute( TC_t3193() );
2136 execute( TC_mo_ping_pong() );
2137 execute( TC_mo_ping_pong_with_ul_racap() );
2138 execute( TC_mt_ping_pong() );
2139 execute( TC_mt_ping_pong_with_dl_racap() );
2140 execute( TC_imm_ass_dl_block_retrans() );
Vadim Yanitskiy71238c12020-05-11 03:48:06 +07002141 execute( TC_dl_flow_more_blocks() );
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002142 execute( TC_paging_cs_from_bts() );
2143 execute( TC_paging_cs_from_sgsn_sign_ptmsi() );
2144 execute( TC_paging_cs_from_sgsn_sign() );
2145 execute( TC_paging_cs_from_sgsn_ptp() );
2146 execute( TC_paging_ps_from_sgsn_sign_ptmsi() );
2147 execute( TC_paging_ps_from_sgsn_sign() );
2148 execute( TC_paging_ps_from_sgsn_ptp() );
2149
2150 /* EGPRS specific test cases */
2151 execute( TC_egprs_pkt_chan_req_signalling() );
2152 execute( TC_egprs_pkt_chan_req_one_phase() );
2153 execute( TC_egprs_pkt_chan_req_two_phase() );
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +02002154
2155 execute( TC_mo_ping_pong_with_ul_racap_egprs_only() );
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002156}
2157
2158
2159
2160
2161
2162
Harald Weltea419df22019-03-21 17:23:04 +01002163}