blob: 0a6b41030ed93ee45555d62af5c491b5650941f9 [file] [log] [blame]
Harald Weltea0895f92018-03-08 11:51:23 +01001module PCU_Tests {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02002
3/* "RAW" PCU tests: Talk directly to the PCU socket of OsmoPCU on the one hand side (emulating
4 the BTS/BSC side PCU socket server) and the Gb interface on the other hand side. No NS/BSSGP
5 Emulation is used; rather, we simply use the NS_CodecPort to implement both standard and non-
6 standard procedures on the NS and BSSGP level. The goal of these tests is to test exactly
7 those NS and BSSGP implementations on the BSS (PCU) side. */
8
9/* (C) 2018-2019 Harald Welte <laforge@gnumonks.org>
10 * (C) 2019 Vadim Yanitskiy <axilirator@gmail.com>
11 * All rights reserved.
12 *
13 * Released under the terms of GNU General Public License, Version 2 or
14 * (at your option) any later version.
15 *
16 * SPDX-License-Identifier: GPL-2.0-or-later
17 */
18
19friend module PCU_Tests_NS;
20
21import from General_Types all;
22import from Osmocom_Types all;
23import from GSM_Types all;
24import from GSM_RR_Types all;
25
26import from Osmocom_VTY_Functions all;
27import from TELNETasp_PortType all;
28
29import from MobileL3_GMM_SM_Types all;
30import from RLCMAC_CSN1_Types all;
Pau Espin Pedrole8d7d162020-04-29 19:07:36 +020031import from RLCMAC_CSN1_Templates all;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +020032import from RLCMAC_Types all;
Pau Espin Pedrole8d7d162020-04-29 19:07:36 +020033import from RLCMAC_Templates all;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +020034
35import from MobileL3_CommonIE_Types all;
36import from L3_Templates all;
37
38import from NS_Types all;
39import from BSSGP_Types all;
40import from Osmocom_Gb_Types all;
41
42import from BSSGP_Emulation all; /* BssgpConfig */
43import from NS_Emulation all; /* NSConfiguration */
44
45import from UD_Types all;
46import from PCUIF_Types all;
47import from PCUIF_CodecPort all;
48import from PCUIF_Components all;
49import from IPL4asp_Types all;
50import from Native_Functions all;
51import from SGSN_Components all;
52
53modulepar {
54 charstring mp_pcu_sock_path := PCU_SOCK_DEFAULT;
55
56 float X2002 := 0.2; /* Timer -2002, IMM ASSIGN confirm delay */
57}
58
59
60/* FIXME: make sure to use parameters from mp_gb_cfg.cell_id in the PCU INFO IND */
61private template (value) PCUIF_info_ind ts_PCUIF_INFO_default := {
62 version := PCU_IF_VERSION,
63 flags := c_PCUIF_Flags_default,
64 trx := valueof(ts_PCUIF_InfoTrxs_def),
65 bsic := 7,
66 mcc := 262,
67 mnc := 42,
68 mnc_3_digits := 0,
69 lac := 13135,
70 rac := 0,
71 nsei := mp_nsconfig.nsei,
72 nse_timer := { 3, 3, 3, 3, 30, 3, 10 },
73 cell_timer := { 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 },
74 cell_id := 20960,
75 repeat_time := 5 * 50,
76 repeat_count := 3,
77 bvci := mp_gb_cfg.bvci,
78 t3142 := 20,
79 t3169 := 5,
80 t3191 := 5,
81 t3193_10ms := 160,
82 t3195 := 5,
83 t3101 := 10,
84 t3103 := 4,
85 t3105 := 8,
86 cv_countdown := 15,
87 dl_tbf_ext := 250 * 10, /* ms */
88 ul_tbf_ext := 250 * 10, /* ms */
89 initial_cs := 2,
90 initial_mcs := 6,
91 nsvci := { mp_nsconfig.nsvci, 0 },
92 local_pprt := { mp_nsconfig.remote_udp_port, 0 },
93 remote_port := { mp_nsconfig.local_udp_port, 0 },
94 remote_ip := { f_inet_haddr(mp_nsconfig.local_ip) , '00000000'O }
95}
96
97type record lqual_range {
98 /* component reference to the IPA_Client component used for RSL */
99 uint8_t low,
100 uint8_t high
101}
102
103type component RAW_PCU_Test_CT extends bssgp_CT {
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700104 /* PCU interface abstraction component */
105 var RAW_PCUIF_CT vc_PCUIF;
106 /* Virtual BTS component */
107 var RAW_PCU_BTS_CT vc_BTS;
108
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200109 /* Connection to the BTS component (one for now) */
110 port RAW_PCU_MSG_PT BTS;
111 /* Connection to the PCUIF component */
112 port RAW_PCU_MSG_PT PCUIF;
113 /* VTY connection to the PCU */
114 port TELNETasp_PT PCUVTY;
115
116 /* Uplink CS/MCS thresholds, default from pcu_main.c: */
117 var lqual_range g_cs_lqual_ranges[4] := {{low := 0, high := 6},
118 {low := 5, high := 8},
119 {low := 7, high := 13},
120 {low := 12,high := 35}};
121 var lqual_range g_mcs_lqual_ranges[9] := {{low := 0, high := 6},
122 {low := 5, high := 8},
123 {low := 7, high := 13},
124 {low := 12,high := 15},
125 {low := 14, high := 17},
126 {low := 16, high := 18},
127 {low := 17,high := 20},
128 {low := 19, high := 24},
129 {low := 23,high := 35}};
130 var uint8_t g_cs_initial_dl := 1;
131 var uint8_t g_cs_initial_ul := 1;
132 var uint8_t g_mcs_initial_dl := 1;
133 var uint8_t g_mcs_initial_ul := 1;
134 var uint8_t g_cs_max_dl := 4;
135 var uint8_t g_cs_max_ul := 4;
136 var uint8_t g_mcs_max_dl := 9;
137 var uint8_t g_mcs_max_ul := 9;
138
139 var boolean g_egprs_only := false;
140
141 /* Guard timeout */
142 timer g_T_guard := 60.0;
143};
144
145private altstep as_Tguard_RAW() runs on RAW_PCU_Test_CT {
146 [] g_T_guard.timeout {
147 setverdict(fail, "Timeout of T_guard");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700148 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200149 }
150}
151
152private function f_pcuvty_set_allowed_cs_mcs() runs on RAW_PCU_Test_CT {
153 f_vty_config2(PCUVTY, {"pcu"}, "cs " & int2str(g_cs_initial_dl) & " " & int2str(g_cs_initial_ul));
154 f_vty_config2(PCUVTY, {"pcu"}, "cs max " & int2str(g_cs_max_dl) & " " & int2str(g_cs_max_ul));
155
156 f_vty_config2(PCUVTY, {"pcu"}, "mcs " & int2str(g_mcs_initial_dl) & " " & int2str(g_mcs_initial_ul));
157 f_vty_config2(PCUVTY, {"pcu"}, "mcs max " & int2str(g_mcs_max_dl) & " " & int2str(g_mcs_max_ul));
158}
159
160private function f_pcuvty_set_link_quality_ranges() runs on RAW_PCU_Test_CT {
161 var charstring cmd;
162
163 cmd := "cs link-quality-ranges" &
164 " cs1 " & int2str(g_cs_lqual_ranges[0].high) &
165 " cs2 " & int2str(g_cs_lqual_ranges[1].low) & " " & int2str(g_cs_lqual_ranges[1].high) &
166 " cs3 " & int2str(g_cs_lqual_ranges[2].low) & " " & int2str(g_cs_lqual_ranges[2].high) &
167 " cs4 " & int2str(g_cs_lqual_ranges[3].low);
168 f_vty_config2(PCUVTY, {"pcu"}, cmd);
169
170 cmd := "mcs link-quality-ranges" &
171 " mcs1 " & int2str(g_mcs_lqual_ranges[0].high) &
172 " mcs2 " & int2str(g_mcs_lqual_ranges[1].low) & " " & int2str(g_mcs_lqual_ranges[1].high) &
173 " mcs3 " & int2str(g_mcs_lqual_ranges[2].low) & " " & int2str(g_mcs_lqual_ranges[2].high) &
174 " mcs4 " & int2str(g_mcs_lqual_ranges[3].low) & " " & int2str(g_mcs_lqual_ranges[3].high) &
175 " mcs5 " & int2str(g_mcs_lqual_ranges[4].low) & " " & int2str(g_mcs_lqual_ranges[4].high) &
176 " mcs6 " & int2str(g_mcs_lqual_ranges[5].low) & " " & int2str(g_mcs_lqual_ranges[5].high) &
177 " mcs7 " & int2str(g_mcs_lqual_ranges[6].low) & " " & int2str(g_mcs_lqual_ranges[6].high) &
178 " mcs8 " & int2str(g_mcs_lqual_ranges[7].low) & " " & int2str(g_mcs_lqual_ranges[7].high) &
179 " mcs9 " & int2str(g_mcs_lqual_ranges[8].low);
180 f_vty_config2(PCUVTY, {"pcu"}, cmd);
181}
182
183private function f_init_vty(charstring id) runs on RAW_PCU_Test_CT {
184 map(self:PCUVTY, system:PCUVTY);
185 f_vty_set_prompts(PCUVTY);
186 f_vty_transceive(PCUVTY, "enable");
187
188 if (g_egprs_only) {
189 f_vty_config2(PCUVTY, {"pcu"}, "egprs only");
190 } else {
191 f_vty_config2(PCUVTY, {"pcu"}, "no egprs");
192 }
193}
194
Pau Espin Pedrol2456dad2020-04-30 20:22:38 +0200195function f_init_raw(charstring id, template (value) PCUIF_info_ind info_ind := ts_PCUIF_INFO_default)
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200196runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200197 /* Start the guard timer */
198 g_T_guard.start;
199 activate(as_Tguard_RAW());
200
201 /* Init PCU interface component */
202 vc_PCUIF := RAW_PCUIF_CT.create("PCUIF-" & id);
203 connect(vc_PCUIF:MTC, self:PCUIF);
204 map(vc_PCUIF:PCU, system:PCU);
205
206 /* Create one BTS component (we may want more some day) */
207 vc_BTS := RAW_PCU_BTS_CT.create("BTS-" & id);
208 connect(vc_BTS:PCUIF, vc_PCUIF:BTS);
209 connect(vc_BTS:TC, self:BTS);
210
211 f_init_vty(id);
212
213 vc_PCUIF.start(f_PCUIF_CT_handler(mp_pcu_sock_path));
214 vc_BTS.start(f_BTS_CT_handler(0, valueof(info_ind)));
215
216 /* Wait until the BTS is ready (SI13 negotiated) */
217 BTS.receive(tr_RAW_PCU_EV(BTS_EV_SI13_NEGO));
218}
219
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700220private function f_shutdown(charstring file, integer line,
221 boolean final := false)
222runs on RAW_PCU_Test_CT {
223 /* Determine if the test case was aborted in the middle */
224 if (not final) {
225 log("Test case ", testcasename(), " aborted at ", file, ":", line);
226 } else {
227 /* Guard verdict to avoid 'none' */
228 setverdict(pass);
229 }
230
231 /* Properly shutdown virtual BTS and its clock generator */
232 BTS.send(ts_RAW_PCU_CMD(GENERAL_CMD_SHUTDOWN));
233 vc_BTS.done; /* wait untill it's done */
234
235 /* Shutdown the others and MTC */
236 all component.stop;
237 mtc.stop;
238}
239
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200240template AckNackDescription t_AckNackDescription_init := {
241 final_ack := '0'B,
242 starting_seq_nr := 0,
243 receive_block_bitmap := '0000000000000000000000000000000000000000000000000000000000000000'B
244}
245
246private function f_rlcmac_dl_block_get_tfi(RlcmacDlBlock dl_block) return uint5_t {
247 if (ischosen(dl_block.data)) {
248 return dl_block.data.mac_hdr.hdr_ext.tfi;
249 } else {
250 return dl_block.data_egprs.mac_hdr.tfi;
251 }
252}
253
254/* TS 44.060 sec 12.3 Ack/Nack Description */
255private function f_acknackdesc_ack_block(inout AckNackDescription desc, RlcmacDlBlock dl_block, BIT1 final_ack := '0'B)
256{
257 var uint7_t bsn;
258 var integer i;
259 var integer inc;
260
261 if (ischosen(dl_block.data)) {
262 bsn := dl_block.data.mac_hdr.hdr_ext.bsn;
263 } else {
264 bsn := dl_block.data_egprs.mac_hdr.bsn1;
265 }
266
267 inc := bsn - desc.starting_seq_nr + 1;
268 /* Filling hole? */
269 if (bsn < desc.starting_seq_nr) {
270 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - (desc.starting_seq_nr - bsn)] := int2bit(1, 1);
271 return;
272 }
273
274 /* SSN is increased, and so RBB values need to be moved */
275 for (i := 0; i < lengthof(desc.receive_block_bitmap) - inc; i := i+1) {
276 desc.receive_block_bitmap[i] := desc.receive_block_bitmap[i + inc];
277 }
278 for (i := lengthof(desc.receive_block_bitmap) - inc; i < lengthof(desc.receive_block_bitmap) - 1; i := i+1) {
279 desc.receive_block_bitmap[i] := int2bit(0, 1);
280 }
281 /* Now we can set current bit and update SSN */
282 desc.starting_seq_nr := bsn + 1;
283 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - 1] := int2bit(1, 1);
284
285 /* Finally update the final_ack bit as requested: */
286 desc.final_ack := final_ack;
287}
288
289/* This function can be used to send DATA.cnf in response to the IUT originated DATA.req.
290 * NOTE: it's the responsibility of caller to make sure that pcu_msg contains u.data_req. */
291private function f_pcuif_tx_data_cnf(in PCUIF_Message pcu_msg)
292runs on RAW_PCU_Test_CT {
293 var PCUIF_Message pcu_msg_cnf := {
294 msg_type := PCU_IF_MSG_DATA_CNF,
295 bts_nr := pcu_msg.bts_nr,
296 spare := pcu_msg.spare,
297 u := { data_cnf := pcu_msg.u.data_req }
298 };
299
300 /* PCU wants DATA.cnf containing basically everything that was in DATA.req,
301 * but PCU_IF_SAPI_PCH is a special case - paging group shall be excluded. */
302 if (pcu_msg.u.data_req.sapi == PCU_IF_SAPI_PCH) {
303 pcu_msg_cnf.u.data_cnf.data := substr(pcu_msg.u.data_req.data, 3,
304 pcu_msg.u.data_req.len - 3);
305 }
306
307 BTS.send(pcu_msg_cnf);
308}
309
310private function f_pcuif_rx_imm_ass(out GsmRrMessage rr_imm_ass,
311 template PCUIF_Sapi sapi := PCU_IF_SAPI_AGCH,
312 template GsmRrMessage t_imm_ass := ?,
313 uint8_t bts_nr := 0)
314runs on RAW_PCU_Test_CT return boolean {
315 var PCUIF_Message pcu_msg;
316 var octetstring data;
317 timer T;
318
319 T.start(2.0);
320 alt {
321 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
322 sapi := sapi, data := ?)) -> value pcu_msg {
323 /* On PCH the payload is prefixed with paging group (3 octets): skip it.
324 * TODO: add an additional template parameter, so we can match it. */
325 if (pcu_msg.u.data_req.sapi == PCU_IF_SAPI_PCH) {
326 data := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
327 } else {
328 data := pcu_msg.u.data_req.data;
329 }
330
331 rr_imm_ass := dec_GsmRrMessage(data);
332 if (not match(rr_imm_ass, t_imm_ass)) {
333 /* Not for us? Wait for more. */
334 repeat;
335 }
336
337 log("Rx Immediate Assignment: ", rr_imm_ass);
338 setverdict(pass);
339 return true;
340 }
341 [] BTS.receive { repeat; }
342 [] T.timeout {
343 setverdict(fail, "Timeout waiting for Immediate Assignment");
344 }
345 }
346
347 return false;
348}
349
Vadim Yanitskiyf74ae992020-05-06 16:05:51 +0700350/* One phase packet access (see 3GPP TS 44.018, table 9.1.8.1) */
351private const BIT8 chan_req_def := '01111000'B;
352
Vadim Yanitskiy85cb9912020-05-06 16:29:43 +0700353/* Establish an Uplink TBF by sending RACH.ind towards the PCU */
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200354private function f_establish_tbf(out GsmRrMessage rr_imm_ass, uint8_t bts_nr := 0,
Vadim Yanitskiyf74ae992020-05-06 16:05:51 +0700355 uint16_t ra := bit2int(chan_req_def),
356 uint8_t is_11bit := 0,
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200357 PCUIF_BurstType burst_type := BURST_TYPE_0,
358 TimingAdvance ta := 0)
359runs on RAW_PCU_Test_CT return boolean {
360 var uint32_t fn;
361
362 /* FIXME: ask the BTS component to give us the current TDMA fn */
363 fn := 1337 + ta;
364
365 /* Send RACH.ind */
366 log("Sending RACH.ind on fn=", fn, " with RA=", ra, ", TA=", ta);
367 BTS.send(ts_PCUIF_RACH_IND(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
368 ra := ra, is_11bit := is_11bit,
369 burst_type := burst_type,
370 fn := fn, arfcn := 871,
371 qta := ta * 4));
372
373 /* 3GPP TS 44.018, table 9.1.8.1, note 2b: Request Reference shall be set to 127
374 * when Immediate Assignment is triggered by EGPRS Packet Channel Request. Here
375 * we assume that 11 bit RA always contains EGPRS Packet Channel Request. */
376 if (is_11bit != 0) { ra := 127; }
377
378 /* Expect Immediate (TBF) Assignment on TS0/AGCH */
379 return f_pcuif_rx_imm_ass(rr_imm_ass, PCU_IF_SAPI_AGCH,
Vadim Yanitskiy85cb9912020-05-06 16:29:43 +0700380 tr_IMM_TBF_ASS(false, ra, fn),
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200381 bts_nr := bts_nr);
382}
383
Vadim Yanitskiy5b649cc2020-05-06 16:35:38 +0700384private function f_imm_ass_verify_ul_tbf_ass(in GsmRrMessage rr_imm_ass, out PacketUlAssign ul_tbf_ass)
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +0700385runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200386
387 /* Make sure we received an UL TBF Assignment */
388 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
389 ul_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
390 log("Rx Uplink TBF assignment: ", ul_tbf_ass);
391 setverdict(pass);
392 } else {
393 setverdict(fail, "Failed to match UL TBF Assignment");
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +0700394 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200395 }
396
397 /* Make sure we have got a TBF with Dynamic Block Allocation */
398 if (ul_tbf_ass.dynamic == omit) {
399 setverdict(fail, "Single Block Allocation is not handled by ", testcasename());
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +0700400 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200401 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200402}
403
Vadim Yanitskiy5b649cc2020-05-06 16:35:38 +0700404private 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 +0700405runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200406
407 /* Make sure we received a DL TBF Assignment */
408 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := true, rest := tr_IaRestOctets_DLAss(?)))) {
409 dl_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.dl;
410 log("Rx Downlink TBF assignment: ", dl_tbf_ass);
411 setverdict(pass);
412 } else {
413 setverdict(fail, "Failed to match DL TBF Assignment");
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +0700414 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200415 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200416}
417
418/* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
Pau Espin Pedrol2456dad2020-04-30 20:22:38 +0200419function f_pcuif_tx_data_ind(octetstring data, int16_t lqual_cb := 0, uint32_t fn := 0)
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200420runs on RAW_PCU_Test_CT {
421 var template RAW_PCU_EventParam ev_param := {tdma_fn := ? };
422 BTS.send(ts_PCUIF_DATA_IND(bts_nr := 0, trx_nr := 0, ts_nr := 7, block_nr := 0,
423 sapi := PCU_IF_SAPI_PDTCH, data := data,
424 fn := fn, arfcn := 871, lqual_cb := lqual_cb));
425 if (fn != 0) {
426 ev_param := {tdma_fn := fn };
427 }
428 BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PDTCH_BLOCK_SENT, ev_param));
429}
430
431/* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
432private function f_pcuif_rx_data_req(out PCUIF_Message pcu_msg)
433runs on RAW_PCU_Test_CT {
434 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
435 sapi := PCU_IF_SAPI_PDTCH, fn := 0,
436 arfcn := 871, block_nr := 0));
437 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
438 sapi := PCU_IF_SAPI_PDTCH)) -> value pcu_msg;
439}
440
441/* Expect an Immediate Assignment (paging) from PCU on PCUIF on specified sapi. */
442private function f_pcuif_rx_pch_imm_tbf_ass(out GsmRrMessage rr_imm_ass)
443runs on RAW_PCU_Test_CT {
444 var PCUIF_Message pcu_msg;
445 var octetstring macblock;
446 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
447 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
448 /* First 3 bytes contain paging group: */
449 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
450 rr_imm_ass := dec_GsmRrMessage(macblock);
451 if (not match(rr_imm_ass, tr_IMM_TBF_ASS())) {
452 setverdict(fail, "Failed to match Immediate Assignment: ", rr_imm_ass);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700453 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200454 }
455 f_pcuif_tx_data_cnf(pcu_msg);
456}
457
458/* Expect a Paging Request Type 1 from PCU on PCUIF on specified sapi. */
459private function f_pcuif_rx_pch_pag_req1(template MobileIdentityV mi1 := ?,
460 template integer pag_group := ?)
461runs on RAW_PCU_Test_CT return GsmRrMessage {
462 var GsmRrMessage rr_pag_req1;
463 var PCUIF_Message pcu_msg;
464 var octetstring imsi_suff_octstr;
465 var integer pag_group_rx;
466 var octetstring macblock;
467
468 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
469 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
470
471 /* First 3 bytes contain IMSI suffix to calculate paging group: */
472 imsi_suff_octstr := substr(pcu_msg.u.data_req.data, 0, 3);
473 pag_group_rx := str2int(oct2char(imsi_suff_octstr[0])) * 100 +
474 str2int(oct2char(imsi_suff_octstr[1])) * 10 +
475 str2int(oct2char(imsi_suff_octstr[2]));
476
477 /* Make sure we've got RR Paging Request Type 1 for a given MI */
478 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
479 rr_pag_req1 := dec_GsmRrMessage(macblock);
480 if (not match(rr_pag_req1, tr_PAG_REQ1(tr_MI_LV(mi1)))) {
481 setverdict(fail, "Failed to match Paging Request Type 1: ", rr_pag_req1);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700482 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200483 }
484
485 /* Make sure that received paging froup matches the expected one */
486 if (not match(pag_group_rx, pag_group)) {
487 setverdict(fail, "Paging group", pag_group_rx, " does not match expected ", pag_group);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700488 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200489 }
490
491 f_pcuif_tx_data_cnf(pcu_msg);
492 return rr_pag_req1;
493}
494
495private function f_tx_rlcmac_ul_block(template (value) RlcmacUlBlock ul_data, int16_t lqual_cb := 0, uint32_t fn := 0)
496runs on RAW_PCU_Test_CT {
497 var octetstring data;
498 /* Encode the payload of DATA.ind */
499 data := enc_RlcmacUlBlock(valueof(ul_data));
500 data := f_pad_oct(data, 23, '00'O); /* CS-1 */
501
502 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
503 f_pcuif_tx_data_ind(data, lqual_cb, fn);
504}
505
506private function f_tx_rlcmac_ul_n_blocks(PacketUlAssign ul_tbf_ass, integer num_blocks := 1)
507runs on RAW_PCU_Test_CT {
508 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
509 tfi := ul_tbf_ass.dynamic.tfi_assignment,
510 cv := num_blocks - 1, /* num UL blocks to be sent (to be overridden in loop) */
511 bsn := 0, /* TODO: what should be here? */
512 blocks := { /* To be generated in loop */ });
513
514 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
515 ul_data.data.tlli := '00000001'O;
516
517 for (var integer i := 0; i < num_blocks; i := i + 1) {
518 /* Prepare a new UL block (CV, random payload) */
519 ul_data.data.mac_hdr.countdown := (num_blocks - i - 1);
520 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
521 f_tx_rlcmac_ul_block(ul_data);
522 }
523}
524
525private function f_rx_rlcmac_dl_block(out RlcmacDlBlock dl_block, out uint32_t dl_fn, template (present) CodingScheme exp_cs_mcs := ?)
526runs on RAW_PCU_Test_CT {
527 var PCUIF_Message pcu_msg;
528 f_pcuif_rx_data_req(pcu_msg);
529 dl_block := dec_RlcmacDlBlock(pcu_msg.u.data_req.data);
530 dl_fn := pcu_msg.u.data_req.fn;
531
532 var integer len := lengthof(pcu_msg.u.data_req.data);
533 var CodingScheme cs_mcs := f_rlcmac_block_len2cs_mcs(len)
534 if (not match(f_rlcmac_block_len2cs_mcs(len), exp_cs_mcs)) {
535 setverdict(fail, "Failed to match Coding Scheme exp ", exp_cs_mcs, " vs ", cs_mcs, " (", len, ")");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700536 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200537 }
538}
539
540private function f_rx_rlcmac_dl_block_exp_ack_nack(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
541runs on RAW_PCU_Test_CT {
542 var uint32_t dl_fn;
543
544 f_rx_rlcmac_dl_block(dl_block, dl_fn);
545 if (not match(dl_block, tr_RLCMAC_UL_ACK_NACK(ul_tfi := ?, tlli := ?))) {
546 setverdict(fail, "Failed to match Packet Uplink ACK / NACK");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700547 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200548 }
549
Vadim Yanitskiy2742bcd2020-05-10 12:45:18 +0700550 poll_fn := f_rrbp_ack_fn(dl_fn, dl_block.ctrl.mac_hdr.rrbp);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200551}
552
553private function f_rx_rlcmac_dl_block_exp_dummy(out RlcmacDlBlock dl_block)
554runs on RAW_PCU_Test_CT {
555 var uint32_t dl_fn;
556
557 f_rx_rlcmac_dl_block(dl_block, dl_fn);
558 if (not match(dl_block, tr_RLCMAC_DUMMY_CTRL())) {
559 setverdict(fail, "Failed to match Packet DUMMY DL");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700560 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200561 }
562}
563
564private function f_rx_rlcmac_dl_block_exp_pkt_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
565runs on RAW_PCU_Test_CT {
566 var uint32_t dl_fn;
567
568 f_rx_rlcmac_dl_block(dl_block, dl_fn);
569 if (not match(dl_block, tr_RLCMAC_DL_PACKET_ASS())) {
570 setverdict(fail, "Failed to match Packet Downlink Assignment");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700571 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200572 }
573
Vadim Yanitskiy2742bcd2020-05-10 12:45:18 +0700574 poll_fn := f_rrbp_ack_fn(dl_fn, dl_block.ctrl.mac_hdr.rrbp);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200575}
576
577private function f_rx_rlcmac_dl_block_exp_pkt_ul_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
578runs on RAW_PCU_Test_CT {
579 var uint32_t dl_fn;
580
581 f_rx_rlcmac_dl_block(dl_block, dl_fn);
582 if (not match(dl_block, tr_RLCMAC_UL_PACKET_ASS())) {
583 setverdict(fail, "Failed to match Packet Uplink Assignment");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700584 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200585 }
586
Vadim Yanitskiy2742bcd2020-05-10 12:45:18 +0700587 poll_fn := f_rrbp_ack_fn(dl_fn, dl_block.ctrl.mac_hdr.rrbp);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200588}
589
590
591private function f_rx_rlcmac_dl_block_exp_pkt_pag_req(out RlcmacDlBlock dl_block)
592runs on RAW_PCU_Test_CT {
593 var uint32_t dl_fn;
594
595 f_rx_rlcmac_dl_block(dl_block, dl_fn);
596 if (not match(dl_block, tr_RLCMAC_PACKET_PAG_REQ())) {
597 setverdict(fail, "Failed to match Packet Paging Request: ", dl_block, " vs ", tr_RLCMAC_PACKET_PAG_REQ());
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700598 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200599 }
600}
601
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700602/* This function does what could probably be done with templates */
603private function f_rlcmac_dl_block_verify_data_gprs(in RlcmacDlDataBlock data_block,
604 template (present) octetstring data := ?,
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700605 template (present) uint7_t exp_bsn := ?,
606 template (present) CodingScheme exp_cs := ?)
607runs on RAW_PCU_Test_CT {
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700608 if (not match(data_block.mac_hdr.hdr_ext.bsn, exp_bsn)) {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200609 setverdict(fail, "DL block BSN doesn't match: ",
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700610 data_block.mac_hdr.hdr_ext.bsn, " vs exp ", exp_bsn);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200611 }
612
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700613 if (lengthof(data_block.blocks) < 1) {
614 setverdict(fail, "DL block has no LLC payload: ", data_block);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700615 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200616 }
617
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700618 if (not match(data_block.blocks[0].payload, data)) {
619 setverdict(fail, "Failed to match content of LLC payload in DL Block: ",
620 data_block.blocks[0].payload, " vs ", data);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700621 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200622 }
623
624 /* Check next data blocks contain dummy frames */
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700625 if (lengthof(data_block.blocks) > 1 and substr(data_block.blocks[1].payload, 0, 3) != '43C001'O) {
626 setverdict(fail, "Second data payload is not a dummy frame: ",
627 data_block.blocks[1].payload);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700628 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200629 }
630
631 /* TODO: check exp_cs */
632}
633
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700634/* This function does what could probably be done with templates */
635private function f_rlcmac_dl_block_verify_data_egprs(in RlcmacDlEgprsDataBlock data_block,
636 template (present) octetstring data := ?,
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700637 template (present) uint14_t exp_bsn := ?,
638 template (present) CodingScheme exp_cs := ?)
639runs on RAW_PCU_Test_CT {
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700640 if (not match(data_block.mac_hdr.bsn1, exp_bsn)) {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200641 setverdict(fail, "DL block BSN doesn't match: ",
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700642 data_block.mac_hdr.bsn1, " vs exp ", exp_bsn);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200643 }
644
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700645 if (lengthof(data_block.blocks) < 1) {
646 setverdict(fail, "DL block has no LLC payload: ", data_block);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700647 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200648 }
649
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700650 if (not match(data_block.blocks[0].payload, data)) {
651 setverdict(fail, "Failed to match content of LLC payload in DL Block: ",
652 data_block.blocks[0].payload, " vs ", data);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700653 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200654 }
655
656 /* Check next data blocks contain dummy frames */
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700657 if (lengthof(data_block.blocks) > 1 and substr(data_block.blocks[1].payload, 0, 3) != '43C001'O) {
658 setverdict(fail, "Second data payload is not a dummy frame: ",
659 data_block.blocks[1].payload);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700660 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200661 }
662
663 /* 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.
664 See wireshark's egprs_Header_type1_coding_puncturing_scheme_to_mcs. */
665}
666
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700667/* High level (task specific) helper for receiving and matching GPRS/EGPRS data blocks */
668private function f_rx_rlcmac_dl_block_exp_data(out RlcmacDlBlock dl_block, out uint32_t dl_fn,
669 template (present) octetstring data := ?,
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700670 template (present) uint7_t exp_bsn := ?,
671 template (present) CodingScheme exp_cs := ?)
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200672runs on RAW_PCU_Test_CT {
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700673 /* FIXME: ideally we should use an alt statement with timeout here, rather than
674 * having +100500 layers of abstraction. This would facilitate developing the
675 * multi-TBF/-TRX/-BTS tests, where you cannot expect that the first received
676 * block is exactly what you need. */
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200677 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700678
679 /* Make sure it's either GPRS or EGPRS data block */
680 if (not match(dl_block, tr_RLCMAC_DATA)) {
681 setverdict(fail, "Failed to match DL DATA: ", dl_block, " vs ", tr_RLCMAC_DATA);
682 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200683 }
684
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700685 if (ischosen(dl_block.data_egprs)) {
686 f_rlcmac_dl_block_verify_data_egprs(dl_block.data_egprs, data, exp_bsn, exp_cs);
687 } else if (ischosen(dl_block.data)) {
688 f_rlcmac_dl_block_verify_data_gprs(dl_block.data, data, exp_bsn, exp_cs);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200689 } else {
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700690 /* Should not happen, but the caller may theoretically give us a template for CTRL */
691 setverdict(fail, "DL block is neither GPRS nor EGPRS data block: ", dl_block);
692 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200693 }
694}
695
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +0700696private function f_dl_block_ack_fn(in RlcmacDlBlock dl_block, uint32_t dl_fn)
697runs on RAW_PCU_Test_CT return uint32_t {
698 var boolean rrbp_valid;
699 var MacRrbp rrbp;
700
701 /* The argument must be either a GPRS or EGPRS data block */
702 if (ischosen(dl_block.data_egprs)) {
703 rrbp_valid := true; /* always valid */
704 rrbp := dl_block.data_egprs.mac_hdr.rrbp;
705 } else if (ischosen(dl_block.data)) {
706 rrbp_valid := dl_block.data.mac_hdr.mac_hdr.rrbp_valid;
707 rrbp := dl_block.data.mac_hdr.mac_hdr.rrbp;
708 } else {
709 /* Should not happen, but the caller may theoretically give us a CTRL block */
710 setverdict(fail, "DL block is neither GPRS nor EGPRS data block: ", dl_block);
711 f_shutdown(__BFILE__, __LINE__);
712 }
713
714 /* Make sure that the given block really needs to be ACKnowledged */
715 if (not rrbp_valid) {
716 setverdict(fail, "DL block shall not be ACKnowledged, field RRBP is not valid");
717 f_shutdown(__BFILE__, __LINE__);
718 }
719
720 return f_rrbp_ack_fn(dl_fn, rrbp);
721}
722
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200723testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
724 var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.cell_id.ra_id);
725 var GprsTlli tlli := 'FFFFFFFF'O;
726 timer T;
727
728 /* Initialize NS/BSSGP side */
729 f_init_bssgp();
730
731 /* Initialize the PCU interface abstraction */
732 f_init_raw(testcasename());
733
734 /* Establish BSSGP connection to the PCU */
735 f_bssgp_establish();
736
737 BTS.send(ts_PCUIF_SUSP_REQ(0, tlli, ra_id, 0));
738
739 T.start(2.0);
740 alt {
741 [] BSSGP_SIG[0].receive(tr_BSSGP_SUSPEND(tlli, mp_gb_cfg.cell_id.ra_id)) {
742 setverdict(pass);
743 }
744 [] T.timeout {
745 setverdict(fail, "Timeout waiting for BSSGP SUSPEND");
746 }
747 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700748
749 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200750}
751
752/* Test of correct Timing Advance at the time of TBF establishment
753 * (derived from timing offset of the Access Burst). */
754testcase TC_ta_rach_imm_ass() runs on RAW_PCU_Test_CT {
755 var GsmRrMessage rr_msg;
756 var boolean ok;
757
758 /* Initialize the PCU interface abstraction */
759 f_init_raw(testcasename());
760
761 /* We cannot send too many TBF requests in a short time because
762 * at some point the PCU will fail to allocate a new TBF. */
763 for (var TimingAdvance ta := 0; ta < 64; ta := ta + 16) {
764 /* Establish an Uplink TBF (send RACH.ind with current TA) */
765 ok := f_establish_tbf(rr_msg, bts_nr := 0, ta := ta);
766 if (not ok) {
767 setverdict(fail, "Failed to establish an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700768 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200769 }
770
771 /* Make sure Timing Advance IE matches out expectations */
Vadim Yanitskiy8685b382020-05-06 16:53:26 +0700772 if (rr_msg.payload.imm_ass.timing_advance != ta) {
773 setverdict(fail, "Timing Advance mismatch: ",
774 rr_msg.payload.imm_ass.timing_advance,
775 " vs expected ", ta);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700776 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200777 }
778 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700779
780 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200781}
782
783/* Verify Timing Advance value(s) indicated during the packet Downlink assignment
784 * procedure as per 3GPP TS 44.018, section 3.5.3. There seems to be a bug in the
785 * IUT that causes it to send an unreasonable Timing Advance value > 0 despite
786 * no active TBF exists at the moment of establishment (idle mode). */
787testcase TC_ta_idle_dl_tbf_ass() runs on RAW_PCU_Test_CT {
788 var OCT4 tlli := f_rnd_octstring(4);
789 var GsmRrMessage rr_imm_ass;
790
791 /* Initialize NS/BSSGP side */
792 f_init_bssgp();
793
794 /* Initialize the PCU interface abstraction */
795 f_init_raw(testcasename());
796
797 /* Establish BSSGP connection to the PCU */
798 f_bssgp_establish();
799 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
800
801 /* SGSN sends some DL data, PCU will initiate Packet Downlink
802 * Assignment on CCCH (PCH). We don't care about the payload. */
803 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, f_rnd_octstring(10)));
804 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass); // TODO: match by TLLI!
805
806 /* Make sure that Timing Advance is 0 (the actual value is not known yet).
807 * As per 3GPP S 44.018, section 3.5.3.1.2, the network *shall* initiate
808 * the procedures defined in 3GPP TS 44.060 or use the polling mechanism. */
809 if (not match(rr_imm_ass, tr_IMM_TBF_ASS(ta := 0))) {
810 setverdict(fail, "Timing Advance value doesn't match");
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200811 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700812
813 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200814}
815
816/* Verify that the PCU generates valid PTCCH/D messages
817 * while neither Uplink nor Downlink TBF is established. */
818testcase TC_ta_ptcch_idle() runs on RAW_PCU_Test_CT {
819 var PTCCHDownlinkMsg ptcch_msg;
820 var PCUIF_Message pcu_msg;
821 timer T;
822
823 /* Initialize the PCU interface abstraction */
824 f_init_raw(testcasename());
825
826 /* Sent an RTS.req for PTCCH/D */
827 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
828 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
829 arfcn := 871, block_nr := 0));
830 T.start(5.0);
831 alt {
832 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
833 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
834 log("Rx DATA.req message: ", pcu_msg);
835 setverdict(pass);
836 }
837 [] BTS.receive(PCUIF_Message:?) { repeat; }
838 [] T.timeout {
839 setverdict(fail, "Timeout waiting for a PTCCH/D block");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700840 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200841 }
842 }
843
844 ptcch_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
845 log("Decoded PTCCH/D message: ", ptcch_msg);
846
847 /* Make sure the message is encoded correctly
848 * TODO: do we expect all TA values to be equal '1111111'B? */
849 if (not match(ptcch_msg, tr_PTCCHDownlinkMsg)) {
850 setverdict(fail, "Malformed PTCCH/D message");
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/* Test of correct Timing Advance during an active Uplink TBF.
857 *
858 * Unlike the circuit-switched domain, Uplink transmissions on PDCH time-slots
859 * are not continuous and there can be long time gaps between them. This happens
860 * due to a bursty nature of packet data. The actual Timing Advance of a MS may
861 * significantly change between such rare Uplink transmissions, so GPRS introduces
862 * additional mechanisms to control Timing Advance, and thus reduce interference
863 * between neighboring TDMA time-slots.
864 *
865 * At the moment of Uplink TBF establishment, initial Timing Advance is measured
866 * from ToA (Timing of Arrival) of an Access Burst. This is covered by another
867 * test case - TC_ta_rach_imm_ass. In response to that Access Burst the network
868 * sends Immediate Assignment on AGCH, which _may_ contain Timing Advance Index
869 * among with the initial Timing Advance value. And here PTCCH comes to play.
870 *
871 * PTCCH is a unidirectional channel on which the network can instruct a sub-set
872 * of 16 MS (whether TBFs are active or not) to adjust their Timing Advance
873 * continuously. To ensure continuous measurements of the signal propagation
874 * delay, the MSs shall transmit Access Bursts on Uplink (PTCCH/U) on sub-slots
875 * defined by an assigned Timing Advance Index (see 3GPP TS 45.002).
876 *
877 * The purpose of this test case is to verify the assignment of Timing Advance
878 * Index, and the process of Timing Advance notification on PTCCH/D. The MTC
879 * first establishes several Uplink TBFs, but does not transmit any Uplink
880 * blocks on them. During 4 TDMA multi-frame periods the MTC is sending RACH
881 * indications to the PCU, checking the correctness of two received PTCCH/D
882 * messages (period of PTCCH/D is two multi-frames).
883 */
884
885/* List of ToA values for Access Bursts to be sent on PTCCH/U,
886 * each ToA (Timing of Arrival) value is in units of 1/4 of
887 * a symbol (i.e. 1 symbol is 4 QTA units). */
888type record length(16) of int16_t PTCCH_TAI_ToA_MAP;
889const PTCCH_TAI_ToA_MAP ptcch_toa_map_def := {
890 0, 0, 0, 0,
891 0, 0, 0, 0,
892 0, 0, 0, 0,
893 0, 0, 0, 0
894};
895
896private altstep as_ta_ptcch(uint8_t bts_nr := 0, uint8_t trx_nr := 0, uint8_t ts_nr := 7,
897 in PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def)
898runs on RAW_PCU_Test_CT {
899 var RAW_PCU_Event event;
900 var integer ss;
901
902 /* Send Access Bursts on PTCCH/U for every TA Index */
903 [] BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PTCCH_UL_BURST)) -> value event {
904 ss := f_tdma_ptcch_fn2ss(event.data.tdma_fn);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700905 if (ss < 0) { /* Shall not happen */
906 f_shutdown(__BFILE__, __LINE__);
907 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200908
909 log("Sending an Access Burst on PTCCH/U",
910 ", sub-slot=", ss, " (TAI)",
911 ", fn=", event.data.tdma_fn,
912 ", ToA=", toa_map[ss], " (QTA)");
913 /* TODO: do we care about RA and burst format? */
914 BTS.send(ts_PCUIF_RACH_IND(bts_nr, trx_nr, ts_nr,
915 ra := oct2int('3A'O),
916 is_11bit := 0,
917 burst_type := BURST_TYPE_0,
918 fn := event.data.tdma_fn,
919 arfcn := 871,
920 qta := toa_map[ss],
921 sapi := PCU_IF_SAPI_PTCCH));
922 repeat;
923 }
924}
925
926private function f_TC_ta_ptcch_ul_multi_tbf(in PTCCH_TAI_ToA_MAP ptcch_toa_map,
927 template PTCCHDownlinkMsg t_ta_msg)
928runs on RAW_PCU_Test_CT {
929 var PTCCHDownlinkMsg ta_msg;
930 var PCUIF_Message pcu_msg;
931 timer T;
932
933 /* First, send an RTS.req for the upcoming PTCCH/D block */
934 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
935 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
936 arfcn := 871, block_nr := 0));
937 T.start(2.0);
938 alt {
939 /* Keep sending of Access Bursts during two multi-frames (period of PTCCH/D)
940 * with increasing ToA (Timing of Arrival) values: 0, 7, 14, 28, 35... */
941 [] as_ta_ptcch(bts_nr := 0, trx_nr := 0, ts_nr := 7, toa_map := ptcch_toa_map);
942 /* In the end of 2nd multi-frame we should receive a PTCCH/D block */
943 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
944 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
945 ta_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
946 log("Rx PTCCH/D message: ", ta_msg);
947
948 /* Make sure Timing Advance values match our expectations */
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700949 if (not match(ta_msg, t_ta_msg)) {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200950 setverdict(fail, "PTCCH/D message does not match: ", t_ta_msg);
951 }
952 }
953 [] BTS.receive { repeat; }
954 [] T.timeout {
955 setverdict(fail, "Timeout waiting for a PTCCH/D block");
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200956 }
957 }
958}
959
960testcase TC_ta_ptcch_ul_multi_tbf() runs on RAW_PCU_Test_CT {
961 var template PacketUlAssign t_ul_tbf_ass;
962 var PacketUlAssign ul_tbf_ass[7];
963 var GsmRrMessage rr_msg[7];
964 var boolean ok;
965
966 /* Initialize the PCU interface abstraction */
967 f_init_raw(testcasename());
968
969 /* Enable forwarding of PTCCH/U TDMA events to us */
970 BTS.send(ts_RAW_PCU_CMD(TDMA_CMD_ENABLE_PTCCH_UL_FWD));
971
972 /* Establish 7 Uplink TBFs (USF flag is 3 bits long, '111'B is reserved) */
973 for (var integer i := 0; i < 7; i := i + 1) {
974 ok := f_establish_tbf(rr_msg[i], ta := 0);
975 if (not ok) {
976 setverdict(fail, "Failed to establish an Uplink TBF #", i);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700977 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200978 }
979
980 /* Make sure we received an UL TBF Assignment */
981 if (match(rr_msg[i], tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
982 ul_tbf_ass[i] := rr_msg[i].payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
983 log("Rx Uplink TBF assignment for #", i, ": ", ul_tbf_ass[i]);
984 } else {
985 setverdict(fail, "Failed to match UL TBF Assignment for #", i);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700986 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200987 }
988
989 /* We expect incremental TFI/USF assignment (dynamic allocation) */
990 t_ul_tbf_ass := tr_PacketUlDynAssign(tfi := i, usf := i);
991 if (not match(ul_tbf_ass[i], t_ul_tbf_ass)) {
992 setverdict(fail, "Failed to match Packet Uplink Assignment for #", i);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700993 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200994 }
995
996 /* We also expect Timing Advance Index to be a part of the assignment */
997 if (ul_tbf_ass[i].dynamic.ta_index != i) {
998 setverdict(fail, "Failed to match Timing Advance Index for #", i);
999 /* Keep going, the current OsmoPCU does not assign TA Index */
1000 }
1001 }
1002
1003 /* Prepare a list of ToA values for Access Bursts to be sent on PTCCH/U */
1004 var PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def;
1005 for (var integer i := 0; i < 7; i := i + 1) {
1006 /* ToA in units of 1/4 of a symbol */
1007 toa_map[i] := (i + 1) * 7 * 4;
1008 }
1009
1010 /* Now we have all 7 TBFs established in one-phase access mode,
1011 * however we will not be sending any data on them. Instead, we
1012 * will be sending RACH.ind on PTCCH/U during 4 multi-frame
1013 * periods (TAI 0..8), and then will check two PTCCH/D blocks.
1014 *
1015 * Why not 4 TBFs at once? Because Uplink is delayed by 3 TDMA
1016 * time-slots, so at the moment of scheduling a PTCCH/D block
1017 * the PCU has odd number of PTCCH/U Access Bursts received. */
1018 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
1019 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
1020 /* Other values are not known (yet) */
1021 tai3_ta := ?));
1022 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
1023 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
1024 tai3_ta := 28, tai4_ta := 35, tai5_ta := 42,
1025 /* Other values are out of our interest */
1026 tai6_ta := ?));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001027
1028 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001029}
1030
1031/* Default link quality adaptation (Coding Scheme) ranges (inclusive).
1032 * OsmoPCU (VTY): cs link-quality-ranges cs1 6 cs2 5 8 cs3 7 13 cs4 12
1033 *
1034 * NOTE: the ranges are intentionally overlapping because OsmoPCU
1035 * does not change CS/MCS on the range borders (5-6, 7-8, 12-13). */
1036private template integer CS1_lqual_dB_range := (-infinity .. 6);
1037private template integer CS2_lqual_dB_range := (5 .. 8);
1038private template integer CS3_lqual_dB_range := (7 .. 13);
1039private template integer CS4_lqual_dB_range := (12 .. infinity);
1040
1041testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
1042 var GsmRrMessage rr_imm_ass;
1043 var PacketUlAssign ul_tbf_ass;
1044 var RlcmacDlBlock dl_block;
1045 var PCUIF_Message pcu_msg;
1046 var octetstring data;
1047 var boolean ok;
1048 var uint32_t unused_fn;
1049
1050 /* Initialize the PCU interface abstraction */
1051 f_init_raw(testcasename());
1052
1053 f_pcuvty_set_allowed_cs_mcs();
1054 f_pcuvty_set_link_quality_ranges();
1055
1056 /* Establish an Uplink TBF */
1057 ok := f_establish_tbf(rr_imm_ass);
1058 if (not ok) {
1059 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001060 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001061 }
1062
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001063 /* Make sure we've got an Uplink TBF assignment */
1064 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001065
1066 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1067 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1068 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
1069 bsn := 0, /* TODO: what should be here? */
1070 blocks := { /* To be generated in loop */ });
1071
1072 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1073 ul_data.data.tlli := '00000001'O;
1074
1075 /* The actual / old link quality values. We need to keep track of the old
1076 * (basically previous) link quality value, because OsmoPCU actually
1077 * changes the coding scheme if not only the actual, but also the old
1078 * value leaves the current link quality range (window). */
1079 var integer lqual := 0;
1080 var integer lqual_old;
1081
1082 /* 16 UL blocks (0 .. 15 dB, step = 1 dB) */
1083 for (var integer i := 0; i < 16; i := i + 1) {
1084 /* Prepare a new UL block (CV, random payload) */
1085 ul_data.data.mac_hdr.countdown := (15 - i);
1086 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1087
1088 /* Update the old / actual link quality */
1089 lqual_old := lqual;
1090 lqual := i;
1091
1092 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1093 log("Sending DATA.ind with link quality (dB): ", lqual);
1094 f_tx_rlcmac_ul_block(ul_data, lqual * 10);
1095
1096 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1097 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1098
1099 log("Rx Packet Uplink ACK / NACK with Channel Coding Command: ",
1100 dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd);
1101
1102 /* Match the received Channel Coding Command. Since we are increasing
1103 * the link quality value on each iteration and not decreasing, there
1104 * is no need to check the both old and current link quality values. */
1105 var template ChCodingCommand ch_coding;
1106 select (lqual_old) {
1107 case (CS1_lqual_dB_range) { ch_coding := CH_CODING_CS1; }
1108 case (CS2_lqual_dB_range) { ch_coding := CH_CODING_CS2; }
1109 case (CS3_lqual_dB_range) { ch_coding := CH_CODING_CS3; }
1110 case (CS4_lqual_dB_range) { ch_coding := CH_CODING_CS4; }
1111 }
1112
1113 if (not match(dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd, ch_coding)) {
1114 setverdict(fail, "Channel Coding does not match our expectations: ", ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001115 }
1116 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001117
1118 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001119}
1120
1121/* Test the max UL CS set by VTY works fine */
1122testcase TC_cs_initial_ul() runs on RAW_PCU_Test_CT {
1123 var GsmRrMessage rr_imm_ass;
1124 var PacketUlAssign ul_tbf_ass;
1125 var RlcmacDlBlock dl_block;
1126 var boolean ok;
1127 var integer lqual_cb;
1128 var ChCodingCommand last_ch_coding;
1129 var uint32_t unused_fn;
1130
1131 /* Initialize the PCU interface abstraction */
1132 f_init_raw(testcasename());
1133
1134 /* Set initial UL CS to 3 */
1135 g_cs_initial_ul := 3;
1136 f_pcuvty_set_allowed_cs_mcs();
1137 f_pcuvty_set_link_quality_ranges();
1138
1139 /* Take lqual (dB->cB) so that we stay in that CS */
1140 lqual_cb := g_cs_lqual_ranges[2].low * 10;
1141
1142 /* Establish an Uplink TBF */
1143 ok := f_establish_tbf(rr_imm_ass);
1144 if (not ok) {
1145 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001146 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001147 }
1148
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001149 /* Make sure we've got an Uplink TBF assignment */
1150 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001151
1152 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1153 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1154 cv := 3, /* 8 UL blocks to be sent (to be overridden in loop) */
1155 bsn := 0, /* TODO: what should be here? */
1156 blocks := { /* To be generated in loop */ });
1157
1158 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1159 ul_data.data.tlli := '00000001'O;
1160
1161 /* 3 UL blocks, check we are in same initial CS: */
1162 for (var integer i := 0; i < 3; i := i + 1) {
1163 /* Prepare a new UL block (CV, random payload) */
1164 ul_data.data.mac_hdr.countdown := (7 - i);
1165 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1166
1167 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1168 f_tx_rlcmac_ul_block(ul_data, lqual_cb);
1169
1170 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1171 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1172 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1173 }
1174
1175 if (last_ch_coding != CH_CODING_CS3) {
1176 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001177 }
1178
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001179 /* Remaining UL blocks are used to make sure regardless of initial
1180 /* lqual, we can go lower at any time */
1181
1182 /* 5 UL blocks, check we are in same initial CS: */
1183 for (var integer i := 3; i < 8; i := i + 1) {
1184 /* Prepare a new UL block (CV, random payload) */
1185 ul_data.data.mac_hdr.countdown := (7 - i);
1186 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1187
1188 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1189 f_tx_rlcmac_ul_block(ul_data, 0); /* 0 dB, make sure we downgrade CS */
1190
1191 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1192 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1193
1194 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1195 }
1196
1197 if (last_ch_coding != CH_CODING_CS1) {
1198 setverdict(fail, "Channel Coding does not match our expectations (CS-1): ", last_ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001199 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001200
1201 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001202}
1203
1204/* Test the max UL CS set by VTY works fine */
1205testcase TC_cs_max_ul() runs on RAW_PCU_Test_CT {
1206 var GsmRrMessage rr_imm_ass;
1207 var PacketUlAssign ul_tbf_ass;
1208 var RlcmacDlBlock dl_block;
1209 var boolean ok;
1210 var ChCodingCommand last_ch_coding;
1211 var uint32_t unused_fn;
1212
1213 /* Initialize the PCU interface abstraction */
1214 f_init_raw(testcasename());
1215
1216 /* Set maximum allowed UL CS to 3 */
1217 g_cs_max_ul := 3;
1218 f_pcuvty_set_allowed_cs_mcs();
1219 f_pcuvty_set_link_quality_ranges();
1220
1221 /* Establish an Uplink TBF */
1222 ok := f_establish_tbf(rr_imm_ass);
1223 if (not ok) {
1224 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001225 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001226 }
1227
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001228 /* Make sure we've got an Uplink TBF assignment */
1229 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001230
1231 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1232 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1233 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
1234 bsn := 0, /* TODO: what should be here? */
1235 blocks := { /* To be generated in loop */ });
1236
1237 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1238 ul_data.data.tlli := '00000001'O;
1239
1240 /* 16 UL blocks */
1241 for (var integer i := 0; i < 16; i := i + 1) {
1242 /* Prepare a new UL block (CV, random payload) */
1243 ul_data.data.mac_hdr.countdown := (15 - i);
1244 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1245
1246 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1247 f_tx_rlcmac_ul_block(ul_data, 40*10); /* 40 dB */
1248
1249 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1250 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1251
1252 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1253 }
1254
1255 if (last_ch_coding != CH_CODING_CS3) {
1256 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001257 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001258
1259 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001260}
1261
1262/* Verify PCU drops TBF after some time of inactivity. */
1263testcase TC_t3169() runs on RAW_PCU_Test_CT {
1264 var PCUIF_info_ind info_ind;
1265 var GsmRrMessage rr_imm_ass;
1266 var PacketUlAssign ul_tbf_ass;
1267 var RlcmacDlBlock dl_block;
1268 var PCUIF_Message pcu_msg;
1269 var octetstring data;
1270 var boolean ok;
1271 var uint32_t unused_fn;
1272 var OCT4 tlli := '00000001'O;
1273
1274 /* Initialize NS/BSSGP side */
1275 f_init_bssgp();
1276
1277 info_ind := valueof(ts_PCUIF_INFO_default);
1278 /* Set timer to 1 sec (default 5) to speedup test: */
1279 info_ind.t3169 := 1;
1280
1281 /* Initialize the PCU interface abstraction */
1282 f_init_raw(testcasename(), info_ind);
1283
1284 /* Establish BSSGP connection to the PCU */
1285 f_bssgp_establish();
1286 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1287
1288 /* Establish an Uplink TBF */
1289 ok := f_establish_tbf(rr_imm_ass);
1290 if (not ok) {
1291 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001292 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001293 }
1294
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001295 /* Make sure we've got an Uplink TBF assignment */
1296 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001297
1298 /* Send one UL block and make sure it is ACKED fine */
1299 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1300 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1301 /* UL block should be received in SGSN */
1302 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1303
1304 /* Wait until T3169 fires (plus 1 extra sec to make sure) */
1305 f_sleep(int2float(info_ind.t3169) + 1.0);
1306
1307 /* Send an UL block once again, the TBF should be gone by now so no ACK */
1308 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1309 f_rx_rlcmac_dl_block_exp_dummy(dl_block);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001310
1311 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001312}
1313
1314/* Verify that a Downlink TBF can be assigned using PACCH shortly after the
1315 * release of prev DL TBF due to MS staying in PDCH for a while (T3192, in PCU
1316 * T3193) after DL TBF release */
1317testcase TC_t3193() runs on RAW_PCU_Test_CT {
1318 var GsmRrMessage rr_imm_ass;
1319 var PacketDlAssign dl_tbf_ass;
1320 var RlcmacDlBlock dl_block;
1321 var octetstring data := f_rnd_octstring(10);
1322 var boolean ok;
1323 var uint32_t sched_fn;
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001324 var uint32_t dl_fn;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001325 var OCT4 tlli := '00000001'O;
1326 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1327
1328 /* Initialize NS/BSSGP side */
1329 f_init_bssgp();
1330
1331 /* Initialize the PCU interface abstraction */
1332 f_init_raw(testcasename());
1333
1334 /* Establish BSSGP connection to the PCU */
1335 f_bssgp_establish();
1336 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1337
1338 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1339 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1340 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001341
1342 /* Make sure we've got a Downlink TBF assignment */
1343 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1344
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001345 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1346 f_sleep(X2002);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001347 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001348
1349 /* ACK the DL block */
1350 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001351 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1352 0, f_dl_block_ack_fn(dl_block, dl_fn));
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001353 /* we are done with the DL-TBF here so far, let's clean up our local state: */
1354 ack_nack_desc := valueof(t_AckNackDescription_init)
1355
1356 /* Now that final DL block is ACKED and TBF is released, T3193 in PCU
1357 (T3192 in MS) was started and until it fires the MS will be abailable
1358 on PDCH in case new data arrives from SGSN. Let's verify it: */
1359 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1360 f_rx_rlcmac_dl_block_exp_pkt_ass(dl_block, sched_fn);
1361 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1362
1363 /* 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 +07001364 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001365 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001366 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1367 0, f_dl_block_ack_fn(dl_block, dl_fn));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001368
1369 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001370}
1371
1372/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1373 * answered, so TBFs for uplink and later for downlink are created.
1374 */
1375private function f_TC_mo_ping_pong(template (omit) MSRadioAccessCapabilityV ms_racap := omit, template (present) CodingScheme exp_cs_mcs := ?) runs on RAW_PCU_Test_CT {
1376 var GsmRrMessage rr_imm_ass;
1377 var PacketUlAssign ul_tbf_ass;
1378 var PacketDlAssign dl_tbf_ass;
1379 var RlcmacDlBlock dl_block;
1380 var PCUIF_Message pcu_msg;
1381 var octetstring data := f_rnd_octstring(10);
1382 var boolean ok;
1383 var uint32_t sched_fn;
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001384 var uint32_t dl_fn;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001385 var OCT4 tlli := '00000001'O;
1386 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1387
1388 /* Initialize NS/BSSGP side */
1389 f_init_bssgp();
1390
1391 /* Initialize the PCU interface abstraction */
1392 f_init_raw(testcasename());
1393
1394 /* Establish BSSGP connection to the PCU */
1395 f_bssgp_establish();
1396 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1397
1398 /* Establish an Uplink TBF */
1399 ok := f_establish_tbf(rr_imm_ass);
1400 if (not ok) {
1401 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001402 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001403 }
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001404
1405 /* Make sure we've got an Uplink TBF assignment */
1406 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001407
1408 if (not istemplatekind(ms_racap, "omit")) {
1409 /* Send PACKET RESOURCE REQUEST to upgrade to EGPRS
1410 * (see 3GPP TS 04.60 "7.1.3.1 Initiation of the Packet resource request procedure")
1411 */
1412 f_tx_rlcmac_ul_block(ts_RLC_UL_CTRL_ACK(valueof(ts_RlcMacUlCtrl_PKT_RES_REQ(tlli, ms_racap))), 0);
1413 f_rx_rlcmac_dl_block_exp_pkt_ul_ass(dl_block, sched_fn);
1414 if (dl_block.ctrl.payload.u.ul_assignment.identity.tlli.tlli != tlli) {
1415 setverdict(fail, "Wrong TLLI ", dl_block.ctrl.payload.u.ul_assignment.identity.tlli, " received vs exp ", tlli);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001416 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001417 }
1418 }
1419
1420 /* Send one UL block and make sure it is ACKED fine */
1421 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1422 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1423 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1424 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1425
1426 /* UL block should be received in SGSN */
1427 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1428
1429 /* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
1430 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1431 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1432
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001433 /* Make sure we've got a Downlink TBF assignment */
1434 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001435
1436 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1437 f_sleep(X2002);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001438 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0, exp_cs_mcs);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001439
1440 /* ACK the DL block */
1441 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001442 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1443 0, f_dl_block_ack_fn(dl_block, dl_fn));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001444
1445 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001446}
1447
1448/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1449 * answered, so TBFs for uplink and later for downlink are created.
1450 */
1451testcase TC_mo_ping_pong() runs on RAW_PCU_Test_CT {
1452 var CodingScheme exp_cs_mcs := CS_1;
1453 f_TC_mo_ping_pong(omit, exp_cs_mcs);
1454}
1455
1456
1457testcase TC_mo_ping_pong_with_ul_racap() runs on RAW_PCU_Test_CT {
1458 var MultislotCap_GPRS mscap_gprs := {
1459 gprsmultislotclass := '00011'B,
1460 gprsextendeddynalloccap := '0'B
1461 };
1462 var MSRadioAccessCapabilityV ms_racap := { valueof(ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs, omit)) };
1463 var CodingScheme exp_cs_mcs := CS_2;
1464
1465 f_TC_mo_ping_pong(ms_racap, exp_cs_mcs);
1466}
1467
1468/* Test scenario where SGSN wants to send some data against MS and it is
1469 * answered by the MS on PDCH, so TBFs for downlink and later for uplink are created.
1470 */
1471private 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 {
1472 var GsmRrMessage rr_imm_ass;
1473 var PacketUlAssign ul_tbf_ass;
1474 var PacketDlAssign dl_tbf_ass;
1475 var RlcmacDlBlock dl_block;
1476 var PCUIF_Message pcu_msg;
1477 var octetstring data := f_rnd_octstring(10);
1478 var boolean ok;
1479 var uint32_t sched_fn;
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001480 var uint32_t dl_fn;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001481 var OCT4 tlli := '00000001'O;
1482 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1483
1484 /* Initialize NS/BSSGP side */
1485 f_init_bssgp();
1486
1487 /* Initialize the PCU interface abstraction */
1488 f_init_raw(testcasename());
1489
1490 /* Establish BSSGP connection to the PCU */
1491 f_bssgp_establish();
1492 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1493
1494 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1495 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data, ms_racap));
1496 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1497
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001498 /* Make sure we've got a Downlink TBF assignment */
1499 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001500
1501 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1502 f_sleep(X2002);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001503 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0, exp_cs_mcs);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001504
1505 /* ACK the DL block */
1506 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001507 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1508 0, f_dl_block_ack_fn(dl_block, dl_fn));
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001509
1510 /* Now MS wants to answer the DL data, Establish an Uplink TBF */
1511 ok := f_establish_tbf(rr_imm_ass);
1512 if (not ok) {
1513 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001514 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001515 }
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001516
1517 /* Make sure we've got an Uplink TBF assignment */
1518 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001519
1520 /* Send one UL block and make sure it is ACKED fine */
1521 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1522 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1523 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1524 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1525
1526 /* UL block should be received in SGSN */
1527 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001528
1529 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001530}
1531
1532testcase TC_mt_ping_pong() runs on RAW_PCU_Test_CT {
1533 var CodingScheme exp_cs_mcs := CS_1;
1534 f_TC_mt_ping_pong(omit, exp_cs_mcs);
1535}
1536
1537/* TC_mt_ping_pong, but DL-UNITDATA contains RA Access capability with (M)CS
1538/* information about the MS */
1539testcase TC_mt_ping_pong_with_dl_racap() runs on RAW_PCU_Test_CT {
1540 var MultislotCap_GPRS_BSSGP mscap_gprs := {
1541 gprsmultislotclass := '00011'B,
1542 gprsextendeddynalloccap := '0'B
1543 } ;
1544 var MSRadioAccessCapabilityV_BSSGP ms_racap := { valueof(ts_RaCapRec_BSSGP('0001'B /* E-GSM */, mscap_gprs, omit)) };
1545 var CodingScheme exp_cs_mcs := CS_2;
1546 f_TC_mt_ping_pong(ms_racap, exp_cs_mcs);
1547}
1548
1549/* Verify that if PCU doesn't get an ACK for first DL block after IMM ASS, it
1550 * will retry by retransmitting both the IMM ASS + DL block after poll (ack)
1551 * timeout occurs (specified by sent RRBP on DL block). */
1552testcase TC_imm_ass_dl_block_retrans() runs on RAW_PCU_Test_CT {
1553 var GsmRrMessage rr_imm_ass;
1554 var PacketDlAssign dl_tbf_ass;
1555 var RlcmacDlBlock dl_block;
1556 var octetstring data := f_rnd_octstring(10);
1557 var boolean ok;
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001558 var uint32_t dl_fn;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001559 var OCT4 tlli := '00000001'O;
1560 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1561
1562 /* Initialize NS/BSSGP side */
1563 f_init_bssgp();
1564
1565 /* Initialize the PCU interface abstraction */
1566 f_init_raw(testcasename());
1567
1568 /* Establish BSSGP connection to the PCU */
1569 f_bssgp_establish();
1570 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1571
1572 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1573 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1574 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001575
1576 /* Make sure we've got a Downlink TBF assignment */
1577 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001578
1579 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1580 f_sleep(X2002);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001581 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001582
1583 /* Now we don't ack the dl block (emulate MS failed receiveing IMM ASS
1584 * or GPRS DL, or DL ACK was lost for some reason). As a result, PCU
1585 * should retrigger IMM ASS + GPRS DL procedure after poll timeout. */
1586 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001587
1588 /* Make sure we've got a Downlink TBF assignment */
1589 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1590
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001591 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1592 f_sleep(X2002);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001593 f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001594
1595 /* ACK the DL block */
1596 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
Vadim Yanitskiyb6733a62020-05-10 14:39:00 +07001597 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc),
1598 0, f_dl_block_ack_fn(dl_block, dl_fn));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001599
1600 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001601}
1602
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001603private function f_pkt_paging_match_imsi(in PacketPagingReq req, hexstring imsi)
1604runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001605 var MobileIdentityLV_Paging mi_lv := req.repeated_pageinfo.cs.mobile_identity;
1606 var MobileIdentityV mi := dec_MobileIdentityV(mi_lv.mobile_id);
1607
1608 if (mi_lv.len != 8) { /* 8 octets: type of ID (3 bits) + even/odd flag (1 bit) + 15 BCD-encoded digits (60 bits) */
1609 setverdict(fail, "Mobile Identity length mismatch: ",
1610 "expected: 8, got: ", mi_lv.len);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001611 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001612 }
1613
1614 /* Make sure MI contains IMSI before referencing it */
1615 if (mi.typeOfIdentity != '001'B) {
1616 setverdict(fail, "Mobile Identity must be of type IMSI ('001'B), ",
1617 "got: ", mi.typeOfIdentity);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001618 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001619 } else if (mi.oddEvenInd_identity.imsi.digits != imsi) {
1620 setverdict(fail, "Mobile Identity contains unexpected IMSI, ",
1621 "expected: ", imsi, " got: ", mi.oddEvenInd_identity.imsi.digits);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001622 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001623 }
1624}
1625
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001626private function f_pkt_paging_match_tmsi(in PacketPagingReq req, template GsmTmsi tmsi)
1627runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001628 if (not match(req.repeated_pageinfo.cs.tmsi, tmsi)) {
1629 setverdict(fail, "Mobile Identity (TMSI/P-TMSI) mismatch: ",
1630 "expected: ", tmsi, "got: ", req.repeated_pageinfo.cs.tmsi);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001631 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001632 }
1633}
1634
1635/* Test CS paging over the BTS<->PCU socket.
1636 * 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.
1637 * Paging should be send on the PACCH.
1638 *
1639 * 1. Send a Paging Request over PCU socket.
1640 * 2. Send a Ready-To-Send message over PCU socket
1641 * 3. Expect a Paging Frame
1642 */
1643testcase TC_paging_cs_from_bts() runs on RAW_PCU_Test_CT {
1644 var GsmRrMessage rr_imm_ass;
1645 var PacketUlAssign ul_tbf_ass;
1646 var RlcmacDlBlock dl_block;
1647 var boolean ok;
1648 var OCT4 tlli := '00000001'O;
1649 var MobileIdentityLV mi;
1650 var octetstring mi_enc_lv;
1651 var hexstring imsi := f_gen_imsi(42);
1652
1653 /* Initialize NS/BSSGP side */
1654 f_init_bssgp();
1655
1656 /* Initialize the PCU interface abstraction */
1657 f_init_raw(testcasename());
1658
1659 /* Establish BSSGP connection to the PCU */
1660 f_bssgp_establish();
1661 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1662
1663 /* Establish an Uplink TBF */
1664 ok := f_establish_tbf(rr_imm_ass);
1665 if (not ok) {
1666 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001667 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001668 }
1669
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001670 /* Make sure we've got an Uplink TBF assignment */
1671 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001672
1673 /* build mobile Identity */
1674 mi := valueof(ts_MI_IMSI_LV(imsi));
1675 mi_enc_lv := enc_MobileIdentityLV(mi);
1676 /* Send paging request */
1677 BTS.send(ts_PCUIF_PAG_REQ(bts_nr := 0, id_lv := mi_enc_lv, chan_needed := 0,
1678 sapi :=PCU_IF_SAPI_PDTCH));
1679
1680 /* Receive it on BTS side towards MS */
1681 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
1682
1683 /* Make sure that Packet Paging Request contains the same IMSI */
1684 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1685
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001686 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001687}
1688
1689/* Test CS paging over Gb (SGSN->PCU->BTS[PDCH]).
1690 */
1691private function f_tc_paging_cs_from_sgsn(Nsvci bvci, boolean use_ptmsi := false)
1692runs on RAW_PCU_Test_CT {
1693 var GsmRrMessage rr_imm_ass;
1694 var PacketUlAssign ul_tbf_ass;
1695 var RlcmacDlBlock dl_block;
1696 var boolean ok;
1697 var OCT4 tlli := '00000001'O;
1698 var hexstring imsi := f_gen_imsi(42);
1699 var GsmTmsi tmsi;
1700
1701 /* Initialize NS/BSSGP side */
1702 f_init_bssgp();
1703
1704 /* Initialize the PCU interface abstraction */
1705 f_init_raw(testcasename());
1706
1707 /* Establish BSSGP connection to the PCU */
1708 f_bssgp_establish();
1709 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1710
1711 /* Establish an Uplink TBF */
1712 ok := f_establish_tbf(rr_imm_ass);
1713 if (not ok) {
1714 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001715 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001716 }
1717
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001718 /* Make sure we've got an Uplink TBF assignment */
1719 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001720
1721 /* Send paging request with or without TMSI */
1722 if (use_ptmsi) {
1723 tmsi := oct2int(f_rnd_octstring(4)); /* Random P-TMSI */
1724 BSSGP[0].send(ts_BSSGP_CS_PAGING_PTMSI(bvci, imsi, tmsi));
1725 } else {
1726 BSSGP[0].send(ts_BSSGP_CS_PAGING_IMSI(bvci, imsi));
1727 }
1728
1729 /* Receive it on BTS side towards MS */
1730 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
1731
1732 /* Make sure that Packet Paging Request contains the same P-TMSI/IMSI */
1733 if (use_ptmsi) {
1734 f_pkt_paging_match_tmsi(dl_block.ctrl.payload.u.paging, tmsi);
1735 } else {
1736 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1737 }
1738
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001739 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001740}
1741
1742testcase TC_paging_cs_from_sgsn_sign_ptmsi() runs on RAW_PCU_Test_CT {
1743 f_tc_paging_cs_from_sgsn(0, true);
1744}
1745
1746testcase TC_paging_cs_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1747 f_tc_paging_cs_from_sgsn(0);
1748}
1749
1750testcase TC_paging_cs_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1751 f_tc_paging_cs_from_sgsn(mp_gb_cfg.bvci);
1752}
1753
1754/* Test PS paging over Gb (SGSN->PCU->BTS[CCCH]).
1755 */
1756private function f_tc_paging_ps_from_sgsn(Nsvci bvci, boolean use_ptmsi := false)
1757runs on RAW_PCU_Test_CT {
1758 var OCT4 tlli := '00000001'O;
1759 var integer imsi_suff_tx := 423;
1760 var hexstring imsi := f_gen_imsi(imsi_suff_tx);
1761
1762 /* Initialize NS/BSSGP side */
1763 f_init_bssgp();
1764
1765 /* Initialize the PCU interface abstraction */
1766 f_init_raw(testcasename());
1767
1768 /* Establish BSSGP connection to the PCU */
1769 f_bssgp_establish();
1770 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1771
1772 /* Send BSSGP PAGING-PS (with or without TMSI), wait for RR Paging Request Type 1.
1773 * Make sure that both paging group (IMSI suffix) and Mobile Identity match. */
1774 if (use_ptmsi) {
1775 var OCT4 tmsi := f_rnd_octstring(4); /* Random P-TMSI */
1776 BSSGP[0].send(ts_BSSGP_PS_PAGING_PTMSI(bvci, imsi, oct2int(tmsi)));
1777 f_pcuif_rx_pch_pag_req1(t_MI_TMSI(tmsi), imsi_suff_tx);
1778 } else {
1779 BSSGP[0].send(ts_BSSGP_PS_PAGING_IMSI(bvci, imsi));
1780 f_pcuif_rx_pch_pag_req1(tr_MI_IMSI(imsi), imsi_suff_tx);
1781 }
1782
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001783 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001784}
1785
1786testcase TC_paging_ps_from_sgsn_sign_ptmsi() runs on RAW_PCU_Test_CT {
1787 f_tc_paging_ps_from_sgsn(0, true);
1788}
1789
1790testcase TC_paging_ps_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1791 f_tc_paging_ps_from_sgsn(0);
1792}
1793
1794testcase TC_paging_ps_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1795 f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvci);
1796}
1797
1798private function f_TC_egprs_pkt_chan_req(in EGPRSPktChRequest req,
1799 template GsmRrMessage t_imm_ass := ?,
1800 PCUIF_BurstType bt := BURST_TYPE_1)
1801runs on RAW_PCU_Test_CT {
1802 var GsmRrMessage rr_msg;
1803 var uint16_t ra11;
1804 var boolean ok;
1805
1806 ra11 := enc_EGPRSPktChRequest2uint(req);
1807 log("Sending EGPRS Packet Channel Request (", ra11, "): ", req);
1808
1809 ok := f_establish_tbf(rr_msg, ra := ra11, is_11bit := 1, burst_type := bt);
1810 if (not ok) {
1811 setverdict(fail, "Failed to establush an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001812 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001813 }
1814
1815 if (not match(rr_msg, t_imm_ass)) {
1816 setverdict(fail, "Immediate Assignment does not match");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001817 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001818 }
1819
1820 setverdict(pass);
1821}
1822
1823testcase TC_egprs_pkt_chan_req_signalling() runs on RAW_PCU_Test_CT {
1824 var template GsmRrMessage imm_ass;
1825 var template IaRestOctets rest;
1826 var template EgprsUlAss ul_ass;
1827
1828 /* Initialize the PCU interface abstraction */
1829 f_init_raw(testcasename());
1830
1831 var EGPRSPktChRequest req := {
1832 /* NOTE: other fields are set in the loop */
1833 signalling := { tag := '110011'B }
1834 };
1835
1836 for (var integer i := 0; i < 6; i := i + 1) {
1837 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
1838 req.signalling.random_bits := ext_ra;
1839
1840 /* For signalling, do we expect Multiblock UL TBF Assignment? */
1841 ul_ass := tr_EgprsUlAssMultiblock(ext_ra := ext_ra);
1842 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
1843 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
1844
1845 f_TC_egprs_pkt_chan_req(req, imm_ass);
1846 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001847
1848 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001849}
1850
1851testcase TC_egprs_pkt_chan_req_one_phase() runs on RAW_PCU_Test_CT {
1852 var template GsmRrMessage imm_ass;
1853 var template IaRestOctets rest;
1854 var template EgprsUlAss ul_ass;
1855
1856 /* Initialize the PCU interface abstraction */
1857 f_init_raw(testcasename());
1858
1859 var EGPRSPktChRequest req := {
1860 /* NOTE: other fields are set in the loop */
1861 one_phase := { tag := '0'B }
1862 };
1863
1864 for (var integer i := 0; i < 6; i := i + 1) {
1865 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
1866 var BIT5 mslot_class := int2bit(f_rnd_int(32), 5);
1867 var BIT2 priority := substr(ext_ra, 0, 2);
1868 var BIT3 rand := substr(ext_ra, 2, 3);
1869
1870 req.one_phase.multislot_class := mslot_class;
1871 req.one_phase.priority := priority;
1872 req.one_phase.random_bits := rand;
1873
1874 /* For one phase access, do we expect Dynamic UL TBF Assignment? */
1875 ul_ass := tr_EgprsUlAssDynamic(ext_ra := ext_ra);
1876 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
1877 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
1878
1879 f_TC_egprs_pkt_chan_req(req, imm_ass);
1880 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001881
1882 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001883}
1884
1885testcase TC_egprs_pkt_chan_req_two_phase() runs on RAW_PCU_Test_CT {
1886 var template GsmRrMessage imm_ass;
1887 var template IaRestOctets rest;
1888 var template EgprsUlAss ul_ass;
1889
1890 /* Initialize the PCU interface abstraction */
1891 f_init_raw(testcasename());
1892
1893 var EGPRSPktChRequest req := {
1894 /* NOTE: other fields are set in the loop */
1895 two_phase := { tag := '110000'B }
1896 };
1897
1898 for (var integer i := 0; i < 6; i := i + 1) {
1899 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
1900 var BIT2 priority := substr(ext_ra, 0, 2);
1901 var BIT3 rand := substr(ext_ra, 2, 3);
1902
1903 req.two_phase.priority := priority;
1904 req.two_phase.random_bits := rand;
1905
1906 /* For two phase access, do we expect Multiblock UL TBF Assignment? */
1907 ul_ass := tr_EgprsUlAssMultiblock(ext_ra := ext_ra);
1908 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
1909 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
1910
1911 f_TC_egprs_pkt_chan_req(req, imm_ass);
1912 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001913
1914 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001915}
1916
1917control {
1918 execute( TC_pcuif_suspend() );
1919 execute( TC_ta_ptcch_idle() );
1920 execute( TC_ta_rach_imm_ass() );
1921 execute( TC_ta_idle_dl_tbf_ass() );
1922 execute( TC_ta_ptcch_ul_multi_tbf() );
1923 execute( TC_cs_lqual_ul_tbf() );
1924 execute( TC_cs_initial_ul() );
1925 execute( TC_cs_max_ul() );
1926 execute( TC_t3169() );
1927 execute( TC_t3193() );
1928 execute( TC_mo_ping_pong() );
1929 execute( TC_mo_ping_pong_with_ul_racap() );
1930 execute( TC_mt_ping_pong() );
1931 execute( TC_mt_ping_pong_with_dl_racap() );
1932 execute( TC_imm_ass_dl_block_retrans() );
1933 execute( TC_paging_cs_from_bts() );
1934 execute( TC_paging_cs_from_sgsn_sign_ptmsi() );
1935 execute( TC_paging_cs_from_sgsn_sign() );
1936 execute( TC_paging_cs_from_sgsn_ptp() );
1937 execute( TC_paging_ps_from_sgsn_sign_ptmsi() );
1938 execute( TC_paging_ps_from_sgsn_sign() );
1939 execute( TC_paging_ps_from_sgsn_ptp() );
1940
1941 /* EGPRS specific test cases */
1942 execute( TC_egprs_pkt_chan_req_signalling() );
1943 execute( TC_egprs_pkt_chan_req_one_phase() );
1944 execute( TC_egprs_pkt_chan_req_two_phase() );
1945}
1946
1947
1948
1949
1950
1951
Harald Weltea419df22019-03-21 17:23:04 +01001952}