blob: 54412e34faa2281d48126977d06d2085909b37fe [file] [log] [blame]
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001module PCU_Tests_RAW {
2
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
Harald Welte34b5a952019-05-27 11:54:11 +02009/* (C) 2018-2019 Harald Welte <laforge@gnumonks.org>
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +020010 * (C) 2019 Vadim Yanitskiy <axilirator@gmail.com>
Harald Welte34b5a952019-05-27 11:54:11 +020011 * 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
Pau Espin Pedrol4536c822019-12-30 13:22:32 +010019friend module PCU_Tests_RAW_NS;
20
Harald Welte9fbcf4b2018-12-07 07:56:52 +010021import from General_Types all;
22import from Osmocom_Types all;
Harald Welte7fd25cf2019-03-21 22:14:02 +010023import from GSM_Types all;
24import from GSM_RR_Types all;
25
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +010026import from Osmocom_VTY_Functions all;
27import from TELNETasp_PortType all;
28
Pau Espin Pedrol8f245712020-04-24 18:47:30 +020029import from MobileL3_GMM_SM_Types all;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +020030import from RLCMAC_CSN1_Types all;
31import from RLCMAC_Types all;
32
Oliver Smith8f9daab2019-10-09 09:27:19 +020033import from MobileL3_CommonIE_Types all;
34import from L3_Templates all;
35
Harald Welte9fbcf4b2018-12-07 07:56:52 +010036import from NS_Types all;
37import from BSSGP_Types all;
38import from Osmocom_Gb_Types all;
39
40import from BSSGP_Emulation all; /* BssgpConfig */
41import from NS_Emulation all; /* NSConfiguration */
42
43import from UD_Types all;
44import from PCUIF_Types all;
45import from PCUIF_CodecPort all;
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +020046import from PCUIF_RAW_Components all;
Harald Welte9fbcf4b2018-12-07 07:56:52 +010047import from IPL4asp_Types all;
Harald Welte9fbcf4b2018-12-07 07:56:52 +010048import from Native_Functions all;
49import from PCU_Tests all;
50
51modulepar {
52 charstring mp_pcu_sock_path := PCU_SOCK_DEFAULT;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +010053
54 float X2002 := 0.2; /* Timer -2002, IMM ASSIGN confirm delay */
Harald Welte9fbcf4b2018-12-07 07:56:52 +010055}
56
Harald Welte9fbcf4b2018-12-07 07:56:52 +010057
Pau Espin Pedrolf787b092019-10-04 18:34:05 +020058/* FIXME: make sure to use parameters from mp_gb_cfg.cell_id in the PCU INFO IND */
Pau Espin Pedrol4536c822019-12-30 13:22:32 +010059private template (value) PCUIF_info_ind ts_PCUIF_INFO_default := {
Pau Espin Pedrolf787b092019-10-04 18:34:05 +020060 version := PCU_IF_VERSION,
61 flags := c_PCUIF_Flags_default,
62 trx := valueof(ts_PCUIF_InfoTrxs_def),
63 bsic := 7,
64 mcc := 262,
65 mnc := 42,
66 mnc_3_digits := 0,
67 lac := 13135,
68 rac := 0,
69 nsei := mp_nsconfig.nsei,
70 nse_timer := { 3, 3, 3, 3, 30, 3, 10 },
71 cell_timer := { 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 },
72 cell_id := 20960,
73 repeat_time := 5 * 50,
74 repeat_count := 3,
75 bvci := mp_gb_cfg.bvci,
76 t3142 := 20,
77 t3169 := 5,
78 t3191 := 5,
79 t3193_10ms := 160,
80 t3195 := 5,
81 t3101 := 10,
82 t3103 := 4,
83 t3105 := 8,
84 cv_countdown := 15,
85 dl_tbf_ext := 250 * 10, /* ms */
86 ul_tbf_ext := 250 * 10, /* ms */
87 initial_cs := 2,
88 initial_mcs := 6,
89 nsvci := { mp_nsconfig.nsvci, 0 },
90 local_pprt := { mp_nsconfig.remote_udp_port, 0 },
91 remote_port := { mp_nsconfig.local_udp_port, 0 },
92 remote_ip := { f_inet_haddr(mp_nsconfig.local_ip) , '00000000'O }
93}
94
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +010095type record lqual_range {
96 /* component reference to the IPA_Client component used for RSL */
97 uint8_t low,
98 uint8_t high
99}
100
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200101type component RAW_PCU_Test_CT extends bssgp_CT {
102 /* Connection to the BTS component (one for now) */
103 port RAW_PCU_MSG_PT BTS;
104 /* Connection to the PCUIF component */
105 port RAW_PCU_MSG_PT PCUIF;
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100106 /* VTY connection to the PCU */
107 port TELNETasp_PT PCUVTY;
108
109 /* Uplink CS/MCS thresholds, default from pcu_main.c: */
110 var lqual_range g_cs_lqual_ranges[4] := {{low := 0, high := 6},
111 {low := 5, high := 8},
112 {low := 7, high := 13},
113 {low := 12,high := 35}};
114 var lqual_range g_mcs_lqual_ranges[9] := {{low := 0, high := 6},
115 {low := 5, high := 8},
116 {low := 7, high := 13},
117 {low := 12,high := 15},
118 {low := 14, high := 17},
119 {low := 16, high := 18},
120 {low := 17,high := 20},
121 {low := 19, high := 24},
122 {low := 23,high := 35}};
123 var uint8_t g_cs_initial_dl := 1;
124 var uint8_t g_cs_initial_ul := 1;
125 var uint8_t g_mcs_initial_dl := 1;
126 var uint8_t g_mcs_initial_ul := 1;
127 var uint8_t g_cs_max_dl := 4;
128 var uint8_t g_cs_max_ul := 4;
129 var uint8_t g_mcs_max_dl := 9;
130 var uint8_t g_mcs_max_ul := 9;
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200131
132 /* Guard timeout */
133 timer g_T_guard := 60.0;
134};
135
136private altstep as_Tguard_RAW() runs on RAW_PCU_Test_CT {
137 [] g_T_guard.timeout {
138 setverdict(fail, "Timeout of T_guard");
139 mtc.stop;
140 }
141}
142
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100143private function f_pcuvty_set_allowed_cs_mcs() runs on RAW_PCU_Test_CT {
144 f_vty_config2(PCUVTY, {"pcu"}, "cs " & int2str(g_cs_initial_dl) & " " & int2str(g_cs_initial_ul));
145 f_vty_config2(PCUVTY, {"pcu"}, "cs max " & int2str(g_cs_max_dl) & " " & int2str(g_cs_max_ul));
146
147 f_vty_config2(PCUVTY, {"pcu"}, "mcs " & int2str(g_mcs_initial_dl) & " " & int2str(g_mcs_initial_ul));
148 f_vty_config2(PCUVTY, {"pcu"}, "mcs max " & int2str(g_mcs_max_dl) & " " & int2str(g_mcs_max_ul));
149}
150
151private function f_pcuvty_set_link_quality_ranges() runs on RAW_PCU_Test_CT {
152 var charstring cmd;
153
154 cmd := "cs link-quality-ranges" &
155 " cs1 " & int2str(g_cs_lqual_ranges[0].high) &
156 " cs2 " & int2str(g_cs_lqual_ranges[1].low) & " " & int2str(g_cs_lqual_ranges[1].high) &
157 " cs3 " & int2str(g_cs_lqual_ranges[2].low) & " " & int2str(g_cs_lqual_ranges[2].high) &
158 " cs4 " & int2str(g_cs_lqual_ranges[3].low);
159 f_vty_config2(PCUVTY, {"pcu"}, cmd);
160
161 cmd := "mcs link-quality-ranges" &
162 " mcs1 " & int2str(g_mcs_lqual_ranges[0].high) &
163 " mcs2 " & int2str(g_mcs_lqual_ranges[1].low) & " " & int2str(g_mcs_lqual_ranges[1].high) &
164 " mcs3 " & int2str(g_mcs_lqual_ranges[2].low) & " " & int2str(g_mcs_lqual_ranges[2].high) &
165 " mcs4 " & int2str(g_mcs_lqual_ranges[3].low) & " " & int2str(g_mcs_lqual_ranges[3].high) &
166 " mcs5 " & int2str(g_mcs_lqual_ranges[4].low) & " " & int2str(g_mcs_lqual_ranges[4].high) &
167 " mcs6 " & int2str(g_mcs_lqual_ranges[5].low) & " " & int2str(g_mcs_lqual_ranges[5].high) &
168 " mcs7 " & int2str(g_mcs_lqual_ranges[6].low) & " " & int2str(g_mcs_lqual_ranges[6].high) &
169 " mcs8 " & int2str(g_mcs_lqual_ranges[7].low) & " " & int2str(g_mcs_lqual_ranges[7].high) &
170 " mcs9 " & int2str(g_mcs_lqual_ranges[8].low);
171 f_vty_config2(PCUVTY, {"pcu"}, cmd);
172}
173
174private function f_init_vty(charstring id) runs on RAW_PCU_Test_CT {
175 map(self:PCUVTY, system:PCUVTY);
176 f_vty_set_prompts(PCUVTY);
177 f_vty_transceive(PCUVTY, "enable");
178}
179
Pau Espin Pedrolf787b092019-10-04 18:34:05 +0200180private function f_init_raw(charstring id, template (value) PCUIF_info_ind info_ind := ts_PCUIF_INFO_default)
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200181runs on RAW_PCU_Test_CT {
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200182 var RAW_PCUIF_CT vc_PCUIF;
183 var RAW_PCU_BTS_CT vc_BTS;
184
185 /* Start the guard timer */
186 g_T_guard.start;
187 activate(as_Tguard_RAW());
188
189 /* Init PCU interface component */
190 vc_PCUIF := RAW_PCUIF_CT.create("PCUIF-" & id);
191 connect(vc_PCUIF:MTC, self:PCUIF);
192 map(vc_PCUIF:PCU, system:PCU);
193
194 /* Create one BTS component (we may want more some day) */
195 vc_BTS := RAW_PCU_BTS_CT.create("BTS-" & id);
196 connect(vc_BTS:PCUIF, vc_PCUIF:BTS);
197 connect(vc_BTS:TC, self:BTS);
198
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100199 f_init_vty(id);
200
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200201 vc_PCUIF.start(f_PCUIF_CT_handler(mp_pcu_sock_path));
Pau Espin Pedrolf787b092019-10-04 18:34:05 +0200202 vc_BTS.start(f_BTS_CT_handler(0, valueof(info_ind)));
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200203
204 /* Wait until the BTS is ready (SI13 negotiated) */
205 BTS.receive(tr_RAW_PCU_EV(BTS_EV_SI13_NEGO));
206}
207
Pau Espin Pedrol89486332019-12-05 14:05:46 +0100208template AckNackDescription t_AckNackDescription_init := {
209 final_ack := '0'B,
210 starting_seq_nr := 0,
211 receive_block_bitmap := '0000000000000000000000000000000000000000000000000000000000000000'B
212}
213
214/* TS 44.060 sec 12.3 Ack/Nack Description */
215private function f_acknackdesc_ack_block(inout AckNackDescription desc, uint7_t bsn, BIT1 final_ack := '0'B)
216{
217 var integer i;
218 var integer inc := bsn - desc.starting_seq_nr + 1;
219 /* Filling hole? */
220 if (bsn < desc.starting_seq_nr) {
221 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - (desc.starting_seq_nr - bsn)] := int2bit(1, 1);
222 return;
223 }
224
225 /* SSN is increased, and so RBB values need to be moved */
226 for (i := 0; i < lengthof(desc.receive_block_bitmap) - inc; i := i+1) {
227 desc.receive_block_bitmap[i] := desc.receive_block_bitmap[i + inc];
228 }
229 for (i := lengthof(desc.receive_block_bitmap) - inc; i < lengthof(desc.receive_block_bitmap) - 1; i := i+1) {
230 desc.receive_block_bitmap[i] := int2bit(0, 1);
231 }
232 /* Now we can set current bit and update SSN */
233 desc.starting_seq_nr := bsn + 1;
234 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - 1] := int2bit(1, 1);
235
236 /* Finally update the final_ack bit as requested: */
237 desc.final_ack := final_ack;
238}
239
Vadim Yanitskiy8ae978c2020-04-01 23:01:55 +0700240private function f_pcuif_rx_imm_ass(out GsmRrMessage rr_imm_ass,
241 template GsmRrMessage t_imm_ass := ?,
242 uint8_t bts_nr := 0)
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200243runs on RAW_PCU_Test_CT return boolean {
244 var PCUIF_Message pcu_msg;
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200245 timer T;
246
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200247 T.start(2.0);
248 alt {
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700249 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200250 sapi := PCU_IF_SAPI_AGCH, data := ?))
251 -> value pcu_msg {
252 rr_imm_ass := dec_GsmRrMessage(pcu_msg.u.data_req.data);
253 log("Rx Immediate Assignment: ", rr_imm_ass);
254
Vadim Yanitskiy8ae978c2020-04-01 23:01:55 +0700255 if (match(rr_imm_ass, t_imm_ass)) {
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200256 setverdict(pass);
257 return true;
258 }
259
260 /* Not for us? Wait for more. */
261 repeat;
262 }
263 [] BTS.receive { repeat; }
264 [] T.timeout {
265 setverdict(fail, "Timeout waiting for Immediate Assignment");
266 }
267 }
268
269 return false;
270}
271
Vadim Yanitskiy8ae978c2020-04-01 23:01:55 +0700272/* FIXME: properly encode RA (see TS 24.060, table 11.2.5.2) */
273private function f_establish_tbf(out GsmRrMessage rr_imm_ass, uint8_t bts_nr := 0,
274 uint16_t ra := oct2int('3A'O), uint8_t is_11bit := 0,
275 PCUIF_BurstType burst_type := BURST_TYPE_0,
276 TimingAdvance ta := 0)
277runs on RAW_PCU_Test_CT return boolean {
278 var uint32_t fn;
279
280 /* FIXME: ask the BTS component to give us the current TDMA fn */
281 fn := 1337 + ta;
282
283 /* Send RACH.ind */
284 log("Sending RACH.ind on fn=", fn, " with RA=", ra, ", TA=", ta);
285 BTS.send(ts_PCUIF_RACH_IND(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
286 ra := ra, is_11bit := is_11bit,
287 burst_type := burst_type,
288 fn := fn, arfcn := 871,
289 qta := ta * 4));
290
Vadim Yanitskiya0b47cf2020-04-02 01:50:18 +0700291 /* 3GPP TS 44.018, table 9.1.8.1, note 2b: Request Reference shall be set to 127
292 * when Immediate Assignment is triggered by EGPRS Packet Channel Request. Here
293 * we assume that 11 bit RA always contains EGPRS Packet Channel Request. */
294 if (is_11bit != 0) { ra := 127; }
295
Vadim Yanitskiy8ae978c2020-04-01 23:01:55 +0700296 /* Expect Immediate (TBF) Assignment on TS0/AGCH */
297 return f_pcuif_rx_imm_ass(rr_imm_ass, tr_IMM_TBF_ASS(?, ra, fn), bts_nr);
298}
299
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200300private function f_imm_ass_verify_ul_tbf_ass(GsmRrMessage rr_imm_ass, out PacketUlAssign ul_tbf_ass)
301runs on RAW_PCU_Test_CT return boolean {
302
303 /* Make sure we received an UL TBF Assignment */
304 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
305 ul_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
306 log("Rx Uplink TBF assignment: ", ul_tbf_ass);
307 setverdict(pass);
308 } else {
309 setverdict(fail, "Failed to match UL TBF Assignment");
310 return false;
311 }
312
313 /* Make sure we have got a TBF with Dynamic Block Allocation */
314 if (ul_tbf_ass.dynamic == omit) {
315 setverdict(fail, "Single Block Allocation is not handled by ", testcasename());
316 return false;
317 }
318
319 return true;
320}
321
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +0200322private function f_imm_ass_verify_dl_tbf_ass(GsmRrMessage rr_imm_ass, out PacketDlAssign dl_tbf_ass)
323runs on RAW_PCU_Test_CT return boolean {
324
325 /* Make sure we received a DL TBF Assignment */
326 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := true, rest := tr_IaRestOctets_DLAss(?)))) {
327 dl_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.dl;
328 log("Rx Downlink TBF assignment: ", dl_tbf_ass);
329 setverdict(pass);
330 } else {
331 setverdict(fail, "Failed to match DL TBF Assignment");
332 return false;
333 }
334
335 return true;
336}
337
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200338/* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100339private function f_pcuif_tx_data_ind(octetstring data, int16_t lqual_cb := 0, uint32_t fn := 0)
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200340runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100341 var template RAW_PCU_EventParam ev_param := {tdma_fn := ? };
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200342 BTS.send(ts_PCUIF_DATA_IND(bts_nr := 0, trx_nr := 0, ts_nr := 7, block_nr := 0,
343 sapi := PCU_IF_SAPI_PDTCH, data := data,
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100344 fn := fn, arfcn := 871, lqual_cb := lqual_cb));
345 if (fn != 0) {
346 ev_param := {tdma_fn := fn };
347 }
348 BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PDTCH_BLOCK_SENT, ev_param));
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200349}
350
351/* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
352private function f_pcuif_rx_data_req(out PCUIF_Message pcu_msg)
353runs on RAW_PCU_Test_CT {
354 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
355 sapi := PCU_IF_SAPI_PDTCH, fn := 0,
356 arfcn := 871, block_nr := 0));
357 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
358 sapi := PCU_IF_SAPI_PDTCH)) -> value pcu_msg;
359}
360
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +0200361/* Expect an Immediate Assignment (paging) from PCU on PCUIF on specified sapi. */
362private function f_pcuif_rx_pch_imm_tbf_ass(out GsmRrMessage rr_imm_ass)
363runs on RAW_PCU_Test_CT {
364 var PCUIF_Message pcu_msg;
365 var octetstring macblock;
366 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
367 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
368 /* First 3 bytes contain paging group: */
369 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
370 rr_imm_ass := dec_GsmRrMessage(macblock);
371 if (not match(rr_imm_ass, tr_IMM_TBF_ASS())) {
372 setverdict(fail, "Failed to match Immediate Assignment: ", rr_imm_ass);
373 mtc.stop;
374 }
375 BTS.send(ts_PCUIF_DATA_CNF(bts_nr := 0, trx_nr := 0, ts_nr := 0, block_nr := 0,
Pau Espin Pedrolf04ba542019-12-23 14:47:44 +0100376 fn := pcu_msg.u.data_req.fn, arfcn := 871, sapi := PCU_IF_SAPI_PCH, data := macblock));
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +0200377}
378
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100379/* Expect a Paging Request Type 1 from PCU on PCUIF on specified sapi. */
Vadim Yanitskiy9c513132020-03-28 04:33:07 +0700380private function f_pcuif_rx_pch_pag_req1(template MobileIdentityV mi1 := ?,
381 template integer pag_group := ?)
382runs on RAW_PCU_Test_CT return GsmRrMessage {
383 var GsmRrMessage rr_pag_req1;
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100384 var PCUIF_Message pcu_msg;
Pau Espin Pedrol925818a2020-01-02 14:06:51 +0100385 var octetstring imsi_suff_octstr;
Vadim Yanitskiy9c513132020-03-28 04:33:07 +0700386 var integer pag_group_rx;
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100387 var octetstring macblock;
Vadim Yanitskiy9c513132020-03-28 04:33:07 +0700388
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100389 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
390 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
Vadim Yanitskiy9c513132020-03-28 04:33:07 +0700391
Pau Espin Pedrol925818a2020-01-02 14:06:51 +0100392 /* First 3 bytes contain IMSI suffix to calculate paging group: */
393 imsi_suff_octstr := substr(pcu_msg.u.data_req.data, 0, 3);
Vadim Yanitskiy9c513132020-03-28 04:33:07 +0700394 pag_group_rx := str2int(oct2char(imsi_suff_octstr[0])) * 100 +
Pau Espin Pedrol925818a2020-01-02 14:06:51 +0100395 str2int(oct2char(imsi_suff_octstr[1])) * 10 +
396 str2int(oct2char(imsi_suff_octstr[2]));
397
Vadim Yanitskiy9c513132020-03-28 04:33:07 +0700398 /* Make sure we've got RR Paging Request Type 1 for a given MI */
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100399 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
400 rr_pag_req1 := dec_GsmRrMessage(macblock);
Vadim Yanitskiy9c513132020-03-28 04:33:07 +0700401 if (not match(rr_pag_req1, tr_PAG_REQ1(tr_MI_LV(mi1)))) {
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100402 setverdict(fail, "Failed to match Paging Request Type 1: ", rr_pag_req1);
403 mtc.stop;
404 }
Vadim Yanitskiy9c513132020-03-28 04:33:07 +0700405
406 /* Make sure that received paging froup matches the expected one */
407 if (not match(pag_group_rx, pag_group)) {
408 setverdict(fail, "Paging group", pag_group_rx, " does not match expected ", pag_group);
409 mtc.stop;
410 }
411
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100412 BTS.send(ts_PCUIF_DATA_CNF(bts_nr := 0, trx_nr := 0, ts_nr := 0, block_nr := 0,
413 fn := pcu_msg.u.data_req.fn, arfcn := 871, sapi := PCU_IF_SAPI_PCH, data := macblock));
Vadim Yanitskiy9c513132020-03-28 04:33:07 +0700414
415 return rr_pag_req1;
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100416}
417
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100418private function f_tx_rlcmac_ul_block(template (value) RlcmacUlBlock ul_data, int16_t lqual_cb := 0, uint32_t fn := 0)
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200419runs on RAW_PCU_Test_CT {
420 var octetstring data;
421 /* Encode the payload of DATA.ind */
422 data := enc_RlcmacUlBlock(valueof(ul_data));
423 data := f_pad_oct(data, 23, '00'O); /* CS-1 */
424
425 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100426 f_pcuif_tx_data_ind(data, lqual_cb, fn);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200427}
428
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200429private function f_tx_rlcmac_ul_n_blocks(PacketUlAssign ul_tbf_ass, integer num_blocks := 1)
430runs on RAW_PCU_Test_CT {
431 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
432 tfi := ul_tbf_ass.dynamic.tfi_assignment,
433 cv := num_blocks - 1, /* num UL blocks to be sent (to be overridden in loop) */
434 bsn := 0, /* TODO: what should be here? */
435 blocks := { /* To be generated in loop */ });
436
437 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
438 ul_data.data.tlli := '00000001'O;
439
440 for (var integer i := 0; i < num_blocks; i := i + 1) {
441 /* Prepare a new UL block (CV, random payload) */
442 ul_data.data.mac_hdr.countdown := (num_blocks - i - 1);
443 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
444 f_tx_rlcmac_ul_block(ul_data);
445 }
446}
447
Pau Espin Pedroldc9666f2020-03-18 20:30:16 +0100448private function f_rx_rlcmac_dl_block(out RlcmacDlBlock dl_block, out uint32_t dl_fn, template (present) CodingScheme exp_cs_mcs := ?)
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200449runs on RAW_PCU_Test_CT {
450 var PCUIF_Message pcu_msg;
451 f_pcuif_rx_data_req(pcu_msg);
452 dl_block := dec_RlcmacDlBlock(pcu_msg.u.data_req.data);
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100453 dl_fn := pcu_msg.u.data_req.fn;
Pau Espin Pedroldc9666f2020-03-18 20:30:16 +0100454
455 var integer len := lengthof(pcu_msg.u.data_req.data);
456 var CodingScheme cs_mcs := f_rlcmac_block_len2cs_mcs(len)
457 if (not match(f_rlcmac_block_len2cs_mcs(len), exp_cs_mcs)) {
458 setverdict(fail, "Failed to match Coding Scheme exp ", exp_cs_mcs, " vs ", cs_mcs, " (", len, ")");
459 mtc.stop;
460 }
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200461}
462
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100463private function f_rx_rlcmac_dl_block_exp_ack_nack(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200464runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100465 var uint32_t dl_fn;
466
467 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Pau Espin Pedrol21659632019-12-02 19:12:08 +0100468 if (not match(dl_block, tr_RLCMAC_UL_ACK_NACK(ul_tfi := ?, tlli := ?))) {
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200469 setverdict(fail, "Failed to match Packet Uplink ACK / NACK");
470 mtc.stop;
471 }
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100472
473 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200474}
475
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200476private function f_rx_rlcmac_dl_block_exp_dummy(out RlcmacDlBlock dl_block)
477runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100478 var uint32_t dl_fn;
479
480 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200481 if (not match(dl_block, tr_RLCMAC_DUMMY_CTRL())) {
482 setverdict(fail, "Failed to match Packet DUMMY DL");
483 mtc.stop;
484 }
485}
486
Pau Espin Pedrolff8da192019-12-05 17:23:58 +0100487private function f_rx_rlcmac_dl_block_exp_pkt_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
488runs on RAW_PCU_Test_CT {
489 var uint32_t dl_fn;
490
491 f_rx_rlcmac_dl_block(dl_block, dl_fn);
492 if (not match(dl_block, tr_RLCMAC_DL_PACKET_ASS())) {
493 setverdict(fail, "Failed to match Packet Downlink Assignment");
494 mtc.stop;
495 }
496
497 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
498}
499
Pau Espin Pedrol8f245712020-04-24 18:47:30 +0200500private function f_rx_rlcmac_dl_block_exp_pkt_ul_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
501runs on RAW_PCU_Test_CT {
502 var uint32_t dl_fn;
503
504 f_rx_rlcmac_dl_block(dl_block, dl_fn);
505 if (not match(dl_block, tr_RLCMAC_UL_PACKET_ASS())) {
506 setverdict(fail, "Failed to match Packet Uplink Assignment");
507 mtc.stop;
508 }
509
510 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
511}
512
513
Oliver Smith8f9daab2019-10-09 09:27:19 +0200514private function f_rx_rlcmac_dl_block_exp_pkt_pag_req(out RlcmacDlBlock dl_block)
515runs on RAW_PCU_Test_CT {
516 var uint32_t dl_fn;
517
518 f_rx_rlcmac_dl_block(dl_block, dl_fn);
519 if (not match(dl_block, tr_RLCMAC_PACKET_PAG_REQ())) {
520 setverdict(fail, "Failed to match Packet Paging Request: ", dl_block, " vs ", tr_RLCMAC_PACKET_PAG_REQ());
521 mtc.stop;
522 }
523}
524
Pau Espin Pedroldc9666f2020-03-18 20:30:16 +0100525private 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 := ?)
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100526runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100527 var PCUIF_Message pcu_msg;
528 var uint32_t dl_fn;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100529 var template RlcmacDlBlock dl_template := tr_RLCMAC_DATA_RRBP;
530 dl_template.data.blocks := ?;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100531
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100532 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100533 if (not match(dl_block, dl_template)) {
534 setverdict(fail, "Failed to match Packet data: ", dl_block, " vs ", dl_template);
535 mtc.stop;
536 }
Pau Espin Pedrol6e3b6892019-12-04 19:24:16 +0100537
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100538 ack_fn := dl_fn + f_rrbp_fn_delay(dl_block.data.mac_hdr.mac_hdr.rrbp);
539
Pau Espin Pedrol89486332019-12-05 14:05:46 +0100540 if (not match(dl_block.data.mac_hdr.hdr_ext.bsn, exp_bsn)) {
541 setverdict(fail, "DL block BSN doesn't match: ",
542 dl_block.data.blocks[0].hdr.length_ind, " vs exp ", exp_bsn);
543 }
544
Pau Espin Pedrol6e3b6892019-12-04 19:24:16 +0100545 if (lengthof(dl_block.data.blocks) < 1) {
546 setverdict(fail, "DL block has no LLC payload: ", dl_block);
547 mtc.stop;
548 }
549
550 if (ispresent(dl_block.data.blocks[0].hdr) and dl_block.data.blocks[0].hdr.length_ind != lengthof(data)) {
551 setverdict(fail, "DL block has LLC header with wrong expected size: ",
552 dl_block.data.blocks[0].hdr.length_ind, " vs ", lengthof(data));
553 mtc.stop;
554 }
555
556 if (dl_block.data.blocks[0].payload != data) {
557 setverdict(fail, "Failed to match content of LLC payload in DL Block: ", dl_block, " vs ", data);
558 mtc.stop;
559 }
560
561 /* Check next data blocks contain dummy frames */
562 if (lengthof(dl_block.data.blocks) > 1 and substr(dl_block.data.blocks[1].payload, 0, 3) != '43C001'O) {
563 setverdict(fail, "Second data payload is not a dummy frame: ", dl_block.data.blocks[1].payload);
564 mtc.stop;
565 }
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100566}
567
Vadim Yanitskiy740ae762019-09-29 16:13:41 +0700568testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
569 var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.cell_id.ra_id);
570 var GprsTlli tlli := 'FFFFFFFF'O;
571 timer T;
572
573 /* Initialize NS/BSSGP side */
574 f_init_bssgp();
575
576 /* Initialize the PCU interface abstraction */
577 f_init_raw(testcasename());
578
579 /* Establish BSSGP connection to the PCU */
580 f_bssgp_establish();
581
582 BTS.send(ts_PCUIF_SUSP_REQ(0, tlli, ra_id, 0));
583
584 T.start(2.0);
585 alt {
586 [] BSSGP_SIG[0].receive(tr_BSSGP_SUSPEND(tlli, mp_gb_cfg.cell_id.ra_id)) {
587 setverdict(pass);
588 }
589 [] T.timeout {
590 setverdict(fail, "Timeout waiting for BSSGP SUSPEND");
591 }
592 }
593}
594
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200595/* Test of correct Timing Advance at the time of TBF establishment
596 * (derived from timing offset of the Access Burst). */
597testcase TC_ta_rach_imm_ass() runs on RAW_PCU_Test_CT {
598 var GsmRrMessage rr_msg;
599 var boolean ok;
600
601 /* Initialize the PCU interface abstraction */
602 f_init_raw(testcasename());
603
604 /* We cannot send too many TBF requests in a short time because
605 * at some point the PCU will fail to allocate a new TBF. */
606 for (var TimingAdvance ta := 0; ta < 64; ta := ta + 16) {
607 /* Establish an Uplink TBF (send RACH.ind with current TA) */
608 ok := f_establish_tbf(rr_msg, bts_nr := 0, ta := ta);
609 if (not ok) {
610 setverdict(fail, "Failed to establish an Uplink TBF");
611 mtc.stop;
612 }
613
614 /* Make sure Timing Advance IE matches out expectations */
615 if (match(rr_msg, tr_IMM_TBF_ASS(dl := false, ta := ta))) {
616 setverdict(pass);
617 }
618 }
619}
620
Vadim Yanitskiyfd6cbdf2020-04-28 18:24:41 +0700621/* Verify Timing Advance value(s) indicated during the packet Downlink assignment
622 * procedure as per 3GPP TS 44.018, section 3.5.3. There seems to be a bug in the
623 * IUT that causes it to send an unreasonable Timing Advance value > 0 despite
624 * no active TBF exists at the moment of establishment (idle mode). */
625testcase TC_ta_idle_dl_tbf_ass() runs on RAW_PCU_Test_CT {
626 var OCT4 tlli := f_rnd_octstring(4);
627 var GsmRrMessage rr_imm_ass;
628
629 /* Initialize NS/BSSGP side */
630 f_init_bssgp();
631
632 /* Initialize the PCU interface abstraction */
633 f_init_raw(testcasename());
634
635 /* Establish BSSGP connection to the PCU */
636 f_bssgp_establish();
637 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
638
639 /* SGSN sends some DL data, PCU will initiate Packet Downlink
640 * Assignment on CCCH (PCH). We don't care about the payload. */
641 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, f_rnd_octstring(10)));
642 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass); // TODO: match by TLLI!
643
644 /* Make sure that Timing Advance is 0 (the actual value is not known yet).
645 * As per 3GPP S 44.018, section 3.5.3.1.2, the network *shall* initiate
646 * the procedures defined in 3GPP TS 44.060 or use the polling mechanism. */
647 if (not match(rr_imm_ass, tr_IMM_TBF_ASS(ta := 0))) {
648 setverdict(fail, "Timing Advance value doesn't match");
649 mtc.stop;
650 }
651}
652
Vadim Yanitskiy1f72b0a2019-10-01 05:58:45 +0700653/* Verify that the PCU generates valid PTCCH/D messages
654 * while neither Uplink nor Downlink TBF is established. */
655testcase TC_ta_ptcch_idle() runs on RAW_PCU_Test_CT {
656 var PTCCHDownlinkMsg ptcch_msg;
657 var PCUIF_Message pcu_msg;
658 timer T;
659
660 /* Initialize the PCU interface abstraction */
661 f_init_raw(testcasename());
662
663 /* Sent an RTS.req for PTCCH/D */
664 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
665 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
666 arfcn := 871, block_nr := 0));
667 T.start(5.0);
668 alt {
669 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
670 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
671 log("Rx DATA.req message: ", pcu_msg);
672 setverdict(pass);
673 }
674 [] BTS.receive(PCUIF_Message:?) { repeat; }
675 [] T.timeout {
676 setverdict(fail, "Timeout waiting for a PTCCH/D block");
677 mtc.stop;
678 }
679 }
680
681 ptcch_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
682 log("Decoded PTCCH/D message: ", ptcch_msg);
683
684 /* Make sure the message is encoded correctly
685 * TODO: do we expect all TA values to be equal '1111111'B? */
686 if (not match(ptcch_msg, tr_PTCCHDownlinkMsg)) {
687 setverdict(fail, "Malformed PTCCH/D message");
688 mtc.stop;
689 }
690}
691
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700692/* Test of correct Timing Advance during an active Uplink TBF.
693 *
694 * Unlike the circuit-switched domain, Uplink transmissions on PDCH time-slots
695 * are not continuous and there can be long time gaps between them. This happens
696 * due to a bursty nature of packet data. The actual Timing Advance of a MS may
697 * significantly change between such rare Uplink transmissions, so GPRS introduces
698 * additional mechanisms to control Timing Advance, and thus reduce interference
699 * between neighboring TDMA time-slots.
700 *
701 * At the moment of Uplink TBF establishment, initial Timing Advance is measured
702 * from ToA (Timing of Arrival) of an Access Burst. This is covered by another
703 * test case - TC_ta_rach_imm_ass. In response to that Access Burst the network
704 * sends Immediate Assignment on AGCH, which _may_ contain Timing Advance Index
705 * among with the initial Timing Advance value. And here PTCCH comes to play.
706 *
707 * PTCCH is a unidirectional channel on which the network can instruct a sub-set
708 * of 16 MS (whether TBFs are active or not) to adjust their Timing Advance
709 * continuously. To ensure continuous measurements of the signal propagation
710 * delay, the MSs shall transmit Access Bursts on Uplink (PTCCH/U) on sub-slots
711 * defined by an assigned Timing Advance Index (see 3GPP TS 45.002).
712 *
713 * The purpose of this test case is to verify the assignment of Timing Advance
714 * Index, and the process of Timing Advance notification on PTCCH/D. The MTC
715 * first establishes several Uplink TBFs, but does not transmit any Uplink
716 * blocks on them. During 4 TDMA multi-frame periods the MTC is sending RACH
717 * indications to the PCU, checking the correctness of two received PTCCH/D
718 * messages (period of PTCCH/D is two multi-frames).
719 */
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700720
721/* List of ToA values for Access Bursts to be sent on PTCCH/U,
722 * each ToA (Timing of Arrival) value is in units of 1/4 of
723 * a symbol (i.e. 1 symbol is 4 QTA units). */
724type record length(16) of int16_t PTCCH_TAI_ToA_MAP;
725const PTCCH_TAI_ToA_MAP ptcch_toa_map_def := {
726 0, 0, 0, 0,
727 0, 0, 0, 0,
728 0, 0, 0, 0,
729 0, 0, 0, 0
730};
731
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700732private altstep as_ta_ptcch(uint8_t bts_nr := 0, uint8_t trx_nr := 0, uint8_t ts_nr := 7,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700733 in PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def)
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700734runs on RAW_PCU_Test_CT {
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700735 var RAW_PCU_Event event;
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700736 var integer ss;
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700737
738 /* Send Access Bursts on PTCCH/U for every TA Index */
739 [] BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PTCCH_UL_BURST)) -> value event {
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700740 ss := f_tdma_ptcch_fn2ss(event.data.tdma_fn);
741 if (ss < 0) { mtc.stop; } /* Shall not happen */
742
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700743 log("Sending an Access Burst on PTCCH/U",
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700744 ", sub-slot=", ss, " (TAI)",
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700745 ", fn=", event.data.tdma_fn,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700746 ", ToA=", toa_map[ss], " (QTA)");
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700747 /* TODO: do we care about RA and burst format? */
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700748 BTS.send(ts_PCUIF_RACH_IND(bts_nr, trx_nr, ts_nr,
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700749 ra := oct2int('3A'O),
750 is_11bit := 0,
751 burst_type := BURST_TYPE_0,
752 fn := event.data.tdma_fn,
753 arfcn := 871,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700754 qta := toa_map[ss],
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700755 sapi := PCU_IF_SAPI_PTCCH));
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700756 repeat;
757 }
758}
759
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700760private function f_TC_ta_ptcch_ul_multi_tbf(in PTCCH_TAI_ToA_MAP ptcch_toa_map,
761 template PTCCHDownlinkMsg t_ta_msg)
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700762runs on RAW_PCU_Test_CT {
763 var PTCCHDownlinkMsg ta_msg;
764 var PCUIF_Message pcu_msg;
765 timer T;
766
767 /* First, send an RTS.req for the upcoming PTCCH/D block */
768 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
769 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
770 arfcn := 871, block_nr := 0));
771 T.start(2.0);
772 alt {
773 /* Keep sending of Access Bursts during two multi-frames (period of PTCCH/D)
774 * with increasing ToA (Timing of Arrival) values: 0, 7, 14, 28, 35... */
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700775 [] as_ta_ptcch(bts_nr := 0, trx_nr := 0, ts_nr := 7, toa_map := ptcch_toa_map);
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700776 /* In the end of 2nd multi-frame we should receive a PTCCH/D block */
777 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
778 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
779 ta_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
780 log("Rx PTCCH/D message: ", ta_msg);
781
782 /* Make sure Timing Advance values match our expectations */
783 if (match(ta_msg, t_ta_msg)) {
784 setverdict(pass);
785 } else {
786 setverdict(fail, "PTCCH/D message does not match: ", t_ta_msg);
787 }
788 }
789 [] BTS.receive { repeat; }
790 [] T.timeout {
791 setverdict(fail, "Timeout waiting for a PTCCH/D block");
792 mtc.stop;
793 }
794 }
795}
796
797testcase TC_ta_ptcch_ul_multi_tbf() runs on RAW_PCU_Test_CT {
798 var template PacketUlAssign t_ul_tbf_ass;
799 var PacketUlAssign ul_tbf_ass[7];
800 var GsmRrMessage rr_msg[7];
801 var boolean ok;
802
803 /* Initialize the PCU interface abstraction */
804 f_init_raw(testcasename());
805
806 /* Enable forwarding of PTCCH/U TDMA events to us */
807 BTS.send(ts_RAW_PCU_CMD(TDMA_CMD_ENABLE_PTCCH_UL_FWD));
808
809 /* Establish 7 Uplink TBFs (USF flag is 3 bits long, '111'B is reserved) */
810 for (var integer i := 0; i < 7; i := i + 1) {
811 ok := f_establish_tbf(rr_msg[i], ta := 0);
812 if (not ok) {
813 setverdict(fail, "Failed to establish an Uplink TBF #", i);
814 mtc.stop;
815 }
816
817 /* Make sure we received an UL TBF Assignment */
818 if (match(rr_msg[i], tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
819 ul_tbf_ass[i] := rr_msg[i].payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
820 log("Rx Uplink TBF assignment for #", i, ": ", ul_tbf_ass[i]);
821 } else {
822 setverdict(fail, "Failed to match UL TBF Assignment for #", i);
823 mtc.stop;
824 }
825
826 /* We expect incremental TFI/USF assignment (dynamic allocation) */
827 t_ul_tbf_ass := tr_PacketUlDynAssign(tfi := i, usf := i);
828 if (not match(ul_tbf_ass[i], t_ul_tbf_ass)) {
829 setverdict(fail, "Failed to match Packet Uplink Assignment for #", i);
830 mtc.stop;
831 }
832
833 /* We also expect Timing Advance Index to be a part of the assignment */
834 if (ul_tbf_ass[i].dynamic.ta_index != i) {
835 setverdict(fail, "Failed to match Timing Advance Index for #", i);
836 /* Keep going, the current OsmoPCU does not assign TA Index */
837 }
838 }
839
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700840 /* Prepare a list of ToA values for Access Bursts to be sent on PTCCH/U */
841 var PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def;
842 for (var integer i := 0; i < 7; i := i + 1) {
843 /* ToA in units of 1/4 of a symbol */
844 toa_map[i] := (i + 1) * 7 * 4;
845 }
846
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700847 /* Now we have all 7 TBFs established in one-phase access mode,
848 * however we will not be sending any data on them. Instead, we
849 * will be sending RACH.ind on PTCCH/U during 4 multi-frame
850 * periods (TAI 0..8), and then will check two PTCCH/D blocks.
851 *
852 * Why not 4 TBFs at once? Because Uplink is delayed by 3 TDMA
853 * time-slots, so at the moment of scheduling a PTCCH/D block
854 * the PCU has odd number of PTCCH/U Access Bursts received. */
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700855 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700856 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
857 /* Other values are not known (yet) */
858 tai3_ta := ?));
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700859 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700860 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
861 tai3_ta := 28, tai4_ta := 35, tai5_ta := 42,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700862 /* Other values are out of our interest */
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700863 tai6_ta := ?));
864}
865
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700866/* Default link quality adaptation (Coding Scheme) ranges (inclusive).
867 * OsmoPCU (VTY): cs link-quality-ranges cs1 6 cs2 5 8 cs3 7 13 cs4 12
868 *
869 * NOTE: the ranges are intentionally overlapping because OsmoPCU
870 * does not change CS/MCS on the range borders (5-6, 7-8, 12-13). */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200871private template integer CS1_lqual_dB_range := (-infinity .. 6);
872private template integer CS2_lqual_dB_range := (5 .. 8);
873private template integer CS3_lqual_dB_range := (7 .. 13);
874private template integer CS4_lqual_dB_range := (12 .. infinity);
875
876testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200877 var GsmRrMessage rr_imm_ass;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200878 var PacketUlAssign ul_tbf_ass;
879 var RlcmacDlBlock dl_block;
880 var PCUIF_Message pcu_msg;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200881 var octetstring data;
882 var boolean ok;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100883 var uint32_t unused_fn;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200884
885 /* Initialize the PCU interface abstraction */
886 f_init_raw(testcasename());
887
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100888 f_pcuvty_set_allowed_cs_mcs();
889 f_pcuvty_set_link_quality_ranges();
890
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200891 /* Establish an Uplink TBF */
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200892 ok := f_establish_tbf(rr_imm_ass);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200893 if (not ok) {
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200894 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200895 mtc.stop;
896 }
897
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200898 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
899 if (not ok) {
900 setverdict(fail, "Immediate Assignment not an Uplink TBF");
Vadim Yanitskiy6276b6c2019-09-29 19:48:26 +0700901 mtc.stop;
902 }
903
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200904 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
905 tfi := ul_tbf_ass.dynamic.tfi_assignment,
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100906 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200907 bsn := 0, /* TODO: what should be here? */
908 blocks := { /* To be generated in loop */ });
909
910 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
911 ul_data.data.tlli := '00000001'O;
912
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700913 /* The actual / old link quality values. We need to keep track of the old
914 * (basically previous) link quality value, because OsmoPCU actually
915 * changes the coding scheme if not only the actual, but also the old
916 * value leaves the current link quality range (window). */
917 var integer lqual := 0;
918 var integer lqual_old;
919
920 /* 16 UL blocks (0 .. 15 dB, step = 1 dB) */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200921 for (var integer i := 0; i < 16; i := i + 1) {
922 /* Prepare a new UL block (CV, random payload) */
923 ul_data.data.mac_hdr.countdown := (15 - i);
924 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
925
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700926 /* Update the old / actual link quality */
927 lqual_old := lqual;
928 lqual := i;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200929
930 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
931 log("Sending DATA.ind with link quality (dB): ", lqual);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200932 f_tx_rlcmac_ul_block(ul_data, lqual * 10);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200933
934 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100935 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200936
937 log("Rx Packet Uplink ACK / NACK with Channel Coding Command: ",
938 dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd);
939
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700940 /* Match the received Channel Coding Command. Since we are increasing
941 * the link quality value on each iteration and not decreasing, there
942 * is no need to check the both old and current link quality values. */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200943 var template ChCodingCommand ch_coding;
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700944 select (lqual_old) {
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200945 case (CS1_lqual_dB_range) { ch_coding := CH_CODING_CS1; }
946 case (CS2_lqual_dB_range) { ch_coding := CH_CODING_CS2; }
947 case (CS3_lqual_dB_range) { ch_coding := CH_CODING_CS3; }
948 case (CS4_lqual_dB_range) { ch_coding := CH_CODING_CS4; }
949 }
950
951 if (not match(dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd, ch_coding)) {
952 setverdict(fail, "Channel Coding does not match our expectations: ", ch_coding);
953 } else {
954 setverdict(pass);
955 }
956 }
957}
958
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100959/* Test the max UL CS set by VTY works fine */
960testcase TC_cs_initial_ul() runs on RAW_PCU_Test_CT {
961 var GsmRrMessage rr_imm_ass;
962 var PacketUlAssign ul_tbf_ass;
963 var RlcmacDlBlock dl_block;
964 var boolean ok;
965 var integer lqual_cb;
966 var ChCodingCommand last_ch_coding;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100967 var uint32_t unused_fn;
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100968
969 /* Initialize the PCU interface abstraction */
970 f_init_raw(testcasename());
971
972 /* Set initial UL CS to 3 */
973 g_cs_initial_ul := 3;
974 f_pcuvty_set_allowed_cs_mcs();
975 f_pcuvty_set_link_quality_ranges();
976
977 /* Take lqual (dB->cB) so that we stay in that CS */
978 lqual_cb := g_cs_lqual_ranges[2].low * 10;
979
980 /* Establish an Uplink TBF */
981 ok := f_establish_tbf(rr_imm_ass);
982 if (not ok) {
983 setverdict(fail, "Failed to establish TBF");
984 mtc.stop;
985 }
986
987 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
988 if (not ok) {
989 setverdict(fail, "Immediate Assignment not an Uplink TBF");
990 mtc.stop;
991 }
992
993 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
994 tfi := ul_tbf_ass.dynamic.tfi_assignment,
995 cv := 3, /* 8 UL blocks to be sent (to be overridden in loop) */
996 bsn := 0, /* TODO: what should be here? */
997 blocks := { /* To be generated in loop */ });
998
999 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1000 ul_data.data.tlli := '00000001'O;
1001
1002 /* 3 UL blocks, check we are in same initial CS: */
1003 for (var integer i := 0; i < 3; i := i + 1) {
1004 /* Prepare a new UL block (CV, random payload) */
1005 ul_data.data.mac_hdr.countdown := (7 - i);
1006 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1007
1008 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1009 f_tx_rlcmac_ul_block(ul_data, lqual_cb);
1010
1011 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001012 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001013 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1014 }
1015
1016 if (last_ch_coding != CH_CODING_CS3) {
1017 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
1018 mtc.stop;
1019 }
1020
1021 setverdict(pass);
1022
1023 /* Remaining UL blocks are used to make sure regardless of initial
1024 /* lqual, we can go lower at any time */
1025
1026 /* 5 UL blocks, check we are in same initial CS: */
1027 for (var integer i := 3; i < 8; i := i + 1) {
1028 /* Prepare a new UL block (CV, random payload) */
1029 ul_data.data.mac_hdr.countdown := (7 - i);
1030 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1031
1032 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1033 f_tx_rlcmac_ul_block(ul_data, 0); /* 0 dB, make sure we downgrade CS */
1034
1035 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001036 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001037
1038 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1039 }
1040
1041 if (last_ch_coding != CH_CODING_CS1) {
1042 setverdict(fail, "Channel Coding does not match our expectations (CS-1): ", last_ch_coding);
1043 } else {
1044 setverdict(pass);
1045 }
1046}
1047
1048/* Test the max UL CS set by VTY works fine */
1049testcase TC_cs_max_ul() runs on RAW_PCU_Test_CT {
1050 var GsmRrMessage rr_imm_ass;
1051 var PacketUlAssign ul_tbf_ass;
1052 var RlcmacDlBlock dl_block;
1053 var boolean ok;
1054 var ChCodingCommand last_ch_coding;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001055 var uint32_t unused_fn;
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001056
1057 /* Initialize the PCU interface abstraction */
1058 f_init_raw(testcasename());
1059
1060 /* Set maximum allowed UL CS to 3 */
1061 g_cs_max_ul := 3;
1062 f_pcuvty_set_allowed_cs_mcs();
1063 f_pcuvty_set_link_quality_ranges();
1064
1065 /* Establish an Uplink TBF */
1066 ok := f_establish_tbf(rr_imm_ass);
1067 if (not ok) {
1068 setverdict(fail, "Failed to establish TBF");
1069 mtc.stop;
1070 }
1071
1072 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1073 if (not ok) {
1074 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1075 mtc.stop;
1076 }
1077
1078 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1079 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1080 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
1081 bsn := 0, /* TODO: what should be here? */
1082 blocks := { /* To be generated in loop */ });
1083
1084 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1085 ul_data.data.tlli := '00000001'O;
1086
1087 /* 16 UL blocks */
1088 for (var integer i := 0; i < 16; i := i + 1) {
1089 /* Prepare a new UL block (CV, random payload) */
1090 ul_data.data.mac_hdr.countdown := (15 - i);
1091 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1092
1093 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1094 f_tx_rlcmac_ul_block(ul_data, 40*10); /* 40 dB */
1095
1096 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001097 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001098
1099 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1100 }
1101
1102 if (last_ch_coding != CH_CODING_CS3) {
1103 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
1104 } else {
1105 setverdict(pass);
1106 }
1107}
1108
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001109/* Verify PCU drops TBF after some time of inactivity. */
1110testcase TC_t3169() runs on RAW_PCU_Test_CT {
1111 var PCUIF_info_ind info_ind;
1112 var GsmRrMessage rr_imm_ass;
1113 var PacketUlAssign ul_tbf_ass;
1114 var RlcmacDlBlock dl_block;
1115 var PCUIF_Message pcu_msg;
1116 var octetstring data;
1117 var boolean ok;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001118 var uint32_t unused_fn;
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001119 var OCT4 tlli := '00000001'O;
1120
1121 /* Initialize NS/BSSGP side */
1122 f_init_bssgp();
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001123
1124 info_ind := valueof(ts_PCUIF_INFO_default);
1125 /* Set timer to 1 sec (default 5) to speedup test: */
1126 info_ind.t3169 := 1;
1127
1128 /* Initialize the PCU interface abstraction */
1129 f_init_raw(testcasename(), info_ind);
1130
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001131 /* Establish BSSGP connection to the PCU */
1132 f_bssgp_establish();
1133 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1134
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001135 /* Establish an Uplink TBF */
1136 ok := f_establish_tbf(rr_imm_ass);
1137 if (not ok) {
1138 setverdict(fail, "Failed to establish TBF");
1139 mtc.stop;
1140 }
1141
1142 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1143 if (not ok) {
1144 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1145 mtc.stop;
1146 }
1147
1148 /* Send one UL block and make sure it is ACKED fine */
1149 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001150 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001151 /* UL block should be received in SGSN */
1152 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001153
1154 /* Wait until T3169 fires (plus 1 extra sec to make sure) */
1155 f_sleep(int2float(info_ind.t3169) + 1.0);
1156
1157 /* Send an UL block once again, the TBF should be gone by now so no ACK */
1158 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1159 f_rx_rlcmac_dl_block_exp_dummy(dl_block);
1160}
1161
Pau Espin Pedrolff8da192019-12-05 17:23:58 +01001162/* Verify that a Downlink TBF can be assigned using PACCH shortly after the
1163 * release of prev DL TBF due to MS staying in PDCH for a while (T3192, in PCU
1164 * T3193) after DL TBF release */
1165testcase TC_t3193() runs on RAW_PCU_Test_CT {
1166 var GsmRrMessage rr_imm_ass;
1167 var PacketDlAssign dl_tbf_ass;
1168 var RlcmacDlBlock dl_block;
1169 var octetstring data := f_rnd_octstring(10);
1170 var boolean ok;
1171 var uint32_t sched_fn;
1172 var OCT4 tlli := '00000001'O;
1173 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1174
1175 /* Initialize NS/BSSGP side */
1176 f_init_bssgp();
1177
1178 /* Initialize the PCU interface abstraction */
1179 f_init_raw(testcasename());
1180
1181 /* Establish BSSGP connection to the PCU */
1182 f_bssgp_establish();
1183 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1184
1185 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1186 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1187 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1188 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1189 if (not ok) {
1190 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1191 mtc.stop;
1192 }
1193 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1194 f_sleep(X2002);
1195 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1196
1197 /* ACK the DL block */
1198 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1199 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1200 /* we are done with the DL-TBF here so far, let's clean up our local state: */
1201 ack_nack_desc := valueof(t_AckNackDescription_init)
1202
1203 /* Now that final DL block is ACKED and TBF is released, T3193 in PCU
1204 (T3192 in MS) was started and until it fires the MS will be abailable
1205 on PDCH in case new data arrives from SGSN. Let's verify it: */
1206 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1207 f_rx_rlcmac_dl_block_exp_pkt_ass(dl_block, sched_fn);
1208 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1209
1210 /* Now that we confirmed the new assignment in the dl-tbf, lets receive the data and ack it */
1211 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1212 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1213 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1214}
1215
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001216/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1217 * answered, so TBFs for uplink and later for downlink are created.
1218 */
Pau Espin Pedrol8f245712020-04-24 18:47:30 +02001219private function f_TC_mo_ping_pong(template (omit) MSRadioAccessCapabilityV ms_racap := omit, template (present) CodingScheme exp_cs_mcs := ?) runs on RAW_PCU_Test_CT {
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001220 var GsmRrMessage rr_imm_ass;
1221 var PacketUlAssign ul_tbf_ass;
1222 var PacketDlAssign dl_tbf_ass;
1223 var RlcmacDlBlock dl_block;
1224 var PCUIF_Message pcu_msg;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001225 var octetstring data := f_rnd_octstring(10);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001226 var boolean ok;
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +01001227 var uint32_t sched_fn;
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001228 var OCT4 tlli := '00000001'O;
Pau Espin Pedrol89486332019-12-05 14:05:46 +01001229 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001230
1231 /* Initialize NS/BSSGP side */
1232 f_init_bssgp();
1233
1234 /* Initialize the PCU interface abstraction */
1235 f_init_raw(testcasename());
1236
1237 /* Establish BSSGP connection to the PCU */
1238 f_bssgp_establish();
1239 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1240
1241 /* Establish an Uplink TBF */
1242 ok := f_establish_tbf(rr_imm_ass);
1243 if (not ok) {
1244 setverdict(fail, "Failed to establish TBF");
1245 mtc.stop;
1246 }
1247 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1248 if (not ok) {
1249 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1250 mtc.stop;
1251 }
1252
Pau Espin Pedrol8f245712020-04-24 18:47:30 +02001253 if (not istemplatekind(ms_racap, "omit")) {
1254 /* Send PACKET RESOURCE REQUEST to upgrade to EGPRS
1255 * (see 3GPP TS 04.60 "7.1.3.1 Initiation of the Packet resource request procedure")
1256 */
1257 f_tx_rlcmac_ul_block(ts_RLC_UL_CTRL_ACK(valueof(ts_RlcMacUlCtrl_PKT_RES_REQ(tlli, ms_racap))), 0);
1258 f_rx_rlcmac_dl_block_exp_pkt_ul_ass(dl_block, sched_fn);
1259 if (dl_block.ctrl.payload.u.ul_assignment.identity.tlli.tlli != tlli) {
1260 setverdict(fail, "Wrong TLLI ", dl_block.ctrl.payload.u.ul_assignment.identity.tlli, " received vs exp ", tlli);
1261 mtc.stop;
1262 }
1263 }
1264
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001265 /* Send one UL block and make sure it is ACKED fine */
1266 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001267 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1268 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1269 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001270
1271 /* UL block should be received in SGSN */
1272 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1273
1274 /* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001275 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001276 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1277
1278 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1279 if (not ok) {
1280 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1281 mtc.stop;
1282 }
1283
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001284 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1285 f_sleep(X2002);
Pau Espin Pedrol8f245712020-04-24 18:47:30 +02001286 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0, exp_cs_mcs);
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001287
1288 /* ACK the DL block */
Pau Espin Pedrol89486332019-12-05 14:05:46 +01001289 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +01001290 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001291}
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001292
Pau Espin Pedrol8f245712020-04-24 18:47:30 +02001293/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1294 * answered, so TBFs for uplink and later for downlink are created.
1295 */
1296testcase TC_mo_ping_pong() runs on RAW_PCU_Test_CT {
1297 var CodingScheme exp_cs_mcs := CS_1;
1298 f_TC_mo_ping_pong(omit, exp_cs_mcs);
1299}
1300
1301
1302testcase TC_mo_ping_pong_with_ul_racap() runs on RAW_PCU_Test_CT {
1303 var MultislotCap_GPRS mscap_gprs := {
1304 gprsmultislotclass := '00011'B,
1305 gprsextendeddynalloccap := '0'B
1306 };
1307 var MSRadioAccessCapabilityV ms_racap := { valueof(ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs, omit)) };
1308 var CodingScheme exp_cs_mcs := CS_2;
1309
1310 f_TC_mo_ping_pong(ms_racap, exp_cs_mcs);
1311}
1312
Pau Espin Pedrole7cabe62020-01-23 14:35:15 +01001313/* Test scenario where SGSN wants to send some data against MS and it is
1314 * answered by the MS on PDCH, so TBFs for downlink and later for uplink are created.
1315 */
Pau Espin Pedroldc9666f2020-03-18 20:30:16 +01001316private 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 {
Pau Espin Pedrole7cabe62020-01-23 14:35:15 +01001317 var GsmRrMessage rr_imm_ass;
1318 var PacketUlAssign ul_tbf_ass;
1319 var PacketDlAssign dl_tbf_ass;
1320 var RlcmacDlBlock dl_block;
1321 var PCUIF_Message pcu_msg;
1322 var octetstring data := f_rnd_octstring(10);
1323 var boolean ok;
1324 var uint32_t sched_fn;
1325 var OCT4 tlli := '00000001'O;
1326 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1327
1328 /* Initialize NS/BSSGP side */
1329 f_init_bssgp();
1330
1331 /* Initialize the PCU interface abstraction */
1332 f_init_raw(testcasename());
1333
1334 /* Establish BSSGP connection to the PCU */
1335 f_bssgp_establish();
1336 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1337
1338 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
Pau Espin Pedrol2422d1f2020-01-23 17:51:04 +01001339 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data, ms_racap));
Pau Espin Pedrole7cabe62020-01-23 14:35:15 +01001340 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1341
1342 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1343 if (not ok) {
1344 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1345 mtc.stop;
1346 }
1347
1348 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1349 f_sleep(X2002);
Pau Espin Pedroldc9666f2020-03-18 20:30:16 +01001350 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0, exp_cs_mcs);
Pau Espin Pedrole7cabe62020-01-23 14:35:15 +01001351
1352 /* ACK the DL block */
1353 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1354 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1355
1356 /* Now MS wants to answer the DL data, Establish an Uplink TBF */
1357 ok := f_establish_tbf(rr_imm_ass);
1358 if (not ok) {
1359 setverdict(fail, "Failed to establish TBF");
1360 mtc.stop;
1361 }
1362 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1363 if (not ok) {
1364 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1365 mtc.stop;
1366 }
1367
1368 /* Send one UL block and make sure it is ACKED fine */
1369 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1370 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1371 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1372 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1373
1374 /* UL block should be received in SGSN */
1375 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1376}
1377
Pau Espin Pedrol2422d1f2020-01-23 17:51:04 +01001378testcase TC_mt_ping_pong() runs on RAW_PCU_Test_CT {
Pau Espin Pedroldc9666f2020-03-18 20:30:16 +01001379 var CodingScheme exp_cs_mcs := CS_1;
1380 f_TC_mt_ping_pong(omit, exp_cs_mcs);
Pau Espin Pedrol2422d1f2020-01-23 17:51:04 +01001381}
1382
1383/* TC_mt_ping_pong, but DL-UNITDATA contains RA Access capability with (M)CS
1384/* information about the MS */
1385testcase TC_mt_ping_pong_with_dl_racap() runs on RAW_PCU_Test_CT {
1386 var MultislotCap_GPRS_BSSGP mscap_gprs := {
1387 gprsmultislotclass := '00011'B,
1388 gprsextendeddynalloccap := '0'B
1389 } ;
1390 var MSRadioAccessCapabilityV_BSSGP ms_racap := { valueof(ts_RaCapRec_BSSGP('0001'B /* E-GSM */, mscap_gprs, omit)) };
Pau Espin Pedroldc9666f2020-03-18 20:30:16 +01001391 var CodingScheme exp_cs_mcs := CS_2;
1392 f_TC_mt_ping_pong(ms_racap, exp_cs_mcs);
Pau Espin Pedrol2422d1f2020-01-23 17:51:04 +01001393}
1394
Pau Espin Pedrola7b75662019-12-05 16:39:55 +01001395/* Verify that if PCU doesn't get an ACK for first DL block after IMM ASS, it
1396 * will retry by retransmitting both the IMM ASS + DL block after poll (ack)
1397 * timeout occurs (specified by sent RRBP on DL block). */
1398testcase TC_imm_ass_dl_block_retrans() runs on RAW_PCU_Test_CT {
1399 var GsmRrMessage rr_imm_ass;
1400 var PacketDlAssign dl_tbf_ass;
1401 var RlcmacDlBlock dl_block;
1402 var octetstring data := f_rnd_octstring(10);
1403 var boolean ok;
1404 var uint32_t sched_fn;
1405 var OCT4 tlli := '00000001'O;
1406 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1407
1408 /* Initialize NS/BSSGP side */
1409 f_init_bssgp();
1410
1411 /* Initialize the PCU interface abstraction */
1412 f_init_raw(testcasename());
1413
1414 /* Establish BSSGP connection to the PCU */
1415 f_bssgp_establish();
1416 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1417
1418 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1419 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1420 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1421 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1422 if (not ok) {
1423 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1424 mtc.stop;
1425 }
1426
1427 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1428 f_sleep(X2002);
1429 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1430
1431 /* Now we don't ack the dl block (emulate MS failed receiveing IMM ASS
1432 * or GPRS DL, or DL ACK was lost for some reason). As a result, PCU
1433 * should retrigger IMM ASS + GPRS DL procedure after poll timeout. */
1434 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1435 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1436 if (not ok) {
1437 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1438 mtc.stop;
1439 }
1440 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1441 f_sleep(X2002);
1442 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1443
1444 /* ACK the DL block */
1445 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1446 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1447}
1448
Vadim Yanitskiy322c7932020-01-01 23:03:47 +01001449private function f_pkt_paging_match_imsi(in PacketPagingReq req, hexstring imsi) {
1450 var MobileIdentityLV_Paging mi_lv := req.repeated_pageinfo.cs.mobile_identity;
1451 var MobileIdentityV mi := dec_MobileIdentityV(mi_lv.mobile_id);
1452
1453 if (mi_lv.len != 8) { /* 8 octets: type of ID (3 bits) + even/odd flag (1 bit) + 15 BCD-encoded digits (60 bits) */
1454 setverdict(fail, "Mobile Identity length mismatch: ",
1455 "expected: 8, got: ", mi_lv.len);
1456 mtc.stop;
1457 }
1458
1459 /* Make sure MI contains IMSI before referencing it */
1460 if (mi.typeOfIdentity != '001'B) {
1461 setverdict(fail, "Mobile Identity must be of type IMSI ('001'B), ",
1462 "got: ", mi.typeOfIdentity);
1463 mtc.stop;
1464 } else if (mi.oddEvenInd_identity.imsi.digits != imsi) {
1465 setverdict(fail, "Mobile Identity contains unexpected IMSI, ",
1466 "expected: ", imsi, " got: ", mi.oddEvenInd_identity.imsi.digits);
1467 mtc.stop;
1468 }
1469}
1470
Vadim Yanitskiy7b224212020-03-26 02:43:55 +07001471private function f_pkt_paging_match_tmsi(in PacketPagingReq req, template GsmTmsi tmsi) {
1472 if (not match(req.repeated_pageinfo.cs.tmsi, tmsi)) {
1473 setverdict(fail, "Mobile Identity (TMSI/P-TMSI) mismatch: ",
1474 "expected: ", tmsi, "got: ", req.repeated_pageinfo.cs.tmsi);
1475 mtc.stop;
1476 }
1477}
1478
Oliver Smith8f9daab2019-10-09 09:27:19 +02001479/* Test CS paging over the BTS<->PCU socket.
1480 * 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.
1481 * Paging should be send on the PACCH.
1482 *
1483 * 1. Send a Paging Request over PCU socket.
1484 * 2. Send a Ready-To-Send message over PCU socket
1485 * 3. Expect a Paging Frame
1486 */
1487testcase TC_paging_cs_from_bts() runs on RAW_PCU_Test_CT {
1488 var GsmRrMessage rr_imm_ass;
1489 var PacketUlAssign ul_tbf_ass;
1490 var RlcmacDlBlock dl_block;
1491 var boolean ok;
1492 var OCT4 tlli := '00000001'O;
Vadim Yanitskiy98bb2d52020-03-28 00:57:21 +07001493 var MobileIdentityLV mi;
Oliver Smith8f9daab2019-10-09 09:27:19 +02001494 var octetstring mi_enc_lv;
Oliver Smith8f9daab2019-10-09 09:27:19 +02001495 var hexstring imsi := f_gen_imsi(42);
1496
1497 /* Initialize NS/BSSGP side */
1498 f_init_bssgp();
1499
1500 /* Initialize the PCU interface abstraction */
1501 f_init_raw(testcasename());
1502
1503 /* Establish BSSGP connection to the PCU */
1504 f_bssgp_establish();
1505 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1506
1507 /* Establish an Uplink TBF */
1508 ok := f_establish_tbf(rr_imm_ass);
1509 if (not ok) {
1510 setverdict(fail, "Failed to establish TBF");
1511 mtc.stop;
1512 }
1513
1514 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1515 if (not ok) {
1516 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1517 mtc.stop;
1518 }
1519
1520
1521 /* build mobile Identity */
1522 mi := valueof(ts_MI_IMSI_LV(imsi));
1523 mi_enc_lv := enc_MobileIdentityLV(mi);
1524 /* Send paging request */
1525 BTS.send(ts_PCUIF_PAG_REQ(bts_nr := 0, id_lv := mi_enc_lv, chan_needed := 0,
1526 sapi :=PCU_IF_SAPI_PDTCH));
1527
1528 /* Receive it on BTS side towards MS */
1529 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
Vadim Yanitskiy5e518732020-01-01 21:27:18 +01001530
Vadim Yanitskiy322c7932020-01-01 23:03:47 +01001531 /* Make sure that Packet Paging Request contains the same IMSI */
1532 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1533
Oliver Smith8f9daab2019-10-09 09:27:19 +02001534 setverdict(pass);
1535}
1536
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001537/* Test CS paging over Gb (SGSN->PCU->BTS[PDCH]).
1538 */
Vadim Yanitskiy7b224212020-03-26 02:43:55 +07001539private function f_tc_paging_cs_from_sgsn(Nsvci bvci, boolean use_ptmsi := false)
1540runs on RAW_PCU_Test_CT {
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001541 var GsmRrMessage rr_imm_ass;
1542 var PacketUlAssign ul_tbf_ass;
1543 var RlcmacDlBlock dl_block;
1544 var boolean ok;
1545 var OCT4 tlli := '00000001'O;
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001546 var hexstring imsi := f_gen_imsi(42);
Vadim Yanitskiy7b224212020-03-26 02:43:55 +07001547 var GsmTmsi tmsi;
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001548
1549 /* Initialize NS/BSSGP side */
1550 f_init_bssgp();
1551
1552 /* Initialize the PCU interface abstraction */
1553 f_init_raw(testcasename());
1554
1555 /* Establish BSSGP connection to the PCU */
1556 f_bssgp_establish();
1557 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1558
1559 /* Establish an Uplink TBF */
1560 ok := f_establish_tbf(rr_imm_ass);
1561 if (not ok) {
1562 setverdict(fail, "Failed to establish TBF");
1563 mtc.stop;
1564 }
1565
1566 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1567 if (not ok) {
1568 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1569 mtc.stop;
1570 }
1571
Vadim Yanitskiy7b224212020-03-26 02:43:55 +07001572 /* Send paging request with or without TMSI */
1573 if (use_ptmsi) {
1574 tmsi := oct2int(f_rnd_octstring(4)); /* Random P-TMSI */
1575 BSSGP[0].send(ts_BSSGP_CS_PAGING_PTMSI(bvci, imsi, tmsi));
1576 } else {
1577 BSSGP[0].send(ts_BSSGP_CS_PAGING_IMSI(bvci, imsi));
1578 }
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001579
1580 /* Receive it on BTS side towards MS */
1581 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
1582
Vadim Yanitskiy7b224212020-03-26 02:43:55 +07001583 /* Make sure that Packet Paging Request contains the same P-TMSI/IMSI */
1584 if (use_ptmsi) {
1585 f_pkt_paging_match_tmsi(dl_block.ctrl.payload.u.paging, tmsi);
1586 } else {
1587 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1588 }
Vadim Yanitskiy322c7932020-01-01 23:03:47 +01001589
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001590 setverdict(pass);
1591}
1592
Vadim Yanitskiy7b224212020-03-26 02:43:55 +07001593testcase TC_paging_cs_from_sgsn_sign_ptmsi() runs on RAW_PCU_Test_CT {
1594 f_tc_paging_cs_from_sgsn(0, true);
1595}
1596
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001597testcase TC_paging_cs_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1598 f_tc_paging_cs_from_sgsn(0);
1599}
1600
1601testcase TC_paging_cs_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1602 f_tc_paging_cs_from_sgsn(mp_gb_cfg.bvci);
1603}
1604
1605/* Test PS paging over Gb (SGSN->PCU->BTS[CCCH]).
1606 */
Vadim Yanitskiy7b224212020-03-26 02:43:55 +07001607private function f_tc_paging_ps_from_sgsn(Nsvci bvci, boolean use_ptmsi := false)
1608runs on RAW_PCU_Test_CT {
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001609 var OCT4 tlli := '00000001'O;
Pau Espin Pedrol925818a2020-01-02 14:06:51 +01001610 var integer imsi_suff_tx := 423;
1611 var hexstring imsi := f_gen_imsi(imsi_suff_tx);
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001612
1613 /* Initialize NS/BSSGP side */
1614 f_init_bssgp();
1615
1616 /* Initialize the PCU interface abstraction */
1617 f_init_raw(testcasename());
1618
1619 /* Establish BSSGP connection to the PCU */
1620 f_bssgp_establish();
1621 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1622
Vadim Yanitskiy9c513132020-03-28 04:33:07 +07001623 /* Send BSSGP PAGING-PS (with or without TMSI), wait for RR Paging Request Type 1.
1624 * Make sure that both paging group (IMSI suffix) and Mobile Identity match. */
Vadim Yanitskiy7b224212020-03-26 02:43:55 +07001625 if (use_ptmsi) {
Vadim Yanitskiy9c513132020-03-28 04:33:07 +07001626 var OCT4 tmsi := f_rnd_octstring(4); /* Random P-TMSI */
1627 BSSGP[0].send(ts_BSSGP_PS_PAGING_PTMSI(bvci, imsi, oct2int(tmsi)));
1628 f_pcuif_rx_pch_pag_req1(t_MI_TMSI(tmsi), imsi_suff_tx);
Vadim Yanitskiy7b224212020-03-26 02:43:55 +07001629 } else {
1630 BSSGP[0].send(ts_BSSGP_PS_PAGING_IMSI(bvci, imsi));
Vadim Yanitskiy9c513132020-03-28 04:33:07 +07001631 f_pcuif_rx_pch_pag_req1(tr_MI_IMSI(imsi), imsi_suff_tx);
Vadim Yanitskiy7b224212020-03-26 02:43:55 +07001632 }
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001633
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001634 setverdict(pass);
1635}
1636
Vadim Yanitskiy7b224212020-03-26 02:43:55 +07001637testcase TC_paging_ps_from_sgsn_sign_ptmsi() runs on RAW_PCU_Test_CT {
1638 f_tc_paging_ps_from_sgsn(0, true);
1639}
1640
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001641testcase TC_paging_ps_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1642 f_tc_paging_ps_from_sgsn(0);
1643}
1644
1645testcase TC_paging_ps_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1646 f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvci);
1647}
1648
Vadim Yanitskiya0b47cf2020-04-02 01:50:18 +07001649private function f_TC_egprs_pkt_chan_req(in EGPRSPktChRequest req,
1650 template GsmRrMessage t_imm_ass := ?,
1651 PCUIF_BurstType bt := BURST_TYPE_1)
1652runs on RAW_PCU_Test_CT {
1653 var GsmRrMessage rr_msg;
1654 var uint16_t ra11;
1655 var boolean ok;
1656
1657 ra11 := enc_EGPRSPktChRequest2uint(req);
1658 log("Sending EGPRS Packet Channel Request (", ra11, "): ", req);
1659
1660 ok := f_establish_tbf(rr_msg, ra := ra11, is_11bit := 1, burst_type := bt);
1661 if (not ok) {
1662 setverdict(fail, "Failed to establush an Uplink TBF");
1663 mtc.stop;
1664 }
1665
1666 if (not match(rr_msg, t_imm_ass)) {
1667 setverdict(fail, "Immediate Assignment does not match");
1668 mtc.stop;
1669 }
1670
1671 setverdict(pass);
1672}
1673
1674testcase TC_egprs_pkt_chan_req_signalling() runs on RAW_PCU_Test_CT {
1675 var template GsmRrMessage imm_ass;
1676 var template IaRestOctets rest;
1677 var template EgprsUlAss ul_ass;
1678
1679 /* Initialize the PCU interface abstraction */
1680 f_init_raw(testcasename());
1681
1682 var EGPRSPktChRequest req := {
1683 /* NOTE: other fields are set in the loop */
1684 signalling := { tag := '110011'B }
1685 };
1686
1687 for (var integer i := 0; i < 6; i := i + 1) {
1688 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
1689 req.signalling.random_bits := ext_ra;
1690
1691 /* For signalling, do we expect Multiblock UL TBF Assignment? */
1692 ul_ass := tr_EgprsUlAssMultiblock(ext_ra := ext_ra);
1693 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
1694 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
1695
1696 f_TC_egprs_pkt_chan_req(req, imm_ass);
1697 }
1698}
1699
1700testcase TC_egprs_pkt_chan_req_one_phase() runs on RAW_PCU_Test_CT {
1701 var template GsmRrMessage imm_ass;
1702 var template IaRestOctets rest;
1703 var template EgprsUlAss ul_ass;
1704
1705 /* Initialize the PCU interface abstraction */
1706 f_init_raw(testcasename());
1707
1708 var EGPRSPktChRequest req := {
1709 /* NOTE: other fields are set in the loop */
1710 one_phase := { tag := '0'B }
1711 };
1712
1713 for (var integer i := 0; i < 6; i := i + 1) {
1714 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
1715 var BIT5 mslot_class := int2bit(f_rnd_int(32), 5);
1716 var BIT2 priority := substr(ext_ra, 0, 2);
1717 var BIT3 rand := substr(ext_ra, 2, 3);
1718
1719 req.one_phase.multislot_class := mslot_class;
1720 req.one_phase.priority := priority;
1721 req.one_phase.random_bits := rand;
1722
1723 /* For one phase access, do we expect Dynamic UL TBF Assignment? */
1724 ul_ass := tr_EgprsUlAssDynamic(ext_ra := ext_ra);
1725 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
1726 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
1727
1728 f_TC_egprs_pkt_chan_req(req, imm_ass);
1729 }
1730}
1731
1732testcase TC_egprs_pkt_chan_req_two_phase() runs on RAW_PCU_Test_CT {
1733 var template GsmRrMessage imm_ass;
1734 var template IaRestOctets rest;
1735 var template EgprsUlAss ul_ass;
1736
1737 /* Initialize the PCU interface abstraction */
1738 f_init_raw(testcasename());
1739
1740 var EGPRSPktChRequest req := {
1741 /* NOTE: other fields are set in the loop */
1742 two_phase := { tag := '110000'B }
1743 };
1744
1745 for (var integer i := 0; i < 6; i := i + 1) {
1746 var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
1747 var BIT2 priority := substr(ext_ra, 0, 2);
1748 var BIT3 rand := substr(ext_ra, 2, 3);
1749
1750 req.two_phase.priority := priority;
1751 req.two_phase.random_bits := rand;
1752
1753 /* For two phase access, do we expect Multiblock UL TBF Assignment? */
1754 ul_ass := tr_EgprsUlAssMultiblock(ext_ra := ext_ra);
1755 rest := tr_IaRestOctets_EGPRSULAss(ul_ass);
1756 imm_ass := tr_IMM_TBF_ASS(dl := false, rest := rest);
1757
1758 f_TC_egprs_pkt_chan_req(req, imm_ass);
1759 }
1760}
1761
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001762control {
Harald Welte7fd25cf2019-03-21 22:14:02 +01001763 execute( TC_pcuif_suspend() );
Vadim Yanitskiy1f72b0a2019-10-01 05:58:45 +07001764 execute( TC_ta_ptcch_idle() );
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +02001765 execute( TC_ta_rach_imm_ass() );
Vadim Yanitskiyfd6cbdf2020-04-28 18:24:41 +07001766 execute( TC_ta_idle_dl_tbf_ass() );
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001767 execute( TC_ta_ptcch_ul_multi_tbf() );
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001768 execute( TC_cs_lqual_ul_tbf() );
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001769 execute( TC_cs_initial_ul() );
1770 execute( TC_cs_max_ul() );
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001771 execute( TC_t3169() );
Pau Espin Pedrolff8da192019-12-05 17:23:58 +01001772 execute( TC_t3193() );
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001773 execute( TC_mo_ping_pong() );
Pau Espin Pedrol8f245712020-04-24 18:47:30 +02001774 execute( TC_mo_ping_pong_with_ul_racap() );
Pau Espin Pedrole7cabe62020-01-23 14:35:15 +01001775 execute( TC_mt_ping_pong() );
Pau Espin Pedrol2422d1f2020-01-23 17:51:04 +01001776 execute( TC_mt_ping_pong_with_dl_racap() );
Pau Espin Pedrola7b75662019-12-05 16:39:55 +01001777 execute( TC_imm_ass_dl_block_retrans() );
Oliver Smith8f9daab2019-10-09 09:27:19 +02001778 execute( TC_paging_cs_from_bts() );
Vadim Yanitskiy7b224212020-03-26 02:43:55 +07001779 execute( TC_paging_cs_from_sgsn_sign_ptmsi() );
Vadim Yanitskiycca15a32020-03-24 21:27:00 +07001780 execute( TC_paging_cs_from_sgsn_sign() );
1781 execute( TC_paging_cs_from_sgsn_ptp() );
Vadim Yanitskiy7b224212020-03-26 02:43:55 +07001782 execute( TC_paging_ps_from_sgsn_sign_ptmsi() );
Vadim Yanitskiycca15a32020-03-24 21:27:00 +07001783 execute( TC_paging_ps_from_sgsn_sign() );
1784 execute( TC_paging_ps_from_sgsn_ptp() );
Vadim Yanitskiya0b47cf2020-04-02 01:50:18 +07001785
1786 /* EGPRS specific test cases */
1787 execute( TC_egprs_pkt_chan_req_signalling() );
1788 execute( TC_egprs_pkt_chan_req_one_phase() );
1789 execute( TC_egprs_pkt_chan_req_two_phase() );
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001790}
1791
1792
1793
1794
1795
1796
1797}