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