aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2018-03-02 23:37:51 +0100
committerHarald Welte <laforge@gnumonks.org>2018-03-12 14:23:57 +0000
commit7024baa66cc1d7fc4360a50b2787ea0bb93e75ab (patch)
tree932b6714a45dadc9778014a996a7b2fbdb53a36e
parentfd445c34fe47349f9576b6a8e4c53372e2ca8a59 (diff)
gprs_gb: working Uplink PACKET_CONTROL_ACK against OsmoPCU
-rw-r--r--Common.cfg2
-rw-r--r--gprs_gb/Test.ttcn81
-rw-r--r--library/L1CTL_Types.ttcn22
-rw-r--r--library/LAPDm_RAW_PT.ttcn43
-rw-r--r--library/Osmocom_Gb_Types.ttcn4
-rw-r--r--library/RLCMAC_CSN1_Types.ttcn12
-rw-r--r--library/RLCMAC_Types.ttcn13
7 files changed, 146 insertions, 31 deletions
diff --git a/Common.cfg b/Common.cfg
index 4a504204..38beb5ae 100644
--- a/Common.cfg
+++ b/Common.cfg
@@ -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]
diff --git a/gprs_gb/Test.ttcn b/gprs_gb/Test.ttcn
index 7251ef90..8741e863 100644
--- a/gprs_gb/Test.ttcn
+++ b/gprs_gb/Test.ttcn
@@ -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);
diff --git a/library/L1CTL_Types.ttcn b/library/L1CTL_Types.ttcn
index f853057b..33a01a81 100644
--- a/library/L1CTL_Types.ttcn
+++ b/library/L1CTL_Types.ttcn
@@ -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" };
diff --git a/library/LAPDm_RAW_PT.ttcn b/library/LAPDm_RAW_PT.ttcn
index 229aff04..ab995389 100644
--- a/library/LAPDm_RAW_PT.ttcn
+++ b/library/LAPDm_RAW_PT.ttcn
@@ -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 */
diff --git a/library/Osmocom_Gb_Types.ttcn b/library/Osmocom_Gb_Types.ttcn
index f943c9c0..3de74271 100644
--- a/library/Osmocom_Gb_Types.ttcn
+++ b/library/Osmocom_Gb_Types.ttcn
@@ -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
}
diff --git a/library/RLCMAC_CSN1_Types.ttcn b/library/RLCMAC_CSN1_Types.ttcn
index 2335c29d..95b58386 100644
--- a/library/RLCMAC_CSN1_Types.ttcn
+++ b/library/RLCMAC_CSN1_Types.ttcn
@@ -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)" };
diff --git a/library/RLCMAC_Types.ttcn b/library/RLCMAC_Types.ttcn
index a30a43cd..937aa7b2 100644
--- a/library/RLCMAC_Types.ttcn
+++ b/library/RLCMAC_Types.ttcn
@@ -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)" }