pcu: Take into account TbfStartingTime
New versions of osmo-pcu will validate the Pkt Resource Request is sent
on the correct FN, so we must send first UL block exactly when
requested.
Change-Id: I6dad0f3167ace8d4a763fed971db94f32faf6ced
diff --git a/pcu/GPRS_Components.ttcn b/pcu/GPRS_Components.ttcn
index 57cd837..d3ace4d 100644
--- a/pcu/GPRS_Components.ttcn
+++ b/pcu/GPRS_Components.ttcn
@@ -96,7 +96,8 @@
uint3_t usf[8],
boolean is_egprs,
uint14_t bsn,
- CodingScheme tx_cs_mcs
+ CodingScheme tx_cs_mcs,
+ GsmFrameNumber start_time_fn
};
type record GprsMS {
@@ -160,7 +161,8 @@
usf := { USF_UNUSED, USF_UNUSED, USF_UNUSED, USF_UNUSED, USF_UNUSED, USF_UNUSED, USF_UNUSED, USF_UNUSED },
is_egprs := false,
bsn := 0,
- tx_cs_mcs := CS_1
+ tx_cs_mcs := CS_1,
+ start_time_fn := 0
};
type component MS_BTS_IFACE_CT {
@@ -233,6 +235,12 @@
return mp_base_arfcn + trx_nr;
}
+/* 3GPP TS 44.018 10.5.2.38 Starting Time */
+function f_tbf_starting_time_2_fn_mod_42432(TbfStartingTime st)
+runs on MS_BTS_IFACE_CT return GsmFrameNumber {
+ return 51 * ((st.t3 - st.t2) mod 26) + st.t3 + 51 * 26 * st.t1;
+}
+
function f_ultbf_new_from_rr_imm_ass(in GsmRrMessage rr_imm_ass)
runs on MS_BTS_IFACE_CT return UlTbf {
var UlTbf ul_tbf := valueof(t_UlTbf_def);
@@ -254,8 +262,11 @@
ul_tbf.tfi := ul_tbf.ass.ccch.dynamic.tfi_assignment;
ul_tbf.tx_cs_mcs := f_rlcmac_block_ChCodingCommand2cs_mcs(ul_tbf.ass.ccch.dynamic.ch_coding_cmd);
ul_tbf.usf[tn_allocated] := ul_tbf.ass.ccch.dynamic.usf;
+ if (ul_tbf.ass.ccch.dynamic.tbf_starting_time_present == '1'B) {
+ ul_tbf.start_time_fn := f_tbf_starting_time_2_fn_mod_42432(ul_tbf.ass.ccch.dynamic.tbf_starting_time);
+ }
} else if (match(ul_tbf.ass.ccch, tr_PacketUlSglAssign)) {
- /* Nothing to do here yet */
+ ul_tbf.start_time_fn := f_tbf_starting_time_2_fn_mod_42432(ul_tbf.ass.ccch.single.tbf_starting_time);
}
} else if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_EGPRSULAss(?)))) {
ul_tbf.ass.ccch_egprs := rr_imm_ass.payload.imm_ass.rest_octets.lh.egprs_ul;
@@ -265,7 +276,11 @@
ul_tbf.tfi := ul_tbf.ass.ccch_egprs.dynamic.tfi_assignment;
ul_tbf.tx_cs_mcs := f_rlcmac_block_EgprsChCodingCommand2cs_mcs(ul_tbf.ass.ccch_egprs.dynamic.egprs_ch_coding_cmd);
ul_tbf.usf[tn_allocated] := ul_tbf.ass.ccch_egprs.dynamic.usf;
+ if (ul_tbf.ass.ccch_egprs.dynamic.tbf_starting_time_present == '1'B) {
+ ul_tbf.start_time_fn := f_tbf_starting_time_2_fn_mod_42432(ul_tbf.ass.ccch_egprs.dynamic.tbf_starting_time);
+ }
} else if (match(ul_tbf.ass.ccch_egprs, tr_EgprsUlAssMultiblock)) {
+ ul_tbf.start_time_fn := f_tbf_starting_time_2_fn_mod_42432(ul_tbf.ass.ccch_egprs.multiblock.tbf_starting_time);
/* Nothing to do here yet */
}
} else {
@@ -661,7 +676,7 @@
/* Send random payload for last "num_blocks" blocks in Ul TBF (ending with CV=0). */
function f_ms_tx_ul_data_block_multi(inout GprsMS ms, integer num_blocks := 1, boolean with_tlli := false,
- template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
+ uint32_t fn := 0, template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
runs on MS_BTS_IFACE_CT return octetstring {
var octetstring total_payload := ''O;
var uint32_t payload_fill_len := f_ultbf_payload_fill_length(ms.ul_tbf, with_tlli, 0);
@@ -673,7 +688,12 @@
if (cv > g_bs_cv_max) {
cv := 15;
}
- f_ms_tx_ul_data_block(ms, payload, cv := cv, with_tlli := with_tlli, nr := nr);
+ if (i == 1) {
+ /* We use FN on i=0 to jump to wanted FN time, then simply submit on next
+ * available frame (fn=0) */
+ fn := 0;
+ }
+ f_ms_tx_ul_data_block(ms, payload, cv := cv, with_tlli := with_tlli, fn := fn, nr := nr);
total_payload := total_payload & payload;
}
return total_payload;
diff --git a/pcu/PCU_Tests.ttcn b/pcu/PCU_Tests.ttcn
index a466732..52d6271 100644
--- a/pcu/PCU_Tests.ttcn
+++ b/pcu/PCU_Tests.ttcn
@@ -316,7 +316,7 @@
var RlcmacDlBlock dl_block;
var uint32_t poll_fn;
- f_ms_tx_ul_data_block(g_ms[i], dummy, with_tlli := true, nr := nr);
+ f_ms_tx_ul_data_block(g_ms[i], dummy, with_tlli := true, fn := g_ms[i].ul_tbf.start_time_fn, nr := nr);
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, poll_fn, nr := nr);
}
}
@@ -354,7 +354,7 @@
pkt_res_req := ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, omit);
}
- f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(valueof(pkt_res_req)), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(valueof(pkt_res_req)), ms.ul_tbf.start_time_fn, nr := f_ms_tx_TsTrxBtsNum(ms));
/* Store 1st UlTBF context before receiving next one, will
* overwrite the TS allocation on MS with info from new UL TBF:
*/
@@ -420,7 +420,7 @@
/* 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);
+ f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
@@ -765,7 +765,7 @@
contention resoultion) and make sure it is ACKED fine. */
/* 16 bytes fills the llc block (because TLLI takes 4 bytes) */
/* Set CV = 15 to signal there's still more than BS_CV_MAX blocks to be sent */
- f_ms_tx_ul_data_block(ms, f_rnd_octstring(16), cv := 15, with_tlli := true)
+ f_ms_tx_ul_data_block(ms, f_rnd_octstring(16), cv := 15, with_tlli := true, fn := ms.ul_tbf.start_time_fn)
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
@@ -849,7 +849,7 @@
contention resoultion) and make sure it is ACKED fine. */
/* 16 bytes fills the llc block (because TLLI takes 4 bytes) */
/* Set CV = 15 to signal there's still more than BS_CV_MAX blocks to be sent */
- f_ms_tx_ul_data_block(ms, f_rnd_octstring(16), cv := 15, with_tlli := true)
+ f_ms_tx_ul_data_block(ms, f_rnd_octstring(16), cv := 15, with_tlli := true, fn := ms.ul_tbf.start_time_fn)
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
@@ -921,7 +921,7 @@
contention resoultion) and make sure it is ACKED fine. */
/* 16 bytes fills the llc block (because TLLI takes 4 bytes) */
/* Set CV = 15 to signal there's still more than BS_CV_MAX blocks to be sent */
- f_ms_tx_ul_data_block(ms, f_rnd_octstring(16), cv := 15, with_tlli := true)
+ f_ms_tx_ul_data_block(ms, f_rnd_octstring(16), cv := 15, with_tlli := true, fn := ms.ul_tbf.start_time_fn)
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
@@ -1299,7 +1299,7 @@
/* 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(ms, f_rnd_octstring(10), cv := 1, with_tlli := true)
+ f_ms_tx_ul_data_block(ms, f_rnd_octstring(10), cv := 1, with_tlli := true, fn := ms.ul_tbf.start_time_fn)
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
/* UL block should NOT be received in SGSN, since we didn't get CV=0 */
@@ -1905,7 +1905,7 @@
contention resoultion) and make sure it is ACKED fine. */
total_payload := f_rnd_octstring(f_ultbf_payload_fill_length(ms.ul_tbf, true));
/* Set CV = 15 to signal there's still more than BS_CV_MAX blocks to be sent */
- f_ms_tx_ul_data_block(ms, total_payload, cv := 15, with_tlli := true)
+ f_ms_tx_ul_data_block(ms, total_payload, cv := 15, with_tlli := true, fn := ms.ul_tbf.start_time_fn)
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
@@ -1966,7 +1966,7 @@
blocks := blocks,
tlli := ms.tlli);
f_ultbf_inc_bsn(ms.ul_tbf);
- f_ms_tx_ul_block(ms, ul_data);
+ f_ms_tx_ul_block(ms, ul_data, ms.ul_tbf.start_time_fn);
/* ACK and check it was received fine */
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
@@ -2122,7 +2122,7 @@
/* 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);
+ f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
@@ -2349,7 +2349,7 @@
/* Send one UL block (with TLLI since we are in One-Phase Access
contention resoultion) and make sure it is ACKED fine. */
payload := f_rnd_octstring(f_ultbf_payload_fill_length(ms.ul_tbf, true)); /* 16 bytes fills the llc block (because TLLI takes 4 bytes) */
- f_ms_tx_ul_data_block(ms, payload, cv := 15, with_tlli := true);
+ f_ms_tx_ul_data_block(ms, payload, cv := 15, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
@@ -2580,7 +2580,7 @@
* RLCMAC block being sent. */
ul_data.data.mac_hdr.e := true;
f_ultbf_inc_bsn(ms.ul_tbf);
- f_ms_tx_ul_block(ms, ul_data);
+ f_ms_tx_ul_block(ms, ul_data, ms.ul_tbf.start_time_fn);
/* UL RlcDataBlock(dataA finished, dataB starts) [BSN=1, CV=2] */
ul_data := t_RLCMAC_UL_DATA_TLLI(cs := CS_1,
@@ -2765,7 +2765,8 @@
/* 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(ms, data, with_tlli := true, nr := f_ms_tx_TsTrxBtsNum(ms));
+ f_ms_tx_ul_data_block(ms, data, with_tlli := true, fn := ms.ul_tbf.start_time_fn,
+ nr := f_ms_tx_TsTrxBtsNum(ms));
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, poll_fn, nr := f_ms_tx_TsTrxBtsNum(ms));
@@ -2908,7 +2909,7 @@
/* 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);
+ 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));
@@ -3128,7 +3129,7 @@
f_ms_establish_ul_tbf(ms);
/* Fake GMM GPRS Attach or similar, PCU doesn't care about upper layers here */
- f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true);
+ f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
@@ -3187,7 +3188,7 @@
f_ms_establish_ul_tbf(ms);
/* Fake GMM GPRS Attach or similar, PCU doesn't care about upper layers here */
- f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true);
+ f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
@@ -3676,11 +3677,16 @@
/* Initialize the PCU interface abstraction */
f_init_raw(testcasename(), info_ind);
+ /* Single block (two phase) packet access */
+ var uint16_t ra := bit2int(chan_req_sb);
+ f_ms_use_ra(ms, ra, ra_is_11bit := 0);
+
/* Establish an Uplink TBF */
f_ms_establish_ul_tbf(ms);
/* Send Packet Resource Request, so the network will allocate an Uplink resource */
- f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, omit)));
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, omit)),
+ fn := ms.ul_tbf.start_time_fn);
/* Expect an RLC/MAC block with Packet Uplink Assignment on PACCH (see 11.2.29) */
f_ms_rx_pkt_ass_pacch(ms, poll_fn, tr_RLCMAC_UL_PACKET_ASS);
@@ -3729,7 +3735,7 @@
f_ms_establish_ul_tbf(ms);
/* Send an Uplink block, so this TBF becomes "active" */
- f_ms_tx_ul_data_block(ms, data, with_tlli := true);
+ f_ms_tx_ul_data_block(ms, data, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, poll_fn);