pcu: Implement ACKing EGPRS Dl TBF blocks
Change-Id: I9f1b621a8365e69d2e1a33d59cb8c7a59639ad94
diff --git a/library/RLCMAC_Templates.ttcn b/library/RLCMAC_Templates.ttcn
index e6f982f..d59c74e 100644
--- a/library/RLCMAC_Templates.ttcn
+++ b/library/RLCMAC_Templates.ttcn
@@ -361,8 +361,16 @@
}
}
+ private function f_presence_bit_chreq_desc(template (omit) ChannelReqDescription chreq_desc) return BIT1 {
+ if (istemplatekind(chreq_desc, "omit")) {
+ return '0'B;
+ }
+ return '1'B;
+ }
+
/* Send Template for Downlink ACK/NACK */
- template RlcmacUlBlock ts_RLCMAC_DL_ACK_NACK(template uint5_t tfi, AckNackDescription andesc, boolean retry := false) := {
+ template RlcmacUlBlock ts_RLCMAC_DL_ACK_NACK(template uint5_t tfi, AckNackDescription andesc, boolean retry := false,
+ template (omit) ChannelReqDescription chreq_desc := omit) := {
ctrl := {
mac_hdr := {
payload_type := MAC_PT_RLCMAC_NO_OPT,
@@ -375,8 +383,8 @@
dl_ack_nack := {
dl_tfi := tfi,
ack_nack_desc := andesc,
- chreq_desc_presence := '0'B,
- chreq_desc := omit,
+ chreq_desc_presence := f_presence_bit_chreq_desc(chreq_desc),
+ chreq_desc := chreq_desc,
ch_qual_rep := c_ChQualRep_default
}
}
@@ -384,25 +392,9 @@
}
}
- template RlcmacUlBlock ts_RLCMAC_DL_ACK_NACK_CHREQ(template uint5_t tfi,
- AckNackDescription andesc,
- boolean retry := false,
- template ChannelReqDescription chreq_desc := c_ChReqDesc_default)
- modifies ts_RLCMAC_DL_ACK_NACK := {
- ctrl := {
- payload := {
- u := {
- dl_ack_nack := {
- chreq_desc_presence := '1'B,
- chreq_desc := chreq_desc
- }
- }
- }
- }
- }
-
/* Send Template for Egprs Downlink ACK/NACK */
- template RlcmacUlBlock ts_RLCMAC_DL_ACK_NACK_EGPRS(template uint5_t tfi, EgprsAckNackDescription andesc, boolean retry := false) := {
+ template RlcmacUlBlock ts_RLCMAC_DL_ACK_NACK_EGPRS(template uint5_t tfi, EgprsAckNackDescription andesc, boolean retry := false,
+ template (omit) ChannelReqDescription chreq_desc := omit) := {
ctrl := {
mac_hdr := {
payload_type := MAC_PT_RLCMAC_NO_OPT,
@@ -417,8 +409,8 @@
ms_oom := '0'B,
egprs_ch_qual_rep_presence := '0'B,
egprs_ch_qual_rep := omit,
- chreq_desc_presence := '0'B,
- chreq_desc := omit,
+ chreq_desc_presence := f_presence_bit_chreq_desc(chreq_desc),
+ chreq_desc := chreq_desc,
pfi_presence := '0'B,
pfi := omit,
epdan_presence := '0'B,
diff --git a/pcu/GPRS_Components.ttcn b/pcu/GPRS_Components.ttcn
index 51c5a8d..0850a3d 100644
--- a/pcu/GPRS_Components.ttcn
+++ b/pcu/GPRS_Components.ttcn
@@ -77,7 +77,8 @@
uint5_t tfi,
GsmArfcn arfcn optional,
BIT8 ts_mask,
- AckNackDescription acknack_desc
+ AckNackDescription acknack_desc,
+ EgprsAckNackDescription egprs_acknack_desc
};
type union PacketUlAssignChan {
@@ -117,6 +118,15 @@
receive_block_bitmap := '0000000000000000000000000000000000000000000000000000000000000000'B
}
+template EgprsAckNackDescription t_EgprsAckNackDescription_init := {
+ final_ack := '0'B,
+ begin_window := '1'B,
+ end_window := '1'B,
+ starting_seq_nr := 1,
+ compressed := '0'B,
+ urbb := '0000000000000000000000000000000000000000000000000000000000000000'B
+}
+
const uint3_t USF_UNUSED := 7; /* used to indicate PRACH */
template (value) GprsMS t_GprsMS_def := {
@@ -137,7 +147,8 @@
tfi := 0,
arfcn := omit,
ts_mask := '00000000'B,
- acknack_desc := t_AckNackDescription_init
+ acknack_desc := t_AckNackDescription_init,
+ egprs_acknack_desc := t_EgprsAckNackDescription_init
};
template (value) UlTbf t_UlTbf_def := {
@@ -401,10 +412,34 @@
return n;
}
+function f_dltbf_ack_block(inout DlTbf dl_tbf, RlcmacDlBlock dl_block, BIT1 final_ack := '0'B)
+runs on MS_BTS_IFACE_CT {
+ var boolean is_egprs := ischosen(dl_block.data_egprs);
+ if (is_egprs) {
+ f_egprs_acknackdesc_ack_block(dl_tbf.egprs_acknack_desc, dl_block, final_ack);
+ } else {
+ f_acknackdesc_ack_block(dl_tbf.acknack_desc, dl_block, final_ack);
+ }
+}
+
+function f_dltbf_ts_RLCMAC_DL_ACK_NACK(DlTbf dl_tbf, boolean use_egprs := false,
+ template ChannelReqDescription chreq_desc := omit)
+runs on MS_BTS_IFACE_CT return template RlcmacUlBlock {
+ if (use_egprs) {
+ return ts_RLCMAC_DL_ACK_NACK_EGPRS(dl_tbf.tfi, dl_tbf.egprs_acknack_desc, false, chreq_desc);
+ } else {
+ return ts_RLCMAC_DL_ACK_NACK(dl_tbf.tfi, dl_tbf.acknack_desc, false, chreq_desc);
+ }
+}
+
function f_ultbf_inc_bsn(inout UlTbf ul_tbf)
runs on MS_BTS_IFACE_CT {
ul_tbf.bsn := ul_tbf.bsn + 1;
- ul_tbf.bsn := ul_tbf.bsn mod 128; /* FIXME: EGPRS SNS: 2048 */
+ if (ul_tbf.is_egprs) {
+ ul_tbf.bsn := ul_tbf.bsn mod 2048;
+ } else {
+ ul_tbf.bsn := ul_tbf.bsn mod 128;
+ }
}
function f_ultbf_next_ts(UlTbf ul_tbf)
@@ -640,12 +675,7 @@
var uint7_t bsn;
var integer i;
var integer inc;
-
- if (ischosen(dl_block.data)) {
- bsn := dl_block.data.mac_hdr.hdr_ext.bsn;
- } else {
- bsn := dl_block.data_egprs.mac_hdr.bsn1;
- }
+ bsn := dl_block.data.mac_hdr.hdr_ext.bsn;
/* Filling hole? */
if (bsn < desc.starting_seq_nr) {
@@ -675,6 +705,53 @@
desc.final_ack := final_ack;
}
+/* TS 44.060 sec 12.3 Ack/Nack Description */
+function f_egprs_acknackdesc_ack_block(inout EgprsAckNackDescription desc, RlcmacDlBlock dl_block, BIT1 final_ack := '0'B)
+{
+ var uint11_t bsn;
+ var integer i;
+ var integer inc;
+ var integer n := 0;
+ var integer v_q := (desc.starting_seq_nr + 2047) mod 2048; /* SSN = V(Q) + 1 */
+
+ bsn := dl_block.data_egprs.mac_hdr.bsn1;
+
+ /* Repetition? */
+ if (bsn < v_q) {
+ /* Filling hole, wraparound: */
+ if (bsn - v_q > lengthof(desc.urbb)) {
+ desc.urbb[lengthof(desc.urbb) - (v_q + (2048 - bsn))] := int2bit(1, 1);
+ return;
+ }
+ return;
+ }
+
+ inc := bsn - v_q + 1;
+ desc.urbb[lengthof(desc.urbb) - inc] := int2bit(1, 1);
+
+ for (i := lengthof(desc.urbb) - 1; i >= lengthof(desc.urbb) - inc; i := i - 1) {
+ if (desc.urbb[i] == '0'B) {
+ break;
+ }
+ n := n + 1;
+ }
+
+ if (n > 0) {
+ /* SSN is increased, and so RBB values need to be moved */
+ for (i := lengthof(desc.urbb) - 1; i >= n; i := i - 1) {
+ desc.urbb[i] := desc.urbb[i - n];
+ }
+ for (i := n - 1; i >= 0; i := i - 1) {
+ desc.urbb[i] := int2bit(0, 1);
+ }
+
+ desc.starting_seq_nr := (desc.starting_seq_nr + n) mod 2048;
+ }
+
+ /* Finally update the final_ack bit as requested: */
+ desc.final_ack := final_ack;
+}
+
/* This function can be used to send DATA.cnf in response to the IUT originated DATA.req.
* NOTE: it's the responsibility of caller to make sure that pcu_msg contains u.data_req. */
function f_pcuif_tx_data_cnf(in PCUIF_Message pcu_msg)
@@ -1037,6 +1114,17 @@
return f_rrbp_ack_fn(dl_fn, rrbp);
}
+function f_dl_block_rrbp_valid(in RlcmacDlBlock dl_block)
+runs on MS_BTS_IFACE_CT return boolean {
+ if (ischosen(dl_block.data_egprs)) {
+ return dl_block.data_egprs.mac_hdr.esp != '00'B;
+ } else if (ischosen(dl_block.data)) {
+ return dl_block.data.mac_hdr.mac_hdr.rrbp_valid;
+ } else {
+ return dl_block.ctrl.mac_hdr.rrbp_valid;
+ }
+}
+
/* Return true if a given Packet Paging Request contains the given IMSI, false otherwise */
function f_pkt_paging_match_imsi(in PacketPagingReq req, template hexstring imsi,
boolean cs_domain := true, boolean ps_domain := true)
diff --git a/pcu/PCU_Tests.ttcn b/pcu/PCU_Tests.ttcn
index 779d430..3cbc732 100644
--- a/pcu/PCU_Tests.ttcn
+++ b/pcu/PCU_Tests.ttcn
@@ -1143,8 +1143,8 @@
f_rx_rlcmac_dl_block_exp_data(dl_block, poll_fn, data, 0, exp_dl_cs_mcs);
/* 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),
+ 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, ischosen(dl_block.data_egprs)),
f_dl_block_ack_fn(dl_block, poll_fn));
f_shutdown(__BFILE__, __LINE__, final := true);
@@ -1584,8 +1584,8 @@
f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0, exp_dl_cs_mcs);
/* 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.ul_tbf.tfi, ms.dl_tbf.acknack_desc),
+ 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, ischosen(dl_block.data_egprs)),
f_dl_block_ack_fn(dl_block, dl_fn));
f_shutdown(__BFILE__, __LINE__, final := true);
@@ -1668,8 +1668,8 @@
f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0, exp_cs_mcs);
/* ACK the DL block, and request UL TBF at the same time */
- f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block, '1'B);
- f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK_CHREQ(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc),
+ 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, ischosen(dl_block.data_egprs), c_ChReqDesc_default),
f_dl_block_ack_fn(dl_block, dl_fn));
/* Expect UL ass */