summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bsc/BSC_Tests.ttcn446
-rw-r--r--bts/BTS_Tests.ttcn544
-rw-r--r--bts/BTS_Tests_LAPDm.ttcn5
-rw-r--r--library/GSM_RR_Types.ttcn24
-rw-r--r--library/L1CTL_PortType.ttcn23
-rw-r--r--library/L3_Templates.ttcn17
-rw-r--r--library/MNCC_Emulation.ttcn2
-rw-r--r--library/MNCC_EncDec.cc130
-rw-r--r--library/MNCC_Types.ttcn94
-rw-r--r--library/Osmocom_CTRL_Functions.ttcn79
-rw-r--r--library/RLCMAC_CSN1_Templates.ttcn36
-rw-r--r--library/RLCMAC_CSN1_Types.ttcn32
-rw-r--r--library/RSL_Types.ttcn47
-rw-r--r--library/SCCP_Templates.ttcn47
-rw-r--r--library/mncc.h23
-rw-r--r--ns/NS_Tests.fr.cfg2
-rw-r--r--ns/osmo-ns.fr.cfg10
-rw-r--r--pcu/GPRS_Components.ttcn15
-rw-r--r--pcu/PCU_Tests.ttcn626
-rw-r--r--sccp/SCCP_Tests_RAW.ttcn26
20 files changed, 1985 insertions, 243 deletions
diff --git a/bsc/BSC_Tests.ttcn b/bsc/BSC_Tests.ttcn
index a65871be..4fdd0597 100644
--- a/bsc/BSC_Tests.ttcn
+++ b/bsc/BSC_Tests.ttcn
@@ -170,6 +170,16 @@ const CounterNameVals counternames_bsc_bts_handover := {
{ "interbsc_ho_in:error", 0 }
};
+const CounterNameVals counternames_bts_handover := {
+ { "incoming_intra_bsc_ho:attempted", 0 },
+ { "incoming_intra_bsc_ho:completed", 0 },
+ { "incoming_intra_bsc_ho:stopped", 0 },
+ { "incoming_intra_bsc_ho:no_channel", 0 },
+ { "incoming_intra_bsc_ho:timeout", 0 },
+ { "incoming_intra_bsc_ho:failed", 0 },
+ { "incoming_intra_bsc_ho:error", 0 }
+};
+
/* Set of all System Information received during one RSL port's startup.
* Note that some System Information may be sent on RSL, but lacking actual SI data, to indicate that the BTS should not
* broadcast that SI type. That will be reflected as 'omit' here.
@@ -756,17 +766,36 @@ private function f_ctrs_msc_expect(integer msc_nr, charstring countername, integ
/* Convenience functions for rate counters using g_ctr_bts, always also including g_ctr_bsc. */
-private function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
+private function f_ctrs_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, counternames);
+}
+
+function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
+ f_ctrs_bts_init(bts_count, counternames);
log("initial bts rate counters: ", g_ctr_bts);
f_ctrs_bsc_init(counternames);
}
-private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
+private function f_ctrs_bsc_and_bts_handover_init(integer bts_count := NUM_BTS) runs on test_CT {
+ var CounterNameVals bts_names := counternames_bsc_bts_handover & counternames_bts_handover;
+ g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, bts_names);
+ log("initial bts rate counters: ", g_ctr_bts);
+ f_ctrs_bsc_init(counternames_bsc_bts_handover);
+}
+
+private function f_ctrs_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
f_counter_name_vals_list_add(g_ctr_bts, bts_nr, countername, val);
+}
+
+private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
+ f_ctrs_bts_add(bts_nr, countername, val);
f_ctrs_bsc_add(countername, val);
}
+function f_ctrs_bts_verify() runs on test_CT {
+ f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
+}
+
/* f_ctrs_bsc_and_bts_init();
* f_do_thing(on_bts := 0);
* f_do_thing(on_bts := 0);
@@ -776,7 +805,7 @@ private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername,
* f_ctrs_bsc_and_bts_verify();
*/
private function f_ctrs_bsc_and_bts_verify() runs on test_CT {
- f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
+ f_ctrs_bts_verify();
f_ctrs_bsc_verify();
}
@@ -1400,7 +1429,7 @@ testcase TC_chan_exhaustion() runs on test_CT {
chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
- /* GSM 04.08 Table 9.9a:
+ /* GSM 44.018 Table 9.1.8.2:
* RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
* With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS; i := i+1) {
@@ -1642,6 +1671,8 @@ type record DchanTuple {
RslChannelNr rsl_chan_nr
}
+type record of DchanTuple DchanTuples;
+
/* Send CHAN RQD and wait for allocation; acknowledge it */
private function f_chreq_act_ack(OCT1 ra := '23'O, GsmFrameNumber fn := 23)
runs on test_CT return RslChannelNr {
@@ -1672,6 +1703,37 @@ runs on test_CT return DchanTuple {
return dt;
}
+/* Like f_est_dchan(), but for the first lchan of a dynamic timeslot: first ACK the deactivation of PDCH. */
+function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3)
+runs on test_CT return DchanTuple {
+ var BSSAP_N_CONNECT_ind rx_c_ind;
+ var DchanTuple dt;
+
+ /* Send CHAN RQD */
+ var RSL_Message rx_rsl;
+ f_ipa_tx(0, ts_RSL_CHAN_RQD(ra, fn));
+
+ /* The dyn TS first deactivates PDCH */
+ rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), T3101_MAX);
+ dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
+ f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
+
+ rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+ dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
+
+ /* Now activates the signalling channel */
+ f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10));
+ rx_rsl := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
+
+ f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
+
+ BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
+ dt.sccp_conn_id := rx_c_ind.connectionId;
+ BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
+
+ return dt;
+}
+
/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
private function f_exp_chan_rel_and_clear(DchanTuple dt, integer bts_nr := 0) runs on test_CT {
var RSL_Message rx_rsl;
@@ -5123,7 +5185,7 @@ testcase TC_ho_int() runs on test_CT {
pars.expect_tsc := BTS_TSC[0];
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
vc_conn.done;
@@ -5136,6 +5198,8 @@ testcase TC_ho_int() runs on test_CT {
f_ctrs_bsc_and_bts_add(0, "handover:completed");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
f_ctrs_bsc_and_bts_verify();
f_shutdown_helper();
}
@@ -5149,7 +5213,7 @@ function f_tc_ho_int_a5(OCT1 encr_alg, charstring enc_a5 := "0 1 3") runs on tes
f_vty_encryption_a5(enc_a5);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
vc_conn.done;
@@ -5162,6 +5226,8 @@ function f_tc_ho_int_a5(OCT1 encr_alg, charstring enc_a5 := "0 1 3") runs on tes
f_ctrs_bsc_and_bts_add(0, "handover:completed");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
f_ctrs_bsc_and_bts_verify();
f_vty_encryption_a5_reset();
f_shutdown_helper();
@@ -5269,7 +5335,7 @@ testcase TC_ho_int_radio_link_failure() runs on test_CT {
f_init(2, true);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
vc_conn.done;
@@ -5282,6 +5348,8 @@ testcase TC_ho_int_radio_link_failure() runs on test_CT {
f_ctrs_bsc_and_bts_add(0, "handover:stopped");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
f_ctrs_bsc_and_bts_verify();
f_shutdown_helper();
}
@@ -5389,7 +5457,7 @@ testcase TC_ho_out_of_this_bsc() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
vc_conn.done;
@@ -5472,7 +5540,7 @@ testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
vc_conn.done;
@@ -5553,7 +5621,7 @@ testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
vc_conn.done;
@@ -5653,7 +5721,7 @@ testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
vc_conn.done;
@@ -5770,7 +5838,7 @@ function f_tc_ho_into_this_bsc_main(TestHdlrParams pars) runs on test_CT {
f_init(1, true);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
@@ -5872,7 +5940,7 @@ private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_ret
}
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
pars.last_used_eutran_plmn := '323454'O;
pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
@@ -5979,7 +6047,7 @@ testcase TC_ho_in_fail_msc_clears() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
@@ -6069,7 +6137,7 @@ testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
@@ -6158,7 +6226,7 @@ testcase TC_ho_in_fail_no_detect() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
@@ -6239,7 +6307,7 @@ testcase TC_ho_in_fail_no_detect2() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
@@ -6449,7 +6517,7 @@ testcase TC_ho_neighbor_config_1() runs on test_CT {
var MSC_ConnHdlr vc_conn;
f_init(3, true, guard_timeout := 60.0);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
vc_conn.done;
@@ -6464,6 +6532,8 @@ testcase TC_ho_neighbor_config_1() runs on test_CT {
f_ctrs_bsc_and_bts_add(0, "handover:failed");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
/* 1.b */
f_ctrs_bsc_and_bts_add(0, "handover:attempted");
@@ -6478,6 +6548,8 @@ testcase TC_ho_neighbor_config_1() runs on test_CT {
f_ctrs_bsc_and_bts_add(0, "handover:failed");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
f_ctrs_bsc_and_bts_verify();
f_shutdown_helper();
@@ -6509,7 +6581,7 @@ testcase TC_ho_neighbor_config_2() runs on test_CT {
var MSC_ConnHdlr vc_conn;
f_init(3, true, guard_timeout := 50.0);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
vc_conn.done;
@@ -6524,6 +6596,8 @@ testcase TC_ho_neighbor_config_2() runs on test_CT {
f_ctrs_bsc_and_bts_add(0, "handover:failed");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
/* 2.b */
f_ctrs_bsc_and_bts_add(0, "handover:attempted");
@@ -6558,7 +6632,7 @@ testcase TC_ho_neighbor_config_3() runs on test_CT {
var MSC_ConnHdlr vc_conn;
f_init(3, true, guard_timeout := 50.0);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
vc_conn.done;
@@ -6577,6 +6651,8 @@ testcase TC_ho_neighbor_config_3() runs on test_CT {
f_ctrs_bsc_and_bts_add(0, "handover:failed");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
+ f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
f_ctrs_bsc_and_bts_verify();
f_shutdown_helper();
@@ -6610,7 +6686,7 @@ testcase TC_ho_neighbor_config_4() runs on test_CT {
var MSC_ConnHdlr vc_conn;
f_init(3, true, guard_timeout := 50.0);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
vc_conn.done;
@@ -6660,7 +6736,7 @@ testcase TC_ho_neighbor_config_5() runs on test_CT {
var MSC_ConnHdlr vc_conn;
f_init(3, true);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
vc_conn.done;
@@ -6703,7 +6779,7 @@ testcase TC_ho_neighbor_config_6() runs on test_CT {
var MSC_ConnHdlr vc_conn;
f_init(3, true);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
vc_conn.done;
@@ -6747,7 +6823,7 @@ testcase TC_ho_neighbor_config_7() runs on test_CT {
var MSC_ConnHdlr vc_conn;
f_init(3, true, guard_timeout := 50.0);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
vc_conn.done;
@@ -6762,6 +6838,8 @@ testcase TC_ho_neighbor_config_7() runs on test_CT {
f_ctrs_bsc_and_bts_add(0, "handover:failed");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
+ f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
/* 7.b */
/* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
@@ -7202,7 +7280,7 @@ testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
/* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
* on CCCH+SDCCH4+CBCH) */
var integer i;
- for (i := 0; i < 3; i := i + 1) {
+ for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
dt := f_est_dchan('23'O, i, '00010203040506'O);
}
@@ -7241,6 +7319,53 @@ testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
f_shutdown_helper();
}
+/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
+testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
+ var ASP_RSL_Unitdata rsl_ud;
+ var integer i;
+ var integer chreq_total, chreq_nochan;
+
+ f_init_vty();
+ for (i := 1; i < 8; i := i + 1) {
+ if (i == 2) {
+ f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
+ } else {
+ f_ts_set_chcomb(0, 0, i, "PDCH");
+ }
+ }
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
+ f_init(1);
+
+ /* The dyn TS want to activate PDCH mode, ACK that. */
+ var RslChannelNr chan_nr;
+ chan_nr := valueof(t_RslChanNr_PDCH(2));
+ f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr, ?));
+ f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
+
+ f_sleep(1.0);
+
+ /* Exhaust all dedicated SDCCH lchans.
+ /* GSM 44.018 Table 9.1.8.2:
+ * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
+ */
+ for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
+ f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
+ }
+
+ /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
+ f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
+ /* Also occupy the seven other SDCCH of the dyn TS */
+ for (i := 0; i < 7; i := i+1) {
+ f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
+ }
+
+ /* clean up config */
+ f_ts_reset_chcomb(0);
+
+ f_shutdown_helper();
+}
+
/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
SDCCH8 would end up in having no free TCH, then BSC should decide to activate
it as TCH directly instead. SYS#5309. */
@@ -7279,7 +7404,7 @@ testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
/* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
* on CCCH+SDCCH4+CBCH) */
var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
- for (i := 0; i < 3; i := i + 1) {
+ for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
dt := f_est_dchan(ra, i, '00010203040506'O);
}
@@ -7349,7 +7474,7 @@ testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
/* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
* on CCCH+SDCCH4+CBCH) */
var integer i;
- for (i := 0; i < 3; i := i + 1) {
+ for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
dt := f_est_dchan('23'O, i, '00010203040506'O);
}
@@ -8361,7 +8486,7 @@ private type record FHParamsTs {
/* Hopping parameters per a transceiver */
private type record FHParamsTrx {
- GsmArfcn arfcn,
+ GsmBandArfcn arfcn,
FHParamsTs ts[8]
};
@@ -8370,8 +8495,10 @@ private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
runs on test_CT return FHParamsTrx {
var FHParamsTrx fhp;
- /* Generate a random ARFCN, including ARFCN 0 */
- fhp.arfcn := f_rnd_int(3);
+ /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
+ * fall in the GSM900 band. */
+ fhp.arfcn.arfcn := f_rnd_int(3);
+ fhp.arfcn.pcs := false;
for (var integer tn := 0; tn < 8; tn := tn + 1) {
if (not match(tn, tr_tn)) {
@@ -8410,7 +8537,7 @@ private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDe
tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
} else {
- tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn);
+ tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
}
if (not match(cd, tr_cd)) {
@@ -8455,7 +8582,7 @@ return template MobileAllocationLV {
}
/* Take ARFCN of the TRX itself into account */
- full_mask[fhp.arfcn] := '1'B;
+ full_mask[fhp.arfcn.arfcn] := '1'B;
/* Compose a bit-mask for the given timeslot number */
for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
@@ -8492,15 +8619,41 @@ return template MobileAllocationLV {
return { len := ma_mask_len, ma := ma_mask };
}
+/* Configure the appropriate band for a given arfcn, exc */
+private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
+{
+ var charstring band;
+ var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
+
+ select (arfcn_) {
+ case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
+ case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
+ case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
+ case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
+ case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
+ case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
+ case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
+ case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
+ case else { return; }
+ }
+
+ f_vty_enter_cfg_bts(BSCVTY, bts_nr);
+ f_vty_transceive(BSCVTY, "band " & band);
+ f_vty_transceive(BSCVTY, "end");
+}
+
/* Configure the hopping parameters in accordance with the given record */
private function f_TC_fh_params_set(in FHParamsTrx fhp,
uint8_t bts_nr := 0,
uint8_t trx_nr := 0)
runs on test_CT {
+
+ f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
+
/* Enter the configuration node for the given BTS/TRX numbers */
f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
- f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn));
+ f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
@@ -8531,12 +8684,15 @@ runs on test_CT {
private function f_TC_fh_params_unset(in FHParamsTrx fhp,
uint8_t bts_nr := 0,
uint8_t trx_nr := 0,
- GsmArfcn arfcn := 871)
+ GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
runs on test_CT {
+
+ f_TC_set_band_by_arfcn(bts_nr, arfcn);
+
/* Enter the configuration node for the given BTS/TRX numbers */
f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
- f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn));
+ f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
@@ -9641,7 +9797,7 @@ testcase TC_reassignment_fr() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
- f_ctrs_bsc_and_bts_init();
+ f_ctrs_bsc_and_bts_handover_init();
pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
@@ -10198,15 +10354,66 @@ testcase TC_ctrl_trx_rf_locked() runs on test_CT {
f_shutdown_helper();
}
+const CounterNameVals counternames_cm_serv_rej := {
+ { "cm_serv_rej", 0 },
+ { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
+ { "cm_serv_rej:illegal_ms", 0 },
+ { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
+ { "cm_serv_rej:imei_not_accepted", 0 },
+ { "cm_serv_rej:illegal_me", 0 },
+ { "cm_serv_rej:plmn_not_allowed", 0 },
+ { "cm_serv_rej:loc_not_allowed", 0 },
+ { "cm_serv_rej:roaming_not_allowed", 0 },
+ { "cm_serv_rej:network_failure", 0 },
+ { "cm_serv_rej:synch_failure", 0 },
+ { "cm_serv_rej:congestion", 0 },
+ { "cm_serv_rej:srv_opt_not_supported", 0 },
+ { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
+ { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
+ { "cm_serv_rej:call_can_not_be_identified", 0 },
+ { "cm_serv_rej:incorrect_message", 0 },
+ { "cm_serv_rej:invalid_mandantory_inf", 0 },
+ { "cm_serv_rej:msg_type_not_implemented", 0 },
+ { "cm_serv_rej:msg_type_not_compatible", 0 },
+ { "cm_serv_rej:inf_eleme_not_implemented", 0 },
+ { "cm_serv_rej:condtional_ie_error", 0 },
+ { "cm_serv_rej:msg_not_compatible", 0 },
+ { "cm_serv_rej:protocol_error", 0 },
+ { "cm_serv_rej:retry_in_new_cell", 0 }
+};
+
+private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
+{
+ f_create_chan_and_exp();
+ BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
+ f_sleep(3.0);
+}
+testcase TC_cm_serv_rej() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ f_ctrs_bts_init(1, counternames_cm_serv_rej);
+
+ vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
+ vc_conn.done;
+
+ f_ctrs_bts_add(0, "cm_serv_rej", 1);
+ f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
+ f_ctrs_bts_verify();
+
+ f_shutdown_helper();
+}
+
/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
* Activ Ack (SYS#5627). */
private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
var PDU_BSSAP ass_cmd := f_gen_ass_req();
- if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
- ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
- }
- ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
- f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
+
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
var BSSMAP_FIELD_CodecType codecType;
codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
@@ -10280,13 +10487,162 @@ testcase TC_lost_sdcch_during_assignment() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
- pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
vc_conn.done;
f_shutdown_helper();
}
+const CounterNameVals counternames_bsc_bts_all_available_allocated := {
+ { "all_allocated:sdcch", 0 },
+ { "all_allocated:static_sdcch", 0 },
+ { "all_allocated:tch", 0 },
+ { "all_allocated:static_tch", 0 }
+}
+
+private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
+{
+ /* Make sure counters settle first */
+ f_sleep(1.0);
+
+ /* Take a baseline of counters */
+ f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
+
+ /* Elapse some time so that we see changes in counters, hopefully where expected */
+ f_sleep(2.0);
+
+ /* Get new counters */
+ var charstring_list all_changed := {};
+ all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
+ all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
+
+ /* Compare with expectations */
+ var charstring_list all_expect_changed := {};
+ for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
+ all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
+ }
+ f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
+}
+
+testcase TC_ratectr_all_available_allocated() runs on test_CT {
+ var ASP_RSL_Unitdata rsl_ud;
+ var integer i;
+ var integer chreq_total, chreq_nochan;
+
+ f_init(1);
+ f_sleep(1.0);
+
+ /* Exhaust all dedicated SDCCH lchans.
+ /* GSM 44.018 Table 9.1.8.2:
+ * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
+ */
+ for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
+ f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
+ }
+
+ /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
+ * level.
+ * All SDCCH are now occupied. */
+ f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
+
+ /* Also fill up all remaining (TCH) channels */
+ for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
+ f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
+ }
+
+ /* All TCH are now also occupied */
+ f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
+ "all_allocated:tch", "all_allocated:static_tch"});
+
+ f_shutdown_helper();
+}
+
+testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
+ var ASP_RSL_Unitdata rsl_ud;
+ var integer i;
+ var integer chreq_total, chreq_nochan;
+
+ f_init_vty();
+ f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+ /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
+
+ f_init(1, guard_timeout := 60.0);
+ f_sleep(1.0);
+
+ /* The dyn TS wants to activate PDCH mode, ACK that. */
+ var RslChannelNr chan_nr;
+ chan_nr := valueof(t_RslChanNr_PDCH(2));
+ f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr, ?));
+ f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
+
+ /* Exhaust all dedicated SDCCH lchans.
+ /* GSM 44.018 Table 9.1.8.2:
+ * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
+ */
+ for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
+ f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
+ }
+
+ /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
+ * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
+ f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
+
+ /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
+ * Will release them later, so remember all the DchanTuples. */
+ var DchanTuples dyn_sddch := {};
+ dyn_sddch := dyn_sddch & { f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
+
+ /* Also occupy the seven other SDCCH of the dyn TS */
+ for (i := 0; i < 7; i := i+1) {
+ dyn_sddch := dyn_sddch & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O) };
+ }
+
+ /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
+ f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
+
+ /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
+ for (i := 0; i < 5; i := i+1) {
+ f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, '00010203040506'O);
+ }
+
+ /* All TCH lchans are now also occupied, both static and dynamic */
+ f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
+ "all_allocated:tch", "all_allocated:static_tch"});
+
+ /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
+ * incrementing. */
+ var BssmapCause cause := 0;
+ var DchanTuple dt := dyn_sddch[0];
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
+ f_exp_chan_rel_and_clear(dt, 0);
+
+ /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
+ * count as occupied, so those still both increment. */
+ f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
+ "all_allocated:tch", "all_allocated:static_tch"});
+
+ /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
+ for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
+ dt := dyn_sddch[i];
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
+ f_exp_chan_rel_and_clear(dt, 0);
+ }
+
+ /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
+ chan_nr := valueof(t_RslChanNr_PDCH(2));
+ f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr, ?));
+ f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
+
+ /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
+ f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
+
+ /* clean up config */
+ f_ts_reset_chcomb(0);
+
+ f_shutdown_helper();
+}
+
control {
/* CTRL interface testing */
execute( TC_ctrl_msc_connection_status() );
@@ -10517,6 +10873,7 @@ control {
execute( TC_dyn_pdch_osmo_act_nack() );
if (mp_enable_dyn_sdcch8_test) {
execute( TC_dyn_ts_sdcch8_act_deact() );
+ execute( TC_dyn_ts_sdcch8_all_subslots_used() );
execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
execute( TC_dyn_ts_sdcch8_act_nack() );
}
@@ -10595,6 +10952,11 @@ control {
execute( TC_ctrl_trx_rf_locked() );
+ execute( TC_ratectr_all_available_allocated() );
+ execute( TC_ratectr_all_available_allocated_dyn() );
+
+ execute( TC_cm_serv_rej() );
+
execute( TC_lost_sdcch_during_assignment() );
}
diff --git a/bts/BTS_Tests.ttcn b/bts/BTS_Tests.ttcn
index 03519d94..27b004a8 100644
--- a/bts/BTS_Tests.ttcn
+++ b/bts/BTS_Tests.ttcn
@@ -300,6 +300,7 @@ friend type record FreqHopPars {
};
type record ConnHdlrPars {
+ uint8_t trx_nr,
RslChannelNr chan_nr,
RSL_IE_ChannelMode chan_mode,
float t_guard,
@@ -316,7 +317,8 @@ type record ConnHdlrPars {
/* Test-specific parameters */
friend type union TestSpecUnion {
- RllTestCase rll
+ RllTestCase rll,
+ TopTestCase top
}
private template (value) RachControlParameters ts_RachCtrl_default := {
@@ -733,7 +735,7 @@ runs on ConnHdlr {
g_Tguard.start(pars.t_guard);
activate(as_Tguard());
- f_rslem_register(0, pars.chan_nr);
+ f_rslem_register(pars.trx_nr, pars.chan_nr);
/* call the user-supplied test case function */
fn.apply(id);
@@ -772,6 +774,43 @@ runs on ConnHdlr {
var RSL_Message rx := f_rsl_transceive_ret(tx, exp_rx, id, ignore_other);
}
+/* Send the given measurement results to the IUT over the Um interface,
+ * wait for the IUT to receive then and forward over the A-bis/RSL interface. */
+friend function f_transceive_meas_rep(template (value) MeasurementResults meas_res)
+runs on ConnHdlr {
+ var template (value) SacchL1Header l1h;
+ var octetstring l2, l3;
+ timer T;
+
+ /* RR Measurement Report to be sent */
+ var GsmRrL3Message meas_rep := {
+ header := valueof(t_RrL3Header(MEASUREMENT_REPORT)),
+ payload := { meas_rep := { meas_res := valueof(meas_res) } }
+ };
+
+ /* TITAN has weird (and often unusable) padding model, so we pad here manaully */
+ l3 := f_pad_oct(enc_GsmRrL3Message(meas_rep), 18, '00'O);
+ l2 := f_pad_oct(enc_LapdmFrameAB(valueof(ts_LAPDm_AB(0, meas_rep))), 21, '00'O);
+ l1h := ts_SacchL1Header(g_pars.l1_pars.ms_power_level, false,
+ g_pars.l1_pars.ms_actual_ta);
+
+ /* Send RR Measurement Report over the Um interface */
+ L1CTL.send(ts_L1CTL_DATA_REQ_SACCH(g_chan_nr, ts_RslLinkID_SACCH(0), l1h, l2));
+
+ /* Expect MEASurement RESult on the A-bis/RSL interface */
+ T.start(2.0);
+ alt {
+ [] RSL.receive(tr_RSL_MEAS_RES_OSMO(g_chan_nr, l3_info := l3)) {
+ setverdict(pass);
+ }
+ [] RSL.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for RSL MEASurement RESult");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+}
+
friend function f_rsl_chan_act(RSL_IE_ChannelMode mode,
boolean encr_enable := false,
RSL_IE_List more_ies := {},
@@ -797,7 +836,8 @@ friend function f_rsl_chan_deact() runs on ConnHdlr {
friend template ConnHdlrPars t_Pars(template RslChannelNr chan_nr,
template RSL_IE_ChannelMode chan_mode,
template (omit) TestSpecUnion spec := omit,
- float t_guard := 20.0) := {
+ uint8_t trx_nr := 0, float t_guard := 20.0) := {
+ trx_nr := trx_nr,
chan_nr := valueof(chan_nr),
chan_mode := valueof(chan_mode),
t_guard := t_guard,
@@ -2220,8 +2260,9 @@ private function f_rach_req_wait_chan_rqd(integer ra) runs on ConnHdlr return Gs
/* Tune to a dedicated channel: L1CTL only */
private function f_l1ctl_est_dchan(L1CTL_PT pt, ConnHdlrPars pars) {
if (not pars.fhp.enabled) {
+ var TrxParsItem trx_pars := mp_trx_pars[pars.trx_nr];
pt.send(ts_L1CTL_DM_EST_REQ_H0(pars.chan_nr, pars.tsc,
- mp_trx_pars[0].arfcn));
+ trx_pars.arfcn));
} else {
pt.send(ts_L1CTL_DM_EST_REQ_H1(pars.chan_nr, pars.tsc,
pars.fhp.maio_hsn.hsn,
@@ -2232,13 +2273,7 @@ private function f_l1ctl_est_dchan(L1CTL_PT pt, ConnHdlrPars pars) {
/* Establish dedicated channel: L1CTL + RSL side */
private function f_est_dchan(boolean encr_enable := false, RSL_IE_List more_ies := {}) runs on ConnHdlr {
- var GsmFrameNumber fn;
- var ImmediateAssignment imm_ass;
var ChannelDescription ch_desc;
- var integer ra := 23;
-
- /* Send RACH request and wait for ChanReq */
- fn := f_rach_req_wait_chan_rqd(ra);
/* Activate channel on BTS side */
f_rsl_chan_act(g_pars.chan_mode, encr_enable, more_ies);
@@ -2247,24 +2282,13 @@ private function f_est_dchan(boolean encr_enable := false, RSL_IE_List more_ies
if (g_pars.fhp.enabled) {
ch_desc := valueof(ts_ChanDescH1(g_pars.chan_nr, g_pars.fhp.maio_hsn, g_pars.tsc));
} else {
- ch_desc := valueof(ts_ChanDescH0(g_pars.chan_nr, mp_trx_pars[0].arfcn, g_pars.tsc));
- }
-
- /* Send IMM.ASS via CCHAN */
- var GsmRrMessage rr_msg := valueof(ts_IMM_ASS(ra, fn, 0, ch_desc, g_pars.fhp.ma_map));
- RSL.send(ts_RSL_IMM_ASSIGN(enc_GsmRrMessage(rr_msg)));
-
- /* receive IMM.ASS on MS side */
- var ImmediateAssignment ia_um;
- ia_um := f_L1CTL_WAIT_IMM_ASS(L1CTL, ra, fn);
-
- /* Make sure that IMM.ASS contains hopping parameters (if enabled) */
- if (ch_desc.h != ia_um.chan_desc.h) {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Hopping parameters mismatch");
+ var TrxParsItem trx_pars := mp_trx_pars[g_pars.trx_nr];
+ ch_desc := valueof(ts_ChanDescH0(g_pars.chan_nr, trx_pars.arfcn, g_pars.tsc));
}
/* enable dedicated mode */
- f_L1CTL_DM_EST_REQ_IA(L1CTL, ia_um, ma := g_pars.fhp.ma);
+ f_l1ctl_est_dchan(L1CTL, g_pars);
+
/* enable encryption, if requested */
if (encr_enable) {
var uint8_t alg_id := f_alg_id_to_l1ctl(g_pars.encr.alg_id);
@@ -2687,26 +2711,28 @@ private function f_TC_rsl_bs_pwr_static_power_control(charstring id) runs on Con
testcase TC_rsl_bs_pwr_static_ass() runs on test_CT {
var ConnHdlr vc_conn;
var ConnHdlrPars pars;
+
f_init();
- for (var integer tn := 1; tn <= 4; tn := tn+1) {
- pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
- vc_conn := f_start_handler(refers(f_TC_rsl_bs_pwr_static_ass), pars,
- pcu_comp := false, trxc_comp := true);
- vc_conn.done;
- }
+
+ pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN, trx_nr := 1));
+ vc_conn := f_start_handler(refers(f_TC_rsl_bs_pwr_static_ass), pars,
+ pcu_comp := false, trxc_comp := true);
+ vc_conn.done;
+
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
testcase TC_rsl_bs_pwr_static_power_control() runs on test_CT {
var ConnHdlr vc_conn;
var ConnHdlrPars pars;
+
f_init();
- for (var integer tn := 1; tn <= 4; tn := tn+1) {
- pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
- vc_conn := f_start_handler(refers(f_TC_rsl_bs_pwr_static_power_control), pars,
- pcu_comp := false, trxc_comp := true);
- vc_conn.done;
- }
+
+ pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN, trx_nr := 1));
+ vc_conn := f_start_handler(refers(f_TC_rsl_bs_pwr_static_power_control), pars,
+ pcu_comp := false, trxc_comp := true);
+ vc_conn.done;
+
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
@@ -3310,6 +3336,86 @@ testcase TC_meas_res_sign_tchh_toa256() runs on test_CT {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
+/* Make sure that we always get RSL MEASurement RESult messages regardless
+ * of what is sent on SACCH: (RR) Measurement Report or SAPI=3 data (SMS). */
+private function f_TC_meas_res_sapi3(charstring id) runs on ConnHdlr {
+ timer Texec := 8.0;
+ timer Timpf := 2.0;
+ timer Tmr;
+
+ f_l1_tune(L1CTL);
+ RSL.clear;
+
+ f_est_dchan();
+ L1CTL.clear;
+
+ /* Establish the main SAPI=0 link on DCCH first */
+ f_tx_lapdm(ts_LAPDm_SABM(0, cr_MO_CMD, true, ''O), ts_RslLinkID_DCCH(0));
+
+ /* Give more time for the first RSL MEASurement RESult */
+ Tmr.start(0.480 * 2.0);
+ Texec.start; /* EXECution timer */
+ Timpf.start; /* IMPFung timer */
+
+ alt {
+ /* We expect RSL MEASurement RESult messages every ~480ms (plus some guard) */
+ [] RSL.receive(tr_RSL_MEAS_RES(g_pars.chan_nr)) {
+ /* Reschedule the MEAS RES timer */
+ Tmr.start(0.480 + 0.120);
+ repeat;
+ }
+ [] RSL.receive { repeat; }
+ [] Tmr.timeout {
+ setverdict(fail, "Timeout waiting for RSL MEAS RES");
+ }
+ /* Inject some SAPI=3 traffic on SACCH every 2 seconds */
+ [] Timpf.timeout {
+ f_tx_lapdm(ts_LAPDm_SABM(3, cr_MO_CMD, true, ''O), ts_RslLinkID_SACCH(3));
+ log("Injected SAPI=3 traffic on SACCH");
+ Timpf.start;
+ repeat;
+ }
+ /* We're good if survived so far */
+ [] Texec.timeout {
+ setverdict(pass);
+ }
+ }
+
+ f_rsl_chan_deact();
+ f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+ f_rslem_unregister(0, g_chan_nr);
+}
+testcase TC_meas_res_speech_tchf_sapi3() runs on test_CT {
+ var template RSL_IE_ChannelMode ch_mode;
+ var template ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ ch_mode := ts_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1);
+ pars := t_Pars(t_RslChanNr_Bm(1), ch_mode);
+
+ vc_conn := f_start_handler(refers(f_TC_meas_res_sapi3), valueof(pars));
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+testcase TC_meas_res_speech_tchh_sapi3() runs on test_CT {
+ var template RSL_IE_ChannelMode ch_mode;
+ var template ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ ch_mode := ts_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1);
+ pars := t_Pars(t_RslChanNr_Lm(5, 0), ch_mode);
+
+ vc_conn := f_start_handler(refers(f_TC_meas_res_sapi3), valueof(pars));
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
/* establish DChan, and send MS POWER CONTROL messages via RSL, verify that
* the BTS is forwarding those values to the MS via the SACCH L1 header. */
private function f_tc_rsl_ms_pwr_ctrl(charstring id) runs on ConnHdlr {
@@ -5999,9 +6105,15 @@ testcase TC_pcu_interf_ind() runs on test_CT {
var template PCUIF_Message tr_interf_ind;
var template PCUIF_interf ts_interf;
var integer interf_ind_num := 0;
+ var boolean first := true;
var PCUIF_send_data sd;
timer T;
+ /* Set the averaging/reporting period to 480ms */
+ f_init_vty_bsc();
+ f_vty_cfg_bts(BSCVTY, 0, { "interference-meas avg-period 1" });
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
f_init_with_pcuif();
f_TC_pcu_act_req(0, 0, 7, true);
@@ -6018,16 +6130,17 @@ testcase TC_pcu_interf_ind() runs on test_CT {
interf := ts_interf
);
- /* 4 SACCH periods => 4 reports (plus some guard time) */
- var float Tval := int2float(4 * 480) / 1000.0 + 0.5;
-
- /* Let it some time to stabilize */
- f_sleep(0.5);
- PCU.clear;
-
- T.start(Tval);
+ T.start(0.480 * 1.5);
alt {
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_interf_ind)) -> value sd {
+ /* The first interference report may contain unreliable values, so we ignore it */
+ [first] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_INTERF_IND(0, 0))) {
+ /* 4 SACCH periods => 4 reports (plus some guard time) */
+ T.start(0.480 * 4.0 + 0.480 / 2.0);
+ first := false;
+ repeat;
+ }
+ /* Subsequent interference reports shall match our expectations */
+ [not first] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_interf_ind)) -> value sd {
/* Check TDMA frame number period */
if (sd.data.u.interf_ind.fn mod 104 != 0) {
setverdict(fail, "Odd TDMA frame number := ",
@@ -6037,7 +6150,7 @@ testcase TC_pcu_interf_ind() runs on test_CT {
if (interf_ind_num < 4)
{ repeat; }
}
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_INTERF_IND(0, 0))) -> value sd {
+ [not first] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_INTERF_IND(0, 0))) -> value sd {
setverdict(fail, "Received unexpected interference report: ", sd.data);
}
[] PCU.receive { repeat; }
@@ -6046,6 +6159,9 @@ testcase TC_pcu_interf_ind() runs on test_CT {
}
}
+ /* Reset the averaging/reporting period back to default */
+ f_vty_cfg_bts(BSCVTY, 0, { "interference-meas avg-period 6" });
+
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
@@ -7829,6 +7945,331 @@ testcase TC_early_immediate_assignment() runs on test_CT {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
+private function f_TC_est_dchan(charstring id) runs on ConnHdlr {
+ var integer ra := oct2int(f_rnd_ra_cs());
+ var ChannelDescription ch_desc;
+
+ /* Tune the MS to BCCH */
+ f_l1_tune(L1CTL);
+
+ /* Send RACH request and wait for ChanReq */
+ var GsmFrameNumber fn := f_rach_req_wait_chan_rqd(ra);
+
+ /* Activate channel on the BTS side */
+ f_rsl_chan_act(g_pars.chan_mode);
+
+ /* Craft channel description (with or without frequency hopping parameters) */
+ if (g_pars.fhp.enabled) {
+ ch_desc := valueof(ts_ChanDescH1(g_pars.chan_nr, g_pars.fhp.maio_hsn, g_pars.tsc));
+ } else {
+ ch_desc := valueof(ts_ChanDescH0(g_pars.chan_nr, mp_trx_pars[0].arfcn, g_pars.tsc));
+ }
+
+ /* Send IMM.ASS via CCHAN */
+ var GsmRrMessage rr_msg := valueof(ts_IMM_ASS(ra, fn, 0, ch_desc, g_pars.fhp.ma_map));
+ RSL.send(ts_RSL_IMM_ASSIGN(enc_GsmRrMessage(rr_msg)));
+
+ /* Receive IMM.ASS on the MS side */
+ var ImmediateAssignment imm_ass := f_L1CTL_WAIT_IMM_ASS(L1CTL, ra, fn);
+
+ /* Match the Channel Description IE in received IMM.ASS */
+ if (not match(imm_ass.chan_desc, ch_desc)) {
+ setverdict(fail, "Channel Description IE does not match");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+
+ /* Tune the MS to a dedicated channel indicated in the IMM.ASS */
+ f_L1CTL_DM_EST_REQ_IA(L1CTL, imm_ass, g_pars.fhp.ma);
+
+ /* Expect SACCH frames on Downlink */
+ L1CTL.clear;
+ f_exp_sacch(true);
+
+ /* We're done, deactivate and release */
+ f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+ f_rsl_chan_deact();
+}
+testcase TC_est_dchan() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ for (var integer i := 0; i < sizeof(g_AllChannels); i := i + 1) {
+ pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
+ vc_conn := f_start_handler(refers(f_TC_est_dchan), pars);
+ vc_conn.done;
+ }
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+private type record TopTestCase {
+ RSL_IE_BS_Power bs_power,
+ RSL_IE_OSMO_TopAcchCap top_cap,
+ record of TopTestStep steps
+};
+private type record TopTestStep {
+ MeasurementResults meas_res optional,
+ GsmRxLev overpower_sacch,
+ GsmRxLev overpower_facch
+};
+
+private function f_rxlev_match(template (present) RslLinkId link_id,
+ template (present) GsmRxLev rxlev)
+runs on ConnHdlr {
+ var L1ctlDlMessage dl := f_L1CTL_rx_data(L1CTL, g_chan_nr, link_id);
+ if (not match(dl.dl_info.rx_level, rxlev)) {
+ setverdict(fail, "RxLev(", link_id, ") := ", dl.dl_info.rx_level,
+ " does not match expected RxLev := ", rxlev);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+}
+
+private function f_TC_acch_overpower(charstring id) runs on ConnHdlr {
+ var TopTestCase tc := g_pars.spec.top;
+ var GsmRxLev rxlev_dcch;
+ var L1ctlDlMessage dl;
+
+ /* Wait for Pau ramping to complete */
+ f_sleep(6.0);
+
+ f_l1_tune(L1CTL);
+ L1CTL.clear;
+ RSL.clear;
+
+ /* Measure RxLev(BCCH), calculate RxLev(DCCH) */
+ dl := f_L1CTL_rx_data(L1CTL, t_RslChanNr_BCCH(0));
+ rxlev_dcch := dl.dl_info.rx_level - (tc.bs_power.power_level * 2);
+
+ log("RxLev(BCCH) := ", dl.dl_info.rx_level);
+ log("Expected RxLev(DCCH) := ", rxlev_dcch);
+
+ /* Additional IEs for the CHANnel ACTIVation message */
+ var template (value) RSL_IE_List ies := {
+ /* Employ BS power control in static mode */
+ t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{
+ bs_power := tc.bs_power
+ }),
+ /* Indicate the given Temporary Overpower capability */
+ t_RSL_IE(RSL_IE_OSMO_TOP_ACCH_CAP, RSL_IE_Body:{
+ top_acch_cap := tc.top_cap
+ })
+ };
+
+ /* Establish a dedicated channel */
+ f_est_dchan(more_ies := valueof(ies));
+
+ /* Give it some time to stabilize */
+ f_sleep(0.480 * 2.0);
+ L1CTL.clear;
+ RSL.clear;
+
+ for (var integer i := 0; i < lengthof(tc.steps); i := i + 1) {
+ var TopTestStep step := tc.steps[i];
+ var GsmRxLev rxlev_facch := rxlev_dcch + step.overpower_facch;
+ var GsmRxLev rxlev_sacch := rxlev_dcch + step.overpower_sacch;
+
+ log("Executing step[", i, "] := ", step);
+
+ /* Send RR Measurement Report (if present) */
+ if (ispresent(step.meas_res)) {
+ f_transceive_meas_rep(step.meas_res);
+ f_sleep(0.480 * 2.0);
+ L1CTL.clear;
+ }
+
+ /* Check RxLev on both FACCH and SACCH */
+ f_rxlev_match(tr_RslLinkID_DCCH(?), rxlev_facch);
+ f_rxlev_match(tr_RslLinkID_SACCH(?), rxlev_sacch);
+
+ setverdict(pass);
+ }
+}
+testcase TC_acch_overpower_rxqual_thresh() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ /* Verify lower and upper RxQual thresholds */
+ var template TopTestCase top := {
+ bs_power := ts_RSL_IE_BS_Power(4), /* 4 x 2dB = 8dB */
+ top_cap := ts_RSL_IE_OSMO_TopAcchCap(4), /* 4dB */
+ steps := {
+ /* Channel established, no overpower */
+ { meas_res := omit,
+ overpower_sacch := 0, overpower_facch := 0 },
+
+ /* Worst possible RxQual value, overpower of 4dB */
+ { meas_res := ts_MeasurementResults(rxq_f := 7),
+ overpower_sacch := 4, overpower_facch := 4 },
+ /* Worst possible RxQual value, disabling overpower */
+ { meas_res := ts_MeasurementResults(rxq_f := 0),
+ overpower_sacch := 0, overpower_facch := 0 },
+
+ /* Lower threshold not reached, no overpower */
+ { meas_res := ts_MeasurementResults(rxq_f := 1),
+ overpower_sacch := 0, overpower_facch := 0 },
+ /* Lower threshold not reached, no overpower */
+ { meas_res := ts_MeasurementResults(rxq_f := 2),
+ overpower_sacch := 0, overpower_facch := 0 },
+ /* Lower threshold reached, overpower of 4dB */
+ { meas_res := ts_MeasurementResults(rxq_f := 4),
+ overpower_sacch := 4, overpower_facch := 4 },
+ /* Upper threshold not reached, keeping overpower */
+ { meas_res := ts_MeasurementResults(rxq_f := 3),
+ overpower_sacch := 4, overpower_facch := 4 },
+ /* Upper threshold reached, disabling overpower */
+ { meas_res := ts_MeasurementResults(rxq_f := 2),
+ overpower_sacch := 0, overpower_facch := 0 }
+ }
+ };
+
+ pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN,
+ spec := { top := top }, trx_nr := 1));
+ vc_conn := f_start_handler(refers(f_TC_acch_overpower), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+testcase TC_acch_overpower_rxqual_thresh_dtx() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ /* Verify handling of FULL and SUB values */
+ var template TopTestCase top := {
+ bs_power := ts_RSL_IE_BS_Power(4), /* 4 x 2dB = 8dB */
+ top_cap := ts_RSL_IE_OSMO_TopAcchCap(4), /* 4dB */
+ steps := {
+ /* Channel established, no overpower */
+ { meas_res := omit,
+ overpower_sacch := 0, overpower_facch := 0 },
+
+ /* Invalid measurement results, no overpower */
+ { meas_res := ts_MeasurementResults(rxq_f := 7,
+ rxq_s := 7,
+ valid := false),
+ overpower_sacch := 0, overpower_facch := 0 },
+
+ /* DTXu was in use, no overpower */
+ { meas_res := ts_MeasurementResults(rxq_f := 7,
+ rxq_s := 0,
+ dtx_used := true),
+ overpower_sacch := 0, overpower_facch := 0 },
+ /* DTXu was in use, overpower of 4 dB */
+ { meas_res := ts_MeasurementResults(rxq_f := 0,
+ rxq_s := 7,
+ dtx_used := true),
+ overpower_sacch := 4, overpower_facch := 4 }
+ }
+ };
+
+ pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN,
+ spec := { top := top }, trx_nr := 1));
+ vc_conn := f_start_handler(refers(f_TC_acch_overpower), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+testcase TC_acch_overpower_always_on_facch() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ /* Overpower is always on, SACCH disabled */
+ var template TopTestCase top := {
+ bs_power := ts_RSL_IE_BS_Power(4), /* 4 x 2dB = 8dB */
+ top_cap := ts_RSL_IE_OSMO_TopAcchCap(overpower := 4, /* 4dB */
+ rxqual := 0, /* always on */
+ sacch_enable := false),
+ steps := {
+ /* Channel established, FACCH overpower */
+ { meas_res := omit,
+ overpower_sacch := 0, overpower_facch := 4 },
+ /* MS indicates good RxQual, no difference */
+ { meas_res := ts_MeasurementResults(rxq_f := 0),
+ overpower_sacch := 0, overpower_facch := 4 },
+ /* MS indicates bad RxQual, no difference */
+ { meas_res := ts_MeasurementResults(rxq_f := 7),
+ overpower_sacch := 0, overpower_facch := 4 }
+ }
+ };
+
+ pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN,
+ spec := { top := top }, trx_nr := 1));
+ vc_conn := f_start_handler(refers(f_TC_acch_overpower), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+testcase TC_acch_overpower_always_on_sacch() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ /* Overpower is always on, FACCH disabled */
+ var template TopTestCase top := {
+ bs_power := ts_RSL_IE_BS_Power(4), /* 4 x 2dB = 8dB */
+ top_cap := ts_RSL_IE_OSMO_TopAcchCap(overpower := 4, /* 4dB */
+ rxqual := 0, /* always on */
+ facch_enable := false),
+ steps := {
+ /* Channel established, SACCH overpower */
+ { meas_res := omit,
+ overpower_sacch := 4, overpower_facch := 0 },
+ /* MS indicates good RxQual, no difference */
+ { meas_res := ts_MeasurementResults(rxq_f := 0),
+ overpower_sacch := 4, overpower_facch := 0 },
+ /* MS indicates bad RxQual, no difference */
+ { meas_res := ts_MeasurementResults(rxq_f := 7),
+ overpower_sacch := 4, overpower_facch := 0 }
+ }
+ };
+
+ pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN,
+ spec := { top := top }, trx_nr := 1));
+ vc_conn := f_start_handler(refers(f_TC_acch_overpower), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+testcase TC_acch_overpower_limit() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ /* Overpower higher than current power reduction level (2dB) */
+ var template TopTestCase top := {
+ bs_power := ts_RSL_IE_BS_Power(1), /* 1 x 2dB = 2dB */
+ top_cap := ts_RSL_IE_OSMO_TopAcchCap(overpower := 4, /* 4dB */
+ rxqual := 0 /* always on */),
+ steps := {
+ /* Channel established, ACCH overpower of 2dB */
+ { meas_res := omit,
+ overpower_sacch := 2, overpower_facch := 2 },
+ /* MS indicates good RxQual, no difference */
+ { meas_res := ts_MeasurementResults(rxq_f := 0),
+ overpower_sacch := 2, overpower_facch := 2 },
+ /* MS indicates bad RxQual, no difference */
+ { meas_res := ts_MeasurementResults(rxq_f := 7),
+ overpower_sacch := 2, overpower_facch := 2 }
+ }
+ };
+
+ pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN,
+ spec := { top := top }, trx_nr := 1));
+ vc_conn := f_start_handler(refers(f_TC_acch_overpower), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
/* test generation of RLL ERR IND based on Um errors (TS 48.058 3.9) */
/* protocol error as per 44.006 */
/* link layer failure (repetition of I-frame N200 times without ACK */
@@ -7860,6 +8301,7 @@ testcase TC_early_immediate_assignment() runs on test_CT {
*/
control {
+ execute( TC_est_dchan() );
execute( TC_chan_act_stress() );
execute( TC_chan_act_react() );
execute( TC_chan_deact_not_active() );
@@ -7890,6 +8332,8 @@ control {
execute( TC_meas_res_sign_sdcch4() );
execute( TC_meas_res_sign_sdcch8() );
execute( TC_meas_res_sign_tchh_toa256() );
+ execute( TC_meas_res_speech_tchf_sapi3() );
+ execute( TC_meas_res_speech_tchh_sapi3() );
execute( TC_tx_power_start_ramp_up_bcch() );
execute( TC_tx_power_start_ramp_down_bcch() );
execute( TC_tx_power_ramp_adm_state_change() );
@@ -8030,6 +8474,12 @@ control {
execute( TC_early_immediate_assignment() );
+ execute( TC_acch_overpower_rxqual_thresh() );
+ execute( TC_acch_overpower_rxqual_thresh_dtx() );
+ execute( TC_acch_overpower_always_on_facch() );
+ execute( TC_acch_overpower_always_on_sacch() );
+ execute( TC_acch_overpower_limit() );
+
/* BEWARE: these test cases can potentially break the IUT or cause
* weird/unexpected behavior. Ensure that they are executed last. */
execute( TC_dyn_osmo_pdch_tchh_race_act() );
diff --git a/bts/BTS_Tests_LAPDm.ttcn b/bts/BTS_Tests_LAPDm.ttcn
index 6d252e0a..edd974ba 100644
--- a/bts/BTS_Tests_LAPDm.ttcn
+++ b/bts/BTS_Tests_LAPDm.ttcn
@@ -43,7 +43,8 @@ function f_lapdm_exit() runs on lapdm_test_CT {
/* master function switching to a dedicated radio channel */
function f_switch_dcch() runs on ConnHdlr {
- var GsmBandArfcn arfcn := valueof(ts_GsmBandArfcn(mp_trx_pars[0].arfcn));
+ var TrxParsItem trx_pars := mp_trx_pars[g_pars.trx_nr];
+ var GsmBandArfcn arfcn := valueof(ts_GsmBandArfcn(trx_pars.arfcn));
var BCCH_tune_req tune_req := { arfcn := arfcn, combined_ccch := true };
var DCCH_switch_req sw_req;
@@ -55,7 +56,7 @@ function f_switch_dcch() runs on ConnHdlr {
sw_req.ma := g_pars.fhp.ma;
} else {
sw_req.chan_desc := valueof(ts_ChanDescH0(g_pars.chan_nr,
- mp_trx_pars[0].arfcn,
+ trx_pars.arfcn,
g_pars.tsc));
sw_req.ma := omit;
}
diff --git a/library/GSM_RR_Types.ttcn b/library/GSM_RR_Types.ttcn
index f7b00e15..980020e9 100644
--- a/library/GSM_RR_Types.ttcn
+++ b/library/GSM_RR_Types.ttcn
@@ -650,8 +650,7 @@ module GSM_RR_Types {
NcellReports ncell_reports optional
} with { variant (no_ncell_m) "LENGTHTO(ncell_reports)"
variant (no_ncell_m) "UNIT(elements)"
- variant "PADDING(yes)"
- variant "FIELDLENGTH(16)"
+ /* FIXME: pad to 16 octets */
};
type record NcellReport {
@@ -1105,6 +1104,27 @@ module GSM_RR_Types {
}
};
+ template (value) MeasurementResults
+ ts_MeasurementResults(template (value) uint6_t rxl_f := 63,
+ template (value) uint6_t rxl_s := 63,
+ template (value) uint3_t rxq_f := 0,
+ template (value) uint3_t rxq_s := 0,
+ boolean dtx_used := false,
+ boolean valid := true,
+ template (omit) NcellReports reps := omit) := {
+ ba_used := '0'B,
+ dtx_used := bool2bit(dtx_used),
+ rxlev_full_srv_cell := rxl_f,
+ threeg_ba_used := '0'B,
+ meas_valid := bool2bit(not valid),
+ rxlev_sub_srv_cell := rxl_s,
+ si23_ba_used := '0'B,
+ rxqual_full_srv_cell := rxq_f,
+ rxqual_sub_srv_cell := rxq_s,
+ no_ncell_m := 0,
+ ncell_reports := reps
+ };
+
template (value) GsmRrL3Message ts_MEAS_REP(boolean valid,
template (value) uint6_t rxl_f,
template (value) uint6_t rxl_s,
diff --git a/library/L1CTL_PortType.ttcn b/library/L1CTL_PortType.ttcn
index 80e33a81..ed235d3e 100644
--- a/library/L1CTL_PortType.ttcn
+++ b/library/L1CTL_PortType.ttcn
@@ -42,6 +42,29 @@ module L1CTL_PortType {
return len;
}
+ function f_L1CTL_rx_data(L1CTL_PT pt,
+ template (present) RslChannelNr chan_nr := ?,
+ template (present) RslLinkId link_id := ?)
+ return L1ctlDlMessage {
+ var L1ctlDlMessage dl;
+ timer T := 2.0;
+
+ T.start;
+ alt {
+ [] pt.receive(tr_L1CTL_DATA_IND(chan_nr, link_id)) -> value dl {
+ return dl;
+ }
+ [] pt.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for L1CTL DATA.ind");
+ mtc.stop;
+ }
+ }
+
+ /* Unreachable, make TITAN happy */
+ return dl;
+ }
+
function f_L1CTL_FBSB(L1CTL_PT pt, GsmBandArfcn arfcn,
L1ctlCcchMode ccch_mode := CCCH_MODE_COMBINED,
integer rxlev_exp := 57)
diff --git a/library/L3_Templates.ttcn b/library/L3_Templates.ttcn
index 997b433f..e6efb688 100644
--- a/library/L3_Templates.ttcn
+++ b/library/L3_Templates.ttcn
@@ -389,6 +389,23 @@ template (value) PDU_ML3_MS_NW ts_CM_SERV_REQ(CmServiceType serv_type, MobileIde
}
}
+template (value) PDU_ML3_NW_MS ts_CM_SERV_REJ(OCT1 rejectCause) := {
+ discriminator := '0000'B, /* overwritten */
+ tiOrSkip := {
+ skipIndicator := '0000'B
+ },
+ msgs := {
+ mm := {
+ cMServiceReject := {
+ messageType := '000000'B, /* overwritten */
+ nsd := '00'B,
+ rejectCause := rejectCause,
+ t3246_Value := omit
+ }
+ }
+ }
+}
+
template (value) PDU_ML3_MS_NW ts_CM_REESTABL_REQ(MobileIdentityLV mi_lv) := {
discriminator := '0000'B, /* overwritten */
tiOrSkip := {
diff --git a/library/MNCC_Emulation.ttcn b/library/MNCC_Emulation.ttcn
index 66294a4a..85556c1f 100644
--- a/library/MNCC_Emulation.ttcn
+++ b/library/MNCC_Emulation.ttcn
@@ -38,7 +38,7 @@ import from MNCC_Types all;
import from UD_Types all;
modulepar {
- int mp_mncc_version := 7;
+ int mp_mncc_version := 8;
}
/* General "base class" component definition, of which specific implementations
diff --git a/library/MNCC_EncDec.cc b/library/MNCC_EncDec.cc
index be5d01a5..ffc2aa8c 100644
--- a/library/MNCC_EncDec.cc
+++ b/library/MNCC_EncDec.cc
@@ -9,7 +9,7 @@ static int mncc_sock_version = MNCC_SOCK_VERSION;
BOOLEAN set__MNCC__version(INTEGER const& version)
{
- if (version != 6 && version != 7)
+ if (version != 7 && version != 8)
return false;
mncc_sock_version = version;
return true;
@@ -184,6 +184,20 @@ OCTETSTRING enc__MNCC__PDU(const MNCC__PDU& in)
strncpy(mncc.imsi, in_sig.imsi(), sizeof(mncc.imsi));
mncc.lchan_type = in_sig.lchan__type();
mncc.lchan_mode = in_sig.lchan__mode();
+ if (in_sig.gcr().is_value()) {
+ const OCTETSTRING &gcr = in_sig.gcr();
+ if (mncc_sock_version < 8)
+ TTCN_error("GCR is only available since MNCCv8");
+ memcpy(&mncc.v8.gcr[0], gcr, sizeof(mncc.v8.gcr));
+ mncc.fields |= MNCC_F_GCR;
+ }
+ if (in_sig.sdp().is_value()) {
+ const CHARSTRING &sdp = in_sig.sdp();
+ if (mncc_sock_version > 7)
+ strncpy(&mncc.v8.sdp[0], sdp, sizeof(mncc.v8.sdp));
+ else
+ strncpy(&mncc.v7.sdp[0], sdp, sizeof(mncc.v7.sdp));
+ }
ret_val = OCTETSTRING(sizeof(mncc), (uint8_t *)&mncc);
}
break;
@@ -195,46 +209,27 @@ OCTETSTRING enc__MNCC__PDU(const MNCC__PDU& in)
ret_val = ret_val & in.u().data().data();
break;
case MNCC__MsgUnion::ALT_rtp:
- switch (mncc_sock_version) {
- case 6:
- struct gsm_mncc_rtp_mncc6 rtp_old;
- memset(&rtp_old, 0, sizeof(rtp_old));
- rtp_old.msg_type = in.msg__type();
- rtp_old.callref = in.u().rtp().callref();
- ttcn_buffer.put_string(in.u().rtp().ip());
- if (!in.u().rtp().is__ipv6()) {
- memcpy(&rtp_old.ip, ttcn_buffer.get_data(), sizeof(struct in_addr));
- rtp_old.ip = ntohl(rtp_old.ip);
- } /* else: ipv6 not supported in MNCCv6 */
- rtp_old.port = in.u().rtp().rtp__port();
- rtp_old.payload_type = in.u().rtp().payload__type();
- rtp_old.payload_msg_type = in.u().rtp().payload__msg__type();
- ret_val = OCTETSTRING(sizeof(rtp_old), (uint8_t *) &rtp_old);
- break;
- case 7:
- struct gsm_mncc_rtp rtp;
- memset(&rtp, 0, sizeof(rtp));
- rtp.msg_type = in.msg__type();
- rtp.callref = in.u().rtp().callref();
- ttcn_buffer.put_string(in.u().rtp().ip());
- if (in.u().rtp().is__ipv6()) {
- // if(in.u().rtp().ip().lengthof() != 16) print error
- rtp.addr.ss_family = AF_INET6;
- memcpy(&((struct sockaddr_in6*)&rtp.addr)->sin6_addr, ttcn_buffer.get_data(),
- sizeof(struct in6_addr));
- ((struct sockaddr_in6*)&rtp.addr)->sin6_port = htons(in.u().rtp().rtp__port());
- } else {
- // if(in.u().rtp().ip().lengthof() != 4) print error
- rtp.addr.ss_family = AF_INET;
- memcpy(&((struct sockaddr_in*)&rtp.addr)->sin_addr, ttcn_buffer.get_data(),
- sizeof(struct in_addr));
- ((struct sockaddr_in*)&rtp.addr)->sin_port = htons(in.u().rtp().rtp__port());
- }
- rtp.payload_type = in.u().rtp().payload__type();
- rtp.payload_msg_type = in.u().rtp().payload__msg__type();
- ret_val = OCTETSTRING(sizeof(rtp), (uint8_t *) &rtp);
- break;
+ struct gsm_mncc_rtp rtp;
+ memset(&rtp, 0, sizeof(rtp));
+ rtp.msg_type = in.msg__type();
+ rtp.callref = in.u().rtp().callref();
+ ttcn_buffer.put_string(in.u().rtp().ip());
+ if (in.u().rtp().is__ipv6()) {
+ // if(in.u().rtp().ip().lengthof() != 16) print error
+ rtp.addr.ss_family = AF_INET6;
+ memcpy(&((struct sockaddr_in6*)&rtp.addr)->sin6_addr, ttcn_buffer.get_data(),
+ sizeof(struct in6_addr));
+ ((struct sockaddr_in6*)&rtp.addr)->sin6_port = htons(in.u().rtp().rtp__port());
+ } else {
+ // if(in.u().rtp().ip().lengthof() != 4) print error
+ rtp.addr.ss_family = AF_INET;
+ memcpy(&((struct sockaddr_in*)&rtp.addr)->sin_addr, ttcn_buffer.get_data(),
+ sizeof(struct in_addr));
+ ((struct sockaddr_in*)&rtp.addr)->sin_port = htons(in.u().rtp().rtp__port());
}
+ rtp.payload_type = in.u().rtp().payload__type();
+ rtp.payload_msg_type = in.u().rtp().payload__msg__type();
+ ret_val = OCTETSTRING(sizeof(rtp), (uint8_t *) &rtp);
break;
case MNCC__MsgUnion::ALT_hello:
struct gsm_mncc_hello hello;
@@ -264,7 +259,6 @@ MNCC__PDU dec__MNCC__PDU(const OCTETSTRING& in)
const struct gsm_data_frame *in_data;
MNCC__PDU__Data data;
const struct gsm_mncc_rtp *in_rtp;
- const struct gsm_mncc_rtp_mncc6 *in_rtp_old;
MNCC__PDU__Rtp rtp;
MNCC__MsgUnion u;
bool is_ipv6;
@@ -303,40 +297,26 @@ MNCC__PDU dec__MNCC__PDU(const OCTETSTRING& in)
case MNCC_RTP_CREATE:
case MNCC_RTP_CONNECT:
case MNCC_RTP_FREE:
- switch (mncc_sock_version) {
- case 6:
- struct in_addr inaddr;
- in_rtp_old = (const struct gsm_mncc_rtp_mncc6 *) in_mncc;
- inaddr.s_addr = htonl(in_rtp_old->ip);
- ip = OCTETSTRING(sizeof(struct in_addr),
- (const unsigned char*)&inaddr);
- rtp = MNCC__PDU__Rtp(in_rtp_old->callref, false, ip, in_rtp_old->port, in_rtp_old->payload_type,
- in_rtp_old->payload_msg_type, in_rtp_old->sdp);
- u.rtp() = rtp;
- break;
- case 7:
- in_rtp = (const struct gsm_mncc_rtp *) in_mncc;
- switch (in_rtp->addr.ss_family) {
- case AF_INET6:
- is_ipv6 = true;
- port = ntohs(((struct sockaddr_in6*)&in_rtp->addr)->sin6_port);
- ip = OCTETSTRING(sizeof(struct in6_addr),
- (const unsigned char*)&((struct sockaddr_in6*)&in_rtp->addr)->sin6_addr);
+ in_rtp = (const struct gsm_mncc_rtp *) in_mncc;
+ switch (in_rtp->addr.ss_family) {
+ case AF_INET6:
+ is_ipv6 = true;
+ port = ntohs(((struct sockaddr_in6*)&in_rtp->addr)->sin6_port);
+ ip = OCTETSTRING(sizeof(struct in6_addr),
+ (const unsigned char*)&((struct sockaddr_in6*)&in_rtp->addr)->sin6_addr);
break;
- case AF_UNSPEC: //RTP_CREATE and RTP_FREE can contain fully zeroed addr
- case AF_INET:
- is_ipv6 = false;
- port = ntohs(((struct sockaddr_in*)&in_rtp->addr)->sin_port);
- ip = OCTETSTRING(sizeof(struct in_addr),
- (const unsigned char*)&((struct sockaddr_in*)&in_rtp->addr)->sin_addr);
- break;
- }
- rtp = MNCC__PDU__Rtp(in_rtp->callref, is_ipv6, ip, port, in_rtp->payload_type,
- in_rtp->payload_msg_type, in_rtp->sdp);
- u.rtp() = rtp;
+ case AF_UNSPEC: //RTP_CREATE and RTP_FREE can contain fully zeroed addr
+ case AF_INET:
+ is_ipv6 = false;
+ port = ntohs(((struct sockaddr_in*)&in_rtp->addr)->sin_port);
+ ip = OCTETSTRING(sizeof(struct in_addr),
+ (const unsigned char*)&((struct sockaddr_in*)&in_rtp->addr)->sin_addr);
break;
}
+ rtp = MNCC__PDU__Rtp(in_rtp->callref, is_ipv6, ip, port, in_rtp->payload_type,
+ in_rtp->payload_msg_type, in_rtp->sdp);
+ u.rtp() = rtp;
break;
default:
sign.callref() = in_mncc->callref;
@@ -391,7 +371,13 @@ MNCC__PDU dec__MNCC__PDU(const OCTETSTRING& in)
sign.imsi() = CHARSTRING(in_mncc->imsi);
sign.lchan__type() = in_mncc->lchan_type;
sign.lchan__mode() = in_mncc->lchan_mode;
- sign.sdp() = in_mncc->sdp;
+ if (mncc_sock_version > 7) {
+ if (in_mncc->fields & MNCC_F_GCR)
+ sign.gcr() = OCTETSTRING(sizeof(in_mncc->v8.gcr), in_mncc->v8.gcr);
+ sign.sdp() = in_mncc->v8.sdp;
+ } else {
+ sign.sdp() = in_mncc->v7.sdp;
+ }
u.signal() = sign;
break;
}
diff --git a/library/MNCC_Types.ttcn b/library/MNCC_Types.ttcn
index bd233cea..1de34a0f 100644
--- a/library/MNCC_Types.ttcn
+++ b/library/MNCC_Types.ttcn
@@ -362,6 +362,7 @@ type record MNCC_PDU_Signal {
uint8_t lchan_type, /* empty in OSmoMSC */
uint8_t lchan_mode, /* empty in OsmoMSC */
+ octetstring gcr optional,
charstring sdp optional
};
@@ -472,7 +473,8 @@ template MNCC_PDU ts_MNCC_SIMPLE(MNCC_MsgType msg_type, uint32_t call_id) := {
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -503,6 +505,7 @@ template MNCC_PDU tr_MNCC_SIMPLE(template MNCC_MsgType msg_type, template uint32
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -537,7 +540,8 @@ template MNCC_PDU ts_MNCC_SETUP_req(uint32_t call_id, charstring called, charstr
imsi := imsi,
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
};
@@ -570,6 +574,7 @@ template MNCC_PDU tr_MNCC_SETUP_req(template uint32_t call_id := ?,
imsi := imsi,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -604,7 +609,8 @@ template MNCC_PDU ts_MNCC_SETUP_rsp(uint32_t call_id, charstring imsi := "",
imsi := imsi,
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
};
@@ -636,6 +642,7 @@ template MNCC_PDU tr_MNCC_SETUP_rsp(template uint32_t call_id,
imsi := imsi,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -670,6 +677,7 @@ template MNCC_PDU tr_MNCC_SETUP_ind(template uint32_t call_id := ?, template MNC
imsi := imsi,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -703,7 +711,8 @@ template (value) MNCC_PDU ts_MNCC_SETUP_ind(uint32_t call_id, MNCC_number called
imsi := imsi,
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -735,7 +744,8 @@ template MNCC_PDU ts_MNCC_SETUP_CNF(uint32_t call_id, template MNCC_number conne
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -767,6 +777,7 @@ template MNCC_PDU tr_MNCC_SETUP_cnf(uint32_t call_id, template MNCC_number conne
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -809,6 +820,7 @@ template MNCC_PDU tr_MNCC_REJ_req(template uint32_t call_id, template MNCC_cause
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -841,7 +853,8 @@ template MNCC_PDU ts_MNCC_REJ_ind(uint32_t call_id, template MNCC_cause cause :=
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -875,6 +888,7 @@ template MNCC_PDU tr_MNCC_CALL_CONF_ind(template uint32_t call_id, template MNCC
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -908,7 +922,8 @@ template MNCC_PDU ts_MNCC_CALL_CONF_ind(uint32_t call_id,
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -944,7 +959,8 @@ template MNCC_PDU ts_MNCC_CALL_PROC_req(uint32_t call_id, template MNCC_bearer_c
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -978,6 +994,7 @@ template MNCC_PDU tr_MNCC_CALL_PROC_req(template uint32_t call_id,
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1012,7 +1029,8 @@ template MNCC_PDU ts_MNCC_PROGRESS_req(uint32_t call_id, MNCC_progress prog,
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1046,7 +1064,8 @@ template MNCC_PDU ts_MNCC_ALERT_req(uint32_t call_id, template MNCC_progress pro
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1079,6 +1098,7 @@ template MNCC_PDU tr_MNCC_ALERT_req(template uint32_t call_id,
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1115,6 +1135,7 @@ template MNCC_PDU tr_MNCC_ALERT_ind(template uint32_t call_id, template MNCC_pro
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1148,7 +1169,8 @@ template (value) MNCC_PDU ts_MNCC_ALERT_ind(uint32_t call_id,
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1181,7 +1203,8 @@ template MNCC_PDU ts_MNCC_NOTIFY_req(uint32_t call_id, MNCC_notify notify) := {
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1213,6 +1236,7 @@ template MNCC_PDU tr_MNCC_NOTIFY_ind(template uint32_t call_id, template MNCC_no
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1248,6 +1272,7 @@ template MNCC_PDU tr_MNCC_DISC_ind(template uint32_t call_id := ?, template MNCC
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1281,7 +1306,8 @@ template (value) MNCC_PDU ts_MNCC_DISC_ind(uint32_t call_id, template (value) MN
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1316,7 +1342,8 @@ template MNCC_PDU ts_MNCC_DISC_req(uint32_t call_id, MNCC_cause cause,
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1350,6 +1377,7 @@ template MNCC_PDU tr_MNCC_DISC_req(template uint32_t call_id,
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1384,6 +1412,7 @@ template MNCC_PDU tr_MNCC_REL_ind(template uint32_t call_id := ?, template MNCC_
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1417,7 +1446,8 @@ template (value) MNCC_PDU ts_MNCC_REL_ind(uint32_t call_id,
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1450,7 +1480,8 @@ template MNCC_PDU ts_MNCC_REL_req(uint32_t call_id, MNCC_cause cause,
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1481,6 +1512,7 @@ template MNCC_PDU tr_MNCC_REL_req(template uint32_t call_id, template MNCC_cause
imsi := ?,
lchan_type := 0,
lchan_mode := 0,
+ gcr := *,
sdp := *
}
}
@@ -1529,7 +1561,8 @@ template MNCC_PDU ts_MNCC_FACILITY_req(uint32_t call_id, charstring fac) := {
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1561,6 +1594,7 @@ template MNCC_PDU tr_MNCC_FACILITY_ind(template uint32_t call_id := ?, template
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1593,6 +1627,7 @@ template MNCC_PDU tr_MNCC_START_DTMF_ind(template uint32_t call_id := ?, templat
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1625,7 +1660,8 @@ template MNCC_PDU ts_MNCC_START_DTMF_rsp(uint32_t call_id, MNCC_keypad keypad) :
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1657,7 +1693,8 @@ template MNCC_PDU ts_MNCC_START_DTMF_rej(uint32_t call_id, MNCC_cause cause) :=
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1697,6 +1734,7 @@ template MNCC_PDU tr_MNCC_MODIFY_ind(template uint32_t call_id := ?, template MN
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1729,7 +1767,8 @@ template MNCC_PDU ts_MNCC_MODIFY_rsp(uint32_t call_id, MNCC_bearer_cap bcap) :=
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1761,7 +1800,8 @@ template MNCC_PDU ts_MNCC_MODIFY_req(uint32_t call_id, MNCC_bearer_cap bcap) :=
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1794,6 +1834,7 @@ template MNCC_PDU tr_MNCC_MODIFY_cnf(template uint32_t call_id := ?,
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1826,7 +1867,8 @@ template MNCC_PDU ts_MNCC_USERINFO_req(uint32_t call_id, MNCC_useruser uu, integ
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1859,6 +1901,7 @@ template MNCC_PDU tr_MNCC_USERINFO_ind(template uint32_t call_id := ?, template
imsi := "",
lchan_type := 0,
lchan_mode := 0,
+ gcr := *,
sdp := *
}
}
@@ -1899,7 +1942,8 @@ template MNCC_PDU ts_MNCC_HOLD_rej(uint32_t call_id, MNCC_cause cause) := {
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1929,7 +1973,7 @@ template MNCC_PDU ts_MNCC_SIMPLE_RTP(MNCC_MsgType msg_type, uint32_t call_id) :=
rtp_port := 0,
payload_type := 0,
payload_msg_type := 0,
- sdp := ""
+ sdp := omit
}
}
}
@@ -1967,7 +2011,7 @@ template MNCC_PDU ts_MNCC_RTP_CONNECT(uint32_t call_id, boolean is_ipv6, octetst
rtp_port := rtp_port,
payload_type := pt,
payload_msg_type := 0,
- sdp := ""
+ sdp := omit
}
}
}
diff --git a/library/Osmocom_CTRL_Functions.ttcn b/library/Osmocom_CTRL_Functions.ttcn
index 8d5607b6..2c90de45 100644
--- a/library/Osmocom_CTRL_Functions.ttcn
+++ b/library/Osmocom_CTRL_Functions.ttcn
@@ -23,6 +23,8 @@ module Osmocom_CTRL_Functions {
import from Osmocom_CTRL_Types all;
import from IPA_Emulation all;
+ type record of charstring charstring_list;
+
private function f_gen_rand_id() return CtrlId {
return int2str(float2int(rnd()*999999999.0));
}
@@ -289,4 +291,81 @@ module Osmocom_CTRL_Functions {
}
}
+ /* For a specific instance, call f_counter_name_vals_get() and indentify counters that have changed with respect
+ * to 'vals'. Return list of the changed counter names in the order they appear in 'vals'. */
+ function f_counter_name_vals_get_changed(IPA_CTRL_PT pt, charstring instance_name, integer instance_nr,
+ CounterNameVals vals)
+ return charstring_list {
+ var charstring_list changed := {};
+ var CounterNameVals last := f_counter_name_vals_get(pt, instance_name, instance_nr, vals);
+ for (var integer i := 0; i < lengthof(vals); i := i + 1) {
+ if (last[i].name != vals[i].name) {
+ setverdict(fail, "Internal error");
+ }
+ if (last[i].val != vals[i].val) {
+ changed := changed & { instance_name & "." & int2str(instance_nr) & "." & vals[i].name };
+ }
+ }
+ return changed;
+ }
+
+ /* For N instances, call f_counter_name_vals_get() and indentify counters that have changed with respect
+ * to 'vals'. Return list of the changed counter names in the order they appear in 'vals'. */
+ function f_counter_name_vals_get_changed_n(IPA_CTRL_PT pt, charstring instance_name, CounterNameValsList valslist)
+ return charstring_list {
+ var charstring_list changed := {};
+ for (var integer instance_nr := 0; instance_nr < lengthof(valslist); instance_nr := instance_nr + 1) {
+ changed := changed & f_counter_name_vals_get_changed(pt, instance_name, instance_nr, valslist[instance_nr]);
+ }
+ return changed;
+ }
+
+ function f_counter_name_vals_expect_changed(IPA_CTRL_PT pt, charstring instance_name, CounterNameValsList valslist,
+ charstring_list expect_changed) {
+ var charstring_list changed := f_counter_name_vals_get_changed_n(pt, instance_name, valslist);
+ f_counter_name_vals_expect_changed_list(changed, expect_changed);
+ }
+
+ function f_counter_name_vals_expect_changed_list(charstring_list got_list, charstring_list expect_list) {
+ var charstring unexpected_change := "";
+ for (var integer i := 0; i < lengthof(got_list); i := i + 1) {
+ var boolean found := false;
+ for (var integer j := 0; j < lengthof(expect_list); j := j + 1) {
+ if (got_list[i] == expect_list[j]) {
+ found := true;
+ break;
+ }
+ }
+ if (not found) {
+ unexpected_change := unexpected_change & " " & got_list[i];
+ }
+ }
+ var charstring missing_change := "";
+ for (var integer i := 0; i < lengthof(expect_list); i := i + 1) {
+ var boolean found := false;
+ for (var integer j := 0; j < lengthof(got_list); j := j + 1) {
+ if (expect_list[i] == got_list[j]) {
+ found := true;
+ break;
+ }
+ }
+ if (not found) {
+ missing_change := missing_change & " " & expect_list[i];
+ }
+ }
+ var charstring diff := "";
+ if (lengthof(unexpected_change) > 0) {
+ diff := diff & " Unexpected changes in" & unexpected_change & ";";
+ }
+ if (lengthof(missing_change) > 0) {
+ diff := diff & " Missing changes in" & missing_change & ";";
+ }
+ if (lengthof(diff) > 0) {
+ log("ERROR\nExpected: ", expect_list, "\nGot: ", got_list);
+ setverdict(fail, "Rate counters did not change as expected:" & diff);
+ } else {
+ setverdict(pass);
+ }
+ }
+
}
diff --git a/library/RLCMAC_CSN1_Templates.ttcn b/library/RLCMAC_CSN1_Templates.ttcn
index 254983a8..df506094 100644
--- a/library/RLCMAC_CSN1_Templates.ttcn
+++ b/library/RLCMAC_CSN1_Templates.ttcn
@@ -19,6 +19,28 @@ module RLCMAC_CSN1_Templates {
import from MobileL3_GMM_SM_Types all;
import from RLCMAC_CSN1_Types all;
+ /* 11.2.1 Packet Access Reject */
+ template PacketAccessRejectStruct tr_RlcMacDlCtrl_PKT_ACC_REJ_ID_TLLI(template GprsTlli tlli := ?) := {
+ id_type := '0'B,
+ id := {
+ tlli := tlli
+ }
+ }
+ template RlcmacDlCtrlMsg tr_RlcMacDlCtrl_PKT_ACC_REJ(template PacketAccessRejectStruct rej := ?,
+ template uint8_t wait_ind := *,
+ template BIT1 wait_ind_size := *) := {
+ msg_type := PACKET_ACCESS_REJECT,
+ u := {
+ access_reject := {
+ page_mode := ?,
+ reject_struct := rej,
+ wait_ind_presence := ?,
+ wait_ind := wait_ind,
+ wait_ind_size := wait_ind_size
+ }
+ }
+ }
+
template (value) RlcmacUlCtrlMsg ts_RlcMacUlCtrl_PKT_CTRL_ACK(GprsTlli tlli,
CtrlAck ack := MS_RCVD_TWO_RLC_SAME_RTI_DIFF_RBSN) := {
msg_type := PACKET_CONTROL_ACK,
@@ -77,7 +99,19 @@ module RLCMAC_CSN1_Templates {
rlc_mode := RLC_MODE_ACKNOWLEDGED,
llc_pdu_type := LLC_PDU_IS_NOT_SACK_OR_ACK,
RlcOctetCount := 0
- }
+ };
+
+ template (value) ChannelReqDescription ts_ChannelReqDescription(uint4_t peak_tput_class := 0,
+ uint2_t priority := 0,
+ RlcMode rlc_mode := RLC_MODE_ACKNOWLEDGED,
+ LlcPduType llc_pdu_type := LLC_PDU_IS_NOT_SACK_OR_ACK,
+ uint16_t RlcOctetCount := 0) := {
+ peak_tput_class := peak_tput_class,
+ priority := priority,
+ rlc_mode := rlc_mode,
+ llc_pdu_type := llc_pdu_type,
+ RlcOctetCount := RlcOctetCount
+ };
/* TS 44.060 sec 11.2.16 */
template (value) RlcmacUlCtrlMsg ts_RlcMacUlCtrl_PKT_RES_REQ(GprsTlli tlli,
diff --git a/library/RLCMAC_CSN1_Types.ttcn b/library/RLCMAC_CSN1_Types.ttcn
index d9a56626..e1dbc167 100644
--- a/library/RLCMAC_CSN1_Types.ttcn
+++ b/library/RLCMAC_CSN1_Types.ttcn
@@ -705,6 +705,7 @@ module RLCMAC_CSN1_Types {
/* 11.2.0.1 */
type union RlcmacDlCtrlUnion {
+ PacketAccessReject access_reject,
PacketDlAssignment dl_assignment,
PacketMeasOrder meas_order,
PacketUlAssignment ul_assignment,
@@ -721,7 +722,8 @@ module RLCMAC_CSN1_Types {
RlcmacDlCtrlMsgType msg_type,
RlcmacDlCtrlUnion u
} with {
- variant (u) "CROSSTAG(dl_assignment, msg_type = PACKET_DL_ASSIGNMENT;
+ variant (u) "CROSSTAG(access_reject, msg_type = PACKET_ACCESS_REJECT;
+ dl_assignment, msg_type = PACKET_DL_ASSIGNMENT;
meas_order, msg_type = PACKET_MEASUREMENT_ORDER;
ul_assignment, msg_type = PACKET_UL_ASSIGNMENT;
paging, msg_type = PACKET_PAGING_REQUEST;
@@ -739,6 +741,34 @@ module RLCMAC_CSN1_Types {
external function dec_RlcmacDlCtrlMsg(in octetstring stream) return RlcmacDlCtrlMsg
with { extension "prototype(convert) decode(RAW)" };
+ /* 11.2.1 Packet Access Reject */
+ type record PacketAccessRejectIDSub {
+ BIT1 id_type,
+ PacketRequestReference req_ref optional,
+ GlobalTfi gtfi optional
+ } with { variant (req_ref) "PRESENCE(id_type = '0'B)"
+ variant (gtfi) "PRESENCE(id_type = '1'B)"
+ };
+ type union PacketAccessRejectID {
+ GprsTlli tlli,
+ PacketAccessRejectIDSub id_sub
+ } with { variant (tlli) "BYTEORDER(first)" };
+ type record PacketAccessRejectStruct {
+ BIT1 id_type,
+ PacketAccessRejectID id
+ } with { variant (id) "CROSSTAG(tlli, id_type = '0'B; id_sub, id_type = '1'B)" };
+ type record PacketAccessReject {
+ PageMode page_mode,
+ PacketAccessRejectStruct reject_struct,
+ BIT1 wait_ind_presence,
+ uint8_t wait_ind,
+ BIT1 wait_ind_size
+ /* TODO: Additional Reject */
+ /* TODO: Rel5 additions */
+ } with { variant (wait_ind) "PRESENCE(wait_ind_presence = '1'B)"
+ variant (wait_ind_size) "PRESENCE(wait_ind_presence = '1'B)"
+ };
+
/* 11.2.6 Packet Downlink Ack/Nack */
type record ILevel {
diff --git a/library/RSL_Types.ttcn b/library/RSL_Types.ttcn
index aa206a39..1057f0bb 100644
--- a/library/RSL_Types.ttcn
+++ b/library/RSL_Types.ttcn
@@ -220,7 +220,9 @@ module RSL_Types {
RSL_IE_TFO_STATUS ('00111011'B),
RSL_IE_LLP_APDU ('00111100'B),
+ RSL_IE_OSMO_REP_ACCH_CAP ('01100000'B),
RSL_IE_OSMO_TRAINING_SEQUENCE ('01100001'B),
+ RSL_IE_OSMO_TOP_ACCH_CAP ('01100010'B),
/* ip.access */
RSL_IE_IPAC_SRTP_CONFIG ('11100000'B),
@@ -873,6 +875,47 @@ module RSL_Types {
uint8_t tsc
} with { variant (len) "LENGTHTO(tsc_set,tsc)" }
+ type record RSL_IE_OSMO_RepAcchCap {
+ uint8_t len,
+ BIT1 rfu ('0'B),
+ uint3_t rxqual,
+ boolean ul_sacch,
+ boolean dl_sacch,
+ boolean dl_facch_all,
+ boolean dl_facch_cmd
+ } with { variant (len) "LENGTHTO(rfu,rxqual,ul_sacch,dl_sacch,dl_facch_all,dl_facch_cmd)" }
+
+ type record RSL_IE_OSMO_TopAcchCap {
+ uint8_t len,
+ boolean sacch_enable,
+ boolean facch_enable,
+ uint3_t rxqual,
+ uint3_t overpower_db
+ } with { variant (len) "LENGTHTO(sacch_enable,facch_enable,rxqual,overpower_db)" }
+
+ template (value) RSL_IE_OSMO_TopAcchCap
+ ts_RSL_IE_OSMO_TopAcchCap(template (value) uint3_t overpower := 2,
+ template (value) uint3_t rxqual := 4,
+ boolean facch_enable := true,
+ boolean sacch_enable := true) := {
+ len := 0, /* overwritten */
+ sacch_enable := sacch_enable,
+ facch_enable := facch_enable,
+ rxqual := rxqual,
+ overpower_db := overpower
+ };
+ template RSL_IE_OSMO_TopAcchCap
+ tr_RSL_IE_OSMO_TopAcchCap(template (present) uint3_t overpower := ?,
+ template (present) uint3_t rxqual := ?,
+ template (present) boolean facch_enable := ?,
+ template (present) boolean sacch_enable := ?) := {
+ len := ?, /* overwritten */
+ sacch_enable := sacch_enable,
+ facch_enable := facch_enable,
+ rxqual := rxqual,
+ overpower_db := overpower
+ };
+
/* union of all IE bodies */
type union RSL_IE_Body {
RslChannelNr chan_nr,
@@ -927,6 +970,8 @@ module RSL_Types {
RSL_IE_IPA_SpeechMode ipa_speech_mode,
RSL_IE_OSMO_TrainingSequence osmo_training_sequence,
+ RSL_IE_OSMO_RepAcchCap rep_acch_cap,
+ RSL_IE_OSMO_TopAcchCap top_acch_cap,
RSL_LV other
}
@@ -989,6 +1034,8 @@ module RSL_Types {
ipa_speech_mode, iei = RSL_IE_IPAC_SPEECH_MODE;
osmo_training_sequence, iei = RSL_IE_OSMO_TRAINING_SEQUENCE;
+ rep_acch_cap, iei = RSL_IE_OSMO_REP_ACCH_CAP;
+ top_acch_cap, iei = RSL_IE_OSMO_TOP_ACCH_CAP;
other, OTHERWISE;
)" };
diff --git a/library/SCCP_Templates.ttcn b/library/SCCP_Templates.ttcn
index 5167e4b2..74f1a206 100644
--- a/library/SCCP_Templates.ttcn
+++ b/library/SCCP_Templates.ttcn
@@ -171,6 +171,53 @@ template PDU_SCCP tr_SCCP_UDT(template (present) SCCP_PAR_Address calling, templ
}
}
+template (value) PDU_SCCP ts_SCCP_XUDT(SCCP_PAR_Address calling, SCCP_PAR_Address called,
+ template (value) octetstring data,
+ template (value) BIT4 msg_hdl := '0000'B,
+ template (value) integer hop_ctr := 16) := {
+ extudata := {
+ messageType := xudt,
+ protClass := {'0000'B, msg_hdl},
+ hopCounter := hop_ctr,
+ pointer1 := 0, /* overwritten */
+ pointer2 := 0, /* overwritten */
+ pointer3 := 0, /* overwritten */
+ pointer4 := 0, /* overwritten */
+ calledPAddress := ConvertASPAddressToEncodedAddress_itu(called),
+ callingPAddress := ConvertASPAddressToEncodedAddress_itu(calling),
+ data := {
+ paramLength := 0,
+ data := data
+ },
+ optionalPart := omit,
+ eop := omit
+ }
+}
+
+template PDU_SCCP tr_SCCP_XUDT(template (present) SCCP_PAR_Address calling, template (present) SCCP_PAR_Address called,
+ template octetstring data := ?,
+ template BIT4 msg_hdl := '0000'B,
+ template integer hop_ctr := ?) := {
+ extudata := {
+ messageType := xudt,
+ protClass := {'0000'B, msg_hdl},
+ hopCounter := hop_ctr,
+ pointer1 := ?,
+ pointer2 := ?,
+ pointer3 := ?,
+ pointer4 := ?,
+ calledPAddress := tr_Addr(called),
+ callingPAddress := tr_Addr(calling),
+ data := {
+ paramLength := ?,
+ data := data
+ },
+ optionalPart := { segmentation:= omit, importance := * } ifpresent,
+ eop := { paramName:= con_SCCP_eop } ifpresent
+ }
+}
+
+
template PDU_SCCP tr_SCCP_IT(template (present) OCT3 source_lref := ?,
template (present) OCT3 dest_lref := ?) := {
inacttest := {
diff --git a/library/mncc.h b/library/mncc.h
index a55d155b..f70f9bda 100644
--- a/library/mncc.h
+++ b/library/mncc.h
@@ -230,6 +230,7 @@ enum {
#define MNCC_F_CCCAP 0x0800
#define MNCC_F_KEYPAD 0x1000
#define MNCC_F_SIGNAL 0x2000
+#define MNCC_F_GCR 0x4000
struct gsm_mncc {
/* context based information */
@@ -267,7 +268,15 @@ struct gsm_mncc {
unsigned char lchan_type;
unsigned char lchan_mode;
- char sdp[1024];
+ union {
+ struct {
+ char sdp[1024];
+ } v7;
+ struct {
+ uint8_t gcr[16];
+ char sdp[1024];
+ } v8;
+ };
};
struct gsm_data_frame {
@@ -292,18 +301,6 @@ struct gsm_mncc_hello {
uint32_t lchan_type_offset;
};
-/* Use this one in MNCCv6 */
-struct gsm_mncc_rtp_mncc6 {
- uint32_t msg_type;
- uint32_t callref;
- uint32_t ip;
- uint16_t port;
- uint32_t payload_type;
- uint32_t payload_msg_type;
-
- char sdp[1024];
-};
-
struct gsm_mncc_rtp {
uint32_t msg_type;
uint32_t callref;
diff --git a/ns/NS_Tests.fr.cfg b/ns/NS_Tests.fr.cfg
index 91fb5c5f..5e387a90 100644
--- a/ns/NS_Tests.fr.cfg
+++ b/ns/NS_Tests.fr.cfg
@@ -7,7 +7,7 @@
[LOGGING]
[MODULE_PARAMETERS]
-NS_Tests.mp_dialect := NS2_DIALECT_IPACCESS
+NS_Tests.mp_dialect := NS2_DIALECT_STATIC_RESETBLOCK
NS_Tests.mp_nsconfig := {
nsei := 2001,
role_sgsn := false,
diff --git a/ns/osmo-ns.fr.cfg b/ns/osmo-ns.fr.cfg
index d1109ab4..3f941f1b 100644
--- a/ns/osmo-ns.fr.cfg
+++ b/ns/osmo-ns.fr.cfg
@@ -25,6 +25,16 @@ line vty
bind 127.0.0.1
ns
+ timer tns-block 3
+ timer tns-block-retries 3
+ timer tns-reset 3
+ timer tns-reset-retries 3
+ timer tns-test 12
+ timer tns-alive 3
+ timer tns-alive-retries 3
+ timer tsns-prov 3
+ timer tsns-size-retries 3
+ timer tsns-config-retries 3
bind fr hdlcnet1
fr hdlcnet1 frnet
bind fr hdlcnet2
diff --git a/pcu/GPRS_Components.ttcn b/pcu/GPRS_Components.ttcn
index 10144985..d6749d7d 100644
--- a/pcu/GPRS_Components.ttcn
+++ b/pcu/GPRS_Components.ttcn
@@ -559,6 +559,21 @@ runs on MS_BTS_IFACE_CT {
}
}
+altstep as_pcuif_rx_ignore_empty(template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
+runs on MS_BTS_IFACE_CT {
+ var BTS_PDTCH_Block data_msg;
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ omit)) -> value data_msg {
+
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+}
+
altstep as_rx_fail_dummy(template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
runs on MS_BTS_IFACE_CT {
var BTS_PDTCH_Block data_msg;
diff --git a/pcu/PCU_Tests.ttcn b/pcu/PCU_Tests.ttcn
index 4b8035c5..db57755e 100644
--- a/pcu/PCU_Tests.ttcn
+++ b/pcu/PCU_Tests.ttcn
@@ -246,6 +246,15 @@ runs on RAW_PCU_Test_CT {
}
}
+private function f_pcuvty_set_timer(integer t, integer val)
+runs on RAW_PCU_Test_CT {
+ if (t >= 0) {
+ f_vty_config2(PCUVTY, {"pcu"}, "timer T" & int2str(t) & " " & int2str(val));
+ } else {
+ f_vty_config2(PCUVTY, {"pcu"}, "timer X" & int2str(t * -1) & " " & int2str(val));
+ }
+}
+
private function f_init_vty(charstring id, boolean egprs_only) runs on RAW_PCU_Test_CT {
map(self:PCUVTY, system:PCUVTY);
f_vty_set_prompts(PCUVTY);
@@ -397,6 +406,7 @@ testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
/* Make sure TBF is released and no data is sent for in after reciving a Suspend Request from that MS. See OS#4761 */
testcase TC_pcuif_suspend_active_tbf() runs on RAW_PCU_Test_CT {
var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.bvc[0].cell_id.ra_id);
+ var BTS_PDTCH_Block data_msg;
var RlcmacDlBlock dl_block;
var octetstring data := f_rnd_octstring(10);
var uint32_t sched_fn;
@@ -454,9 +464,17 @@ testcase TC_pcuif_suspend_active_tbf() runs on RAW_PCU_Test_CT {
/* Make sure we don't receive data for that TBF since it was released
* before. Also check our TBF is not polled for UL. */
- f_rx_rlcmac_dl_block_exp_dummy(dl_block);
- if (dl_block.ctrl.mac_hdr.usf != USF_UNUSED) {
- setverdict(fail, "Unexpected USF ", dl_block.ctrl.mac_hdr.usf);
+ f_pcuif_rx_data_req_pdtch(data_msg);
+ if (mp_osmo_pcu_newer_than_0_9_0 and data_msg.dl_block == omit) {
+ /* IDLE block, expected on new PCU versions */
+ } else if (not mp_osmo_pcu_newer_than_0_9_0 and match(data_msg.dl_block, tr_RLCMAC_DUMMY_CTRL())) {
+ /* Dummy RLCMAC block, expected on older PCU versions */
+ if (data_msg.dl_block.ctrl.mac_hdr.usf != USF_UNUSED) {
+ setverdict(fail, "Unexpected USF ", data_msg.dl_block.ctrl.mac_hdr.usf);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ } else {
+ setverdict(fail, "Unexpected dl_block", data_msg.dl_block);
f_shutdown(__BFILE__, __LINE__);
}
@@ -583,7 +601,7 @@ testcase TC_ta_idle_dl_tbf_ass() runs on RAW_PCU_Test_CT {
f_shutdown(__BFILE__, __LINE__, final := true);
}
-/* Verify that the PCU generates valid PTCCH/D messages
+/* Verify that the PCU generates idle blocks in PTCCH/D
* while neither Uplink nor Downlink TBF is established. */
testcase TC_ta_ptcch_idle() runs on RAW_PCU_Test_CT {
var BTS_PTCCH_Block pcu_msg;
@@ -599,10 +617,20 @@ testcase TC_ta_ptcch_idle() runs on RAW_PCU_Test_CT {
T.start(5.0);
alt {
- /* Make sure the message is encoded correctly
- * TODO: do we expect all TA values to be equal '1111111'B? */
- [] as_rx_ptcch(pcu_msg, tr_PTCCHDownlinkMsg);
-
+ [] BTS.receive(tr_PCUIF_DATA_PTCCH(0,
+ tr_PCUIF_DATA(0, 7, sapi := PCU_IF_SAPI_PTCCH),
+ omit)) {
+ if (not mp_osmo_pcu_newer_than_0_9_0) {
+ setverdict(fail, "Expected PTCCH/D block instead of IDLE block");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+ [] as_rx_ptcch(pcu_msg, tr_PTCCHDownlinkMsg) {
+ if (mp_osmo_pcu_newer_than_0_9_0) {
+ setverdict(fail, "Expected IDLE block instead of PTCCH/D block");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
[] BTS.receive(PCUIF_Message:?) { repeat; }
[] T.timeout {
setverdict(fail, "Timeout waiting for a PTCCH/D block");
@@ -1505,6 +1533,9 @@ testcase TC_n3101_max_t3169() runs on RAW_PCU_Test_CT {
block_nr := nr.blk_nr));
repeat;
}
+ /* We may already receive empty (idle) blocks before our own TTCN3 timer
+ * triggers due to the TBF being released. Keep going until our T_3169 triggers. */
+ [mp_osmo_pcu_newer_than_0_9_0 and n3101 == N3101_MAX + 1] as_pcuif_rx_ignore_empty(nr);
[] T_3169.timeout {
log("T_3169 expired");
/* Done in alt */
@@ -1603,6 +1634,7 @@ testcase TC_n3103_max_t3169() runs on RAW_PCU_Test_CT {
f_shutdown(__BFILE__, __LINE__);
}
[] as_ms_rx_ignore_dummy(ms, nr);
+ [] as_pcuif_rx_ignore_empty(nr);
[T_3169.running] T_3169.timeout {
log("T_3169 timeout");
/* Done in alt, wait for pending RTS initiated previously in
@@ -1886,6 +1918,7 @@ testcase TC_n3105_max_t3195() runs on RAW_PCU_Test_CT {
var integer N3105 := 0;
timer T_3195 := 1.0;
var integer num_poll_recv := 0;
+ var template RlcmacDlBlock dl_block_exp;
/* Initialize NS/BSSGP side */
f_init_bssgp();
@@ -1947,7 +1980,7 @@ testcase TC_n3105_max_t3195() runs on RAW_PCU_Test_CT {
repeat;
}
/* At this point in time (N3105_MAX reached), PCU already moved TBF to
- * RELEASE state so no data for it is tx'ed, hence the dummy blocks:
+ * RELEASE state so no data for it is tx'ed, hence the dummy/idle blocks:
*/
[N3105 == N3105_MAX] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
@@ -1964,14 +1997,23 @@ testcase TC_n3105_max_t3195() runs on RAW_PCU_Test_CT {
block_nr := nr.blk_nr));
repeat;
}
+ /* We may already receive idle blocks before our own TTCN3 timer
+ * triggers due to the TBF being released. Keep going until our T_3195 triggers. */
+ [mp_osmo_pcu_newer_than_0_9_0 and N3105 == N3105_MAX] as_pcuif_rx_ignore_empty(nr);
[T_3195.running] T_3195.timeout {
log("T_3195 timeout");
/* Done in alt, wait for pending RTS initiated previously in
- * above case before continuing (expect /* Dummy block): */
+ * above case before continuing (expect empty blocks on new
+ * versions, Dummy block on older versions): */
+ if (mp_osmo_pcu_newer_than_0_9_0) {
+ dl_block_exp := omit;
+ } else {
+ dl_block_exp := tr_RLCMAC_DUMMY_CTRL;
+ }
BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
- tr_RLCMAC_DUMMY_CTRL));
- }
+ dl_block_exp));
+ }
[] BTS.receive {
setverdict(fail, "Unexpected BTS message");
f_shutdown(__BFILE__, __LINE__);
@@ -1994,6 +2036,105 @@ testcase TC_n3105_max_t3195() runs on RAW_PCU_Test_CT {
f_shutdown(__BFILE__, __LINE__, final := true);
}
+/* Verify configured T3172 is properly transmitted as WAIT_INDICATION in Pkt Access Reject in PACCH. */
+function f_TC_t3172(integer t3172_ms, BIT1 wait_ind_size) runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind;
+ var template IARRestOctets rest;
+ var BIT11 ra11;
+ var GprsMS ms;
+ var octetstring data := f_rnd_octstring(10);
+ var RlcmacDlBlock dl_block;
+ var template RlcmacDlBlock rej_tmpl;
+ var uint32_t dl_fn;
+ var uint32_t sched_fn;
+ var uint8_t wait_ind_val;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ info_ind := valueof(ts_PCUIF_INFO_default);
+
+ /* Only the first TRX is enabled. */
+ f_PCUIF_PDCHMask_set(info_ind, '00000000'B, (1 .. 7));
+ f_PCUIF_PDCHMask_set(info_ind, '00000001'B, 0);
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ f_pcuvty_set_timer(3172, t3172_ms);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ var EGPRSPktChRequest req := {
+ one_phase := {
+ tag := '0'B,
+ multislot_class := '10101'B,
+ priority := '01'B,
+ random_bits := '101'B
+ }
+ };
+
+ /* We send 7 requests, the IUT gives us all available USFs (0..6) */
+ for (var integer i := 0; i < 7; i := i + 1) {
+ req.one_phase.random_bits := int2bit(f_rnd_int(8), 3);
+ f_TC_egprs_pkt_chan_req(req, tr_IMM_TBF_ASS);
+ }
+
+ /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data));
+ f_ms_exp_dl_tbf_ass_ccch(ms, PCU_IF_SAPI_PCH);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
+
+ /* ACK the DL block */
+ f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block, '1'B);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc, false, ts_ChannelReqDescription()),
+ f_dl_block_ack_fn(dl_block, dl_fn));
+
+ /* Since all USF are taken, we should receive a Reject: */
+
+ if (wait_ind_size == '0'B) {
+ wait_ind_val := t3172_ms / 1000;
+ } else {
+ wait_ind_val := t3172_ms / 20;
+ }
+ rej_tmpl := tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_ACC_REJ(tr_RlcMacDlCtrl_PKT_ACC_REJ_ID_TLLI(ms.tlli),
+ wait_ind_val, wait_ind_size));
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ alt {
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ rej_tmpl));
+ [] BTS.receive {
+ setverdict(fail, "Unexpected BTS message");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+testcase TC_t3172_wait_ind_size0() runs on RAW_PCU_Test_CT {
+ /* size=0 means value is provided in seconds. De to value being 8
+ * bit, in the 20ms step case (size=1) the maximum value possible is 20 * 255
+ * = 5100. Hence, values above it should use size=0 to be able to
+ * provide values in range. Let's use 6 seconds, 6000ms
+ */
+ f_TC_t3172(6000, '0'B);
+}
+testcase TC_t3172_wait_ind_size1() runs on RAW_PCU_Test_CT {
+ f_TC_t3172(3000, '1'B);
+}
+
/* Verify PCU handles correctly Countdown Procedure based on BS_CV_MAX */
testcase TC_countdown_procedure() runs on RAW_PCU_Test_CT {
var RlcmacDlBlock dl_block;
@@ -2344,6 +2485,22 @@ testcase TC_mo_ping_pong_with_ul_racap() runs on RAW_PCU_Test_CT {
var template (present) CodingScheme exp_dl_cs_mcs := cs_gprs_any;
f_TC_mo_ping_pong_2phase_access(c_PCUIF_Flags_noMCS, ms_racap_gprs_def, exp_ul_cs_mcs, exp_dl_cs_mcs);
+
+ if (mp_osmo_pcu_newer_than_0_9_0) {
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.pkt.ul_assignment", mtype := "c", min := 1, max := 1 }
+ };
+ f_statsd_expect(expect);
+ }
}
testcase TC_mo_ping_pong_with_ul_racap_egprs_only() runs on RAW_PCU_Test_CT {
@@ -2351,6 +2508,21 @@ testcase TC_mo_ping_pong_with_ul_racap_egprs_only() runs on RAW_PCU_Test_CT {
var template (present) CodingScheme exp_dl_cs_mcs := mcs_egprs_any;
f_TC_mo_ping_pong_2phase_access(c_PCUIF_Flags_default, ms_racap_egprs_def, exp_ul_cs_mcs, exp_dl_cs_mcs);
+ if (mp_osmo_pcu_newer_than_0_9_0) {
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.pkt.ul_assignment", mtype := "c", min := 1, max := 1 }
+ };
+ f_statsd_expect(expect);
+ }
}
testcase TC_force_two_phase_access() runs on RAW_PCU_Test_CT {
@@ -2361,6 +2533,22 @@ testcase TC_force_two_phase_access() runs on RAW_PCU_Test_CT {
var template (present) CodingScheme exp_dl_cs_mcs := cs_gprs_any;
f_TC_mo_ping_pong_2phase_access(c_PCUIF_Flags_noMCS, ms_racap_gprs_def, exp_ul_cs_mcs, exp_dl_cs_mcs);
+
+ if (mp_osmo_pcu_newer_than_0_9_0) {
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.pkt.ul_assignment", mtype := "c", min := 1, max := 1 }
+ };
+ f_statsd_expect(expect);
+ }
}
/* Test scenario where SGSN wants to send some data against MS and it is
@@ -3015,6 +3203,7 @@ testcase TC_ul_tbf_reestablish_with_pkt_resource_req() runs on RAW_PCU_Test_CT {
/* Initialize the PCU interface abstraction */
f_init_raw(testcasename());
+ f_statsd_reset();
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
@@ -3055,8 +3244,213 @@ testcase TC_ul_tbf_reestablish_with_pkt_resource_req() runs on RAW_PCU_Test_CT {
/* ACK the ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ if (mp_osmo_pcu_newer_than_0_9_0) {
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.pkt.ul_assignment", mtype := "c", min := 1, max := 1 }
+ };
+ f_statsd_expect(expect);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test scenario where MS wants to request a new TBF once the current one is
+ * ending, by means of sending a Packet Resource Request on ul slot provided by
+ * last Pkt Ul ACK's RRBP. new Pkt Ul Ass is never confirmed by the MS in this test.
+ * See 3GPP TS 44.060 sec 9.3.2.4.2 "Non-extended uplink TBF mode" */
+testcase TC_ul_tbf_reestablish_with_pkt_resource_req_n3105_max() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind;
+ var RlcmacDlBlock dl_block;
+ var octetstring data := f_rnd_octstring(10);
+ var uint32_t sched_fn;
+ var uint32_t dl_fn;
+ var template (value) TsTrxBtsNum nr;
+ var BTS_PDTCH_Block data_msg;
+ var template RlcmacDlBlock acknack_tmpl;
+ var GprsMS ms;
+ const integer N3105_MAX := 2;
+ var integer N3105 := 0;
+ timer T_3195 := 1.0 + 0.5; /* 0.5: extra offset since we cannot match exactly */
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ info_ind := valueof(ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+ /* Speedup test: */
+ info_ind.n3105 := N3105_MAX;
+ info_ind.t3195 := 1;
+ f_init_raw(testcasename(), info_ind);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Establish an Uplink TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Send one UL block (with TLLI since we are in One-Phase Access
+ contention resoultion) and make sure it is ACKED fine */
+ f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
+
+ /* UL block should be received in SGSN */
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
+
+ acknack_tmpl := tr_RLCMAC_UL_ACK_NACK_GPRS(ms.ul_tbf.tfi,
+ tr_UlAckNackGprs(ms.tlli,
+ tr_AckNackDescription(final_ack := '1'B),
+ tr_UlAckNackGprsAdditionsRel99(tbf_est := true)))
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn, acknack_tmpl);
+
+ /* TODO: verify TBF_EST and FinalACK are both '1' above */
+
+ /* Send PACKET RESOURCE REQUEST to request a new UL TBF */
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, omit)), sched_fn);
+
+ /* Now Keep ignoring the Pkt Ul Ass on PACCH: */
+ /* Now we go on receiving DL data and not answering RRBP: */
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ alt {
+ [not T_3195.running] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_UL_PACKET_ASS)) -> value data_msg {
+ if (f_dl_block_rrbp_valid(data_msg.dl_block)) {
+ log("Ignoring RRBP N3105 ", N3105);
+ N3105 := N3105 + 1;
+ }
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ /* At this point in time (N3105_MAX reached), PCU already moved TBF to
+ * RELEASE state so no data for it is tx'ed, hence the dummy blocks:
+ */
+ [N3105 == N3105_MAX] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_DUMMY_CTRL)) -> value data_msg {
+ if (not T_3195.running) {
+ T_3195.start;
+ }
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ [N3105 == N3105_MAX] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ omit)) -> value data_msg {
+ /* We may already receive idle blocks before our own TTCN3 timer
+ * triggers due to the TBF being released. Keep going until our T_3195 triggers. */
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ /* We receive Dummy blocks in between Pkt Ul Ass while PCU waits for us to ack it */
+ [not T_3195.running] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_DUMMY_CTRL)) -> value data_msg {
+ log("Ignoring Dummy block FN ", data_msg.raw.fn);
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ [T_3195.running] T_3195.timeout {
+ log("T_3195 timeout");
+ /* Done in alt, wait for pending RTS initiated previously in
+ * above case before continuing (expect nothing to be sent since there's no active TBF): */
+ BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ omit));
+ }
+ [] BTS.receive {
+ setverdict(fail, "Unexpected BTS message");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test scenario where MS wants to request a new UL TBF using a DL (EGPRS) ACK/NACK
+ * transmitted on ul slot provided by its DL TBF.
+ * See 3GPP TS 44.060 sec 9.3.2.4.2 "Non-extended uplink TBF mode" */
+function f_TC_ul_tbf_reestablish_with_pkt_dl_ack_nack(boolean use_egprs) runs on RAW_PCU_Test_CT {
+ var GprsMS ms;
+ var octetstring data := f_rnd_octstring(10);
+ var RlcmacDlBlock dl_block;
+ var template RlcmacDlBlock rej_tmpl;
+ var uint32_t dl_fn;
+ var uint32_t sched_fn;
+ var template (value) MSRadioAccessCapabilityV_BSSGP racap_tmpl;
+
+ if (use_egprs == true) {
+ racap_tmpl := bssgp_ms_racap_egprs_def;
+ } else {
+ racap_tmpl := bssgp_ms_racap_gprs_def;
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename());
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, racap_tmpl));
+ f_ms_exp_dl_tbf_ass_ccch(ms, PCU_IF_SAPI_PCH);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
+
+ /* ACK the DL block, asking for new UL TBF by including ChanReqDesc */
+ f_dltbf_ack_block(ms.dl_tbf, dl_block, '1'B);
+ f_ms_tx_ul_block(ms, f_dltbf_ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf, use_egprs, ts_ChannelReqDescription()),
+ f_dl_block_ack_fn(dl_block, dl_fn));
+
+ /* We should receive a Pkt Ul ASS */
+ f_ms_rx_pkt_ass_pacch(ms, sched_fn, tr_RLCMAC_UL_PACKET_ASS);
f_shutdown(__BFILE__, __LINE__, final := true);
}
+testcase TC_ul_tbf_reestablish_with_pkt_dl_ack_nack() runs on RAW_PCU_Test_CT {
+ f_TC_ul_tbf_reestablish_with_pkt_dl_ack_nack(false);
+}
+testcase TC_ul_tbf_reestablish_with_pkt_dl_ack_nack_egprs() runs on RAW_PCU_Test_CT {
+ f_TC_ul_tbf_reestablish_with_pkt_dl_ack_nack(true);
+}
/* Test CS paging over the BTS<->PCU socket.
* 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.
@@ -3454,16 +3848,18 @@ testcase TC_egprs_pkt_chan_req_signalling() runs on RAW_PCU_Test_CT {
var template GsmRrMessage imm_ass;
var template IaRestOctets rest;
var template EgprsUlAss ul_ass;
+ const integer num_req := 6;
/* Initialize the PCU interface abstraction */
f_init_raw(testcasename());
+ f_statsd_reset();
var EGPRSPktChRequest req := {
/* NOTE: other fields are set in the loop */
signalling := { tag := '110011'B }
};
- for (var integer i := 0; i < 6; i := i + 1) {
+ for (var integer i := 0; i < num_req; i := i + 1) {
var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
req.signalling.random_bits := ext_ra;
@@ -3475,6 +3871,21 @@ testcase TC_egprs_pkt_chan_req_signalling() runs on RAW_PCU_Test_CT {
f_TC_egprs_pkt_chan_req(req, imm_ass);
}
+ if (mp_osmo_pcu_newer_than_0_9_0) {
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 }
+ };
+ f_statsd_expect(expect);
+ }
+
f_shutdown(__BFILE__, __LINE__, final := true);
}
@@ -3482,16 +3893,18 @@ testcase TC_egprs_pkt_chan_req_one_phase() runs on RAW_PCU_Test_CT {
var template GsmRrMessage imm_ass;
var template IaRestOctets rest;
var template EgprsUlAss ul_ass;
+ const integer num_req := 6;
/* Initialize the PCU interface abstraction */
f_init_raw(testcasename());
+ f_statsd_reset();
var EGPRSPktChRequest req := {
/* NOTE: other fields are set in the loop */
one_phase := { tag := '0'B }
};
- for (var integer i := 0; i < 6; i := i + 1) {
+ for (var integer i := 0; i < num_req; i := i + 1) {
var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
var BIT5 mslot_class := int2bit(f_rnd_int(32), 5);
var BIT2 priority := substr(ext_ra, 0, 2);
@@ -3509,6 +3922,21 @@ testcase TC_egprs_pkt_chan_req_one_phase() runs on RAW_PCU_Test_CT {
f_TC_egprs_pkt_chan_req(req, imm_ass);
}
+ if (mp_osmo_pcu_newer_than_0_9_0) {
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 }
+ };
+ f_statsd_expect(expect);
+ }
+
f_shutdown(__BFILE__, __LINE__, final := true);
}
@@ -3516,16 +3944,18 @@ testcase TC_egprs_pkt_chan_req_two_phase() runs on RAW_PCU_Test_CT {
var template GsmRrMessage imm_ass;
var template IaRestOctets rest;
var template EgprsUlAss ul_ass;
+ const integer num_req := 6;
/* Initialize the PCU interface abstraction */
f_init_raw(testcasename());
+ f_statsd_reset();
var EGPRSPktChRequest req := {
/* NOTE: other fields are set in the loop */
two_phase := { tag := '110000'B }
};
- for (var integer i := 0; i < 6; i := i + 1) {
+ for (var integer i := 0; i < num_req; i := i + 1) {
var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
var BIT2 priority := substr(ext_ra, 0, 2);
var BIT3 rand := substr(ext_ra, 2, 3);
@@ -3541,6 +3971,21 @@ testcase TC_egprs_pkt_chan_req_two_phase() runs on RAW_PCU_Test_CT {
f_TC_egprs_pkt_chan_req(req, imm_ass);
}
+ if (mp_osmo_pcu_newer_than_0_9_0) {
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 }
+ };
+ f_statsd_expect(expect);
+ }
+
f_shutdown(__BFILE__, __LINE__, final := true);
}
@@ -3593,11 +4038,13 @@ runs on RAW_PCU_Test_CT {
testcase TC_egprs_pkt_chan_req_reject_content() runs on RAW_PCU_Test_CT {
var template IARRestOctets rest;
var BIT5 ext_ra;
+ const integer num_req := 6;
/* Initialize the PCU interface abstraction */
f_init_raw(testcasename());
+ f_statsd_reset();
- for (var integer i := 0; i < 6; i := i + 1) {
+ for (var integer i := 0; i < num_req; i := i + 1) {
ext_ra := int2bit(f_rnd_int(32), 5); /* 5 LSB's of RA11 */
rest := tr_IARRestOctets({ *, tr_ExtRAOpt(ext_ra), * });
@@ -3605,6 +4052,20 @@ testcase TC_egprs_pkt_chan_req_reject_content() runs on RAW_PCU_Test_CT {
f_TC_egprs_pkt_chan_req_reject('111111'B & ext_ra, 1337 + i, rest);
}
+ if (mp_osmo_pcu_newer_than_0_9_0) {
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.unexpected", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_rej", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 }
+ };
+ f_statsd_expect(expect);
+ }
+
f_shutdown(__BFILE__, __LINE__, final := true);
}
@@ -3614,16 +4075,18 @@ testcase TC_egprs_pkt_chan_req_reject_emergency() runs on RAW_PCU_Test_CT {
var template IARRestOctets rest;
var BIT5 ext_ra;
var BIT11 ra11;
+ const integer num_req := 6;
/* Initialize the PCU interface abstraction */
f_init_raw(testcasename());
+ f_statsd_reset();
var EGPRSPktChRequest req := {
/* NOTE: other fields are set in the loop */
emergency := { tag := '110111'B }
};
- for (var integer i := 0; i < 6; i := i + 1) {
+ for (var integer i := 0; i < num_req; i := i + 1) {
ext_ra := int2bit(f_rnd_int(32), 5); /* 5 LSB's of RA11 */
rest := tr_IARRestOctets({ *, tr_ExtRAOpt(ext_ra), * });
@@ -3634,6 +4097,20 @@ testcase TC_egprs_pkt_chan_req_reject_emergency() runs on RAW_PCU_Test_CT {
f_TC_egprs_pkt_chan_req_reject(ra11, 1337 + i, rest);
}
+ if (mp_osmo_pcu_newer_than_0_9_0) {
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.unexpected", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_rej", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 }
+ };
+ f_statsd_expect(expect);
+ }
+
f_shutdown(__BFILE__, __LINE__, final := true);
}
@@ -3652,6 +4129,7 @@ testcase TC_egprs_pkt_chan_req_reject_exhaustion() runs on RAW_PCU_Test_CT {
/* Initialize the PCU interface abstraction */
f_init_raw(testcasename(), info_ind);
+ f_statsd_reset();
var EGPRSPktChRequest req := {
one_phase := {
@@ -3675,6 +4153,23 @@ testcase TC_egprs_pkt_chan_req_reject_exhaustion() runs on RAW_PCU_Test_CT {
/* At this point, the IUT should run out of free USFs */
f_TC_egprs_pkt_chan_req_reject(ra11, 1870, rest, wi := info_ind.t3142);
+ if (mp_osmo_pcu_newer_than_0_9_0) {
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := 8, max := 8 },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := 8, max := 8 },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 8, max := 8 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.unexpected", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := 7, max := 7 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := 7, max := 7 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_rej", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 }
+ };
+ f_statsd_expect(expect);
+ }
+
f_shutdown(__BFILE__, __LINE__, final := true);
}
@@ -5968,12 +6463,13 @@ testcase TC_rim_ran_info_req_single_rep_no_si() runs on RAW_PCU_Test_CT {
f_shutdown(__BFILE__, __LINE__, final := true);
}
-/* Verify TRX!=C0 don't schedule rlcmac blocks if no TBF attached to it. See OS#4772, SYS#4919 */
+/* Verify PCU schedule idle blocks (len=0) if no TBF attached to it. See OS#4772, SYS#4919 */
testcase TC_pdch_energy_saving() runs on RAW_PCU_Test_CT {
var PCUIF_info_ind info_ind;
var template (value) TsTrxBtsNum nr;
var RlcmacDlBlock dl_block;
var BTS_PDTCH_Block data_msg;
+ var integer ts;
timer T;
/* Initialize NS/BSSGP side */
@@ -5991,25 +6487,30 @@ testcase TC_pdch_energy_saving() runs on RAW_PCU_Test_CT {
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- /* Verify C0 gets always dummy blocks: */
- nr := ts_TsTrxBtsNum(ts_nr := 7, trx_nr := 0, bts_nr := 0, blk_nr := 0);
- f_rx_rlcmac_dl_block_exp_dummy(dl_block, nr := nr);
+ for (ts := 0; ts < 2; ts := ts + 1) {
+ nr := ts_TsTrxBtsNum(ts_nr := 7, trx_nr := ts, bts_nr := 0, blk_nr := 0);
- /* TRX1 doesn't send dummy blocks when not needed, in order to honour energy saving: */
- nr.trx_nr := 1;
- BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
- sapi := PCU_IF_SAPI_PDTCH, fn := 0,
- arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)), block_nr := nr.blk_nr));
- T.start(0.5);
- alt {
- [] as_rx_fail_dummy(nr);
- [] BTS.receive {
- setverdict(fail, "Unexpected block from BTS");
- f_shutdown(__BFILE__, __LINE__);
- }
- [] T.timeout {
- setverdict(pass);
- }
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)), block_nr := nr.blk_nr));
+ T.start(0.5);
+ alt {
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ omit)) -> value data_msg {
+ setverdict(pass);
+ T.stop;
+ }
+ [] as_rx_fail_dummy(nr);
+ [] BTS.receive {
+ setverdict(fail, "Unexpected block from BTS");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ [] T.timeout {
+ setverdict(fail, "Expected IDLE block from BTS");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
}
f_shutdown(__BFILE__, __LINE__, final := true);
@@ -6165,6 +6666,53 @@ testcase TC_stat_pdch_avail_occ_ms_not_known_egprs() runs on RAW_PCU_Test_CT {
f_tc_stat_pdch_avail_occ_ms_not_known(true);
}
+/* Make sure that bts.0.pdch.all_allocated is set when we allocate all resources */
+testcase TC_ratectr_all_available_allocated() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind;
+ var template IARRestOctets rest;
+ var BIT11 ra11;
+
+ info_ind := valueof(ts_PCUIF_INFO_default);
+
+ /* Only the first TRX is enabled. */
+ f_PCUIF_PDCHMask_set(info_ind, '00000000'B, (1 .. 7));
+ f_PCUIF_PDCHMask_set(info_ind, '00000001'B, 0);
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+ f_statsd_reset();
+
+ var EGPRSPktChRequest req := {
+ one_phase := {
+ tag := '0'B,
+ multislot_class := '10101'B,
+ priority := '01'B,
+ random_bits := '101'B
+ }
+ };
+
+ /* We send 7 requests, the IUT gives us all available USFs (0..6) */
+ for (var integer i := 0; i < 7; i := i + 1) {
+ req.one_phase.random_bits := int2bit(f_rnd_int(8), 3);
+ f_TC_egprs_pkt_chan_req(req, tr_IMM_TBF_ASS);
+ }
+
+ ra11 := enc_EGPRSPktChRequest2bits(req);
+ rest := tr_IARRestOctets({ *, tr_ExtRAOpt(substr(ra11, 6, 5)), * });
+
+ /* At this point, the IUT should run out of free USFs */
+ f_TC_egprs_pkt_chan_req_reject(ra11, 1870, rest);
+
+ /* bts.0.pdch.all_allocated is updated once per second, wait some time to make sure it was updated. */
+ f_sleep(2.0);
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.pdch.all_allocated", mtype := "c", min := 1, max := 1 }
+ };
+ f_statsd_expect(expect);
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
control {
execute( TC_pcuif_suspend() );
execute( TC_pcuif_suspend_active_tbf() );
@@ -6190,6 +6738,8 @@ control {
execute( TC_zero_x2031_t3191() );
execute( TC_t3193() );
execute( TC_n3105_max_t3195() );
+ execute( TC_t3172_wait_ind_size0() );
+ execute( TC_t3172_wait_ind_size1() );
execute( TC_countdown_procedure() );
execute( TC_ul_all_sizes() );
execute( TC_ul_data_toolong_fills_padding() );
@@ -6243,6 +6793,9 @@ control {
execute( TC_dl_multislot_tbf_ms_class_from_2phase() );
execute( TC_ul_multislot_tbf_ms_class_from_2phase() );
execute( TC_ul_tbf_reestablish_with_pkt_resource_req() );
+ execute( TC_ul_tbf_reestablish_with_pkt_resource_req_n3105_max() );
+ execute( TC_ul_tbf_reestablish_with_pkt_dl_ack_nack() );
+ execute( TC_ul_tbf_reestablish_with_pkt_dl_ack_nack_egprs() );
execute( TC_multiplex_dl_gprs_egprs() );
@@ -6278,6 +6831,7 @@ control {
execute( TC_stat_pdch_avail_occ() );
execute( TC_stat_pdch_avail_occ_ms_not_known_gprs() );
execute( TC_stat_pdch_avail_occ_ms_not_known_egprs() );
+ execute( TC_ratectr_all_available_allocated() );
}
}
diff --git a/sccp/SCCP_Tests_RAW.ttcn b/sccp/SCCP_Tests_RAW.ttcn
index 1ac82a2b..5013ddf3 100644
--- a/sccp/SCCP_Tests_RAW.ttcn
+++ b/sccp/SCCP_Tests_RAW.ttcn
@@ -310,6 +310,31 @@ testcase TC_it_avoids_tiar() runs on SCCP_Test_RAW_CT {
}
}
+private function f_tx_xudt_exp(SCCP_PAR_Address calling, SCCP_PAR_Address called, octetstring data) runs on SCCP_Test_RAW_CT {
+ var template PDU_SCCP exp_rx;
+ f_send_sccp(ts_SCCP_XUDT(calling, called, data));
+ exp_rx := (tr_SCCP_UDT(called, calling, data), tr_SCCP_XUDT(called, calling, data));
+ f_exp_sccp(exp_rx);
+}
+
+/* Test if the IUT SCCP code processes an XUDT [treat it like UDT] and answers back. */
+testcase TC_process_rx_xudt() runs on SCCP_Test_RAW_CT {
+ var SCCP_PAR_Address calling, called;
+ var octetstring data := f_rnd_octstring(f_rnd_int(100));
+
+ f_init_raw(mp_sccp_cfg[0]);
+ f_sleep(1.0);
+
+ called := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].peer_pc, mp_sccp_cfg[0].peer_ssn,
+ mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
+ calling := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].own_pc, mp_sccp_cfg[0].own_ssn,
+ mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
+
+ /* Make sure an XUDT is echoed back just like an UDT */
+ f_tx_xudt_exp(calling, called, data);
+ setverdict(pass);
+}
+
function f_scmg_xceive(SCCP_PAR_Address calling, SCCP_PAR_Address called,
template (value) PDU_SCMG_message tx,
template (omit) PDU_SCMG_message rx_exp,
@@ -429,6 +454,7 @@ control {
execute( TC_udt_without_cr_cc() );
execute( TC_tiar_timeout() );
execute( TC_it_avoids_tiar() );
+ execute( TC_process_rx_xudt() );
execute( TC_scmg_sst_ssn1() );
execute( TC_scmg_sst_ssn_valid() );