WIP: Work towards a more real DL TBF receiver implementation
Change-Id: I300312734d99f2b8a406f39e04b4f738940f7579
This commit is contained in:
parent
b669ee029e
commit
cc5c1152cc
|
@ -113,7 +113,14 @@ module RLCMAC_Types {
|
|||
boolean e
|
||||
} with {
|
||||
variant (e) "FIELDLENGTH(1)"
|
||||
encode "RAW"
|
||||
};
|
||||
|
||||
external function enc_LlcBlockHdr(in LlcBlockHdr si) return octetstring
|
||||
with { extension "prototype(convert) encode(RAW)" };
|
||||
external function dec_LlcBlockHdr(in octetstring stream) return LlcBlockHdr
|
||||
with { extension "prototype(convert) decode(RAW)" };
|
||||
|
||||
type record LlcBlock {
|
||||
/* Header is only present if LI field was present */
|
||||
LlcBlockHdr hdr optional,
|
||||
|
|
|
@ -18,8 +18,25 @@ import from RLCMAC_CSN1_Types all;
|
|||
import from LLC_Types all;
|
||||
import from GPRS_Context all;
|
||||
|
||||
/* input parameters into TBF (mostly mode/cs + LLC PDUs */
|
||||
private const integer RLC_GPRS_SNS := 128;
|
||||
private const integer RLC_GPRS_WS := 64;
|
||||
private const integer RLC_EGPRS_MIN_WS := 64;
|
||||
private const integer RLC_EGPRS_MAX_WS := 1024;
|
||||
private const integer RLC_EGPRS_SNS := 2048;
|
||||
private const integer RLC_EGPRS_MAX_BSN_DELTA := 512;
|
||||
private const integer RLC_MAX_SNS := RLC_EGPRS_SNS;
|
||||
private const integer RLC_MAX_WS := RLC_EGPRS_MAX_WS;
|
||||
private const integer RLC_MAX_LEN := 74 /* MCS-9 data unit */
|
||||
|
||||
private const integer sns_half := (RLC_MAX_SNS / 2);
|
||||
private const integer mod_sns_half := (RLC_MAX_SNS / 2) - 1;
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Uplink TBF handling
|
||||
***********************************************************************/
|
||||
|
||||
/* input parameters into TBF (mostly mode/cs + LLC PDUs */
|
||||
type record UlTbfPars {
|
||||
/* Acknowledged mode (true) or unacknowledged (false) */
|
||||
boolean ack_mode,
|
||||
|
@ -46,22 +63,6 @@ private function f_RlcEndpointTx_init(inout RlcEndpointTx ep) {
|
|||
ep.v_b := int2bit(0, 128); /* FIXME: EGPRS 2048 bits length */
|
||||
}
|
||||
|
||||
type record RlcEndpointRx {
|
||||
/* receive state variable V(R) (9.1.5): BSN one higher than highest BSN yet received (mod SNS) */
|
||||
integer v_r,
|
||||
/* receive window state variable V(Q) (9.1.6): Lowest BSN not yet received (mod SNS) */
|
||||
integer v_q,
|
||||
/* receive state array V(N) (9.1.7) */
|
||||
bitstring v_n
|
||||
}
|
||||
|
||||
private function f_RlcEndpointRx_init(inout RlcEndpointRx ep) {
|
||||
ep.v_r := 0;
|
||||
ep.v_q := 0;
|
||||
ep.v_n := int2bit(0, 128); /* FIXME: EGPRS 2048 bits length */
|
||||
}
|
||||
|
||||
|
||||
type record UlTbfState {
|
||||
/* "const" input state with TBF Data */
|
||||
UlTbfPars tbf,
|
||||
|
@ -360,6 +361,142 @@ function f_ul_tbf_process_acknack(inout UlTbfState us, RlcmacDlCtrlBlock db) {
|
|||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Downlink TBF handling
|
||||
***********************************************************************/
|
||||
|
||||
type record RlcEndpointRx {
|
||||
/* receive state variable V(R) (9.1.5): BSN one higher than highest BSN yet received (mod SNS) */
|
||||
integer v_r,
|
||||
/* receive window state variable V(Q) (9.1.6): Lowest BSN not yet received (mod SNS) */
|
||||
integer v_q,
|
||||
/* receive state array V(N) (9.1.7) */
|
||||
bitstring v_n
|
||||
}
|
||||
|
||||
private function f_RlcEndpointRx_init(inout RlcEndpointRx ep) {
|
||||
ep.v_r := 0;
|
||||
ep.v_q := 0;
|
||||
ep.v_n := int2bit(0, 128); /* FIXME: EGPRS 2048 bits length */
|
||||
}
|
||||
|
||||
type record DlTbfPars {
|
||||
/* Acknowledged mode (true) or unacknowledged (false) */
|
||||
boolean ack_mode,
|
||||
/* Coding Scheme for transmission, determines block size */
|
||||
GprsCodingScheme initial_cs,
|
||||
/* Sequence Number Space */
|
||||
integer sns,
|
||||
/* Window Size */
|
||||
integer ws
|
||||
}
|
||||
|
||||
type record DlTbfState {
|
||||
/* "const" input state with TBF Data */
|
||||
DlTbfPars tbf,
|
||||
uint8_t num_ts,
|
||||
|
||||
RlcEndpointRx er,
|
||||
|
||||
integer tfi,
|
||||
|
||||
/* list of abstract/decoded RLC PDUs */
|
||||
record of RlcmacDlBlock rlc_received
|
||||
}
|
||||
|
||||
function f_dl_tbf_mod_sns(DlTbfState ds, integer val) return integer
|
||||
{
|
||||
return (val mod ds.tbf.sns);
|
||||
}
|
||||
|
||||
function f_dl_tbf_is_in_window(integer bsn) return boolean {
|
||||
setverdict(fail, "pleaes implement me");
|
||||
self.stop;
|
||||
}
|
||||
|
||||
function f_dl_tbf_is_received(inout DlTbfState ds, integer bsn) return boolean {
|
||||
var integer offset_v_r;
|
||||
|
||||
if (not f_dl_tbf_is_in_window(bsn)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* offset to the end of the received window */
|
||||
offset_v_r := f_dl_tbf_mod_sns(ds, ds.er.v_r - 1 - bsn);
|
||||
if (not (offset_v_r < ds.tbf.ws)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ds.er.v_n[bsn mod sns_half] == '1'B) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function f_dl_tbf_mark_received(inout DlTbfState ds, integer bsn) {
|
||||
ds.er.v_n[bsn mod sns_half] := '1'B;
|
||||
f_dl_tbf_raise_v_r(ds, bsn);
|
||||
}
|
||||
|
||||
/* Raise V(Q) if possible */
|
||||
function f_dl_tbf_raise_v_q(inout DlTbfState ds, integer bsn) return integer {
|
||||
var integer count := 0;
|
||||
while (ds.er.v_q != ds.er.v_r) {
|
||||
var integer v_q_old := ds.er.v_q;
|
||||
if (not f_dl_tbf_is_received(ds, v_q_old)) {
|
||||
break;
|
||||
}
|
||||
ds.er.v_q := f_dl_tbf_mod_sns(ds, ds.er.v_q + 1)
|
||||
log("RLCMAC: Taking block ", v_q_old, " out, raising V(Q) to ", ds.er.v_q);
|
||||
count := count+1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
function f_dl_tbf_raise_v_r(inout DlTbfState ds, integer bsn) {
|
||||
var integer offset_v_r := f_dl_tbf_mod_sns(ds, bsn + 1 - ds.er.v_r);
|
||||
if (offset_v_r < (ds.tbf.sns / 2)) {
|
||||
for (var integer i := offset_v_r; i > 0; i := i-1) {
|
||||
/* mark as missing */
|
||||
ds.er.v_n[bsn mod sns_half] := '0'B;
|
||||
//raise_v_r_to(1);
|
||||
}
|
||||
log("RLCMAC: Raising V(R) to ", ds.er.v_r);
|
||||
}
|
||||
}
|
||||
|
||||
/* process the actual data and update TbfState */
|
||||
function f_dl_tbf_process_dl_data(inout DlTbfState ds, RlcmacDlDataBlock db) {
|
||||
var integer bsn := db.mac_hdr.hdr_ext.bsn;
|
||||
if (db.mac_hdr.hdr_ext.tfi != ds.tfi) {
|
||||
setverdict(fail, "Unexpected TFI of DL Data Block ", db);
|
||||
self.stop;
|
||||
}
|
||||
f_dl_tbf_mark_received(ds, bsn);
|
||||
if (ds.tbf.ack_mode) {
|
||||
/* In RLC acknowledged mode, the receive window is defined by the receive window
|
||||
* state variable V(Q) in the following inequality[ V(Q) ≤ BSN < V(Q)+ WS ] modulo
|
||||
* SNS */
|
||||
if (bsn < ds.er.v_q or bsn > ds.er.v_q + ds.tbf.ws) {
|
||||
setverdict(fail, "Unexpected BSN outside of window ", bsn);
|
||||
self.stop;
|
||||
}
|
||||
|
||||
/* In RLC acknowledged mode, the value of V(Q) shall be updated when the RLC
|
||||
* receiver receives the RLC data block whose BSN is equal to V(Q). The value of
|
||||
* V(Q) shall then be set to the BSN value of the next RLC data block in the receive
|
||||
* window (modulo SNS) that has not yet been received, or it shall be set to V(R) if
|
||||
* all RLC data blocks in the receive window have been received */
|
||||
f_dl_tbf_mark_received(ds, bsn);
|
||||
} else {
|
||||
/* In RLC unacknowledged mode, if [V(R) - V(Q)] modulo SNS > WS after updating V(R),
|
||||
* then V(Q) is set to [V(R) - WS] modulo SNS. */
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue