pcu: First DL TBF hack
Change-Id: Ib3f09e125a7a4492d9072f8e9f5896eaac7ed03b
This commit is contained in:
parent
0cae455d2c
commit
b669ee029e
|
@ -706,6 +706,57 @@ module GSM_RR_Types {
|
|||
}
|
||||
};
|
||||
|
||||
template ImmediateAssignment t_IMM_ASS_TBF_DL(template GprsTlli tlli) := {
|
||||
ded_or_tbf := {
|
||||
spare := ?,
|
||||
tma := ?,
|
||||
downlink := ?,
|
||||
tbf := true
|
||||
},
|
||||
page_mode := ?,
|
||||
chan_desc := omit,
|
||||
pkt_chan_desc := {
|
||||
channel_Type_spare := ?,
|
||||
tn := ?,
|
||||
tsc := ?,
|
||||
presence := ?,
|
||||
zero := *,
|
||||
one := omit
|
||||
},
|
||||
req_ref := ?,
|
||||
timing_advance := ?,
|
||||
mobile_allocation := ?,
|
||||
rest_octets := {
|
||||
presence := '11'B,
|
||||
ll := omit,
|
||||
lh := omit,
|
||||
hl := omit,
|
||||
hh := {
|
||||
presence := '01'B,
|
||||
ul := omit,
|
||||
dl := {
|
||||
tlli := tlli,
|
||||
group1_present := ?,
|
||||
group1 := *,
|
||||
ta_index_present := ?,
|
||||
ta_index := *,
|
||||
tbf_starting_time_present := ?,
|
||||
tbf_starting_time := *,
|
||||
p0_present := ?,
|
||||
p0 := *,
|
||||
pr_mode := *
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template GsmRrMessage t_RR_IMM_ASS_TBF_DL(template GprsTlli tlli) := {
|
||||
header := t_RrHeader(IMMEDIATE_ASSIGNMENT, ?),
|
||||
payload := {
|
||||
imm_ass := t_IMM_ASS_TBF_DL(tlli)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
} with { encode "RAW" ; variant "FIELDORDER(msb)" }
|
||||
|
|
|
@ -90,6 +90,28 @@ module L1CTL_PortType {
|
|||
return rr.payload.imm_ass;
|
||||
}
|
||||
|
||||
function f_L1CTL_WAIT_IMM_ASS_TBF_DL(L1CTL_PT pt, GprsTlli tlli) return ImmediateAssignment {
|
||||
var L1ctlDlMessage dl;
|
||||
var GsmRrMessage rr;
|
||||
timer T := 10.0;
|
||||
T.start;
|
||||
alt {
|
||||
[] pt.receive(t_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
|
||||
rr := dec_GsmRrMessage(dl.payload.data_ind.payload);
|
||||
log("PCH/AGCN DL RR: ", rr);
|
||||
if (match(rr, t_RR_IMM_ASS_TBF_DL(tlli))) {
|
||||
log("Received IMM.ASS for our TLLI!");
|
||||
} else {
|
||||
repeat;
|
||||
}
|
||||
};
|
||||
[] pt.receive { repeat };
|
||||
[] T.timeout { setverdict(fail, "Timeout waiting for IMM ASS") };
|
||||
}
|
||||
T.stop;
|
||||
return rr.payload.imm_ass;
|
||||
}
|
||||
|
||||
function f_L1CTL_TBF_CFG(L1CTL_PT pt, boolean is_uplink, TfiUsfArr tfi_usf) {
|
||||
timer T := 2.0;
|
||||
T.start;
|
||||
|
|
|
@ -26,7 +26,21 @@ module LAPDm_RAW_PT {
|
|||
charstring err optional
|
||||
}
|
||||
|
||||
type record TBF_establish_res {
|
||||
type record length(8) of uint8_t TfiList;
|
||||
type record TbfPars {
|
||||
GsmArfcn arfcn optional,
|
||||
/* Temporary Flow Identifier for each TN */
|
||||
TfiList tfi
|
||||
}
|
||||
type record length(8) of TbfPars TbfParsPerTs;
|
||||
|
||||
template TbfPars t_TbfParsInit := {
|
||||
arfcn := omit,
|
||||
tfi := { 255, 255, 255, 255, 255, 255, 255, 255 }
|
||||
}
|
||||
|
||||
type record TBF_UL_establish_res {
|
||||
TbfPars pars optional,
|
||||
charstring err optional
|
||||
}
|
||||
|
||||
|
@ -40,10 +54,17 @@ module LAPDm_RAW_PT {
|
|||
LapdmFrame lapdm
|
||||
}
|
||||
|
||||
type record TBF_establish_req {
|
||||
type integer TbfNr (0..7); /* maximum of 8 concurrent TBF per direction */
|
||||
type record TBF_UL_establish_req {
|
||||
TbfNr tbf_nr,
|
||||
uint8_t ra
|
||||
}
|
||||
|
||||
type record TBF_DL_establish_req {
|
||||
TbfNr tbf_nr,
|
||||
TbfPars pars
|
||||
}
|
||||
|
||||
/* PH-DATA.ind / PH-DATA.req */
|
||||
type record RLCMAC_ph_data_ind {
|
||||
GprsCodingScheme cs,
|
||||
|
@ -74,11 +95,12 @@ module LAPDm_RAW_PT {
|
|||
in BCCH_tune_req,
|
||||
DCCH_establish_req,
|
||||
DCCH_release_req,
|
||||
TBF_establish_req,
|
||||
TBF_UL_establish_req,
|
||||
TBF_DL_establish_req,
|
||||
RLCMAC_ph_data_req,
|
||||
LAPDm_ph_data;
|
||||
out DCCH_establish_res,
|
||||
TBF_establish_res,
|
||||
TBF_UL_establish_res,
|
||||
RLCMAC_ph_data_ind,
|
||||
LAPDm_ph_data;
|
||||
} with {extension "internal"};
|
||||
|
@ -86,13 +108,14 @@ module LAPDm_RAW_PT {
|
|||
/* port from user (external) point of view */
|
||||
type port LAPDm_PT message {
|
||||
in DCCH_establish_res,
|
||||
TBF_establish_res,
|
||||
TBF_UL_establish_res,
|
||||
RLCMAC_ph_data_ind,
|
||||
LAPDm_ph_data;
|
||||
out BCCH_tune_req,
|
||||
DCCH_establish_req,
|
||||
DCCH_release_req,
|
||||
TBF_establish_req,
|
||||
TBF_UL_establish_req,
|
||||
TBF_DL_establish_req,
|
||||
RLCMAC_ph_data_req,
|
||||
LAPDm_ph_data;
|
||||
} with {extension "internal"};
|
||||
|
@ -124,6 +147,9 @@ module LAPDm_RAW_PT {
|
|||
|
||||
/* channel description of the currently active DCH */
|
||||
var ChannelDescription chan_desc;
|
||||
|
||||
var TbfParsPerTs g_tbf_ul;
|
||||
var TbfParsPerTs g_tbf_dl;
|
||||
};
|
||||
|
||||
/* wrapper function to log state transitions */
|
||||
|
@ -286,6 +312,51 @@ module LAPDm_RAW_PT {
|
|||
set_ph_state(PH_STATE_BCH);
|
||||
}
|
||||
|
||||
/* Establish TBF / packet transfer mode */
|
||||
private altstep as_tbf_ul_est() runs on lapdm_CT {
|
||||
var TBF_UL_establish_req tbf_ul_req;
|
||||
[] LAPDM_SP.receive(TBF_UL_establish_req:?) -> value tbf_ul_req {
|
||||
var TbfNr tbf_nr := tbf_ul_req.tbf_nr;
|
||||
var TBF_UL_establish_res res;
|
||||
if (isvalue(g_tbf_ul[tbf_nr].arfcn)) {
|
||||
setverdict(fail, "Cannot establish UL TBF ID ", tbf_nr, ": BUSY");
|
||||
self.stop;
|
||||
}
|
||||
f_establish_tbf(tbf_ul_req.ra);
|
||||
if (ph_state == PH_STATE_TBF) {
|
||||
g_tbf_ul[tbf_nr] := valueof(t_TbfParsInit); /* FIXME: Actual TFI[s] */
|
||||
log("Established UL TBF ", tbf_nr);
|
||||
res := { pars := g_tbf_ul[tbf_nr], err := omit };
|
||||
} else {
|
||||
res := { pars := omit, err := "Unable to establish UL TBF" };
|
||||
}
|
||||
LAPDM_SP.send(res);
|
||||
}
|
||||
}
|
||||
|
||||
private altstep as_tbf_dl_est() runs on lapdm_CT {
|
||||
var TBF_DL_establish_req tbf_dl_req;
|
||||
[] LAPDM_SP.receive(TBF_DL_establish_req:?) -> value tbf_dl_req {
|
||||
var TbfNr tbf_nr := tbf_dl_req.tbf_nr;
|
||||
if (isvalue(g_tbf_dl[tbf_nr].arfcn)) {
|
||||
setverdict(fail, "Cannot establish DL TBF ID ", tbf_nr, ": BUSY");
|
||||
self.stop;
|
||||
}
|
||||
g_tbf_dl[tbf_nr] := tbf_dl_req.pars;
|
||||
f_L1CTL_TBF_CFG(L1CTL, false, tbf_dl_req.pars.tfi);
|
||||
set_ph_state(PH_STATE_TBF);
|
||||
log("Established DL TBF ", tbf_nr, ": ", tbf_dl_req.pars);
|
||||
}
|
||||
}
|
||||
|
||||
private function f_init_tbf() runs on lapdm_CT {
|
||||
var integer i;
|
||||
for (i := 0; i < 8; i := i+1) {
|
||||
g_tbf_ul[i] := valueof(t_TbfParsInit);
|
||||
g_tbf_dl[i] := valueof(t_TbfParsInit);
|
||||
}
|
||||
}
|
||||
|
||||
function ScanEvents() runs on lapdm_CT {
|
||||
var L1ctlDlMessage dl;
|
||||
var BCCH_tune_req bt;
|
||||
|
@ -294,7 +365,8 @@ module LAPDm_RAW_PT {
|
|||
var RLCMAC_ph_data_req rpdr;
|
||||
var DCCH_establish_req est_req;
|
||||
var DCCH_establish_res est_res;
|
||||
var TBF_establish_req tbf_req;
|
||||
|
||||
f_init_tbf();
|
||||
|
||||
while (true) {
|
||||
if (ph_state == PH_STATE_NULL) {
|
||||
|
@ -341,17 +413,8 @@ module LAPDm_RAW_PT {
|
|||
LAPDM_SP.send(res);
|
||||
}
|
||||
|
||||
/* Establish TBF / packet transfer mode */
|
||||
[] LAPDM_SP.receive(TBF_establish_req:?) -> value tbf_req {
|
||||
var TBF_establish_res res;
|
||||
f_establish_tbf(tbf_req.ra);
|
||||
if (ph_state == PH_STATE_TBF) {
|
||||
res := { err := omit };
|
||||
} else {
|
||||
res := { err := "Unable to establish TBF" };
|
||||
}
|
||||
LAPDM_SP.send(res);
|
||||
}
|
||||
[] as_tbf_ul_est();
|
||||
[] as_tbf_dl_est();
|
||||
|
||||
[] LAPDM_SP.receive {}
|
||||
[] L1CTL.receive {}
|
||||
|
@ -404,6 +467,7 @@ module LAPDm_RAW_PT {
|
|||
/* decode + forward any blocks from L1 to L23*/
|
||||
[] L1CTL.receive(t_L1CTL_DATA_IND(t_RslChanNr_PDCH(?))) -> value dl {
|
||||
rpdi.block := dec_RlcmacDlBlock(dl.payload.data_ind.payload);
|
||||
/* FIXME: Filter based on g_tbf_dl */
|
||||
rpdi.fn := dl.dl_info.frame_nr;
|
||||
rpdi.ts_nr := dl.dl_info.chan_nr.tn;
|
||||
rpdi.cs := CS1; /* FIXME */
|
||||
|
@ -427,10 +491,14 @@ module LAPDm_RAW_PT {
|
|||
}
|
||||
}
|
||||
|
||||
[] as_tbf_ul_est();
|
||||
[] as_tbf_dl_est();
|
||||
|
||||
/* FIXME: release TBF mode */
|
||||
[] LAPDM_SP.receive(DCCH_release_req:?) {
|
||||
/* go back to BCCH */
|
||||
f_release_tbf();
|
||||
f_init_tbf();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -524,5 +524,31 @@ module RLCMAC_CSN1_Types {
|
|||
}
|
||||
}
|
||||
|
||||
private const ILevel iNone := {
|
||||
presence := '0'B,
|
||||
i_level := omit
|
||||
}
|
||||
private const ChannelQualityReport c_ChQualRep_default := {
|
||||
c_value := 0,
|
||||
rxqual := 0,
|
||||
sign_var := 0,
|
||||
i_levels := { iNone, iNone, iNone, iNone, iNone, iNone, iNone, iNone }
|
||||
}
|
||||
template (value) RlcmacUlCtrlMsg ts_RlcMacUlCtrl_PKT_DL_ACK(uint5_t dl_tfi,
|
||||
AckNackDescription andesc,
|
||||
ChannelQualityReport qual_rep := c_ChQualRep_default) := {
|
||||
msg_type := PACKET_DL_ACK_NACK,
|
||||
u := {
|
||||
dl_ack_nack := {
|
||||
dl_tfi := dl_tfi,
|
||||
ack_nack_desc := andesc,
|
||||
chreq_desc_presence := '0'B,
|
||||
chreq_desc := omit,
|
||||
ch_qual_rep := qual_rep
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} with { encode "RAW"; variant "FIELDORDER(msb)" variant "BYTEORDER(last)" };
|
||||
|
|
|
@ -323,6 +323,21 @@ uint3_t usf) := {
|
|||
}
|
||||
}
|
||||
|
||||
template RlcmacDlBlock tr_RLCMAC_DATA_RRBP := {
|
||||
data := {
|
||||
mac_hdr := {
|
||||
mac_hdr := {
|
||||
payload_type := MAC_PT_RLC_DATA,
|
||||
rrbp := ?,
|
||||
rrbp_valid := true,
|
||||
usf := ?
|
||||
},
|
||||
hdr_ext := ?
|
||||
},
|
||||
blocks := ?
|
||||
}
|
||||
}
|
||||
|
||||
/* Template for Uplink MAC Control Header */
|
||||
template UlMacCtrlHeader t_RLCMAC_UlMacCtrlH(template MacPayloadType pt, template boolean retry := false) := {
|
||||
payload_type := pt,
|
||||
|
|
|
@ -16,6 +16,7 @@ module PCU_Tests {
|
|||
import from LAPDm_RAW_PT all;
|
||||
import from GPRS_Context all;
|
||||
import from GPRS_TBF all;
|
||||
import from L1CTL_PortType all;
|
||||
|
||||
modulepar {
|
||||
BssgpConfig mp_gb_cfg := {
|
||||
|
@ -221,12 +222,12 @@ module PCU_Tests {
|
|||
L1.send(tune_req);
|
||||
/* FIXME: wait for confirm */
|
||||
|
||||
var TBF_establish_req est_req := { ra := hex2int('7B'H) };
|
||||
var TBF_UL_establish_req est_req := { tbf_nr := 0, ra := hex2int('7B'H) };
|
||||
L1.send(est_req);
|
||||
T.start;
|
||||
/* FIXME: wait for confirm */
|
||||
alt {
|
||||
[] L1.receive(TBF_establish_res:?) {}
|
||||
[] L1.receive(TBF_UL_establish_res:?) {}
|
||||
[] L1.receive { repeat; }
|
||||
[] T.timeout {
|
||||
setverdict(fail, "Timeout establishing UL TBF");
|
||||
|
@ -526,6 +527,82 @@ function f_ul_tbf(inout UlTbfState us) runs on dummy_CT {
|
|||
f_exit();
|
||||
}
|
||||
|
||||
testcase TC_dl_tbf() runs on dummy_CT {
|
||||
g_mmctx.imsi := '262420123456789'H;
|
||||
g_mmctx.tlli := f_random_tlli();
|
||||
f_init();
|
||||
|
||||
f_establish_dl_tbf();
|
||||
|
||||
f_exit();
|
||||
}
|
||||
|
||||
function f_wait_tbf_dl(TbfNr tbf_nr, GprsTlli tlli) runs on dummy_CT return ImmediateAssignment {
|
||||
var LAPDm_ph_data ph_data;
|
||||
var GsmRrMessage rr;
|
||||
timer T := 10.0;
|
||||
T.start;
|
||||
alt {
|
||||
[] L1.receive(LAPDm_ph_data:{sacch:=?,sapi:=0,lapdm:={bbis:=?}}) -> value ph_data {
|
||||
rr := dec_GsmRrMessage(ph_data.lapdm.bbis.payload);
|
||||
log("PCH/AGCH DL RR: ", rr);
|
||||
if (match(rr, t_RR_IMM_ASS_TBF_DL(tlli))) {
|
||||
var TbfPars tbf_pars := valueof(t_TbfParsInit);
|
||||
log("Received IMM.ASS for our TLLI!");
|
||||
tbf_pars.tfi[rr.payload.imm_ass.pkt_chan_desc.tn] :=
|
||||
rr.payload.imm_ass.rest_octets.hh.dl.group1.tfi_assignment;
|
||||
L1.send(TBF_DL_establish_req:{tbf_nr, tbf_pars});
|
||||
} else {
|
||||
repeat;
|
||||
}
|
||||
}
|
||||
[] L1.receive { repeat };
|
||||
[] T.timeout {
|
||||
setverdict(fail, "Timeout waiting for IMM ASS")
|
||||
self.stop;
|
||||
}
|
||||
}
|
||||
T.stop;
|
||||
return rr.payload.imm_ass;
|
||||
}
|
||||
|
||||
/* Establish an UL TBF: Tune to ARFCN, send RACH, receive AGCH, enable TBF Rx */
|
||||
function f_establish_dl_tbf() runs on dummy_CT {
|
||||
timer T := 5.0;
|
||||
var BCCH_tune_req tune_req := { { false, 871 }, true };
|
||||
L1.send(tune_req);
|
||||
/* FIXME: wait for confirm */
|
||||
|
||||
/* sending a GMM PDU as DL-UNITDATA should trigger Paging + DL TBF Assignment */
|
||||
tx_gmm('1'B, '01020304'O, c_LLC_SAPI_LLGMM);
|
||||
|
||||
/* Expect an IMM.ASS for PDCH on the AGCH */
|
||||
f_wait_tbf_dl(0, g_mmctx.tlli);
|
||||
|
||||
var RLCMAC_ph_data_ind dl;
|
||||
alt {
|
||||
[] L1.receive(RLCMAC_ph_data_ind:{cs:=?, ts_nr:=?, fn:=?, block:=tr_RLCMAC_DATA_RRBP}) ->
|
||||
value dl {
|
||||
var uint6_t tfi := dl.block.data.mac_hdr.hdr_ext.tfi;
|
||||
var GsmFrameNumber ul_fn := f_rrbp_fn(dl.fn, dl.block.data.mac_hdr.mac_hdr.rrbp);
|
||||
var AckNackDescription an_desc := { /* FIXME: compute this based on state */
|
||||
final_ack := '1'B,
|
||||
starting_seq_nr := 0,
|
||||
receive_block_bitmap := '0000000000000000000000000000000000000000000000000000000000000001'B
|
||||
}
|
||||
var RlcmacUlCtrlMsg ctrl_ack;
|
||||
ctrl_ack := valueof(ts_RlcMacUlCtrl_PKT_DL_ACK(tfi, an_desc));
|
||||
var RlcmacUlBlock ul_block := valueof(ts_RLC_UL_CTRL_ACK(ctrl_ack));
|
||||
L1.send(ts_PH_DATA_ABS(0, CS1, dl.ts_nr, ul_fn, {false, 871}, ul_block));
|
||||
log("Sent DL ACK: ", ul_block);
|
||||
}
|
||||
[] L1.receive { repeat; }
|
||||
}
|
||||
|
||||
f_sleep(10.0);
|
||||
}
|
||||
|
||||
|
||||
control {
|
||||
execute(TC_selftest_bssgp());
|
||||
execute(TC_selftest_ns());
|
||||
|
|
Loading…
Reference in New Issue