blob: 044d3685dee69fafe6b162b2885a8bd62a4652f6 [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;
Pau Espin Pedrol0c0bf872020-05-14 15:50:49 +0200140 var boolean g_force_two_phase_access := false;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200141
142 /* Guard timeout */
143 timer g_T_guard := 60.0;
144};
145
146private altstep as_Tguard_RAW() runs on RAW_PCU_Test_CT {
147 [] g_T_guard.timeout {
148 setverdict(fail, "Timeout of T_guard");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700149 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200150 }
151}
152
153private function f_pcuvty_set_allowed_cs_mcs() runs on RAW_PCU_Test_CT {
154 f_vty_config2(PCUVTY, {"pcu"}, "cs " & int2str(g_cs_initial_dl) & " " & int2str(g_cs_initial_ul));
155 f_vty_config2(PCUVTY, {"pcu"}, "cs max " & int2str(g_cs_max_dl) & " " & int2str(g_cs_max_ul));
156
157 f_vty_config2(PCUVTY, {"pcu"}, "mcs " & int2str(g_mcs_initial_dl) & " " & int2str(g_mcs_initial_ul));
158 f_vty_config2(PCUVTY, {"pcu"}, "mcs max " & int2str(g_mcs_max_dl) & " " & int2str(g_mcs_max_ul));
159}
160
161private function f_pcuvty_set_link_quality_ranges() runs on RAW_PCU_Test_CT {
162 var charstring cmd;
163
164 cmd := "cs link-quality-ranges" &
165 " cs1 " & int2str(g_cs_lqual_ranges[0].high) &
166 " cs2 " & int2str(g_cs_lqual_ranges[1].low) & " " & int2str(g_cs_lqual_ranges[1].high) &
167 " cs3 " & int2str(g_cs_lqual_ranges[2].low) & " " & int2str(g_cs_lqual_ranges[2].high) &
168 " cs4 " & int2str(g_cs_lqual_ranges[3].low);
169 f_vty_config2(PCUVTY, {"pcu"}, cmd);
170
171 cmd := "mcs link-quality-ranges" &
172 " mcs1 " & int2str(g_mcs_lqual_ranges[0].high) &
173 " mcs2 " & int2str(g_mcs_lqual_ranges[1].low) & " " & int2str(g_mcs_lqual_ranges[1].high) &
174 " mcs3 " & int2str(g_mcs_lqual_ranges[2].low) & " " & int2str(g_mcs_lqual_ranges[2].high) &
175 " mcs4 " & int2str(g_mcs_lqual_ranges[3].low) & " " & int2str(g_mcs_lqual_ranges[3].high) &
176 " mcs5 " & int2str(g_mcs_lqual_ranges[4].low) & " " & int2str(g_mcs_lqual_ranges[4].high) &
177 " mcs6 " & int2str(g_mcs_lqual_ranges[5].low) & " " & int2str(g_mcs_lqual_ranges[5].high) &
178 " mcs7 " & int2str(g_mcs_lqual_ranges[6].low) & " " & int2str(g_mcs_lqual_ranges[6].high) &
179 " mcs8 " & int2str(g_mcs_lqual_ranges[7].low) & " " & int2str(g_mcs_lqual_ranges[7].high) &
180 " mcs9 " & int2str(g_mcs_lqual_ranges[8].low);
181 f_vty_config2(PCUVTY, {"pcu"}, cmd);
182}
183
184private function f_init_vty(charstring id) runs on RAW_PCU_Test_CT {
185 map(self:PCUVTY, system:PCUVTY);
186 f_vty_set_prompts(PCUVTY);
187 f_vty_transceive(PCUVTY, "enable");
188
189 if (g_egprs_only) {
190 f_vty_config2(PCUVTY, {"pcu"}, "egprs only");
191 } else {
192 f_vty_config2(PCUVTY, {"pcu"}, "no egprs");
193 }
Pau Espin Pedrol0c0bf872020-05-14 15:50:49 +0200194
195 if (g_force_two_phase_access) {
196 f_vty_config2(PCUVTY, {"pcu"}, "two-phase-access");
197 } else {
198 f_vty_config2(PCUVTY, {"pcu"}, "no two-phase-access");
199 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200200}
201
Pau Espin Pedrol2456dad2020-04-30 20:22:38 +0200202function f_init_raw(charstring id, template (value) PCUIF_info_ind info_ind := ts_PCUIF_INFO_default)
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200203runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200204 /* Start the guard timer */
205 g_T_guard.start;
206 activate(as_Tguard_RAW());
207
208 /* Init PCU interface component */
209 vc_PCUIF := RAW_PCUIF_CT.create("PCUIF-" & id);
210 connect(vc_PCUIF:MTC, self:PCUIF);
211 map(vc_PCUIF:PCU, system:PCU);
212
213 /* Create one BTS component (we may want more some day) */
214 vc_BTS := RAW_PCU_BTS_CT.create("BTS-" & id);
215 connect(vc_BTS:PCUIF, vc_PCUIF:BTS);
216 connect(vc_BTS:TC, self:BTS);
217
218 f_init_vty(id);
219
220 vc_PCUIF.start(f_PCUIF_CT_handler(mp_pcu_sock_path));
221 vc_BTS.start(f_BTS_CT_handler(0, valueof(info_ind)));
222
223 /* Wait until the BTS is ready (SI13 negotiated) */
224 BTS.receive(tr_RAW_PCU_EV(BTS_EV_SI13_NEGO));
225}
226
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700227private function f_shutdown(charstring file, integer line,
228 boolean final := false)
229runs on RAW_PCU_Test_CT {
230 /* Determine if the test case was aborted in the middle */
231 if (not final) {
232 log("Test case ", testcasename(), " aborted at ", file, ":", line);
233 } else {
234 /* Guard verdict to avoid 'none' */
235 setverdict(pass);
236 }
237
238 /* Properly shutdown virtual BTS and its clock generator */
239 BTS.send(ts_RAW_PCU_CMD(GENERAL_CMD_SHUTDOWN));
240 vc_BTS.done; /* wait untill it's done */
241
242 /* Shutdown the others and MTC */
243 all component.stop;
244 mtc.stop;
245}
246
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200247template AckNackDescription t_AckNackDescription_init := {
248 final_ack := '0'B,
249 starting_seq_nr := 0,
250 receive_block_bitmap := '0000000000000000000000000000000000000000000000000000000000000000'B
251}
252
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200253private function f_rlcmac_dl_block_get_tfi(RlcmacDlBlock dl_block)
254runs on RAW_PCU_Test_CT return uint5_t {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200255 if (ischosen(dl_block.data)) {
256 return dl_block.data.mac_hdr.hdr_ext.tfi;
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200257 } else if (ischosen(dl_block.data_egprs)) {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200258 return dl_block.data_egprs.mac_hdr.tfi;
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200259 } else { /* Ctrl block */
Pau Espin Pedrol45b664b2020-05-14 15:16:40 +0200260 if (match(dl_block, tr_RLCMAC_UL_PACKET_ASS_GPRS(?, tr_PktUlAssGprsDynamic(tr_DynamicAllocation(?))))) {
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200261 return dl_block.ctrl.payload.u.ul_assignment.gprs.dyn_block_alloc.ul_tfi_assignment;
262 }
Pau Espin Pedrol45b664b2020-05-14 15:16:40 +0200263 if (match(dl_block, tr_RLCMAC_UL_PACKET_ASS_EGPRS(?, tr_PktUlAssEgprsDynamic(tr_DynamicAllocation(?))))) {
264 return dl_block.ctrl.payload.u.ul_assignment.egprs.dyn_block_alloc.ul_tfi_assignment;
265 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200266 }
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200267 setverdict(fail, "DlBlock doesn't contain a TFI:", dl_block);
268 f_shutdown(__BFILE__, __LINE__);
269 return 0; /* make compiler happy */
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200270}
271
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +0200272/* Get the Chan coding command from a dl block containing PACCH UL Assignment */
273private function f_rlcmac_dl_block_get_assigned_ul_cs_mcs(RlcmacDlBlock dl_block)
274runs on RAW_PCU_Test_CT return CodingScheme {
275 if (match(dl_block, tr_RLCMAC_UL_PACKET_ASS_GPRS(?, tr_PktUlAssGprsDynamic(?)))) {
276 return f_rlcmac_block_ChCodingCommand2cs_mcs(dl_block.ctrl.payload.u.ul_assignment.gprs.ch_coding_cmd);
277 }
278 if (match(dl_block, tr_RLCMAC_UL_PACKET_ASS_EGPRS(?, tr_PktUlAssEgprsDynamic(?)))) {
279 return f_rlcmac_block_EgprsChCodingCommand2cs_mcs(dl_block.ctrl.payload.u.ul_assignment.egprs.chan_coding_cmd);
280 }
281 setverdict(fail, "DlBlock doesn't contain CS_MCS information:", dl_block);
282 f_shutdown(__BFILE__, __LINE__);
283 return CS_1; /* make compiler happy */
284}
285
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200286/* TS 44.060 sec 12.3 Ack/Nack Description */
287private function f_acknackdesc_ack_block(inout AckNackDescription desc, RlcmacDlBlock dl_block, BIT1 final_ack := '0'B)
288{
289 var uint7_t bsn;
290 var integer i;
291 var integer inc;
292
293 if (ischosen(dl_block.data)) {
294 bsn := dl_block.data.mac_hdr.hdr_ext.bsn;
295 } else {
296 bsn := dl_block.data_egprs.mac_hdr.bsn1;
297 }
298
299 inc := bsn - desc.starting_seq_nr + 1;
300 /* Filling hole? */
301 if (bsn < desc.starting_seq_nr) {
302 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - (desc.starting_seq_nr - bsn)] := int2bit(1, 1);
303 return;
304 }
305
306 /* SSN is increased, and so RBB values need to be moved */
307 for (i := 0; i < lengthof(desc.receive_block_bitmap) - inc; i := i+1) {
308 desc.receive_block_bitmap[i] := desc.receive_block_bitmap[i + inc];
309 }
310 for (i := lengthof(desc.receive_block_bitmap) - inc; i < lengthof(desc.receive_block_bitmap) - 1; i := i+1) {
311 desc.receive_block_bitmap[i] := int2bit(0, 1);
312 }
313 /* Now we can set current bit and update SSN */
314 desc.starting_seq_nr := bsn + 1;
315 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - 1] := int2bit(1, 1);
316
317 /* Finally update the final_ack bit as requested: */
318 desc.final_ack := final_ack;
319}
320
321/* This function can be used to send DATA.cnf in response to the IUT originated DATA.req.
322 * NOTE: it's the responsibility of caller to make sure that pcu_msg contains u.data_req. */
323private function f_pcuif_tx_data_cnf(in PCUIF_Message pcu_msg)
324runs on RAW_PCU_Test_CT {
325 var PCUIF_Message pcu_msg_cnf := {
326 msg_type := PCU_IF_MSG_DATA_CNF,
327 bts_nr := pcu_msg.bts_nr,
328 spare := pcu_msg.spare,
329 u := { data_cnf := pcu_msg.u.data_req }
330 };
331
332 /* PCU wants DATA.cnf containing basically everything that was in DATA.req,
333 * but PCU_IF_SAPI_PCH is a special case - paging group shall be excluded. */
334 if (pcu_msg.u.data_req.sapi == PCU_IF_SAPI_PCH) {
335 pcu_msg_cnf.u.data_cnf.data := substr(pcu_msg.u.data_req.data, 3,
336 pcu_msg.u.data_req.len - 3);
337 }
338
339 BTS.send(pcu_msg_cnf);
340}
341
342private function f_pcuif_rx_imm_ass(out GsmRrMessage rr_imm_ass,
343 template PCUIF_Sapi sapi := PCU_IF_SAPI_AGCH,
344 template GsmRrMessage t_imm_ass := ?,
345 uint8_t bts_nr := 0)
346runs on RAW_PCU_Test_CT return boolean {
347 var PCUIF_Message pcu_msg;
348 var octetstring data;
349 timer T;
350
351 T.start(2.0);
352 alt {
353 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
354 sapi := sapi, data := ?)) -> value pcu_msg {
355 /* On PCH the payload is prefixed with paging group (3 octets): skip it.
356 * TODO: add an additional template parameter, so we can match it. */
357 if (pcu_msg.u.data_req.sapi == PCU_IF_SAPI_PCH) {
358 data := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
359 } else {
360 data := pcu_msg.u.data_req.data;
361 }
362
363 rr_imm_ass := dec_GsmRrMessage(data);
364 if (not match(rr_imm_ass, t_imm_ass)) {
365 /* Not for us? Wait for more. */
366 repeat;
367 }
368
369 log("Rx Immediate Assignment: ", rr_imm_ass);
370 setverdict(pass);
371 return true;
372 }
373 [] BTS.receive { repeat; }
374 [] T.timeout {
375 setverdict(fail, "Timeout waiting for Immediate Assignment");
376 }
377 }
378
379 return false;
380}
381
Vadim Yanitskiyf74ae992020-05-06 16:05:51 +0700382/* One phase packet access (see 3GPP TS 44.018, table 9.1.8.1) */
383private const BIT8 chan_req_def := '01111000'B;
384
Vadim Yanitskiy85cb9912020-05-06 16:29:43 +0700385/* Establish an Uplink TBF by sending RACH.ind towards the PCU */
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200386private function f_establish_tbf(out GsmRrMessage rr_imm_ass, uint8_t bts_nr := 0,
Vadim Yanitskiyf74ae992020-05-06 16:05:51 +0700387 uint16_t ra := bit2int(chan_req_def),
388 uint8_t is_11bit := 0,
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200389 PCUIF_BurstType burst_type := BURST_TYPE_0,
390 TimingAdvance ta := 0)
391runs on RAW_PCU_Test_CT return boolean {
392 var uint32_t fn;
393
394 /* FIXME: ask the BTS component to give us the current TDMA fn */
395 fn := 1337 + ta;
396
397 /* Send RACH.ind */
398 log("Sending RACH.ind on fn=", fn, " with RA=", ra, ", TA=", ta);
399 BTS.send(ts_PCUIF_RACH_IND(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
400 ra := ra, is_11bit := is_11bit,
401 burst_type := burst_type,
402 fn := fn, arfcn := 871,
403 qta := ta * 4));
404
405 /* 3GPP TS 44.018, table 9.1.8.1, note 2b: Request Reference shall be set to 127
406 * when Immediate Assignment is triggered by EGPRS Packet Channel Request. Here
407 * we assume that 11 bit RA always contains EGPRS Packet Channel Request. */
408 if (is_11bit != 0) { ra := 127; }
409
410 /* Expect Immediate (TBF) Assignment on TS0/AGCH */
411 return f_pcuif_rx_imm_ass(rr_imm_ass, PCU_IF_SAPI_AGCH,
Vadim Yanitskiy85cb9912020-05-06 16:29:43 +0700412 tr_IMM_TBF_ASS(false, ra, fn),
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200413 bts_nr := bts_nr);
414}
415
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200416private 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 +0700417runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200418
419 /* Make sure we received an UL TBF Assignment */
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200420 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 +0200421 ul_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
422 log("Rx Uplink TBF assignment: ", ul_tbf_ass);
423 setverdict(pass);
424 } else {
425 setverdict(fail, "Failed to match UL TBF Assignment");
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +0700426 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200427 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200428}
429
Vadim Yanitskiy5b649cc2020-05-06 16:35:38 +0700430private 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 +0700431runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200432
433 /* Make sure we received a DL TBF Assignment */
434 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := true, rest := tr_IaRestOctets_DLAss(?)))) {
435 dl_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.dl;
436 log("Rx Downlink TBF assignment: ", dl_tbf_ass);
437 setverdict(pass);
438 } else {
439 setverdict(fail, "Failed to match DL TBF Assignment");
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +0700440 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200441 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200442}
443
444/* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
Pau Espin Pedrol2456dad2020-04-30 20:22:38 +0200445function f_pcuif_tx_data_ind(octetstring data, int16_t lqual_cb := 0, uint32_t fn := 0)
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200446runs on RAW_PCU_Test_CT {
447 var template RAW_PCU_EventParam ev_param := {tdma_fn := ? };
448 BTS.send(ts_PCUIF_DATA_IND(bts_nr := 0, trx_nr := 0, ts_nr := 7, block_nr := 0,
449 sapi := PCU_IF_SAPI_PDTCH, data := data,
450 fn := fn, arfcn := 871, lqual_cb := lqual_cb));
451 if (fn != 0) {
452 ev_param := {tdma_fn := fn };
453 }
454 BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PDTCH_BLOCK_SENT, ev_param));
455}
456
457/* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
458private function f_pcuif_rx_data_req(out PCUIF_Message pcu_msg)
459runs on RAW_PCU_Test_CT {
460 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
461 sapi := PCU_IF_SAPI_PDTCH, fn := 0,
462 arfcn := 871, block_nr := 0));
463 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
464 sapi := PCU_IF_SAPI_PDTCH)) -> value pcu_msg;
465}
466
467/* Expect an Immediate Assignment (paging) from PCU on PCUIF on specified sapi. */
468private function f_pcuif_rx_pch_imm_tbf_ass(out GsmRrMessage rr_imm_ass)
469runs on RAW_PCU_Test_CT {
470 var PCUIF_Message pcu_msg;
471 var octetstring macblock;
472 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
473 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
474 /* First 3 bytes contain paging group: */
475 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
476 rr_imm_ass := dec_GsmRrMessage(macblock);
477 if (not match(rr_imm_ass, tr_IMM_TBF_ASS())) {
478 setverdict(fail, "Failed to match Immediate Assignment: ", rr_imm_ass);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700479 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200480 }
481 f_pcuif_tx_data_cnf(pcu_msg);
482}
483
484/* Expect a Paging Request Type 1 from PCU on PCUIF on specified sapi. */
485private function f_pcuif_rx_pch_pag_req1(template MobileIdentityV mi1 := ?,
486 template integer pag_group := ?)
487runs on RAW_PCU_Test_CT return GsmRrMessage {
488 var GsmRrMessage rr_pag_req1;
489 var PCUIF_Message pcu_msg;
490 var octetstring imsi_suff_octstr;
491 var integer pag_group_rx;
492 var octetstring macblock;
493
494 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
495 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
496
497 /* First 3 bytes contain IMSI suffix to calculate paging group: */
498 imsi_suff_octstr := substr(pcu_msg.u.data_req.data, 0, 3);
499 pag_group_rx := str2int(oct2char(imsi_suff_octstr[0])) * 100 +
500 str2int(oct2char(imsi_suff_octstr[1])) * 10 +
501 str2int(oct2char(imsi_suff_octstr[2]));
502
503 /* Make sure we've got RR Paging Request Type 1 for a given MI */
504 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
505 rr_pag_req1 := dec_GsmRrMessage(macblock);
506 if (not match(rr_pag_req1, tr_PAG_REQ1(tr_MI_LV(mi1)))) {
507 setverdict(fail, "Failed to match Paging Request Type 1: ", rr_pag_req1);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700508 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200509 }
510
511 /* Make sure that received paging froup matches the expected one */
512 if (not match(pag_group_rx, pag_group)) {
513 setverdict(fail, "Paging group", pag_group_rx, " does not match expected ", pag_group);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700514 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200515 }
516
517 f_pcuif_tx_data_cnf(pcu_msg);
518 return rr_pag_req1;
519}
520
521private function f_tx_rlcmac_ul_block(template (value) RlcmacUlBlock ul_data, int16_t lqual_cb := 0, uint32_t fn := 0)
522runs on RAW_PCU_Test_CT {
523 var octetstring data;
524 /* Encode the payload of DATA.ind */
525 data := enc_RlcmacUlBlock(valueof(ul_data));
526 data := f_pad_oct(data, 23, '00'O); /* CS-1 */
527
528 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
529 f_pcuif_tx_data_ind(data, lqual_cb, fn);
530}
531
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200532private 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 +0200533runs on RAW_PCU_Test_CT {
534 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200535 tfi := tfi,
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200536 cv := num_blocks - 1, /* num UL blocks to be sent (to be overridden in loop) */
537 bsn := 0, /* TODO: what should be here? */
538 blocks := { /* To be generated in loop */ });
539
Pau Espin Pedrol4aac3d02020-05-13 15:13:49 +0200540 if (not istemplatekind(tlli, "omit")) {
541 ul_data.data.mac_hdr.tlli_ind := true;
542 ul_data.data.tlli := tlli;
543 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200544
545 for (var integer i := 0; i < num_blocks; i := i + 1) {
546 /* Prepare a new UL block (CV, random payload) */
547 ul_data.data.mac_hdr.countdown := (num_blocks - i - 1);
548 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
549 f_tx_rlcmac_ul_block(ul_data);
550 }
551}
552
553private function f_rx_rlcmac_dl_block(out RlcmacDlBlock dl_block, out uint32_t dl_fn, template (present) CodingScheme exp_cs_mcs := ?)
554runs on RAW_PCU_Test_CT {
555 var PCUIF_Message pcu_msg;
556 f_pcuif_rx_data_req(pcu_msg);
557 dl_block := dec_RlcmacDlBlock(pcu_msg.u.data_req.data);
558 dl_fn := pcu_msg.u.data_req.fn;
559
560 var integer len := lengthof(pcu_msg.u.data_req.data);
561 var CodingScheme cs_mcs := f_rlcmac_block_len2cs_mcs(len)
562 if (not match(f_rlcmac_block_len2cs_mcs(len), exp_cs_mcs)) {
563 setverdict(fail, "Failed to match Coding Scheme exp ", exp_cs_mcs, " vs ", cs_mcs, " (", len, ")");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700564 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200565 }
566}
567
568private function f_rx_rlcmac_dl_block_exp_ack_nack(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
569runs on RAW_PCU_Test_CT {
570 var uint32_t dl_fn;
571
572 f_rx_rlcmac_dl_block(dl_block, dl_fn);
573 if (not match(dl_block, tr_RLCMAC_UL_ACK_NACK(ul_tfi := ?, tlli := ?))) {
574 setverdict(fail, "Failed to match Packet Uplink ACK / NACK");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700575 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200576 }
577
Vadim Yanitskiy2742bcd2020-05-10 12:45:18 +0700578 poll_fn := f_rrbp_ack_fn(dl_fn, dl_block.ctrl.mac_hdr.rrbp);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200579}
580
581private function f_rx_rlcmac_dl_block_exp_dummy(out RlcmacDlBlock dl_block)
582runs on RAW_PCU_Test_CT {
583 var uint32_t dl_fn;
584
585 f_rx_rlcmac_dl_block(dl_block, dl_fn);
586 if (not match(dl_block, tr_RLCMAC_DUMMY_CTRL())) {
587 setverdict(fail, "Failed to match Packet DUMMY DL");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700588 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200589 }
590}
591
592private function f_rx_rlcmac_dl_block_exp_pkt_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
593runs on RAW_PCU_Test_CT {
594 var uint32_t dl_fn;
595
596 f_rx_rlcmac_dl_block(dl_block, dl_fn);
597 if (not match(dl_block, tr_RLCMAC_DL_PACKET_ASS())) {
598 setverdict(fail, "Failed to match Packet Downlink Assignment");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700599 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200600 }
601
Vadim Yanitskiy2742bcd2020-05-10 12:45:18 +0700602 poll_fn := f_rrbp_ack_fn(dl_fn, dl_block.ctrl.mac_hdr.rrbp);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200603}
604
605private function f_rx_rlcmac_dl_block_exp_pkt_ul_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
606runs on RAW_PCU_Test_CT {
607 var uint32_t dl_fn;
608
609 f_rx_rlcmac_dl_block(dl_block, dl_fn);
610 if (not match(dl_block, tr_RLCMAC_UL_PACKET_ASS())) {
611 setverdict(fail, "Failed to match Packet Uplink Assignment");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700612 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200613 }
614
Vadim Yanitskiy2742bcd2020-05-10 12:45:18 +0700615 poll_fn := f_rrbp_ack_fn(dl_fn, dl_block.ctrl.mac_hdr.rrbp);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200616}
617
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +0200618private function f_rx_rlcmac_dl_block_exp_pkt_dl_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
619runs on RAW_PCU_Test_CT {
620 var uint32_t dl_fn;
621
622 f_rx_rlcmac_dl_block(dl_block, dl_fn);
623 if (not match(dl_block, tr_RLCMAC_DL_PACKET_ASS())) {
624 setverdict(fail, "Failed to match Packet Downlink Assignment");
625 f_shutdown(__BFILE__, __LINE__);
626 }
627
628 poll_fn := f_rrbp_ack_fn(dl_fn, dl_block.ctrl.mac_hdr.rrbp);
629}
630
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200631
632private function f_rx_rlcmac_dl_block_exp_pkt_pag_req(out RlcmacDlBlock dl_block)
633runs on RAW_PCU_Test_CT {
634 var uint32_t dl_fn;
635
636 f_rx_rlcmac_dl_block(dl_block, dl_fn);
637 if (not match(dl_block, tr_RLCMAC_PACKET_PAG_REQ())) {
638 setverdict(fail, "Failed to match Packet Paging Request: ", dl_block, " vs ", tr_RLCMAC_PACKET_PAG_REQ());
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700639 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200640 }
641}
642
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700643/* This function does what could probably be done with templates */
644private function f_rlcmac_dl_block_verify_data_gprs(in RlcmacDlDataBlock data_block,
645 template (present) octetstring data := ?,
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700646 template (present) uint7_t exp_bsn := ?,
647 template (present) CodingScheme exp_cs := ?)
648runs on RAW_PCU_Test_CT {
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700649 if (not match(data_block.mac_hdr.hdr_ext.bsn, exp_bsn)) {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200650 setverdict(fail, "DL block BSN doesn't match: ",
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700651 data_block.mac_hdr.hdr_ext.bsn, " vs exp ", exp_bsn);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200652 }
653
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700654 if (lengthof(data_block.blocks) < 1) {
655 setverdict(fail, "DL block has no LLC payload: ", data_block);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700656 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200657 }
658
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700659 if (not match(data_block.blocks[0].payload, data)) {
660 setverdict(fail, "Failed to match content of LLC payload in DL Block: ",
661 data_block.blocks[0].payload, " vs ", data);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700662 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200663 }
664
665 /* Check next data blocks contain dummy frames */
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700666 if (lengthof(data_block.blocks) > 1 and substr(data_block.blocks[1].payload, 0, 3) != '43C001'O) {
667 setverdict(fail, "Second data payload is not a dummy frame: ",
668 data_block.blocks[1].payload);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700669 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200670 }
671
672 /* TODO: check exp_cs */
673}
674
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700675/* This function does what could probably be done with templates */
676private function f_rlcmac_dl_block_verify_data_egprs(in RlcmacDlEgprsDataBlock data_block,
677 template (present) octetstring data := ?,
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700678 template (present) uint14_t exp_bsn := ?,
679 template (present) CodingScheme exp_cs := ?)
680runs on RAW_PCU_Test_CT {
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700681 if (not match(data_block.mac_hdr.bsn1, exp_bsn)) {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200682 setverdict(fail, "DL block BSN doesn't match: ",
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700683 data_block.mac_hdr.bsn1, " vs exp ", exp_bsn);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200684 }
685
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700686 if (lengthof(data_block.blocks) < 1) {
687 setverdict(fail, "DL block has no LLC payload: ", data_block);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700688 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200689 }
690
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700691 if (not match(data_block.blocks[0].payload, data)) {
692 setverdict(fail, "Failed to match content of LLC payload in DL Block: ",
693 data_block.blocks[0].payload, " vs ", data);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700694 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200695 }
696
697 /* Check next data blocks contain dummy frames */
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700698 if (lengthof(data_block.blocks) > 1 and substr(data_block.blocks[1].payload, 0, 3) != '43C001'O) {
699 setverdict(fail, "Second data payload is not a dummy frame: ",
700 data_block.blocks[1].payload);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700701 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200702 }
703
704 /* 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.
705 See wireshark's egprs_Header_type1_coding_puncturing_scheme_to_mcs. */
706}
707
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700708/* High level (task specific) helper for receiving and matching GPRS/EGPRS data blocks */
709private function f_rx_rlcmac_dl_block_exp_data(out RlcmacDlBlock dl_block, out uint32_t dl_fn,
710 template (present) octetstring data := ?,
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700711 template (present) uint7_t exp_bsn := ?,
712 template (present) CodingScheme exp_cs := ?)
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200713runs on RAW_PCU_Test_CT {
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700714 /* FIXME: ideally we should use an alt statement with timeout here, rather than
715 * having +100500 layers of abstraction. This would facilitate developing the
716 * multi-TBF/-TRX/-BTS tests, where you cannot expect that the first received
717 * block is exactly what you need. */
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200718 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700719
720 /* Make sure it's either GPRS or EGPRS data block */
721 if (not match(dl_block, tr_RLCMAC_DATA)) {
722 setverdict(fail, "Failed to match DL DATA: ", dl_block, " vs ", tr_RLCMAC_DATA);
723 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200724 }
725
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700726 if (ischosen(dl_block.data_egprs)) {
727 f_rlcmac_dl_block_verify_data_egprs(dl_block.data_egprs, data, exp_bsn, exp_cs);
728 } else if (ischosen(dl_block.data)) {
729 f_rlcmac_dl_block_verify_data_gprs(dl_block.data, data, exp_bsn, exp_cs);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200730 } else {
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700731 /* Should not happen, but the caller may theoretically give us a template for CTRL */
732 setverdict(fail, "DL block is neither GPRS nor EGPRS data block: ", dl_block);
733 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200734 }
735}
736
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700737private function f_dl_block_ack_fn(in RlcmacDlBlock dl_block, uint32_t dl_fn)
738runs on RAW_PCU_Test_CT return uint32_t {
739 var boolean rrbp_valid;
740 var MacRrbp rrbp;
741
742 /* The argument must be either a GPRS or EGPRS data block */
743 if (ischosen(dl_block.data_egprs)) {
744 rrbp_valid := true; /* always valid */
745 rrbp := dl_block.data_egprs.mac_hdr.rrbp;
746 } else if (ischosen(dl_block.data)) {
747 rrbp_valid := dl_block.data.mac_hdr.mac_hdr.rrbp_valid;
748 rrbp := dl_block.data.mac_hdr.mac_hdr.rrbp;
749 } else {
Pau Espin Pedrol1832cd82020-05-13 16:42:24 +0200750 rrbp_valid := dl_block.ctrl.mac_hdr.rrbp_valid;
751 rrbp := dl_block.ctrl.mac_hdr.rrbp;
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700752 }
753
754 /* Make sure that the given block really needs to be ACKnowledged */
755 if (not rrbp_valid) {
756 setverdict(fail, "DL block shall not be ACKnowledged, field RRBP is not valid");
757 f_shutdown(__BFILE__, __LINE__);
758 }
759
760 return f_rrbp_ack_fn(dl_fn, rrbp);
761}
762
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200763testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
764 var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.cell_id.ra_id);
765 var GprsTlli tlli := 'FFFFFFFF'O;
766 timer T;
767
768 /* Initialize NS/BSSGP side */
769 f_init_bssgp();
770
771 /* Initialize the PCU interface abstraction */
772 f_init_raw(testcasename());
773
774 /* Establish BSSGP connection to the PCU */
775 f_bssgp_establish();
776
777 BTS.send(ts_PCUIF_SUSP_REQ(0, tlli, ra_id, 0));
778
779 T.start(2.0);
780 alt {
781 [] BSSGP_SIG[0].receive(tr_BSSGP_SUSPEND(tlli, mp_gb_cfg.cell_id.ra_id)) {
782 setverdict(pass);
783 }
784 [] T.timeout {
785 setverdict(fail, "Timeout waiting for BSSGP SUSPEND");
786 }
787 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700788
789 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200790}
791
792/* Test of correct Timing Advance at the time of TBF establishment
793 * (derived from timing offset of the Access Burst). */
794testcase TC_ta_rach_imm_ass() runs on RAW_PCU_Test_CT {
795 var GsmRrMessage rr_msg;
796 var boolean ok;
797
798 /* Initialize the PCU interface abstraction */
799 f_init_raw(testcasename());
800
801 /* We cannot send too many TBF requests in a short time because
802 * at some point the PCU will fail to allocate a new TBF. */
803 for (var TimingAdvance ta := 0; ta < 64; ta := ta + 16) {
804 /* Establish an Uplink TBF (send RACH.ind with current TA) */
805 ok := f_establish_tbf(rr_msg, bts_nr := 0, ta := ta);
806 if (not ok) {
807 setverdict(fail, "Failed to establish an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700808 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200809 }
810
811 /* Make sure Timing Advance IE matches out expectations */
Vadim Yanitskiy8685b382020-05-06 16:53:26 +0700812 if (rr_msg.payload.imm_ass.timing_advance != ta) {
813 setverdict(fail, "Timing Advance mismatch: ",
814 rr_msg.payload.imm_ass.timing_advance,
815 " vs expected ", ta);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700816 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200817 }
818 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700819
820 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200821}
822
823/* Verify Timing Advance value(s) indicated during the packet Downlink assignment
824 * procedure as per 3GPP TS 44.018, section 3.5.3. There seems to be a bug in the
825 * IUT that causes it to send an unreasonable Timing Advance value > 0 despite
826 * no active TBF exists at the moment of establishment (idle mode). */
827testcase TC_ta_idle_dl_tbf_ass() runs on RAW_PCU_Test_CT {
828 var OCT4 tlli := f_rnd_octstring(4);
829 var GsmRrMessage rr_imm_ass;
830
831 /* Initialize NS/BSSGP side */
832 f_init_bssgp();
833
834 /* Initialize the PCU interface abstraction */
835 f_init_raw(testcasename());
836
837 /* Establish BSSGP connection to the PCU */
838 f_bssgp_establish();
839 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
840
841 /* SGSN sends some DL data, PCU will initiate Packet Downlink
842 * Assignment on CCCH (PCH). We don't care about the payload. */
843 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, f_rnd_octstring(10)));
844 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass); // TODO: match by TLLI!
845
846 /* Make sure that Timing Advance is 0 (the actual value is not known yet).
847 * As per 3GPP S 44.018, section 3.5.3.1.2, the network *shall* initiate
848 * the procedures defined in 3GPP TS 44.060 or use the polling mechanism. */
849 if (not match(rr_imm_ass, tr_IMM_TBF_ASS(ta := 0))) {
850 setverdict(fail, "Timing Advance value doesn't match");
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200851 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700852
853 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200854}
855
856/* Verify that the PCU generates valid PTCCH/D messages
857 * while neither Uplink nor Downlink TBF is established. */
858testcase TC_ta_ptcch_idle() runs on RAW_PCU_Test_CT {
859 var PTCCHDownlinkMsg ptcch_msg;
860 var PCUIF_Message pcu_msg;
861 timer T;
862
863 /* Initialize the PCU interface abstraction */
864 f_init_raw(testcasename());
865
866 /* Sent an RTS.req for PTCCH/D */
867 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
868 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
869 arfcn := 871, block_nr := 0));
870 T.start(5.0);
871 alt {
872 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
873 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
874 log("Rx DATA.req message: ", pcu_msg);
875 setverdict(pass);
876 }
877 [] BTS.receive(PCUIF_Message:?) { repeat; }
878 [] T.timeout {
879 setverdict(fail, "Timeout waiting for a PTCCH/D block");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700880 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200881 }
882 }
883
884 ptcch_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
885 log("Decoded PTCCH/D message: ", ptcch_msg);
886
887 /* Make sure the message is encoded correctly
888 * TODO: do we expect all TA values to be equal '1111111'B? */
889 if (not match(ptcch_msg, tr_PTCCHDownlinkMsg)) {
890 setverdict(fail, "Malformed PTCCH/D message");
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200891 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700892
893 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200894}
895
896/* Test of correct Timing Advance during an active Uplink TBF.
897 *
898 * Unlike the circuit-switched domain, Uplink transmissions on PDCH time-slots
899 * are not continuous and there can be long time gaps between them. This happens
900 * due to a bursty nature of packet data. The actual Timing Advance of a MS may
901 * significantly change between such rare Uplink transmissions, so GPRS introduces
902 * additional mechanisms to control Timing Advance, and thus reduce interference
903 * between neighboring TDMA time-slots.
904 *
905 * At the moment of Uplink TBF establishment, initial Timing Advance is measured
906 * from ToA (Timing of Arrival) of an Access Burst. This is covered by another
907 * test case - TC_ta_rach_imm_ass. In response to that Access Burst the network
908 * sends Immediate Assignment on AGCH, which _may_ contain Timing Advance Index
909 * among with the initial Timing Advance value. And here PTCCH comes to play.
910 *
911 * PTCCH is a unidirectional channel on which the network can instruct a sub-set
912 * of 16 MS (whether TBFs are active or not) to adjust their Timing Advance
913 * continuously. To ensure continuous measurements of the signal propagation
914 * delay, the MSs shall transmit Access Bursts on Uplink (PTCCH/U) on sub-slots
915 * defined by an assigned Timing Advance Index (see 3GPP TS 45.002).
916 *
917 * The purpose of this test case is to verify the assignment of Timing Advance
918 * Index, and the process of Timing Advance notification on PTCCH/D. The MTC
919 * first establishes several Uplink TBFs, but does not transmit any Uplink
920 * blocks on them. During 4 TDMA multi-frame periods the MTC is sending RACH
921 * indications to the PCU, checking the correctness of two received PTCCH/D
922 * messages (period of PTCCH/D is two multi-frames).
923 */
924
925/* List of ToA values for Access Bursts to be sent on PTCCH/U,
926 * each ToA (Timing of Arrival) value is in units of 1/4 of
927 * a symbol (i.e. 1 symbol is 4 QTA units). */
928type record length(16) of int16_t PTCCH_TAI_ToA_MAP;
929const PTCCH_TAI_ToA_MAP ptcch_toa_map_def := {
930 0, 0, 0, 0,
931 0, 0, 0, 0,
932 0, 0, 0, 0,
933 0, 0, 0, 0
934};
935
936private altstep as_ta_ptcch(uint8_t bts_nr := 0, uint8_t trx_nr := 0, uint8_t ts_nr := 7,
937 in PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def)
938runs on RAW_PCU_Test_CT {
939 var RAW_PCU_Event event;
940 var integer ss;
941
942 /* Send Access Bursts on PTCCH/U for every TA Index */
943 [] BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PTCCH_UL_BURST)) -> value event {
944 ss := f_tdma_ptcch_fn2ss(event.data.tdma_fn);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700945 if (ss < 0) { /* Shall not happen */
946 f_shutdown(__BFILE__, __LINE__);
947 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200948
949 log("Sending an Access Burst on PTCCH/U",
950 ", sub-slot=", ss, " (TAI)",
951 ", fn=", event.data.tdma_fn,
952 ", ToA=", toa_map[ss], " (QTA)");
953 /* TODO: do we care about RA and burst format? */
954 BTS.send(ts_PCUIF_RACH_IND(bts_nr, trx_nr, ts_nr,
955 ra := oct2int('3A'O),
956 is_11bit := 0,
957 burst_type := BURST_TYPE_0,
958 fn := event.data.tdma_fn,
959 arfcn := 871,
960 qta := toa_map[ss],
961 sapi := PCU_IF_SAPI_PTCCH));
962 repeat;
963 }
964}
965
966private function f_TC_ta_ptcch_ul_multi_tbf(in PTCCH_TAI_ToA_MAP ptcch_toa_map,
967 template PTCCHDownlinkMsg t_ta_msg)
968runs on RAW_PCU_Test_CT {
969 var PTCCHDownlinkMsg ta_msg;
970 var PCUIF_Message pcu_msg;
971 timer T;
972
973 /* First, send an RTS.req for the upcoming PTCCH/D block */
974 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
975 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
976 arfcn := 871, block_nr := 0));
977 T.start(2.0);
978 alt {
979 /* Keep sending of Access Bursts during two multi-frames (period of PTCCH/D)
980 * with increasing ToA (Timing of Arrival) values: 0, 7, 14, 28, 35... */
981 [] as_ta_ptcch(bts_nr := 0, trx_nr := 0, ts_nr := 7, toa_map := ptcch_toa_map);
982 /* In the end of 2nd multi-frame we should receive a PTCCH/D block */
983 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
984 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
985 ta_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
986 log("Rx PTCCH/D message: ", ta_msg);
987
988 /* Make sure Timing Advance values match our expectations */
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700989 if (not match(ta_msg, t_ta_msg)) {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200990 setverdict(fail, "PTCCH/D message does not match: ", t_ta_msg);
991 }
992 }
993 [] BTS.receive { repeat; }
994 [] T.timeout {
995 setverdict(fail, "Timeout waiting for a PTCCH/D block");
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200996 }
997 }
998}
999
1000testcase TC_ta_ptcch_ul_multi_tbf() runs on RAW_PCU_Test_CT {
1001 var template PacketUlAssign t_ul_tbf_ass;
1002 var PacketUlAssign ul_tbf_ass[7];
1003 var GsmRrMessage rr_msg[7];
1004 var boolean ok;
1005
1006 /* Initialize the PCU interface abstraction */
1007 f_init_raw(testcasename());
1008
1009 /* Enable forwarding of PTCCH/U TDMA events to us */
1010 BTS.send(ts_RAW_PCU_CMD(TDMA_CMD_ENABLE_PTCCH_UL_FWD));
1011
1012 /* Establish 7 Uplink TBFs (USF flag is 3 bits long, '111'B is reserved) */
1013 for (var integer i := 0; i < 7; i := i + 1) {
1014 ok := f_establish_tbf(rr_msg[i], ta := 0);
1015 if (not ok) {
1016 setverdict(fail, "Failed to establish an Uplink TBF #", i);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001017 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001018 }
1019
1020 /* Make sure we received an UL TBF Assignment */
1021 if (match(rr_msg[i], tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
1022 ul_tbf_ass[i] := rr_msg[i].payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
1023 log("Rx Uplink TBF assignment for #", i, ": ", ul_tbf_ass[i]);
1024 } else {
1025 setverdict(fail, "Failed to match UL TBF Assignment for #", i);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001026 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001027 }
1028
1029 /* We expect incremental TFI/USF assignment (dynamic allocation) */
1030 t_ul_tbf_ass := tr_PacketUlDynAssign(tfi := i, usf := i);
1031 if (not match(ul_tbf_ass[i], t_ul_tbf_ass)) {
1032 setverdict(fail, "Failed to match Packet Uplink Assignment for #", i);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001033 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001034 }
1035
1036 /* We also expect Timing Advance Index to be a part of the assignment */
1037 if (ul_tbf_ass[i].dynamic.ta_index != i) {
1038 setverdict(fail, "Failed to match Timing Advance Index for #", i);
1039 /* Keep going, the current OsmoPCU does not assign TA Index */
1040 }
1041 }
1042
1043 /* Prepare a list of ToA values for Access Bursts to be sent on PTCCH/U */
1044 var PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def;
1045 for (var integer i := 0; i < 7; i := i + 1) {
1046 /* ToA in units of 1/4 of a symbol */
1047 toa_map[i] := (i + 1) * 7 * 4;
1048 }
1049
1050 /* Now we have all 7 TBFs established in one-phase access mode,
1051 * however we will not be sending any data on them. Instead, we
1052 * will be sending RACH.ind on PTCCH/U during 4 multi-frame
1053 * periods (TAI 0..8), and then will check two PTCCH/D blocks.
1054 *
1055 * Why not 4 TBFs at once? Because Uplink is delayed by 3 TDMA
1056 * time-slots, so at the moment of scheduling a PTCCH/D block
1057 * the PCU has odd number of PTCCH/U Access Bursts received. */
1058 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
1059 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
1060 /* Other values are not known (yet) */
1061 tai3_ta := ?));
1062 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
1063 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
1064 tai3_ta := 28, tai4_ta := 35, tai5_ta := 42,
1065 /* Other values are out of our interest */
1066 tai6_ta := ?));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001067
1068 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001069}
1070
1071/* Default link quality adaptation (Coding Scheme) ranges (inclusive).
1072 * OsmoPCU (VTY): cs link-quality-ranges cs1 6 cs2 5 8 cs3 7 13 cs4 12
1073 *
1074 * NOTE: the ranges are intentionally overlapping because OsmoPCU
1075 * does not change CS/MCS on the range borders (5-6, 7-8, 12-13). */
1076private template integer CS1_lqual_dB_range := (-infinity .. 6);
1077private template integer CS2_lqual_dB_range := (5 .. 8);
1078private template integer CS3_lqual_dB_range := (7 .. 13);
1079private template integer CS4_lqual_dB_range := (12 .. infinity);
1080
1081testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
1082 var GsmRrMessage rr_imm_ass;
1083 var PacketUlAssign ul_tbf_ass;
1084 var RlcmacDlBlock dl_block;
1085 var PCUIF_Message pcu_msg;
1086 var octetstring data;
1087 var boolean ok;
1088 var uint32_t unused_fn;
1089
1090 /* Initialize the PCU interface abstraction */
1091 f_init_raw(testcasename());
1092
1093 f_pcuvty_set_allowed_cs_mcs();
1094 f_pcuvty_set_link_quality_ranges();
1095
1096 /* Establish an Uplink TBF */
1097 ok := f_establish_tbf(rr_imm_ass);
1098 if (not ok) {
1099 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001100 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001101 }
1102
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001103 /* Make sure we've got an Uplink TBF assignment */
1104 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001105
1106 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1107 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1108 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
1109 bsn := 0, /* TODO: what should be here? */
1110 blocks := { /* To be generated in loop */ });
1111
1112 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1113 ul_data.data.tlli := '00000001'O;
1114
1115 /* The actual / old link quality values. We need to keep track of the old
1116 * (basically previous) link quality value, because OsmoPCU actually
1117 * changes the coding scheme if not only the actual, but also the old
1118 * value leaves the current link quality range (window). */
1119 var integer lqual := 0;
1120 var integer lqual_old;
1121
1122 /* 16 UL blocks (0 .. 15 dB, step = 1 dB) */
1123 for (var integer i := 0; i < 16; i := i + 1) {
1124 /* Prepare a new UL block (CV, random payload) */
1125 ul_data.data.mac_hdr.countdown := (15 - i);
1126 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1127
1128 /* Update the old / actual link quality */
1129 lqual_old := lqual;
1130 lqual := i;
1131
1132 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1133 log("Sending DATA.ind with link quality (dB): ", lqual);
1134 f_tx_rlcmac_ul_block(ul_data, lqual * 10);
1135
1136 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1137 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1138
1139 log("Rx Packet Uplink ACK / NACK with Channel Coding Command: ",
1140 dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd);
1141
1142 /* Match the received Channel Coding Command. Since we are increasing
1143 * the link quality value on each iteration and not decreasing, there
1144 * is no need to check the both old and current link quality values. */
1145 var template ChCodingCommand ch_coding;
1146 select (lqual_old) {
1147 case (CS1_lqual_dB_range) { ch_coding := CH_CODING_CS1; }
1148 case (CS2_lqual_dB_range) { ch_coding := CH_CODING_CS2; }
1149 case (CS3_lqual_dB_range) { ch_coding := CH_CODING_CS3; }
1150 case (CS4_lqual_dB_range) { ch_coding := CH_CODING_CS4; }
1151 }
1152
1153 if (not match(dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd, ch_coding)) {
1154 setverdict(fail, "Channel Coding does not match our expectations: ", ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001155 }
1156 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001157
1158 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001159}
1160
1161/* Test the max UL CS set by VTY works fine */
1162testcase TC_cs_initial_ul() runs on RAW_PCU_Test_CT {
1163 var GsmRrMessage rr_imm_ass;
1164 var PacketUlAssign ul_tbf_ass;
1165 var RlcmacDlBlock dl_block;
1166 var boolean ok;
1167 var integer lqual_cb;
1168 var ChCodingCommand last_ch_coding;
1169 var uint32_t unused_fn;
1170
1171 /* Initialize the PCU interface abstraction */
1172 f_init_raw(testcasename());
1173
1174 /* Set initial UL CS to 3 */
1175 g_cs_initial_ul := 3;
1176 f_pcuvty_set_allowed_cs_mcs();
1177 f_pcuvty_set_link_quality_ranges();
1178
1179 /* Take lqual (dB->cB) so that we stay in that CS */
1180 lqual_cb := g_cs_lqual_ranges[2].low * 10;
1181
1182 /* Establish an Uplink TBF */
1183 ok := f_establish_tbf(rr_imm_ass);
1184 if (not ok) {
1185 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001186 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001187 }
1188
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001189 /* Make sure we've got an Uplink TBF assignment */
1190 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001191
1192 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1193 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1194 cv := 3, /* 8 UL blocks to be sent (to be overridden in loop) */
1195 bsn := 0, /* TODO: what should be here? */
1196 blocks := { /* To be generated in loop */ });
1197
1198 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1199 ul_data.data.tlli := '00000001'O;
1200
1201 /* 3 UL blocks, check we are in same initial CS: */
1202 for (var integer i := 0; i < 3; i := i + 1) {
1203 /* Prepare a new UL block (CV, random payload) */
1204 ul_data.data.mac_hdr.countdown := (7 - i);
1205 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1206
1207 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1208 f_tx_rlcmac_ul_block(ul_data, lqual_cb);
1209
1210 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1211 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1212 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1213 }
1214
1215 if (last_ch_coding != CH_CODING_CS3) {
1216 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001217 }
1218
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001219 /* Remaining UL blocks are used to make sure regardless of initial
1220 /* lqual, we can go lower at any time */
1221
1222 /* 5 UL blocks, check we are in same initial CS: */
1223 for (var integer i := 3; i < 8; i := i + 1) {
1224 /* Prepare a new UL block (CV, random payload) */
1225 ul_data.data.mac_hdr.countdown := (7 - i);
1226 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1227
1228 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1229 f_tx_rlcmac_ul_block(ul_data, 0); /* 0 dB, make sure we downgrade CS */
1230
1231 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1232 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1233
1234 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1235 }
1236
1237 if (last_ch_coding != CH_CODING_CS1) {
1238 setverdict(fail, "Channel Coding does not match our expectations (CS-1): ", last_ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001239 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001240
1241 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001242}
1243
1244/* Test the max UL CS set by VTY works fine */
1245testcase TC_cs_max_ul() runs on RAW_PCU_Test_CT {
1246 var GsmRrMessage rr_imm_ass;
1247 var PacketUlAssign ul_tbf_ass;
1248 var RlcmacDlBlock dl_block;
1249 var boolean ok;
1250 var ChCodingCommand last_ch_coding;
1251 var uint32_t unused_fn;
1252
1253 /* Initialize the PCU interface abstraction */
1254 f_init_raw(testcasename());
1255
1256 /* Set maximum allowed UL CS to 3 */
1257 g_cs_max_ul := 3;
1258 f_pcuvty_set_allowed_cs_mcs();
1259 f_pcuvty_set_link_quality_ranges();
1260
1261 /* Establish an Uplink TBF */
1262 ok := f_establish_tbf(rr_imm_ass);
1263 if (not ok) {
1264 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001265 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001266 }
1267
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001268 /* Make sure we've got an Uplink TBF assignment */
1269 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001270
1271 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1272 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1273 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
1274 bsn := 0, /* TODO: what should be here? */
1275 blocks := { /* To be generated in loop */ });
1276
1277 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1278 ul_data.data.tlli := '00000001'O;
1279
1280 /* 16 UL blocks */
1281 for (var integer i := 0; i < 16; i := i + 1) {
1282 /* Prepare a new UL block (CV, random payload) */
1283 ul_data.data.mac_hdr.countdown := (15 - i);
1284 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1285
1286 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1287 f_tx_rlcmac_ul_block(ul_data, 40*10); /* 40 dB */
1288
1289 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1290 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1291
1292 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1293 }
1294
1295 if (last_ch_coding != CH_CODING_CS3) {
1296 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001297 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001298
1299 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001300}
1301
1302/* Verify PCU drops TBF after some time of inactivity. */
1303testcase TC_t3169() runs on RAW_PCU_Test_CT {
1304 var PCUIF_info_ind info_ind;
1305 var GsmRrMessage rr_imm_ass;
1306 var PacketUlAssign ul_tbf_ass;
1307 var RlcmacDlBlock dl_block;
1308 var PCUIF_Message pcu_msg;
1309 var octetstring data;
1310 var boolean ok;
1311 var uint32_t unused_fn;
1312 var OCT4 tlli := '00000001'O;
1313
1314 /* Initialize NS/BSSGP side */
1315 f_init_bssgp();
1316
1317 info_ind := valueof(ts_PCUIF_INFO_default);
1318 /* Set timer to 1 sec (default 5) to speedup test: */
1319 info_ind.t3169 := 1;
1320
1321 /* Initialize the PCU interface abstraction */
1322 f_init_raw(testcasename(), info_ind);
1323
1324 /* Establish BSSGP connection to the PCU */
1325 f_bssgp_establish();
1326 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1327
1328 /* Establish an Uplink TBF */
1329 ok := f_establish_tbf(rr_imm_ass);
1330 if (not ok) {
1331 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001332 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001333 }
1334
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001335 /* Make sure we've got an Uplink TBF assignment */
1336 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001337
Pau Espin Pedrol4aac3d02020-05-13 15:13:49 +02001338 /* Send one UL block (with TLLI since we are in One-Phase Access
1339 contention resoultion) and make sure it is ACKED fine */
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001340 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass.dynamic.tfi_assignment, 1, tlli);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001341 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1342 /* UL block should be received in SGSN */
1343 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1344
1345 /* Wait until T3169 fires (plus 1 extra sec to make sure) */
1346 f_sleep(int2float(info_ind.t3169) + 1.0);
1347
1348 /* Send an UL block once again, the TBF should be gone by now so no ACK */
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001349 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass.dynamic.tfi_assignment, 1);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001350 f_rx_rlcmac_dl_block_exp_dummy(dl_block);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001351
1352 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001353}
1354
1355/* Verify that a Downlink TBF can be assigned using PACCH shortly after the
1356 * release of prev DL TBF due to MS staying in PDCH for a while (T3192, in PCU
1357 * T3193) after DL TBF release */
1358testcase TC_t3193() runs on RAW_PCU_Test_CT {
1359 var GsmRrMessage rr_imm_ass;
1360 var PacketDlAssign dl_tbf_ass;
1361 var RlcmacDlBlock dl_block;
1362 var octetstring data := f_rnd_octstring(10);
1363 var boolean ok;
1364 var uint32_t sched_fn;
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001365 var uint32_t dl_fn;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001366 var OCT4 tlli := '00000001'O;
1367 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1368
1369 /* Initialize NS/BSSGP side */
1370 f_init_bssgp();
1371
1372 /* Initialize the PCU interface abstraction */
1373 f_init_raw(testcasename());
1374
1375 /* Establish BSSGP connection to the PCU */
1376 f_bssgp_establish();
1377 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1378
1379 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1380 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1381 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001382
1383 /* Make sure we've got a Downlink TBF assignment */
1384 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1385
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001386 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1387 f_sleep(X2002);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001388 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001389
1390 /* ACK the DL block */
1391 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001392 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1393 0, f_dl_block_ack_fn(dl_block, dl_fn));
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001394 /* we are done with the DL-TBF here so far, let's clean up our local state: */
1395 ack_nack_desc := valueof(t_AckNackDescription_init)
1396
1397 /* Now that final DL block is ACKED and TBF is released, T3193 in PCU
1398 (T3192 in MS) was started and until it fires the MS will be abailable
1399 on PDCH in case new data arrives from SGSN. Let's verify it: */
1400 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1401 f_rx_rlcmac_dl_block_exp_pkt_ass(dl_block, sched_fn);
1402 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1403
1404 /* 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 +07001405 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001406 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001407 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1408 0, f_dl_block_ack_fn(dl_block, dl_fn));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001409
1410 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001411}
1412
1413/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1414 * answered, so TBFs for uplink and later for downlink are created.
1415 */
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001416private 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 +02001417 var GsmRrMessage rr_imm_ass;
1418 var PacketUlAssign ul_tbf_ass;
1419 var PacketDlAssign dl_tbf_ass;
1420 var RlcmacDlBlock dl_block;
1421 var PCUIF_Message pcu_msg;
1422 var octetstring data := f_rnd_octstring(10);
1423 var boolean ok;
1424 var uint32_t sched_fn;
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001425 var uint32_t dl_fn;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001426 var OCT4 tlli := '00000001'O;
1427 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1428
1429 /* Initialize NS/BSSGP side */
1430 f_init_bssgp();
1431
1432 /* Initialize the PCU interface abstraction */
1433 f_init_raw(testcasename());
1434
1435 /* Establish BSSGP connection to the PCU */
1436 f_bssgp_establish();
1437 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1438
1439 /* Establish an Uplink TBF */
1440 ok := f_establish_tbf(rr_imm_ass);
1441 if (not ok) {
1442 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001443 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001444 }
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001445
1446 /* Make sure we've got an Uplink TBF assignment */
1447 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001448
Pau Espin Pedrol4aac3d02020-05-13 15:13:49 +02001449 /* Send one UL block (with TLLI since we are in One-Phase Access
1450 contention resoultion) and make sure it is ACKED fine */
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001451 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass.dynamic.tfi_assignment, 1, tlli);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001452 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1453 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1454 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1455
1456 /* UL block should be received in SGSN */
1457 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1458
1459 /* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
1460 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1461 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1462
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001463 /* Make sure we've got a Downlink TBF assignment */
1464 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001465
1466 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1467 f_sleep(X2002);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001468 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0, exp_cs_mcs);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001469
1470 /* ACK the DL block */
1471 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001472 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1473 0, f_dl_block_ack_fn(dl_block, dl_fn));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001474
1475 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001476}
1477
1478/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1479 * answered, so TBFs for uplink and later for downlink are created.
1480 */
1481testcase TC_mo_ping_pong() runs on RAW_PCU_Test_CT {
1482 var CodingScheme exp_cs_mcs := CS_1;
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001483 f_TC_mo_ping_pong_1phase_access(exp_cs_mcs);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001484}
1485
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001486/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1487 * answered, so TBFs for uplink and later for downlink are created.
1488 */
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +02001489private function f_TC_mo_ping_pong_2phase_access(template (value) MSRadioAccessCapabilityV ms_racap,
1490 template (present) CodingScheme exp_ul_cs_mcs := ?,
1491 template (present) CodingScheme exp_dl_cs_mcs := ?)
1492runs on RAW_PCU_Test_CT {
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001493 var GsmRrMessage rr_imm_ass;
1494 var PacketUlAssign ul_tbf_ass;
1495 var PacketDlAssign dl_tbf_ass;
1496 var RlcmacDlBlock dl_block;
1497 var PCUIF_Message pcu_msg;
1498 var octetstring data := f_rnd_octstring(10);
1499 var boolean ok;
1500 var uint32_t sched_fn;
1501 var uint32_t dl_fn;
1502 var OCT4 tlli := '00000001'O;
1503 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +02001504 var CodingScheme cs_mcs;
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001505 /* 0111 0xxx: Single block packet access; one block period on a PDCH is needed for two phase packet access or other RR signalling purpose. */
1506 var uint16_t ra := oct2int('70'O);
Pau Espin Pedrol0c0bf872020-05-14 15:50:49 +02001507 if (g_force_two_phase_access) {
1508 /* If 2phase access is enforced by the network, then let's
1509 request a One phase packet access, we'll receive a single block
1510 anyway */
1511 ra := bit2int(chan_req_def);
1512 }
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001513
1514 /* Initialize NS/BSSGP side */
1515 f_init_bssgp();
1516
1517 /* Initialize the PCU interface abstraction */
1518 f_init_raw(testcasename());
1519
1520 /* Establish BSSGP connection to the PCU */
1521 f_bssgp_establish();
1522 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1523
1524 /* Establish an Uplink TBF */
1525 ok := f_establish_tbf(rr_imm_ass, ra := ra);
1526 if (not ok) {
1527 setverdict(fail, "Failed to establish TBF");
1528 f_shutdown(__BFILE__, __LINE__);
1529 }
1530
1531 /* Make sure we've got an Uplink TBF assignment */
1532 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass, tr_PacketUlSglAssign);
1533
1534 /* Send PACKET RESOURCE REQUEST to upgrade to EGPRS
1535 * (see 3GPP TS 04.60 "7.1.3.1 Initiation of the Packet resource request procedure")
1536 */
1537 f_tx_rlcmac_ul_block(ts_RLC_UL_CTRL_ACK(valueof(ts_RlcMacUlCtrl_PKT_RES_REQ(tlli, ms_racap))), 0);
1538 f_rx_rlcmac_dl_block_exp_pkt_ul_ass(dl_block, sched_fn);
1539 if (dl_block.ctrl.payload.u.ul_assignment.identity.tlli.tlli != tlli) {
1540 setverdict(fail, "Wrong TLLI ", dl_block.ctrl.payload.u.ul_assignment.identity.tlli, " received vs exp ", tlli);
1541 f_shutdown(__BFILE__, __LINE__);
1542 }
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +02001543 cs_mcs := f_rlcmac_dl_block_get_assigned_ul_cs_mcs(dl_block);
1544 if (not match(cs_mcs, exp_ul_cs_mcs)) {
1545 setverdict(fail, "Wrong CS_MCS ", cs_mcs, " received vs exp ", exp_ul_cs_mcs);
1546 f_shutdown(__BFILE__, __LINE__);
1547 }
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001548
1549 /* Send one UL block (without TLLI since we are in Second-Phase Access)
1550 and make sure it is ACKED fine */
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +02001551 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 +02001552
1553 //f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1554 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1555 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1556
1557 /* UL block should be received in SGSN */
1558 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1559
1560 /* Now SGSN sends some DL data, PCU will page on PACCH */
1561 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1562 f_rx_rlcmac_dl_block_exp_pkt_dl_ass(dl_block, sched_fn);
1563 /* DL Ass sets poll+rrbp requesting PACKET CONTROL ACK */
1564 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1565
1566 /* 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 +02001567 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 +02001568
1569 /* ACK the DL block */
1570 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
1571 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1572 0, f_dl_block_ack_fn(dl_block, dl_fn));
1573
1574 f_shutdown(__BFILE__, __LINE__, final := true);
1575}
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001576
1577testcase TC_mo_ping_pong_with_ul_racap() runs on RAW_PCU_Test_CT {
1578 var MultislotCap_GPRS mscap_gprs := {
1579 gprsmultislotclass := '00011'B,
1580 gprsextendeddynalloccap := '0'B
1581 };
1582 var MSRadioAccessCapabilityV ms_racap := { valueof(ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs, omit)) };
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +02001583 var CodingScheme exp_ul_cs_mcs := f_rlcmac_block_int2cs_mcs(g_mcs_initial_ul, false);
1584 var CodingScheme exp_dl_cs_mcs := CS_2;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001585
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +02001586 f_TC_mo_ping_pong_2phase_access(ms_racap, exp_ul_cs_mcs, exp_dl_cs_mcs);
1587}
1588
1589testcase TC_mo_ping_pong_with_ul_racap_egprs_only() runs on RAW_PCU_Test_CT {
1590 /* Initialize the PCU interface abstraction with EGPRS-only */
1591 g_egprs_only := true;
1592
1593 var MultislotCap_GPRS mscap_gprs := {
1594 gprsmultislotclass := '00011'B,
1595 gprsextendeddynalloccap := '0'B
1596 };
1597 var MultislotCap_EGPRS mscap_egprs := {
1598 egprsmultislotclass := '00011'B,
1599 egprsextendeddynalloccap := '0'B
1600 };
1601 var MSRadioAccessCapabilityV ms_racap := { valueof(ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs, mscap_egprs)) };
1602 var CodingScheme exp_ul_cs_mcs := f_rlcmac_block_int2cs_mcs(g_mcs_initial_ul, true);
1603 var CodingScheme exp_dl_cs_mcs := MCS_1;
1604
1605 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 +02001606}
1607
Pau Espin Pedrol0c0bf872020-05-14 15:50:49 +02001608testcase TC_force_two_phase_access() runs on RAW_PCU_Test_CT {
1609 /* Configure PCU to force two phase access */
1610 g_force_two_phase_access := true;
1611
1612 var MultislotCap_GPRS mscap_gprs := {
1613 gprsmultislotclass := '00011'B,
1614 gprsextendeddynalloccap := '0'B
1615 };
1616 var MSRadioAccessCapabilityV ms_racap := { valueof(ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs, omit)) };
1617 var CodingScheme exp_ul_cs_mcs := f_rlcmac_block_int2cs_mcs(g_mcs_initial_ul, false);
1618 var CodingScheme exp_dl_cs_mcs := CS_2;
1619
1620 f_TC_mo_ping_pong_2phase_access(ms_racap, exp_ul_cs_mcs, exp_dl_cs_mcs);
1621}
1622
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001623/* Test scenario where SGSN wants to send some data against MS and it is
1624 * answered by the MS on PDCH, so TBFs for downlink and later for uplink are created.
1625 */
1626private 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 {
1627 var GsmRrMessage rr_imm_ass;
1628 var PacketUlAssign ul_tbf_ass;
1629 var PacketDlAssign dl_tbf_ass;
1630 var RlcmacDlBlock dl_block;
1631 var PCUIF_Message pcu_msg;
1632 var octetstring data := f_rnd_octstring(10);
1633 var boolean ok;
1634 var uint32_t sched_fn;
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001635 var uint32_t dl_fn;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001636 var OCT4 tlli := '00000001'O;
1637 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1638
1639 /* Initialize NS/BSSGP side */
1640 f_init_bssgp();
1641
1642 /* Initialize the PCU interface abstraction */
1643 f_init_raw(testcasename());
1644
1645 /* Establish BSSGP connection to the PCU */
1646 f_bssgp_establish();
1647 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1648
1649 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1650 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data, ms_racap));
1651 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1652
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001653 /* Make sure we've got a Downlink TBF assignment */
1654 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001655
1656 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1657 f_sleep(X2002);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001658 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0, exp_cs_mcs);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001659
1660 /* ACK the DL block */
1661 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001662 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1663 0, f_dl_block_ack_fn(dl_block, dl_fn));
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001664
1665 /* Now MS wants to answer the DL data, Establish an Uplink TBF */
1666 ok := f_establish_tbf(rr_imm_ass);
1667 if (not ok) {
1668 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001669 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001670 }
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001671
1672 /* Make sure we've got an Uplink TBF assignment */
1673 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001674
Pau Espin Pedrol4aac3d02020-05-13 15:13:49 +02001675 /* Send one UL block (with TLLI since we are in One-Phase Access
1676 contention resoultion) and make sure it is ACKED fine */
Pau Espin Pedrol02c972d2020-05-13 15:56:16 +02001677 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass.dynamic.tfi_assignment, 1, tlli);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001678 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1679 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1680 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1681
1682 /* UL block should be received in SGSN */
1683 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001684
1685 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001686}
1687
1688testcase TC_mt_ping_pong() runs on RAW_PCU_Test_CT {
1689 var CodingScheme exp_cs_mcs := CS_1;
1690 f_TC_mt_ping_pong(omit, exp_cs_mcs);
1691}
1692
1693/* TC_mt_ping_pong, but DL-UNITDATA contains RA Access capability with (M)CS
1694/* information about the MS */
1695testcase TC_mt_ping_pong_with_dl_racap() runs on RAW_PCU_Test_CT {
1696 var MultislotCap_GPRS_BSSGP mscap_gprs := {
1697 gprsmultislotclass := '00011'B,
1698 gprsextendeddynalloccap := '0'B
1699 } ;
1700 var MSRadioAccessCapabilityV_BSSGP ms_racap := { valueof(ts_RaCapRec_BSSGP('0001'B /* E-GSM */, mscap_gprs, omit)) };
1701 var CodingScheme exp_cs_mcs := CS_2;
1702 f_TC_mt_ping_pong(ms_racap, exp_cs_mcs);
1703}
1704
1705/* Verify that if PCU doesn't get an ACK for first DL block after IMM ASS, it
1706 * will retry by retransmitting both the IMM ASS + DL block after poll (ack)
1707 * timeout occurs (specified by sent RRBP on DL block). */
1708testcase TC_imm_ass_dl_block_retrans() runs on RAW_PCU_Test_CT {
1709 var GsmRrMessage rr_imm_ass;
1710 var PacketDlAssign dl_tbf_ass;
1711 var RlcmacDlBlock dl_block;
1712 var octetstring data := f_rnd_octstring(10);
1713 var boolean ok;
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001714 var uint32_t dl_fn;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001715 var OCT4 tlli := '00000001'O;
1716 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1717
1718 /* Initialize NS/BSSGP side */
1719 f_init_bssgp();
1720
1721 /* Initialize the PCU interface abstraction */
1722 f_init_raw(testcasename());
1723
1724 /* Establish BSSGP connection to the PCU */
1725 f_bssgp_establish();
1726 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1727
1728 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1729 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1730 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001731
1732 /* Make sure we've got a Downlink TBF assignment */
1733 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001734
1735 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1736 f_sleep(X2002);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001737 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001738
1739 /* Now we don't ack the dl block (emulate MS failed receiveing IMM ASS
1740 * or GPRS DL, or DL ACK was lost for some reason). As a result, PCU
1741 * should retrigger IMM ASS + GPRS DL procedure after poll timeout. */
1742 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001743
1744 /* Make sure we've got a Downlink TBF assignment */
1745 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1746
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001747 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1748 f_sleep(X2002);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001749 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001750
1751 /* ACK the DL block */
1752 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001753 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1754 0, f_dl_block_ack_fn(dl_block, dl_fn));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001755
1756 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001757}
1758
Vadim Yanitskiy71238c12020-05-11 03:48:06 +07001759/* Verify scheduling of multiple Downlink data blocks during one RRBP. */
1760testcase TC_dl_flow_more_blocks() runs on RAW_PCU_Test_CT {
1761 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1762 var octetstring data := f_rnd_octstring(16);
1763 var OCT4 tlli := f_rnd_octstring(4);
1764 var PacketDlAssign dl_tbf_ass;
1765 var GsmRrMessage rr_imm_ass;
1766 var RlcmacDlBlock dl_block;
1767 var uint32_t ack_fn;
1768 var uint32_t fn;
1769 timer T := 5.0;
1770
1771 /* Initialize NS/BSSGP side */
1772 f_init_bssgp();
1773
1774 /* Initialize the PCU interface abstraction */
1775 f_init_raw(testcasename());
1776
1777 /* Establish BSSGP connection to the PCU */
1778 f_bssgp_establish();
1779 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1780
1781 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1782 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1783 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1784
1785 /* Make sure we've got a Downlink TBF assignment with DL TFI */
1786 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1787 if (not ispresent(dl_tbf_ass.group1)) {
1788 setverdict(fail, "Immediate Assignment contains no DL TFI");
1789 f_shutdown(__BFILE__, __LINE__);
1790 }
1791
1792 /* Get DL TFI from received Downlink TBF assignment */
1793 var uint5_t tfi := dl_tbf_ass.group1.tfi_assignment;
1794
1795 /* Wait timer X2002 and DL block is available after CCCH IMM ASS */
1796 f_sleep(X2002);
1797
1798 /* Expect the first (GPRS DL) block with bsn=0 and rrbp_valid=1 */
1799 f_rx_rlcmac_dl_block_exp_data(dl_block, fn, data, 0);
1800 f_acknackdesc_ack_block(ack_nack_desc, dl_block);
1801
1802 /* TDMA frame number on which we are supposed to send the ACK */
1803 ack_fn := f_dl_block_ack_fn(dl_block, fn);
1804
1805 /* SGSN sends more blocks during the indicated RRBP */
1806 for (var integer bsn := 1; bsn < 63; bsn := bsn + 1) {
1807 data := f_rnd_octstring(16); /* Random LLC data */
1808 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1809
1810 f_rx_rlcmac_dl_block_exp_data(dl_block, fn, data, bsn);
1811
1812 /* Make sure this block has the same TFI as was assigned
1813 * FIXME: this is only valid for GPRS, not EGPRS. */
1814 if (dl_block.data.mac_hdr.hdr_ext.tfi != tfi) {
1815 setverdict(fail, "Rx DL data block with unexpected TFI: ",
1816 dl_block.data.mac_hdr.hdr_ext.tfi);
1817 f_shutdown(__BFILE__, __LINE__);
1818 }
1819
1820 /* Keep Ack/Nack description updated */
1821 f_acknackdesc_ack_block(ack_nack_desc, dl_block);
1822
1823 /* Break if this is the end of RRBP */
1824 if (fn == ack_fn) {
1825 ack_nack_desc.final_ack := '1'B;
1826 break;
1827 }
1828 }
1829
1830 /* This is the end of RRBP, send Packet Downlink Ack/Nack */
1831 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(tfi, ack_nack_desc), fn := fn);
1832
1833 /* Make sure that the next block (after the Ack) is dummy */
1834 f_rx_rlcmac_dl_block_exp_dummy(dl_block);
1835
1836 f_shutdown(__BFILE__, __LINE__, final := true);
1837}
1838
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001839private function f_pkt_paging_match_imsi(in PacketPagingReq req, hexstring imsi)
1840runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001841 var MobileIdentityLV_Paging mi_lv := req.repeated_pageinfo.cs.mobile_identity;
1842 var MobileIdentityV mi := dec_MobileIdentityV(mi_lv.mobile_id);
1843
1844 if (mi_lv.len != 8) { /* 8 octets: type of ID (3 bits) + even/odd flag (1 bit) + 15 BCD-encoded digits (60 bits) */
1845 setverdict(fail, "Mobile Identity length mismatch: ",
1846 "expected: 8, got: ", mi_lv.len);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001847 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001848 }
1849
1850 /* Make sure MI contains IMSI before referencing it */
1851 if (mi.typeOfIdentity != '001'B) {
1852 setverdict(fail, "Mobile Identity must be of type IMSI ('001'B), ",
1853 "got: ", mi.typeOfIdentity);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001854 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001855 } else if (mi.oddEvenInd_identity.imsi.digits != imsi) {
1856 setverdict(fail, "Mobile Identity contains unexpected IMSI, ",
1857 "expected: ", imsi, " got: ", mi.oddEvenInd_identity.imsi.digits);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001858 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001859 }
1860}
1861
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001862private function f_pkt_paging_match_tmsi(in PacketPagingReq req, template GsmTmsi tmsi)
1863runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001864 if (not match(req.repeated_pageinfo.cs.tmsi, tmsi)) {
1865 setverdict(fail, "Mobile Identity (TMSI/P-TMSI) mismatch: ",
1866 "expected: ", tmsi, "got: ", req.repeated_pageinfo.cs.tmsi);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001867 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001868 }
1869}
1870
1871/* Test CS paging over the BTS<->PCU socket.
1872 * 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.
1873 * Paging should be send on the PACCH.
1874 *
1875 * 1. Send a Paging Request over PCU socket.
1876 * 2. Send a Ready-To-Send message over PCU socket
1877 * 3. Expect a Paging Frame
1878 */
1879testcase TC_paging_cs_from_bts() runs on RAW_PCU_Test_CT {
1880 var GsmRrMessage rr_imm_ass;
1881 var PacketUlAssign ul_tbf_ass;
1882 var RlcmacDlBlock dl_block;
1883 var boolean ok;
1884 var OCT4 tlli := '00000001'O;
1885 var MobileIdentityLV mi;
1886 var octetstring mi_enc_lv;
1887 var hexstring imsi := f_gen_imsi(42);
1888
1889 /* Initialize NS/BSSGP side */
1890 f_init_bssgp();
1891
1892 /* Initialize the PCU interface abstraction */
1893 f_init_raw(testcasename());
1894
1895 /* Establish BSSGP connection to the PCU */
1896 f_bssgp_establish();
1897 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1898
1899 /* Establish an Uplink TBF */
1900 ok := f_establish_tbf(rr_imm_ass);
1901 if (not ok) {
1902 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001903 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001904 }
1905
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001906 /* Make sure we've got an Uplink TBF assignment */
1907 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001908
1909 /* build mobile Identity */
1910 mi := valueof(ts_MI_IMSI_LV(imsi));
1911 mi_enc_lv := enc_MobileIdentityLV(mi);
1912 /* Send paging request */
1913 BTS.send(ts_PCUIF_PAG_REQ(bts_nr := 0, id_lv := mi_enc_lv, chan_needed := 0,
1914 sapi :=PCU_IF_SAPI_PDTCH));
1915
1916 /* Receive it on BTS side towards MS */
1917 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
1918
1919 /* Make sure that Packet Paging Request contains the same IMSI */
1920 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1921
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001922 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001923}
1924
1925/* Test CS paging over Gb (SGSN->PCU->BTS[PDCH]).
1926 */
1927private function f_tc_paging_cs_from_sgsn(Nsvci bvci, boolean use_ptmsi := false)
1928runs on RAW_PCU_Test_CT {
1929 var GsmRrMessage rr_imm_ass;
1930 var PacketUlAssign ul_tbf_ass;
1931 var RlcmacDlBlock dl_block;
1932 var boolean ok;
1933 var OCT4 tlli := '00000001'O;
1934 var hexstring imsi := f_gen_imsi(42);
1935 var GsmTmsi tmsi;
1936
1937 /* Initialize NS/BSSGP side */
1938 f_init_bssgp();
1939
1940 /* Initialize the PCU interface abstraction */
1941 f_init_raw(testcasename());
1942
1943 /* Establish BSSGP connection to the PCU */
1944 f_bssgp_establish();
1945 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1946
1947 /* Establish an Uplink TBF */
1948 ok := f_establish_tbf(rr_imm_ass);
1949 if (not ok) {
1950 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001951 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001952 }
1953
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001954 /* Make sure we've got an Uplink TBF assignment */
1955 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001956
1957 /* Send paging request with or without TMSI */
1958 if (use_ptmsi) {
1959 tmsi := oct2int(f_rnd_octstring(4)); /* Random P-TMSI */
1960 BSSGP[0].send(ts_BSSGP_CS_PAGING_PTMSI(bvci, imsi, tmsi));
1961 } else {
1962 BSSGP[0].send(ts_BSSGP_CS_PAGING_IMSI(bvci, imsi));
1963 }
1964
1965 /* Receive it on BTS side towards MS */
1966 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
1967
1968 /* Make sure that Packet Paging Request contains the same P-TMSI/IMSI */
1969 if (use_ptmsi) {
1970 f_pkt_paging_match_tmsi(dl_block.ctrl.payload.u.paging, tmsi);
1971 } else {
1972 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1973 }
1974
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001975 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001976}
1977
1978testcase TC_paging_cs_from_sgsn_sign_ptmsi() runs on RAW_PCU_Test_CT {
1979 f_tc_paging_cs_from_sgsn(0, true);
1980}
1981
1982testcase TC_paging_cs_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1983 f_tc_paging_cs_from_sgsn(0);
1984}
1985
1986testcase TC_paging_cs_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1987 f_tc_paging_cs_from_sgsn(mp_gb_cfg.bvci);
1988}
1989
1990/* Test PS paging over Gb (SGSN->PCU->BTS[CCCH]).
1991 */
1992private function f_tc_paging_ps_from_sgsn(Nsvci bvci, boolean use_ptmsi := false)
1993runs on RAW_PCU_Test_CT {
1994 var OCT4 tlli := '00000001'O;
1995 var integer imsi_suff_tx := 423;
1996 var hexstring imsi := f_gen_imsi(imsi_suff_tx);
1997
1998 /* Initialize NS/BSSGP side */
1999 f_init_bssgp();
2000
2001 /* Initialize the PCU interface abstraction */
2002 f_init_raw(testcasename());
2003
2004 /* Establish BSSGP connection to the PCU */
2005 f_bssgp_establish();
2006 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
2007
2008 /* Send BSSGP PAGING-PS (with or without TMSI), wait for RR Paging Request Type 1.
2009 * Make sure that both paging group (IMSI suffix) and Mobile Identity match. */
2010 if (use_ptmsi) {
2011 var OCT4 tmsi := f_rnd_octstring(4); /* Random P-TMSI */
2012 BSSGP[0].send(ts_BSSGP_PS_PAGING_PTMSI(bvci, imsi, oct2int(tmsi)));
2013 f_pcuif_rx_pch_pag_req1(t_MI_TMSI(tmsi), imsi_suff_tx);
2014 } else {
2015 BSSGP[0].send(ts_BSSGP_PS_PAGING_IMSI(bvci, imsi));
2016 f_pcuif_rx_pch_pag_req1(tr_MI_IMSI(imsi), imsi_suff_tx);
2017 }
2018
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07002019 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002020}
2021
2022testcase TC_paging_ps_from_sgsn_sign_ptmsi() runs on RAW_PCU_Test_CT {
2023 f_tc_paging_ps_from_sgsn(0, true);
2024}
2025
2026testcase TC_paging_ps_from_sgsn_sign() runs on RAW_PCU_Test_CT {
2027 f_tc_paging_ps_from_sgsn(0);
2028}
2029
2030testcase TC_paging_ps_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
2031 f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvci);
2032}
2033
2034private function f_TC_egprs_pkt_chan_req(in EGPRSPktChRequest req,
2035 template GsmRrMessage t_imm_ass := ?,
2036 PCUIF_BurstType bt := BURST_TYPE_1)
2037runs on RAW_PCU_Test_CT {
2038 var GsmRrMessage rr_msg;
2039 var uint16_t ra11;
2040 var boolean ok;
2041
2042 ra11 := enc_EGPRSPktChRequest2uint(req);
2043 log("Sending EGPRS Packet Channel Request (", ra11, "): ", req);
2044
2045 ok := f_establish_tbf(rr_msg, ra := ra11, is_11bit := 1, burst_type := bt);
2046 if (not ok) {
2047 setverdict(fail, "Failed to establush an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07002048 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002049 }
2050
2051 if (not match(rr_msg, t_imm_ass)) {
2052 setverdict(fail, "Immediate Assignment does not match");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07002053 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002054 }
2055
2056 setverdict(pass);
2057}
2058
2059testcase TC_egprs_pkt_chan_req_signalling() 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 signalling := { tag := '110011'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 req.signalling.random_bits := ext_ra;
2075
2076 /* For signalling, do we expect Multiblock UL TBF Assignment? */
2077 ul_ass := tr_EgprsUlAssMultiblock(ext_ra := ext_ra);
2078 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
2079 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
2080
2081 f_TC_egprs_pkt_chan_req(req, imm_ass);
2082 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07002083
2084 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002085}
2086
2087testcase TC_egprs_pkt_chan_req_one_phase() runs on RAW_PCU_Test_CT {
2088 var template GsmRrMessage imm_ass;
2089 var template IaRestOctets rest;
2090 var template EgprsUlAss ul_ass;
2091
2092 /* Initialize the PCU interface abstraction */
2093 f_init_raw(testcasename());
2094
2095 var EGPRSPktChRequest req := {
2096 /* NOTE: other fields are set in the loop */
2097 one_phase := { tag := '0'B }
2098 };
2099
2100 for (var integer i := 0; i < 6; i := i + 1) {
2101 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
2102 var BIT5 mslot_class := int2bit(f_rnd_int(32), 5);
2103 var BIT2 priority := substr(ext_ra, 0, 2);
2104 var BIT3 rand := substr(ext_ra, 2, 3);
2105
2106 req.one_phase.multislot_class := mslot_class;
2107 req.one_phase.priority := priority;
2108 req.one_phase.random_bits := rand;
2109
2110 /* For one phase access, do we expect Dynamic UL TBF Assignment? */
2111 ul_ass := tr_EgprsUlAssDynamic(ext_ra := ext_ra);
2112 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
2113 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
2114
2115 f_TC_egprs_pkt_chan_req(req, imm_ass);
2116 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07002117
2118 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002119}
2120
2121testcase TC_egprs_pkt_chan_req_two_phase() runs on RAW_PCU_Test_CT {
2122 var template GsmRrMessage imm_ass;
2123 var template IaRestOctets rest;
2124 var template EgprsUlAss ul_ass;
2125
2126 /* Initialize the PCU interface abstraction */
2127 f_init_raw(testcasename());
2128
2129 var EGPRSPktChRequest req := {
2130 /* NOTE: other fields are set in the loop */
2131 two_phase := { tag := '110000'B }
2132 };
2133
2134 for (var integer i := 0; i < 6; i := i + 1) {
2135 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
2136 var BIT2 priority := substr(ext_ra, 0, 2);
2137 var BIT3 rand := substr(ext_ra, 2, 3);
2138
2139 req.two_phase.priority := priority;
2140 req.two_phase.random_bits := rand;
2141
2142 /* For two phase access, do we expect Multiblock UL TBF Assignment? */
2143 ul_ass := tr_EgprsUlAssMultiblock(ext_ra := ext_ra);
2144 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
2145 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
2146
2147 f_TC_egprs_pkt_chan_req(req, imm_ass);
2148 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07002149
2150 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002151}
2152
2153control {
2154 execute( TC_pcuif_suspend() );
2155 execute( TC_ta_ptcch_idle() );
2156 execute( TC_ta_rach_imm_ass() );
2157 execute( TC_ta_idle_dl_tbf_ass() );
2158 execute( TC_ta_ptcch_ul_multi_tbf() );
2159 execute( TC_cs_lqual_ul_tbf() );
2160 execute( TC_cs_initial_ul() );
2161 execute( TC_cs_max_ul() );
2162 execute( TC_t3169() );
2163 execute( TC_t3193() );
2164 execute( TC_mo_ping_pong() );
2165 execute( TC_mo_ping_pong_with_ul_racap() );
Pau Espin Pedrol0c0bf872020-05-14 15:50:49 +02002166 execute( TC_force_two_phase_access() );
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002167 execute( TC_mt_ping_pong() );
2168 execute( TC_mt_ping_pong_with_dl_racap() );
2169 execute( TC_imm_ass_dl_block_retrans() );
Vadim Yanitskiy71238c12020-05-11 03:48:06 +07002170 execute( TC_dl_flow_more_blocks() );
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002171 execute( TC_paging_cs_from_bts() );
2172 execute( TC_paging_cs_from_sgsn_sign_ptmsi() );
2173 execute( TC_paging_cs_from_sgsn_sign() );
2174 execute( TC_paging_cs_from_sgsn_ptp() );
2175 execute( TC_paging_ps_from_sgsn_sign_ptmsi() );
2176 execute( TC_paging_ps_from_sgsn_sign() );
2177 execute( TC_paging_ps_from_sgsn_ptp() );
2178
2179 /* EGPRS specific test cases */
2180 execute( TC_egprs_pkt_chan_req_signalling() );
2181 execute( TC_egprs_pkt_chan_req_one_phase() );
2182 execute( TC_egprs_pkt_chan_req_two_phase() );
Pau Espin Pedrol42acafc2020-05-14 15:18:38 +02002183
2184 execute( TC_mo_ping_pong_with_ul_racap_egprs_only() );
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002185}
2186
2187
2188
2189
2190
2191
Harald Weltea419df22019-03-21 17:23:04 +01002192}