blob: 4242502a61caadc992335323505b4529fd3672ed [file] [log] [blame]
Harald Welte97cca2f2019-05-30 16:33:38 +02001module BTS_Tests_LAPDm {
Harald Weltef6543322017-07-16 07:35:10 +02002
Harald Welte72c81e72019-05-30 16:36:11 +02003import from GSM_Types all;
4import from Osmocom_Types all;
5import from LAPDm_RAW_PT all;
6import from LAPDm_Types all;
Harald Welte2f2b2b72019-05-31 22:24:57 +02007import from RSL_Types all;
Harald Welte72c81e72019-05-30 16:36:11 +02008import from BTS_Tests all;
Harald Welte2f2b2b72019-05-31 22:24:57 +02009import from Misc_Helpers all;
Harald Welte66110f02017-07-16 21:05:18 +020010
Harald Welte72c81e72019-05-30 16:36:11 +020011/* test that use exclusively only LAPDm over L1CTL */
12type component lapdm_test_CT {
13 port LAPDm_PT LAPDM;
14 var lapdm_CT lapdm_component;
15};
16
17/* contrary to BTS_Tests.ttcn, we use LAPDm_PT here, a convenience wrapper
18 * around L1CTL to perform encode/decode of abstract LAPDm frames */
Harald Welte72c81e72019-05-30 16:36:11 +020019
Harald Welte61332c02019-05-30 16:45:15 +020020/*********************************************************************************
21 * Test using only L1CTL/LAPDm
22 *********************************************************************************/
23
24function f_lapdm_init() runs on lapdm_test_CT {
Harald Welte72c81e72019-05-30 16:36:11 +020025 /* create the LAPDm component */
26 lapdm_component := lapdm_CT.create;
27 /* connect our own LAPDM port to the LAPDM Service Provider of the LAPDm component */
28 connect(self:LAPDM, lapdm_component:LAPDM_SP);
29 /* connect the LAPDm compoent's lower-side port to the system L1CTL port (which is internally
30 * connected to the Unix Domain Socket test port */
31 map(lapdm_component:L1CTL, system:L1CTL);
32
33 /* start the LAPDm parallel component calling it's local function LAPDmStart */
34 lapdm_component.start(LAPDmStart());
35}
36
Harald Welte2f2b2b72019-05-31 22:24:57 +020037function f_lapdm_exit() runs on lapdm_test_CT {
38 lapdm_component.stop;
39 lapdm_component.done;
40 unmap(lapdm_component:L1CTL, system:L1CTL);
41}
42
Harald Welte72c81e72019-05-30 16:36:11 +020043/* master function establishing a dedicated radio channel (takes care of RACH/IMM.ASS handling) */
44function f_establish_dcch() runs on lapdm_test_CT {
Harald Welte2f2b2b72019-05-31 22:24:57 +020045 var BCCH_tune_req tune_req := { arfcn := { false, mp_trx0_arfcn }, combined_ccch := true };
Harald Welte72c81e72019-05-30 16:36:11 +020046 var DCCH_establish_req est_req := { ra := 23 };
47
48 LAPDM.send(tune_req);
49 LAPDM.send(est_req);
50 LAPDM.receive(DCCH_establish_res:?);
51}
52
Harald Welte2f2b2b72019-05-31 22:24:57 +020053/* master function switching to a dedicated radio channel */
54function f_switch_dcch(Arfcn arfcn, RslChannelNr chan_nr, GsmTsc tsc) runs on lapdm_test_CT {
55 var BCCH_tune_req tune_req := { arfcn := arfcn, combined_ccch := true };
56 var DCCH_switch_req sw_req := { arfcn, chan_nr, tsc };
57
58 LAPDM.send(tune_req);
59 LAPDM.send(sw_req);
60 LAPDM.receive(DCCH_switch_res:?);
61}
62
Harald Welte72c81e72019-05-30 16:36:11 +020063/* helper function releasing dedicated radio channel physically (no Um signaling!) */
64function f_release_dcch() runs on lapdm_test_CT {
65 var DCCH_release_req rel_req := {};
66 LAPDM.send(rel_req);
67}
68
69template LAPDm_ph_data t_PH_DATA(template GsmSapi sapi, template boolean sacch, template LapdmFrame frame) := {
70 sacch := sacch,
71 sapi := sapi,
72 lapdm := frame
73}
Harald Weltec38611b2019-05-30 16:33:58 +020074
Eric Wild74f25ae2019-06-14 11:44:29 +020075function f_test_sabm_results_in_ua(uint8_t sapi, boolean use_sacch, octetstring payload) runs on ConnHdlr return boolean {
Harald Welte72c81e72019-05-30 16:36:11 +020076 var LAPDm_ph_data phd;
77 var boolean result := false;
78 timer T := 5.0;
79
Eric Wild74f25ae2019-06-14 11:44:29 +020080 LAPDM.send(t_PH_DATA(sapi, use_sacch, ts_LAPDm_SABM(sapi, c_r:=cr_MO_CMD, p:=false, l3:=payload)));
Harald Welte72c81e72019-05-30 16:36:11 +020081 T.start
82 alt {
Eric Wild74f25ae2019-06-14 11:44:29 +020083 [] LAPDM.receive(t_PH_DATA(?, use_sacch, tr_LAPDm_UA(sapi, cr_MT_RSP, f:=false, l3:=payload))) { result := true; }
84 [] RSL.receive {repeat;}
85 [] LAPDM.receive { repeat; }
Harald Welte72c81e72019-05-30 16:36:11 +020086 [] T.timeout { }
87 }
Eric Wild74f25ae2019-06-14 11:44:29 +020088 LAPDM.send(t_PH_DATA(sapi, use_sacch, ts_LAPDm_RR(sapi, c_r:=cr_MT_CMD, p:=false, nr:=0)));
Harald Welte72c81e72019-05-30 16:36:11 +020089 return result;
90}
91
Eric Wild74f25ae2019-06-14 11:44:29 +020092function f_TC_sabm_ua_dcch_sapi0(charstring id) runs on ConnHdlr {
93 fp_common_init();
94 RSL.clear;
95 LAPDM.clear;
96 var default d := activate(as_ignore_background());
Harald Welte72c81e72019-05-30 16:36:11 +020097 if (not f_test_sabm_results_in_ua(0, false, 'FEFE'O)) {
98 setverdict(fail);
99 }
100 setverdict(pass);
Eric Wild74f25ae2019-06-14 11:44:29 +0200101 deactivate(d);
102 fp_common_fini();
Harald Welte72c81e72019-05-30 16:36:11 +0200103}
104
Eric Wild74f25ae2019-06-14 11:44:29 +0200105function f_TC_sabm_ua_dcch_sapi0_nopayload(charstring id) runs on ConnHdlr {
106 fp_common_init();
107 RSL.clear;
108 LAPDM.clear;
109 var default d := activate(as_ignore_background());
Harald Welte72c81e72019-05-30 16:36:11 +0200110 if (f_test_sabm_results_in_ua(0, false, ''O)) {
111 setverdict(fail, "Initial SABM/UA must contain L3 payload but BTS accepts without");
112 }
113 setverdict(pass);
Eric Wild74f25ae2019-06-14 11:44:29 +0200114 deactivate(d);
115 fp_common_fini();
Harald Welte72c81e72019-05-30 16:36:11 +0200116}
117
Eric Wild74f25ae2019-06-14 11:44:29 +0200118function f_TC_sabm_ua_dcch_sapi3(charstring id) runs on ConnHdlr {
119 fp_common_init();
120 RSL.clear;
121 LAPDM.clear;
122 var default d := activate(as_ignore_background());
Harald Welte72c81e72019-05-30 16:36:11 +0200123 if (f_test_sabm_results_in_ua(3, false, 'FEFE'O)) {
124 setverdict(fail, "Initial SABM/UA must be on SAPI0, but BTS accepts SAPI=3");
125 }
126 setverdict(pass);
Eric Wild74f25ae2019-06-14 11:44:29 +0200127 deactivate(d);
128 fp_common_fini();
Harald Welte72c81e72019-05-30 16:36:11 +0200129}
130
Eric Wild74f25ae2019-06-14 11:44:29 +0200131function f_TC_sabm_ua_dcch_sapi4(charstring id) runs on ConnHdlr {
132 fp_common_init();
133 RSL.clear;
134 LAPDM.clear;
135 var default d := activate(as_ignore_background());
Harald Welte72c81e72019-05-30 16:36:11 +0200136 if (f_test_sabm_results_in_ua(4, false, 'FEFE'O)) {
137 setverdict(fail, "Initial SABM/UA must be on SAPI0, but BTS accepts SAPI=4");
138 }
139 setverdict(pass);
Eric Wild74f25ae2019-06-14 11:44:29 +0200140 deactivate(d);
141 fp_common_fini();
Harald Welte72c81e72019-05-30 16:36:11 +0200142}
143
Eric Wild74f25ae2019-06-14 11:44:29 +0200144testcase TC_sabm_ua_dcch_sapi0() runs on test_CT {
145 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
146 f_testmatrix_each_chan(pars, refers(f_TC_sabm_ua_dcch_sapi0));
147}
148
149testcase TC_sabm_ua_dcch_sapi0_nopayload() runs on test_CT {
150 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
151 f_testmatrix_each_chan(pars, refers(f_TC_sabm_ua_dcch_sapi0_nopayload));
152}
153
154testcase TC_sabm_ua_dcch_sapi3() runs on test_CT {
155 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
156 f_testmatrix_each_chan(pars, refers(f_TC_sabm_ua_dcch_sapi3));
157}
158
159testcase TC_sabm_ua_dcch_sapi4() runs on test_CT {
160 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
161 f_testmatrix_each_chan(pars, refers(f_TC_sabm_ua_dcch_sapi4));
162}
163
164function f_TC_sabm_contention(charstring id) runs on ConnHdlr {
Harald Welte72c81e72019-05-30 16:36:11 +0200165 var LAPDm_ph_data phd;
166 const octetstring payload := '0102030405'O;
167 const GsmSapi sapi := 0;
168 const boolean use_sacch := false;
169 timer T := 5.0;
170
Eric Wild74f25ae2019-06-14 11:44:29 +0200171 fp_common_init();
172 RSL.clear;
173 LAPDM.clear;
Harald Welte72c81e72019-05-30 16:36:11 +0200174
Harald Welte72c81e72019-05-30 16:36:11 +0200175 /* first frame is our real SABM */
Eric Wild74f25ae2019-06-14 11:44:29 +0200176 LAPDM.send(t_PH_DATA(sapi, use_sacch, ts_LAPDm_SABM(sapi, c_r:=cr_MO_CMD, p:=false, l3:=payload)));
Harald Welte72c81e72019-05-30 16:36:11 +0200177 /* second frame is a SABM with different payload, which BTS has to ignore according to 8.4.1.4 */
Eric Wild74f25ae2019-06-14 11:44:29 +0200178 LAPDM.send(t_PH_DATA(sapi, use_sacch, ts_LAPDm_SABM(sapi, c_r:=cr_MO_CMD, p:=false, l3:='ABCDEF'O)));
Harald Welte72c81e72019-05-30 16:36:11 +0200179 T.start
180 alt {
Eric Wild74f25ae2019-06-14 11:44:29 +0200181 [] LAPDM.receive(t_PH_DATA(?, use_sacch, tr_LAPDm_UA(sapi, cr_MT_RSP, f:=false, l3:=payload))) { setverdict(pass); repeat; }
182 [] LAPDM.receive(t_PH_DATA(?, use_sacch, tr_LAPDm_UA(sapi, cr_MT_RSP, f:=false, l3:=?))) {
Harald Welte72c81e72019-05-30 16:36:11 +0200183 setverdict(fail, "Second SABM was responded to during contention resolution");
Eric Wild74f25ae2019-06-14 11:44:29 +0200184 }
185 [] RSL.receive {repeat;}
Harald Welte72c81e72019-05-30 16:36:11 +0200186 [] LAPDM.receive { repeat };
187 [] T.timeout { }
Harald Welte9e4725d2017-07-16 23:18:09 +0200188 }
Eric Wild74f25ae2019-06-14 11:44:29 +0200189
190 fp_common_fini();
191}
192
193testcase TC_sabm_contention() runs on test_CT {
194 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
195 f_testmatrix_each_chan(pars, refers(f_TC_sabm_contention));
Harald Welte72c81e72019-05-30 16:36:11 +0200196}
Harald Welte9e4725d2017-07-16 23:18:09 +0200197
Harald Welte72c81e72019-05-30 16:36:11 +0200198/* we test that a re-transmitted SABM with identical payload will result in the retransmission of a
199 * UA. This is required during the contention resolution procedure as specified in 8.4.1.4 */
Eric Wild74f25ae2019-06-14 11:44:29 +0200200function f_TC_sabm_retransmit(charstring id) runs on ConnHdlr {
Harald Welte72c81e72019-05-30 16:36:11 +0200201 const octetstring payload := '00FEFEDEADBEEF'O;
Eric Wild74f25ae2019-06-14 11:44:29 +0200202 fp_common_init();
203 RSL.clear;
204 LAPDM.clear;
205 var default d := activate(as_ignore_background());
Harald Welte72c81e72019-05-30 16:36:11 +0200206 if (not f_test_sabm_results_in_ua(0, false, payload)) {
Eric Wild74f25ae2019-06-14 11:44:29 +0200207 setverdict(fail);
Harald Welte599faa12017-07-17 21:49:24 +0200208 }
Harald Welte72c81e72019-05-30 16:36:11 +0200209 if (not f_test_sabm_results_in_ua(0, false, payload)) {
Eric Wild74f25ae2019-06-14 11:44:29 +0200210 setverdict(fail);
Harald Welted4ba7ff2017-07-17 21:00:48 +0200211 }
Harald Welte72c81e72019-05-30 16:36:11 +0200212 setverdict(pass);
Eric Wild74f25ae2019-06-14 11:44:29 +0200213 deactivate(d);
214 fp_common_fini();
Harald Welte72c81e72019-05-30 16:36:11 +0200215}
Harald Welted4ba7ff2017-07-17 21:00:48 +0200216
Eric Wild74f25ae2019-06-14 11:44:29 +0200217testcase TC_sabm_retransmit() runs on test_CT {
218 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
219 f_testmatrix_each_chan(pars, refers(f_TC_sabm_retransmit));
Harald Welte72c81e72019-05-30 16:36:11 +0200220}
Harald Welted4ba7ff2017-07-17 21:00:48 +0200221
Harald Welte2f2b2b72019-05-31 22:24:57 +0200222/*********************************************************************************
223 * Test using both L1CTL/LAPDm and RSL
224 *********************************************************************************/
225
226private function fp_common_init() runs on ConnHdlr
227{
228 /* undo what f_start_handler is doing and pull LAPDm_CT into the loop */
229 unmap(self:L1CTL, system:L1CTL);
230 f_lapdm_init();
Vadim Yanitskiya9894282020-07-14 01:56:15 +0700231
232 /* Obtain frequency hopping parameters for a given timeslot */
233 if (mp_freq_hop_enabled and mp_transceiver_num > 1) {
234 f_resolve_fh_params(g_pars);
235 }
236
Harald Welte2f2b2b72019-05-31 22:24:57 +0200237 /* activate the channel on the BTS side */
238 f_rsl_chan_act(g_pars.chan_mode, false, {});
239 /* activate the channel on the MS side */
240 f_switch_dcch({false, mp_trx0_arfcn}, g_chan_nr, 7);
241}
242
243private function fp_common_fini() runs on ConnHdlr
244{
245 f_release_dcch();
246 f_rsl_chan_deact();
247 f_lapdm_exit();
248}
249
Harald Welte76771f12019-06-02 22:58:58 +0200250/* Mobile-Originated LAPDm establishment on given Link ID */
251private function f_establish_mo(RslLinkId link_id) runs on ConnHdlr
252{
253 var integer sapi := link_id.sapi;
254 var boolean is_sacch := false;
255 if (link_id.c == SACCH) {
256 is_sacch := true;
257 }
258
259 var octetstring l3_mo := f_rnd_octstring(5);
260
261 /* MO Establish Request via LADPm: SAPI = 0, C = 0, P = 1, M = 0, 0 ≤ L ≤ N201.. */
262 if (is_sacch) {
263 /* no payload permitted, as this is not contention resolution */
264 l3_mo := ''O;
265 LAPDM.send(t_PH_DATA(0, is_sacch, ts_LAPDm_SABM(sapi, c_r:=cr_MO_CMD, p:=true, l3:=l3_mo)));
266 RSL.receive(tr_RSL_EST_IND_NOL3(g_chan_nr, link_id));
267 } else {
268 LAPDM.send(t_PH_DATA(0, is_sacch, ts_LAPDm_SABM(sapi, c_r:=cr_MO_CMD, p:=true, l3:=l3_mo)));
269 RSL.receive(tr_RSL_EST_IND(g_chan_nr, link_id, l3_mo));
270 }
271 /* UA: SAPI = 0, R = 0, F = 1, M = 0, L = L of SABM. */
272 LAPDM.receive(t_PH_DATA(0, is_sacch, tr_LAPDm_UA(sapi, cr_MT_RSP, f:=true, l3:=l3_mo)));
273}
274
Harald Welte2f2b2b72019-05-31 22:24:57 +0200275/* Verify that the BTS is re-transmitting SABM messages after T200 timeout, inspired
276 by 3GPP TS 51.010-1 25.2.1.1.2.1 + 25.2.1.2.4 */
277private function f_TC_sabm_retransmit_bts(charstring id) runs on ConnHdlr {
278 const integer sapi := 3; /* BTS may not establish SAPI=0 outbound */
279 fp_common_init();
280
281 LAPDM.clear;
282 RSL.send(ts_RSL_EST_REQ(g_chan_nr, ts_RslLinkID_DCCH(sapi)));
283
284 timer T := 8.0;
285 var integer sabm_received := 0;
286 T.start;
287 alt {
288 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_SABM(sapi, ?, ?, ''O))) {
289 sabm_received := sabm_received + 1;
290 repeat;
291 }
292 [] LAPDM.receive { repeat; }
293 [] T.timeout { }
294 }
295 if (sabm_received == 0) {
296 setverdict(fail, "No SABM observed at all!");
297 } else if (sabm_received != 6) {
298 setverdict(fail, "Incorrect number of SABM re-transmissions of observed: ",
299 sabm_received);
300 } else {
301 setverdict(pass, "Received ", sabm_received, " SABM");
302 }
303
304 fp_common_fini();
305}
306testcase TC_sabm_retransmit_bts() runs on test_CT {
307 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
308 f_testmatrix_each_chan(pars, refers(f_TC_sabm_retransmit_bts));
309}
310
311
312type record LapdmNamedFrame {
313 charstring name,
314 LapdmFrame lapdm
315};
316
317/* Test that the BTS will ignore receipt of frames other than a UA when
318 * received in response to the SABM frame, inspired from 3GPP TS 51.010-1
319 * Section 25.2.1.1.2.3 */
320private function f_TC_sabm_invalid_resp2(charstring id, LapdmNamedFrame err_frame) runs on ConnHdlr {
321 var integer sapi := err_frame.lapdm.ab.addr.sapi;
322 fp_common_init();
323
324 /* Establish Request via RSL; Expect SABM on LAPDm side */
325 LAPDM.clear;
326 RSL.send(ts_RSL_EST_REQ(g_chan_nr, ts_RslLinkID_DCCH(sapi)));
327 alt {
328 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_SABM(sapi, ?, ?, ''O)));
329 [] LAPDM.receive { repeat; }
330 }
331
332 /* send erroneous response to SABM */
333 LAPDM.send(t_PH_DATA(0, false, err_frame.lapdm));
334
335 /* expect a SABM retransmission of the BTS */
336 timer T := 3.0;
337 T.start;
338 alt {
339 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_SABM(sapi, ?, ?, ''O))) {
340 setverdict(pass);
341 }
342 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_UI(0, ?, ''O))) { repeat; }
343 [] LAPDM.receive(t_PH_DATA(0, false, ?)) {
344 setverdict(fail, "Received unexpected LAPDm frame instead of SABM after sending ",
345 err_frame.name);
346 }
347 [] LAPDM.receive { repeat; }
348 [] T.timeout {
349 setverdict(fail, "Timeout waiting for SABM retransmission after sending ",
350 err_frame.name);
351 }
352 }
353
354 fp_common_fini();
355}
356private function f_TC_sabm_invalid_resp(charstring id) runs on ConnHdlr {
357 const integer sapi := 3; /* BTS may not establish SAPI=0 outbound */
358 var LapdmNamedFrame err_frame[3] := {
359 { "I", valueof(ts_LAPDm_I(sapi, c_r := cr_MO_CMD, p := true, nr := 0, ns := 0,
360 l3 := '01020304'O)) },
361 { "RR", valueof(ts_LAPDm_RR(sapi, c_r := cr_MO_CMD, p := true, nr := 0)) },
362 { "REJ" , valueof(ts_LAPDm_REJ(sapi, c_r := cr_MO_CMD, p := true, nr := 0)) }
363 };
364 var integer i;
365
366 for (i := 0; i < lengthof(err_frame); i := i+1) {
367 f_TC_sabm_invalid_resp2(id, err_frame[i])
368 }
369}
370testcase TC_sabm_invalid_resp() runs on test_CT {
371 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
372 f_testmatrix_each_chan(pars, refers(f_TC_sabm_invalid_resp));
373}
374
375/* Test that the BTS will not re-transmit SABM frames after receiving a DM response,
376 * inspired from 3GPP TS 51.010-1 Section 25.2.1.1.3 */
377private function f_TC_sabm_dm(charstring id) runs on ConnHdlr {
378 const integer sapi := 3; /* BTS may not establish SAPI=0 outbound */
379 fp_common_init();
380
381 /* Establish Request via RSL; Expect SABM on LAPDm side */
382 LAPDM.clear;
383 RSL.send(ts_RSL_EST_REQ(g_chan_nr, ts_RslLinkID_DCCH(sapi)));
384 alt {
385 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_SABM(sapi, ?, ?, ''O)));
386 [] LAPDM.receive { repeat; }
387 }
388
389 /* send DM response to SABM */
390 RSL.clear;
391 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_DM(sapi, c_r:=cr_MO_RSP, f:=true)));
392 alt {
393 [] RSL.receive(tr_RSL_REL_IND(g_chan_nr, tr_RslLinkID_DCCH(sapi)));
394 [] RSL.receive { repeat; }
395 }
396
397 /* expect no SABM retransmission of the BTS */
398 timer T := 3.0;
399 T.start;
400 alt {
401 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_SABM(sapi, ?, ?, ''O))) {
402 setverdict(fail, "Received unexpected SABM retransmission");
403 }
404 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_UI(0, ?, ''O))) { repeat; }
405 [] LAPDM.receive(t_PH_DATA(0, false, ?)) {
406 setverdict(fail, "Received unexpected LAPDm frame");
407 }
408 [] LAPDM.receive { repeat; }
409 [] T.timeout {
410 setverdict(pass);
411 }
412 }
413
414 fp_common_fini();
415}
416testcase TC_sabm_dm() runs on test_CT {
417 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
418 f_testmatrix_each_chan(pars, refers(f_TC_sabm_dm));
419}
420
421/* Test the full LAPDm establishment while simulating the loss of the initial SABM or UA
422 * frame, requiring the BTS to re-transmit one SABM and then following up all the way to
423 * dedicated mode; inspired by 3GPP TS 51.010-1 25.2.1.2.2 */
424private function f_TC_establish_ign_first_sabm(charstring id) runs on ConnHdlr {
425 const integer sapi := 3; /* BTS may not establish SAPI=0 outbound */
426 var integer num_sabm := 0;
427 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(sapi));
428 timer T := 3.0;
429
430 fp_common_init();
431
432 /* Establish Request via RSL */
433 LAPDM.clear;
434 RSL.send(ts_RSL_EST_REQ(g_chan_nr, link_id));
435 /* Expect two SABM (retransmit) */
436 T.start;
437 alt {
438 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_SABM(sapi, ?, ?, ''O))) {
439 num_sabm := num_sabm + 1;
440 if (num_sabm < 2) {
441 repeat;
442 }
443 }
444 [] LAPDM.receive { repeat; }
445 }
446
447 /* send UA response to SABM */
448 RSL.clear;
449 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_UA(sapi, c_r:=cr_MO_RSP, f:=true, l3:=''O)));
450 alt {
451 [] RSL.receive(tr_RSL_EST_CONF(g_chan_nr, link_id));
452 [] RSL.receive { repeat; }
453 }
454
455 /* Send I frame from BTS to MS */
456 var octetstring l3 := f_rnd_octstring(10);
457 RSL.send(ts_RSL_DATA_REQ(g_chan_nr, link_id, l3));
458 alt {
459 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_I(sapi, c_r:=cr_MT_CMD, p:=false,
460 nr:=0, ns:=0, l3:=l3)));
461 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_UI(0, ?, ''O))) { repeat; }
462 [] LAPDM.receive(t_PH_DATA(0, true, ?)) { repeat; }
463 [] LAPDM.receive { setverdict(fail, "Unexpected LAPDm received"); }
464 }
465 /* Send RR frame in response */
466 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_RR(sapi, c_r:=cr_MO_RSP, p:=false, nr:=1)));
467
468 /* expect idle UI Frame from BTS */
469 alt {
470 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_UI(0, ?, ''O))) {
471 setverdict(pass);
472 }
473 [] LAPDM.receive(t_PH_DATA(0, true, ?)) { repeat; }
474 [] LAPDM.receive { setverdict(fail, "Unexpected LAPDm received"); }
475 }
476
477 fp_common_fini();
478}
479testcase TC_establish_ign_first_sabm() runs on test_CT {
480 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
481 f_testmatrix_each_chan(pars, refers(f_TC_establish_ign_first_sabm));
482}
483
484/* ignore all SACCH frames */
485private altstep as_lapdm_acch() runs on ConnHdlr {
486 [] LAPDM.receive(t_PH_DATA(0, true, ?)) { repeat; }
487}
Harald Welteef6fd442019-06-01 21:41:29 +0200488/* ignore all DCCH frames */
489private altstep as_lapdm_dcch() runs on ConnHdlr {
490 [] LAPDM.receive(t_PH_DATA(0, false, ?)) { repeat; }
491}
Harald Welte2f2b2b72019-05-31 22:24:57 +0200492/* ignore all LAPDm idle frames (UI) */
493private altstep as_lapdm_idle() runs on ConnHdlr {
Harald Welteef6fd442019-06-01 21:41:29 +0200494 [] LAPDM.receive(t_PH_DATA(0, ?, tr_LAPDm_UI(?, ?, ''O))) { repeat; }
Harald Welte2f2b2b72019-05-31 22:24:57 +0200495}
496/* ignore all measurement reports */
497private altstep as_rsl_meas_rep() runs on ConnHdlr {
498 [] RSL.receive(tr_RSL_MEAS_RES(g_chan_nr)) { repeat; }
499}
500/* fail if we receive an RSL ERROR IND */
501private altstep as_rsl_fail_err() runs on ConnHdlr {
502 var RSL_Message rx_rsl;
503 [] RSL.receive(tr_RSL_ERROR_IND(g_chan_nr, ?, ?)) {
504 setverdict(fail, "Received RSL ERROR IND ", rx_rsl);
505 }
506}
507/* all of the above */
Eric Wild211acc32019-06-11 19:06:38 +0200508private altstep as_ignore_background(boolean want_dcch := true, boolean ignore_rsl_errors := false) runs on ConnHdlr {
Harald Welteef6fd442019-06-01 21:41:29 +0200509 [want_dcch] as_lapdm_acch();
510 [not want_dcch] as_lapdm_dcch();
Harald Welte2f2b2b72019-05-31 22:24:57 +0200511 [] as_lapdm_idle();
512 [] as_rsl_meas_rep();
Eric Wild211acc32019-06-11 19:06:38 +0200513 [not ignore_rsl_errors] as_rsl_fail_err();
514 [ignore_rsl_errors] RSL.receive(tr_RSL_ERROR_IND(g_chan_nr, ?, ?)) { repeat;}
Harald Welte2f2b2b72019-05-31 22:24:57 +0200515}
516
517/* Test the operation of Layer 2 sequence numbering.
518 * dedicated mode; inspired by 3GPP TS 51.010-1 25.2.2.1 */
519private function f_TC_iframe_seq_and_ack(charstring id) runs on ConnHdlr {
520 const integer sapi := 0;
521 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(sapi));
522 var octetstring l3 := f_rnd_octstring(18);
523 var default d;
524 timer T := 3.0;
525
526 fp_common_init();
527
528 /* some common altstep for meas res and other background noise */
529 d := activate(as_ignore_background());
530 RSL.clear;
531 LAPDM.clear;
532
Harald Welte76771f12019-06-02 22:58:58 +0200533 f_establish_mo(link_id);
Harald Welte2f2b2b72019-05-31 22:24:57 +0200534
535 var integer last_ns_rx := 0;
536
537 for (var integer i := 0; i < 10; i := i+1) {
538 var octetstring l3_mo := f_rnd_octstring(12);
539 var octetstring l3_mt := f_rnd_octstring(12);
540 var LAPDm_ph_data pd;
541
542 log("Starting iteration ", i);
543 /* MT I frame */
544 RSL.send(ts_RSL_DATA_REQ(g_chan_nr, link_id, l3_mt));
545 alt {
546 /* SAPI = 0, R = 1, F = 0, M = 0, L = 0. */
547 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_RR(sapi, c_r:=cr_MT_RSP, p:=false,
548 nr:=i mod 8))) {
549 log("Ignoring RR in iteration ", i);
550 repeat;
551 }
552 /* SAPI = 0, C = 1, P = 0, M = 0, 0 ≤ L ≤ N201. */
553 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_I(sapi, c_r:=cr_MT_CMD, p:=false,
554 nr:=i mod 8, ns:=i mod 8,
555 l3:=l3_mt))) -> value pd {
556 last_ns_rx := pd.lapdm.ab.ctrl.i.n_s;
557 }
558 }
559 /* respond with MO I-frame: SAPI = 0, C = 0, P = 0, M = 0, 0 <= L <= N201. */
560 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_I(sapi, c_r:=cr_MO_CMD, p:=false,
561 nr:=(last_ns_rx+1)mod 8,
562 ns:=i mod 8, l3 := l3_mo)));
563 RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, l3_mo));
564 }
565 log("Completed iteration");
566
567 deactivate(d);
568 fp_common_fini();
569}
570testcase TC_iframe_seq_and_ack() runs on test_CT {
571 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
572 f_testmatrix_each_chan(pars, refers(f_TC_iframe_seq_and_ack));
573}
574
575/* To test that the BTS is able to respond to I frames whilst in the timer recovery state.
576 * Inspired by 3GPP TS 51.010-1 25.2.2.2 */
577
578/*
579 1) The BTS is brought into the multiple frame established state
580 2) The MS sends an L3 Request asking for IMEI to the MS.
581 3) The BTS shall respond with a RR frame though this may be incorporated with
582 the L3 Response I frame. The MS does not respond to the I frame.
583 4) The BTS shall wait for expiry of timer T200 and then repeat the I frame but
584 with the P bit set to 1.
585 5) The MS then sends a valid L3 Request I frame asking for IMEI which
586 does not acknowledge receipt of the I frame from the BTS.
587On the FACCH the BTS may send an RR frame acknowledging the I frame.
588 6) The BTS shall repeat the I frame, this frame will acknowledge receipt of
589 the second I frame from the MS.
590 7) The MS then acknowledges receipt of the MS I frame by sending a RR frame.
591 8) The BTS shall send the next I frame. The MS acknowledges this I frame.
592*/
593private function f_TC_iframe_timer_recovery(charstring id) runs on ConnHdlr {
594 const integer sapi := 0;
595 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(sapi));
596 var default d;
597 timer T := 3.0;
598
599 fp_common_init();
600
601 /* some common altstep for meas res and other background noise */
602 d := activate(as_ignore_background());
603 RSL.clear;
604 LAPDM.clear;
605
606 var octetstring l3_mo := f_rnd_octstring(12);
607 var octetstring l3_mt := f_rnd_octstring(12);
608
609 /* 1) The BTS is brought into the multiple frame established state */
610
611 /* MO Establish Request via LADPm: SAPI = 0, C = 0, P = 1, M = 0, 0 ≤ L ≤ N201.. */
612 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_SABM(sapi, c_r:=cr_MO_CMD, p:=true, l3:=l3_mo)));
613 RSL.receive(tr_RSL_EST_IND(g_chan_nr, link_id, l3_mo));
614 /* UA: SAPI = 0, R = 0, F = 1, M = 0, L = L of SABM. */
615 LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_UA(sapi, cr_MT_RSP, f:=true, l3:=l3_mo)));
616
617 /* 2) The MS sends an L3 Request to the BTS */
618 l3_mo := f_rnd_octstring(18);
619 /* SAPI = 0, C = 1, P = 0, M = 0, 0 ≤ L ≤ N201, N(S) = 0, N(R) = 0. * */
620 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_I(sapi, c_r:=cr_MO_CMD, p:=false,
621 nr:=0, ns:=0, l3:=l3_mo)));
622 RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, l3_mo));
623 /* 3) The BTS shall respond with a RR frame though this may be incorporated with
624 the L3 Response I frame. The MS does not respond to the I frame. */
625 RSL.send(ts_RSL_DATA_REQ(g_chan_nr, link_id, l3_mt));
626 alt {
627 /* SAPI = 0, R = 1, F = 0, M = 0, L = 0, N(R) = 1. */
628 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_RR(sapi, c_r:=cr_MT_RSP, p:=false, nr:=1))) {
629 repeat;
630 }
631 /* SAPI = 0, C = 0, P = 0, M = 0, 0 ≤ L ≤ N201, N(R) = 1, N(S) = 0 */
632 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_I(sapi, c_r:=cr_MT_CMD, p:=false,
633 nr:=1, ns:=0, l3:=l3_mt)));
634 }
635
636 /* 4) The BTS shall wait for expiry of timer T200 and then repeat the I frame but
637 with the P bit set to 1. */
638 /* SAPI = 0, C = 0, P = 1, M = 0, 0 ≤ L ≤ N201, N(R) = 1, N(S) = 0. * */
639 LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_I(sapi, c_r:=cr_MT_CMD, p:=true,
640 nr:=1, ns:=0, l3:=l3_mt)));
641
642 /* 5) The MS then sends a valid L3 Request I frame asking for IMEI which
643 does not acknowledge receipt of the I frame from the BTS. */
644 /* SAPI = 0, C = 1, P = 0, M = 0, 0 ≤ L ≤ N201, N(S) = 1, N(R) = 0. * */
645 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_I(sapi, c_r:=cr_MO_CMD, p:=false,
646 nr:=0, ns:=1, l3 := l3_mo)));
647 RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, l3_mo));
648 alt {
649 /* On the FACCH the BTS may send an RR frame acknowledging the I frame. */
650 /* SAPI = 0, R = 1, F = 0, M = 0, L = 0, N(R) = 2. */
651 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_RR(sapi, c_r:=cr_MT_RSP, p:=false, nr:=2))) {
652 repeat;
653 }
654 /* 6) The BTS shall repeat the I frame, this frame will acknowledge
655 receipt of the second I frame from the MS. */
656 /* SAPI = 0, C = 0, P = 1, M = 0, 0 ≤ L ≤ N201, N(R) = 2, N(S) = 0. * */
657 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_I(sapi, c_r:=cr_MT_CMD, p:=true,
658 nr:=2, ns:=0, l3:=l3_mt)));
659 }
660
661 /* 7) The MS then acknowledges receipt of the BTS I frame by sending a RR * frame. */
662 /* SAPI = 0, R = 0, F = 1, 0, M = 0, L = 0, N(R) = 1 */
663 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_RR(sapi, c_r:=cr_MO_RSP, p:=true, nr:=1)));
664
665 /* 8) The BTS shall send the next I frame. The MS acknowledges this I frame. */
666 l3_mt := f_rnd_octstring(16);
667 RSL.send(ts_RSL_DATA_REQ(g_chan_nr, link_id, l3_mt));
668 /* SAPI = 0, C = 0, P = 0, M = 0, 0 ≤ L ≤ N201, N(R) = 2, N(S) = 1 */
669 LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_I(sapi, c_r:=cr_MT_CMD, p:=false,
670 nr:=2, ns:=1, l3:=l3_mt)));
671 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_RR(sapi, c_r:=cr_MO_RSP, p:=true, nr:=2)));
672
673 deactivate(d);
674 fp_common_fini();
675}
676testcase TC_iframe_timer_recovery() runs on test_CT {
677 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
678 f_testmatrix_each_chan(pars, refers(f_TC_iframe_timer_recovery));
679}
680
Eric Wild211acc32019-06-11 19:06:38 +0200681/* 25.2.6.1 ns sequence error
682sends wrong N(S), expects REJ, sends wrong N(S) with P=1, expects REJ with F=1 */
683private function f_TC_ns_seq_error(charstring id) runs on ConnHdlr {
684 const integer sapi := 0;
685 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(sapi));
686 var default d;
687 timer T := 3.0;
688
689 fp_common_init();
690
691 /* some common altstep for meas res and other background noise */
692 d := activate(as_ignore_background(ignore_rsl_errors := true));
693 RSL.clear;
694 LAPDM.clear;
695
696 var octetstring l3_mo := f_rnd_octstring(12);
697 var octetstring l3_mt := f_rnd_octstring(12);
698
699 /* 1) The BTS is brought into the multiple frame established state */
700
701 /* MO Establish Request via LADPm: SAPI = 0, C = 0, P = 1, M = 0, 0 ≤ L ≤ N201.. */
702 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_SABM(sapi, c_r:=cr_MO_CMD, p:=true, l3:=l3_mo)));
703 RSL.receive(tr_RSL_EST_IND(g_chan_nr, link_id, l3_mo));
704 /* UA: SAPI = 0, R = 0, F = 1, M = 0, L = L of SABM. */
705 LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_UA(sapi, cr_MT_RSP, f:=true, l3:=l3_mo)));
706
707 /* 2) The MS sends an L3 Request to the BTS */
708 l3_mo := f_rnd_octstring(18);
709 /* SAPI = 0, C = 1, P = 0, M = 0, 0 ≤ L ≤ N201, N(S) = 0, N(R) = 0. * */
710 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_I(sapi, c_r:=cr_MO_CMD, p:=false,
711 nr:=0, ns:=0, l3:=l3_mo)));
712 RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, l3_mo));
713 /* 3) The BTS shall respond with a RR frame though this may be incorporated with
714 the L3 Response I frame. */
715 RSL.send(ts_RSL_DATA_REQ(g_chan_nr, link_id, l3_mt));
716 alt {
717 /* SAPI = 0, R = 1, F = 0, M = 0, L = 0, N(R) = 1. */
718 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_RR(sapi, c_r:=cr_MT_RSP, p:=false, nr:=1))) {
719 repeat;
720 }
721 /* SAPI = 0, C = 0, P = 0, M = 0, 0 ≤ L ≤ N201, N(R) = 1, N(S) = 0 */
722 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_I(sapi, c_r:=cr_MT_CMD, p:=false,
723 nr:=1, ns:=0, l3:=l3_mt)));
724 }
725
726 /* 4) The MS shall then send an I frame containing Identity Request with incorrect N(S)
727 but correctly acknowledging the MS's I frame; P bit set to zero. */
728 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_I(sapi, c_r:=cr_MO_CMD, p:=false,
729 nr:=1, ns:=0, l3:=l3_mo)));
730
731 /* no rsl data ind due to wrong ns */
732
733 /* The BTS shall send a REJ frame. */
734 timer T1 := 2.0;
735 T1.start;
736 alt{
737 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_REJ(sapi, c_r:=cr_MT_RSP, p:=false, nr:=1)));
738 [] T1.timeout{ setverdict(fail, "Missing first REJ")}
739 }
740
741 f_sleep(2.0); // T200
742
743 /* The MS shall, after T200, send another I frame with incorrect N(S), P bit set to 1 this time. */
744 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_I(sapi, c_r:=cr_MO_CMD, p:=true,
745 nr:=1, ns:=0, l3:=l3_mo)));
746
747 /* The BTS shall respond with a REJ, F bit set to 1. */
748 T1.start;
749 alt{
750 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_REJ(sapi, c_r:=cr_MT_RSP, p:=true, nr:=1)));
751 [] T1.timeout{ setverdict(fail, "Missing second REJ")}
752 }
753
754 deactivate(d);
755 fp_common_fini();
756 setverdict(pass);
757}
758
759testcase TC_ns_seq_error() runs on test_CT {
760 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
761 f_testmatrix_each_chan(pars, refers(f_TC_ns_seq_error));
762}
763
764/* 25.2.6.2 nr sequence error */
765private function f_TC_nr_seq_error(charstring id) runs on ConnHdlr {
766 const integer sapi := 0;
767 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(sapi));
768 var default d;
769 var integer n201 := 20;
770 if (link_id.c == SACCH) {
771 n201 := 18;
772 }
773
774 fp_common_init();
775
776 /* some common altstep for meas res and other background noise */
777 d := activate(as_ignore_background(ignore_rsl_errors := true));
778 RSL.clear;
779 LAPDM.clear;
780
781 var octetstring l3_mo := f_rnd_octstring(12);
782 var octetstring l3_mt := f_rnd_octstring(12);
783
784 /* 1) The BTS is brought into the multiple frame established state */
785
786 /* MO Establish Request via LADPm: SAPI = 0, C = 0, P = 1, M = 0, 0 ≤ L ≤ N201.. */
787 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_SABM(sapi, c_r:=cr_MO_CMD, p:=true, l3:=l3_mo)));
788 RSL.receive(tr_RSL_EST_IND(g_chan_nr, link_id, l3_mo));
789 /* UA: SAPI = 0, R = 0, F = 1, M = 0, L = L of SABM. */
790 LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_UA(sapi, cr_MT_RSP, f:=true, l3:=l3_mo)));
791
792 /* 2) The MS shall send an I frame containing an information field of length N201 and an
793 incorrect receive sequence number. */
794 l3_mo := f_rnd_octstring(n201);
795 /* SAPI = 0, C = 1, P = 0, M = 0, L = N201, N(S) = 0, N(R) = 1. * */
796 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_I(sapi, c_r:=cr_MO_CMD, p:=false,
797 nr:=1, ns:=0, l3:=l3_mo)));
798
799 /* The BTS may: a) send a DISC frame within N200×T200; */
800 /* DISC SAPI = 0, C = 0, P = 1, M = 0, L = 0. */
801 timer T1 := 2.0;
802 T1.start;
803 alt{
804 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_DISC(sapi, c_r:=cr_MT_CMD, p:=true)));
805 [] T1.timeout{ setverdict(fail, "Missing DISC from BTS")}
806 }
807
808 /* a) the MS shall respond with a UA frame.
809 SAPI = 0, R = 0, F = 1, M = 0, L = 0. */
810 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_UA(sapi, c_r:=cr_MO_CMD, f:=true, l3:=l3_mo)));
811
812 deactivate(d);
813 fp_common_fini();
814 setverdict(pass);
815}
816
817testcase TC_nr_seq_error() runs on test_CT {
818 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
819 f_testmatrix_each_chan(pars, refers(f_TC_nr_seq_error));
820}
821
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100822private function f_TC_rec_invalid_frame_txrx(integer sapi, LapdmFrame x, integer line_nr) runs on ConnHdlr {
Eric Wild211acc32019-06-11 19:06:38 +0200823 LAPDM.send(t_PH_DATA(0, false, x));
824 f_sleep(2.0); // T200
825 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_RR(sapi, c_r:=cr_MO_CMD, p:=true, nr:=0)));
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100826 timer T1 := 2.0;
827 T1.start;
828 alt {
829 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_RR(sapi, c_r:=cr_MT_RSP, p:=true , nr := 0))) { T1.stop; }
830 [] T1.timeout{ Misc_Helpers.f_shutdown(__BFILE__, line_nr, fail, "Missing LAPDm_RR RSP"); }
831 }
Eric Wild211acc32019-06-11 19:06:38 +0200832}
833
834/* 25.2.7 Test on receipt of invalid frames
835sends a bunch of different invalid frames, expects the BTS to ignore all of them */
836private function f_TC_rec_invalid_frame(charstring id) runs on ConnHdlr {
837 const integer sapi := 0;
838 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(sapi));
839 var default d;
840 timer T := 3.0;
841
842 fp_common_init();
843
844 /* some common altstep for meas res and other background noise */
845 d := activate(as_ignore_background(ignore_rsl_errors := true));
846 RSL.clear;
847 LAPDM.clear;
848
849 var octetstring l3_mo := f_rnd_octstring(12);
850 var octetstring l3_mt := f_rnd_octstring(12);
851
852 /* 1) The BTS is brought into the multiple frame established state */
853
854 /* MO Establish Request via LADPm: SAPI = 0, C = 0, P = 1, M = 0, 0 ≤ L ≤ N201.. */
855 LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_SABM(sapi, c_r:=cr_MO_CMD, p:=true, l3:=l3_mo)));
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100856 T.start
857 alt {
858 [] RSL.receive(tr_RSL_EST_IND(g_chan_nr, link_id, l3_mo)) {}
859 [] T.timeout{ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Missing RSL EST IND"); }
860 }
861 alt {
Eric Wild211acc32019-06-11 19:06:38 +0200862 /* UA: SAPI = 0, R = 0, F = 1, M = 0, L = L of SABM. */
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100863 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_UA(sapi, cr_MT_RSP, f:=true, l3:=l3_mo))) { T.stop; }
864 [] T.timeout{ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Missing LAPDm UA RSP"); }
865 }
Eric Wild211acc32019-06-11 19:06:38 +0200866
867 /* 1: One RR frame: SAPI = 0, R = 0, F = 0, M = 0, L > 0, N(R) = 1.
868 RR frame with the Length indicator greater than zero and a faulty N(R); */
869 var LapdmFrame x:= valueof(ts_LAPDm_RR(sapi, c_r:=cr_MO_CMD, p:=false, nr:=1));
870 x.ab.payload := f_rnd_octstring(5);
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100871 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200872 /* 3: One REJ frame: SAPI = 0, R = 0, F = 0, M = 0, L = 0, N(R) = 1, EA = 0.
873 EJ frame with the EA bit set to zero and a faulty N(R); */
874 x:= valueof(ts_LAPDm_REJ(sapi, c_r:=cr_MO_CMD, p:=false, nr:=1));
875 x.ab.addr.ea := false;
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100876 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200877 /* 4: One SABM frame: SAPI = 0, C = 1, P = 1, M = 0, L = 0, EL = 0.
878 SABM frame with the EL bit set to zero; */
879 l3_mo := ''O;
880 x:= valueof(ts_LAPDm_SABM(sapi, c_r:=cr_MO_CMD, p:=true, l3:=l3_mo));
881 x.ab.el := 0;
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100882 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200883 /* 5: One DM frame: SAPI = 0, R = 0, F = 1, M = 0, L > 0.
884 DM frame with the Length indicator greater than zero;*/
885 x:= valueof(ts_LAPDm_DM(sapi, c_r:=cr_MO_CMD, f:=true));
886 x.ab.payload := f_rnd_octstring(5);
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100887 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200888 /* 6: One DISC frame: SAPI = 0, C = 1, P = 1, M = 1, L = 0.
889 DISC frame with the M bit set to 1; */
890 x:= valueof(ts_LAPDm_DISC(sapi, c_r:=cr_MO_CMD, p:=true));
891 x.ab.m := true;
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100892 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200893 /* 7: One UA frame: SAPI = 0, R = 0, F = 0, M = 0, L = 0, EA = 0.
894 UA frame with the EA bit set to zero*/
895 x:= valueof(ts_LAPDm_UA(sapi, c_r:=cr_MO_CMD, f:=false, l3:=''O));
896 x.ab.addr.ea := false;
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100897 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200898 /* 8: One I frame: SAPI = 0, C = 1, P = 0, M = 0, L > N201, N(R) = 0, N(S) = 6.
899 I frame with the Length indicator greater than N201;*/
900 x:= valueof(ts_LAPDm_I(sapi, c_r:=cr_MO_CMD, p:=true, nr := 0, ns := 6, l3 := f_rnd_octstring(25)))
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100901 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200902 /* 9: One I frame: SAPI = 0, C = 1, P = 0, M = 1, L < N201, N(R) = 0, N(S) = 7.
903 I frame with the M bit set to 1 and the Length indicator less than N201;*/
904 x:= valueof(ts_LAPDm_I(sapi, c_r:=cr_MO_CMD, p:=true, nr := 0, ns := 7, l3 := f_rnd_octstring(5)))
905 x.ab.m := true;
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100906 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200907 /* 10: One RR frame: SAPI = 0, C = 1, P = 1, M = 0, L = 0, N(R) = 0. */
908 x:= valueof(ts_LAPDm_RR(sapi, c_r:=cr_MO_CMD, p:=true, nr:=0));
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100909 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200910
911 /* command frames with correct Address and Length indicator field and a non-implemented control field */
912 /* 12: One command frame with Control Field = xxx1 1101. */
913 x:= valueof(ts_LAPDm_RR(sapi, c_r:=cr_MO_CMD, p:=false, nr:=1));
914 x.ab.ctrl.other := bit2int('00011101'B);
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100915 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200916 /* 13: One command frame with Control field = xxx1 1011. */
917 x:= valueof(ts_LAPDm_RR(sapi, c_r:=cr_MO_CMD, p:=false, nr:=1));
918 x.ab.ctrl.other := bit2int('00011011'B);
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100919 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200920 /* 14: One command frame with Control field = xxx1 0111. */
921 x:= valueof(ts_LAPDm_RR(sapi, c_r:=cr_MO_CMD, p:=false, nr:=1));
922 x.ab.ctrl.other := bit2int('00010001'B);
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100923 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200924 /* 15: One command frame with Control field = 01x1 1111. */
925 x:= valueof(ts_LAPDm_RR(sapi, c_r:=cr_MO_CMD, p:=false, nr:=1));
926 x.ab.ctrl.other := bit2int('01011111'B);
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100927 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200928 /* 16: One command frame with Control field = 1xx1 1111. */
929 x:= valueof(ts_LAPDm_RR(sapi, c_r:=cr_MO_CMD, p:=false, nr:=1));
930 x.ab.ctrl.other := bit2int('10011111'B);
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100931 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200932 /* 17: One command frame with Control field = 0011 0011. */
933 x:= valueof(ts_LAPDm_RR(sapi, c_r:=cr_MO_CMD, p:=false, nr:=1));
934 x.ab.ctrl.other := bit2int('00110011'B);
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100935 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200936 /* 18: One command frame with Control field = 1xx1 0011. */
937 x:= valueof(ts_LAPDm_RR(sapi, c_r:=cr_MO_CMD, p:=false, nr:=1));
938 x.ab.ctrl.other := bit2int('10010011'B);
Pau Espin Pedrol26b562c2019-12-10 14:35:30 +0100939 f_TC_rec_invalid_frame_txrx(0, x, __LINE__);
Eric Wild211acc32019-06-11 19:06:38 +0200940
941 deactivate(d);
942 fp_common_fini();
943 setverdict(pass);
944}
945
946testcase TC_rec_invalid_frame() runs on test_CT {
947 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
948 pars.t_guard := 60.0;
949 f_testmatrix_each_chan(pars, refers(f_TC_rec_invalid_frame));
950}
951
Harald Welte9ea918c2019-06-01 11:46:25 +0200952type record LapdmDlConfig {
953 integer n201,
954 integer t200
955};
956
957type record LapdmDlState {
958 integer v_s,
959 integer v_a,
960 integer v_r
961};
962
963template (value) LapdmDlState t_init_LapdmDlState := {
964 v_s := 0,
965 v_a := 0,
966 v_r := 0
967}
968
969private function inc_mod8(inout integer v)
970{
971 v := (v + 1) mod 8;
972}
973
974private function f_lapdm_transceive_mo(inout LapdmDlState dls, RslLinkId link_id, octetstring l3)
975runs on ConnHdlr {
976 var LAPDm_ph_data pd;
977 var integer offset := 0;
978 var integer n201 := 20;
979 var boolean is_sacch := false;
980 if (link_id.c == SACCH) {
981 n201 := 18;
982 is_sacch := true;
983 }
984
985 while (offset < lengthof(l3)) {
986 var integer remain_len := lengthof(l3) - offset;
987 var integer seg_len := remain_len;
988 if (remain_len > n201) {
989 seg_len := n201;
990 }
991 var octetstring segment := substr(l3, offset, seg_len);
992 var boolean more;
993 if (offset + lengthof(segment) < lengthof(l3)) {
994 more := true;
995 } else {
996 more := false;
997 }
998 /* send the next segment */
999 LAPDM.send(t_PH_DATA(0, is_sacch,
1000 ts_LAPDm_I(link_id.sapi, c_r:=cr_MO_CMD, p:=false,
1001 nr:=dls.v_a, ns:=dls.v_s, l3:=segment, m:=more)));
1002 inc_mod8(dls.v_s);
1003 offset := offset + lengthof(segment);
1004
1005 /* wait for it to be acknowledged */
1006 alt {
1007 [] LAPDM.receive(t_PH_DATA(0, is_sacch, tr_LAPDm_RR(link_id.sapi, c_r:=cr_MT_RSP,
1008 p:=false, nr:=(dls.v_s) mod 8)));
Harald Welteef6fd442019-06-01 21:41:29 +02001009 [] as_ignore_background(not is_sacch);
Harald Welte9ea918c2019-06-01 11:46:25 +02001010 [] LAPDM.receive(t_PH_DATA(0, is_sacch, ?)) -> value pd {
1011 setverdict(fail, "received unexpected LAPDm ", pd);
1012 repeat;
1013 }
1014 [] LAPDM.receive(t_PH_DATA(0, ?, ?)) { repeat; }
1015 [offset < lengthof(l3)] RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, ?)) {
1016 setverdict(fail, "received RSL DATA IND before message complete");
1017 }
1018 }
1019 }
1020
1021 timer T := 1.0;
1022 T.start;
1023 alt {
1024 [] RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, l3)) {
1025 setverdict(pass);
1026 }
1027 [] RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, ?)) {
1028 setverdict(fail, "Received RSL DATA IND with wrong payload");
1029 }
1030 [] T.timeout {
1031 setverdict(fail, "Timeout waiting for RSL DATA IND of de-segmented message");
1032 }
1033 }
1034}
1035
1036/* Section 5.8.5 of TS 04.06 */
1037const integer c_TS0406_MAX_L3_OCTETS := 251;
1038
Harald Welteef6fd442019-06-01 21:41:29 +02001039/* test segmentation and de-segmentation (concatenation) of a large message in uplink
1040 * on specified SAPI/channel */
1041private function f_TC_segm_concat(charstring id, RslLinkId link_id) runs on ConnHdlr {
1042 var integer sapi := link_id.sapi;
1043 var boolean is_sacch := false;
1044 if (link_id.c == SACCH) {
1045 is_sacch := true;
1046 }
Harald Welte9ea918c2019-06-01 11:46:25 +02001047 var default d;
1048 timer T := 3.0;
1049
1050 fp_common_init();
1051
1052 /* some common altstep for meas res and other background noise */
Harald Welteef6fd442019-06-01 21:41:29 +02001053 d := activate(as_ignore_background(not is_sacch));
Harald Welte9ea918c2019-06-01 11:46:25 +02001054 RSL.clear;
1055 LAPDM.clear;
1056
Harald Welte76771f12019-06-02 22:58:58 +02001057 f_establish_mo(link_id);
Harald Welte9ea918c2019-06-01 11:46:25 +02001058
Harald Welte76771f12019-06-02 22:58:58 +02001059 var octetstring l3_mo := f_rnd_octstring(c_TS0406_MAX_L3_OCTETS);
Harald Welte9ea918c2019-06-01 11:46:25 +02001060
1061 deactivate(d);
1062
1063 var LapdmDlState dls := valueof(t_init_LapdmDlState);
1064 f_lapdm_transceive_mo(dls, link_id, l3_mo);
1065
1066 fp_common_fini();
1067}
Harald Welteef6fd442019-06-01 21:41:29 +02001068private function f_TC_segm_concat_dcch(charstring id) runs on ConnHdlr {
1069 f_TC_segm_concat(id, valueof(ts_RslLinkID_DCCH(0)));
Harald Welte9ea918c2019-06-01 11:46:25 +02001070}
Harald Welteef6fd442019-06-01 21:41:29 +02001071private function f_TC_segm_concat_sacch(charstring id) runs on ConnHdlr {
1072 f_TC_segm_concat(id, link_id :=valueof(ts_RslLinkID_SACCH(0)));
1073}
1074/* test mobile-originated segmentation/de-segmentation on DCCH */
1075testcase TC_segm_concat_dcch() runs on test_CT {
1076 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
1077 f_testmatrix_each_chan(pars, refers(f_TC_segm_concat_dcch));
1078}
1079/* test mobile-originated segmentation/de-segmentation on SACCH */
1080testcase TC_segm_concat_sacch() runs on test_CT {
1081 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
1082 f_testmatrix_each_chan(pars, refers(f_TC_segm_concat_sacch));
1083}
1084
Harald Welteb2a30342019-06-02 22:13:50 +02001085/* TS 04.06 Section 5.8.2.1 */
1086private function f_n200_by_chan_nr(RslChannelNr chan_nr, RslLinkId link_id) return integer {
1087 /* SACCH irrespective of physical channel type */
1088 if (match(link_id, tr_RslLinkID_SACCH(?))) {
1089 return 5;
1090 }
1091 /* DCCH below */
1092 select (chan_nr) {
1093 case (t_RslChanNr_SDCCH4(?, ?)) { return 23; }
1094 case (t_RslChanNr_SDCCH8(?, ?)) { return 23; }
1095 case (t_RslChanNr_Bm(?)) { return 34; }
1096 case (t_RslChanNr_Lm(?, ?)) { return 29; }
1097 }
1098 setverdict(fail, "Unknown chan_nr ", chan_nr, " or link_id ", link_id);
1099 return -1;
1100}
Harald Welte2f2b2b72019-05-31 22:24:57 +02001101
Harald Welteb2a30342019-06-02 22:13:50 +02001102/* Test if there are exactly N200+1 transmissions of I frames; inspired by 25.2.4.1 */
1103private function f_TC_t200_n200(charstring id) runs on ConnHdlr {
1104 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
1105 var integer sapi := link_id.sapi;
1106 var boolean is_sacch := false;
1107 if (link_id.c == SACCH) {
1108 is_sacch := true;
1109 }
1110 var integer n200 := f_n200_by_chan_nr(g_chan_nr, link_id);
1111 var integer num_retrans := 0;
1112 timer T := 3.0;
1113 var default d;
1114
1115 fp_common_init();
1116
1117 /* some common altstep for meas res and other background noise */
1118 d := activate(as_ignore_background(true));
1119 RSL.clear;
1120 LAPDM.clear;
1121
Harald Welte76771f12019-06-02 22:58:58 +02001122 f_establish_mo(link_id);
Harald Welteb2a30342019-06-02 22:13:50 +02001123
1124 var octetstring l3_mt := f_rnd_octstring(20);
1125 RSL.send(ts_RSL_DATA_REQ(g_chan_nr, link_id, l3_mt));
1126 /* first transmission, P = 0 */
1127 LAPDM.receive(t_PH_DATA(0, is_sacch, tr_LAPDm_I(sapi, c_r:=cr_MT_CMD, p:=false,
1128 nr:=0, ns:=0, l3:=l3_mt)));
1129 deactivate(d);
1130
1131 alt {
1132 /* re-transmission, P = 1 */
1133 [] LAPDM.receive(t_PH_DATA(0, is_sacch,
1134 tr_LAPDm_I(sapi, c_r:=cr_MT_CMD, p:=true, nr:=0, ns:=0, l3:=l3_mt))) {
1135 num_retrans := num_retrans + 1;
1136 if (num_retrans < n200) {
1137 repeat;
1138 } else if (num_retrans == n200) {
1139 T.start; /* wait for some more time if there are more retransmissions */
1140 repeat;
1141 } else {
1142 /* break */
1143 }
1144 }
1145 [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_I(sapi, ?, ?, ?, ?, ?))) {
1146 setverdict(fail, "Received unexpected I frame");
1147 }
1148 [not is_sacch] as_lapdm_acch();
1149 [is_sacch] as_lapdm_dcch();
1150 [] as_lapdm_idle();
1151 [] as_rsl_meas_rep();
1152 [num_retrans == n200] RSL.receive(tr_RSL_ERROR_IND(g_chan_nr, link_id, '01'O)) {
1153 /* break */
1154 }
1155 [] T.timeout {
1156 setverdict(fail, "Missing RSL RLL ERROR INDICATION");
1157 }
1158 }
1159
1160 if (num_retrans == n200) {
1161 setverdict(pass, "Received ", num_retrans, " on channel ", g_chan_nr, " link ", link_id);
1162 } else if (num_retrans < n200) {
1163 setverdict(fail, "Too few retransmissions (", num_retrans, "); N200=", n200,
1164 " on channel ", g_chan_nr, " link ", link_id);
1165 }
1166
1167 fp_common_fini();
1168}
1169testcase TC_t200_n200() runs on test_CT {
1170 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
1171 f_testmatrix_each_chan(pars, refers(f_TC_t200_n200));
1172}
Harald Welte2f2b2b72019-05-31 22:24:57 +02001173
Harald Welte7d9f6db2019-06-02 23:14:04 +02001174/* Ensure BTS repeats RR frame after retransmitting I frame to emulate RR loss;
1175 Inspired by TS 51.010-1 25.2.4.3 */
1176private function f_TC_rr_response_frame_loss(charstring id) runs on ConnHdlr {
1177 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
1178 var integer sapi := link_id.sapi;
1179 var boolean is_sacch := false;
1180 if (link_id.c == SACCH) {
1181 is_sacch := true;
1182 }
1183 timer T := 3.0;
1184 var default d;
1185
1186 fp_common_init();
1187
1188 /* some common altstep for meas res and other background noise */
1189 d := activate(as_ignore_background(true));
1190 RSL.clear;
1191 LAPDM.clear;
1192
1193 f_establish_mo(link_id);
1194
1195 var octetstring l3_mo := f_rnd_octstring(10);
1196 /* Send an I frame to the BTS: SAPI = 0, C = 1, P = 0, M = 0, L = 3, N(S) = 0, N(R) = 0 */
1197 LAPDM.send(t_PH_DATA(0, is_sacch, ts_LAPDm_I(sapi, c_r:=cr_MO_CMD, p:=false, nr:=0, ns:=0,
1198 l3:=l3_mo)));
1199 RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, l3_mo));
1200 /* SAPI = 0, R = 1, F = 0, M = 0, L = 0, N(R) = 1. */
1201 LAPDM.receive(t_PH_DATA(0, is_sacch, tr_LAPDm_RR(sapi, c_r:=cr_MT_RSP, p:=false, nr:=1)));
1202
1203 /* Re-send I frame: SAPI = 0, C = 1, P = 1, M = 0, L = 3, N(S) = 0, N(R) = 0. */
1204 LAPDM.send(t_PH_DATA(0, is_sacch, ts_LAPDm_I(sapi, c_r:=cr_MO_CMD, p:=true, nr:=0, ns:=0,
1205 l3:=l3_mo)));
1206
1207 T.start;
1208 alt {
1209 /* RR: SAPI = 0, R = 1, F = 1, M = 0, L = 0, N(R) = 1. */
1210 [] LAPDM.receive(t_PH_DATA(0, is_sacch, tr_LAPDm_RR(sapi, c_r:=cr_MT_RSP, p:=true, nr:=1))) {
1211 setverdict(pass);
1212 }
1213 /* REJ: SAPI = 0, R = 1, F = 1, M = 0, L = 0, N(R) = 1. */
1214 [] LAPDM.receive(t_PH_DATA(0, is_sacch, tr_LAPDm_REJ(sapi, c_r:=cr_MT_RSP, p:=true, nr:=1))) {
1215 setverdict(pass);
1216 }
1217 [] T.timeout {
1218 setverdict(fail, "Timeout waiting for RR or REJ");
1219 }
1220 }
1221
1222 deactivate(d);
1223
1224 fp_common_fini();
1225}
1226testcase TC_rr_response_frame_loss() runs on test_CT {
1227 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
1228 f_testmatrix_each_chan(pars, refers(f_TC_rr_response_frame_loss));
1229}
1230
Harald Welte44479782019-06-02 23:23:45 +02001231/* Ensure BTS ignores I frames with wrong C/R bit; Inspired by TS 51.010-1 25.2.5.1 */
1232private function f_TC_incorrect_cr(charstring id) runs on ConnHdlr {
1233 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
1234 var integer sapi := link_id.sapi;
1235 var boolean is_sacch := false;
1236 if (link_id.c == SACCH) {
1237 is_sacch := true;
1238 }
1239 timer T := 3.0;
1240 var default d;
1241
1242 fp_common_init();
1243
1244 /* some common altstep for meas res and other background noise */
1245 d := activate(as_ignore_background(true));
1246 RSL.clear;
1247 LAPDM.clear;
1248
1249 f_establish_mo(link_id);
1250
1251 var octetstring l3_mo := f_rnd_octstring(10);
1252 /* Send an I frame to the BTS: SAPI = 0, C = 0, P = 1, M = 0, L = 3, N(S) = 0, N(R) = 0 */
1253 LAPDM.send(t_PH_DATA(0, is_sacch, ts_LAPDm_I(sapi, c_r:=cr_MO_RSP, p:=true, nr:=0, ns:=0,
1254 l3:=l3_mo)));
1255 T.start;
1256 alt {
1257 [] RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, l3_mo)) {
1258 setverdict(fail, "BTS didn't ignore I frame with wrong C/R bit");
1259 }
1260 [] RSL.receive(tr_RSL_ERROR_IND(g_chan_nr, link_id, '0C'O)) {
1261 repeat;
1262 }
1263 /* ensure BTS still sends idle frames */
1264 [] as_lapdm_idle() {
1265 setverdict(pass, "still sending idle frames");
1266 }
1267 [] T.timeout {}
1268 }
1269
1270 /* Send RR command P=1 */
1271 LAPDM.send(t_PH_DATA(0, is_sacch, ts_LAPDm_RR(sapi, c_r:=cr_MO_CMD, p:=true, nr:=0)));
1272
1273 /* The BTS shall respond with a RR response, F bit set to 1. */
1274 LAPDM.receive(t_PH_DATA(0, is_sacch, tr_LAPDm_RR(sapi, c_r:=cr_MT_RSP, p:=true, nr:=0)));
1275
1276 deactivate(d);
1277
1278 fp_common_fini();
1279}
1280testcase TC_incorrect_cr() runs on test_CT {
1281 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
1282 f_testmatrix_each_chan(pars, refers(f_TC_incorrect_cr));
1283}
Harald Weltea39ac752019-06-04 21:46:07 +02001284
1285/* test that the BTS will take no action when it receives an SABM frame with the C bit set wrong (R)
1286 Inspired by TS 51.010-1 25.2.5.2 */
1287private function f_TC_sabm_incorrect_c(charstring id) runs on ConnHdlr {
1288 var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
1289 var integer sapi := link_id.sapi;
1290 var boolean is_sacch := false;
1291 if (link_id.c == SACCH) {
1292 is_sacch := true;
1293 }
1294 timer T := 3.0;
1295 var default d;
1296
1297 fp_common_init();
1298
1299 /* some common altstep for meas res and other background noise */
1300 d := activate(as_ignore_background(true));
1301 RSL.clear;
1302 LAPDM.clear;
1303
1304 f_establish_mo(link_id);
1305
1306 /* Send I-frame SAPI = 0, C = 1, P = 0, M = 0, L = 3, N(S) = 0, N(R) = 0 */
1307 var octetstring l3_mo := '010203'O;
1308 LAPDM.send(t_PH_DATA(0, is_sacch, ts_LAPDm_I(sapi, c_r:=cr_MO_CMD, p:=false, nr:=0, ns:=0,
1309 l3:=l3_mo)));
1310 /* Expect RR SAPI = 0, R = 1, F = 0, M = 0, L = 0, N(R) = 1 */
1311 LAPDM.receive(t_PH_DATA(0, is_sacch, tr_LAPDm_RR(sapi, c_r:=cr_MT_RSP, p:=false, nr:=1)));
1312 RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, l3_mo));
1313 /* Send SABM SAPI = 0, C = 0, P = 1, M = 0, L = 0 */
1314 LAPDM.send(t_PH_DATA(0, is_sacch, ts_LAPDm_SABM(sapi, c_r:=cr_MO_RSP, p:=true, l3:=''O)));
1315 /* Expect RSL ERR IND */
1316 RSL.receive(tr_RSL_ERROR_IND(g_chan_nr, link_id, '0C'O));
1317 /* Expect fill frame C = 0, P = 0, M = 0, L = 0 */
1318 LAPDM.receive(t_PH_DATA(0, is_sacch, tr_LAPDm_UI(0, ?, ''O)));
1319 /* Send RR command (P=1) SAPI = 0, C = 1, P = 1, M = 0, L = 0, N(R) = 0 */
1320 LAPDM.send(t_PH_DATA(0, is_sacch, ts_LAPDm_RR(sapi, c_r:=cr_MO_CMD, p:=true, nr:=0)));
1321 /* Expect RR response (F=1) SAPI = 0, R = 1, F = 1, M = 0, L = 0, N(R) = 1 */
1322 LAPDM.receive(t_PH_DATA(0, is_sacch, tr_LAPDm_RR(sapi, c_r:=cr_MT_RSP, p:=true, nr:=1)));
1323
1324 deactivate(d);
1325
1326 fp_common_fini();
1327}
1328testcase TC_sabm_incorrect_c() runs on test_CT {
1329 var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
1330 f_testmatrix_each_chan(pars, refers(f_TC_sabm_incorrect_c));
1331}
1332
Harald Welte72c81e72019-05-30 16:36:11 +02001333control {
Harald Welte72c81e72019-05-30 16:36:11 +02001334 execute(TC_sabm_ua_dcch_sapi0());
1335 execute(TC_sabm_ua_dcch_sapi0_nopayload());
1336 execute(TC_sabm_ua_dcch_sapi3());
1337 execute(TC_sabm_ua_dcch_sapi4());
1338 execute(TC_sabm_contention());
1339 execute(TC_sabm_retransmit());
Harald Welte2f2b2b72019-05-31 22:24:57 +02001340 execute(TC_sabm_retransmit_bts());
1341 execute(TC_sabm_invalid_resp());
1342 execute(TC_sabm_dm());
1343 execute(TC_establish_ign_first_sabm());
1344 execute(TC_iframe_seq_and_ack());
1345 execute(TC_iframe_timer_recovery());
Eric Wild211acc32019-06-11 19:06:38 +02001346 execute(TC_ns_seq_error());
1347 execute(TC_nr_seq_error());
1348 execute(TC_rec_invalid_frame());
Harald Welteef6fd442019-06-01 21:41:29 +02001349 execute(TC_segm_concat_dcch());
1350 execute(TC_segm_concat_sacch());
Harald Welteb2a30342019-06-02 22:13:50 +02001351 execute(TC_t200_n200());
Harald Welte7d9f6db2019-06-02 23:14:04 +02001352 execute(TC_rr_response_frame_loss());
Harald Welte44479782019-06-02 23:23:45 +02001353 execute(TC_incorrect_cr());
Harald Weltea39ac752019-06-04 21:46:07 +02001354 execute(TC_sabm_incorrect_c());
Harald Welte72c81e72019-05-30 16:36:11 +02001355}
1356
Harald Weltef6543322017-07-16 07:35:10 +02001357}