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
This commit is contained in:
Pau Espin 2021-04-23 21:08:22 +02:00
parent 95e3d9906c
commit dee557059b
2 changed files with 49 additions and 23 deletions

View File

@ -96,7 +96,8 @@ type record UlTbf {
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 @@ template (value) UlTbf t_UlTbf_def := {
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 @@ function f_trxnr2arfcn(uint3_t trx_nr) return GsmArfcn {
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 @@ runs on MS_BTS_IFACE_CT return UlTbf {
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 @@ runs on MS_BTS_IFACE_CT return UlTbf {
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 @@ runs on MS_BTS_IFACE_CT {
/* 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 @@ runs on MS_BTS_IFACE_CT return octetstring {
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;

View File

@ -316,7 +316,7 @@ runs on RAW_PCU_Test_CT {
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 @@ runs on RAW_PCU_Test_CT return PollFnCtx {
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 @@ testcase TC_pcuif_suspend_active_tbf() runs on RAW_PCU_Test_CT {
/* 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 @@ testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
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 @@ testcase TC_cs_initial_ul() runs on RAW_PCU_Test_CT {
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 @@ testcase TC_cs_max_ul() runs on RAW_PCU_Test_CT {
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 @@ testcase TC_t3169() runs on RAW_PCU_Test_CT {
/* 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 @@ testcase TC_countdown_procedure() runs on RAW_PCU_Test_CT {
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 @@ testcase TC_ul_all_sizes() runs on RAW_PCU_Test_CT {
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 @@ private function f_TC_mo_ping_pong_1phase_access(template (present) CodingScheme
/* 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 @@ testcase TC_ul_intermediate_retrans() runs on RAW_PCU_Test_CT {
/* 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 @@ testcase TC_ul_flow_multiple_llc_blocks() runs on RAW_PCU_Test_CT {
* 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 @@ testcase TC_dl_multislot_tbf_ms_class_from_sgsn() runs on RAW_PCU_Test_CT {
/* 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 @@ testcase TC_ul_tbf_reestablish_with_pkt_resource_req() runs on RAW_PCU_Test_CT {
/* 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 @@ testcase TC_bssgp_dl_unitdata_with_valid_imsi() runs on RAW_PCU_Test_CT {
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 @@ testcase TC_bssgp_dl_unitdata_with_invalid_imsi() runs on RAW_PCU_Test_CT {
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 @@ testcase TC_pcuif_fh_pkt_ass_ul() runs on RAW_PCU_Test_CT {
/* 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 @@ testcase TC_pcuif_fh_pkt_ass_dl() runs on RAW_PCU_Test_CT {
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);