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