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/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);