blob: 2564617c2275be8d428869b71a35f5e0d9386902 [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
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +020029import from RLCMAC_CSN1_Types all;
30import from RLCMAC_Types all;
31
Oliver Smith8f9daab2019-10-09 09:27:19 +020032import from MobileL3_CommonIE_Types all;
33import from L3_Templates all;
34
Harald Welte9fbcf4b2018-12-07 07:56:52 +010035import from NS_Types all;
36import from BSSGP_Types all;
37import from Osmocom_Gb_Types all;
38
39import from BSSGP_Emulation all; /* BssgpConfig */
40import from NS_Emulation all; /* NSConfiguration */
41
42import from UD_Types all;
43import from PCUIF_Types all;
44import from PCUIF_CodecPort all;
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +020045import from PCUIF_RAW_Components all;
Harald Welte9fbcf4b2018-12-07 07:56:52 +010046import from IPL4asp_Types all;
Harald Welte9fbcf4b2018-12-07 07:56:52 +010047import from Native_Functions all;
48import from PCU_Tests all;
49
50modulepar {
51 charstring mp_pcu_sock_path := PCU_SOCK_DEFAULT;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +010052
53 float X2002 := 0.2; /* Timer -2002, IMM ASSIGN confirm delay */
Harald Welte9fbcf4b2018-12-07 07:56:52 +010054}
55
Harald Welte9fbcf4b2018-12-07 07:56:52 +010056
Pau Espin Pedrolf787b092019-10-04 18:34:05 +020057/* 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 +010058private template (value) PCUIF_info_ind ts_PCUIF_INFO_default := {
Pau Espin Pedrolf787b092019-10-04 18:34:05 +020059 version := PCU_IF_VERSION,
60 flags := c_PCUIF_Flags_default,
61 trx := valueof(ts_PCUIF_InfoTrxs_def),
62 bsic := 7,
63 mcc := 262,
64 mnc := 42,
65 mnc_3_digits := 0,
66 lac := 13135,
67 rac := 0,
68 nsei := mp_nsconfig.nsei,
69 nse_timer := { 3, 3, 3, 3, 30, 3, 10 },
70 cell_timer := { 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 },
71 cell_id := 20960,
72 repeat_time := 5 * 50,
73 repeat_count := 3,
74 bvci := mp_gb_cfg.bvci,
75 t3142 := 20,
76 t3169 := 5,
77 t3191 := 5,
78 t3193_10ms := 160,
79 t3195 := 5,
80 t3101 := 10,
81 t3103 := 4,
82 t3105 := 8,
83 cv_countdown := 15,
84 dl_tbf_ext := 250 * 10, /* ms */
85 ul_tbf_ext := 250 * 10, /* ms */
86 initial_cs := 2,
87 initial_mcs := 6,
88 nsvci := { mp_nsconfig.nsvci, 0 },
89 local_pprt := { mp_nsconfig.remote_udp_port, 0 },
90 remote_port := { mp_nsconfig.local_udp_port, 0 },
91 remote_ip := { f_inet_haddr(mp_nsconfig.local_ip) , '00000000'O }
92}
93
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +010094type record lqual_range {
95 /* component reference to the IPA_Client component used for RSL */
96 uint8_t low,
97 uint8_t high
98}
99
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200100type component RAW_PCU_Test_CT extends bssgp_CT {
101 /* Connection to the BTS component (one for now) */
102 port RAW_PCU_MSG_PT BTS;
103 /* Connection to the PCUIF component */
104 port RAW_PCU_MSG_PT PCUIF;
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100105 /* VTY connection to the PCU */
106 port TELNETasp_PT PCUVTY;
107
108 /* Uplink CS/MCS thresholds, default from pcu_main.c: */
109 var lqual_range g_cs_lqual_ranges[4] := {{low := 0, high := 6},
110 {low := 5, high := 8},
111 {low := 7, high := 13},
112 {low := 12,high := 35}};
113 var lqual_range g_mcs_lqual_ranges[9] := {{low := 0, high := 6},
114 {low := 5, high := 8},
115 {low := 7, high := 13},
116 {low := 12,high := 15},
117 {low := 14, high := 17},
118 {low := 16, high := 18},
119 {low := 17,high := 20},
120 {low := 19, high := 24},
121 {low := 23,high := 35}};
122 var uint8_t g_cs_initial_dl := 1;
123 var uint8_t g_cs_initial_ul := 1;
124 var uint8_t g_mcs_initial_dl := 1;
125 var uint8_t g_mcs_initial_ul := 1;
126 var uint8_t g_cs_max_dl := 4;
127 var uint8_t g_cs_max_ul := 4;
128 var uint8_t g_mcs_max_dl := 9;
129 var uint8_t g_mcs_max_ul := 9;
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200130
131 /* Guard timeout */
132 timer g_T_guard := 60.0;
133};
134
135private altstep as_Tguard_RAW() runs on RAW_PCU_Test_CT {
136 [] g_T_guard.timeout {
137 setverdict(fail, "Timeout of T_guard");
138 mtc.stop;
139 }
140}
141
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100142private function f_pcuvty_set_allowed_cs_mcs() runs on RAW_PCU_Test_CT {
143 f_vty_config2(PCUVTY, {"pcu"}, "cs " & int2str(g_cs_initial_dl) & " " & int2str(g_cs_initial_ul));
144 f_vty_config2(PCUVTY, {"pcu"}, "cs max " & int2str(g_cs_max_dl) & " " & int2str(g_cs_max_ul));
145
146 f_vty_config2(PCUVTY, {"pcu"}, "mcs " & int2str(g_mcs_initial_dl) & " " & int2str(g_mcs_initial_ul));
147 f_vty_config2(PCUVTY, {"pcu"}, "mcs max " & int2str(g_mcs_max_dl) & " " & int2str(g_mcs_max_ul));
148}
149
150private function f_pcuvty_set_link_quality_ranges() runs on RAW_PCU_Test_CT {
151 var charstring cmd;
152
153 cmd := "cs link-quality-ranges" &
154 " cs1 " & int2str(g_cs_lqual_ranges[0].high) &
155 " cs2 " & int2str(g_cs_lqual_ranges[1].low) & " " & int2str(g_cs_lqual_ranges[1].high) &
156 " cs3 " & int2str(g_cs_lqual_ranges[2].low) & " " & int2str(g_cs_lqual_ranges[2].high) &
157 " cs4 " & int2str(g_cs_lqual_ranges[3].low);
158 f_vty_config2(PCUVTY, {"pcu"}, cmd);
159
160 cmd := "mcs link-quality-ranges" &
161 " mcs1 " & int2str(g_mcs_lqual_ranges[0].high) &
162 " mcs2 " & int2str(g_mcs_lqual_ranges[1].low) & " " & int2str(g_mcs_lqual_ranges[1].high) &
163 " mcs3 " & int2str(g_mcs_lqual_ranges[2].low) & " " & int2str(g_mcs_lqual_ranges[2].high) &
164 " mcs4 " & int2str(g_mcs_lqual_ranges[3].low) & " " & int2str(g_mcs_lqual_ranges[3].high) &
165 " mcs5 " & int2str(g_mcs_lqual_ranges[4].low) & " " & int2str(g_mcs_lqual_ranges[4].high) &
166 " mcs6 " & int2str(g_mcs_lqual_ranges[5].low) & " " & int2str(g_mcs_lqual_ranges[5].high) &
167 " mcs7 " & int2str(g_mcs_lqual_ranges[6].low) & " " & int2str(g_mcs_lqual_ranges[6].high) &
168 " mcs8 " & int2str(g_mcs_lqual_ranges[7].low) & " " & int2str(g_mcs_lqual_ranges[7].high) &
169 " mcs9 " & int2str(g_mcs_lqual_ranges[8].low);
170 f_vty_config2(PCUVTY, {"pcu"}, cmd);
171}
172
173private function f_init_vty(charstring id) runs on RAW_PCU_Test_CT {
174 map(self:PCUVTY, system:PCUVTY);
175 f_vty_set_prompts(PCUVTY);
176 f_vty_transceive(PCUVTY, "enable");
177}
178
Pau Espin Pedrolf787b092019-10-04 18:34:05 +0200179private function f_init_raw(charstring id, template (value) PCUIF_info_ind info_ind := ts_PCUIF_INFO_default)
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200180runs on RAW_PCU_Test_CT {
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200181 var RAW_PCUIF_CT vc_PCUIF;
182 var RAW_PCU_BTS_CT vc_BTS;
183
184 /* Start the guard timer */
185 g_T_guard.start;
186 activate(as_Tguard_RAW());
187
188 /* Init PCU interface component */
189 vc_PCUIF := RAW_PCUIF_CT.create("PCUIF-" & id);
190 connect(vc_PCUIF:MTC, self:PCUIF);
191 map(vc_PCUIF:PCU, system:PCU);
192
193 /* Create one BTS component (we may want more some day) */
194 vc_BTS := RAW_PCU_BTS_CT.create("BTS-" & id);
195 connect(vc_BTS:PCUIF, vc_PCUIF:BTS);
196 connect(vc_BTS:TC, self:BTS);
197
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100198 f_init_vty(id);
199
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200200 vc_PCUIF.start(f_PCUIF_CT_handler(mp_pcu_sock_path));
Pau Espin Pedrolf787b092019-10-04 18:34:05 +0200201 vc_BTS.start(f_BTS_CT_handler(0, valueof(info_ind)));
Vadim Yanitskiyf7d9c0f2019-09-06 00:08:17 +0200202
203 /* Wait until the BTS is ready (SI13 negotiated) */
204 BTS.receive(tr_RAW_PCU_EV(BTS_EV_SI13_NEGO));
205}
206
Pau Espin Pedrol89486332019-12-05 14:05:46 +0100207template AckNackDescription t_AckNackDescription_init := {
208 final_ack := '0'B,
209 starting_seq_nr := 0,
210 receive_block_bitmap := '0000000000000000000000000000000000000000000000000000000000000000'B
211}
212
213/* TS 44.060 sec 12.3 Ack/Nack Description */
214private function f_acknackdesc_ack_block(inout AckNackDescription desc, uint7_t bsn, BIT1 final_ack := '0'B)
215{
216 var integer i;
217 var integer inc := bsn - desc.starting_seq_nr + 1;
218 /* Filling hole? */
219 if (bsn < desc.starting_seq_nr) {
220 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - (desc.starting_seq_nr - bsn)] := int2bit(1, 1);
221 return;
222 }
223
224 /* SSN is increased, and so RBB values need to be moved */
225 for (i := 0; i < lengthof(desc.receive_block_bitmap) - inc; i := i+1) {
226 desc.receive_block_bitmap[i] := desc.receive_block_bitmap[i + inc];
227 }
228 for (i := lengthof(desc.receive_block_bitmap) - inc; i < lengthof(desc.receive_block_bitmap) - 1; i := i+1) {
229 desc.receive_block_bitmap[i] := int2bit(0, 1);
230 }
231 /* Now we can set current bit and update SSN */
232 desc.starting_seq_nr := bsn + 1;
233 desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - 1] := int2bit(1, 1);
234
235 /* Finally update the final_ack bit as requested: */
236 desc.final_ack := final_ack;
237}
238
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200239/* FIXME: properly encode RA (see TS 24.060, table 11.2.5.2) */
240private function f_establish_tbf(out GsmRrMessage rr_imm_ass, uint8_t bts_nr := 0,
241 uint16_t ra := oct2int('3A'O), uint8_t is_11bit := 0,
242 PCUIF_BurstType burst_type := BURST_TYPE_0,
243 TimingAdvance ta := 0)
244runs on RAW_PCU_Test_CT return boolean {
245 var PCUIF_Message pcu_msg;
246 var GsmRrMessage rr_msg;
247 var uint32_t fn;
248 timer T;
249
250 /* FIXME: ask the BTS component to give us the current TDMA fn */
251 fn := 1337 + ta;
252
253 /* Send RACH.ind */
254 log("Sending RACH.ind on fn=", fn, " with RA=", ra, ", TA=", ta);
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700255 BTS.send(ts_PCUIF_RACH_IND(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200256 ra := ra, is_11bit := is_11bit,
257 burst_type := burst_type,
258 fn := fn, arfcn := 871,
259 qta := ta * 4));
260
261 /* Expect Immediate (TBF) Assignment on TS0/AGCH */
262 T.start(2.0);
263 alt {
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700264 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := bts_nr, trx_nr := 0, ts_nr := 0,
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200265 sapi := PCU_IF_SAPI_AGCH, data := ?))
266 -> value pcu_msg {
267 rr_imm_ass := dec_GsmRrMessage(pcu_msg.u.data_req.data);
268 log("Rx Immediate Assignment: ", rr_imm_ass);
269
270 /* Make sure this assignment is for us
271 * TODO: Uplink or Downlink TBF? */
272 if (match(rr_imm_ass, tr_IMM_TBF_ASS(?, ra, fn))) {
273 setverdict(pass);
274 return true;
275 }
276
277 /* Not for us? Wait for more. */
278 repeat;
279 }
280 [] BTS.receive { repeat; }
281 [] T.timeout {
282 setverdict(fail, "Timeout waiting for Immediate Assignment");
283 }
284 }
285
286 return false;
287}
288
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200289private function f_imm_ass_verify_ul_tbf_ass(GsmRrMessage rr_imm_ass, out PacketUlAssign ul_tbf_ass)
290runs on RAW_PCU_Test_CT return boolean {
291
292 /* Make sure we received an UL TBF Assignment */
293 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
294 ul_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
295 log("Rx Uplink TBF assignment: ", ul_tbf_ass);
296 setverdict(pass);
297 } else {
298 setverdict(fail, "Failed to match UL TBF Assignment");
299 return false;
300 }
301
302 /* Make sure we have got a TBF with Dynamic Block Allocation */
303 if (ul_tbf_ass.dynamic == omit) {
304 setverdict(fail, "Single Block Allocation is not handled by ", testcasename());
305 return false;
306 }
307
308 return true;
309}
310
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +0200311private function f_imm_ass_verify_dl_tbf_ass(GsmRrMessage rr_imm_ass, out PacketDlAssign dl_tbf_ass)
312runs on RAW_PCU_Test_CT return boolean {
313
314 /* Make sure we received a DL TBF Assignment */
315 if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := true, rest := tr_IaRestOctets_DLAss(?)))) {
316 dl_tbf_ass := rr_imm_ass.payload.imm_ass.rest_octets.hh.pa.uldl.ass.dl;
317 log("Rx Downlink TBF assignment: ", dl_tbf_ass);
318 setverdict(pass);
319 } else {
320 setverdict(fail, "Failed to match DL TBF Assignment");
321 return false;
322 }
323
324 return true;
325}
326
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200327/* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100328private 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 +0200329runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100330 var template RAW_PCU_EventParam ev_param := {tdma_fn := ? };
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200331 BTS.send(ts_PCUIF_DATA_IND(bts_nr := 0, trx_nr := 0, ts_nr := 7, block_nr := 0,
332 sapi := PCU_IF_SAPI_PDTCH, data := data,
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100333 fn := fn, arfcn := 871, lqual_cb := lqual_cb));
334 if (fn != 0) {
335 ev_param := {tdma_fn := fn };
336 }
337 BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PDTCH_BLOCK_SENT, ev_param));
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200338}
339
340/* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
341private function f_pcuif_rx_data_req(out PCUIF_Message pcu_msg)
342runs on RAW_PCU_Test_CT {
343 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
344 sapi := PCU_IF_SAPI_PDTCH, fn := 0,
345 arfcn := 871, block_nr := 0));
346 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
347 sapi := PCU_IF_SAPI_PDTCH)) -> value pcu_msg;
348}
349
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +0200350/* Expect an Immediate Assignment (paging) from PCU on PCUIF on specified sapi. */
351private function f_pcuif_rx_pch_imm_tbf_ass(out GsmRrMessage rr_imm_ass)
352runs on RAW_PCU_Test_CT {
353 var PCUIF_Message pcu_msg;
354 var octetstring macblock;
355 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
356 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
357 /* First 3 bytes contain paging group: */
358 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
359 rr_imm_ass := dec_GsmRrMessage(macblock);
360 if (not match(rr_imm_ass, tr_IMM_TBF_ASS())) {
361 setverdict(fail, "Failed to match Immediate Assignment: ", rr_imm_ass);
362 mtc.stop;
363 }
364 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 +0100365 fn := pcu_msg.u.data_req.fn, arfcn := 871, sapi := PCU_IF_SAPI_PCH, data := macblock));
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +0200366}
367
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100368/* Expect a Paging Request Type 1 from PCU on PCUIF on specified sapi. */
Pau Espin Pedrol925818a2020-01-02 14:06:51 +0100369private function f_pcuif_rx_pch_pag_req1(out integer imsi_suff_rx, out GsmRrMessage rr_pag_req1)
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100370runs on RAW_PCU_Test_CT {
371 var PCUIF_Message pcu_msg;
Pau Espin Pedrol925818a2020-01-02 14:06:51 +0100372 var octetstring imsi_suff_octstr;
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100373 var octetstring macblock;
374 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
375 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
Pau Espin Pedrol925818a2020-01-02 14:06:51 +0100376 /* First 3 bytes contain IMSI suffix to calculate paging group: */
377 imsi_suff_octstr := substr(pcu_msg.u.data_req.data, 0, 3);
378 imsi_suff_rx := str2int(oct2char(imsi_suff_octstr[0])) * 100 +
379 str2int(oct2char(imsi_suff_octstr[1])) * 10 +
380 str2int(oct2char(imsi_suff_octstr[2]));
381
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +0100382 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
383 rr_pag_req1 := dec_GsmRrMessage(macblock);
384 if (not match(rr_pag_req1, tr_PAG_REQ1())) {
385 setverdict(fail, "Failed to match Paging Request Type 1: ", rr_pag_req1);
386 mtc.stop;
387 }
388 BTS.send(ts_PCUIF_DATA_CNF(bts_nr := 0, trx_nr := 0, ts_nr := 0, block_nr := 0,
389 fn := pcu_msg.u.data_req.fn, arfcn := 871, sapi := PCU_IF_SAPI_PCH, data := macblock));
390}
391
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100392private 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 +0200393runs on RAW_PCU_Test_CT {
394 var octetstring data;
395 /* Encode the payload of DATA.ind */
396 data := enc_RlcmacUlBlock(valueof(ul_data));
397 data := f_pad_oct(data, 23, '00'O); /* CS-1 */
398
399 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100400 f_pcuif_tx_data_ind(data, lqual_cb, fn);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200401}
402
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200403private function f_tx_rlcmac_ul_n_blocks(PacketUlAssign ul_tbf_ass, integer num_blocks := 1)
404runs on RAW_PCU_Test_CT {
405 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
406 tfi := ul_tbf_ass.dynamic.tfi_assignment,
407 cv := num_blocks - 1, /* num UL blocks to be sent (to be overridden in loop) */
408 bsn := 0, /* TODO: what should be here? */
409 blocks := { /* To be generated in loop */ });
410
411 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
412 ul_data.data.tlli := '00000001'O;
413
414 for (var integer i := 0; i < num_blocks; i := i + 1) {
415 /* Prepare a new UL block (CV, random payload) */
416 ul_data.data.mac_hdr.countdown := (num_blocks - i - 1);
417 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
418 f_tx_rlcmac_ul_block(ul_data);
419 }
420}
421
Pau Espin Pedroldc9666f2020-03-18 20:30:16 +0100422private 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 +0200423runs on RAW_PCU_Test_CT {
424 var PCUIF_Message pcu_msg;
425 f_pcuif_rx_data_req(pcu_msg);
426 dl_block := dec_RlcmacDlBlock(pcu_msg.u.data_req.data);
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100427 dl_fn := pcu_msg.u.data_req.fn;
Pau Espin Pedroldc9666f2020-03-18 20:30:16 +0100428
429 var integer len := lengthof(pcu_msg.u.data_req.data);
430 var CodingScheme cs_mcs := f_rlcmac_block_len2cs_mcs(len)
431 if (not match(f_rlcmac_block_len2cs_mcs(len), exp_cs_mcs)) {
432 setverdict(fail, "Failed to match Coding Scheme exp ", exp_cs_mcs, " vs ", cs_mcs, " (", len, ")");
433 mtc.stop;
434 }
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200435}
436
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100437private 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 +0200438runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100439 var uint32_t dl_fn;
440
441 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Pau Espin Pedrol21659632019-12-02 19:12:08 +0100442 if (not match(dl_block, tr_RLCMAC_UL_ACK_NACK(ul_tfi := ?, tlli := ?))) {
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200443 setverdict(fail, "Failed to match Packet Uplink ACK / NACK");
444 mtc.stop;
445 }
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100446
447 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200448}
449
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200450private function f_rx_rlcmac_dl_block_exp_dummy(out RlcmacDlBlock dl_block)
451runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100452 var uint32_t dl_fn;
453
454 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200455 if (not match(dl_block, tr_RLCMAC_DUMMY_CTRL())) {
456 setverdict(fail, "Failed to match Packet DUMMY DL");
457 mtc.stop;
458 }
459}
460
Pau Espin Pedrolff8da192019-12-05 17:23:58 +0100461private function f_rx_rlcmac_dl_block_exp_pkt_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
462runs on RAW_PCU_Test_CT {
463 var uint32_t dl_fn;
464
465 f_rx_rlcmac_dl_block(dl_block, dl_fn);
466 if (not match(dl_block, tr_RLCMAC_DL_PACKET_ASS())) {
467 setverdict(fail, "Failed to match Packet Downlink Assignment");
468 mtc.stop;
469 }
470
471 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
472}
473
Oliver Smith8f9daab2019-10-09 09:27:19 +0200474private function f_rx_rlcmac_dl_block_exp_pkt_pag_req(out RlcmacDlBlock dl_block)
475runs on RAW_PCU_Test_CT {
476 var uint32_t dl_fn;
477
478 f_rx_rlcmac_dl_block(dl_block, dl_fn);
479 if (not match(dl_block, tr_RLCMAC_PACKET_PAG_REQ())) {
480 setverdict(fail, "Failed to match Packet Paging Request: ", dl_block, " vs ", tr_RLCMAC_PACKET_PAG_REQ());
481 mtc.stop;
482 }
483}
484
Pau Espin Pedroldc9666f2020-03-18 20:30:16 +0100485private 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 +0100486runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100487 var PCUIF_Message pcu_msg;
488 var uint32_t dl_fn;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100489 var template RlcmacDlBlock dl_template := tr_RLCMAC_DATA_RRBP;
490 dl_template.data.blocks := ?;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100491
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100492 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100493 if (not match(dl_block, dl_template)) {
494 setverdict(fail, "Failed to match Packet data: ", dl_block, " vs ", dl_template);
495 mtc.stop;
496 }
Pau Espin Pedrol6e3b6892019-12-04 19:24:16 +0100497
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100498 ack_fn := dl_fn + f_rrbp_fn_delay(dl_block.data.mac_hdr.mac_hdr.rrbp);
499
Pau Espin Pedrol89486332019-12-05 14:05:46 +0100500 if (not match(dl_block.data.mac_hdr.hdr_ext.bsn, exp_bsn)) {
501 setverdict(fail, "DL block BSN doesn't match: ",
502 dl_block.data.blocks[0].hdr.length_ind, " vs exp ", exp_bsn);
503 }
504
Pau Espin Pedrol6e3b6892019-12-04 19:24:16 +0100505 if (lengthof(dl_block.data.blocks) < 1) {
506 setverdict(fail, "DL block has no LLC payload: ", dl_block);
507 mtc.stop;
508 }
509
510 if (ispresent(dl_block.data.blocks[0].hdr) and dl_block.data.blocks[0].hdr.length_ind != lengthof(data)) {
511 setverdict(fail, "DL block has LLC header with wrong expected size: ",
512 dl_block.data.blocks[0].hdr.length_ind, " vs ", lengthof(data));
513 mtc.stop;
514 }
515
516 if (dl_block.data.blocks[0].payload != data) {
517 setverdict(fail, "Failed to match content of LLC payload in DL Block: ", dl_block, " vs ", data);
518 mtc.stop;
519 }
520
521 /* Check next data blocks contain dummy frames */
522 if (lengthof(dl_block.data.blocks) > 1 and substr(dl_block.data.blocks[1].payload, 0, 3) != '43C001'O) {
523 setverdict(fail, "Second data payload is not a dummy frame: ", dl_block.data.blocks[1].payload);
524 mtc.stop;
525 }
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100526}
527
Vadim Yanitskiy740ae762019-09-29 16:13:41 +0700528testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
529 var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.cell_id.ra_id);
530 var GprsTlli tlli := 'FFFFFFFF'O;
531 timer T;
532
533 /* Initialize NS/BSSGP side */
534 f_init_bssgp();
535
536 /* Initialize the PCU interface abstraction */
537 f_init_raw(testcasename());
538
539 /* Establish BSSGP connection to the PCU */
540 f_bssgp_establish();
541
542 BTS.send(ts_PCUIF_SUSP_REQ(0, tlli, ra_id, 0));
543
544 T.start(2.0);
545 alt {
546 [] BSSGP_SIG[0].receive(tr_BSSGP_SUSPEND(tlli, mp_gb_cfg.cell_id.ra_id)) {
547 setverdict(pass);
548 }
549 [] T.timeout {
550 setverdict(fail, "Timeout waiting for BSSGP SUSPEND");
551 }
552 }
553}
554
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200555/* Test of correct Timing Advance at the time of TBF establishment
556 * (derived from timing offset of the Access Burst). */
557testcase TC_ta_rach_imm_ass() runs on RAW_PCU_Test_CT {
558 var GsmRrMessage rr_msg;
559 var boolean ok;
560
561 /* Initialize the PCU interface abstraction */
562 f_init_raw(testcasename());
563
564 /* We cannot send too many TBF requests in a short time because
565 * at some point the PCU will fail to allocate a new TBF. */
566 for (var TimingAdvance ta := 0; ta < 64; ta := ta + 16) {
567 /* Establish an Uplink TBF (send RACH.ind with current TA) */
568 ok := f_establish_tbf(rr_msg, bts_nr := 0, ta := ta);
569 if (not ok) {
570 setverdict(fail, "Failed to establish an Uplink TBF");
571 mtc.stop;
572 }
573
574 /* Make sure Timing Advance IE matches out expectations */
575 if (match(rr_msg, tr_IMM_TBF_ASS(dl := false, ta := ta))) {
576 setverdict(pass);
577 }
578 }
579}
580
Vadim Yanitskiy1f72b0a2019-10-01 05:58:45 +0700581/* Verify that the PCU generates valid PTCCH/D messages
582 * while neither Uplink nor Downlink TBF is established. */
583testcase TC_ta_ptcch_idle() runs on RAW_PCU_Test_CT {
584 var PTCCHDownlinkMsg ptcch_msg;
585 var PCUIF_Message pcu_msg;
586 timer T;
587
588 /* Initialize the PCU interface abstraction */
589 f_init_raw(testcasename());
590
591 /* Sent an RTS.req for PTCCH/D */
592 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
593 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
594 arfcn := 871, block_nr := 0));
595 T.start(5.0);
596 alt {
597 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
598 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
599 log("Rx DATA.req message: ", pcu_msg);
600 setverdict(pass);
601 }
602 [] BTS.receive(PCUIF_Message:?) { repeat; }
603 [] T.timeout {
604 setverdict(fail, "Timeout waiting for a PTCCH/D block");
605 mtc.stop;
606 }
607 }
608
609 ptcch_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
610 log("Decoded PTCCH/D message: ", ptcch_msg);
611
612 /* Make sure the message is encoded correctly
613 * TODO: do we expect all TA values to be equal '1111111'B? */
614 if (not match(ptcch_msg, tr_PTCCHDownlinkMsg)) {
615 setverdict(fail, "Malformed PTCCH/D message");
616 mtc.stop;
617 }
618}
619
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700620/* Test of correct Timing Advance during an active Uplink TBF.
621 *
622 * Unlike the circuit-switched domain, Uplink transmissions on PDCH time-slots
623 * are not continuous and there can be long time gaps between them. This happens
624 * due to a bursty nature of packet data. The actual Timing Advance of a MS may
625 * significantly change between such rare Uplink transmissions, so GPRS introduces
626 * additional mechanisms to control Timing Advance, and thus reduce interference
627 * between neighboring TDMA time-slots.
628 *
629 * At the moment of Uplink TBF establishment, initial Timing Advance is measured
630 * from ToA (Timing of Arrival) of an Access Burst. This is covered by another
631 * test case - TC_ta_rach_imm_ass. In response to that Access Burst the network
632 * sends Immediate Assignment on AGCH, which _may_ contain Timing Advance Index
633 * among with the initial Timing Advance value. And here PTCCH comes to play.
634 *
635 * PTCCH is a unidirectional channel on which the network can instruct a sub-set
636 * of 16 MS (whether TBFs are active or not) to adjust their Timing Advance
637 * continuously. To ensure continuous measurements of the signal propagation
638 * delay, the MSs shall transmit Access Bursts on Uplink (PTCCH/U) on sub-slots
639 * defined by an assigned Timing Advance Index (see 3GPP TS 45.002).
640 *
641 * The purpose of this test case is to verify the assignment of Timing Advance
642 * Index, and the process of Timing Advance notification on PTCCH/D. The MTC
643 * first establishes several Uplink TBFs, but does not transmit any Uplink
644 * blocks on them. During 4 TDMA multi-frame periods the MTC is sending RACH
645 * indications to the PCU, checking the correctness of two received PTCCH/D
646 * messages (period of PTCCH/D is two multi-frames).
647 */
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700648
649/* List of ToA values for Access Bursts to be sent on PTCCH/U,
650 * each ToA (Timing of Arrival) value is in units of 1/4 of
651 * a symbol (i.e. 1 symbol is 4 QTA units). */
652type record length(16) of int16_t PTCCH_TAI_ToA_MAP;
653const PTCCH_TAI_ToA_MAP ptcch_toa_map_def := {
654 0, 0, 0, 0,
655 0, 0, 0, 0,
656 0, 0, 0, 0,
657 0, 0, 0, 0
658};
659
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700660private 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 +0700661 in PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def)
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700662runs on RAW_PCU_Test_CT {
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700663 var RAW_PCU_Event event;
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700664 var integer ss;
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700665
666 /* Send Access Bursts on PTCCH/U for every TA Index */
667 [] BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PTCCH_UL_BURST)) -> value event {
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700668 ss := f_tdma_ptcch_fn2ss(event.data.tdma_fn);
669 if (ss < 0) { mtc.stop; } /* Shall not happen */
670
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700671 log("Sending an Access Burst on PTCCH/U",
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700672 ", sub-slot=", ss, " (TAI)",
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700673 ", fn=", event.data.tdma_fn,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700674 ", ToA=", toa_map[ss], " (QTA)");
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700675 /* TODO: do we care about RA and burst format? */
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700676 BTS.send(ts_PCUIF_RACH_IND(bts_nr, trx_nr, ts_nr,
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700677 ra := oct2int('3A'O),
678 is_11bit := 0,
679 burst_type := BURST_TYPE_0,
680 fn := event.data.tdma_fn,
681 arfcn := 871,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700682 qta := toa_map[ss],
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700683 sapi := PCU_IF_SAPI_PTCCH));
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700684 repeat;
685 }
686}
687
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700688private function f_TC_ta_ptcch_ul_multi_tbf(in PTCCH_TAI_ToA_MAP ptcch_toa_map,
689 template PTCCHDownlinkMsg t_ta_msg)
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700690runs on RAW_PCU_Test_CT {
691 var PTCCHDownlinkMsg ta_msg;
692 var PCUIF_Message pcu_msg;
693 timer T;
694
695 /* First, send an RTS.req for the upcoming PTCCH/D block */
696 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
697 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
698 arfcn := 871, block_nr := 0));
699 T.start(2.0);
700 alt {
701 /* Keep sending of Access Bursts during two multi-frames (period of PTCCH/D)
702 * with increasing ToA (Timing of Arrival) values: 0, 7, 14, 28, 35... */
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700703 [] as_ta_ptcch(bts_nr := 0, trx_nr := 0, ts_nr := 7, toa_map := ptcch_toa_map);
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700704 /* In the end of 2nd multi-frame we should receive a PTCCH/D block */
705 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
706 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
707 ta_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
708 log("Rx PTCCH/D message: ", ta_msg);
709
710 /* Make sure Timing Advance values match our expectations */
711 if (match(ta_msg, t_ta_msg)) {
712 setverdict(pass);
713 } else {
714 setverdict(fail, "PTCCH/D message does not match: ", t_ta_msg);
715 }
716 }
717 [] BTS.receive { repeat; }
718 [] T.timeout {
719 setverdict(fail, "Timeout waiting for a PTCCH/D block");
720 mtc.stop;
721 }
722 }
723}
724
725testcase TC_ta_ptcch_ul_multi_tbf() runs on RAW_PCU_Test_CT {
726 var template PacketUlAssign t_ul_tbf_ass;
727 var PacketUlAssign ul_tbf_ass[7];
728 var GsmRrMessage rr_msg[7];
729 var boolean ok;
730
731 /* Initialize the PCU interface abstraction */
732 f_init_raw(testcasename());
733
734 /* Enable forwarding of PTCCH/U TDMA events to us */
735 BTS.send(ts_RAW_PCU_CMD(TDMA_CMD_ENABLE_PTCCH_UL_FWD));
736
737 /* Establish 7 Uplink TBFs (USF flag is 3 bits long, '111'B is reserved) */
738 for (var integer i := 0; i < 7; i := i + 1) {
739 ok := f_establish_tbf(rr_msg[i], ta := 0);
740 if (not ok) {
741 setverdict(fail, "Failed to establish an Uplink TBF #", i);
742 mtc.stop;
743 }
744
745 /* Make sure we received an UL TBF Assignment */
746 if (match(rr_msg[i], tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
747 ul_tbf_ass[i] := rr_msg[i].payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
748 log("Rx Uplink TBF assignment for #", i, ": ", ul_tbf_ass[i]);
749 } else {
750 setverdict(fail, "Failed to match UL TBF Assignment for #", i);
751 mtc.stop;
752 }
753
754 /* We expect incremental TFI/USF assignment (dynamic allocation) */
755 t_ul_tbf_ass := tr_PacketUlDynAssign(tfi := i, usf := i);
756 if (not match(ul_tbf_ass[i], t_ul_tbf_ass)) {
757 setverdict(fail, "Failed to match Packet Uplink Assignment for #", i);
758 mtc.stop;
759 }
760
761 /* We also expect Timing Advance Index to be a part of the assignment */
762 if (ul_tbf_ass[i].dynamic.ta_index != i) {
763 setverdict(fail, "Failed to match Timing Advance Index for #", i);
764 /* Keep going, the current OsmoPCU does not assign TA Index */
765 }
766 }
767
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700768 /* Prepare a list of ToA values for Access Bursts to be sent on PTCCH/U */
769 var PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def;
770 for (var integer i := 0; i < 7; i := i + 1) {
771 /* ToA in units of 1/4 of a symbol */
772 toa_map[i] := (i + 1) * 7 * 4;
773 }
774
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700775 /* Now we have all 7 TBFs established in one-phase access mode,
776 * however we will not be sending any data on them. Instead, we
777 * will be sending RACH.ind on PTCCH/U during 4 multi-frame
778 * periods (TAI 0..8), and then will check two PTCCH/D blocks.
779 *
780 * Why not 4 TBFs at once? Because Uplink is delayed by 3 TDMA
781 * time-slots, so at the moment of scheduling a PTCCH/D block
782 * the PCU has odd number of PTCCH/U Access Bursts received. */
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700783 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700784 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
785 /* Other values are not known (yet) */
786 tai3_ta := ?));
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700787 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700788 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
789 tai3_ta := 28, tai4_ta := 35, tai5_ta := 42,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700790 /* Other values are out of our interest */
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700791 tai6_ta := ?));
792}
793
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700794/* Default link quality adaptation (Coding Scheme) ranges (inclusive).
795 * OsmoPCU (VTY): cs link-quality-ranges cs1 6 cs2 5 8 cs3 7 13 cs4 12
796 *
797 * NOTE: the ranges are intentionally overlapping because OsmoPCU
798 * does not change CS/MCS on the range borders (5-6, 7-8, 12-13). */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200799private template integer CS1_lqual_dB_range := (-infinity .. 6);
800private template integer CS2_lqual_dB_range := (5 .. 8);
801private template integer CS3_lqual_dB_range := (7 .. 13);
802private template integer CS4_lqual_dB_range := (12 .. infinity);
803
804testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200805 var GsmRrMessage rr_imm_ass;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200806 var PacketUlAssign ul_tbf_ass;
807 var RlcmacDlBlock dl_block;
808 var PCUIF_Message pcu_msg;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200809 var octetstring data;
810 var boolean ok;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100811 var uint32_t unused_fn;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200812
813 /* Initialize the PCU interface abstraction */
814 f_init_raw(testcasename());
815
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100816 f_pcuvty_set_allowed_cs_mcs();
817 f_pcuvty_set_link_quality_ranges();
818
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200819 /* Establish an Uplink TBF */
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200820 ok := f_establish_tbf(rr_imm_ass);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200821 if (not ok) {
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200822 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200823 mtc.stop;
824 }
825
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200826 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
827 if (not ok) {
828 setverdict(fail, "Immediate Assignment not an Uplink TBF");
Vadim Yanitskiy6276b6c2019-09-29 19:48:26 +0700829 mtc.stop;
830 }
831
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200832 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
833 tfi := ul_tbf_ass.dynamic.tfi_assignment,
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100834 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200835 bsn := 0, /* TODO: what should be here? */
836 blocks := { /* To be generated in loop */ });
837
838 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
839 ul_data.data.tlli := '00000001'O;
840
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700841 /* The actual / old link quality values. We need to keep track of the old
842 * (basically previous) link quality value, because OsmoPCU actually
843 * changes the coding scheme if not only the actual, but also the old
844 * value leaves the current link quality range (window). */
845 var integer lqual := 0;
846 var integer lqual_old;
847
848 /* 16 UL blocks (0 .. 15 dB, step = 1 dB) */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200849 for (var integer i := 0; i < 16; i := i + 1) {
850 /* Prepare a new UL block (CV, random payload) */
851 ul_data.data.mac_hdr.countdown := (15 - i);
852 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
853
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700854 /* Update the old / actual link quality */
855 lqual_old := lqual;
856 lqual := i;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200857
858 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
859 log("Sending DATA.ind with link quality (dB): ", lqual);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200860 f_tx_rlcmac_ul_block(ul_data, lqual * 10);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200861
862 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100863 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200864
865 log("Rx Packet Uplink ACK / NACK with Channel Coding Command: ",
866 dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd);
867
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700868 /* Match the received Channel Coding Command. Since we are increasing
869 * the link quality value on each iteration and not decreasing, there
870 * is no need to check the both old and current link quality values. */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200871 var template ChCodingCommand ch_coding;
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700872 select (lqual_old) {
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200873 case (CS1_lqual_dB_range) { ch_coding := CH_CODING_CS1; }
874 case (CS2_lqual_dB_range) { ch_coding := CH_CODING_CS2; }
875 case (CS3_lqual_dB_range) { ch_coding := CH_CODING_CS3; }
876 case (CS4_lqual_dB_range) { ch_coding := CH_CODING_CS4; }
877 }
878
879 if (not match(dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd, ch_coding)) {
880 setverdict(fail, "Channel Coding does not match our expectations: ", ch_coding);
881 } else {
882 setverdict(pass);
883 }
884 }
885}
886
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100887/* Test the max UL CS set by VTY works fine */
888testcase TC_cs_initial_ul() runs on RAW_PCU_Test_CT {
889 var GsmRrMessage rr_imm_ass;
890 var PacketUlAssign ul_tbf_ass;
891 var RlcmacDlBlock dl_block;
892 var boolean ok;
893 var integer lqual_cb;
894 var ChCodingCommand last_ch_coding;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100895 var uint32_t unused_fn;
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100896
897 /* Initialize the PCU interface abstraction */
898 f_init_raw(testcasename());
899
900 /* Set initial UL CS to 3 */
901 g_cs_initial_ul := 3;
902 f_pcuvty_set_allowed_cs_mcs();
903 f_pcuvty_set_link_quality_ranges();
904
905 /* Take lqual (dB->cB) so that we stay in that CS */
906 lqual_cb := g_cs_lqual_ranges[2].low * 10;
907
908 /* Establish an Uplink TBF */
909 ok := f_establish_tbf(rr_imm_ass);
910 if (not ok) {
911 setverdict(fail, "Failed to establish TBF");
912 mtc.stop;
913 }
914
915 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
916 if (not ok) {
917 setverdict(fail, "Immediate Assignment not an Uplink TBF");
918 mtc.stop;
919 }
920
921 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
922 tfi := ul_tbf_ass.dynamic.tfi_assignment,
923 cv := 3, /* 8 UL blocks to be sent (to be overridden in loop) */
924 bsn := 0, /* TODO: what should be here? */
925 blocks := { /* To be generated in loop */ });
926
927 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
928 ul_data.data.tlli := '00000001'O;
929
930 /* 3 UL blocks, check we are in same initial CS: */
931 for (var integer i := 0; i < 3; i := i + 1) {
932 /* Prepare a new UL block (CV, random payload) */
933 ul_data.data.mac_hdr.countdown := (7 - i);
934 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
935
936 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
937 f_tx_rlcmac_ul_block(ul_data, lqual_cb);
938
939 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100940 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100941 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
942 }
943
944 if (last_ch_coding != CH_CODING_CS3) {
945 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
946 mtc.stop;
947 }
948
949 setverdict(pass);
950
951 /* Remaining UL blocks are used to make sure regardless of initial
952 /* lqual, we can go lower at any time */
953
954 /* 5 UL blocks, check we are in same initial CS: */
955 for (var integer i := 3; i < 8; i := i + 1) {
956 /* Prepare a new UL block (CV, random payload) */
957 ul_data.data.mac_hdr.countdown := (7 - i);
958 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
959
960 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
961 f_tx_rlcmac_ul_block(ul_data, 0); /* 0 dB, make sure we downgrade CS */
962
963 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100964 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100965
966 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
967 }
968
969 if (last_ch_coding != CH_CODING_CS1) {
970 setverdict(fail, "Channel Coding does not match our expectations (CS-1): ", last_ch_coding);
971 } else {
972 setverdict(pass);
973 }
974}
975
976/* Test the max UL CS set by VTY works fine */
977testcase TC_cs_max_ul() runs on RAW_PCU_Test_CT {
978 var GsmRrMessage rr_imm_ass;
979 var PacketUlAssign ul_tbf_ass;
980 var RlcmacDlBlock dl_block;
981 var boolean ok;
982 var ChCodingCommand last_ch_coding;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100983 var uint32_t unused_fn;
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100984
985 /* Initialize the PCU interface abstraction */
986 f_init_raw(testcasename());
987
988 /* Set maximum allowed UL CS to 3 */
989 g_cs_max_ul := 3;
990 f_pcuvty_set_allowed_cs_mcs();
991 f_pcuvty_set_link_quality_ranges();
992
993 /* Establish an Uplink TBF */
994 ok := f_establish_tbf(rr_imm_ass);
995 if (not ok) {
996 setverdict(fail, "Failed to establish TBF");
997 mtc.stop;
998 }
999
1000 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1001 if (not ok) {
1002 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1003 mtc.stop;
1004 }
1005
1006 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
1007 tfi := ul_tbf_ass.dynamic.tfi_assignment,
1008 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
1009 bsn := 0, /* TODO: what should be here? */
1010 blocks := { /* To be generated in loop */ });
1011
1012 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
1013 ul_data.data.tlli := '00000001'O;
1014
1015 /* 16 UL blocks */
1016 for (var integer i := 0; i < 16; i := i + 1) {
1017 /* Prepare a new UL block (CV, random payload) */
1018 ul_data.data.mac_hdr.countdown := (15 - i);
1019 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
1020
1021 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
1022 f_tx_rlcmac_ul_block(ul_data, 40*10); /* 40 dB */
1023
1024 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001025 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001026
1027 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1028 }
1029
1030 if (last_ch_coding != CH_CODING_CS3) {
1031 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
1032 } else {
1033 setverdict(pass);
1034 }
1035}
1036
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001037/* Verify PCU drops TBF after some time of inactivity. */
1038testcase TC_t3169() runs on RAW_PCU_Test_CT {
1039 var PCUIF_info_ind info_ind;
1040 var GsmRrMessage rr_imm_ass;
1041 var PacketUlAssign ul_tbf_ass;
1042 var RlcmacDlBlock dl_block;
1043 var PCUIF_Message pcu_msg;
1044 var octetstring data;
1045 var boolean ok;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001046 var uint32_t unused_fn;
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001047 var OCT4 tlli := '00000001'O;
1048
1049 /* Initialize NS/BSSGP side */
1050 f_init_bssgp();
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001051
1052 info_ind := valueof(ts_PCUIF_INFO_default);
1053 /* Set timer to 1 sec (default 5) to speedup test: */
1054 info_ind.t3169 := 1;
1055
1056 /* Initialize the PCU interface abstraction */
1057 f_init_raw(testcasename(), info_ind);
1058
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001059 /* Establish BSSGP connection to the PCU */
1060 f_bssgp_establish();
1061 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1062
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001063 /* Establish an Uplink TBF */
1064 ok := f_establish_tbf(rr_imm_ass);
1065 if (not ok) {
1066 setverdict(fail, "Failed to establish TBF");
1067 mtc.stop;
1068 }
1069
1070 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1071 if (not ok) {
1072 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1073 mtc.stop;
1074 }
1075
1076 /* Send one UL block and make sure it is ACKED fine */
1077 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001078 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001079 /* UL block should be received in SGSN */
1080 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001081
1082 /* Wait until T3169 fires (plus 1 extra sec to make sure) */
1083 f_sleep(int2float(info_ind.t3169) + 1.0);
1084
1085 /* Send an UL block once again, the TBF should be gone by now so no ACK */
1086 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1087 f_rx_rlcmac_dl_block_exp_dummy(dl_block);
1088}
1089
Pau Espin Pedrolff8da192019-12-05 17:23:58 +01001090/* Verify that a Downlink TBF can be assigned using PACCH shortly after the
1091 * release of prev DL TBF due to MS staying in PDCH for a while (T3192, in PCU
1092 * T3193) after DL TBF release */
1093testcase TC_t3193() runs on RAW_PCU_Test_CT {
1094 var GsmRrMessage rr_imm_ass;
1095 var PacketDlAssign dl_tbf_ass;
1096 var RlcmacDlBlock dl_block;
1097 var octetstring data := f_rnd_octstring(10);
1098 var boolean ok;
1099 var uint32_t sched_fn;
1100 var OCT4 tlli := '00000001'O;
1101 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1102
1103 /* Initialize NS/BSSGP side */
1104 f_init_bssgp();
1105
1106 /* Initialize the PCU interface abstraction */
1107 f_init_raw(testcasename());
1108
1109 /* Establish BSSGP connection to the PCU */
1110 f_bssgp_establish();
1111 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1112
1113 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1114 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1115 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1116 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1117 if (not ok) {
1118 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1119 mtc.stop;
1120 }
1121 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1122 f_sleep(X2002);
1123 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1124
1125 /* ACK the DL block */
1126 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1127 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1128 /* we are done with the DL-TBF here so far, let's clean up our local state: */
1129 ack_nack_desc := valueof(t_AckNackDescription_init)
1130
1131 /* Now that final DL block is ACKED and TBF is released, T3193 in PCU
1132 (T3192 in MS) was started and until it fires the MS will be abailable
1133 on PDCH in case new data arrives from SGSN. Let's verify it: */
1134 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1135 f_rx_rlcmac_dl_block_exp_pkt_ass(dl_block, sched_fn);
1136 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1137
1138 /* Now that we confirmed the new assignment in the dl-tbf, lets receive the data and ack it */
1139 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1140 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1141 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1142}
1143
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001144/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1145 * answered, so TBFs for uplink and later for downlink are created.
1146 */
1147testcase TC_mo_ping_pong() runs on RAW_PCU_Test_CT {
1148 var GsmRrMessage rr_imm_ass;
1149 var PacketUlAssign ul_tbf_ass;
1150 var PacketDlAssign dl_tbf_ass;
1151 var RlcmacDlBlock dl_block;
1152 var PCUIF_Message pcu_msg;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001153 var octetstring data := f_rnd_octstring(10);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001154 var boolean ok;
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +01001155 var uint32_t sched_fn;
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001156 var OCT4 tlli := '00000001'O;
Pau Espin Pedrol89486332019-12-05 14:05:46 +01001157 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001158
1159 /* Initialize NS/BSSGP side */
1160 f_init_bssgp();
1161
1162 /* Initialize the PCU interface abstraction */
1163 f_init_raw(testcasename());
1164
1165 /* Establish BSSGP connection to the PCU */
1166 f_bssgp_establish();
1167 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1168
1169 /* Establish an Uplink TBF */
1170 ok := f_establish_tbf(rr_imm_ass);
1171 if (not ok) {
1172 setverdict(fail, "Failed to establish TBF");
1173 mtc.stop;
1174 }
1175 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1176 if (not ok) {
1177 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1178 mtc.stop;
1179 }
1180
1181 /* Send one UL block and make sure it is ACKED fine */
1182 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001183 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1184 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1185 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001186
1187 /* UL block should be received in SGSN */
1188 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1189
1190 /* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001191 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001192 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1193
1194 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1195 if (not ok) {
1196 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1197 mtc.stop;
1198 }
1199
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001200 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1201 f_sleep(X2002);
Pau Espin Pedrol89486332019-12-05 14:05:46 +01001202 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001203
1204 /* ACK the DL block */
Pau Espin Pedrol89486332019-12-05 14:05:46 +01001205 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 +01001206 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 +02001207}
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001208
Pau Espin Pedrole7cabe62020-01-23 14:35:15 +01001209/* Test scenario where SGSN wants to send some data against MS and it is
1210 * answered by the MS on PDCH, so TBFs for downlink and later for uplink are created.
1211 */
Pau Espin Pedroldc9666f2020-03-18 20:30:16 +01001212private 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 +01001213 var GsmRrMessage rr_imm_ass;
1214 var PacketUlAssign ul_tbf_ass;
1215 var PacketDlAssign dl_tbf_ass;
1216 var RlcmacDlBlock dl_block;
1217 var PCUIF_Message pcu_msg;
1218 var octetstring data := f_rnd_octstring(10);
1219 var boolean ok;
1220 var uint32_t sched_fn;
1221 var OCT4 tlli := '00000001'O;
1222 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1223
1224 /* Initialize NS/BSSGP side */
1225 f_init_bssgp();
1226
1227 /* Initialize the PCU interface abstraction */
1228 f_init_raw(testcasename());
1229
1230 /* Establish BSSGP connection to the PCU */
1231 f_bssgp_establish();
1232 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1233
1234 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
Pau Espin Pedrol2422d1f2020-01-23 17:51:04 +01001235 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data, ms_racap));
Pau Espin Pedrole7cabe62020-01-23 14:35:15 +01001236 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1237
1238 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1239 if (not ok) {
1240 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1241 mtc.stop;
1242 }
1243
1244 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1245 f_sleep(X2002);
Pau Espin Pedroldc9666f2020-03-18 20:30:16 +01001246 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0, exp_cs_mcs);
Pau Espin Pedrole7cabe62020-01-23 14:35:15 +01001247
1248 /* ACK the DL block */
1249 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1250 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1251
1252 /* Now MS wants to answer the DL data, Establish an Uplink TBF */
1253 ok := f_establish_tbf(rr_imm_ass);
1254 if (not ok) {
1255 setverdict(fail, "Failed to establish TBF");
1256 mtc.stop;
1257 }
1258 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1259 if (not ok) {
1260 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1261 mtc.stop;
1262 }
1263
1264 /* Send one UL block and make sure it is ACKED fine */
1265 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1266 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1267 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1268 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1269
1270 /* UL block should be received in SGSN */
1271 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1272}
1273
Pau Espin Pedrol2422d1f2020-01-23 17:51:04 +01001274testcase TC_mt_ping_pong() runs on RAW_PCU_Test_CT {
Pau Espin Pedroldc9666f2020-03-18 20:30:16 +01001275 var CodingScheme exp_cs_mcs := CS_1;
1276 f_TC_mt_ping_pong(omit, exp_cs_mcs);
Pau Espin Pedrol2422d1f2020-01-23 17:51:04 +01001277}
1278
1279/* TC_mt_ping_pong, but DL-UNITDATA contains RA Access capability with (M)CS
1280/* information about the MS */
1281testcase TC_mt_ping_pong_with_dl_racap() runs on RAW_PCU_Test_CT {
1282 var MultislotCap_GPRS_BSSGP mscap_gprs := {
1283 gprsmultislotclass := '00011'B,
1284 gprsextendeddynalloccap := '0'B
1285 } ;
1286 var MSRadioAccessCapabilityV_BSSGP ms_racap := { valueof(ts_RaCapRec_BSSGP('0001'B /* E-GSM */, mscap_gprs, omit)) };
Pau Espin Pedroldc9666f2020-03-18 20:30:16 +01001287 var CodingScheme exp_cs_mcs := CS_2;
1288 f_TC_mt_ping_pong(ms_racap, exp_cs_mcs);
Pau Espin Pedrol2422d1f2020-01-23 17:51:04 +01001289}
1290
Pau Espin Pedrola7b75662019-12-05 16:39:55 +01001291/* Verify that if PCU doesn't get an ACK for first DL block after IMM ASS, it
1292 * will retry by retransmitting both the IMM ASS + DL block after poll (ack)
1293 * timeout occurs (specified by sent RRBP on DL block). */
1294testcase TC_imm_ass_dl_block_retrans() runs on RAW_PCU_Test_CT {
1295 var GsmRrMessage rr_imm_ass;
1296 var PacketDlAssign dl_tbf_ass;
1297 var RlcmacDlBlock dl_block;
1298 var octetstring data := f_rnd_octstring(10);
1299 var boolean ok;
1300 var uint32_t sched_fn;
1301 var OCT4 tlli := '00000001'O;
1302 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1303
1304 /* Initialize NS/BSSGP side */
1305 f_init_bssgp();
1306
1307 /* Initialize the PCU interface abstraction */
1308 f_init_raw(testcasename());
1309
1310 /* Establish BSSGP connection to the PCU */
1311 f_bssgp_establish();
1312 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1313
1314 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1315 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1316 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1317 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1318 if (not ok) {
1319 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1320 mtc.stop;
1321 }
1322
1323 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1324 f_sleep(X2002);
1325 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1326
1327 /* Now we don't ack the dl block (emulate MS failed receiveing IMM ASS
1328 * or GPRS DL, or DL ACK was lost for some reason). As a result, PCU
1329 * should retrigger IMM ASS + GPRS DL procedure after poll timeout. */
1330 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1331 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1332 if (not ok) {
1333 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1334 mtc.stop;
1335 }
1336 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1337 f_sleep(X2002);
1338 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1339
1340 /* ACK the DL block */
1341 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1342 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1343}
1344
Vadim Yanitskiy322c7932020-01-01 23:03:47 +01001345private function f_pkt_paging_match_imsi(in PacketPagingReq req, hexstring imsi) {
1346 var MobileIdentityLV_Paging mi_lv := req.repeated_pageinfo.cs.mobile_identity;
1347 var MobileIdentityV mi := dec_MobileIdentityV(mi_lv.mobile_id);
1348
1349 if (mi_lv.len != 8) { /* 8 octets: type of ID (3 bits) + even/odd flag (1 bit) + 15 BCD-encoded digits (60 bits) */
1350 setverdict(fail, "Mobile Identity length mismatch: ",
1351 "expected: 8, got: ", mi_lv.len);
1352 mtc.stop;
1353 }
1354
1355 /* Make sure MI contains IMSI before referencing it */
1356 if (mi.typeOfIdentity != '001'B) {
1357 setverdict(fail, "Mobile Identity must be of type IMSI ('001'B), ",
1358 "got: ", mi.typeOfIdentity);
1359 mtc.stop;
1360 } else if (mi.oddEvenInd_identity.imsi.digits != imsi) {
1361 setverdict(fail, "Mobile Identity contains unexpected IMSI, ",
1362 "expected: ", imsi, " got: ", mi.oddEvenInd_identity.imsi.digits);
1363 mtc.stop;
1364 }
1365}
1366
Oliver Smith8f9daab2019-10-09 09:27:19 +02001367/* Test CS paging over the BTS<->PCU socket.
1368 * 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.
1369 * Paging should be send on the PACCH.
1370 *
1371 * 1. Send a Paging Request over PCU socket.
1372 * 2. Send a Ready-To-Send message over PCU socket
1373 * 3. Expect a Paging Frame
1374 */
1375testcase TC_paging_cs_from_bts() runs on RAW_PCU_Test_CT {
1376 var GsmRrMessage rr_imm_ass;
1377 var PacketUlAssign ul_tbf_ass;
1378 var RlcmacDlBlock dl_block;
1379 var boolean ok;
1380 var OCT4 tlli := '00000001'O;
1381 var MobileL3_CommonIE_Types.MobileIdentityLV mi;
1382 var octetstring mi_enc_lv;
Oliver Smith8f9daab2019-10-09 09:27:19 +02001383 var hexstring imsi := f_gen_imsi(42);
1384
1385 /* Initialize NS/BSSGP side */
1386 f_init_bssgp();
1387
1388 /* Initialize the PCU interface abstraction */
1389 f_init_raw(testcasename());
1390
1391 /* Establish BSSGP connection to the PCU */
1392 f_bssgp_establish();
1393 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1394
1395 /* Establish an Uplink TBF */
1396 ok := f_establish_tbf(rr_imm_ass);
1397 if (not ok) {
1398 setverdict(fail, "Failed to establish TBF");
1399 mtc.stop;
1400 }
1401
1402 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1403 if (not ok) {
1404 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1405 mtc.stop;
1406 }
1407
1408
1409 /* build mobile Identity */
1410 mi := valueof(ts_MI_IMSI_LV(imsi));
1411 mi_enc_lv := enc_MobileIdentityLV(mi);
1412 /* Send paging request */
1413 BTS.send(ts_PCUIF_PAG_REQ(bts_nr := 0, id_lv := mi_enc_lv, chan_needed := 0,
1414 sapi :=PCU_IF_SAPI_PDTCH));
1415
1416 /* Receive it on BTS side towards MS */
1417 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
Vadim Yanitskiy5e518732020-01-01 21:27:18 +01001418
Vadim Yanitskiy322c7932020-01-01 23:03:47 +01001419 /* Make sure that Packet Paging Request contains the same IMSI */
1420 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1421
Oliver Smith8f9daab2019-10-09 09:27:19 +02001422 setverdict(pass);
1423}
1424
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001425/* Test CS paging over Gb (SGSN->PCU->BTS[PDCH]).
1426 */
1427private function f_tc_paging_cs_from_sgsn(Nsvci bvci) runs on RAW_PCU_Test_CT {
1428 var GsmRrMessage rr_imm_ass;
1429 var PacketUlAssign ul_tbf_ass;
1430 var RlcmacDlBlock dl_block;
1431 var boolean ok;
1432 var OCT4 tlli := '00000001'O;
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001433 var hexstring imsi := f_gen_imsi(42);
1434
1435 /* Initialize NS/BSSGP side */
1436 f_init_bssgp();
1437
1438 /* Initialize the PCU interface abstraction */
1439 f_init_raw(testcasename());
1440
1441 /* Establish BSSGP connection to the PCU */
1442 f_bssgp_establish();
1443 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1444
1445 /* Establish an Uplink TBF */
1446 ok := f_establish_tbf(rr_imm_ass);
1447 if (not ok) {
1448 setverdict(fail, "Failed to establish TBF");
1449 mtc.stop;
1450 }
1451
1452 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1453 if (not ok) {
1454 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1455 mtc.stop;
1456 }
1457
1458 /* Send paging request */
1459 BSSGP[0].send(ts_BSSGP_CS_PAGING_IMSI(bvci, imsi));
1460
1461 /* Receive it on BTS side towards MS */
1462 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
1463
Vadim Yanitskiy322c7932020-01-01 23:03:47 +01001464 /* Make sure that Packet Paging Request contains the same IMSI */
1465 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1466
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001467 setverdict(pass);
1468}
1469
1470testcase TC_paging_cs_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1471 f_tc_paging_cs_from_sgsn(0);
1472}
1473
1474testcase TC_paging_cs_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1475 f_tc_paging_cs_from_sgsn(mp_gb_cfg.bvci);
1476}
1477
1478/* Test PS paging over Gb (SGSN->PCU->BTS[CCCH]).
1479 */
1480private function f_tc_paging_ps_from_sgsn(Nsvci bvci) runs on RAW_PCU_Test_CT {
1481 var GsmRrMessage rr_pag_req1;
1482 var OCT4 tlli := '00000001'O;
Pau Espin Pedrol925818a2020-01-02 14:06:51 +01001483 var integer imsi_suff_rx;
1484 var integer imsi_suff_tx := 423;
1485 var hexstring imsi := f_gen_imsi(imsi_suff_tx);
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001486
1487 /* Initialize NS/BSSGP side */
1488 f_init_bssgp();
1489
1490 /* Initialize the PCU interface abstraction */
1491 f_init_raw(testcasename());
1492
1493 /* Establish BSSGP connection to the PCU */
1494 f_bssgp_establish();
1495 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1496
1497 /* Send paging request */
1498 BSSGP[0].send(ts_BSSGP_PS_PAGING_IMSI(bvci, imsi));
1499
1500 /* Receive it on BTS side towards MS */
Pau Espin Pedrol925818a2020-01-02 14:06:51 +01001501 f_pcuif_rx_pch_pag_req1(imsi_suff_rx, rr_pag_req1);
1502 if (imsi_suff_rx != imsi_suff_tx) {
1503 setverdict(fail, "Wrong IMSI suffix: expected ", imsi_suff_tx, " but received ", imsi_suff_rx);
1504 mtc.stop;
1505 }
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001506
1507 setverdict(pass);
1508}
1509
1510testcase TC_paging_ps_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1511 f_tc_paging_ps_from_sgsn(0);
1512}
1513
1514testcase TC_paging_ps_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1515 f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvci);
1516}
1517
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001518control {
Harald Welte7fd25cf2019-03-21 22:14:02 +01001519 execute( TC_pcuif_suspend() );
Vadim Yanitskiy1f72b0a2019-10-01 05:58:45 +07001520 execute( TC_ta_ptcch_idle() );
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +02001521 execute( TC_ta_rach_imm_ass() );
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001522 execute( TC_ta_ptcch_ul_multi_tbf() );
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001523 execute( TC_cs_lqual_ul_tbf() );
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001524 execute( TC_cs_initial_ul() );
1525 execute( TC_cs_max_ul() );
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001526 execute( TC_t3169() );
Pau Espin Pedrolff8da192019-12-05 17:23:58 +01001527 execute( TC_t3193() );
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001528 execute( TC_mo_ping_pong() );
Pau Espin Pedrole7cabe62020-01-23 14:35:15 +01001529 execute( TC_mt_ping_pong() );
Pau Espin Pedrol2422d1f2020-01-23 17:51:04 +01001530 execute( TC_mt_ping_pong_with_dl_racap() );
Pau Espin Pedrola7b75662019-12-05 16:39:55 +01001531 execute( TC_imm_ass_dl_block_retrans() );
Oliver Smith8f9daab2019-10-09 09:27:19 +02001532 execute( TC_paging_cs_from_bts() );
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001533 execute (TC_paging_cs_from_sgsn_sign() );
1534 execute (TC_paging_cs_from_sgsn_ptp() );
1535 execute (TC_paging_ps_from_sgsn_sign() );
1536 execute (TC_paging_ps_from_sgsn_ptp() );
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001537}
1538
1539
1540
1541
1542
1543
1544}