blob: d0181a9e1c549d9185cadc7452886d0f6fef4c3c [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. */
369private function f_pcuif_rx_pch_pag_req1(out GsmRrMessage rr_pag_req1)
370runs on RAW_PCU_Test_CT {
371 var PCUIF_Message pcu_msg;
372 var octetstring macblock;
373 BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
374 sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
375 /* First 3 bytes contain paging group: */
376 macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
377 rr_pag_req1 := dec_GsmRrMessage(macblock);
378 if (not match(rr_pag_req1, tr_PAG_REQ1())) {
379 setverdict(fail, "Failed to match Paging Request Type 1: ", rr_pag_req1);
380 mtc.stop;
381 }
382 BTS.send(ts_PCUIF_DATA_CNF(bts_nr := 0, trx_nr := 0, ts_nr := 0, block_nr := 0,
383 fn := pcu_msg.u.data_req.fn, arfcn := 871, sapi := PCU_IF_SAPI_PCH, data := macblock));
384}
385
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100386private 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 +0200387runs on RAW_PCU_Test_CT {
388 var octetstring data;
389 /* Encode the payload of DATA.ind */
390 data := enc_RlcmacUlBlock(valueof(ul_data));
391 data := f_pad_oct(data, 23, '00'O); /* CS-1 */
392
393 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100394 f_pcuif_tx_data_ind(data, lqual_cb, fn);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200395}
396
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200397private function f_tx_rlcmac_ul_n_blocks(PacketUlAssign ul_tbf_ass, integer num_blocks := 1)
398runs on RAW_PCU_Test_CT {
399 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
400 tfi := ul_tbf_ass.dynamic.tfi_assignment,
401 cv := num_blocks - 1, /* num UL blocks to be sent (to be overridden in loop) */
402 bsn := 0, /* TODO: what should be here? */
403 blocks := { /* To be generated in loop */ });
404
405 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
406 ul_data.data.tlli := '00000001'O;
407
408 for (var integer i := 0; i < num_blocks; i := i + 1) {
409 /* Prepare a new UL block (CV, random payload) */
410 ul_data.data.mac_hdr.countdown := (num_blocks - i - 1);
411 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
412 f_tx_rlcmac_ul_block(ul_data);
413 }
414}
415
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100416private function f_rx_rlcmac_dl_block(out RlcmacDlBlock dl_block, out uint32_t dl_fn)
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200417runs on RAW_PCU_Test_CT {
418 var PCUIF_Message pcu_msg;
419 f_pcuif_rx_data_req(pcu_msg);
420 dl_block := dec_RlcmacDlBlock(pcu_msg.u.data_req.data);
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100421 dl_fn := pcu_msg.u.data_req.fn;
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200422}
423
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100424private 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 +0200425runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100426 var uint32_t dl_fn;
427
428 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Pau Espin Pedrol21659632019-12-02 19:12:08 +0100429 if (not match(dl_block, tr_RLCMAC_UL_ACK_NACK(ul_tfi := ?, tlli := ?))) {
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200430 setverdict(fail, "Failed to match Packet Uplink ACK / NACK");
431 mtc.stop;
432 }
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100433
434 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200435}
436
Pau Espin Pedrol596faa42019-10-04 19:31:29 +0200437private function f_rx_rlcmac_dl_block_exp_dummy(out RlcmacDlBlock dl_block)
438runs 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 Pedrol596faa42019-10-04 19:31:29 +0200442 if (not match(dl_block, tr_RLCMAC_DUMMY_CTRL())) {
443 setverdict(fail, "Failed to match Packet DUMMY DL");
444 mtc.stop;
445 }
446}
447
Pau Espin Pedrolff8da192019-12-05 17:23:58 +0100448private function f_rx_rlcmac_dl_block_exp_pkt_ass(out RlcmacDlBlock dl_block, out uint32_t poll_fn)
449runs on RAW_PCU_Test_CT {
450 var uint32_t dl_fn;
451
452 f_rx_rlcmac_dl_block(dl_block, dl_fn);
453 if (not match(dl_block, tr_RLCMAC_DL_PACKET_ASS())) {
454 setverdict(fail, "Failed to match Packet Downlink Assignment");
455 mtc.stop;
456 }
457
458 poll_fn := dl_fn + f_rrbp_fn_delay(dl_block.ctrl.mac_hdr.rrbp);
459}
460
Oliver Smith8f9daab2019-10-09 09:27:19 +0200461private function f_rx_rlcmac_dl_block_exp_pkt_pag_req(out RlcmacDlBlock dl_block)
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_PACKET_PAG_REQ())) {
467 setverdict(fail, "Failed to match Packet Paging Request: ", dl_block, " vs ", tr_RLCMAC_PACKET_PAG_REQ());
468 mtc.stop;
469 }
470}
471
Pau Espin Pedrol89486332019-12-05 14:05:46 +0100472private 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 := ?)
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100473runs on RAW_PCU_Test_CT {
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100474 var PCUIF_Message pcu_msg;
475 var uint32_t dl_fn;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100476 var template RlcmacDlBlock dl_template := tr_RLCMAC_DATA_RRBP;
477 dl_template.data.blocks := ?;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100478
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100479 f_rx_rlcmac_dl_block(dl_block, dl_fn);
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100480 if (not match(dl_block, dl_template)) {
481 setverdict(fail, "Failed to match Packet data: ", dl_block, " vs ", dl_template);
482 mtc.stop;
483 }
Pau Espin Pedrol6e3b6892019-12-04 19:24:16 +0100484
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +0100485 ack_fn := dl_fn + f_rrbp_fn_delay(dl_block.data.mac_hdr.mac_hdr.rrbp);
486
Pau Espin Pedrol89486332019-12-05 14:05:46 +0100487 if (not match(dl_block.data.mac_hdr.hdr_ext.bsn, exp_bsn)) {
488 setverdict(fail, "DL block BSN doesn't match: ",
489 dl_block.data.blocks[0].hdr.length_ind, " vs exp ", exp_bsn);
490 }
491
Pau Espin Pedrol6e3b6892019-12-04 19:24:16 +0100492 if (lengthof(dl_block.data.blocks) < 1) {
493 setverdict(fail, "DL block has no LLC payload: ", dl_block);
494 mtc.stop;
495 }
496
497 if (ispresent(dl_block.data.blocks[0].hdr) and dl_block.data.blocks[0].hdr.length_ind != lengthof(data)) {
498 setverdict(fail, "DL block has LLC header with wrong expected size: ",
499 dl_block.data.blocks[0].hdr.length_ind, " vs ", lengthof(data));
500 mtc.stop;
501 }
502
503 if (dl_block.data.blocks[0].payload != data) {
504 setverdict(fail, "Failed to match content of LLC payload in DL Block: ", dl_block, " vs ", data);
505 mtc.stop;
506 }
507
508 /* Check next data blocks contain dummy frames */
509 if (lengthof(dl_block.data.blocks) > 1 and substr(dl_block.data.blocks[1].payload, 0, 3) != '43C001'O) {
510 setverdict(fail, "Second data payload is not a dummy frame: ", dl_block.data.blocks[1].payload);
511 mtc.stop;
512 }
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +0100513}
514
Vadim Yanitskiy740ae762019-09-29 16:13:41 +0700515testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
516 var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.cell_id.ra_id);
517 var GprsTlli tlli := 'FFFFFFFF'O;
518 timer T;
519
520 /* Initialize NS/BSSGP side */
521 f_init_bssgp();
522
523 /* Initialize the PCU interface abstraction */
524 f_init_raw(testcasename());
525
526 /* Establish BSSGP connection to the PCU */
527 f_bssgp_establish();
528
529 BTS.send(ts_PCUIF_SUSP_REQ(0, tlli, ra_id, 0));
530
531 T.start(2.0);
532 alt {
533 [] BSSGP_SIG[0].receive(tr_BSSGP_SUSPEND(tlli, mp_gb_cfg.cell_id.ra_id)) {
534 setverdict(pass);
535 }
536 [] T.timeout {
537 setverdict(fail, "Timeout waiting for BSSGP SUSPEND");
538 }
539 }
540}
541
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +0200542/* Test of correct Timing Advance at the time of TBF establishment
543 * (derived from timing offset of the Access Burst). */
544testcase TC_ta_rach_imm_ass() runs on RAW_PCU_Test_CT {
545 var GsmRrMessage rr_msg;
546 var boolean ok;
547
548 /* Initialize the PCU interface abstraction */
549 f_init_raw(testcasename());
550
551 /* We cannot send too many TBF requests in a short time because
552 * at some point the PCU will fail to allocate a new TBF. */
553 for (var TimingAdvance ta := 0; ta < 64; ta := ta + 16) {
554 /* Establish an Uplink TBF (send RACH.ind with current TA) */
555 ok := f_establish_tbf(rr_msg, bts_nr := 0, ta := ta);
556 if (not ok) {
557 setverdict(fail, "Failed to establish an Uplink TBF");
558 mtc.stop;
559 }
560
561 /* Make sure Timing Advance IE matches out expectations */
562 if (match(rr_msg, tr_IMM_TBF_ASS(dl := false, ta := ta))) {
563 setverdict(pass);
564 }
565 }
566}
567
Vadim Yanitskiy1f72b0a2019-10-01 05:58:45 +0700568/* Verify that the PCU generates valid PTCCH/D messages
569 * while neither Uplink nor Downlink TBF is established. */
570testcase TC_ta_ptcch_idle() runs on RAW_PCU_Test_CT {
571 var PTCCHDownlinkMsg ptcch_msg;
572 var PCUIF_Message pcu_msg;
573 timer T;
574
575 /* Initialize the PCU interface abstraction */
576 f_init_raw(testcasename());
577
578 /* Sent an RTS.req for PTCCH/D */
579 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
580 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
581 arfcn := 871, block_nr := 0));
582 T.start(5.0);
583 alt {
584 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
585 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
586 log("Rx DATA.req message: ", pcu_msg);
587 setverdict(pass);
588 }
589 [] BTS.receive(PCUIF_Message:?) { repeat; }
590 [] T.timeout {
591 setverdict(fail, "Timeout waiting for a PTCCH/D block");
592 mtc.stop;
593 }
594 }
595
596 ptcch_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
597 log("Decoded PTCCH/D message: ", ptcch_msg);
598
599 /* Make sure the message is encoded correctly
600 * TODO: do we expect all TA values to be equal '1111111'B? */
601 if (not match(ptcch_msg, tr_PTCCHDownlinkMsg)) {
602 setverdict(fail, "Malformed PTCCH/D message");
603 mtc.stop;
604 }
605}
606
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700607/* Test of correct Timing Advance during an active Uplink TBF.
608 *
609 * Unlike the circuit-switched domain, Uplink transmissions on PDCH time-slots
610 * are not continuous and there can be long time gaps between them. This happens
611 * due to a bursty nature of packet data. The actual Timing Advance of a MS may
612 * significantly change between such rare Uplink transmissions, so GPRS introduces
613 * additional mechanisms to control Timing Advance, and thus reduce interference
614 * between neighboring TDMA time-slots.
615 *
616 * At the moment of Uplink TBF establishment, initial Timing Advance is measured
617 * from ToA (Timing of Arrival) of an Access Burst. This is covered by another
618 * test case - TC_ta_rach_imm_ass. In response to that Access Burst the network
619 * sends Immediate Assignment on AGCH, which _may_ contain Timing Advance Index
620 * among with the initial Timing Advance value. And here PTCCH comes to play.
621 *
622 * PTCCH is a unidirectional channel on which the network can instruct a sub-set
623 * of 16 MS (whether TBFs are active or not) to adjust their Timing Advance
624 * continuously. To ensure continuous measurements of the signal propagation
625 * delay, the MSs shall transmit Access Bursts on Uplink (PTCCH/U) on sub-slots
626 * defined by an assigned Timing Advance Index (see 3GPP TS 45.002).
627 *
628 * The purpose of this test case is to verify the assignment of Timing Advance
629 * Index, and the process of Timing Advance notification on PTCCH/D. The MTC
630 * first establishes several Uplink TBFs, but does not transmit any Uplink
631 * blocks on them. During 4 TDMA multi-frame periods the MTC is sending RACH
632 * indications to the PCU, checking the correctness of two received PTCCH/D
633 * messages (period of PTCCH/D is two multi-frames).
634 */
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700635
636/* List of ToA values for Access Bursts to be sent on PTCCH/U,
637 * each ToA (Timing of Arrival) value is in units of 1/4 of
638 * a symbol (i.e. 1 symbol is 4 QTA units). */
639type record length(16) of int16_t PTCCH_TAI_ToA_MAP;
640const PTCCH_TAI_ToA_MAP ptcch_toa_map_def := {
641 0, 0, 0, 0,
642 0, 0, 0, 0,
643 0, 0, 0, 0,
644 0, 0, 0, 0
645};
646
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700647private 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 +0700648 in PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def)
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700649runs on RAW_PCU_Test_CT {
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700650 var RAW_PCU_Event event;
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700651 var integer ss;
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700652
653 /* Send Access Bursts on PTCCH/U for every TA Index */
654 [] BTS.receive(tr_RAW_PCU_EV(TDMA_EV_PTCCH_UL_BURST)) -> value event {
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700655 ss := f_tdma_ptcch_fn2ss(event.data.tdma_fn);
656 if (ss < 0) { mtc.stop; } /* Shall not happen */
657
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700658 log("Sending an Access Burst on PTCCH/U",
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700659 ", sub-slot=", ss, " (TAI)",
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700660 ", fn=", event.data.tdma_fn,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700661 ", ToA=", toa_map[ss], " (QTA)");
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700662 /* TODO: do we care about RA and burst format? */
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700663 BTS.send(ts_PCUIF_RACH_IND(bts_nr, trx_nr, ts_nr,
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700664 ra := oct2int('3A'O),
665 is_11bit := 0,
666 burst_type := BURST_TYPE_0,
667 fn := event.data.tdma_fn,
668 arfcn := 871,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700669 qta := toa_map[ss],
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700670 sapi := PCU_IF_SAPI_PTCCH));
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700671 repeat;
672 }
673}
674
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700675private function f_TC_ta_ptcch_ul_multi_tbf(in PTCCH_TAI_ToA_MAP ptcch_toa_map,
676 template PTCCHDownlinkMsg t_ta_msg)
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700677runs on RAW_PCU_Test_CT {
678 var PTCCHDownlinkMsg ta_msg;
679 var PCUIF_Message pcu_msg;
680 timer T;
681
682 /* First, send an RTS.req for the upcoming PTCCH/D block */
683 BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
684 sapi := PCU_IF_SAPI_PTCCH, fn := 0,
685 arfcn := 871, block_nr := 0));
686 T.start(2.0);
687 alt {
688 /* Keep sending of Access Bursts during two multi-frames (period of PTCCH/D)
689 * with increasing ToA (Timing of Arrival) values: 0, 7, 14, 28, 35... */
Vadim Yanitskiy36558d92019-11-17 02:23:51 +0700690 [] as_ta_ptcch(bts_nr := 0, trx_nr := 0, ts_nr := 7, toa_map := ptcch_toa_map);
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700691 /* In the end of 2nd multi-frame we should receive a PTCCH/D block */
692 [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
693 sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
694 ta_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
695 log("Rx PTCCH/D message: ", ta_msg);
696
697 /* Make sure Timing Advance values match our expectations */
698 if (match(ta_msg, t_ta_msg)) {
699 setverdict(pass);
700 } else {
701 setverdict(fail, "PTCCH/D message does not match: ", t_ta_msg);
702 }
703 }
704 [] BTS.receive { repeat; }
705 [] T.timeout {
706 setverdict(fail, "Timeout waiting for a PTCCH/D block");
707 mtc.stop;
708 }
709 }
710}
711
712testcase TC_ta_ptcch_ul_multi_tbf() runs on RAW_PCU_Test_CT {
713 var template PacketUlAssign t_ul_tbf_ass;
714 var PacketUlAssign ul_tbf_ass[7];
715 var GsmRrMessage rr_msg[7];
716 var boolean ok;
717
718 /* Initialize the PCU interface abstraction */
719 f_init_raw(testcasename());
720
721 /* Enable forwarding of PTCCH/U TDMA events to us */
722 BTS.send(ts_RAW_PCU_CMD(TDMA_CMD_ENABLE_PTCCH_UL_FWD));
723
724 /* Establish 7 Uplink TBFs (USF flag is 3 bits long, '111'B is reserved) */
725 for (var integer i := 0; i < 7; i := i + 1) {
726 ok := f_establish_tbf(rr_msg[i], ta := 0);
727 if (not ok) {
728 setverdict(fail, "Failed to establish an Uplink TBF #", i);
729 mtc.stop;
730 }
731
732 /* Make sure we received an UL TBF Assignment */
733 if (match(rr_msg[i], tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
734 ul_tbf_ass[i] := rr_msg[i].payload.imm_ass.rest_octets.hh.pa.uldl.ass.ul;
735 log("Rx Uplink TBF assignment for #", i, ": ", ul_tbf_ass[i]);
736 } else {
737 setverdict(fail, "Failed to match UL TBF Assignment for #", i);
738 mtc.stop;
739 }
740
741 /* We expect incremental TFI/USF assignment (dynamic allocation) */
742 t_ul_tbf_ass := tr_PacketUlDynAssign(tfi := i, usf := i);
743 if (not match(ul_tbf_ass[i], t_ul_tbf_ass)) {
744 setverdict(fail, "Failed to match Packet Uplink Assignment for #", i);
745 mtc.stop;
746 }
747
748 /* We also expect Timing Advance Index to be a part of the assignment */
749 if (ul_tbf_ass[i].dynamic.ta_index != i) {
750 setverdict(fail, "Failed to match Timing Advance Index for #", i);
751 /* Keep going, the current OsmoPCU does not assign TA Index */
752 }
753 }
754
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700755 /* Prepare a list of ToA values for Access Bursts to be sent on PTCCH/U */
756 var PTCCH_TAI_ToA_MAP toa_map := ptcch_toa_map_def;
757 for (var integer i := 0; i < 7; i := i + 1) {
758 /* ToA in units of 1/4 of a symbol */
759 toa_map[i] := (i + 1) * 7 * 4;
760 }
761
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700762 /* Now we have all 7 TBFs established in one-phase access mode,
763 * however we will not be sending any data on them. Instead, we
764 * will be sending RACH.ind on PTCCH/U during 4 multi-frame
765 * periods (TAI 0..8), and then will check two PTCCH/D blocks.
766 *
767 * Why not 4 TBFs at once? Because Uplink is delayed by 3 TDMA
768 * time-slots, so at the moment of scheduling a PTCCH/D block
769 * the PCU has odd number of PTCCH/U Access Bursts received. */
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700770 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700771 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
772 /* Other values are not known (yet) */
773 tai3_ta := ?));
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700774 f_TC_ta_ptcch_ul_multi_tbf(toa_map, tr_PTCCHDownlinkMsg(
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700775 tai0_ta := 7, tai1_ta := 14, tai2_ta := 21,
776 tai3_ta := 28, tai4_ta := 35, tai5_ta := 42,
Vadim Yanitskiy20f87002019-10-06 00:51:50 +0700777 /* Other values are out of our interest */
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +0700778 tai6_ta := ?));
779}
780
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700781/* Default link quality adaptation (Coding Scheme) ranges (inclusive).
782 * OsmoPCU (VTY): cs link-quality-ranges cs1 6 cs2 5 8 cs3 7 13 cs4 12
783 *
784 * NOTE: the ranges are intentionally overlapping because OsmoPCU
785 * does not change CS/MCS on the range borders (5-6, 7-8, 12-13). */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200786private template integer CS1_lqual_dB_range := (-infinity .. 6);
787private template integer CS2_lqual_dB_range := (5 .. 8);
788private template integer CS3_lqual_dB_range := (7 .. 13);
789private template integer CS4_lqual_dB_range := (12 .. infinity);
790
791testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200792 var GsmRrMessage rr_imm_ass;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200793 var PacketUlAssign ul_tbf_ass;
794 var RlcmacDlBlock dl_block;
795 var PCUIF_Message pcu_msg;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200796 var octetstring data;
797 var boolean ok;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100798 var uint32_t unused_fn;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200799
800 /* Initialize the PCU interface abstraction */
801 f_init_raw(testcasename());
802
Pau Espin Pedrol2a45a502019-11-29 12:48:16 +0100803 f_pcuvty_set_allowed_cs_mcs();
804 f_pcuvty_set_link_quality_ranges();
805
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200806 /* Establish an Uplink TBF */
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200807 ok := f_establish_tbf(rr_imm_ass);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200808 if (not ok) {
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200809 setverdict(fail, "Failed to establish TBF");
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200810 mtc.stop;
811 }
812
Pau Espin Pedrol6c1b4be2019-10-04 19:31:02 +0200813 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
814 if (not ok) {
815 setverdict(fail, "Immediate Assignment not an Uplink TBF");
Vadim Yanitskiy6276b6c2019-09-29 19:48:26 +0700816 mtc.stop;
817 }
818
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200819 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
820 tfi := ul_tbf_ass.dynamic.tfi_assignment,
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100821 cv := 15, /* 16 UL blocks to be sent (to be overridden in loop) */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200822 bsn := 0, /* TODO: what should be here? */
823 blocks := { /* To be generated in loop */ });
824
825 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
826 ul_data.data.tlli := '00000001'O;
827
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700828 /* The actual / old link quality values. We need to keep track of the old
829 * (basically previous) link quality value, because OsmoPCU actually
830 * changes the coding scheme if not only the actual, but also the old
831 * value leaves the current link quality range (window). */
832 var integer lqual := 0;
833 var integer lqual_old;
834
835 /* 16 UL blocks (0 .. 15 dB, step = 1 dB) */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200836 for (var integer i := 0; i < 16; i := i + 1) {
837 /* Prepare a new UL block (CV, random payload) */
838 ul_data.data.mac_hdr.countdown := (15 - i);
839 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
840
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700841 /* Update the old / actual link quality */
842 lqual_old := lqual;
843 lqual := i;
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200844
845 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
846 log("Sending DATA.ind with link quality (dB): ", lqual);
Pau Espin Pedrolc3a77322019-10-03 19:40:08 +0200847 f_tx_rlcmac_ul_block(ul_data, lqual * 10);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200848
849 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100850 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200851
852 log("Rx Packet Uplink ACK / NACK with Channel Coding Command: ",
853 dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd);
854
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700855 /* Match the received Channel Coding Command. Since we are increasing
856 * the link quality value on each iteration and not decreasing, there
857 * is no need to check the both old and current link quality values. */
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200858 var template ChCodingCommand ch_coding;
Vadim Yanitskiy26cd2442019-11-08 05:39:06 +0700859 select (lqual_old) {
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +0200860 case (CS1_lqual_dB_range) { ch_coding := CH_CODING_CS1; }
861 case (CS2_lqual_dB_range) { ch_coding := CH_CODING_CS2; }
862 case (CS3_lqual_dB_range) { ch_coding := CH_CODING_CS3; }
863 case (CS4_lqual_dB_range) { ch_coding := CH_CODING_CS4; }
864 }
865
866 if (not match(dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd, ch_coding)) {
867 setverdict(fail, "Channel Coding does not match our expectations: ", ch_coding);
868 } else {
869 setverdict(pass);
870 }
871 }
872}
873
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100874/* Test the max UL CS set by VTY works fine */
875testcase TC_cs_initial_ul() runs on RAW_PCU_Test_CT {
876 var GsmRrMessage rr_imm_ass;
877 var PacketUlAssign ul_tbf_ass;
878 var RlcmacDlBlock dl_block;
879 var boolean ok;
880 var integer lqual_cb;
881 var ChCodingCommand last_ch_coding;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100882 var uint32_t unused_fn;
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100883
884 /* Initialize the PCU interface abstraction */
885 f_init_raw(testcasename());
886
887 /* Set initial UL CS to 3 */
888 g_cs_initial_ul := 3;
889 f_pcuvty_set_allowed_cs_mcs();
890 f_pcuvty_set_link_quality_ranges();
891
892 /* Take lqual (dB->cB) so that we stay in that CS */
893 lqual_cb := g_cs_lqual_ranges[2].low * 10;
894
895 /* Establish an Uplink TBF */
896 ok := f_establish_tbf(rr_imm_ass);
897 if (not ok) {
898 setverdict(fail, "Failed to establish TBF");
899 mtc.stop;
900 }
901
902 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
903 if (not ok) {
904 setverdict(fail, "Immediate Assignment not an Uplink TBF");
905 mtc.stop;
906 }
907
908 var template (value) RlcmacUlBlock ul_data := t_RLCMAC_UL_DATA(
909 tfi := ul_tbf_ass.dynamic.tfi_assignment,
910 cv := 3, /* 8 UL blocks to be sent (to be overridden in loop) */
911 bsn := 0, /* TODO: what should be here? */
912 blocks := { /* To be generated in loop */ });
913
914 /* HACK: patch missing TLLI; otherwise OsmoPCU rejects DATA.req */
915 ul_data.data.tlli := '00000001'O;
916
917 /* 3 UL blocks, check we are in same initial CS: */
918 for (var integer i := 0; i < 3; i := i + 1) {
919 /* Prepare a new UL block (CV, random payload) */
920 ul_data.data.mac_hdr.countdown := (7 - i);
921 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
922
923 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
924 f_tx_rlcmac_ul_block(ul_data, lqual_cb);
925
926 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100927 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100928 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
929 }
930
931 if (last_ch_coding != CH_CODING_CS3) {
932 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
933 mtc.stop;
934 }
935
936 setverdict(pass);
937
938 /* Remaining UL blocks are used to make sure regardless of initial
939 /* lqual, we can go lower at any time */
940
941 /* 5 UL blocks, check we are in same initial CS: */
942 for (var integer i := 3; i < 8; i := i + 1) {
943 /* Prepare a new UL block (CV, random payload) */
944 ul_data.data.mac_hdr.countdown := (7 - i);
945 ul_data.data.blocks := { valueof(t_RLCMAC_LLCBLOCK(f_rnd_octstring(10))) };
946
947 /* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
948 f_tx_rlcmac_ul_block(ul_data, 0); /* 0 dB, make sure we downgrade CS */
949
950 /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100951 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100952
953 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
954 }
955
956 if (last_ch_coding != CH_CODING_CS1) {
957 setverdict(fail, "Channel Coding does not match our expectations (CS-1): ", last_ch_coding);
958 } else {
959 setverdict(pass);
960 }
961}
962
963/* Test the max UL CS set by VTY works fine */
964testcase TC_cs_max_ul() runs on RAW_PCU_Test_CT {
965 var GsmRrMessage rr_imm_ass;
966 var PacketUlAssign ul_tbf_ass;
967 var RlcmacDlBlock dl_block;
968 var boolean ok;
969 var ChCodingCommand last_ch_coding;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +0100970 var uint32_t unused_fn;
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +0100971
972 /* Initialize the PCU interface abstraction */
973 f_init_raw(testcasename());
974
975 /* Set maximum allowed UL CS to 3 */
976 g_cs_max_ul := 3;
977 f_pcuvty_set_allowed_cs_mcs();
978 f_pcuvty_set_link_quality_ranges();
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 := 15, /* 16 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 /* 16 UL blocks */
1003 for (var integer i := 0; i < 16; i := i + 1) {
1004 /* Prepare a new UL block (CV, random payload) */
1005 ul_data.data.mac_hdr.countdown := (15 - 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, 40*10); /* 40 dB */
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
1014 last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.gprs.ch_coding_cmd;
1015 }
1016
1017 if (last_ch_coding != CH_CODING_CS3) {
1018 setverdict(fail, "Channel Coding does not match our expectations (CS-3): ", last_ch_coding);
1019 } else {
1020 setverdict(pass);
1021 }
1022}
1023
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001024/* Verify PCU drops TBF after some time of inactivity. */
1025testcase TC_t3169() runs on RAW_PCU_Test_CT {
1026 var PCUIF_info_ind info_ind;
1027 var GsmRrMessage rr_imm_ass;
1028 var PacketUlAssign ul_tbf_ass;
1029 var RlcmacDlBlock dl_block;
1030 var PCUIF_Message pcu_msg;
1031 var octetstring data;
1032 var boolean ok;
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001033 var uint32_t unused_fn;
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001034 var OCT4 tlli := '00000001'O;
1035
1036 /* Initialize NS/BSSGP side */
1037 f_init_bssgp();
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001038
1039 info_ind := valueof(ts_PCUIF_INFO_default);
1040 /* Set timer to 1 sec (default 5) to speedup test: */
1041 info_ind.t3169 := 1;
1042
1043 /* Initialize the PCU interface abstraction */
1044 f_init_raw(testcasename(), info_ind);
1045
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001046 /* Establish BSSGP connection to the PCU */
1047 f_bssgp_establish();
1048 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1049
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001050 /* Establish an Uplink TBF */
1051 ok := f_establish_tbf(rr_imm_ass);
1052 if (not ok) {
1053 setverdict(fail, "Failed to establish TBF");
1054 mtc.stop;
1055 }
1056
1057 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1058 if (not ok) {
1059 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1060 mtc.stop;
1061 }
1062
1063 /* Send one UL block and make sure it is ACKED fine */
1064 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001065 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
Pau Espin Pedrolcf47a922019-10-07 15:26:52 +02001066 /* UL block should be received in SGSN */
1067 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001068
1069 /* Wait until T3169 fires (plus 1 extra sec to make sure) */
1070 f_sleep(int2float(info_ind.t3169) + 1.0);
1071
1072 /* Send an UL block once again, the TBF should be gone by now so no ACK */
1073 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
1074 f_rx_rlcmac_dl_block_exp_dummy(dl_block);
1075}
1076
Pau Espin Pedrolff8da192019-12-05 17:23:58 +01001077/* Verify that a Downlink TBF can be assigned using PACCH shortly after the
1078 * release of prev DL TBF due to MS staying in PDCH for a while (T3192, in PCU
1079 * T3193) after DL TBF release */
1080testcase TC_t3193() runs on RAW_PCU_Test_CT {
1081 var GsmRrMessage rr_imm_ass;
1082 var PacketDlAssign dl_tbf_ass;
1083 var RlcmacDlBlock dl_block;
1084 var octetstring data := f_rnd_octstring(10);
1085 var boolean ok;
1086 var uint32_t sched_fn;
1087 var OCT4 tlli := '00000001'O;
1088 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1089
1090 /* Initialize NS/BSSGP side */
1091 f_init_bssgp();
1092
1093 /* Initialize the PCU interface abstraction */
1094 f_init_raw(testcasename());
1095
1096 /* Establish BSSGP connection to the PCU */
1097 f_bssgp_establish();
1098 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1099
1100 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1101 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1102 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1103 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1104 if (not ok) {
1105 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1106 mtc.stop;
1107 }
1108 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1109 f_sleep(X2002);
1110 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1111
1112 /* ACK the DL block */
1113 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1114 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1115 /* we are done with the DL-TBF here so far, let's clean up our local state: */
1116 ack_nack_desc := valueof(t_AckNackDescription_init)
1117
1118 /* Now that final DL block is ACKED and TBF is released, T3193 in PCU
1119 (T3192 in MS) was started and until it fires the MS will be abailable
1120 on PDCH in case new data arrives from SGSN. Let's verify it: */
1121 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1122 f_rx_rlcmac_dl_block_exp_pkt_ass(dl_block, sched_fn);
1123 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
1124
1125 /* Now that we confirmed the new assignment in the dl-tbf, lets receive the data and ack it */
1126 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1127 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1128 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1129}
1130
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001131/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
1132 * answered, so TBFs for uplink and later for downlink are created.
1133 */
1134testcase TC_mo_ping_pong() runs on RAW_PCU_Test_CT {
1135 var GsmRrMessage rr_imm_ass;
1136 var PacketUlAssign ul_tbf_ass;
1137 var PacketDlAssign dl_tbf_ass;
1138 var RlcmacDlBlock dl_block;
1139 var PCUIF_Message pcu_msg;
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001140 var octetstring data := f_rnd_octstring(10);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001141 var boolean ok;
Pau Espin Pedrol65bab9e2019-12-04 21:05:10 +01001142 var uint32_t sched_fn;
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001143 var OCT4 tlli := '00000001'O;
Pau Espin Pedrol89486332019-12-05 14:05:46 +01001144 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001145
1146 /* Initialize NS/BSSGP side */
1147 f_init_bssgp();
1148
1149 /* Initialize the PCU interface abstraction */
1150 f_init_raw(testcasename());
1151
1152 /* Establish BSSGP connection to the PCU */
1153 f_bssgp_establish();
1154 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1155
1156 /* Establish an Uplink TBF */
1157 ok := f_establish_tbf(rr_imm_ass);
1158 if (not ok) {
1159 setverdict(fail, "Failed to establish TBF");
1160 mtc.stop;
1161 }
1162 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1163 if (not ok) {
1164 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1165 mtc.stop;
1166 }
1167
1168 /* Send one UL block and make sure it is ACKED fine */
1169 f_tx_rlcmac_ul_n_blocks(ul_tbf_ass, 1);
Pau Espin Pedrol7503c872019-12-05 12:55:08 +01001170 f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
1171 /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
1172 f_tx_rlcmac_ul_block(ts_RLCMAC_CTRL_ACK(tlli), 0, sched_fn);
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001173
1174 /* UL block should be received in SGSN */
1175 BSSGP[0].receive(tr_BSSGP_UL_UD(tlli, mp_gb_cfg.cell_id));
1176
1177 /* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001178 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001179 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1180
1181 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1182 if (not ok) {
1183 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1184 mtc.stop;
1185 }
1186
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001187 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1188 f_sleep(X2002);
Pau Espin Pedrol89486332019-12-05 14:05:46 +01001189 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
Pau Espin Pedrola3f0a852019-12-02 19:16:26 +01001190
1191 /* ACK the DL block */
Pau Espin Pedrol89486332019-12-05 14:05:46 +01001192 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 +01001193 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 +02001194}
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001195
Pau Espin Pedrola7b75662019-12-05 16:39:55 +01001196/* Verify that if PCU doesn't get an ACK for first DL block after IMM ASS, it
1197 * will retry by retransmitting both the IMM ASS + DL block after poll (ack)
1198 * timeout occurs (specified by sent RRBP on DL block). */
1199testcase TC_imm_ass_dl_block_retrans() runs on RAW_PCU_Test_CT {
1200 var GsmRrMessage rr_imm_ass;
1201 var PacketDlAssign dl_tbf_ass;
1202 var RlcmacDlBlock dl_block;
1203 var octetstring data := f_rnd_octstring(10);
1204 var boolean ok;
1205 var uint32_t sched_fn;
1206 var OCT4 tlli := '00000001'O;
1207 var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
1208
1209 /* Initialize NS/BSSGP side */
1210 f_init_bssgp();
1211
1212 /* Initialize the PCU interface abstraction */
1213 f_init_raw(testcasename());
1214
1215 /* Establish BSSGP connection to the PCU */
1216 f_bssgp_establish();
1217 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1218
1219 /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
1220 BSSGP[0].send(ts_BSSGP_DL_UD(tlli, data));
1221 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1222 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1223 if (not ok) {
1224 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1225 mtc.stop;
1226 }
1227
1228 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1229 f_sleep(X2002);
1230 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1231
1232 /* Now we don't ack the dl block (emulate MS failed receiveing IMM ASS
1233 * or GPRS DL, or DL ACK was lost for some reason). As a result, PCU
1234 * should retrigger IMM ASS + GPRS DL procedure after poll timeout. */
1235 f_pcuif_rx_pch_imm_tbf_ass(rr_imm_ass);
1236 ok := f_imm_ass_verify_dl_tbf_ass(rr_imm_ass, dl_tbf_ass);
1237 if (not ok) {
1238 setverdict(fail, "Immediate Assignment not a Downlink TBF");
1239 mtc.stop;
1240 }
1241 /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
1242 f_sleep(X2002);
1243 f_rx_rlcmac_dl_block_exp_data(dl_block, sched_fn, data, 0);
1244
1245 /* ACK the DL block */
1246 f_acknackdesc_ack_block(ack_nack_desc, dl_block.data.mac_hdr.hdr_ext.bsn, '1'B);
1247 f_tx_rlcmac_ul_block(ts_RLCMAC_DL_ACK_NACK(dl_block.data.mac_hdr.hdr_ext.tfi, ack_nack_desc), 0, sched_fn);
1248}
1249
Vadim Yanitskiy322c7932020-01-01 23:03:47 +01001250private function f_pkt_paging_match_imsi(in PacketPagingReq req, hexstring imsi) {
1251 var MobileIdentityLV_Paging mi_lv := req.repeated_pageinfo.cs.mobile_identity;
1252 var MobileIdentityV mi := dec_MobileIdentityV(mi_lv.mobile_id);
1253
1254 if (mi_lv.len != 8) { /* 8 octets: type of ID (3 bits) + even/odd flag (1 bit) + 15 BCD-encoded digits (60 bits) */
1255 setverdict(fail, "Mobile Identity length mismatch: ",
1256 "expected: 8, got: ", mi_lv.len);
1257 mtc.stop;
1258 }
1259
1260 /* Make sure MI contains IMSI before referencing it */
1261 if (mi.typeOfIdentity != '001'B) {
1262 setverdict(fail, "Mobile Identity must be of type IMSI ('001'B), ",
1263 "got: ", mi.typeOfIdentity);
1264 mtc.stop;
1265 } else if (mi.oddEvenInd_identity.imsi.digits != imsi) {
1266 setverdict(fail, "Mobile Identity contains unexpected IMSI, ",
1267 "expected: ", imsi, " got: ", mi.oddEvenInd_identity.imsi.digits);
1268 mtc.stop;
1269 }
1270}
1271
Oliver Smith8f9daab2019-10-09 09:27:19 +02001272/* Test CS paging over the BTS<->PCU socket.
1273 * 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.
1274 * Paging should be send on the PACCH.
1275 *
1276 * 1. Send a Paging Request over PCU socket.
1277 * 2. Send a Ready-To-Send message over PCU socket
1278 * 3. Expect a Paging Frame
1279 */
1280testcase TC_paging_cs_from_bts() runs on RAW_PCU_Test_CT {
1281 var GsmRrMessage rr_imm_ass;
1282 var PacketUlAssign ul_tbf_ass;
1283 var RlcmacDlBlock dl_block;
1284 var boolean ok;
1285 var OCT4 tlli := '00000001'O;
1286 var MobileL3_CommonIE_Types.MobileIdentityLV mi;
1287 var octetstring mi_enc_lv;
Oliver Smith8f9daab2019-10-09 09:27:19 +02001288 var hexstring imsi := f_gen_imsi(42);
1289
1290 /* Initialize NS/BSSGP side */
1291 f_init_bssgp();
1292
1293 /* Initialize the PCU interface abstraction */
1294 f_init_raw(testcasename());
1295
1296 /* Establish BSSGP connection to the PCU */
1297 f_bssgp_establish();
1298 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1299
1300 /* Establish an Uplink TBF */
1301 ok := f_establish_tbf(rr_imm_ass);
1302 if (not ok) {
1303 setverdict(fail, "Failed to establish TBF");
1304 mtc.stop;
1305 }
1306
1307 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1308 if (not ok) {
1309 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1310 mtc.stop;
1311 }
1312
1313
1314 /* build mobile Identity */
1315 mi := valueof(ts_MI_IMSI_LV(imsi));
1316 mi_enc_lv := enc_MobileIdentityLV(mi);
1317 /* Send paging request */
1318 BTS.send(ts_PCUIF_PAG_REQ(bts_nr := 0, id_lv := mi_enc_lv, chan_needed := 0,
1319 sapi :=PCU_IF_SAPI_PDTCH));
1320
1321 /* Receive it on BTS side towards MS */
1322 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
Vadim Yanitskiy5e518732020-01-01 21:27:18 +01001323
Vadim Yanitskiy322c7932020-01-01 23:03:47 +01001324 /* Make sure that Packet Paging Request contains the same IMSI */
1325 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1326
Oliver Smith8f9daab2019-10-09 09:27:19 +02001327 setverdict(pass);
1328}
1329
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001330/* Test CS paging over Gb (SGSN->PCU->BTS[PDCH]).
1331 */
1332private function f_tc_paging_cs_from_sgsn(Nsvci bvci) runs on RAW_PCU_Test_CT {
1333 var GsmRrMessage rr_imm_ass;
1334 var PacketUlAssign ul_tbf_ass;
1335 var RlcmacDlBlock dl_block;
1336 var boolean ok;
1337 var OCT4 tlli := '00000001'O;
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001338 var hexstring imsi := f_gen_imsi(42);
1339
1340 /* Initialize NS/BSSGP side */
1341 f_init_bssgp();
1342
1343 /* Initialize the PCU interface abstraction */
1344 f_init_raw(testcasename());
1345
1346 /* Establish BSSGP connection to the PCU */
1347 f_bssgp_establish();
1348 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1349
1350 /* Establish an Uplink TBF */
1351 ok := f_establish_tbf(rr_imm_ass);
1352 if (not ok) {
1353 setverdict(fail, "Failed to establish TBF");
1354 mtc.stop;
1355 }
1356
1357 ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass);
1358 if (not ok) {
1359 setverdict(fail, "Immediate Assignment not an Uplink TBF");
1360 mtc.stop;
1361 }
1362
1363 /* Send paging request */
1364 BSSGP[0].send(ts_BSSGP_CS_PAGING_IMSI(bvci, imsi));
1365
1366 /* Receive it on BTS side towards MS */
1367 f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
1368
Vadim Yanitskiy322c7932020-01-01 23:03:47 +01001369 /* Make sure that Packet Paging Request contains the same IMSI */
1370 f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
1371
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001372 setverdict(pass);
1373}
1374
1375testcase TC_paging_cs_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1376 f_tc_paging_cs_from_sgsn(0);
1377}
1378
1379testcase TC_paging_cs_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1380 f_tc_paging_cs_from_sgsn(mp_gb_cfg.bvci);
1381}
1382
1383/* Test PS paging over Gb (SGSN->PCU->BTS[CCCH]).
1384 */
1385private function f_tc_paging_ps_from_sgsn(Nsvci bvci) runs on RAW_PCU_Test_CT {
1386 var GsmRrMessage rr_pag_req1;
1387 var OCT4 tlli := '00000001'O;
1388 var hexstring imsi := f_gen_imsi(42);
1389
1390 /* Initialize NS/BSSGP side */
1391 f_init_bssgp();
1392
1393 /* Initialize the PCU interface abstraction */
1394 f_init_raw(testcasename());
1395
1396 /* Establish BSSGP connection to the PCU */
1397 f_bssgp_establish();
1398 f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
1399
1400 /* Send paging request */
1401 BSSGP[0].send(ts_BSSGP_PS_PAGING_IMSI(bvci, imsi));
1402
1403 /* Receive it on BTS side towards MS */
1404 f_pcuif_rx_pch_pag_req1(rr_pag_req1);
1405
1406 setverdict(pass);
1407}
1408
1409testcase TC_paging_ps_from_sgsn_sign() runs on RAW_PCU_Test_CT {
1410 f_tc_paging_ps_from_sgsn(0);
1411}
1412
1413testcase TC_paging_ps_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
1414 f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvci);
1415}
1416
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001417control {
Harald Welte7fd25cf2019-03-21 22:14:02 +01001418 execute( TC_pcuif_suspend() );
Vadim Yanitskiy1f72b0a2019-10-01 05:58:45 +07001419 execute( TC_ta_ptcch_idle() );
Vadim Yanitskiy3e1d3182019-09-11 16:53:45 +02001420 execute( TC_ta_rach_imm_ass() );
Vadim Yanitskiy02f77d82019-10-04 17:12:35 +07001421 execute( TC_ta_ptcch_ul_multi_tbf() );
Vadim Yanitskiy0eb26622019-09-14 20:35:28 +02001422 execute( TC_cs_lqual_ul_tbf() );
Pau Espin Pedrol3eef95c2019-11-29 14:07:24 +01001423 execute( TC_cs_initial_ul() );
1424 execute( TC_cs_max_ul() );
Pau Espin Pedrol596faa42019-10-04 19:31:29 +02001425 execute( TC_t3169() );
Pau Espin Pedrolff8da192019-12-05 17:23:58 +01001426 execute( TC_t3193() );
Pau Espin Pedrol1755fab2019-10-08 11:18:54 +02001427 execute( TC_mo_ping_pong() );
Pau Espin Pedrola7b75662019-12-05 16:39:55 +01001428 execute( TC_imm_ass_dl_block_retrans() );
Oliver Smith8f9daab2019-10-09 09:27:19 +02001429 execute( TC_paging_cs_from_bts() );
Pau Espin Pedrol88bf5372019-12-09 21:12:28 +01001430 execute (TC_paging_cs_from_sgsn_sign() );
1431 execute (TC_paging_cs_from_sgsn_ptp() );
1432 execute (TC_paging_ps_from_sgsn_sign() );
1433 execute (TC_paging_ps_from_sgsn_ptp() );
Harald Welte9fbcf4b2018-12-07 07:56:52 +01001434}
1435
1436
1437
1438
1439
1440
1441}