blob: 0c61595efc8ce11ca16a85a993dde20e074c8724 [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
550 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
551}
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
574 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
575}
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
587 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
588}
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 Yanitskiy91f8a092020-05-06 21:41:05 +0700602private function f_rlcmac_dl_block_verify_data_gprs(RlcmacDlBlock dl_block, uint32_t dl_fn,
603 out uint32_t ack_fn, octetstring data,
604 template (present) uint7_t exp_bsn := ?,
605 template (present) CodingScheme exp_cs := ?)
606runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200607 log("verifying dl data block (gprs): ", dl_block);
608
609 ack_fn := dl_fn + f_rrbp_fn_delay(dl_block.data.mac_hdr.mac_hdr.rrbp);
610
611 if (not match(dl_block.data.mac_hdr.hdr_ext.bsn, exp_bsn)) {
612 setverdict(fail, "DL block BSN doesn't match: ",
613 dl_block.data.blocks[0].hdr.length_ind, " vs exp ", exp_bsn);
614 }
615
616 if (lengthof(dl_block.data.blocks) < 1) {
617 setverdict(fail, "DL block has no LLC payload: ", dl_block);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700618 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200619 }
620
621 if (ispresent(dl_block.data.blocks[0].hdr) and dl_block.data.blocks[0].hdr.length_ind != lengthof(data)) {
622 setverdict(fail, "DL block has LLC header with wrong expected size: ",
623 dl_block.data.blocks[0].hdr.length_ind, " vs ", lengthof(data));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700624 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200625 }
626
627 if (dl_block.data.blocks[0].payload != data) {
628 setverdict(fail, "Failed to match content of LLC payload in DL Block: ", dl_block, " vs ", data);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700629 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200630 }
631
632 /* Check next data blocks contain dummy frames */
633 if (lengthof(dl_block.data.blocks) > 1 and substr(dl_block.data.blocks[1].payload, 0, 3) != '43C001'O) {
634 setverdict(fail, "Second data payload is not a dummy frame: ", dl_block.data.blocks[1].payload);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700635 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200636 }
637
638 /* TODO: check exp_cs */
639}
640
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700641private function f_rlcmac_dl_block_verify_data_egprs(RlcmacDlBlock dl_block, uint32_t dl_fn,
642 out uint32_t ack_fn, octetstring data,
643 template (present) uint14_t exp_bsn := ?,
644 template (present) CodingScheme exp_cs := ?)
645runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200646 log("verifying dl data block (egprs): ", dl_block);
647
648 ack_fn := dl_fn + f_rrbp_fn_delay(dl_block.data_egprs.mac_hdr.rrbp);
649
650 if (not match(dl_block.data_egprs.mac_hdr.bsn1, exp_bsn)) {
651 setverdict(fail, "DL block BSN doesn't match: ",
652 dl_block.data_egprs.blocks[0].hdr.length_ind, " vs exp ", exp_bsn);
653 }
654
655 if (lengthof(dl_block.data_egprs.blocks) < 1) {
656 setverdict(fail, "DL block has no LLC payload: ", dl_block);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700657 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200658 }
659
660 if (ispresent(dl_block.data_egprs.blocks[0].hdr) and dl_block.data_egprs.blocks[0].hdr.length_ind != lengthof(data)) {
661 setverdict(fail, "DL block has LLC header with wrong expected size: ",
662 dl_block.data_egprs.blocks[0].hdr.length_ind, " vs ", lengthof(data));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700663 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200664 }
665
666 if (dl_block.data_egprs.blocks[0].payload != data) {
667 setverdict(fail, "Failed to match content of LLC payload in DL Block: ", dl_block, " vs ", data);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700668 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200669 }
670
671 /* Check next data blocks contain dummy frames */
672 if (lengthof(dl_block.data_egprs.blocks) > 1 and substr(dl_block.data_egprs.blocks[1].payload, 0, 3) != '43C001'O) {
673 setverdict(fail, "Second data payload is not a dummy frame: ", dl_block.data.blocks[1].payload);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700674 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200675 }
676
677 /* 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.
678 See wireshark's egprs_Header_type1_coding_puncturing_scheme_to_mcs. */
679}
680
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700681private function f_rx_rlcmac_dl_block_exp_data(out RlcmacDlBlock dl_block, out uint32_t ack_fn,
682 octetstring data,
683 template (present) uint7_t exp_bsn := ?,
684 template (present) CodingScheme exp_cs := ?)
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200685runs on RAW_PCU_Test_CT {
686 var PCUIF_Message pcu_msg;
687 var uint32_t dl_fn;
688 var boolean is_egprs := false;
689 var template RlcmacDlBlock dl_template := tr_RLCMAC_DATA_RRBP;
690 dl_template.data.blocks := ?;
691
692 f_rx_rlcmac_dl_block(dl_block, dl_fn);
693 if (not match(dl_block, dl_template)) {
694 dl_template := tr_RLCMAC_DATA_EGPRS;
695 dl_template.data_egprs.blocks := ?;
696 if (not match(dl_block, dl_template)) {
697 setverdict(fail, "Failed to match Packet data: ", dl_block, " vs ", dl_template);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700698 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200699 }
700 is_egprs := true;
701 }
702
703 if (is_egprs) {
704 f_rlcmac_dl_block_verify_data_egprs(dl_block, dl_fn, ack_fn, data, exp_bsn, exp_cs);
705 } else {
706 f_rlcmac_dl_block_verify_data_gprs(dl_block, dl_fn, ack_fn, data, exp_bsn, exp_cs);
707 }
708}
709
710testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
711 var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.cell_id.ra_id);
712 var GprsTlli tlli := 'FFFFFFFF'O;
713 timer T;
714
715 /* Initialize NS/BSSGP side */
716 f_init_bssgp();
717
718 /* Initialize the PCU interface abstraction */
719 f_init_raw(testcasename());
720
721 /* Establish BSSGP connection to the PCU */
722 f_bssgp_establish();
723
724 BTS.send(ts_PCUIF_SUSP_REQ(0, tlli, ra_id, 0));
725
726 T.start(2.0);
727 alt {
728 [] BSSGP_SIG[0].receive(tr_BSSGP_SUSPEND(tlli, mp_gb_cfg.cell_id.ra_id)) {
729 setverdict(pass);
730 }
731 [] T.timeout {
732 setverdict(fail, "Timeout waiting for BSSGP SUSPEND");
733 }
734 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700735
736 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200737}
738
739/* Test of correct Timing Advance at the time of TBF establishment
740 * (derived from timing offset of the Access Burst). */
741testcase TC_ta_rach_imm_ass() runs on RAW_PCU_Test_CT {
742 var GsmRrMessage rr_msg;
743 var boolean ok;
744
745 /* Initialize the PCU interface abstraction */
746 f_init_raw(testcasename());
747
748 /* We cannot send too many TBF requests in a short time because
749 * at some point the PCU will fail to allocate a new TBF. */
750 for (var TimingAdvance ta := 0; ta < 64; ta := ta + 16) {
751 /* Establish an Uplink TBF (send RACH.ind with current TA) */
752 ok := f_establish_tbf(rr_msg, bts_nr := 0, ta := ta);
753 if (not ok) {
754 setverdict(fail, "Failed to establish an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700755 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200756 }
757
758 /* Make sure Timing Advance IE matches out expectations */
Vadim Yanitskiy8685b382020-05-06 16:53:26 +0700759 if (rr_msg.payload.imm_ass.timing_advance != ta) {
760 setverdict(fail, "Timing Advance mismatch: ",
761 rr_msg.payload.imm_ass.timing_advance,
762 " vs expected ", ta);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700763 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200764 }
765 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700766
767 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200768}
769
770/* Verify Timing Advance value(s) indicated during the packet Downlink assignment
771 * procedure as per 3GPP TS 44.018, section 3.5.3. There seems to be a bug in the
772 * IUT that causes it to send an unreasonable Timing Advance value > 0 despite
773 * no active TBF exists at the moment of establishment (idle mode). */
774testcase TC_ta_idle_dl_tbf_ass() runs on RAW_PCU_Test_CT {
775 var OCT4 tlli := f_rnd_octstring(4);
776 var GsmRrMessage rr_imm_ass;
777
778 /* Initialize NS/BSSGP side */
779 f_init_bssgp();
780
781 /* Initialize the PCU interface abstraction */
782 f_init_raw(testcasename());
783
784 /* Establish BSSGP connection to the PCU */
785 f_bssgp_establish();
786 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
787
788 /* SGSN sends some DL data, PCU will initiate Packet Downlink
789 * Assignment on CCCH (PCH). We don't care about the payload. */
790 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, f_rnd_octstring(10)));
791 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass); // TODO: match by TLLI!
792
793 /* Make sure that Timing Advance is 0 (the actual value is not known yet).
794 * As per 3GPP S 44.018, section 3.5.3.1.2, the network *shall* initiate
795 * the procedures defined in 3GPP TS 44.060 or use the polling mechanism. */
796 if (not match(rr_imm_ass, tr_IMM_TBF_ASS(ta := 0))) {
797 setverdict(fail, "Timing Advance value doesn't match");
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200798 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700799
800 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200801}
802
803/* Verify that the PCU generates valid PTCCH/D messages
804 * while neither Uplink nor Downlink TBF is established. */
805testcase TC_ta_ptcch_idle() runs on RAW_PCU_Test_CT {
806 var PTCCHDownlinkMsg ptcch_msg;
807 var PCUIF_Message pcu_msg;
808 timer T;
809
810 /* Initialize the PCU interface abstraction */
811 f_init_raw(testcasename());
812
813 /* Sent an RTS.req for PTCCH/D */
814 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
815 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
816 arfcn := 871, block_nr := 0));
817 T.start(5.0);
818 alt {
819 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
820 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
821 log("Rx DATA.req message: ", pcu_msg);
822 setverdict(pass);
823 }
824 [] BTS.receive(PCUIF_Message:?) { repeat; }
825 [] T.timeout {
826 setverdict(fail, "Timeout waiting for a PTCCH/D block");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700827 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200828 }
829 }
830
831 ptcch_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
832 log("Decoded PTCCH/D message: ", ptcch_msg);
833
834 /* Make sure the message is encoded correctly
835 * TODO: do we expect all TA values to be equal '1111111'B? */
836 if (not match(ptcch_msg, tr_PTCCHDownlinkMsg)) {
837 setverdict(fail, "Malformed PTCCH/D message");
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200838 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700839
840 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200841}
842
843/* Test of correct Timing Advance during an active Uplink TBF.
844 *
845 * Unlike the circuit-switched domain, Uplink transmissions on PDCH time-slots
846 * are not continuous and there can be long time gaps between them. This happens
847 * due to a bursty nature of packet data. The actual Timing Advance of a MS may
848 * significantly change between such rare Uplink transmissions, so GPRS introduces
849 * additional mechanisms to control Timing Advance, and thus reduce interference
850 * between neighboring TDMA time-slots.
851 *
852 * At the moment of Uplink TBF establishment, initial Timing Advance is measured
853 * from ToA (Timing of Arrival) of an Access Burst. This is covered by another
854 * test case - TC_ta_rach_imm_ass. In response to that Access Burst the network
855 * sends Immediate Assignment on AGCH, which _may_ contain Timing Advance Index
856 * among with the initial Timing Advance value. And here PTCCH comes to play.
857 *
858 * PTCCH is a unidirectional channel on which the network can instruct a sub-set
859 * of 16 MS (whether TBFs are active or not) to adjust their Timing Advance
860 * continuously. To ensure continuous measurements of the signal propagation
861 * delay, the MSs shall transmit Access Bursts on Uplink (PTCCH/U) on sub-slots
862 * defined by an assigned Timing Advance Index (see 3GPP TS 45.002).
863 *
864 * The purpose of this test case is to verify the assignment of Timing Advance
865 * Index, and the process of Timing Advance notification on PTCCH/D. The MTC
866 * first establishes several Uplink TBFs, but does not transmit any Uplink
867 * blocks on them. During 4 TDMA multi-frame periods the MTC is sending RACH
868 * indications to the PCU, checking the correctness of two received PTCCH/D
869 * messages (period of PTCCH/D is two multi-frames).
870 */
871
872/* List of ToA values for Access Bursts to be sent on PTCCH/U,
873 * each ToA (Timing of Arrival) value is in units of 1/4 of
874 * a symbol (i.e. 1 symbol is 4 QTA units). */
875type record length(16) of int16_t PTCCH_TAI_ToA_MAP;
876const PTCCH_TAI_ToA_MAP ptcch_toa_map_def := {
877 0, 0, 0, 0,
878 0, 0, 0, 0,
879 0, 0, 0, 0,
880 0, 0, 0, 0
881};
882
883private altstep as_ta_ptcch(uint8_t bts_nr := 0, uint8_t trx_nr := 0, uint8_t ts_nr := 7,
884 in PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def)
885runs on RAW_PCU_Test_CT {
886 var RAW_PCU_Event event;
887 var integer ss;
888
889 /* Send Access Bursts on PTCCH/U for every TA Index */
890 [] BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PTCCH_UL_BURST)) -> value event {
891 ss := f_tdma_ptcch_fn2ss(event.data.tdma_fn);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700892 if (ss < 0) { /* Shall not happen */
893 f_shutdown(__BFILE__, __LINE__);
894 }
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200895
896 log("Sending an Access Burst on PTCCH/U",
897 ", sub-slot=", ss, " (TAI)",
898 ", fn=", event.data.tdma_fn,
899 ", ToA=", toa_map[ss], " (QTA)");
900 /* TODO: do we care about RA and burst format? */
901 BTS.send(ts_PCUIF_RACH_IND(bts_nr, trx_nr, ts_nr,
902 ra := oct2int('3A'O),
903 is_11bit := 0,
904 burst_type := BURST_TYPE_0,
905 fn := event.data.tdma_fn,
906 arfcn := 871,
907 qta := toa_map[ss],
908 sapi := PCU_IF_SAPI_PTCCH));
909 repeat;
910 }
911}
912
913private function f_TC_ta_ptcch_ul_multi_tbf(in PTCCH_TAI_ToA_MAP ptcch_toa_map,
914 template PTCCHDownlinkMsg t_ta_msg)
915runs on RAW_PCU_Test_CT {
916 var PTCCHDownlinkMsg ta_msg;
917 var PCUIF_Message pcu_msg;
918 timer T;
919
920 /* First, send an RTS.req for the upcoming PTCCH/D block */
921 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
922 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
923 arfcn := 871, block_nr := 0));
924 T.start(2.0);
925 alt {
926 /* Keep sending of Access Bursts during two multi-frames (period of PTCCH/D)
927 * with increasing ToA (Timing of Arrival) values: 0, 7, 14, 28, 35... */
928 [] as_ta_ptcch(bts_nr := 0, trx_nr := 0, ts_nr := 7, toa_map := ptcch_toa_map);
929 /* In the end of 2nd multi-frame we should receive a PTCCH/D block */
930 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
931 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
932 ta_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
933 log("Rx PTCCH/D message: ", ta_msg);
934
935 /* Make sure Timing Advance values match our expectations */
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700936 if (not match(ta_msg, t_ta_msg)) {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200937 setverdict(fail, "PTCCH/D message does not match: ", t_ta_msg);
938 }
939 }
940 [] BTS.receive { repeat; }
941 [] T.timeout {
942 setverdict(fail, "Timeout waiting for a PTCCH/D block");
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200943 }
944 }
945}
946
947testcase TC_ta_ptcch_ul_multi_tbf() runs on RAW_PCU_Test_CT {
948 var template PacketUlAssign t_ul_tbf_ass;
949 var PacketUlAssign ul_tbf_ass[7];
950 var GsmRrMessage rr_msg[7];
951 var boolean ok;
952
953 /* Initialize the PCU interface abstraction */
954 f_init_raw(testcasename());
955
956 /* Enable forwarding of PTCCH/U TDMA events to us */
957 BTS.send(ts_RAW_PCU_CMD(TDMA_CMD_ENABLE_PTCCH_UL_FWD));
958
959 /* Establish 7 Uplink TBFs (USF flag is 3 bits long, '111'B is reserved) */
960 for (var integer i := 0; i < 7; i := i + 1) {
961 ok := f_establish_tbf(rr_msg[i], ta := 0);
962 if (not ok) {
963 setverdict(fail, "Failed to establish an Uplink TBF #", i);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700964 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200965 }
966
967 /* Make sure we received an UL TBF Assignment */
968 if (match(rr_msg[i], tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
969 ul_tbf_ass[i] := rr_msg[i].payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
970 log("Rx Uplink TBF assignment for #", i, ": ", ul_tbf_ass[i]);
971 } else {
972 setverdict(fail, "Failed to match UL TBF Assignment for #", i);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700973 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200974 }
975
976 /* We expect incremental TFI/USF assignment (dynamic allocation) */
977 t_ul_tbf_ass := tr_PacketUlDynAssign(tfi := i, usf := i);
978 if (not match(ul_tbf_ass[i], t_ul_tbf_ass)) {
979 setverdict(fail, "Failed to match Packet Uplink Assignment for #", i);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +0700980 break;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +0200981 }
982
983 /* We also expect Timing Advance Index to be a part of the assignment */
984 if (ul_tbf_ass[i].dynamic.ta_index != i) {
985 setverdict(fail, "Failed to match Timing Advance Index for #", i);
986 /* Keep going, the current OsmoPCU does not assign TA Index */
987 }
988 }
989
990 /* Prepare a list of ToA values for Access Bursts to be sent on PTCCH/U */
991 var PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def;
992 for (var integer i := 0; i < 7; i := i + 1) {
993 /* ToA in units of 1/4 of a symbol */
994 toa_map[i] := (i + 1) * 7 * 4;
995 }
996
997 /* Now we have all 7 TBFs established in one-phase access mode,
998 * however we will not be sending any data on them. Instead, we
999 * will be sending RACH.ind on PTCCH/U during 4 multi-frame
1000 * periods (TAI 0..8), and then will check two PTCCH/D blocks.
1001 *
1002 * Why not 4 TBFs at once? Because Uplink is delayed by 3 TDMA
1003 * time-slots, so at the moment of scheduling a PTCCH/D block
1004 * the PCU has odd number of PTCCH/U Access Bursts received. */
1005 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
1006 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
1007 /* Other values are not known (yet) */
1008 tai3_ta := ?));
1009 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
1010 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
1011 tai3_ta := 28, tai4_ta := 35, tai5_ta := 42,
1012 /* Other values are out of our interest */
1013 tai6_ta := ?));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001014
1015 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001016}
1017
1018/* Default link quality adaptation (Coding Scheme) ranges (inclusive).
1019 * OsmoPCU (VTY): cs link-quality-ranges cs1 6 cs2 5 8 cs3 7 13 cs4 12
1020 *
1021 * NOTE: the ranges are intentionally overlapping because OsmoPCU
1022 * does not change CS/MCS on the range borders (5-6, 7-8, 12-13). */
1023private template integer CS1_lqual_dB_range := (-infinity .. 6);
1024private template integer CS2_lqual_dB_range := (5 .. 8);
1025private template integer CS3_lqual_dB_range := (7 .. 13);
1026private template integer CS4_lqual_dB_range := (12 .. infinity);
1027
1028testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
1029 var GsmRrMessage rr_imm_ass;
1030 var PacketUlAssign ul_tbf_ass;
1031 var RlcmacDlBlock dl_block;
1032 var PCUIF_Message pcu_msg;
1033 var octetstring data;
1034 var boolean ok;
1035 var uint32_t unused_fn;
1036
1037 /* Initialize the PCU interface abstraction */
1038 f_init_raw(testcasename());
1039
1040 f_pcuvty_set_allowed_cs_mcs();
1041 f_pcuvty_set_link_quality_ranges();
1042
1043 /* Establish an Uplink TBF */
1044 ok := f_establish_tbf(rr_imm_ass);
1045 if (not ok) {
1046 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001047 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001048 }
1049
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001050 /* Make sure we've got an Uplink TBF assignment */
1051 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001052
1053 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1054 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1055 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
1056 bsn := 0, /* TODO: what should be here? */
1057 blocks := { /* To be generated in loop */ });
1058
1059 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1060 ul_data.data.tlli := '00000001'O;
1061
1062 /* The actual / old link quality values. We need to keep track of the old
1063 * (basically previous) link quality value, because OsmoPCU actually
1064 * changes the coding scheme if not only the actual, but also the old
1065 * value leaves the current link quality range (window). */
1066 var integer lqual := 0;
1067 var integer lqual_old;
1068
1069 /* 16 UL blocks (0 .. 15 dB, step = 1 dB) */
1070 for (var integer i := 0; i < 16; i := i + 1) {
1071 /* Prepare a new UL block (CV, random payload) */
1072 ul_data.data.mac_hdr.countdown := (15 - i);
1073 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1074
1075 /* Update the old / actual link quality */
1076 lqual_old := lqual;
1077 lqual := i;
1078
1079 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1080 log("Sending DATA.ind with link quality (dB): ", lqual);
1081 f_tx_rlcmac_ul_block(ul_data, lqual * 10);
1082
1083 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1084 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1085
1086 log("Rx Packet Uplink ACK / NACK with Channel Coding Command: ",
1087 dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd);
1088
1089 /* Match the received Channel Coding Command. Since we are increasing
1090 * the link quality value on each iteration and not decreasing, there
1091 * is no need to check the both old and current link quality values. */
1092 var template ChCodingCommand ch_coding;
1093 select (lqual_old) {
1094 case (CS1_lqual_dB_range) { ch_coding := CH_CODING_CS1; }
1095 case (CS2_lqual_dB_range) { ch_coding := CH_CODING_CS2; }
1096 case (CS3_lqual_dB_range) { ch_coding := CH_CODING_CS3; }
1097 case (CS4_lqual_dB_range) { ch_coding := CH_CODING_CS4; }
1098 }
1099
1100 if (not match(dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd, ch_coding)) {
1101 setverdict(fail, "Channel Coding does not match our expectations: ", ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001102 }
1103 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001104
1105 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001106}
1107
1108/* Test the max UL CS set by VTY works fine */
1109testcase TC_cs_initial_ul() runs on RAW_PCU_Test_CT {
1110 var GsmRrMessage rr_imm_ass;
1111 var PacketUlAssign ul_tbf_ass;
1112 var RlcmacDlBlock dl_block;
1113 var boolean ok;
1114 var integer lqual_cb;
1115 var ChCodingCommand last_ch_coding;
1116 var uint32_t unused_fn;
1117
1118 /* Initialize the PCU interface abstraction */
1119 f_init_raw(testcasename());
1120
1121 /* Set initial UL CS to 3 */
1122 g_cs_initial_ul := 3;
1123 f_pcuvty_set_allowed_cs_mcs();
1124 f_pcuvty_set_link_quality_ranges();
1125
1126 /* Take lqual (dB->cB) so that we stay in that CS */
1127 lqual_cb := g_cs_lqual_ranges[2].low * 10;
1128
1129 /* Establish an Uplink TBF */
1130 ok := f_establish_tbf(rr_imm_ass);
1131 if (not ok) {
1132 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001133 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001134 }
1135
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001136 /* Make sure we've got an Uplink TBF assignment */
1137 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001138
1139 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1140 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1141 cv := 3, /* 8 UL blocks to be sent (to be overridden in loop) */
1142 bsn := 0, /* TODO: what should be here? */
1143 blocks := { /* To be generated in loop */ });
1144
1145 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1146 ul_data.data.tlli := '00000001'O;
1147
1148 /* 3 UL blocks, check we are in same initial CS: */
1149 for (var integer i := 0; i < 3; i := i + 1) {
1150 /* Prepare a new UL block (CV, random payload) */
1151 ul_data.data.mac_hdr.countdown := (7 - i);
1152 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1153
1154 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1155 f_tx_rlcmac_ul_block(ul_data, lqual_cb);
1156
1157 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1158 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1159 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1160 }
1161
1162 if (last_ch_coding != CH_CODING_CS3) {
1163 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001164 }
1165
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001166 /* Remaining UL blocks are used to make sure regardless of initial
1167 /* lqual, we can go lower at any time */
1168
1169 /* 5 UL blocks, check we are in same initial CS: */
1170 for (var integer i := 3; i < 8; i := i + 1) {
1171 /* Prepare a new UL block (CV, random payload) */
1172 ul_data.data.mac_hdr.countdown := (7 - i);
1173 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1174
1175 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1176 f_tx_rlcmac_ul_block(ul_data, 0); /* 0 dB, make sure we downgrade CS */
1177
1178 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1179 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1180
1181 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1182 }
1183
1184 if (last_ch_coding != CH_CODING_CS1) {
1185 setverdict(fail, "Channel Coding does not match our expectations (CS-1): ", last_ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001186 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001187
1188 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001189}
1190
1191/* Test the max UL CS set by VTY works fine */
1192testcase TC_cs_max_ul() runs on RAW_PCU_Test_CT {
1193 var GsmRrMessage rr_imm_ass;
1194 var PacketUlAssign ul_tbf_ass;
1195 var RlcmacDlBlock dl_block;
1196 var boolean ok;
1197 var ChCodingCommand last_ch_coding;
1198 var uint32_t unused_fn;
1199
1200 /* Initialize the PCU interface abstraction */
1201 f_init_raw(testcasename());
1202
1203 /* Set maximum allowed UL CS to 3 */
1204 g_cs_max_ul := 3;
1205 f_pcuvty_set_allowed_cs_mcs();
1206 f_pcuvty_set_link_quality_ranges();
1207
1208 /* Establish an Uplink TBF */
1209 ok := f_establish_tbf(rr_imm_ass);
1210 if (not ok) {
1211 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001212 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001213 }
1214
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001215 /* Make sure we've got an Uplink TBF assignment */
1216 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001217
1218 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1219 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1220 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
1221 bsn := 0, /* TODO: what should be here? */
1222 blocks := { /* To be generated in loop */ });
1223
1224 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1225 ul_data.data.tlli := '00000001'O;
1226
1227 /* 16 UL blocks */
1228 for (var integer i := 0; i < 16; i := i + 1) {
1229 /* Prepare a new UL block (CV, random payload) */
1230 ul_data.data.mac_hdr.countdown := (15 - i);
1231 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1232
1233 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1234 f_tx_rlcmac_ul_block(ul_data, 40*10); /* 40 dB */
1235
1236 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
1237 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1238
1239 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1240 }
1241
1242 if (last_ch_coding != CH_CODING_CS3) {
1243 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001244 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001245
1246 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001247}
1248
1249/* Verify PCU drops TBF after some time of inactivity. */
1250testcase TC_t3169() runs on RAW_PCU_Test_CT {
1251 var PCUIF_info_ind info_ind;
1252 var GsmRrMessage rr_imm_ass;
1253 var PacketUlAssign ul_tbf_ass;
1254 var RlcmacDlBlock dl_block;
1255 var PCUIF_Message pcu_msg;
1256 var octetstring data;
1257 var boolean ok;
1258 var uint32_t unused_fn;
1259 var OCT4 tlli := '00000001'O;
1260
1261 /* Initialize NS/BSSGP side */
1262 f_init_bssgp();
1263
1264 info_ind := valueof(ts_PCUIF_INFO_default);
1265 /* Set timer to 1 sec (default 5) to speedup test: */
1266 info_ind.t3169 := 1;
1267
1268 /* Initialize the PCU interface abstraction */
1269 f_init_raw(testcasename(), info_ind);
1270
1271 /* Establish BSSGP connection to the PCU */
1272 f_bssgp_establish();
1273 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1274
1275 /* Establish an Uplink TBF */
1276 ok := f_establish_tbf(rr_imm_ass);
1277 if (not ok) {
1278 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001279 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001280 }
1281
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001282 /* Make sure we've got an Uplink TBF assignment */
1283 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001284
1285 /* Send one UL block and make sure it is ACKED fine */
1286 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1287 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
1288 /* UL block should be received in SGSN */
1289 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1290
1291 /* Wait until T3169 fires (plus 1 extra sec to make sure) */
1292 f_sleep(int2float(info_ind.t3169) + 1.0);
1293
1294 /* Send an UL block once again, the TBF should be gone by now so no ACK */
1295 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1296 f_rx_rlcmac_dl_block_exp_dummy(dl_block);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001297
1298 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001299}
1300
1301/* Verify that a Downlink TBF can be assigned using PACCH shortly after the
1302 * release of prev DL TBF due to MS staying in PDCH for a while (T3192, in PCU
1303 * T3193) after DL TBF release */
1304testcase TC_t3193() runs on RAW_PCU_Test_CT {
1305 var GsmRrMessage rr_imm_ass;
1306 var PacketDlAssign dl_tbf_ass;
1307 var RlcmacDlBlock dl_block;
1308 var octetstring data := f_rnd_octstring(10);
1309 var boolean ok;
1310 var uint32_t sched_fn;
1311 var OCT4 tlli := '00000001'O;
1312 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1313
1314 /* Initialize NS/BSSGP side */
1315 f_init_bssgp();
1316
1317 /* Initialize the PCU interface abstraction */
1318 f_init_raw(testcasename());
1319
1320 /* Establish BSSGP connection to the PCU */
1321 f_bssgp_establish();
1322 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1323
1324 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1325 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1326 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001327
1328 /* Make sure we've got a Downlink TBF assignment */
1329 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1330
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001331 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1332 f_sleep(X2002);
1333 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1334
1335 /* ACK the DL block */
1336 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
1337 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc), 0, sched_fn);
1338 /* we are done with the DL-TBF here so far, let's clean up our local state: */
1339 ack_nack_desc := valueof(t_AckNackDescription_init)
1340
1341 /* Now that final DL block is ACKED and TBF is released, T3193 in PCU
1342 (T3192 in MS) was started and until it fires the MS will be abailable
1343 on PDCH in case new data arrives from SGSN. Let's verify it: */
1344 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1345 f_rx_rlcmac_dl_block_exp_pkt_ass(dl_block, sched_fn);
1346 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1347
1348 /* Now that we confirmed the new assignment in the dl-tbf, lets receive the data and ack it */
1349 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1350 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
1351 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc), 0, sched_fn);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001352
1353 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001354}
1355
1356/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1357 * answered, so TBFs for uplink and later for downlink are created.
1358 */
1359private function f_TC_mo_ping_pong(template (omit) MSRadioAccessCapabilityV ms_racap := omit, template (present) CodingScheme exp_cs_mcs := ?) runs on RAW_PCU_Test_CT {
1360 var GsmRrMessage rr_imm_ass;
1361 var PacketUlAssign ul_tbf_ass;
1362 var PacketDlAssign dl_tbf_ass;
1363 var RlcmacDlBlock dl_block;
1364 var PCUIF_Message pcu_msg;
1365 var octetstring data := f_rnd_octstring(10);
1366 var boolean ok;
1367 var uint32_t sched_fn;
1368 var OCT4 tlli := '00000001'O;
1369 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1370
1371 /* Initialize NS/BSSGP side */
1372 f_init_bssgp();
1373
1374 /* Initialize the PCU interface abstraction */
1375 f_init_raw(testcasename());
1376
1377 /* Establish BSSGP connection to the PCU */
1378 f_bssgp_establish();
1379 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1380
1381 /* Establish an Uplink TBF */
1382 ok := f_establish_tbf(rr_imm_ass);
1383 if (not ok) {
1384 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001385 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001386 }
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001387
1388 /* Make sure we've got an Uplink TBF assignment */
1389 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001390
1391 if (not istemplatekind(ms_racap, "omit")) {
1392 /* Send PACKET RESOURCE REQUEST to upgrade to EGPRS
1393 * (see 3GPP TS 04.60 "7.1.3.1 Initiation of the Packet resource request procedure")
1394 */
1395 f_tx_rlcmac_ul_block(ts_RLC_UL_CTRL_ACK(valueof(ts_RlcMacUlCtrl_PKT_RES_REQ(tlli, ms_racap))), 0);
1396 f_rx_rlcmac_dl_block_exp_pkt_ul_ass(dl_block, sched_fn);
1397 if (dl_block.ctrl.payload.u.ul_assignment.identity.tlli.tlli != tlli) {
1398 setverdict(fail, "Wrong TLLI ", dl_block.ctrl.payload.u.ul_assignment.identity.tlli, " received vs exp ", tlli);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001399 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001400 }
1401 }
1402
1403 /* Send one UL block and make sure it is ACKED fine */
1404 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1405 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1406 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1407 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1408
1409 /* UL block should be received in SGSN */
1410 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1411
1412 /* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
1413 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1414 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1415
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001416 /* Make sure we've got a Downlink TBF assignment */
1417 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001418
1419 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1420 f_sleep(X2002);
1421 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0, exp_cs_mcs);
1422
1423 /* ACK the DL block */
1424 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
1425 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc), 0, sched_fn);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001426
1427 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001428}
1429
1430/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1431 * answered, so TBFs for uplink and later for downlink are created.
1432 */
1433testcase TC_mo_ping_pong() runs on RAW_PCU_Test_CT {
1434 var CodingScheme exp_cs_mcs := CS_1;
1435 f_TC_mo_ping_pong(omit, exp_cs_mcs);
1436}
1437
1438
1439testcase TC_mo_ping_pong_with_ul_racap() runs on RAW_PCU_Test_CT {
1440 var MultislotCap_GPRS mscap_gprs := {
1441 gprsmultislotclass := '00011'B,
1442 gprsextendeddynalloccap := '0'B
1443 };
1444 var MSRadioAccessCapabilityV ms_racap := { valueof(ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs, omit)) };
1445 var CodingScheme exp_cs_mcs := CS_2;
1446
1447 f_TC_mo_ping_pong(ms_racap, exp_cs_mcs);
1448}
1449
1450/* Test scenario where SGSN wants to send some data against MS and it is
1451 * answered by the MS on PDCH, so TBFs for downlink and later for uplink are created.
1452 */
1453private 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 {
1454 var GsmRrMessage rr_imm_ass;
1455 var PacketUlAssign ul_tbf_ass;
1456 var PacketDlAssign dl_tbf_ass;
1457 var RlcmacDlBlock dl_block;
1458 var PCUIF_Message pcu_msg;
1459 var octetstring data := f_rnd_octstring(10);
1460 var boolean ok;
1461 var uint32_t sched_fn;
1462 var OCT4 tlli := '00000001'O;
1463 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1464
1465 /* Initialize NS/BSSGP side */
1466 f_init_bssgp();
1467
1468 /* Initialize the PCU interface abstraction */
1469 f_init_raw(testcasename());
1470
1471 /* Establish BSSGP connection to the PCU */
1472 f_bssgp_establish();
1473 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1474
1475 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1476 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data, ms_racap));
1477 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1478
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001479 /* Make sure we've got a Downlink TBF assignment */
1480 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001481
1482 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1483 f_sleep(X2002);
1484 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0, exp_cs_mcs);
1485
1486 /* ACK the DL block */
1487 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
1488 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc), 0, sched_fn);
1489
1490 /* Now MS wants to answer the DL data, Establish an Uplink TBF */
1491 ok := f_establish_tbf(rr_imm_ass);
1492 if (not ok) {
1493 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001494 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001495 }
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001496
1497 /* Make sure we've got an Uplink TBF assignment */
1498 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001499
1500 /* Send one UL block and make sure it is ACKED fine */
1501 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1502 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1503 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1504 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1505
1506 /* UL block should be received in SGSN */
1507 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001508
1509 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001510}
1511
1512testcase TC_mt_ping_pong() runs on RAW_PCU_Test_CT {
1513 var CodingScheme exp_cs_mcs := CS_1;
1514 f_TC_mt_ping_pong(omit, exp_cs_mcs);
1515}
1516
1517/* TC_mt_ping_pong, but DL-UNITDATA contains RA Access capability with (M)CS
1518/* information about the MS */
1519testcase TC_mt_ping_pong_with_dl_racap() runs on RAW_PCU_Test_CT {
1520 var MultislotCap_GPRS_BSSGP mscap_gprs := {
1521 gprsmultislotclass := '00011'B,
1522 gprsextendeddynalloccap := '0'B
1523 } ;
1524 var MSRadioAccessCapabilityV_BSSGP ms_racap := { valueof(ts_RaCapRec_BSSGP('0001'B /* E-GSM */, mscap_gprs, omit)) };
1525 var CodingScheme exp_cs_mcs := CS_2;
1526 f_TC_mt_ping_pong(ms_racap, exp_cs_mcs);
1527}
1528
1529/* Verify that if PCU doesn't get an ACK for first DL block after IMM ASS, it
1530 * will retry by retransmitting both the IMM ASS + DL block after poll (ack)
1531 * timeout occurs (specified by sent RRBP on DL block). */
1532testcase TC_imm_ass_dl_block_retrans() runs on RAW_PCU_Test_CT {
1533 var GsmRrMessage rr_imm_ass;
1534 var PacketDlAssign dl_tbf_ass;
1535 var RlcmacDlBlock dl_block;
1536 var octetstring data := f_rnd_octstring(10);
1537 var boolean ok;
1538 var uint32_t sched_fn;
1539 var OCT4 tlli := '00000001'O;
1540 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1541
1542 /* Initialize NS/BSSGP side */
1543 f_init_bssgp();
1544
1545 /* Initialize the PCU interface abstraction */
1546 f_init_raw(testcasename());
1547
1548 /* Establish BSSGP connection to the PCU */
1549 f_bssgp_establish();
1550 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1551
1552 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1553 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1554 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001555
1556 /* Make sure we've got a Downlink TBF assignment */
1557 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001558
1559 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1560 f_sleep(X2002);
1561 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1562
1563 /* Now we don't ack the dl block (emulate MS failed receiveing IMM ASS
1564 * or GPRS DL, or DL ACK was lost for some reason). As a result, PCU
1565 * should retrigger IMM ASS + GPRS DL procedure after poll timeout. */
1566 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001567
1568 /* Make sure we've got a Downlink TBF assignment */
1569 f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1570
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001571 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1572 f_sleep(X2002);
1573 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1574
1575 /* ACK the DL block */
1576 f_acknackdesc_ack_block(ack_nack_desc, dl_block, '1'B);
1577 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(f_rlcmac_dl_block_get_tfi(dl_block), ack_nack_desc), 0, sched_fn);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001578
1579 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001580}
1581
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001582private function f_pkt_paging_match_imsi(in PacketPagingReq req, hexstring imsi)
1583runs on RAW_PCU_Test_CT {
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001584 var MobileIdentityLV_Paging mi_lv := req.repeated_pageinfo.cs.mobile_identity;
1585 var MobileIdentityV mi := dec_MobileIdentityV(mi_lv.mobile_id);
1586
1587 if (mi_lv.len != 8) { /* 8 octets: type of ID (3 bits) + even/odd flag (1 bit) + 15 BCD-encoded digits (60 bits) */
1588 setverdict(fail, "Mobile Identity length mismatch: ",
1589 "expected: 8, got: ", mi_lv.len);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001590 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001591 }
1592
1593 /* Make sure MI contains IMSI before referencing it */
1594 if (mi.typeOfIdentity != '001'B) {
1595 setverdict(fail, "Mobile Identity must be of type IMSI ('001'B), ",
1596 "got: ", mi.typeOfIdentity);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001597 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001598 } else if (mi.oddEvenInd_identity.imsi.digits != imsi) {
1599 setverdict(fail, "Mobile Identity contains unexpected IMSI, ",
1600 "expected: ", imsi, " got: ", mi.oddEvenInd_identity.imsi.digits);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001601 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001602 }
1603}
1604
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001605private function f_pkt_paging_match_tmsi(in PacketPagingReq req, template GsmTmsi tmsi)
1606runs on RAW_PCU_Test_CT {
1607 var MobileIdentityLV_Paging mi_lv := req.repeated_pageinfo.cs.mobile_identity;
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001608 if (not match(req.repeated_pageinfo.cs.tmsi, tmsi)) {
1609 setverdict(fail, "Mobile Identity (TMSI/P-TMSI) mismatch: ",
1610 "expected: ", tmsi, "got: ", req.repeated_pageinfo.cs.tmsi);
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001611 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001612 }
1613}
1614
1615/* Test CS paging over the BTS<->PCU socket.
1616 * 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.
1617 * Paging should be send on the PACCH.
1618 *
1619 * 1. Send a Paging Request over PCU socket.
1620 * 2. Send a Ready-To-Send message over PCU socket
1621 * 3. Expect a Paging Frame
1622 */
1623testcase TC_paging_cs_from_bts() runs on RAW_PCU_Test_CT {
1624 var GsmRrMessage rr_imm_ass;
1625 var PacketUlAssign ul_tbf_ass;
1626 var RlcmacDlBlock dl_block;
1627 var boolean ok;
1628 var OCT4 tlli := '00000001'O;
1629 var MobileIdentityLV mi;
1630 var octetstring mi_enc_lv;
1631 var hexstring imsi := f_gen_imsi(42);
1632
1633 /* Initialize NS/BSSGP side */
1634 f_init_bssgp();
1635
1636 /* Initialize the PCU interface abstraction */
1637 f_init_raw(testcasename());
1638
1639 /* Establish BSSGP connection to the PCU */
1640 f_bssgp_establish();
1641 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1642
1643 /* Establish an Uplink TBF */
1644 ok := f_establish_tbf(rr_imm_ass);
1645 if (not ok) {
1646 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001647 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001648 }
1649
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001650 /* Make sure we've got an Uplink TBF assignment */
1651 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001652
1653 /* build mobile Identity */
1654 mi := valueof(ts_MI_IMSI_LV(imsi));
1655 mi_enc_lv := enc_MobileIdentityLV(mi);
1656 /* Send paging request */
1657 BTS.send(ts_PCUIF_PAG_REQ(bts_nr := 0, id_lv := mi_enc_lv, chan_needed := 0,
1658 sapi :=PCU_IF_SAPI_PDTCH));
1659
1660 /* Receive it on BTS side towards MS */
1661 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
1662
1663 /* Make sure that Packet Paging Request contains the same IMSI */
1664 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1665
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001666 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001667}
1668
1669/* Test CS paging over Gb (SGSN->PCU->BTS[PDCH]).
1670 */
1671private function f_tc_paging_cs_from_sgsn(Nsvci bvci, boolean use_ptmsi := false)
1672runs on RAW_PCU_Test_CT {
1673 var GsmRrMessage rr_imm_ass;
1674 var PacketUlAssign ul_tbf_ass;
1675 var RlcmacDlBlock dl_block;
1676 var boolean ok;
1677 var OCT4 tlli := '00000001'O;
1678 var hexstring imsi := f_gen_imsi(42);
1679 var GsmTmsi tmsi;
1680
1681 /* Initialize NS/BSSGP side */
1682 f_init_bssgp();
1683
1684 /* Initialize the PCU interface abstraction */
1685 f_init_raw(testcasename());
1686
1687 /* Establish BSSGP connection to the PCU */
1688 f_bssgp_establish();
1689 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1690
1691 /* Establish an Uplink TBF */
1692 ok := f_establish_tbf(rr_imm_ass);
1693 if (not ok) {
1694 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001695 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001696 }
1697
Vadim Yanitskiy2e213ae2020-05-06 22:26:17 +07001698 /* Make sure we've got an Uplink TBF assignment */
1699 f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001700
1701 /* Send paging request with or without TMSI */
1702 if (use_ptmsi) {
1703 tmsi := oct2int(f_rnd_octstring(4)); /* Random P-TMSI */
1704 BSSGP[0].send(ts_BSSGP_CS_PAGING_PTMSI(bvci, imsi, tmsi));
1705 } else {
1706 BSSGP[0].send(ts_BSSGP_CS_PAGING_IMSI(bvci, imsi));
1707 }
1708
1709 /* Receive it on BTS side towards MS */
1710 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
1711
1712 /* Make sure that Packet Paging Request contains the same P-TMSI/IMSI */
1713 if (use_ptmsi) {
1714 f_pkt_paging_match_tmsi(dl_block.ctrl.payload.u.paging, tmsi);
1715 } else {
1716 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1717 }
1718
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001719 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001720}
1721
1722testcase TC_paging_cs_from_sgsn_sign_ptmsi() runs on RAW_PCU_Test_CT {
1723 f_tc_paging_cs_from_sgsn(0, true);
1724}
1725
1726testcase TC_paging_cs_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1727 f_tc_paging_cs_from_sgsn(0);
1728}
1729
1730testcase TC_paging_cs_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1731 f_tc_paging_cs_from_sgsn(mp_gb_cfg.bvci);
1732}
1733
1734/* Test PS paging over Gb (SGSN->PCU->BTS[CCCH]).
1735 */
1736private function f_tc_paging_ps_from_sgsn(Nsvci bvci, boolean use_ptmsi := false)
1737runs on RAW_PCU_Test_CT {
1738 var OCT4 tlli := '00000001'O;
1739 var integer imsi_suff_tx := 423;
1740 var hexstring imsi := f_gen_imsi(imsi_suff_tx);
1741
1742 /* Initialize NS/BSSGP side */
1743 f_init_bssgp();
1744
1745 /* Initialize the PCU interface abstraction */
1746 f_init_raw(testcasename());
1747
1748 /* Establish BSSGP connection to the PCU */
1749 f_bssgp_establish();
1750 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1751
1752 /* Send BSSGP PAGING-PS (with or without TMSI), wait for RR Paging Request Type 1.
1753 * Make sure that both paging group (IMSI suffix) and Mobile Identity match. */
1754 if (use_ptmsi) {
1755 var OCT4 tmsi := f_rnd_octstring(4); /* Random P-TMSI */
1756 BSSGP[0].send(ts_BSSGP_PS_PAGING_PTMSI(bvci, imsi, oct2int(tmsi)));
1757 f_pcuif_rx_pch_pag_req1(t_MI_TMSI(tmsi), imsi_suff_tx);
1758 } else {
1759 BSSGP[0].send(ts_BSSGP_PS_PAGING_IMSI(bvci, imsi));
1760 f_pcuif_rx_pch_pag_req1(tr_MI_IMSI(imsi), imsi_suff_tx);
1761 }
1762
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001763 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001764}
1765
1766testcase TC_paging_ps_from_sgsn_sign_ptmsi() runs on RAW_PCU_Test_CT {
1767 f_tc_paging_ps_from_sgsn(0, true);
1768}
1769
1770testcase TC_paging_ps_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1771 f_tc_paging_ps_from_sgsn(0);
1772}
1773
1774testcase TC_paging_ps_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1775 f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvci);
1776}
1777
1778private function f_TC_egprs_pkt_chan_req(in EGPRSPktChRequest req,
1779 template GsmRrMessage t_imm_ass := ?,
1780 PCUIF_BurstType bt := BURST_TYPE_1)
1781runs on RAW_PCU_Test_CT {
1782 var GsmRrMessage rr_msg;
1783 var uint16_t ra11;
1784 var boolean ok;
1785
1786 ra11 := enc_EGPRSPktChRequest2uint(req);
1787 log("Sending EGPRS Packet Channel Request (", ra11, "): ", req);
1788
1789 ok := f_establish_tbf(rr_msg, ra := ra11, is_11bit := 1, burst_type := bt);
1790 if (not ok) {
1791 setverdict(fail, "Failed to establush an Uplink TBF");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001792 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001793 }
1794
1795 if (not match(rr_msg, t_imm_ass)) {
1796 setverdict(fail, "Immediate Assignment does not match");
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001797 f_shutdown(__BFILE__, __LINE__);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001798 }
1799
1800 setverdict(pass);
1801}
1802
1803testcase TC_egprs_pkt_chan_req_signalling() runs on RAW_PCU_Test_CT {
1804 var template GsmRrMessage imm_ass;
1805 var template IaRestOctets rest;
1806 var template EgprsUlAss ul_ass;
1807
1808 /* Initialize the PCU interface abstraction */
1809 f_init_raw(testcasename());
1810
1811 var EGPRSPktChRequest req := {
1812 /* NOTE: other fields are set in the loop */
1813 signalling := { tag := '110011'B }
1814 };
1815
1816 for (var integer i := 0; i < 6; i := i + 1) {
1817 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
1818 req.signalling.random_bits := ext_ra;
1819
1820 /* For signalling, do we expect Multiblock UL TBF Assignment? */
1821 ul_ass := tr_EgprsUlAssMultiblock(ext_ra := ext_ra);
1822 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
1823 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
1824
1825 f_TC_egprs_pkt_chan_req(req, imm_ass);
1826 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001827
1828 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001829}
1830
1831testcase TC_egprs_pkt_chan_req_one_phase() runs on RAW_PCU_Test_CT {
1832 var template GsmRrMessage imm_ass;
1833 var template IaRestOctets rest;
1834 var template EgprsUlAss ul_ass;
1835
1836 /* Initialize the PCU interface abstraction */
1837 f_init_raw(testcasename());
1838
1839 var EGPRSPktChRequest req := {
1840 /* NOTE: other fields are set in the loop */
1841 one_phase := { tag := '0'B }
1842 };
1843
1844 for (var integer i := 0; i < 6; i := i + 1) {
1845 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
1846 var BIT5 mslot_class := int2bit(f_rnd_int(32), 5);
1847 var BIT2 priority := substr(ext_ra, 0, 2);
1848 var BIT3 rand := substr(ext_ra, 2, 3);
1849
1850 req.one_phase.multislot_class := mslot_class;
1851 req.one_phase.priority := priority;
1852 req.one_phase.random_bits := rand;
1853
1854 /* For one phase access, do we expect Dynamic UL TBF Assignment? */
1855 ul_ass := tr_EgprsUlAssDynamic(ext_ra := ext_ra);
1856 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
1857 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
1858
1859 f_TC_egprs_pkt_chan_req(req, imm_ass);
1860 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001861
1862 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001863}
1864
1865testcase TC_egprs_pkt_chan_req_two_phase() runs on RAW_PCU_Test_CT {
1866 var template GsmRrMessage imm_ass;
1867 var template IaRestOctets rest;
1868 var template EgprsUlAss ul_ass;
1869
1870 /* Initialize the PCU interface abstraction */
1871 f_init_raw(testcasename());
1872
1873 var EGPRSPktChRequest req := {
1874 /* NOTE: other fields are set in the loop */
1875 two_phase := { tag := '110000'B }
1876 };
1877
1878 for (var integer i := 0; i < 6; i := i + 1) {
1879 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
1880 var BIT2 priority := substr(ext_ra, 0, 2);
1881 var BIT3 rand := substr(ext_ra, 2, 3);
1882
1883 req.two_phase.priority := priority;
1884 req.two_phase.random_bits := rand;
1885
1886 /* For two phase access, do we expect Multiblock UL TBF Assignment? */
1887 ul_ass := tr_EgprsUlAssMultiblock(ext_ra := ext_ra);
1888 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
1889 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
1890
1891 f_TC_egprs_pkt_chan_req(req, imm_ass);
1892 }
Vadim Yanitskiy91f8a092020-05-06 21:41:05 +07001893
1894 f_shutdown(__BFILE__, __LINE__, final := true);
Pau Espin Pedrol8dd59fb2020-04-29 15:08:16 +02001895}
1896
1897control {
1898 execute( TC_pcuif_suspend() );
1899 execute( TC_ta_ptcch_idle() );
1900 execute( TC_ta_rach_imm_ass() );
1901 execute( TC_ta_idle_dl_tbf_ass() );
1902 execute( TC_ta_ptcch_ul_multi_tbf() );
1903 execute( TC_cs_lqual_ul_tbf() );
1904 execute( TC_cs_initial_ul() );
1905 execute( TC_cs_max_ul() );
1906 execute( TC_t3169() );
1907 execute( TC_t3193() );
1908 execute( TC_mo_ping_pong() );
1909 execute( TC_mo_ping_pong_with_ul_racap() );
1910 execute( TC_mt_ping_pong() );
1911 execute( TC_mt_ping_pong_with_dl_racap() );
1912 execute( TC_imm_ass_dl_block_retrans() );
1913 execute( TC_paging_cs_from_bts() );
1914 execute( TC_paging_cs_from_sgsn_sign_ptmsi() );
1915 execute( TC_paging_cs_from_sgsn_sign() );
1916 execute( TC_paging_cs_from_sgsn_ptp() );
1917 execute( TC_paging_ps_from_sgsn_sign_ptmsi() );
1918 execute( TC_paging_ps_from_sgsn_sign() );
1919 execute( TC_paging_ps_from_sgsn_ptp() );
1920
1921 /* EGPRS specific test cases */
1922 execute( TC_egprs_pkt_chan_req_signalling() );
1923 execute( TC_egprs_pkt_chan_req_one_phase() );
1924 execute( TC_egprs_pkt_chan_req_two_phase() );
1925}
1926
1927
1928
1929
1930
1931
Harald Weltea419df22019-03-21 17:23:04 +01001932}