gprs_gb: working Uplink PACKET_CONTROL_ACK against OsmoPCU

Change-Id: I2c7d0eb9371911e28f328caeaed63cb8ec311ac1
This commit is contained in:
Harald Welte 2018-03-02 23:37:51 +01:00
parent fd445c34fe
commit 7024baa66c
7 changed files with 146 additions and 31 deletions

View File

@ -9,7 +9,7 @@ TCPDUMP_STOP := $TTCN3_HACKS_PATH"/ttcn3-tcpdump-stop.sh"
SourceInfoFormat := Single;
LogSourceInfo := Yes;
LoggerPlugins := { JUnitLogger := "libjunitlogger2" }
#FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
#ConsoleMask := ERROR | WARNING | TESTCASE | TTCN_MATCHING | DEBUG_ENCDEC
[EXTERNAL_COMMANDS]

View File

@ -17,8 +17,8 @@ module Test {
modulepar {
BssgpConfig mp_gb_cfg := {
nsei := 96,
bvci := 196,
nsei := 1234,
bvci := 1234,
cell_id := {
ra_id := {
lai := {
@ -33,16 +33,16 @@ module Test {
}
type record MmContext {
octetstring imsi optional,
hexstring imsi optional,
GprsTlli tlli,
uint9_t n_u
};
type component dummy_CT {
type component dummy_CT extends BSSGP_Client_CT {
var lapdm_CT lapdm_component;
port LAPDm_PT L1;
port BSSGP_PT BSSGP;
var NS_CT ns_component;
var BSSGP_CT bssgp_component;
@ -64,6 +64,7 @@ module Test {
bssgp_component := BSSGP_CT.create;
/* connect our BSSGP port to the BSSGP Emulation */
connect(self:BSSGP, bssgp_component:BSSGP_SP);
connect(self:BSSGP_PROC, bssgp_component:BSSGP_PROC);
/* connect lower-end of BSSGP with BSSGP_CODEC_PORT (maps to NS_PT*/
connect(bssgp_component:BSCP, ns_component:NS_SP);
/* connect lower-end of NS emulation to NS_CODEC_PORT (on top of IPl4) */
@ -174,7 +175,7 @@ module Test {
/* Establish BSSGP connection to PCU */
function f_bssgp_establish() runs on dummy_CT {
timer T:= 60.0;
timer T:= 10.0;
f_init();
T.start
@ -251,9 +252,23 @@ module Test {
}
}
template RlcmacUlBlock t_RLCMAC_UL_DATA_TLLI(template uint5_t tfi, template uint4_t cv, template uint7_t bsn,
template LlcBlocks blocks := {}, template boolean stall := false, template GprsTlli tlli) modifies t_RLCMAC_UL_DATA := {
template LlcBlocks blocks := {}, template boolean stall := false, template GprsTlli tlli) := {
data := {
tlli := tlli
mac_hdr := {
payload_type := MAC_PT_RLC_DATA,
countdown := cv,
stall_ind := false,
retry := false,
spare := '0'B,
pfi_ind := false,
tfi := tfi,
tlli_ind := true,
bsn := bsn,
e := false
},
tlli := tlli,
pfi := omit,
blocks := blocks
}
}
@ -338,37 +353,65 @@ uint3_t usf) := {
return tlli;
}
/* Compute the frame number of the uplink block based on current fn + rrbp */
function f_rrbp_fn(GsmFrameNumber fn, MacRrbp rrbp) return GsmFrameNumber {
var integer add;
select (rrbp) {
case (RRBP_Nplus13_mod_2715648) {
add := 13;
}
case (RRBP_Nplus17_or_18_mod_2715648) {
add := 17; /* FIXME: What about 'or 18'? */
}
case (RRBP_Nplus21_or_22_mod_2715648) {
add := 21; /* FIXME: What about 'or 22'? */
}
case (RRBP_Nplus26_mod_2715648) {
add := 26;
}
}
return (fn + add) mod 2715648;
}
/* Send a single Uplink Block via Um; Verify reception on BSSGP; Expect UL_ACK on Um */
function f_single_ul_block(GprsCodingScheme cs) runs on dummy_CT {
var GprsTlli tlli := f_random_tlli();
var octetstring payload := '01020304'O;
var PDU_LLC llc := valueof(ts_LLC_UI(payload, c_LLC_SAPI_LLGMM, '0'B, g_mmctx.n_u));
var octetstring llc_enc := enc_PDU_LLC(llc);
var RLCMAC_ph_data_ind dl;
/* establish upling TBF */
f_establish_ul_tbf();
/* Generate LLC PDU consisting of single RLC block and send it via simulated MS */
var template RlcmacUlBlock blk := t_RLCMAC_UL_DATA_TLLI(0, 0, 0, {t_RLCMAC_LLCBLOCK(payload)}, false, tlli);
L1.send(RLCMAC_ph_data_req:{tbf_id := 0, cs := cs, block := blk});
var template RlcmacUlBlock blk := t_RLCMAC_UL_DATA_TLLI(0, 0, 0, {t_RLCMAC_LLCBLOCK(llc_enc)}, false, g_mmctx.tlli);
L1.send(RLCMAC_ph_data_req:{dyn:={tbf_id := 0, cs := cs, block := blk}});
/* ensure that this LLC-PDU arrives from the right TLLI at the (simulated) SGSN */
BSSGP.receive(tr_BD_BSSGP(tr_BSSGP_UL_UD(tlli, ?, payload)));
BSSGP.receive(tr_BD_BSSGP(tr_BSSGP_UL_UD(g_mmctx.tlli, ?, llc_enc)));
/* ensure the MS eceives an UL_ACK_NACK */
alt {
[] L1.receive(RLCMAC_ph_data_ind:{cs:=?, block:=tr_RLCMAC_ACK_NACK(0, tlli)}) { };
[] L1.receive { repeat; };
[] L1.receive(RLCMAC_ph_data_ind:{cs:=?, ts_nr:=?, fn:=?, block:=tr_RLCMAC_ACK_NACK(0, g_mmctx.tlli)}) -> value dl {
log("found matching ACK/NACK");
/* send CTRL ACK in uplink */
var GsmFrameNumber ul_fn := f_rrbp_fn(dl.fn, dl.block.ctrl.mac_hdr.rrbp);
var RlcmacUlCtrlMsg ctrl_ack := valueof(ts_RlcMacUlCtrl_PKT_CTRL_ACK(g_mmctx.tlli));
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, 0}, ul_block));
}
[] L1.receive { repeat; };
}
log("found matching ACK/NACK");
/* send CTRL ACK in uplink */
//L1.send(FIXME);
}
testcase TC_rach() runs on dummy_CT {
var hexstring imsi := '262420123456789'H;
var BssgpBvci bvci := 196;
var GsmTmsi tmsi := hex2int('01234567'H);
g_mmctx.imsi := '262420123456789'H;
g_mmctx.tlli := f_random_tlli();
f_init();
f_bssgp_client_register(g_mmctx.imsi, g_mmctx.tlli, mp_gb_cfg.cell_id);
f_bssgp_establish();
f_single_ul_block(CS1);

View File

@ -8,6 +8,8 @@ module L1CTL_Types {
import from GSM_RR_Types all;
import from Osmocom_Types all;
type uint32_t uint32_le with { variant "BYTEORDER(first)" };
type enumerated L1ctlMsgType {
L1CTL_NONE,
L1CTL_FBSB_REQ,
@ -143,7 +145,9 @@ module L1CTL_Types {
type record L1ctlDataInd {
octetstring payload length(23)
} with { variant "" };
} with {
variant (payload) "BYTEORDER(first)"
};
type union L1ctlDlPayload {
L1ctlFbsbConf fbsb_conf,
@ -153,7 +157,9 @@ module L1CTL_Types {
L1ctlTrafficReq traffic_ind,
L1ctlTbfCfgReq tbf_cfg_conf,
octetstring other
} with { variant "" };
} with {
variant (other) "BYTEORDER(first)"
};
type record L1ctlDlMessage {
L1ctlHeader header,
@ -196,7 +202,7 @@ module L1CTL_Types {
L1ctlGprsCs cs,
uint8_t ts_nr,
OCT1 padding,
uint32_t fn,
uint32_le fn,
Arfcn arfcn,
OCT2 padding2
} with { variant "" };
@ -277,7 +283,9 @@ module L1CTL_Types {
type record L1ctlTrafficReq {
octetstring data length(TRAFFIC_DATA_LEN)
} with { variant "" };
} with {
variant (data) "BYTEORDER(first)"
}
type record length(8) of uint8_t TfiUsfArr;
@ -300,7 +308,9 @@ module L1CTL_Types {
L1ctlTrafficReq traffic_req,
L1ctlTbfCfgReq tbf_cfg_req,
octetstring other
} with { variant "" };
} with {
variant (other) "BYTEORDER(first)"
};
type record L1ctlUlMessage {
L1ctlHeader header,
@ -586,4 +596,6 @@ module L1CTL_Types {
const octetstring c_DummyUI := '0303012B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B'O;
/* We use "BYTEORDER(last)" so we get little-endian integers. Unfortuantely, this also
switches the byte ordering in octet strings, so we need to explicitly annotate them :/ */
} with { encode "RAW" };

View File

@ -47,13 +47,27 @@ module LAPDm_RAW_PT {
/* PH-DATA.ind / PH-DATA.req */
type record RLCMAC_ph_data_ind {
GprsCodingScheme cs,
uint8_t ts_nr,
GsmFrameNumber fn,
RlcmacDlBlock block
}
type record RLCMAC_ph_data_req {
type record RLCMAC_ph_data_req_dyn {
uint8_t tbf_id,
GprsCodingScheme cs,
RlcmacUlBlock block
}
type record RLCMAC_ph_data_req_abs {
uint8_t tbf_id,
GprsCodingScheme cs,
uint8_t ts_nr,
GsmFrameNumber fn,
Arfcn arfcn,
RlcmacUlBlock block
}
type union RLCMAC_ph_data_req {
RLCMAC_ph_data_req_dyn dyn,
RLCMAC_ph_data_req_abs abs
}
/* port from our (internal) point of view */
type port LAPDm_SP_PT message {
@ -223,6 +237,19 @@ module LAPDm_RAW_PT {
}
};
template (value) RLCMAC_ph_data_req ts_PH_DATA_ABS(uint8_t tbf_id, GprsCodingScheme cs,
uint8_t ts, uint32_t fn, Arfcn arfcn,
RlcmacUlBlock block) := {
abs := {
tbf_id := tbf_id,
cs := CS1, /* FIXME */
ts_nr := ts,
fn := fn,
arfcn := arfcn,
block := block
}
}
private function f_establish_tbf(uint8_t ra) runs on lapdm_CT {
var ImmediateAssignment imm_ass;
var GsmFrameNumber rach_fn;
@ -377,6 +404,8 @@ 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);
rpdi.fn := dl.dl_info.frame_nr;
rpdi.ts_nr := dl.dl_info.chan_nr.tn;
rpdi.cs := CS1; /* FIXME */
log("RPDI: ", rpdi);
LAPDM_SP.send(rpdi);
@ -387,9 +416,15 @@ module LAPDm_RAW_PT {
/* encode + forward any blocks from L23 to L1 */
[] LAPDM_SP.receive(RLCMAC_ph_data_req:?) -> value rpdr {
var octetstring buf;
buf := enc_RlcmacUlBlock(rpdr.block);
L1CTL.send(t_L1CTL_DATA_TBF_REQ(buf, L1CTL_CS1, rpdr.tbf_id));
if (ischosen(rpdr.dyn)) {
buf := enc_RlcmacUlBlock(rpdr.dyn.block);
L1CTL.send(t_L1CTL_DATA_TBF_REQ(buf, L1CTL_CS1, rpdr.dyn.tbf_id));
} else {
buf := enc_RlcmacUlBlock(rpdr.abs.block);
L1CTL.send(t_L1CTL_DATA_ABS_REQ(buf, rpdr.abs.arfcn,
rpdr.abs.ts_nr, rpdr.abs.fn,
L1CTL_CS1, rpdr.abs.tbf_id));
}
}
/* FIXME: release TBF mode */

View File

@ -301,8 +301,8 @@ octetstring sdu) := {
}
template LLC_PDU tr_BSSGP_LLC_PDU(template octetstring pdu := ?) := {
iEI := '0D'O,
ext := '1'B,
iEI := '0E'O,
ext := ?,
lengthIndicator := ?,
lLC_PDU := pdu
}

View File

@ -513,4 +513,16 @@ module RLCMAC_CSN1_Types {
variant (relative_k) "PRESENCE(presence = '1'B)"
};
template (value) RlcmacUlCtrlMsg ts_RlcMacUlCtrl_PKT_CTRL_ACK(GprsTlli tlli,
CtrlAck ack := MS_RCVD_TWO_RLC_SAME_RTI_DIFF_RBSN) := {
msg_type := PACKET_CONTROL_ACK,
u := {
ctrl_ack := {
tlli := tlli,
ctrl_ack := ack
}
}
}
} with { encode "RAW"; variant "FIELDORDER(msb)" variant "BYTEORDER(last)" };

View File

@ -226,4 +226,17 @@ module RLCMAC_Types {
external function enc_RlcmacDlBlock(in RlcmacDlBlock si) return octetstring;
external function dec_RlcmacDlBlock(in octetstring stream) return RlcmacDlBlock;
template (value) RlcmacUlBlock ts_RLC_UL_CTRL_ACK(RlcmacUlCtrlMsg ctrl,
MacPayloadType pt := MAC_PT_RLCMAC_NO_OPT,
boolean retry := false) := {
ctrl := {
mac_hdr := {
payload_type := pt,
spare := '00000'B,
retry := retry
},
payload := ctrl
}
}
} with { encode "RAW"; variant "FIELDORDER(msb)" }