bts: f_est_dchan: verify Chan Rqd originated by RACH arrives on RSL
We cannot notify RSL Emulation layer about expecting a specific FN
(during ts_RSLDC_ChanRqd) because we only know the FN after sending the
RACH request, and since notification to RSL Emulation happens async, it
can happen (verified) that ChanRqd message from BTS arrives and is
handled before we register the RACH req into the ConnectionTable.
Change-Id: I438fd3ee82d88498d928dbcc89ce9bd80d37ab64
diff --git a/bts/BTS_Tests.ttcn b/bts/BTS_Tests.ttcn
index 5b073ef..64c2510 100644
--- a/bts/BTS_Tests.ttcn
+++ b/bts/BTS_Tests.ttcn
@@ -1344,6 +1344,28 @@
}
}
+/* Send RACH request through l1CTL and wait for ChanReq on RSL BST->BSC */
+private function f_rach_req_wait_chan_rqd(integer ra) runs on ConnHdlr return GsmFrameNumber {
+ var GsmFrameNumber fn;
+ timer T := 8.0;
+
+ /* advertise to RSL Emulation that we expect to receive confirmation from RACH */
+ RSL.send(ts_RSLDC_ChanRqd_anyFN(int2oct(ra,1)));
+
+ f_L1CTL_PARAM(L1CTL, g_pars.l1_pars.ms_actual_ta, g_pars.l1_pars.ms_power_level);
+ /* Send the actual RACH */
+ fn := f_L1CTL_RACH(L1CTL, ra);
+
+ T.start;
+ alt {
+ [] RSL.receive(tr_RSL_CHAN_RQD(int2oct(ra,1), fn)) { setverdict(pass, "Received CHAN-RQD from RACH REQ") }
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Timeout waiting for CHAN-RQD from RACH REQ <", ra, ", ", fn, ">"));
+ }
+ }
+ T.stop
+ return fn;
+}
/* Establish dedicated channel: L1CTL + RSL side */
private function f_est_dchan(boolean encr_enable := false) runs on ConnHdlr {
@@ -1351,10 +1373,8 @@
var ImmediateAssignment imm_ass;
var integer ra := 23;
- f_L1CTL_PARAM(L1CTL, g_pars.l1_pars.ms_actual_ta, g_pars.l1_pars.ms_power_level);
- fn := f_L1CTL_RACH(L1CTL, ra);
- /* This arrives on CCHAN, so we cannot test for receiving CHAN RQDhere */
- //RSL.receive(tr_RSL_CHAN_RQD(int2oct(23,1)));
+ /* 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);
diff --git a/library/RSL_Emulation.ttcn b/library/RSL_Emulation.ttcn
index cf02d00..cdeca74 100644
--- a/library/RSL_Emulation.ttcn
+++ b/library/RSL_Emulation.ttcn
@@ -47,14 +47,19 @@
type record RSLDC_ChanRqd {
OCT1 ra,
- GsmFrameNumber fn
+ GsmFrameNumber fn optional
};
-template RSLDC_ChanRqd ts_RSLDC_ChanRqd(OCT1 ra, GsmFrameNumber fn) := {
+template (value) RSLDC_ChanRqd ts_RSLDC_ChanRqd(OCT1 ra, GsmFrameNumber fn) := {
ra := ra,
fn := fn
}
+template (value) RSLDC_ChanRqd ts_RSLDC_ChanRqd_anyFN(OCT1 ra) := {
+ ra := ra,
+ fn := omit
+}
+
type port RSL_DCHAN_PT message {
inout RSLDC_ChanRqd, RSL_Message;
} with { extension "internal" };
@@ -183,15 +188,36 @@
return -1;
}
+/* Matches by only RA if FN is ommited in one of the connections allocated */
+private function f_cid_by_ra_fn2(OCT1 ra, RSL_IE_FrameNumber fn)
+runs on RSL_Emulation_CT return integer {
+ var integer i;
+ for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ispresent(ConnectionTable[i].ra) and
+ ConnectionTable[i].ra == ra) {
+ if (not ispresent(ConnectionTable[i].ra_fn) or
+ fn == valueof(ts_RSL_IE_FrameNumber(ConnectionTable[i].ra_fn))) {
+ return i;
+ }
+ }
+ }
+ log("No Dchan handler for ", ra, fn);
+ return -1;
+}
+
/* create an ew client with given RA and FN */
-private function f_cid_create(OCT1 ra, GsmFrameNumber fn, RSL_DchanHdlr comp_ref)
+private function f_cid_create(OCT1 ra, template (omit) GsmFrameNumber fn, RSL_DchanHdlr comp_ref)
runs on RSL_Emulation_CT {
var integer i;
for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
if (not ispresent(ConnectionTable[i].ra) and
not ispresent(ConnectionTable[i].trx_nr)) {
ConnectionTable[i].ra := ra;
- ConnectionTable[i].ra_fn := fn;
+ if (ispresent(fn)) {
+ ConnectionTable[i].ra_fn := valueof(fn);
+ } else {
+ ConnectionTable[i].ra_fn := omit;
+ }
ConnectionTable[i].comp_ref := comp_ref;
return;
}
@@ -394,6 +420,17 @@
}
}
}
+ [not bts_role] IPA_PT.receive(tr_RSL(tr_RSL_CHAN_RQD(?))) -> value rx_rsl {
+ var RSL_IE_RequestRef req_ref;
+ req_ref := rx_rsl.rsl.ies[1].body.req_ref;
+ cid := f_cid_by_ra_fn2(req_ref.ra, req_ref.frame_nr);
+ if (cid != -1) {
+ CLIENT_PT.send(rx_rsl.rsl) to ConnectionTable[cid].comp_ref;
+ f_cid_clear(cid);
+ } else {
+ CCHAN_PT.send(rx_rsl);
+ }
+ }
[bts_role] IPA_PT.receive(tr_RSL(tr_RSL_PAGING_CMD(?, ?))) -> value rx_rsl {
/* broadcast to all clients? */
@@ -446,6 +483,11 @@
ts_RSL_CHAN_RQD(chan_rqd.ra, chan_rqd.fn)));
}
+ [not bts_role] CLIENT_PT.receive(RSLDC_ChanRqd:?) -> value chan_rqd sender vc_conn {
+ /* Store the knowledge that this sender has requested a certain RQ+time */
+ f_cid_create(chan_rqd.ra, chan_rqd.fn, vc_conn);
+ }
+
[] CLIENT_PT.receive(tr_RSL_MsgType(?)) -> value rx_rsl_msg sender vc_conn {
/* forward to BSC */
cid := f_cid_by_comp_ref(vc_conn);